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