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/. */
6
7 /**
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.
12 */
13
14 #include "nsJSUtils.h"
15 #include "jsapi.h"
16 #include "jsfriendapi.h"
17 #include "js/BinASTFormat.h" // JS::BinASTFormat
18 #include "js/CompilationAndEvaluation.h"
19 #include "js/Date.h"
20 #include "js/Modules.h" // JS::CompileModule, JS::GetModuleScript, JS::Module{Instantiate,Evaluate}
21 #include "js/OffThreadScriptCompilation.h"
22 #include "js/SourceText.h"
23 #include "nsIScriptContext.h"
24 #include "nsIScriptElement.h"
25 #include "nsIScriptGlobalObject.h"
26 #include "nsCOMPtr.h"
27 #include "nsPIDOMWindow.h"
28 #include "GeckoProfiler.h"
29 #include "nsJSPrincipals.h"
30 #include "xpcpublic.h"
31 #include "nsContentUtils.h"
32 #include "nsGlobalWindow.h"
33 #include "mozilla/CycleCollectedJSContext.h"
34 #include "mozilla/StaticPrefs_browser.h"
35 #include "mozilla/dom/BindingUtils.h"
36 #include "mozilla/dom/Element.h"
37 #include "mozilla/dom/ScriptSettings.h"
38 #include "mozilla/Utf8.h" // mozilla::Utf8Unit
39
40 using namespace mozilla;
41 using namespace mozilla::dom;
42
GetCallingLocation(JSContext * aContext,nsACString & aFilename,uint32_t * aLineno,uint32_t * aColumn)43 bool nsJSUtils::GetCallingLocation(JSContext* aContext, nsACString& aFilename,
44 uint32_t* aLineno, uint32_t* aColumn) {
45 JS::AutoFilename filename;
46 if (!JS::DescribeScriptedCaller(aContext, &filename, aLineno, aColumn)) {
47 return false;
48 }
49
50 return aFilename.Assign(filename.get(), fallible);
51 }
52
GetCallingLocation(JSContext * aContext,nsAString & aFilename,uint32_t * aLineno,uint32_t * aColumn)53 bool nsJSUtils::GetCallingLocation(JSContext* aContext, nsAString& aFilename,
54 uint32_t* aLineno, uint32_t* aColumn) {
55 JS::AutoFilename filename;
56 if (!JS::DescribeScriptedCaller(aContext, &filename, aLineno, aColumn)) {
57 return false;
58 }
59
60 return aFilename.Assign(NS_ConvertUTF8toUTF16(filename.get()), fallible);
61 }
62
GetCurrentlyRunningCodeInnerWindowID(JSContext * aContext)63 uint64_t nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(JSContext* aContext) {
64 if (!aContext) return 0;
65
66 nsGlobalWindowInner* win = xpc::CurrentWindowOrNull(aContext);
67 return win ? win->WindowID() : 0;
68 }
69
CompileFunction(AutoJSAPI & jsapi,JS::HandleVector<JSObject * > aScopeChain,JS::CompileOptions & aOptions,const nsACString & aName,uint32_t aArgCount,const char ** aArgArray,const nsAString & aBody,JSObject ** aFunctionObject)70 nsresult nsJSUtils::CompileFunction(AutoJSAPI& jsapi,
71 JS::HandleVector<JSObject*> aScopeChain,
72 JS::CompileOptions& aOptions,
73 const nsACString& aName, uint32_t aArgCount,
74 const char** aArgArray,
75 const nsAString& aBody,
76 JSObject** aFunctionObject) {
77 JSContext* cx = jsapi.cx();
78 MOZ_ASSERT(js::GetContextRealm(cx));
79 MOZ_ASSERT_IF(aScopeChain.length() != 0,
80 js::IsObjectInContextCompartment(aScopeChain[0], cx));
81
82 // Do the junk Gecko is supposed to do before calling into JSAPI.
83 for (size_t i = 0; i < aScopeChain.length(); ++i) {
84 JS::ExposeObjectToActiveJS(aScopeChain[i]);
85 }
86
87 // Compile.
88 const nsPromiseFlatString& flatBody = PromiseFlatString(aBody);
89
90 JS::SourceText<char16_t> source;
91 if (!source.init(cx, flatBody.get(), flatBody.Length(),
92 JS::SourceOwnership::Borrowed)) {
93 return NS_ERROR_FAILURE;
94 }
95
96 JS::Rooted<JSFunction*> fun(
97 cx, JS::CompileFunction(cx, aScopeChain, aOptions,
98 PromiseFlatCString(aName).get(), aArgCount,
99 aArgArray, source));
100 if (!fun) {
101 return NS_ERROR_FAILURE;
102 }
103
104 *aFunctionObject = JS_GetFunctionObject(fun);
105 return NS_OK;
106 }
107
EvaluationExceptionToNSResult(JSContext * aCx)108 static nsresult EvaluationExceptionToNSResult(JSContext* aCx) {
109 if (JS_IsExceptionPending(aCx)) {
110 return NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW;
111 }
112 return NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE;
113 }
114
ExecutionContext(JSContext * aCx,JS::Handle<JSObject * > aGlobal)115 nsJSUtils::ExecutionContext::ExecutionContext(JSContext* aCx,
116 JS::Handle<JSObject*> aGlobal)
117 :
118 #ifdef MOZ_GECKO_PROFILER
119 mAutoProfilerLabel("nsJSUtils::ExecutionContext",
120 /* dynamicStr */ nullptr,
121 JS::ProfilingCategoryPair::JS),
122 #endif
123 mCx(aCx),
124 mRealm(aCx, aGlobal),
125 mRetValue(aCx),
126 mScopeChain(aCx),
127 mScript(aCx),
128 mRv(NS_OK),
129 mSkip(false),
130 mCoerceToString(false),
131 mEncodeBytecode(false)
132 #ifdef DEBUG
133 ,
134 mWantsReturnValue(false),
135 mExpectScopeChain(false),
136 mScriptUsed(false)
137 #endif
138 {
139 MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
140 MOZ_ASSERT(NS_IsMainThread());
141 MOZ_ASSERT(CycleCollectedJSContext::Get() &&
142 CycleCollectedJSContext::Get()->MicroTaskLevel());
143 MOZ_ASSERT(mRetValue.isUndefined());
144
145 MOZ_ASSERT(JS_IsGlobalObject(aGlobal));
146 if (MOZ_UNLIKELY(!xpc::Scriptability::Get(aGlobal).Allowed())) {
147 mSkip = true;
148 mRv = NS_OK;
149 }
150 }
151
SetScopeChain(JS::HandleVector<JSObject * > aScopeChain)152 void nsJSUtils::ExecutionContext::SetScopeChain(
153 JS::HandleVector<JSObject*> aScopeChain) {
154 if (mSkip) {
155 return;
156 }
157
158 #ifdef DEBUG
159 mExpectScopeChain = true;
160 #endif
161 // Now make sure to wrap the scope chain into the right compartment.
162 if (!mScopeChain.reserve(aScopeChain.length())) {
163 mSkip = true;
164 mRv = NS_ERROR_OUT_OF_MEMORY;
165 return;
166 }
167
168 for (size_t i = 0; i < aScopeChain.length(); ++i) {
169 JS::ExposeObjectToActiveJS(aScopeChain[i]);
170 mScopeChain.infallibleAppend(aScopeChain[i]);
171 if (!JS_WrapObject(mCx, mScopeChain[i])) {
172 mSkip = true;
173 mRv = NS_ERROR_OUT_OF_MEMORY;
174 return;
175 }
176 }
177 }
178
JoinCompile(JS::OffThreadToken ** aOffThreadToken)179 nsresult nsJSUtils::ExecutionContext::JoinCompile(
180 JS::OffThreadToken** aOffThreadToken) {
181 if (mSkip) {
182 return mRv;
183 }
184
185 MOZ_ASSERT(!mWantsReturnValue);
186 MOZ_ASSERT(!mExpectScopeChain);
187 MOZ_ASSERT(!mScript);
188 mScript.set(JS::FinishOffThreadScript(mCx, *aOffThreadToken));
189 *aOffThreadToken = nullptr; // Mark the token as having been finished.
190 if (!mScript) {
191 mSkip = true;
192 mRv = EvaluationExceptionToNSResult(mCx);
193 return mRv;
194 }
195
196 if (mEncodeBytecode && !StartIncrementalEncoding(mCx, mScript)) {
197 mSkip = true;
198 mRv = EvaluationExceptionToNSResult(mCx);
199 return mRv;
200 }
201
202 return NS_OK;
203 }
204
205 template <typename Unit>
InternalCompile(JS::CompileOptions & aCompileOptions,JS::SourceText<Unit> & aSrcBuf)206 nsresult nsJSUtils::ExecutionContext::InternalCompile(
207 JS::CompileOptions& aCompileOptions, JS::SourceText<Unit>& aSrcBuf) {
208 if (mSkip) {
209 return mRv;
210 }
211
212 MOZ_ASSERT(aSrcBuf.get());
213 MOZ_ASSERT(mRetValue.isUndefined());
214 #ifdef DEBUG
215 mWantsReturnValue = !aCompileOptions.noScriptRval;
216 #endif
217
218 MOZ_ASSERT(!mScript);
219 mScript =
220 mScopeChain.length() == 0
221 ? JS::Compile(mCx, aCompileOptions, aSrcBuf)
222 : JS::CompileForNonSyntacticScope(mCx, aCompileOptions, aSrcBuf);
223 if (!mScript) {
224 mSkip = true;
225 mRv = EvaluationExceptionToNSResult(mCx);
226 return mRv;
227 }
228
229 if (mEncodeBytecode && !StartIncrementalEncoding(mCx, mScript)) {
230 mSkip = true;
231 mRv = EvaluationExceptionToNSResult(mCx);
232 return mRv;
233 }
234
235 return NS_OK;
236 }
237
Compile(JS::CompileOptions & aCompileOptions,JS::SourceText<char16_t> & aSrcBuf)238 nsresult nsJSUtils::ExecutionContext::Compile(
239 JS::CompileOptions& aCompileOptions, JS::SourceText<char16_t>& aSrcBuf) {
240 return InternalCompile(aCompileOptions, aSrcBuf);
241 }
242
Compile(JS::CompileOptions & aCompileOptions,JS::SourceText<Utf8Unit> & aSrcBuf)243 nsresult nsJSUtils::ExecutionContext::Compile(
244 JS::CompileOptions& aCompileOptions, JS::SourceText<Utf8Unit>& aSrcBuf) {
245 return InternalCompile(aCompileOptions, aSrcBuf);
246 }
247
Compile(JS::CompileOptions & aCompileOptions,const nsAString & aScript)248 nsresult nsJSUtils::ExecutionContext::Compile(
249 JS::CompileOptions& aCompileOptions, const nsAString& aScript) {
250 if (mSkip) {
251 return mRv;
252 }
253
254 const nsPromiseFlatString& flatScript = PromiseFlatString(aScript);
255 JS::SourceText<char16_t> srcBuf;
256 if (!srcBuf.init(mCx, flatScript.get(), flatScript.Length(),
257 JS::SourceOwnership::Borrowed)) {
258 mSkip = true;
259 mRv = EvaluationExceptionToNSResult(mCx);
260 return mRv;
261 }
262
263 return Compile(aCompileOptions, srcBuf);
264 }
265
Decode(JS::CompileOptions & aCompileOptions,mozilla::Vector<uint8_t> & aBytecodeBuf,size_t aBytecodeIndex)266 nsresult nsJSUtils::ExecutionContext::Decode(
267 JS::CompileOptions& aCompileOptions, mozilla::Vector<uint8_t>& aBytecodeBuf,
268 size_t aBytecodeIndex) {
269 if (mSkip) {
270 return mRv;
271 }
272
273 MOZ_ASSERT(!mWantsReturnValue);
274 JS::TranscodeResult tr =
275 JS::DecodeScript(mCx, aBytecodeBuf, &mScript, aBytecodeIndex);
276 // These errors are external parameters which should be handled before the
277 // decoding phase, and which are the only reasons why you might want to
278 // fallback on decoding failures.
279 MOZ_ASSERT(tr != JS::TranscodeResult_Failure_BadBuildId &&
280 tr != JS::TranscodeResult_Failure_WrongCompileOption);
281 if (tr != JS::TranscodeResult_Ok) {
282 mSkip = true;
283 mRv = NS_ERROR_DOM_JS_DECODING_ERROR;
284 return mRv;
285 }
286
287 return mRv;
288 }
289
JoinDecode(JS::OffThreadToken ** aOffThreadToken)290 nsresult nsJSUtils::ExecutionContext::JoinDecode(
291 JS::OffThreadToken** aOffThreadToken) {
292 if (mSkip) {
293 return mRv;
294 }
295
296 MOZ_ASSERT(!mWantsReturnValue);
297 MOZ_ASSERT(!mExpectScopeChain);
298 mScript.set(JS::FinishOffThreadScriptDecoder(mCx, *aOffThreadToken));
299 *aOffThreadToken = nullptr; // Mark the token as having been finished.
300 if (!mScript) {
301 mSkip = true;
302 mRv = EvaluationExceptionToNSResult(mCx);
303 return mRv;
304 }
305
306 return NS_OK;
307 }
308
JoinDecodeBinAST(JS::OffThreadToken ** aOffThreadToken)309 nsresult nsJSUtils::ExecutionContext::JoinDecodeBinAST(
310 JS::OffThreadToken** aOffThreadToken) {
311 #ifdef JS_BUILD_BINAST
312 if (mSkip) {
313 return mRv;
314 }
315
316 MOZ_ASSERT(!mWantsReturnValue);
317 MOZ_ASSERT(!mExpectScopeChain);
318
319 mScript.set(JS::FinishOffThreadBinASTDecode(mCx, *aOffThreadToken));
320 *aOffThreadToken = nullptr; // Mark the token as having been finished.
321
322 if (!mScript) {
323 mSkip = true;
324 mRv = EvaluationExceptionToNSResult(mCx);
325 return mRv;
326 }
327
328 if (mEncodeBytecode && !StartIncrementalEncoding(mCx, mScript)) {
329 mSkip = true;
330 mRv = EvaluationExceptionToNSResult(mCx);
331 return mRv;
332 }
333
334 return NS_OK;
335 #else
336 return NS_ERROR_NOT_IMPLEMENTED;
337 #endif
338 }
339
DecodeBinAST(JS::CompileOptions & aCompileOptions,const uint8_t * aBuf,size_t aLength)340 nsresult nsJSUtils::ExecutionContext::DecodeBinAST(
341 JS::CompileOptions& aCompileOptions, const uint8_t* aBuf, size_t aLength) {
342 #ifdef JS_BUILD_BINAST
343 MOZ_ASSERT(mScopeChain.length() == 0,
344 "BinAST decoding is not supported in non-syntactic scopes");
345
346 if (mSkip) {
347 return mRv;
348 }
349
350 MOZ_ASSERT(aBuf);
351 MOZ_ASSERT(mRetValue.isUndefined());
352 # ifdef DEBUG
353 mWantsReturnValue = !aCompileOptions.noScriptRval;
354 # endif
355
356 mScript.set(JS::DecodeBinAST(mCx, aCompileOptions, aBuf, aLength,
357 JS::BinASTFormat::Multipart));
358
359 if (!mScript) {
360 mSkip = true;
361 mRv = EvaluationExceptionToNSResult(mCx);
362 return mRv;
363 }
364
365 if (mEncodeBytecode && !StartIncrementalEncoding(mCx, mScript)) {
366 mSkip = true;
367 mRv = EvaluationExceptionToNSResult(mCx);
368 return mRv;
369 }
370
371 return NS_OK;
372 #else
373 return NS_ERROR_NOT_IMPLEMENTED;
374 #endif
375 }
376
GetScript()377 JSScript* nsJSUtils::ExecutionContext::GetScript() {
378 #ifdef DEBUG
379 MOZ_ASSERT(!mSkip);
380 MOZ_ASSERT(mScript);
381 mScriptUsed = true;
382 #endif
383
384 return MaybeGetScript();
385 }
386
MaybeGetScript()387 JSScript* nsJSUtils::ExecutionContext::MaybeGetScript() { return mScript; }
388
ExecScript()389 nsresult nsJSUtils::ExecutionContext::ExecScript() {
390 if (mSkip) {
391 return mRv;
392 }
393
394 MOZ_ASSERT(mScript);
395
396 if (!JS_ExecuteScript(mCx, mScopeChain, mScript)) {
397 mSkip = true;
398 mRv = EvaluationExceptionToNSResult(mCx);
399 return mRv;
400 }
401
402 return NS_OK;
403 }
404
IsPromiseValue(JSContext * aCx,JS::Handle<JS::Value> aValue)405 static bool IsPromiseValue(JSContext* aCx, JS::Handle<JS::Value> aValue) {
406 if (!aValue.isObject()) {
407 return false;
408 }
409
410 // We only care about Promise here, so CheckedUnwrapStatic is fine.
411 JS::Rooted<JSObject*> obj(aCx, js::CheckedUnwrapStatic(&aValue.toObject()));
412 if (!obj) {
413 return false;
414 }
415
416 return JS::IsPromiseObject(obj);
417 }
418
ExecScript(JS::MutableHandle<JS::Value> aRetValue)419 nsresult nsJSUtils::ExecutionContext::ExecScript(
420 JS::MutableHandle<JS::Value> aRetValue) {
421 if (mSkip) {
422 aRetValue.setUndefined();
423 return mRv;
424 }
425
426 MOZ_ASSERT(mScript);
427 MOZ_ASSERT(mWantsReturnValue);
428
429 if (!JS_ExecuteScript(mCx, mScopeChain, mScript, aRetValue)) {
430 mSkip = true;
431 mRv = EvaluationExceptionToNSResult(mCx);
432 return mRv;
433 }
434
435 #ifdef DEBUG
436 mWantsReturnValue = false;
437 #endif
438 if (mCoerceToString && IsPromiseValue(mCx, aRetValue)) {
439 // We're a javascript: url and we should treat Promise return values as
440 // undefined.
441 //
442 // Once bug 1477821 is fixed this code might be able to go away, or will
443 // become enshrined in the spec, depending.
444 aRetValue.setUndefined();
445 }
446
447 if (mCoerceToString && !aRetValue.isUndefined()) {
448 JSString* str = JS::ToString(mCx, aRetValue);
449 if (!str) {
450 // ToString can be a function call, so an exception can be raised while
451 // executing the function.
452 mSkip = true;
453 return EvaluationExceptionToNSResult(mCx);
454 }
455 aRetValue.set(JS::StringValue(str));
456 }
457
458 return NS_OK;
459 }
460
461 template <typename Unit>
CompileJSModule(JSContext * aCx,JS::SourceText<Unit> & aSrcBuf,JS::Handle<JSObject * > aEvaluationGlobal,JS::CompileOptions & aCompileOptions,JS::MutableHandle<JSObject * > aModule)462 static nsresult CompileJSModule(JSContext* aCx, JS::SourceText<Unit>& aSrcBuf,
463 JS::Handle<JSObject*> aEvaluationGlobal,
464 JS::CompileOptions& aCompileOptions,
465 JS::MutableHandle<JSObject*> aModule) {
466 AUTO_PROFILER_LABEL("nsJSUtils::CompileModule", JS);
467 MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
468 MOZ_ASSERT(aSrcBuf.get());
469 MOZ_ASSERT(JS_IsGlobalObject(aEvaluationGlobal));
470 MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx) == aEvaluationGlobal);
471 MOZ_ASSERT(NS_IsMainThread());
472 MOZ_ASSERT(CycleCollectedJSContext::Get() &&
473 CycleCollectedJSContext::Get()->MicroTaskLevel());
474
475 NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
476
477 JSObject* module = JS::CompileModule(aCx, aCompileOptions, aSrcBuf);
478 if (!module) {
479 return NS_ERROR_FAILURE;
480 }
481
482 aModule.set(module);
483 return NS_OK;
484 }
485
CompileModule(JSContext * aCx,JS::SourceText<char16_t> & aSrcBuf,JS::Handle<JSObject * > aEvaluationGlobal,JS::CompileOptions & aCompileOptions,JS::MutableHandle<JSObject * > aModule)486 nsresult nsJSUtils::CompileModule(JSContext* aCx,
487 JS::SourceText<char16_t>& aSrcBuf,
488 JS::Handle<JSObject*> aEvaluationGlobal,
489 JS::CompileOptions& aCompileOptions,
490 JS::MutableHandle<JSObject*> aModule) {
491 return CompileJSModule(aCx, aSrcBuf, aEvaluationGlobal, aCompileOptions,
492 aModule);
493 }
494
CompileModule(JSContext * aCx,JS::SourceText<Utf8Unit> & aSrcBuf,JS::Handle<JSObject * > aEvaluationGlobal,JS::CompileOptions & aCompileOptions,JS::MutableHandle<JSObject * > aModule)495 nsresult nsJSUtils::CompileModule(JSContext* aCx,
496 JS::SourceText<Utf8Unit>& aSrcBuf,
497 JS::Handle<JSObject*> aEvaluationGlobal,
498 JS::CompileOptions& aCompileOptions,
499 JS::MutableHandle<JSObject*> aModule) {
500 return CompileJSModule(aCx, aSrcBuf, aEvaluationGlobal, aCompileOptions,
501 aModule);
502 }
503
ModuleInstantiate(JSContext * aCx,JS::Handle<JSObject * > aModule)504 nsresult nsJSUtils::ModuleInstantiate(JSContext* aCx,
505 JS::Handle<JSObject*> aModule) {
506 AUTO_PROFILER_LABEL("nsJSUtils::ModuleInstantiate", JS);
507
508 MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
509 MOZ_ASSERT(NS_IsMainThread());
510 MOZ_ASSERT(CycleCollectedJSContext::Get() &&
511 CycleCollectedJSContext::Get()->MicroTaskLevel());
512
513 NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
514
515 if (!JS::ModuleInstantiate(aCx, aModule)) {
516 return NS_ERROR_FAILURE;
517 }
518
519 return NS_OK;
520 }
521
ModuleEvaluate(JSContext * aCx,JS::Handle<JSObject * > aModule)522 nsresult nsJSUtils::ModuleEvaluate(JSContext* aCx,
523 JS::Handle<JSObject*> aModule) {
524 AUTO_PROFILER_LABEL("nsJSUtils::ModuleEvaluate", JS);
525
526 MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
527 MOZ_ASSERT(NS_IsMainThread());
528 MOZ_ASSERT(CycleCollectedJSContext::Get() &&
529 CycleCollectedJSContext::Get()->MicroTaskLevel());
530
531 NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
532
533 if (!JS::ModuleEvaluate(aCx, aModule)) {
534 return NS_ERROR_FAILURE;
535 }
536
537 return NS_OK;
538 }
539
AddScopeChainItem(JSContext * aCx,nsINode * aNode,JS::MutableHandleVector<JSObject * > aScopeChain)540 static bool AddScopeChainItem(JSContext* aCx, nsINode* aNode,
541 JS::MutableHandleVector<JSObject*> aScopeChain) {
542 JS::RootedValue val(aCx);
543 if (!GetOrCreateDOMReflector(aCx, aNode, &val)) {
544 return false;
545 }
546
547 if (!aScopeChain.append(&val.toObject())) {
548 return false;
549 }
550
551 return true;
552 }
553
554 /* static */
GetScopeChainForElement(JSContext * aCx,Element * aElement,JS::MutableHandleVector<JSObject * > aScopeChain)555 bool nsJSUtils::GetScopeChainForElement(
556 JSContext* aCx, Element* aElement,
557 JS::MutableHandleVector<JSObject*> aScopeChain) {
558 for (nsINode* cur = aElement; cur; cur = cur->GetScopeChainParent()) {
559 if (!AddScopeChainItem(aCx, cur, aScopeChain)) {
560 return false;
561 }
562 }
563
564 return true;
565 }
566
567 /* static */
ResetTimeZone()568 void nsJSUtils::ResetTimeZone() { JS::ResetTimeZone(); }
569
570 /* static */
DumpEnabled()571 bool nsJSUtils::DumpEnabled() {
572 #if defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP)
573 return true;
574 #else
575 return StaticPrefs::browser_dom_window_dump_enabled();
576 #endif
577 }
578
579 //
580 // nsDOMJSUtils.h
581 //
582
583 template <typename T>
init(const JS::Value & v)584 bool nsTAutoJSString<T>::init(const JS::Value& v) {
585 // Note: it's okay to use danger::GetJSContext here instead of AutoJSAPI,
586 // because the init() call below is careful not to run script (for instance,
587 // it only calls JS::ToString for non-object values).
588 JSContext* cx = danger::GetJSContext();
589 if (!init(cx, v)) {
590 JS_ClearPendingException(cx);
591 return false;
592 }
593 return true;
594 }
595
596 template bool nsTAutoJSString<char16_t>::init(const JS::Value&);
597 template bool nsTAutoJSString<char>::init(const JS::Value&);
598