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/Conversions.h"
21 #include "js/String.h" // JS::{,Lossy}CopyLinearStringChars, JS::CopyStringChars, JS::Get{,Linear}StringLength, JS::MaxStringLength, JS::StringHasLatin1Chars
23 #include "xpcpublic.h"
25 class nsIScriptContext
;
26 class nsIScriptElement
;
27 class nsIScriptGlobalObject
;
28 class nsXBLPrototypeBinding
;
37 } // namespace mozilla
41 static bool GetCallingLocation(JSContext
* aContext
, nsACString
& aFilename
,
42 uint32_t* aLineno
= nullptr,
43 uint32_t* aColumn
= nullptr);
44 static bool GetCallingLocation(JSContext
* aContext
, nsAString
& aFilename
,
45 uint32_t* aLineno
= nullptr,
46 uint32_t* aColumn
= nullptr);
49 * Retrieve the inner window ID based on the given JSContext.
51 * @param JSContext aContext
52 * The JSContext from which you want to find the inner window ID.
54 * @returns uint64_t the inner window ID.
56 static uint64_t GetCurrentlyRunningCodeInnerWindowID(JSContext
* aContext
);
58 static nsresult
CompileFunction(mozilla::dom::AutoJSAPI
& jsapi
,
59 JS::HandleVector
<JSObject
*> aScopeChain
,
60 JS::CompileOptions
& aOptions
,
61 const nsACString
& aName
, uint32_t aArgCount
,
62 const char** aArgArray
,
63 const nsAString
& aBody
,
64 JSObject
** aFunctionObject
);
66 static nsresult
CompileModule(JSContext
* aCx
,
67 JS::SourceText
<char16_t
>& aSrcBuf
,
68 JS::Handle
<JSObject
*> aEvaluationGlobal
,
69 JS::CompileOptions
& aCompileOptions
,
70 JS::MutableHandle
<JSObject
*> aModule
);
72 static nsresult
CompileModule(JSContext
* aCx
,
73 JS::SourceText
<mozilla::Utf8Unit
>& aSrcBuf
,
74 JS::Handle
<JSObject
*> aEvaluationGlobal
,
75 JS::CompileOptions
& aCompileOptions
,
76 JS::MutableHandle
<JSObject
*> aModule
);
78 static nsresult
ModuleInstantiate(JSContext
* aCx
,
79 JS::Handle
<JSObject
*> aModule
);
82 * Wrapper for JSAPI ModuleEvaluate function.
84 * @param JSContext aCx
85 * The JSContext where this is executed.
86 * @param JS::Handle<JSObject*> aModule
87 * The module to be evaluated.
88 * @param JS::Handle<Value*> aResult
89 * If Top level await is enabled:
90 * The evaluation promise returned from evaluating the module.
94 static nsresult
ModuleEvaluate(JSContext
* aCx
, JS::Handle
<JSObject
*> aModule
,
95 JS::MutableHandle
<JS::Value
> aResult
);
97 // Returns false if an exception got thrown on aCx. Passing a null
98 // aElement is allowed; that wil produce an empty aScopeChain.
99 static bool GetScopeChainForElement(
100 JSContext
* aCx
, mozilla::dom::Element
* aElement
,
101 JS::MutableHandleVector
<JSObject
*> aScopeChain
);
103 static void ResetTimeZone();
105 static bool DumpEnabled();
108 inline void AssignFromStringBuffer(nsStringBuffer
* buffer
, size_t len
,
110 buffer
->ToString(len
, dest
);
113 template <typename T
, typename
std::enable_if_t
<std::is_same
<
114 typename
T::char_type
, char16_t
>::value
>* = nullptr>
115 inline bool AssignJSString(JSContext
* cx
, T
& dest
, JSString
* s
) {
116 size_t len
= JS::GetStringLength(s
);
117 static_assert(JS::MaxStringLength
< (1 << 30),
118 "Shouldn't overflow here or in SetCapacity");
120 const char16_t
* chars
;
121 if (XPCStringConvert::MaybeGetDOMStringChars(s
, &chars
)) {
122 // The characters represent an existing string buffer that we shared with
123 // JS. We can share that buffer ourselves if the string corresponds to the
124 // whole buffer; otherwise we have to copy.
125 if (chars
[len
] == '\0') {
126 AssignFromStringBuffer(
127 nsStringBuffer::FromData(const_cast<char16_t
*>(chars
)), len
, dest
);
130 } else if (XPCStringConvert::MaybeGetLiteralStringChars(s
, &chars
)) {
131 // The characters represent a literal char16_t string constant
132 // compiled into libxul; we can just use it as-is.
133 dest
.AssignLiteral(chars
, len
);
137 // We don't bother checking for a dynamic-atom external string, because we'd
138 // just need to copy out of it anyway.
140 if (MOZ_UNLIKELY(!dest
.SetLength(len
, mozilla::fallible
))) {
141 JS_ReportOutOfMemory(cx
);
144 return JS::CopyStringChars(cx
, dest
.BeginWriting(), s
, len
);
147 // Specialization for UTF8String.
148 template <typename T
, typename
std::enable_if_t
<std::is_same
<
149 typename
T::char_type
, char>::value
>* = nullptr>
150 inline bool AssignJSString(JSContext
* cx
, T
& dest
, JSString
* s
) {
151 using namespace mozilla
;
152 CheckedInt
<size_t> bufLen(JS::GetStringLength(s
));
153 // From the contract for JS_EncodeStringToUTF8BufferPartial, to guarantee that
154 // the whole string is converted.
155 if (JS::StringHasLatin1Chars(s
)) {
161 if (MOZ_UNLIKELY(!bufLen
.isValid())) {
162 JS_ReportOutOfMemory(cx
);
166 // Shouldn't really matter, but worth being safe.
167 const bool kAllowShrinking
= true;
169 auto handleOrErr
= dest
.BulkWrite(bufLen
.value(), 0, kAllowShrinking
);
170 if (MOZ_UNLIKELY(handleOrErr
.isErr())) {
171 JS_ReportOutOfMemory(cx
);
175 auto handle
= handleOrErr
.unwrap();
177 auto maybe
= JS_EncodeStringToUTF8BufferPartial(cx
, s
, handle
.AsSpan());
178 if (MOZ_UNLIKELY(!maybe
)) {
179 JS_ReportOutOfMemory(cx
);
185 Tie(read
, written
) = *maybe
;
187 MOZ_ASSERT(read
== JS::GetStringLength(s
));
188 handle
.Finish(written
, kAllowShrinking
);
192 inline void AssignJSLinearString(nsAString
& dest
, JSLinearString
* s
) {
193 size_t len
= JS::GetLinearStringLength(s
);
194 static_assert(JS::MaxStringLength
< (1 << 30),
195 "Shouldn't overflow here or in SetCapacity");
197 JS::CopyLinearStringChars(dest
.BeginWriting(), s
, len
);
200 inline void AssignJSLinearString(nsACString
& dest
, JSLinearString
* s
) {
201 size_t len
= JS::GetLinearStringLength(s
);
202 static_assert(JS::MaxStringLength
< (1 << 30),
203 "Shouldn't overflow here or in SetCapacity");
205 JS::LossyCopyLinearStringChars(dest
.BeginWriting(), s
, len
);
208 template <typename T
>
209 class nsTAutoJSLinearString
: public nsTAutoString
<T
> {
211 explicit nsTAutoJSLinearString(JSLinearString
* str
) {
212 AssignJSLinearString(*this, str
);
216 using nsAutoJSLinearString
= nsTAutoJSLinearString
<char16_t
>;
217 using nsAutoJSLinearCString
= nsTAutoJSLinearString
<char>;
219 template <typename T
>
220 class nsTAutoJSString
: public nsTAutoString
<T
> {
223 * nsTAutoJSString should be default constructed, which leaves it empty
224 * (this->IsEmpty()), and initialized with one of the init() methods below.
226 nsTAutoJSString() = default;
228 bool init(JSContext
* aContext
, JSString
* str
) {
229 return AssignJSString(aContext
, *this, str
);
232 bool init(JSContext
* aContext
, const JS::Value
& v
) {
234 return init(aContext
, v
.toString());
237 // Stringify, making sure not to run script.
238 JS::Rooted
<JSString
*> str(aContext
);
240 str
= JS_NewStringCopyZ(aContext
, "[Object]");
242 JS::Rooted
<JS::Value
> rootedVal(aContext
, v
);
243 str
= JS::ToString(aContext
, rootedVal
);
246 return str
&& init(aContext
, str
);
249 bool init(JSContext
* aContext
, jsid id
) {
250 JS::Rooted
<JS::Value
> v(aContext
);
251 return JS_IdToValue(aContext
, id
, &v
) && init(aContext
, v
);
254 bool init(const JS::Value
& v
);
256 ~nsTAutoJSString() = default;
259 using nsAutoJSString
= nsTAutoJSString
<char16_t
>;
261 // Note that this is guaranteed to be UTF-8.
262 using nsAutoJSCString
= nsTAutoJSString
<char>;
264 #endif /* nsJSUtils_h__ */