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"
43 #if !defined(DEBUG) && !defined(MOZ_ENABLE_JS_DUMP)
44 # include "mozilla/StaticPrefs_browser.h"
47 using namespace mozilla
;
48 using namespace mozilla::dom
;
50 bool nsJSUtils::GetCallingLocation(JSContext
* aContext
, nsACString
& aFilename
,
51 uint32_t* aLineno
, uint32_t* aColumn
) {
52 JS::AutoFilename filename
;
53 if (!JS::DescribeScriptedCaller(aContext
, &filename
, aLineno
, aColumn
)) {
57 return aFilename
.Assign(filename
.get(), fallible
);
60 bool nsJSUtils::GetCallingLocation(JSContext
* aContext
, nsAString
& aFilename
,
61 uint32_t* aLineno
, uint32_t* aColumn
) {
62 JS::AutoFilename filename
;
63 if (!JS::DescribeScriptedCaller(aContext
, &filename
, aLineno
, aColumn
)) {
67 return aFilename
.Assign(NS_ConvertUTF8toUTF16(filename
.get()), fallible
);
70 uint64_t nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(JSContext
* aContext
) {
71 if (!aContext
) return 0;
73 nsGlobalWindowInner
* win
= xpc::CurrentWindowOrNull(aContext
);
74 return win
? win
->WindowID() : 0;
77 nsresult
nsJSUtils::CompileFunction(AutoJSAPI
& jsapi
,
78 JS::HandleVector
<JSObject
*> aScopeChain
,
79 JS::CompileOptions
& aOptions
,
80 const nsACString
& aName
, uint32_t aArgCount
,
81 const char** aArgArray
,
82 const nsAString
& aBody
,
83 JSObject
** aFunctionObject
) {
84 JSContext
* cx
= jsapi
.cx();
85 MOZ_ASSERT(js::GetContextRealm(cx
));
86 MOZ_ASSERT_IF(aScopeChain
.length() != 0,
87 js::IsObjectInContextCompartment(aScopeChain
[0], cx
));
89 // Do the junk Gecko is supposed to do before calling into JSAPI.
90 for (size_t i
= 0; i
< aScopeChain
.length(); ++i
) {
91 JS::ExposeObjectToActiveJS(aScopeChain
[i
]);
95 const nsPromiseFlatString
& flatBody
= PromiseFlatString(aBody
);
97 JS::SourceText
<char16_t
> source
;
98 if (!source
.init(cx
, flatBody
.get(), flatBody
.Length(),
99 JS::SourceOwnership::Borrowed
)) {
100 return NS_ERROR_FAILURE
;
103 JS::Rooted
<JSFunction
*> fun(
104 cx
, JS::CompileFunction(cx
, aScopeChain
, aOptions
,
105 PromiseFlatCString(aName
).get(), aArgCount
,
108 return NS_ERROR_FAILURE
;
111 *aFunctionObject
= JS_GetFunctionObject(fun
);
115 template <typename Unit
>
116 static nsresult
CompileJSModule(JSContext
* aCx
, JS::SourceText
<Unit
>& aSrcBuf
,
117 JS::Handle
<JSObject
*> aEvaluationGlobal
,
118 JS::CompileOptions
& aCompileOptions
,
119 JS::MutableHandle
<JSObject
*> aModule
) {
120 AUTO_PROFILER_LABEL("nsJSUtils::CompileModule", JS
);
121 MOZ_ASSERT(aCx
== nsContentUtils::GetCurrentJSContext());
122 MOZ_ASSERT(aSrcBuf
.get());
123 MOZ_ASSERT(JS_IsGlobalObject(aEvaluationGlobal
));
124 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx
) == aEvaluationGlobal
);
125 MOZ_ASSERT(NS_IsMainThread());
126 MOZ_ASSERT(CycleCollectedJSContext::Get() &&
127 CycleCollectedJSContext::Get()->MicroTaskLevel());
129 NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal
).Allowed(), NS_OK
);
131 JSObject
* module
= JS::CompileModule(aCx
, aCompileOptions
, aSrcBuf
);
133 return NS_ERROR_FAILURE
;
140 nsresult
nsJSUtils::CompileModule(JSContext
* aCx
,
141 JS::SourceText
<char16_t
>& aSrcBuf
,
142 JS::Handle
<JSObject
*> aEvaluationGlobal
,
143 JS::CompileOptions
& aCompileOptions
,
144 JS::MutableHandle
<JSObject
*> aModule
) {
145 return CompileJSModule(aCx
, aSrcBuf
, aEvaluationGlobal
, aCompileOptions
,
149 nsresult
nsJSUtils::CompileModule(JSContext
* aCx
,
150 JS::SourceText
<Utf8Unit
>& aSrcBuf
,
151 JS::Handle
<JSObject
*> aEvaluationGlobal
,
152 JS::CompileOptions
& aCompileOptions
,
153 JS::MutableHandle
<JSObject
*> aModule
) {
154 return CompileJSModule(aCx
, aSrcBuf
, aEvaluationGlobal
, aCompileOptions
,
158 nsresult
nsJSUtils::ModuleInstantiate(JSContext
* aCx
,
159 JS::Handle
<JSObject
*> aModule
) {
160 AUTO_PROFILER_LABEL("nsJSUtils::ModuleInstantiate", JS
);
162 MOZ_ASSERT(aCx
== nsContentUtils::GetCurrentJSContext());
163 MOZ_ASSERT(NS_IsMainThread());
164 MOZ_ASSERT(CycleCollectedJSContext::Get() &&
165 CycleCollectedJSContext::Get()->MicroTaskLevel());
167 NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule
).Allowed(), NS_OK
);
169 if (!JS::ModuleInstantiate(aCx
, aModule
)) {
170 return NS_ERROR_FAILURE
;
176 nsresult
nsJSUtils::ModuleEvaluate(JSContext
* aCx
,
177 JS::Handle
<JSObject
*> aModule
,
178 JS::MutableHandle
<JS::Value
> aResult
) {
179 AUTO_PROFILER_LABEL("nsJSUtils::ModuleEvaluate", JS
);
181 MOZ_ASSERT(aCx
== nsContentUtils::GetCurrentJSContext());
182 MOZ_ASSERT(NS_IsMainThread());
183 MOZ_ASSERT(CycleCollectedJSContext::Get() &&
184 CycleCollectedJSContext::Get()->MicroTaskLevel());
186 NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule
).Allowed(), NS_OK
);
188 if (!JS::ModuleEvaluate(aCx
, aModule
, aResult
)) {
189 return NS_ERROR_FAILURE
;
195 static bool AddScopeChainItem(JSContext
* aCx
, nsINode
* aNode
,
196 JS::MutableHandleVector
<JSObject
*> aScopeChain
) {
197 JS::RootedValue
val(aCx
);
198 if (!GetOrCreateDOMReflector(aCx
, aNode
, &val
)) {
202 if (!aScopeChain
.append(&val
.toObject())) {
210 bool nsJSUtils::GetScopeChainForElement(
211 JSContext
* aCx
, Element
* aElement
,
212 JS::MutableHandleVector
<JSObject
*> aScopeChain
) {
213 for (nsINode
* cur
= aElement
; cur
; cur
= cur
->GetScopeChainParent()) {
214 if (!AddScopeChainItem(aCx
, cur
, aScopeChain
)) {
223 void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); }
226 bool nsJSUtils::DumpEnabled() {
227 #if defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP)
230 return StaticPrefs::browser_dom_window_dump_enabled();
238 template <typename T
>
239 bool nsTAutoJSString
<T
>::init(const JS::Value
& v
) {
240 // Note: it's okay to use danger::GetJSContext here instead of AutoJSAPI,
241 // because the init() call below is careful not to run script (for instance,
242 // it only calls JS::ToString for non-object values).
243 JSContext
* cx
= danger::GetJSContext();
245 JS_ClearPendingException(cx
);
251 template bool nsTAutoJSString
<char16_t
>::init(const JS::Value
&);
252 template bool nsTAutoJSString
<char>::init(const JS::Value
&);