1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11 * This is not a generated file. It contains common utility functions
12 * invoked from the JavaScript code generated from IDL interfaces.
13 * The goal of the utility functions is to cut down on the size of
14 * the generated code itself.
17 #include "mozilla/Assertions.h"
20 #include "js/CompileOptions.h"
21 #include "js/Conversions.h"
22 #include "js/SourceText.h"
23 #include "js/String.h" // JS::{,Lossy}CopyLinearStringChars, JS::CopyStringChars, JS::Get{,Linear}StringLength, JS::MaxStringLength, JS::StringHasLatin1Chars
24 #include "js/Utility.h" // JS::FreePolicy
26 #include "xpcpublic.h"
28 class nsIScriptContext
;
29 class nsIScriptElement
;
30 class nsIScriptGlobalObject
;
31 class nsXBLPrototypeBinding
;
40 } // namespace mozilla
44 static bool GetCallingLocation(JSContext
* aContext
, nsACString
& aFilename
,
45 uint32_t* aLineno
= nullptr,
46 uint32_t* aColumn
= nullptr);
47 static bool GetCallingLocation(JSContext
* aContext
, nsAString
& aFilename
,
48 uint32_t* aLineno
= nullptr,
49 uint32_t* aColumn
= nullptr);
52 * Retrieve the inner window ID based on the given JSContext.
54 * @param JSContext aContext
55 * The JSContext from which you want to find the inner window ID.
57 * @returns uint64_t the inner window ID.
59 static uint64_t GetCurrentlyRunningCodeInnerWindowID(JSContext
* aContext
);
61 static nsresult
CompileFunction(mozilla::dom::AutoJSAPI
& jsapi
,
62 JS::HandleVector
<JSObject
*> aScopeChain
,
63 JS::CompileOptions
& aOptions
,
64 const nsACString
& aName
, uint32_t aArgCount
,
65 const char** aArgArray
,
66 const nsAString
& aBody
,
67 JSObject
** aFunctionObject
);
69 static nsresult
UpdateFunctionDebugMetadata(
70 mozilla::dom::AutoJSAPI
& jsapi
, JS::Handle
<JSObject
*> aFun
,
71 JS::CompileOptions
& aOptions
, JS::Handle
<JSString
*> aElementAttributeName
,
72 JS::Handle
<JS::Value
> aPrivateValue
);
74 static bool IsScriptable(JS::Handle
<JSObject
*> aEvaluationGlobal
);
76 // Returns false if an exception got thrown on aCx. Passing a null
77 // aElement is allowed; that wil produce an empty aScopeChain.
78 static bool GetScopeChainForElement(
79 JSContext
* aCx
, mozilla::dom::Element
* aElement
,
80 JS::MutableHandleVector
<JSObject
*> aScopeChain
);
82 static void ResetTimeZone();
84 static bool DumpEnabled();
86 // A helper function that receives buffer pointer, creates ArrayBuffer, and
87 // convert it to Uint8Array.
88 // Note that the buffer needs to be created by JS_malloc (or at least can be
89 // freed by JS_free), as the resulting Uint8Array takes the ownership of the
91 static JSObject
* MoveBufferAsUint8Array(
92 JSContext
* aCx
, size_t aSize
,
93 mozilla::UniquePtr
<uint8_t[], JS::FreePolicy
> aBuffer
);
96 template <typename T
, typename
std::enable_if_t
<std::is_same
<
97 typename
T::char_type
, char16_t
>::value
>* = nullptr>
98 inline bool AssignJSString(JSContext
* cx
, T
& dest
, JSString
* s
) {
99 size_t len
= JS::GetStringLength(s
);
100 static_assert(JS::MaxStringLength
< (1 << 30),
101 "Shouldn't overflow here or in SetCapacity");
103 if (XPCStringConvert::MaybeAssignUCStringChars(s
, len
, dest
)) {
107 // We don't bother checking for a dynamic-atom external string, because we'd
108 // just need to copy out of it anyway.
110 if (MOZ_UNLIKELY(!dest
.SetLength(len
, mozilla::fallible
))) {
111 JS_ReportOutOfMemory(cx
);
114 return JS::CopyStringChars(cx
, dest
.BeginWriting(), s
, len
);
117 // Specialization for UTF8String.
118 template <typename T
, typename
std::enable_if_t
<std::is_same
<
119 typename
T::char_type
, char>::value
>* = nullptr>
120 inline bool AssignJSString(JSContext
* cx
, T
& dest
, JSString
* s
) {
121 using namespace mozilla
;
122 CheckedInt
<size_t> bufLen(JS::GetStringLength(s
));
124 if (XPCStringConvert::MaybeAssignUTF8StringChars(s
, bufLen
.value(), dest
)) {
128 // From the contract for JS_EncodeStringToUTF8BufferPartial, to guarantee that
129 // the whole string is converted.
130 if (JS::StringHasLatin1Chars(s
)) {
136 if (MOZ_UNLIKELY(!bufLen
.isValid())) {
137 JS_ReportOutOfMemory(cx
);
141 // Shouldn't really matter, but worth being safe.
142 const bool kAllowShrinking
= true;
144 auto handleOrErr
= dest
.BulkWrite(bufLen
.value(), 0, kAllowShrinking
);
145 if (MOZ_UNLIKELY(handleOrErr
.isErr())) {
146 JS_ReportOutOfMemory(cx
);
150 auto handle
= handleOrErr
.unwrap();
152 auto maybe
= JS_EncodeStringToUTF8BufferPartial(cx
, s
, handle
.AsSpan());
153 if (MOZ_UNLIKELY(!maybe
)) {
154 JS_ReportOutOfMemory(cx
);
160 std::tie(read
, written
) = *maybe
;
162 MOZ_ASSERT(read
== JS::GetStringLength(s
));
163 handle
.Finish(written
, kAllowShrinking
);
167 inline void AssignJSLinearString(nsAString
& dest
, JSLinearString
* s
) {
168 size_t len
= JS::GetLinearStringLength(s
);
169 static_assert(JS::MaxStringLength
< (1 << 30),
170 "Shouldn't overflow here or in SetCapacity");
172 JS::CopyLinearStringChars(dest
.BeginWriting(), s
, len
);
175 inline void AssignJSLinearString(nsACString
& dest
, JSLinearString
* s
) {
176 size_t len
= JS::GetLinearStringLength(s
);
177 static_assert(JS::MaxStringLength
< (1 << 30),
178 "Shouldn't overflow here or in SetCapacity");
180 JS::LossyCopyLinearStringChars(dest
.BeginWriting(), s
, len
);
183 template <typename T
>
184 class nsTAutoJSLinearString
: public nsTAutoString
<T
> {
186 explicit nsTAutoJSLinearString(JSLinearString
* str
) {
187 AssignJSLinearString(*this, str
);
191 using nsAutoJSLinearString
= nsTAutoJSLinearString
<char16_t
>;
192 using nsAutoJSLinearCString
= nsTAutoJSLinearString
<char>;
194 template <typename T
>
195 class nsTAutoJSString
: public nsTAutoString
<T
> {
198 * nsTAutoJSString should be default constructed, which leaves it empty
199 * (this->IsEmpty()), and initialized with one of the init() methods below.
201 nsTAutoJSString() = default;
203 bool init(JSContext
* aContext
, JSString
* str
) {
204 return AssignJSString(aContext
, *this, str
);
207 bool init(JSContext
* aContext
, const JS::Value
& v
) {
209 return init(aContext
, v
.toString());
212 // Stringify, making sure not to run script.
213 JS::Rooted
<JSString
*> str(aContext
);
215 str
= JS_NewStringCopyZ(aContext
, "[Object]");
217 JS::Rooted
<JS::Value
> rootedVal(aContext
, v
);
218 str
= JS::ToString(aContext
, rootedVal
);
221 return str
&& init(aContext
, str
);
224 bool init(JSContext
* aContext
, jsid id
) {
225 JS::Rooted
<JS::Value
> v(aContext
);
226 return JS_IdToValue(aContext
, id
, &v
) && init(aContext
, v
);
229 bool init(const JS::Value
& v
);
231 ~nsTAutoJSString() = default;
234 using nsAutoJSString
= nsTAutoJSString
<char16_t
>;
236 // Note that this is guaranteed to be UTF-8.
237 using nsAutoJSCString
= nsTAutoJSString
<char>;
239 #endif /* nsJSUtils_h__ */