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/. */
8 * This is not a generated file. It contains common utility functions
9 * invoked from the JavaScript code generated from IDL interfaces.
10 * The goal of the utility functions is to cut down on the size of
11 * the generated code itself.
14 #include "nsJSUtils.h"
17 #include "MainThreadUtils.h"
18 #include "js/ComparisonOperators.h"
19 #include "js/CompilationAndEvaluation.h"
20 #include "js/CompileOptions.h"
22 #include "js/GCVector.h"
23 #include "js/HeapAPI.h"
24 #include "js/Modules.h"
25 #include "js/RootingAPI.h"
26 #include "js/SourceText.h"
27 #include "js/TypeDecls.h"
28 #include "jsfriendapi.h"
29 #include "mozilla/CycleCollectedJSContext.h"
30 #include "mozilla/dom/BindingUtils.h"
31 #include "mozilla/dom/Element.h"
32 #include "mozilla/dom/ScriptSettings.h"
33 #include "mozilla/fallible.h"
34 #include "mozilla/ProfilerLabels.h"
35 #include "nsContentUtils.h"
37 #include "nsGlobalWindowInner.h"
40 #include "nsTPromiseFlatString.h"
44 #if !defined(DEBUG) && !defined(MOZ_ENABLE_JS_DUMP)
45 # include "mozilla/StaticPrefs_browser.h"
48 using namespace mozilla
;
49 using namespace mozilla::dom
;
51 bool nsJSUtils::GetCallingLocation(JSContext
* aContext
, nsACString
& aFilename
,
52 uint32_t* aLineno
, uint32_t* aColumn
) {
53 JS::AutoFilename filename
;
54 JS::ColumnNumberZeroOrigin column
;
55 if (!JS::DescribeScriptedCaller(aContext
, &filename
, aLineno
, &column
)) {
59 *aColumn
= column
.zeroOriginValue();
62 return aFilename
.Assign(filename
.get(), fallible
);
65 bool nsJSUtils::GetCallingLocation(JSContext
* aContext
, nsAString
& aFilename
,
66 uint32_t* aLineno
, uint32_t* aColumn
) {
67 JS::AutoFilename filename
;
68 JS::ColumnNumberZeroOrigin column
;
69 if (!JS::DescribeScriptedCaller(aContext
, &filename
, aLineno
, &column
)) {
73 *aColumn
= column
.zeroOriginValue();
76 return aFilename
.Assign(NS_ConvertUTF8toUTF16(filename
.get()), fallible
);
79 uint64_t nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(JSContext
* aContext
) {
80 if (!aContext
) return 0;
82 nsGlobalWindowInner
* win
= xpc::CurrentWindowOrNull(aContext
);
83 return win
? win
->WindowID() : 0;
86 nsresult
nsJSUtils::UpdateFunctionDebugMetadata(
87 AutoJSAPI
& jsapi
, JS::Handle
<JSObject
*> aFun
, JS::CompileOptions
& aOptions
,
88 JS::Handle
<JSString
*> aElementAttributeName
,
89 JS::Handle
<JS::Value
> aPrivateValue
) {
90 JSContext
* cx
= jsapi
.cx();
92 JS::Rooted
<JSFunction
*> fun(cx
, JS_GetObjectFunction(aFun
));
94 return NS_ERROR_FAILURE
;
97 JS::Rooted
<JSScript
*> script(cx
, JS_GetFunctionScript(cx
, fun
));
102 JS::InstantiateOptions
instantiateOptions(aOptions
);
103 if (!JS::UpdateDebugMetadata(cx
, script
, instantiateOptions
, aPrivateValue
,
104 aElementAttributeName
, nullptr, nullptr)) {
105 return NS_ERROR_FAILURE
;
110 nsresult
nsJSUtils::CompileFunction(AutoJSAPI
& jsapi
,
111 JS::HandleVector
<JSObject
*> aScopeChain
,
112 JS::CompileOptions
& aOptions
,
113 const nsACString
& aName
, uint32_t aArgCount
,
114 const char** aArgArray
,
115 const nsAString
& aBody
,
116 JSObject
** aFunctionObject
) {
117 JSContext
* cx
= jsapi
.cx();
118 MOZ_ASSERT(js::GetContextRealm(cx
));
119 MOZ_ASSERT_IF(aScopeChain
.length() != 0,
120 js::IsObjectInContextCompartment(aScopeChain
[0], cx
));
122 // Do the junk Gecko is supposed to do before calling into JSAPI.
123 for (size_t i
= 0; i
< aScopeChain
.length(); ++i
) {
124 JS::ExposeObjectToActiveJS(aScopeChain
[i
]);
128 const nsPromiseFlatString
& flatBody
= PromiseFlatString(aBody
);
130 JS::SourceText
<char16_t
> source
;
131 if (!source
.init(cx
, flatBody
.get(), flatBody
.Length(),
132 JS::SourceOwnership::Borrowed
)) {
133 return NS_ERROR_FAILURE
;
136 JS::Rooted
<JSFunction
*> fun(
137 cx
, JS::CompileFunction(cx
, aScopeChain
, aOptions
,
138 PromiseFlatCString(aName
).get(), aArgCount
,
141 return NS_ERROR_FAILURE
;
144 *aFunctionObject
= JS_GetFunctionObject(fun
);
149 bool nsJSUtils::IsScriptable(JS::Handle
<JSObject
*> aEvaluationGlobal
) {
150 return xpc::Scriptability::AllowedIfExists(aEvaluationGlobal
);
153 static bool AddScopeChainItem(JSContext
* aCx
, nsINode
* aNode
,
154 JS::MutableHandleVector
<JSObject
*> aScopeChain
) {
155 JS::Rooted
<JS::Value
> val(aCx
);
156 if (!GetOrCreateDOMReflector(aCx
, aNode
, &val
)) {
160 if (!aScopeChain
.append(&val
.toObject())) {
168 bool nsJSUtils::GetScopeChainForElement(
169 JSContext
* aCx
, Element
* aElement
,
170 JS::MutableHandleVector
<JSObject
*> aScopeChain
) {
171 for (nsINode
* cur
= aElement
; cur
; cur
= cur
->GetScopeChainParent()) {
172 if (!AddScopeChainItem(aCx
, cur
, aScopeChain
)) {
181 void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); }
184 bool nsJSUtils::DumpEnabled() {
186 static bool mozFuzzDebug
= !!PR_GetEnv("MOZ_FUZZ_DEBUG");
190 #if defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP)
193 return StaticPrefs::browser_dom_window_dump_enabled();
197 JSObject
* nsJSUtils::MoveBufferAsUint8Array(
198 JSContext
* aCx
, size_t aSize
,
199 UniquePtr
<uint8_t[], JS::FreePolicy
> aBuffer
) {
200 JS::Rooted
<JSObject
*> arrayBuffer(
201 aCx
, JS::NewArrayBufferWithContents(aCx
, aSize
, std::move(aBuffer
)));
206 return JS_NewUint8ArrayWithBuffer(aCx
, arrayBuffer
, 0,
207 static_cast<int64_t>(aSize
));
214 template <typename T
>
215 bool nsTAutoJSString
<T
>::init(const JS::Value
& v
) {
216 // Note: it's okay to use danger::GetJSContext here instead of AutoJSAPI,
217 // because the init() call below is careful not to run script (for instance,
218 // it only calls JS::ToString for non-object values).
219 JSContext
* cx
= danger::GetJSContext();
221 JS_ClearPendingException(cx
);
227 template bool nsTAutoJSString
<char16_t
>::init(const JS::Value
&);
228 template bool nsTAutoJSString
<char>::init(const JS::Value
&);