Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / dom / base / nsJSUtils.h
blobcceb725d393d5e5f83c8f87491089c3fa1d57cc3
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/. */
7 #ifndef nsJSUtils_h__
8 #define nsJSUtils_h__
10 /**
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"
19 #include "jsapi.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
25 #include "nsString.h"
26 #include "xpcpublic.h"
28 class nsIScriptContext;
29 class nsIScriptElement;
30 class nsIScriptGlobalObject;
31 class nsXBLPrototypeBinding;
33 namespace mozilla {
34 union Utf8Unit;
36 namespace dom {
37 class AutoJSAPI;
38 class Element;
39 } // namespace dom
40 } // namespace mozilla
42 class nsJSUtils {
43 public:
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);
51 /**
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
90 // buffer.
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)) {
104 return true;
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);
112 return false;
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)) {
125 return true;
128 // From the contract for JS_EncodeStringToUTF8BufferPartial, to guarantee that
129 // the whole string is converted.
130 if (JS::StringHasLatin1Chars(s)) {
131 bufLen *= 2;
132 } else {
133 bufLen *= 3;
136 if (MOZ_UNLIKELY(!bufLen.isValid())) {
137 JS_ReportOutOfMemory(cx);
138 return false;
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);
147 return false;
150 auto handle = handleOrErr.unwrap();
152 auto maybe = JS_EncodeStringToUTF8BufferPartial(cx, s, handle.AsSpan());
153 if (MOZ_UNLIKELY(!maybe)) {
154 JS_ReportOutOfMemory(cx);
155 return false;
158 size_t read;
159 size_t written;
160 std::tie(read, written) = *maybe;
162 MOZ_ASSERT(read == JS::GetStringLength(s));
163 handle.Finish(written, kAllowShrinking);
164 return true;
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");
171 dest.SetLength(len);
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");
179 dest.SetLength(len);
180 JS::LossyCopyLinearStringChars(dest.BeginWriting(), s, len);
183 template <typename T>
184 class nsTAutoJSLinearString : public nsTAutoString<T> {
185 public:
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> {
196 public:
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) {
208 if (v.isString()) {
209 return init(aContext, v.toString());
212 // Stringify, making sure not to run script.
213 JS::Rooted<JSString*> str(aContext);
214 if (v.isObject()) {
215 str = JS_NewStringCopyZ(aContext, "[Object]");
216 } else {
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__ */