1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sts=4 et sw=4 tw=99:
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  * JavaScript API.
9  */
10 
11 #include "jsapi.h"
12 
13 #include "mozilla/FloatingPoint.h"
14 #include "mozilla/PodOperations.h"
15 #include "mozilla/Sprintf.h"
16 
17 #include <ctype.h>
18 #include <stdarg.h>
19 #include <string.h>
20 #include <sys/stat.h>
21 
22 #include "jsarray.h"
23 #include "jsatom.h"
24 #include "jsbool.h"
25 #include "jscntxt.h"
26 #include "jsdate.h"
27 #include "jsexn.h"
28 #include "jsfriendapi.h"
29 #include "jsfun.h"
30 #include "jsgc.h"
31 #include "jsiter.h"
32 #include "jsmath.h"
33 #include "jsnum.h"
34 #include "jsobj.h"
35 #include "json.h"
36 #include "jsprf.h"
37 #include "jsscript.h"
38 #include "jsstr.h"
39 #include "jstypes.h"
40 #include "jsutil.h"
41 #include "jswatchpoint.h"
42 #include "jsweakmap.h"
43 #include "jswrapper.h"
44 
45 #include "builtin/AtomicsObject.h"
46 #include "builtin/Eval.h"
47 #include "builtin/Intl.h"
48 #include "builtin/MapObject.h"
49 #include "builtin/Promise.h"
50 #include "builtin/RegExp.h"
51 #include "builtin/SymbolObject.h"
52 #ifdef ENABLE_SIMD
53 # include "builtin/SIMD.h"
54 #endif
55 #ifdef ENABLE_BINARYDATA
56 # include "builtin/TypedObject.h"
57 #endif
58 #include "frontend/BytecodeCompiler.h"
59 #include "frontend/FullParseHandler.h"  // for JS_BufferIsCompileableUnit
60 #include "frontend/Parser.h" // for JS_BufferIsCompileableUnit
61 #include "gc/Marking.h"
62 #include "gc/Policy.h"
63 #include "jit/JitCommon.h"
64 #include "js/CharacterEncoding.h"
65 #include "js/Conversions.h"
66 #include "js/Date.h"
67 #include "js/Initialization.h"
68 #include "js/Proxy.h"
69 #include "js/SliceBudget.h"
70 #include "js/StructuredClone.h"
71 #include "js/UniquePtr.h"
72 #include "js/Utility.h"
73 #include "vm/AsyncFunction.h"
74 #include "vm/DateObject.h"
75 #include "vm/Debugger.h"
76 #include "vm/EnvironmentObject.h"
77 #include "vm/ErrorObject.h"
78 #include "vm/HelperThreads.h"
79 #include "vm/Interpreter.h"
80 #include "vm/RegExpStatics.h"
81 #include "vm/Runtime.h"
82 #include "vm/SavedStacks.h"
83 #include "vm/SelfHosting.h"
84 #include "vm/Shape.h"
85 #include "vm/StopIterationObject.h"
86 #include "vm/String.h"
87 #include "vm/StringBuffer.h"
88 #include "vm/Symbol.h"
89 #include "vm/TypedArrayCommon.h"
90 #include "vm/WrapperObject.h"
91 #include "vm/Xdr.h"
92 #include "wasm/AsmJS.h"
93 #include "wasm/WasmModule.h"
94 
95 #include "jsatominlines.h"
96 #include "jsfuninlines.h"
97 #include "jsscriptinlines.h"
98 
99 #include "vm/Interpreter-inl.h"
100 #include "vm/NativeObject-inl.h"
101 #include "vm/SavedStacks-inl.h"
102 #include "vm/String-inl.h"
103 
104 using namespace js;
105 using namespace js::gc;
106 
107 using mozilla::Maybe;
108 using mozilla::PodCopy;
109 using mozilla::PodZero;
110 
111 using JS::AutoGCRooter;
112 using JS::ToInt32;
113 using JS::ToInteger;
114 using JS::ToUint32;
115 
116 #ifdef HAVE_VA_LIST_AS_ARRAY
117 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list*)(ap))
118 #else
119 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
120 #endif
121 
122 JS_PUBLIC_API(bool)
123 JS::CallArgs::requireAtLeast(JSContext* cx, const char* fnname, unsigned required) const
124 {
125     if (length() < required) {
126         char numArgsStr[40];
127         SprintfLiteral(numArgsStr, "%u", required - 1);
128         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
129                                   fnname, numArgsStr, required == 2 ? "" : "s");
130         return false;
131     }
132 
133     return true;
134 }
135 
136 static bool
137 ErrorTakesArguments(unsigned msg)
138 {
139     MOZ_ASSERT(msg < JSErr_Limit);
140     unsigned argCount = js_ErrorFormatString[msg].argCount;
141     MOZ_ASSERT(argCount <= 2);
142     return argCount == 1 || argCount == 2;
143 }
144 
145 static bool
146 ErrorTakesObjectArgument(unsigned msg)
147 {
148     MOZ_ASSERT(msg < JSErr_Limit);
149     unsigned argCount = js_ErrorFormatString[msg].argCount;
150     MOZ_ASSERT(argCount <= 2);
151     return argCount == 2;
152 }
153 
154 JS_PUBLIC_API(bool)
155 JS::ObjectOpResult::reportStrictErrorOrWarning(JSContext* cx, HandleObject obj, HandleId id,
156                                                bool strict)
157 {
158     static_assert(unsigned(OkCode) == unsigned(JSMSG_NOT_AN_ERROR),
159                   "unsigned value of OkCode must not be an error code");
160     MOZ_ASSERT(code_ != Uninitialized);
161     MOZ_ASSERT(!ok());
162 
163     unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_WARNING | JSREPORT_STRICT);
164     if (code_ == JSMSG_OBJECT_NOT_EXTENSIBLE || code_ == JSMSG_SET_NON_OBJECT_RECEIVER) {
165         RootedValue val(cx, ObjectValue(*obj));
166         return ReportValueErrorFlags(cx, flags, code_, JSDVG_IGNORE_STACK, val,
167                                      nullptr, nullptr, nullptr);
168     }
169     if (ErrorTakesArguments(code_)) {
170         RootedValue idv(cx, IdToValue(id));
171         RootedString str(cx, ValueToSource(cx, idv));
172         if (!str)
173             return false;
174 
175         JSAutoByteString propName;
176         if (!propName.encodeUtf8(cx, str))
177             return false;
178 
179         if (ErrorTakesObjectArgument(code_)) {
180             return JS_ReportErrorFlagsAndNumberUTF8(cx, flags, GetErrorMessage, nullptr, code_,
181                                                     obj->getClass()->name, propName.ptr());
182         }
183 
184         return JS_ReportErrorFlagsAndNumberUTF8(cx, flags, GetErrorMessage, nullptr, code_,
185                                                 propName.ptr());
186     }
187     return JS_ReportErrorFlagsAndNumberASCII(cx, flags, GetErrorMessage, nullptr, code_);
188 }
189 
190 JS_PUBLIC_API(bool)
191 JS::ObjectOpResult::reportStrictErrorOrWarning(JSContext* cx, HandleObject obj, bool strict)
192 {
193     MOZ_ASSERT(code_ != Uninitialized);
194     MOZ_ASSERT(!ok());
195     MOZ_ASSERT(!ErrorTakesArguments(code_));
196 
197     unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_WARNING | JSREPORT_STRICT);
198     return JS_ReportErrorFlagsAndNumberASCII(cx, flags, GetErrorMessage, nullptr, code_);
199 }
200 
201 JS_PUBLIC_API(bool)
202 JS::ObjectOpResult::failCantRedefineProp()
203 {
204     return fail(JSMSG_CANT_REDEFINE_PROP);
205 }
206 
207 JS_PUBLIC_API(bool)
208 JS::ObjectOpResult::failReadOnly()
209 {
210     return fail(JSMSG_READ_ONLY);
211 }
212 
213 JS_PUBLIC_API(bool)
214 JS::ObjectOpResult::failGetterOnly()
215 {
216     return fail(JSMSG_GETTER_ONLY);
217 }
218 
219 JS_PUBLIC_API(bool)
220 JS::ObjectOpResult::failCantDelete()
221 {
222     return fail(JSMSG_CANT_DELETE);
223 }
224 
225 JS_PUBLIC_API(bool)
226 JS::ObjectOpResult::failCantSetInterposed()
227 {
228     return fail(JSMSG_CANT_SET_INTERPOSED);
229 }
230 
231 JS_PUBLIC_API(bool)
232 JS::ObjectOpResult::failCantDefineWindowElement()
233 {
234     return fail(JSMSG_CANT_DEFINE_WINDOW_ELEMENT);
235 }
236 
237 JS_PUBLIC_API(bool)
238 JS::ObjectOpResult::failCantDeleteWindowElement()
239 {
240     return fail(JSMSG_CANT_DELETE_WINDOW_ELEMENT);
241 }
242 
243 JS_PUBLIC_API(bool)
244 JS::ObjectOpResult::failCantDeleteWindowNamedProperty()
245 {
246     return fail(JSMSG_CANT_DELETE_WINDOW_NAMED_PROPERTY);
247 }
248 
249 JS_PUBLIC_API(bool)
250 JS::ObjectOpResult::failCantPreventExtensions()
251 {
252     return fail(JSMSG_CANT_PREVENT_EXTENSIONS);
253 }
254 
255 JS_PUBLIC_API(bool)
256 JS::ObjectOpResult::failCantSetProto()
257 {
258     return fail(JSMSG_CANT_SET_PROTO);
259 }
260 
261 JS_PUBLIC_API(bool)
262 JS::ObjectOpResult::failNoNamedSetter()
263 {
264     return fail(JSMSG_NO_NAMED_SETTER);
265 }
266 
267 JS_PUBLIC_API(bool)
268 JS::ObjectOpResult::failNoIndexedSetter()
269 {
270     return fail(JSMSG_NO_INDEXED_SETTER);
271 }
272 
273 JS_PUBLIC_API(int64_t)
274 JS_Now()
275 {
276     return PRMJ_Now();
277 }
278 
279 JS_PUBLIC_API(Value)
280 JS_GetNaNValue(JSContext* cx)
281 {
282     return cx->runtime()->NaNValue;
283 }
284 
285 JS_PUBLIC_API(Value)
286 JS_GetNegativeInfinityValue(JSContext* cx)
287 {
288     return cx->runtime()->negativeInfinityValue;
289 }
290 
291 JS_PUBLIC_API(Value)
292 JS_GetPositiveInfinityValue(JSContext* cx)
293 {
294     return cx->runtime()->positiveInfinityValue;
295 }
296 
297 JS_PUBLIC_API(Value)
298 JS_GetEmptyStringValue(JSContext* cx)
299 {
300     return StringValue(cx->runtime()->emptyString);
301 }
302 
303 JS_PUBLIC_API(JSString*)
304 JS_GetEmptyString(JSContext* cx)
305 {
306     MOZ_ASSERT(cx->emptyString());
307     return cx->emptyString();
308 }
309 
310 namespace js {
311 
312 void
313 AssertHeapIsIdle(JSRuntime* rt)
314 {
315     MOZ_ASSERT(!rt->isHeapBusy());
316 }
317 
318 } // namespace js
319 
320 static void
321 AssertHeapIsIdleOrIterating(JSRuntime* rt)
322 {
323     MOZ_ASSERT(!rt->isHeapCollecting());
324 }
325 
326 static void
327 AssertHeapIsIdleOrStringIsFlat(JSContext* cx, JSString* str)
328 {
329     /*
330      * We allow some functions to be called during a GC as long as the argument
331      * is a flat string, since that will not cause allocation.
332      */
333     MOZ_ASSERT_IF(cx->runtime()->isHeapBusy(), str->isFlat());
334 }
335 
336 JS_PUBLIC_API(bool)
337 JS_ValueToObject(JSContext* cx, HandleValue value, MutableHandleObject objp)
338 {
339     AssertHeapIsIdle(cx);
340     CHECK_REQUEST(cx);
341     assertSameCompartment(cx, value);
342     if (value.isNullOrUndefined()) {
343         objp.set(nullptr);
344         return true;
345     }
346     JSObject* obj = ToObject(cx, value);
347     if (!obj)
348         return false;
349     objp.set(obj);
350     return true;
351 }
352 
353 JS_PUBLIC_API(JSFunction*)
354 JS_ValueToFunction(JSContext* cx, HandleValue value)
355 {
356     AssertHeapIsIdle(cx);
357     CHECK_REQUEST(cx);
358     assertSameCompartment(cx, value);
359     return ReportIfNotFunction(cx, value);
360 }
361 
362 JS_PUBLIC_API(JSFunction*)
363 JS_ValueToConstructor(JSContext* cx, HandleValue value)
364 {
365     AssertHeapIsIdle(cx);
366     CHECK_REQUEST(cx);
367     assertSameCompartment(cx, value);
368     return ReportIfNotFunction(cx, value);
369 }
370 
371 JS_PUBLIC_API(JSString*)
372 JS_ValueToSource(JSContext* cx, HandleValue value)
373 {
374     AssertHeapIsIdle(cx);
375     CHECK_REQUEST(cx);
376     assertSameCompartment(cx, value);
377     return ValueToSource(cx, value);
378 }
379 
380 JS_PUBLIC_API(bool)
381 JS_DoubleIsInt32(double d, int32_t* ip)
382 {
383     return mozilla::NumberIsInt32(d, ip);
384 }
385 
386 JS_PUBLIC_API(JSType)
387 JS_TypeOfValue(JSContext* cx, HandleValue value)
388 {
389     AssertHeapIsIdle(cx);
390     CHECK_REQUEST(cx);
391     assertSameCompartment(cx, value);
392     return TypeOfValue(value);
393 }
394 
395 JS_PUBLIC_API(bool)
396 JS_StrictlyEqual(JSContext* cx, HandleValue value1, HandleValue value2, bool* equal)
397 {
398     AssertHeapIsIdle(cx);
399     CHECK_REQUEST(cx);
400     assertSameCompartment(cx, value1, value2);
401     MOZ_ASSERT(equal);
402     return StrictlyEqual(cx, value1, value2, equal);
403 }
404 
405 JS_PUBLIC_API(bool)
406 JS_LooselyEqual(JSContext* cx, HandleValue value1, HandleValue value2, bool* equal)
407 {
408     AssertHeapIsIdle(cx);
409     CHECK_REQUEST(cx);
410     assertSameCompartment(cx, value1, value2);
411     MOZ_ASSERT(equal);
412     return LooselyEqual(cx, value1, value2, equal);
413 }
414 
415 JS_PUBLIC_API(bool)
416 JS_SameValue(JSContext* cx, HandleValue value1, HandleValue value2, bool* same)
417 {
418     AssertHeapIsIdle(cx);
419     CHECK_REQUEST(cx);
420     assertSameCompartment(cx, value1, value2);
421     MOZ_ASSERT(same);
422     return SameValue(cx, value1, value2, same);
423 }
424 
425 JS_PUBLIC_API(bool)
426 JS_IsBuiltinEvalFunction(JSFunction* fun)
427 {
428     return IsAnyBuiltinEval(fun);
429 }
430 
431 JS_PUBLIC_API(bool)
432 JS_IsBuiltinFunctionConstructor(JSFunction* fun)
433 {
434     return fun->isBuiltinFunctionConstructor();
435 }
436 
437 JS_PUBLIC_API(bool)
438 JS_IsFunctionBound(JSFunction* fun)
439 {
440     return fun->isBoundFunction();
441 }
442 
443 JS_PUBLIC_API(JSObject*)
444 JS_GetBoundFunctionTarget(JSFunction* fun)
445 {
446     return fun->isBoundFunction() ?
447                fun->getBoundFunctionTarget() : nullptr;
448 }
449 
450 /************************************************************************/
451 
452 #ifdef DEBUG
453 JS_FRIEND_API(bool)
454 JS::isGCEnabled()
455 {
456     return !TlsPerThreadData.get()->suppressGC;
457 }
458 #else
459 JS_FRIEND_API(bool) JS::isGCEnabled() { return true; }
460 #endif
461 
462 JS_PUBLIC_API(JSContext*)
463 JS_NewContext(uint32_t maxbytes, uint32_t maxNurseryBytes, JSContext* parentContext)
464 {
465     MOZ_ASSERT(JS::detail::libraryInitState == JS::detail::InitState::Running,
466                "must call JS_Init prior to creating any JSContexts");
467 
468     // Make sure that all parent runtimes are the topmost parent.
469     JSRuntime* parentRuntime = nullptr;
470     if (parentContext) {
471         parentRuntime = parentContext->runtime();
472         while (parentRuntime && parentRuntime->parentRuntime)
473             parentRuntime = parentRuntime->parentRuntime;
474     }
475 
476     return NewContext(maxbytes, maxNurseryBytes, parentRuntime);
477 }
478 
479 JS_PUBLIC_API(void)
480 JS_DestroyContext(JSContext* cx)
481 {
482     DestroyContext(cx);
483 }
484 
485 static JS_CurrentEmbedderTimeFunction currentEmbedderTimeFunction;
486 
487 JS_PUBLIC_API(void)
488 JS_SetCurrentEmbedderTimeFunction(JS_CurrentEmbedderTimeFunction timeFn)
489 {
490     currentEmbedderTimeFunction = timeFn;
491 }
492 
493 JS_PUBLIC_API(double)
494 JS_GetCurrentEmbedderTime()
495 {
496     if (currentEmbedderTimeFunction)
497         return currentEmbedderTimeFunction();
498     return PRMJ_Now() / static_cast<double>(PRMJ_USEC_PER_MSEC);
499 }
500 
501 JS_PUBLIC_API(void*)
502 JS_GetContextPrivate(JSContext* cx)
503 {
504     return cx->data;
505 }
506 
507 JS_PUBLIC_API(void)
508 JS_SetContextPrivate(JSContext* cx, void* data)
509 {
510     cx->data = data;
511 }
512 
513 JS_PUBLIC_API(void)
514 JS_SetFutexCanWait(JSContext* cx)
515 {
516     cx->fx.setCanWait(true);
517 }
518 
519 static void
520 StartRequest(JSContext* cx)
521 {
522     JSRuntime* rt = cx->runtime();
523     MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
524 
525     if (rt->requestDepth) {
526         rt->requestDepth++;
527     } else {
528         /* Indicate that a request is running. */
529         rt->requestDepth = 1;
530         rt->triggerActivityCallback(true);
531     }
532 }
533 
534 static void
535 StopRequest(JSContext* cx)
536 {
537     JSRuntime* rt = cx->runtime();
538     MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
539 
540     MOZ_ASSERT(rt->requestDepth != 0);
541     if (rt->requestDepth != 1) {
542         rt->requestDepth--;
543     } else {
544         rt->requestDepth = 0;
545         rt->triggerActivityCallback(false);
546     }
547 }
548 
549 JS_PUBLIC_API(void)
550 JS_BeginRequest(JSContext* cx)
551 {
552     cx->outstandingRequests++;
553     StartRequest(cx);
554 }
555 
556 JS_PUBLIC_API(void)
557 JS_EndRequest(JSContext* cx)
558 {
559     MOZ_ASSERT(cx->outstandingRequests != 0);
560     cx->outstandingRequests--;
561     StopRequest(cx);
562 }
563 
564 JS_PUBLIC_API(JSContext*)
565 JS_GetParentContext(JSContext* cx)
566 {
567     return cx->parentRuntime ? cx->parentRuntime->unsafeContextFromAnyThread() : cx;
568 }
569 
570 JS_PUBLIC_API(JSVersion)
571 JS_GetVersion(JSContext* cx)
572 {
573     return VersionNumber(cx->findVersion());
574 }
575 
576 JS_PUBLIC_API(void)
577 JS_SetVersionForCompartment(JSCompartment* compartment, JSVersion version)
578 {
579     compartment->behaviors().setVersion(version);
580 }
581 
582 static const struct v2smap {
583     JSVersion   version;
584     const char* string;
585 } v2smap[] = {
586     {JSVERSION_ECMA_3,  "ECMAv3"},
587     {JSVERSION_1_6,     "1.6"},
588     {JSVERSION_1_7,     "1.7"},
589     {JSVERSION_1_8,     "1.8"},
590     {JSVERSION_ECMA_5,  "ECMAv5"},
591     {JSVERSION_DEFAULT, js_default_str},
592     {JSVERSION_DEFAULT, "1.0"},
593     {JSVERSION_DEFAULT, "1.1"},
594     {JSVERSION_DEFAULT, "1.2"},
595     {JSVERSION_DEFAULT, "1.3"},
596     {JSVERSION_DEFAULT, "1.4"},
597     {JSVERSION_DEFAULT, "1.5"},
598     {JSVERSION_UNKNOWN, nullptr},          /* must be last, nullptr is sentinel */
599 };
600 
601 JS_PUBLIC_API(const char*)
602 JS_VersionToString(JSVersion version)
603 {
604     int i;
605 
606     for (i = 0; v2smap[i].string; i++)
607         if (v2smap[i].version == version)
608             return v2smap[i].string;
609     return "unknown";
610 }
611 
612 JS_PUBLIC_API(JSVersion)
613 JS_StringToVersion(const char* string)
614 {
615     int i;
616 
617     for (i = 0; v2smap[i].string; i++)
618         if (strcmp(v2smap[i].string, string) == 0)
619             return v2smap[i].version;
620     return JSVERSION_UNKNOWN;
621 }
622 
623 JS_PUBLIC_API(JS::ContextOptions&)
624 JS::ContextOptionsRef(JSContext* cx)
625 {
626     return cx->options();
627 }
628 
629 JS_PUBLIC_API(bool)
630 JS::InitSelfHostedCode(JSContext* cx)
631 {
632     MOZ_RELEASE_ASSERT(!cx->runtime()->hasInitializedSelfHosting(),
633                        "JS::InitSelfHostedCode() called more than once");
634 
635     JSRuntime* rt = cx->runtime();
636 
637     JSAutoRequest ar(cx);
638     if (!rt->initializeAtoms(cx))
639         return false;
640 
641     if (!cx->cycleDetectorSet.init())
642         return false;
643 
644     if (!rt->initSelfHosting(cx))
645         return false;
646 
647     if (!rt->parentRuntime && !rt->transformToPermanentAtoms(cx))
648         return false;
649 
650     return true;
651 }
652 
653 JS_PUBLIC_API(const char*)
654 JS_GetImplementationVersion(void)
655 {
656     return "JavaScript-C" MOZILLA_VERSION;
657 }
658 
659 JS_PUBLIC_API(void)
660 JS_SetDestroyCompartmentCallback(JSContext* cx, JSDestroyCompartmentCallback callback)
661 {
662     cx->destroyCompartmentCallback = callback;
663 }
664 
665 JS_PUBLIC_API(void)
666 JS_SetSizeOfIncludingThisCompartmentCallback(JSContext* cx,
667                                              JSSizeOfIncludingThisCompartmentCallback callback)
668 {
669     cx->sizeOfIncludingThisCompartmentCallback = callback;
670 }
671 
672 JS_PUBLIC_API(void)
673 JS_SetDestroyZoneCallback(JSContext* cx, JSZoneCallback callback)
674 {
675     cx->destroyZoneCallback = callback;
676 }
677 
678 JS_PUBLIC_API(void)
679 JS_SetSweepZoneCallback(JSContext* cx, JSZoneCallback callback)
680 {
681     cx->sweepZoneCallback = callback;
682 }
683 
684 JS_PUBLIC_API(void)
685 JS_SetCompartmentNameCallback(JSContext* cx, JSCompartmentNameCallback callback)
686 {
687     cx->compartmentNameCallback = callback;
688 }
689 
690 JS_PUBLIC_API(void)
691 JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks)
692 {
693     cx->wrapObjectCallbacks = callbacks;
694 }
695 
696 JS_PUBLIC_API(JSCompartment*)
697 JS_EnterCompartment(JSContext* cx, JSObject* target)
698 {
699     AssertHeapIsIdle(cx);
700     CHECK_REQUEST(cx);
701     MOZ_ASSERT(!JS::ObjectIsMarkedGray(target));
702 
703     JSCompartment* oldCompartment = cx->compartment();
704     cx->enterCompartment(target->compartment());
705     return oldCompartment;
706 }
707 
708 JS_PUBLIC_API(void)
709 JS_LeaveCompartment(JSContext* cx, JSCompartment* oldCompartment)
710 {
711     AssertHeapIsIdle(cx);
712     CHECK_REQUEST(cx);
713     cx->leaveCompartment(oldCompartment);
714 }
715 
716 JSAutoCompartment::JSAutoCompartment(JSContext* cx, JSObject* target
717                                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
718   : cx_(cx),
719     oldCompartment_(cx->compartment())
720 {
721     AssertHeapIsIdleOrIterating(cx_);
722     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
723     MOZ_ASSERT(!JS::ObjectIsMarkedGray(target));
724     cx_->enterCompartment(target->compartment());
725 }
726 
727 JSAutoCompartment::JSAutoCompartment(JSContext* cx, JSScript* target
728                                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
729   : cx_(cx),
730     oldCompartment_(cx->compartment())
731 {
732     AssertHeapIsIdleOrIterating(cx_);
733     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
734     MOZ_ASSERT(!JS::ScriptIsMarkedGray(target));
735     cx_->enterCompartment(target->compartment());
736 }
737 
738 JSAutoCompartment::~JSAutoCompartment()
739 {
740     cx_->leaveCompartment(oldCompartment_);
741 }
742 
743 JSAutoNullableCompartment::JSAutoNullableCompartment(JSContext* cx,
744                                                      JSObject* targetOrNull
745                                                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
746   : cx_(cx),
747     oldCompartment_(cx->compartment())
748 {
749     AssertHeapIsIdleOrIterating(cx_);
750     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
751     if (targetOrNull) {
752         MOZ_ASSERT(!JS::ObjectIsMarkedGray(targetOrNull));
753         cx_->enterCompartment(targetOrNull->compartment());
754     } else {
755         cx_->enterNullCompartment();
756     }
757 }
758 
759 JSAutoNullableCompartment::~JSAutoNullableCompartment()
760 {
761     cx_->leaveCompartment(oldCompartment_);
762 }
763 
764 JS_PUBLIC_API(void)
765 JS_SetCompartmentPrivate(JSCompartment* compartment, void* data)
766 {
767     compartment->data = data;
768 }
769 
770 JS_PUBLIC_API(void*)
771 JS_GetCompartmentPrivate(JSCompartment* compartment)
772 {
773     return compartment->data;
774 }
775 
776 JS_PUBLIC_API(JSAddonId*)
777 JS::NewAddonId(JSContext* cx, HandleString str)
778 {
779     return static_cast<JSAddonId*>(JS_AtomizeAndPinJSString(cx, str));
780 }
781 
782 JS_PUBLIC_API(JSString*)
783 JS::StringOfAddonId(JSAddonId* id)
784 {
785     return id;
786 }
787 
788 JS_PUBLIC_API(JSAddonId*)
789 JS::AddonIdOfObject(JSObject* obj)
790 {
791     return obj->compartment()->creationOptions().addonIdOrNull();
792 }
793 
794 JS_PUBLIC_API(void)
795 JS_SetZoneUserData(JS::Zone* zone, void* data)
796 {
797     zone->data = data;
798 }
799 
800 JS_PUBLIC_API(void*)
801 JS_GetZoneUserData(JS::Zone* zone)
802 {
803     return zone->data;
804 }
805 
806 JS_PUBLIC_API(bool)
807 JS_WrapObject(JSContext* cx, MutableHandleObject objp)
808 {
809     AssertHeapIsIdle(cx);
810     CHECK_REQUEST(cx);
811     if (objp)
812         JS::ExposeObjectToActiveJS(objp);
813     return cx->compartment()->wrap(cx, objp);
814 }
815 
816 JS_PUBLIC_API(bool)
817 JS_WrapValue(JSContext* cx, MutableHandleValue vp)
818 {
819     AssertHeapIsIdle(cx);
820     CHECK_REQUEST(cx);
821     JS::ExposeValueToActiveJS(vp);
822     return cx->compartment()->wrap(cx, vp);
823 }
824 
825 /*
826  * Identity remapping. Not for casual consumers.
827  *
828  * Normally, an object's contents and its identity are inextricably linked.
829  * Identity is determined by the address of the JSObject* in the heap, and
830  * the contents are what is located at that address. Transplanting allows these
831  * concepts to be separated through a combination of swapping (exchanging the
832  * contents of two same-compartment objects) and remapping cross-compartment
833  * identities by altering wrappers.
834  *
835  * The |origobj| argument should be the object whose identity needs to be
836  * remapped, usually to another compartment. The contents of |origobj| are
837  * destroyed.
838  *
839  * The |target| argument serves two purposes:
840  *
841  * First, |target| serves as a hint for the new identity of the object. The new
842  * identity object will always be in the same compartment as |target|, but
843  * if that compartment already had an object representing |origobj| (either a
844  * cross-compartment wrapper for it, or |origobj| itself if the two arguments
845  * are same-compartment), the existing object is used. Otherwise, |target|
846  * itself is used. To avoid ambiguity, JS_TransplantObject always returns the
847  * new identity.
848  *
849  * Second, the new identity object's contents will be those of |target|. A swap()
850  * is used to make this happen if an object other than |target| is used.
851  *
852  * We don't have a good way to recover from failure in this function, so
853  * we intentionally crash instead.
854  */
855 
856 JS_PUBLIC_API(JSObject*)
857 JS_TransplantObject(JSContext* cx, HandleObject origobj, HandleObject target)
858 {
859     AssertHeapIsIdle(cx);
860     MOZ_ASSERT(origobj != target);
861     MOZ_ASSERT(!origobj->is<CrossCompartmentWrapperObject>());
862     MOZ_ASSERT(!target->is<CrossCompartmentWrapperObject>());
863 
864     RootedValue origv(cx, ObjectValue(*origobj));
865     RootedObject newIdentity(cx);
866 
867     // Don't allow a compacting GC to observe any intermediate state.
868     AutoDisableCompactingGC nocgc(cx);
869 
870     AutoDisableProxyCheck adpc(cx->runtime());
871 
872     JSCompartment* destination = target->compartment();
873 
874     if (origobj->compartment() == destination) {
875         // If the original object is in the same compartment as the
876         // destination, then we know that we won't find a wrapper in the
877         // destination's cross compartment map and that the same
878         // object will continue to work.
879         if (!JSObject::swap(cx, origobj, target))
880             MOZ_CRASH();
881         newIdentity = origobj;
882     } else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
883         // There might already be a wrapper for the original object in
884         // the new compartment. If there is, we use its identity and swap
885         // in the contents of |target|.
886         newIdentity = &p->value().get().toObject();
887 
888         // When we remove origv from the wrapper map, its wrapper, newIdentity,
889         // must immediately cease to be a cross-compartment wrapper. Nuke it.
890         destination->removeWrapper(p);
891         NukeCrossCompartmentWrapper(cx, newIdentity);
892 
893         if (!JSObject::swap(cx, newIdentity, target))
894             MOZ_CRASH();
895     } else {
896         // Otherwise, we use |target| for the new identity object.
897         newIdentity = target;
898     }
899 
900     // Now, iterate through other scopes looking for references to the
901     // old object, and update the relevant cross-compartment wrappers.
902     if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
903         MOZ_CRASH();
904 
905     // Lastly, update the original object to point to the new one.
906     if (origobj->compartment() != destination) {
907         RootedObject newIdentityWrapper(cx, newIdentity);
908         AutoCompartment ac(cx, origobj);
909         if (!JS_WrapObject(cx, &newIdentityWrapper))
910             MOZ_CRASH();
911         MOZ_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
912         if (!JSObject::swap(cx, origobj, newIdentityWrapper))
913             MOZ_CRASH();
914         if (!origobj->compartment()->putWrapper(cx, CrossCompartmentKey(newIdentity), origv))
915             MOZ_CRASH();
916     }
917 
918     // The new identity object might be one of several things. Return it to avoid
919     // ambiguity.
920     return newIdentity;
921 }
922 
923 /*
924  * Recompute all cross-compartment wrappers for an object, resetting state.
925  * Gecko uses this to clear Xray wrappers when doing a navigation that reuses
926  * the inner window and global object.
927  */
928 JS_PUBLIC_API(bool)
929 JS_RefreshCrossCompartmentWrappers(JSContext* cx, HandleObject obj)
930 {
931     return RemapAllWrappersForObject(cx, obj, obj);
932 }
933 
934 JS_PUBLIC_API(bool)
935 JS_InitStandardClasses(JSContext* cx, HandleObject obj)
936 {
937     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
938     AssertHeapIsIdle(cx);
939     CHECK_REQUEST(cx);
940 
941     assertSameCompartment(cx, obj);
942 
943     Rooted<GlobalObject*> global(cx, &obj->global());
944     return GlobalObject::initStandardClasses(cx, global);
945 }
946 
947 #define EAGER_ATOM(name)            NAME_OFFSET(name)
948 
949 typedef struct JSStdName {
950     size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
951     JSProtoKey  key;
952     bool isDummy() const { return key == JSProto_Null; }
953     bool isSentinel() const { return key == JSProto_LIMIT; }
954 } JSStdName;
955 
956 static const JSStdName*
957 LookupStdName(const JSAtomState& names, JSAtom* name, const JSStdName* table)
958 {
959     for (unsigned i = 0; !table[i].isSentinel(); i++) {
960         if (table[i].isDummy())
961             continue;
962         JSAtom* atom = AtomStateOffsetToName(names, table[i].atomOffset);
963         MOZ_ASSERT(atom);
964         if (name == atom)
965             return &table[i];
966     }
967 
968     return nullptr;
969 }
970 
971 /*
972  * Table of standard classes, indexed by JSProtoKey. For entries where the
973  * JSProtoKey does not correspond to a class with a meaningful constructor, we
974  * insert a null entry into the table.
975  */
976 #define STD_NAME_ENTRY(name, code, init, clasp) { EAGER_ATOM(name), static_cast<JSProtoKey>(code) },
977 #define STD_DUMMY_ENTRY(name, code, init, dummy) { 0, JSProto_Null },
978 static const JSStdName standard_class_names[] = {
979   JS_FOR_PROTOTYPES(STD_NAME_ENTRY, STD_DUMMY_ENTRY)
980   { 0, JSProto_LIMIT }
981 };
982 
983 /*
984  * Table of top-level function and constant names and the JSProtoKey of the
985  * standard class that initializes them.
986  */
987 static const JSStdName builtin_property_names[] = {
988     { EAGER_ATOM(eval), JSProto_Object },
989 
990     /* Global properties and functions defined by the Number class. */
991     { EAGER_ATOM(NaN), JSProto_Number },
992     { EAGER_ATOM(Infinity), JSProto_Number },
993     { EAGER_ATOM(isNaN), JSProto_Number },
994     { EAGER_ATOM(isFinite), JSProto_Number },
995     { EAGER_ATOM(parseFloat), JSProto_Number },
996     { EAGER_ATOM(parseInt), JSProto_Number },
997 
998     /* String global functions. */
999     { EAGER_ATOM(escape), JSProto_String },
1000     { EAGER_ATOM(unescape), JSProto_String },
1001     { EAGER_ATOM(decodeURI), JSProto_String },
1002     { EAGER_ATOM(encodeURI), JSProto_String },
1003     { EAGER_ATOM(decodeURIComponent), JSProto_String },
1004     { EAGER_ATOM(encodeURIComponent), JSProto_String },
1005 #if JS_HAS_UNEVAL
1006     { EAGER_ATOM(uneval), JSProto_String },
1007 #endif
1008 
1009     { 0, JSProto_LIMIT }
1010 };
1011 
1012 #undef EAGER_ATOM
1013 
1014 JS_PUBLIC_API(bool)
1015 JS_ResolveStandardClass(JSContext* cx, HandleObject obj, HandleId id, bool* resolved)
1016 {
1017     const JSStdName* stdnm;
1018 
1019     AssertHeapIsIdle(cx);
1020     CHECK_REQUEST(cx);
1021     assertSameCompartment(cx, obj, id);
1022 
1023     Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
1024     *resolved = false;
1025 
1026     if (!JSID_IS_ATOM(id))
1027         return true;
1028 
1029     /* Check whether we're resolving 'undefined', and define it if so. */
1030     JSAtom* idAtom = JSID_TO_ATOM(id);
1031     JSAtom* undefinedAtom = cx->names().undefined;
1032     if (idAtom == undefinedAtom) {
1033         *resolved = true;
1034         return DefineProperty(cx, global, id, UndefinedHandleValue, nullptr, nullptr,
1035                               JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING);
1036     }
1037 
1038     /* Try for class constructors/prototypes named by well-known atoms. */
1039     stdnm = LookupStdName(cx->names(), idAtom, standard_class_names);
1040 
1041     /* Try less frequently used top-level functions and constants. */
1042     if (!stdnm)
1043         stdnm = LookupStdName(cx->names(), idAtom, builtin_property_names);
1044 
1045     if (stdnm && GlobalObject::skipDeselectedConstructor(cx, stdnm->key))
1046         stdnm = nullptr;
1047 
1048     // If this class is anonymous, then it doesn't exist as a global
1049     // property, so we won't resolve anything.
1050     JSProtoKey key = stdnm ? stdnm->key : JSProto_Null;
1051     if (key != JSProto_Null) {
1052         const Class* clasp = ProtoKeyToClass(key);
1053         if (!clasp || !(clasp->flags & JSCLASS_IS_ANONYMOUS)) {
1054             if (!GlobalObject::ensureConstructor(cx, global, key))
1055                 return false;
1056 
1057             *resolved = true;
1058             return true;
1059         }
1060     }
1061 
1062     // There is no such property to resolve. An ordinary resolve hook would
1063     // just return true at this point. But the global object is special in one
1064     // more way: its prototype chain is lazily initialized. That is,
1065     // global->getProto() might be null right now because we haven't created
1066     // Object.prototype yet. Force it now.
1067     if (!global->getOrCreateObjectPrototype(cx))
1068         return false;
1069 
1070     return true;
1071 }
1072 
1073 JS_PUBLIC_API(bool)
1074 JS_MayResolveStandardClass(const JSAtomState& names, jsid id, JSObject* maybeObj)
1075 {
1076     MOZ_ASSERT_IF(maybeObj, maybeObj->is<GlobalObject>());
1077 
1078     // The global object's resolve hook is special: JS_ResolveStandardClass
1079     // initializes the prototype chain lazily. Only attempt to optimize here
1080     // if we know the prototype chain has been initialized.
1081     if (!maybeObj || !maybeObj->staticPrototype())
1082         return true;
1083 
1084     if (!JSID_IS_ATOM(id))
1085         return false;
1086 
1087     JSAtom* atom = JSID_TO_ATOM(id);
1088 
1089     // This will return true even for deselected constructors.  (To do
1090     // better, we need a JSContext here; it's fine as it is.)
1091 
1092     return atom == names.undefined ||
1093            LookupStdName(names, atom, standard_class_names) ||
1094            LookupStdName(names, atom, builtin_property_names);
1095 }
1096 
1097 JS_PUBLIC_API(bool)
1098 JS_EnumerateStandardClasses(JSContext* cx, HandleObject obj)
1099 {
1100     AssertHeapIsIdle(cx);
1101     CHECK_REQUEST(cx);
1102     assertSameCompartment(cx, obj);
1103     MOZ_ASSERT(obj->is<GlobalObject>());
1104     Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
1105     return GlobalObject::initStandardClasses(cx, global);
1106 }
1107 
1108 JS_PUBLIC_API(bool)
1109 JS_GetClassObject(JSContext* cx, JSProtoKey key, MutableHandleObject objp)
1110 {
1111     AssertHeapIsIdle(cx);
1112     CHECK_REQUEST(cx);
1113     return GetBuiltinConstructor(cx, key, objp);
1114 }
1115 
1116 JS_PUBLIC_API(bool)
1117 JS_GetClassPrototype(JSContext* cx, JSProtoKey key, MutableHandleObject objp)
1118 {
1119     AssertHeapIsIdle(cx);
1120     CHECK_REQUEST(cx);
1121     return GetBuiltinPrototype(cx, key, objp);
1122 }
1123 
1124 namespace JS {
1125 
1126 JS_PUBLIC_API(void)
1127 ProtoKeyToId(JSContext* cx, JSProtoKey key, MutableHandleId idp)
1128 {
1129     idp.set(NameToId(ClassName(key, cx)));
1130 }
1131 
1132 } /* namespace JS */
1133 
1134 JS_PUBLIC_API(JSProtoKey)
1135 JS_IdToProtoKey(JSContext* cx, HandleId id)
1136 {
1137     AssertHeapIsIdle(cx);
1138     CHECK_REQUEST(cx);
1139 
1140     if (!JSID_IS_ATOM(id))
1141         return JSProto_Null;
1142 
1143     JSAtom* atom = JSID_TO_ATOM(id);
1144     const JSStdName* stdnm = LookupStdName(cx->names(), atom, standard_class_names);
1145     if (!stdnm)
1146         return JSProto_Null;
1147 
1148     if (GlobalObject::skipDeselectedConstructor(cx, stdnm->key))
1149         return JSProto_Null;
1150 
1151     MOZ_ASSERT(MOZ_ARRAY_LENGTH(standard_class_names) == JSProto_LIMIT + 1);
1152     return static_cast<JSProtoKey>(stdnm - standard_class_names);
1153 }
1154 
1155 JS_PUBLIC_API(JSObject*)
1156 JS_GetObjectPrototype(JSContext* cx, HandleObject forObj)
1157 {
1158     CHECK_REQUEST(cx);
1159     assertSameCompartment(cx, forObj);
1160     return forObj->global().getOrCreateObjectPrototype(cx);
1161 }
1162 
1163 JS_PUBLIC_API(JSObject*)
1164 JS_GetFunctionPrototype(JSContext* cx, HandleObject forObj)
1165 {
1166     CHECK_REQUEST(cx);
1167     assertSameCompartment(cx, forObj);
1168     return forObj->global().getOrCreateFunctionPrototype(cx);
1169 }
1170 
1171 JS_PUBLIC_API(JSObject*)
1172 JS_GetArrayPrototype(JSContext* cx, HandleObject forObj)
1173 {
1174     CHECK_REQUEST(cx);
1175     assertSameCompartment(cx, forObj);
1176     Rooted<GlobalObject*> global(cx, &forObj->global());
1177     return GlobalObject::getOrCreateArrayPrototype(cx, global);
1178 }
1179 
1180 JS_PUBLIC_API(JSObject*)
1181 JS_GetErrorPrototype(JSContext* cx)
1182 {
1183     CHECK_REQUEST(cx);
1184     Rooted<GlobalObject*> global(cx, cx->global());
1185     return GlobalObject::getOrCreateCustomErrorPrototype(cx, global, JSEXN_ERR);
1186 }
1187 
1188 JS_PUBLIC_API(JSObject*)
1189 JS_GetIteratorPrototype(JSContext* cx)
1190 {
1191     CHECK_REQUEST(cx);
1192     Rooted<GlobalObject*> global(cx, cx->global());
1193     return GlobalObject::getOrCreateIteratorPrototype(cx, global);
1194 }
1195 
1196 JS_PUBLIC_API(JSObject*)
1197 JS_GetGlobalForObject(JSContext* cx, JSObject* obj)
1198 {
1199     AssertHeapIsIdle(cx);
1200     assertSameCompartment(cx, obj);
1201     return &obj->global();
1202 }
1203 
1204 extern JS_PUBLIC_API(bool)
1205 JS_IsGlobalObject(JSObject* obj)
1206 {
1207     return obj->is<GlobalObject>();
1208 }
1209 
1210 extern JS_PUBLIC_API(JSObject*)
1211 JS_GlobalLexicalEnvironment(JSObject* obj)
1212 {
1213     return &obj->as<GlobalObject>().lexicalEnvironment();
1214 }
1215 
1216 extern JS_PUBLIC_API(bool)
1217 JS_HasExtensibleLexicalEnvironment(JSObject* obj)
1218 {
1219     return obj->is<GlobalObject>() || obj->compartment()->getNonSyntacticLexicalEnvironment(obj);
1220 }
1221 
1222 extern JS_PUBLIC_API(JSObject*)
1223 JS_ExtensibleLexicalEnvironment(JSObject* obj)
1224 {
1225     JSObject* lexical = nullptr;
1226     if (obj->is<GlobalObject>())
1227         lexical = JS_GlobalLexicalEnvironment(obj);
1228     else
1229         lexical = obj->compartment()->getNonSyntacticLexicalEnvironment(obj);
1230     MOZ_ASSERT(lexical);
1231     return lexical;
1232 }
1233 
1234 JS_PUBLIC_API(JSObject*)
1235 JS_GetGlobalForCompartmentOrNull(JSContext* cx, JSCompartment* c)
1236 {
1237     AssertHeapIsIdleOrIterating(cx);
1238     assertSameCompartment(cx, c);
1239     return c->maybeGlobal();
1240 }
1241 
1242 JS_PUBLIC_API(JSObject*)
1243 JS::CurrentGlobalOrNull(JSContext* cx)
1244 {
1245     AssertHeapIsIdleOrIterating(cx);
1246     CHECK_REQUEST(cx);
1247     if (!cx->compartment())
1248         return nullptr;
1249     return cx->global();
1250 }
1251 
1252 JS_PUBLIC_API(Value)
1253 JS::detail::ComputeThis(JSContext* cx, Value* vp)
1254 {
1255     AssertHeapIsIdle(cx);
1256     assertSameCompartment(cx, JSValueArray(vp, 2));
1257 
1258     MutableHandleValue thisv = MutableHandleValue::fromMarkedLocation(&vp[1]);
1259     if (!BoxNonStrictThis(cx, thisv, thisv))
1260         return NullValue();
1261 
1262     return thisv;
1263 }
1264 
1265 JS_PUBLIC_API(void*)
1266 JS_malloc(JSContext* cx, size_t nbytes)
1267 {
1268     AssertHeapIsIdle(cx);
1269     CHECK_REQUEST(cx);
1270     return static_cast<void*>(cx->runtime()->pod_malloc<uint8_t>(nbytes));
1271 }
1272 
1273 JS_PUBLIC_API(void*)
1274 JS_realloc(JSContext* cx, void* p, size_t oldBytes, size_t newBytes)
1275 {
1276     AssertHeapIsIdle(cx);
1277     CHECK_REQUEST(cx);
1278     return static_cast<void*>(cx->zone()->pod_realloc<uint8_t>(static_cast<uint8_t*>(p), oldBytes,
1279                                                                 newBytes));
1280 }
1281 
1282 JS_PUBLIC_API(void)
1283 JS_free(JSContext* cx, void* p)
1284 {
1285     return js_free(p);
1286 }
1287 
1288 JS_PUBLIC_API(void)
1289 JS_freeop(JSFreeOp* fop, void* p)
1290 {
1291     return FreeOp::get(fop)->free_(p);
1292 }
1293 
1294 JS_PUBLIC_API(void)
1295 JS_updateMallocCounter(JSContext* cx, size_t nbytes)
1296 {
1297     return cx->updateMallocCounter(nbytes);
1298 }
1299 
1300 JS_PUBLIC_API(char*)
1301 JS_strdup(JSContext* cx, const char* s)
1302 {
1303     AssertHeapIsIdle(cx);
1304     return DuplicateString(cx, s).release();
1305 }
1306 
1307 #undef JS_AddRoot
1308 
1309 JS_PUBLIC_API(bool)
1310 JS_AddExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data)
1311 {
1312     return cx->gc.addBlackRootsTracer(traceOp, data);
1313 }
1314 
1315 JS_PUBLIC_API(void)
1316 JS_RemoveExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data)
1317 {
1318     return cx->gc.removeBlackRootsTracer(traceOp, data);
1319 }
1320 
1321 JS_PUBLIC_API(void)
1322 JS_GC(JSContext* cx)
1323 {
1324     AssertHeapIsIdle(cx);
1325     JS::PrepareForFullGC(cx);
1326     cx->gc.gc(GC_NORMAL, JS::gcreason::API);
1327 }
1328 
1329 JS_PUBLIC_API(void)
1330 JS_MaybeGC(JSContext* cx)
1331 {
1332     GCRuntime& gc = cx->runtime()->gc;
1333     gc.maybeGC(cx->zone());
1334 }
1335 
1336 JS_PUBLIC_API(void)
1337 JS_SetGCCallback(JSContext* cx, JSGCCallback cb, void* data)
1338 {
1339     AssertHeapIsIdle(cx);
1340     cx->gc.setGCCallback(cb, data);
1341 }
1342 
1343 JS_PUBLIC_API(void)
1344 JS_SetObjectsTenuredCallback(JSContext* cx, JSObjectsTenuredCallback cb,
1345                              void* data)
1346 {
1347     AssertHeapIsIdle(cx);
1348     cx->gc.setObjectsTenuredCallback(cb, data);
1349 }
1350 
1351 JS_PUBLIC_API(bool)
1352 JS_AddFinalizeCallback(JSContext* cx, JSFinalizeCallback cb, void* data)
1353 {
1354     AssertHeapIsIdle(cx);
1355     return cx->gc.addFinalizeCallback(cb, data);
1356 }
1357 
1358 JS_PUBLIC_API(void)
1359 JS_RemoveFinalizeCallback(JSContext* cx, JSFinalizeCallback cb)
1360 {
1361     cx->gc.removeFinalizeCallback(cb);
1362 }
1363 
1364 JS_PUBLIC_API(bool)
1365 JS_AddWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb, void* data)
1366 {
1367     AssertHeapIsIdle(cx);
1368     return cx->gc.addWeakPointerZoneGroupCallback(cb, data);
1369 }
1370 
1371 JS_PUBLIC_API(void)
1372 JS_RemoveWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb)
1373 {
1374     cx->gc.removeWeakPointerZoneGroupCallback(cb);
1375 }
1376 
1377 JS_PUBLIC_API(bool)
1378 JS_AddWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb,
1379                                      void* data)
1380 {
1381     AssertHeapIsIdle(cx);
1382     return cx->gc.addWeakPointerCompartmentCallback(cb, data);
1383 }
1384 
1385 JS_PUBLIC_API(void)
1386 JS_RemoveWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb)
1387 {
1388     cx->gc.removeWeakPointerCompartmentCallback(cb);
1389 }
1390 
1391 
1392 JS_PUBLIC_API(void)
1393 JS_UpdateWeakPointerAfterGC(JS::Heap<JSObject*>* objp)
1394 {
1395     JS_UpdateWeakPointerAfterGCUnbarriered(objp->unsafeGet());
1396 }
1397 
1398 JS_PUBLIC_API(void)
1399 JS_UpdateWeakPointerAfterGCUnbarriered(JSObject** objp)
1400 {
1401     if (IsAboutToBeFinalizedUnbarriered(objp))
1402         *objp = nullptr;
1403 }
1404 
1405 JS_PUBLIC_API(void)
1406 JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value)
1407 {
1408     cx->gc.waitBackgroundSweepEnd();
1409     AutoLockGC lock(cx);
1410     MOZ_ALWAYS_TRUE(cx->gc.setParameter(key, value, lock));
1411 }
1412 
1413 JS_PUBLIC_API(uint32_t)
1414 JS_GetGCParameter(JSContext* cx, JSGCParamKey key)
1415 {
1416     AutoLockGC lock(cx);
1417     return cx->gc.getParameter(key, lock);
1418 }
1419 
1420 static const size_t NumGCConfigs = 14;
1421 struct JSGCConfig {
1422     JSGCParamKey key;
1423     uint32_t value;
1424 };
1425 
1426 JS_PUBLIC_API(void)
1427 JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx, uint32_t availMem)
1428 {
1429     static const JSGCConfig minimal[NumGCConfigs] = {
1430         {JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
1431         {JSGC_SLICE_TIME_BUDGET, 30},
1432         {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1433         {JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 40},
1434         {JSGC_HIGH_FREQUENCY_LOW_LIMIT, 0},
1435         {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300},
1436         {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 120},
1437         {JSGC_LOW_FREQUENCY_HEAP_GROWTH, 120},
1438         {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1439         {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1440         {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1441         {JSGC_ALLOCATION_THRESHOLD, 1},
1442         {JSGC_MODE, JSGC_MODE_INCREMENTAL}
1443     };
1444 
1445     const JSGCConfig* config = minimal;
1446     if (availMem > 512) {
1447         static const JSGCConfig nominal[NumGCConfigs] = {
1448             {JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
1449             {JSGC_SLICE_TIME_BUDGET, 30},
1450             {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1000},
1451             {JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 500},
1452             {JSGC_HIGH_FREQUENCY_LOW_LIMIT, 100},
1453             {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300},
1454             {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 150},
1455             {JSGC_LOW_FREQUENCY_HEAP_GROWTH, 150},
1456             {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1457             {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1458             {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
1459             {JSGC_ALLOCATION_THRESHOLD, 30},
1460             {JSGC_MODE, JSGC_MODE_ZONE}
1461         };
1462 
1463         config = nominal;
1464     }
1465 
1466     for (size_t i = 0; i < NumGCConfigs; i++)
1467         JS_SetGCParameter(cx, config[i].key, config[i].value);
1468 }
1469 
1470 
1471 JS_PUBLIC_API(JSString*)
1472 JS_NewExternalString(JSContext* cx, const char16_t* chars, size_t length,
1473                      const JSStringFinalizer* fin)
1474 {
1475     AssertHeapIsIdle(cx);
1476     CHECK_REQUEST(cx);
1477     JSString* s = JSExternalString::new_(cx, chars, length, fin);
1478     return s;
1479 }
1480 
1481 extern JS_PUBLIC_API(bool)
1482 JS_IsExternalString(JSString* str)
1483 {
1484     return str->isExternal();
1485 }
1486 
1487 extern JS_PUBLIC_API(const JSStringFinalizer*)
1488 JS_GetExternalStringFinalizer(JSString* str)
1489 {
1490     return str->asExternal().externalFinalizer();
1491 }
1492 
1493 static void
1494 SetNativeStackQuotaAndLimit(JSContext* cx, StackKind kind, size_t stackSize)
1495 {
1496     cx->nativeStackQuota[kind] = stackSize;
1497 
1498 #if JS_STACK_GROWTH_DIRECTION > 0
1499     if (stackSize == 0) {
1500         cx->nativeStackLimit[kind] = UINTPTR_MAX;
1501     } else {
1502         MOZ_ASSERT(cx->nativeStackBase <= size_t(-1) - stackSize);
1503         cx->nativeStackLimit[kind] = cx->nativeStackBase + stackSize - 1;
1504     }
1505 #else
1506     if (stackSize == 0) {
1507         cx->nativeStackLimit[kind] = 0;
1508     } else {
1509         MOZ_ASSERT(cx->nativeStackBase >= stackSize);
1510         cx->nativeStackLimit[kind] = cx->nativeStackBase - (stackSize - 1);
1511     }
1512 #endif
1513 }
1514 
1515 JS_PUBLIC_API(void)
1516 JS_SetNativeStackQuota(JSContext* cx, size_t systemCodeStackSize, size_t trustedScriptStackSize,
1517                        size_t untrustedScriptStackSize)
1518 {
1519     MOZ_ASSERT(cx->requestDepth == 0);
1520 
1521     if (!trustedScriptStackSize)
1522         trustedScriptStackSize = systemCodeStackSize;
1523     else
1524         MOZ_ASSERT(trustedScriptStackSize < systemCodeStackSize);
1525 
1526     if (!untrustedScriptStackSize)
1527         untrustedScriptStackSize = trustedScriptStackSize;
1528     else
1529         MOZ_ASSERT(untrustedScriptStackSize < trustedScriptStackSize);
1530 
1531     SetNativeStackQuotaAndLimit(cx, StackForSystemCode, systemCodeStackSize);
1532     SetNativeStackQuotaAndLimit(cx, StackForTrustedScript, trustedScriptStackSize);
1533     SetNativeStackQuotaAndLimit(cx, StackForUntrustedScript, untrustedScriptStackSize);
1534 
1535     cx->initJitStackLimit();
1536 }
1537 
1538 /************************************************************************/
1539 
1540 JS_PUBLIC_API(bool)
1541 JS_ValueToId(JSContext* cx, HandleValue value, MutableHandleId idp)
1542 {
1543     AssertHeapIsIdle(cx);
1544     CHECK_REQUEST(cx);
1545     assertSameCompartment(cx, value);
1546     return ValueToId<CanGC>(cx, value, idp);
1547 }
1548 
1549 JS_PUBLIC_API(bool)
1550 JS_StringToId(JSContext* cx, HandleString string, MutableHandleId idp)
1551 {
1552     AssertHeapIsIdle(cx);
1553     CHECK_REQUEST(cx);
1554     assertSameCompartment(cx, string);
1555     RootedValue value(cx, StringValue(string));
1556     return ValueToId<CanGC>(cx, value, idp);
1557 }
1558 
1559 JS_PUBLIC_API(bool)
1560 JS_IdToValue(JSContext* cx, jsid id, MutableHandleValue vp)
1561 {
1562     AssertHeapIsIdle(cx);
1563     CHECK_REQUEST(cx);
1564     vp.set(IdToValue(id));
1565     assertSameCompartment(cx, vp);
1566     return true;
1567 }
1568 
1569 JS_PUBLIC_API(bool)
1570 JS::ToPrimitive(JSContext* cx, HandleObject obj, JSType hint, MutableHandleValue vp)
1571 {
1572     AssertHeapIsIdle(cx);
1573     CHECK_REQUEST(cx);
1574     MOZ_ASSERT(obj != nullptr);
1575     MOZ_ASSERT(hint == JSTYPE_VOID || hint == JSTYPE_STRING || hint == JSTYPE_NUMBER);
1576     vp.setObject(*obj);
1577     return ToPrimitiveSlow(cx, hint, vp);
1578 }
1579 
1580 JS_PUBLIC_API(bool)
1581 JS::GetFirstArgumentAsTypeHint(JSContext* cx, CallArgs args, JSType *result)
1582 {
1583     if (!args.get(0).isString()) {
1584         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
1585                                   "Symbol.toPrimitive",
1586                                   "\"string\", \"number\", or \"default\"",
1587                                   InformalValueTypeName(args.get(0)));
1588         return false;
1589     }
1590 
1591     RootedString str(cx, args.get(0).toString());
1592     bool match;
1593 
1594     if (!EqualStrings(cx, str, cx->names().default_, &match))
1595         return false;
1596     if (match) {
1597         *result = JSTYPE_VOID;
1598         return true;
1599     }
1600 
1601     if (!EqualStrings(cx, str, cx->names().string, &match))
1602         return false;
1603     if (match) {
1604         *result = JSTYPE_STRING;
1605         return true;
1606     }
1607 
1608     if (!EqualStrings(cx, str, cx->names().number, &match))
1609         return false;
1610     if (match) {
1611         *result = JSTYPE_NUMBER;
1612         return true;
1613     }
1614 
1615     JSAutoByteString bytes;
1616     const char* source = ValueToSourceForError(cx, args.get(0), bytes);
1617     if (!source) {
1618         ReportOutOfMemory(cx);
1619         return false;
1620     }
1621 
1622     JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
1623                                "Symbol.toPrimitive",
1624                                "\"string\", \"number\", or \"default\"", source);
1625     return false;
1626 }
1627 
1628 JS_PUBLIC_API(bool)
1629 JS_PropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
1630 {
1631     return true;
1632 }
1633 
1634 JS_PUBLIC_API(bool)
1635 JS_StrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
1636                       ObjectOpResult& result)
1637 {
1638     return result.succeed();
1639 }
1640 
1641 JS_PUBLIC_API(JSObject*)
1642 JS_InitClass(JSContext* cx, HandleObject obj, HandleObject parent_proto,
1643              const JSClass* clasp, JSNative constructor, unsigned nargs,
1644              const JSPropertySpec* ps, const JSFunctionSpec* fs,
1645              const JSPropertySpec* static_ps, const JSFunctionSpec* static_fs)
1646 {
1647     AssertHeapIsIdle(cx);
1648     CHECK_REQUEST(cx);
1649     assertSameCompartment(cx, obj, parent_proto);
1650     return InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
1651                      nargs, ps, fs, static_ps, static_fs);
1652 }
1653 
1654 JS_PUBLIC_API(bool)
1655 JS_LinkConstructorAndPrototype(JSContext* cx, HandleObject ctor, HandleObject proto)
1656 {
1657     return LinkConstructorAndPrototype(cx, ctor, proto);
1658 }
1659 
1660 JS_PUBLIC_API(const JSClass*)
1661 JS_GetClass(JSObject* obj)
1662 {
1663     return obj->getJSClass();
1664 }
1665 
1666 JS_PUBLIC_API(bool)
1667 JS_InstanceOf(JSContext* cx, HandleObject obj, const JSClass* clasp, CallArgs* args)
1668 {
1669     AssertHeapIsIdle(cx);
1670     CHECK_REQUEST(cx);
1671 #ifdef DEBUG
1672     if (args) {
1673         assertSameCompartment(cx, obj);
1674         assertSameCompartment(cx, args->thisv(), args->calleev());
1675     }
1676 #endif
1677     if (!obj || obj->getJSClass() != clasp) {
1678         if (args)
1679             ReportIncompatibleMethod(cx, *args, Valueify(clasp));
1680         return false;
1681     }
1682     return true;
1683 }
1684 
1685 JS_PUBLIC_API(bool)
1686 JS_HasInstance(JSContext* cx, HandleObject obj, HandleValue value, bool* bp)
1687 {
1688     AssertHeapIsIdle(cx);
1689     assertSameCompartment(cx, obj, value);
1690     return HasInstance(cx, obj, value, bp);
1691 }
1692 
1693 JS_PUBLIC_API(void*)
1694 JS_GetPrivate(JSObject* obj)
1695 {
1696     /* This function can be called by a finalizer. */
1697     return obj->as<NativeObject>().getPrivate();
1698 }
1699 
1700 JS_PUBLIC_API(void)
1701 JS_SetPrivate(JSObject* obj, void* data)
1702 {
1703     /* This function can be called by a finalizer. */
1704     obj->as<NativeObject>().setPrivate(data);
1705 }
1706 
1707 JS_PUBLIC_API(void*)
1708 JS_GetInstancePrivate(JSContext* cx, HandleObject obj, const JSClass* clasp, CallArgs* args)
1709 {
1710     if (!JS_InstanceOf(cx, obj, clasp, args))
1711         return nullptr;
1712     return obj->as<NativeObject>().getPrivate();
1713 }
1714 
1715 JS_PUBLIC_API(JSObject*)
1716 JS_GetConstructor(JSContext* cx, HandleObject proto)
1717 {
1718     AssertHeapIsIdle(cx);
1719     CHECK_REQUEST(cx);
1720     assertSameCompartment(cx, proto);
1721 
1722     RootedValue cval(cx);
1723     if (!GetProperty(cx, proto, proto, cx->names().constructor, &cval))
1724         return nullptr;
1725     if (!IsFunctionObject(cval)) {
1726         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
1727                                   proto->getClass()->name);
1728         return nullptr;
1729     }
1730     return &cval.toObject();
1731 }
1732 
1733 bool
1734 JS::CompartmentBehaviors::extraWarnings(JSContext* cx) const
1735 {
1736     return extraWarningsOverride_.get(cx->options().extraWarnings());
1737 }
1738 
1739 JS::CompartmentCreationOptions&
1740 JS::CompartmentCreationOptions::setZone(ZoneSpecifier spec)
1741 {
1742     zone_.spec = spec;
1743     return *this;
1744 }
1745 
1746 JS::CompartmentCreationOptions&
1747 JS::CompartmentCreationOptions::setSameZoneAs(JSObject* obj)
1748 {
1749     zone_.pointer = static_cast<void*>(obj->zone());
1750     return *this;
1751 }
1752 
1753 const JS::CompartmentCreationOptions&
1754 JS::CompartmentCreationOptionsRef(JSCompartment* compartment)
1755 {
1756     return compartment->creationOptions();
1757 }
1758 
1759 const JS::CompartmentCreationOptions&
1760 JS::CompartmentCreationOptionsRef(JSObject* obj)
1761 {
1762     return obj->compartment()->creationOptions();
1763 }
1764 
1765 const JS::CompartmentCreationOptions&
1766 JS::CompartmentCreationOptionsRef(JSContext* cx)
1767 {
1768     return cx->compartment()->creationOptions();
1769 }
1770 
1771 bool
1772 JS::CompartmentCreationOptions::getSharedMemoryAndAtomicsEnabled() const
1773 {
1774 #if defined(ENABLE_SHARED_ARRAY_BUFFER)
1775     return sharedMemoryAndAtomics_;
1776 #else
1777     return false;
1778 #endif
1779 }
1780 
1781 JS::CompartmentCreationOptions&
1782 JS::CompartmentCreationOptions::setSharedMemoryAndAtomicsEnabled(bool flag)
1783 {
1784 #if defined(ENABLE_SHARED_ARRAY_BUFFER)
1785     sharedMemoryAndAtomics_ = flag;
1786 #endif
1787     return *this;
1788 }
1789 
1790 JS::CompartmentBehaviors&
1791 JS::CompartmentBehaviorsRef(JSCompartment* compartment)
1792 {
1793     return compartment->behaviors();
1794 }
1795 
1796 JS::CompartmentBehaviors&
1797 JS::CompartmentBehaviorsRef(JSObject* obj)
1798 {
1799     return obj->compartment()->behaviors();
1800 }
1801 
1802 JS::CompartmentBehaviors&
1803 JS::CompartmentBehaviorsRef(JSContext* cx)
1804 {
1805     return cx->compartment()->behaviors();
1806 }
1807 
1808 JS_PUBLIC_API(JSObject*)
1809 JS_NewGlobalObject(JSContext* cx, const JSClass* clasp, JSPrincipals* principals,
1810                    JS::OnNewGlobalHookOption hookOption,
1811                    const JS::CompartmentOptions& options)
1812 {
1813     MOZ_RELEASE_ASSERT(cx->runtime()->hasInitializedSelfHosting(),
1814                        "Must call JS::InitSelfHostedCode() before creating a global");
1815 
1816     AssertHeapIsIdle(cx);
1817     CHECK_REQUEST(cx);
1818 
1819     return GlobalObject::new_(cx, Valueify(clasp), principals, hookOption, options);
1820 }
1821 
1822 JS_PUBLIC_API(void)
1823 JS_GlobalObjectTraceHook(JSTracer* trc, JSObject* global)
1824 {
1825     MOZ_ASSERT(global->is<GlobalObject>());
1826 
1827     // Off thread parsing and compilation tasks create a dummy global which is
1828     // then merged back into the host compartment. Since it used to be a
1829     // global, it will still have this trace hook, but it does not have a
1830     // meaning relative to its new compartment. We can safely skip it.
1831     //
1832     // Similarly, if we GC when creating the global, we may not have set that
1833     // global's compartment's global pointer yet. In this case, the compartment
1834     // will not yet contain anything that needs to be traced.
1835     if (!global->isOwnGlobal(trc))
1836         return;
1837 
1838     // Trace the compartment for any GC things that should only stick around if
1839     // we know the compartment is live.
1840     global->compartment()->trace(trc);
1841 
1842     if (JSTraceOp trace = global->compartment()->creationOptions().getTrace())
1843         trace(trc, global);
1844 }
1845 
1846 JS_PUBLIC_API(void)
1847 JS_FireOnNewGlobalObject(JSContext* cx, JS::HandleObject global)
1848 {
1849     // This hook is infallible, because we don't really want arbitrary script
1850     // to be able to throw errors during delicate global creation routines.
1851     // This infallibility will eat OOM and slow script, but if that happens
1852     // we'll likely run up into them again soon in a fallible context.
1853     Rooted<js::GlobalObject*> globalObject(cx, &global->as<GlobalObject>());
1854     Debugger::onNewGlobalObject(cx, globalObject);
1855 }
1856 
1857 JS_PUBLIC_API(JSObject*)
1858 JS_NewObject(JSContext* cx, const JSClass* jsclasp)
1859 {
1860     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
1861     AssertHeapIsIdle(cx);
1862     CHECK_REQUEST(cx);
1863 
1864     const Class* clasp = Valueify(jsclasp);
1865     if (!clasp)
1866         clasp = &PlainObject::class_;    /* default class is Object */
1867 
1868     MOZ_ASSERT(clasp != &JSFunction::class_);
1869     MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
1870 
1871     return NewObjectWithClassProto(cx, clasp, nullptr);
1872 }
1873 
1874 JS_PUBLIC_API(JSObject*)
1875 JS_NewObjectWithGivenProto(JSContext* cx, const JSClass* jsclasp, HandleObject proto)
1876 {
1877     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
1878     AssertHeapIsIdle(cx);
1879     CHECK_REQUEST(cx);
1880     assertSameCompartment(cx, proto);
1881 
1882     const Class* clasp = Valueify(jsclasp);
1883     if (!clasp)
1884         clasp = &PlainObject::class_;    /* default class is Object */
1885 
1886     MOZ_ASSERT(clasp != &JSFunction::class_);
1887     MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
1888 
1889     return NewObjectWithGivenProto(cx, clasp, proto);
1890 }
1891 
1892 JS_PUBLIC_API(JSObject*)
1893 JS_NewPlainObject(JSContext* cx)
1894 {
1895     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
1896     AssertHeapIsIdle(cx);
1897     CHECK_REQUEST(cx);
1898 
1899     return NewBuiltinClassInstance<PlainObject>(cx);
1900 }
1901 
1902 JS_PUBLIC_API(JSObject*)
1903 JS_NewObjectForConstructor(JSContext* cx, const JSClass* clasp, const CallArgs& args)
1904 {
1905     AssertHeapIsIdle(cx);
1906     CHECK_REQUEST(cx);
1907 
1908     Value callee = args.calleev();
1909     assertSameCompartment(cx, callee);
1910     RootedObject obj(cx, &callee.toObject());
1911     return CreateThis(cx, Valueify(clasp), obj);
1912 }
1913 
1914 JS_PUBLIC_API(bool)
1915 JS_IsNative(JSObject* obj)
1916 {
1917     return obj->isNative();
1918 }
1919 
1920 JS_PUBLIC_API(void)
1921 JS::AssertObjectBelongsToCurrentThread(JSObject* obj)
1922 {
1923     JSRuntime* rt = obj->compartment()->runtimeFromAnyThread();
1924     MOZ_RELEASE_ASSERT(CurrentThreadCanAccessRuntime(rt));
1925 }
1926 
1927 
1928 /*** Standard internal methods *******************************************************************/
1929 
1930 JS_PUBLIC_API(bool)
1931 JS_GetPrototype(JSContext* cx, HandleObject obj, MutableHandleObject result)
1932 {
1933     return GetPrototype(cx, obj, result);
1934 }
1935 
1936 JS_PUBLIC_API(bool)
1937 JS_SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto)
1938 {
1939     AssertHeapIsIdle(cx);
1940     CHECK_REQUEST(cx);
1941     assertSameCompartment(cx, obj, proto);
1942 
1943     return SetPrototype(cx, obj, proto);
1944 }
1945 
1946 JS_PUBLIC_API(bool)
1947 JS_GetPrototypeIfOrdinary(JSContext* cx, HandleObject obj, bool* isOrdinary,
1948                           MutableHandleObject result)
1949 {
1950     return GetPrototypeIfOrdinary(cx, obj, isOrdinary, result);
1951 }
1952 
1953 JS_PUBLIC_API(bool)
1954 JS_IsExtensible(JSContext* cx, HandleObject obj, bool* extensible)
1955 {
1956     return IsExtensible(cx, obj, extensible);
1957 }
1958 
1959 JS_PUBLIC_API(bool)
1960 JS_PreventExtensions(JSContext* cx, JS::HandleObject obj, ObjectOpResult& result)
1961 {
1962     return PreventExtensions(cx, obj, result);
1963 }
1964 
1965 JS_PUBLIC_API(bool)
1966 JS_SetImmutablePrototype(JSContext *cx, JS::HandleObject obj, bool *succeeded)
1967 {
1968     return SetImmutablePrototype(cx, obj, succeeded);
1969 }
1970 
1971 JS_PUBLIC_API(bool)
1972 JS_GetOwnPropertyDescriptorById(JSContext* cx, HandleObject obj, HandleId id,
1973                                 MutableHandle<PropertyDescriptor> desc)
1974 {
1975     AssertHeapIsIdle(cx);
1976     CHECK_REQUEST(cx);
1977 
1978     return GetOwnPropertyDescriptor(cx, obj, id, desc);
1979 }
1980 
1981 JS_PUBLIC_API(bool)
1982 JS_GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, const char* name,
1983                             MutableHandle<PropertyDescriptor> desc)
1984 {
1985     JSAtom* atom = Atomize(cx, name, strlen(name));
1986     if (!atom)
1987         return false;
1988     RootedId id(cx, AtomToId(atom));
1989     return JS_GetOwnPropertyDescriptorById(cx, obj, id, desc);
1990 }
1991 
1992 JS_PUBLIC_API(bool)
1993 JS_GetOwnUCPropertyDescriptor(JSContext* cx, HandleObject obj, const char16_t* name,
1994                               MutableHandle<PropertyDescriptor> desc)
1995 {
1996     JSAtom* atom = AtomizeChars(cx, name, js_strlen(name));
1997     if (!atom)
1998         return false;
1999     RootedId id(cx, AtomToId(atom));
2000     return JS_GetOwnPropertyDescriptorById(cx, obj, id, desc);
2001 }
2002 
2003 JS_PUBLIC_API(bool)
2004 JS_GetPropertyDescriptorById(JSContext* cx, HandleObject obj, HandleId id,
2005                              MutableHandle<PropertyDescriptor> desc)
2006 {
2007     return GetPropertyDescriptor(cx, obj, id, desc);
2008 }
2009 
2010 JS_PUBLIC_API(bool)
2011 JS_GetPropertyDescriptor(JSContext* cx, HandleObject obj, const char* name,
2012                          MutableHandle<PropertyDescriptor> desc)
2013 {
2014     JSAtom* atom = Atomize(cx, name, strlen(name));
2015     if (!atom)
2016         return false;
2017     RootedId id(cx, AtomToId(atom));
2018     return atom && JS_GetPropertyDescriptorById(cx, obj, id, desc);
2019 }
2020 
2021 static bool
2022 DefinePropertyByDescriptor(JSContext* cx, HandleObject obj, HandleId id,
2023                            Handle<PropertyDescriptor> desc, ObjectOpResult& result)
2024 {
2025     AssertHeapIsIdle(cx);
2026     CHECK_REQUEST(cx);
2027     assertSameCompartment(cx, obj, id, desc);
2028     return DefineProperty(cx, obj, id, desc.value(), desc.getter(), desc.setter(),
2029                           desc.attributes(), result);
2030 }
2031 
2032 JS_PUBLIC_API(bool)
2033 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id,
2034                       Handle<PropertyDescriptor> desc, ObjectOpResult& result)
2035 {
2036     return DefinePropertyByDescriptor(cx, obj, id, desc, result);
2037 }
2038 
2039 JS_PUBLIC_API(bool)
2040 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id,
2041                       Handle<PropertyDescriptor> desc)
2042 {
2043     ObjectOpResult result;
2044     return DefinePropertyByDescriptor(cx, obj, id, desc, result) &&
2045            result.checkStrict(cx, obj, id);
2046 }
2047 
2048 static bool
2049 DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
2050                    const JSNativeWrapper& get, const JSNativeWrapper& set,
2051                    unsigned attrs, unsigned flags)
2052 {
2053     JSGetterOp getter = JS_CAST_NATIVE_TO(get.op, JSGetterOp);
2054     JSSetterOp setter = JS_CAST_NATIVE_TO(set.op, JSSetterOp);
2055 
2056     // JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd
2057     // throw if this happens, but we've accepted it for long enough that it's
2058     // not worth trying to make callers change their ways. Just flip it off on
2059     // its way through the API layer so that we can enforce this internally.
2060     if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
2061         attrs &= ~JSPROP_READONLY;
2062 
2063     // When we use DefineProperty, we need full scriptable Function objects rather
2064     // than JSNatives. However, we might be pulling this property descriptor off
2065     // of something with JSNative property descriptors. If we are, wrap them in
2066     // JS Function objects.
2067     //
2068     // But skip doing this if our accessors are the well-known stub
2069     // accessors, since those are known to be JSGetterOps.  Assert
2070     // some sanity about it, though.
2071     MOZ_ASSERT_IF(getter == JS_PropertyStub,
2072                   setter == JS_StrictPropertyStub || (attrs & JSPROP_PROPOP_ACCESSORS));
2073     MOZ_ASSERT_IF(setter == JS_StrictPropertyStub,
2074                   getter == JS_PropertyStub || (attrs & JSPROP_PROPOP_ACCESSORS));
2075 
2076     // If !(attrs & JSPROP_PROPOP_ACCESSORS), then either getter/setter are both
2077     // possibly-null JSNatives (or possibly-null JSFunction* if JSPROP_GETTER or
2078     // JSPROP_SETTER is appropriately set), or both are the well-known property
2079     // stubs.  The subsequent block must handle only the first of these cases,
2080     // so carefully exclude the latter case.
2081     if (!(attrs & JSPROP_PROPOP_ACCESSORS) &&
2082         getter != JS_PropertyStub && setter != JS_StrictPropertyStub)
2083     {
2084         if (getter && !(attrs & JSPROP_GETTER)) {
2085             RootedAtom atom(cx, IdToFunctionName(cx, id, "get"));
2086             if (!atom)
2087                 return false;
2088             JSFunction* getobj = NewNativeFunction(cx, (Native) getter, 0, atom);
2089             if (!getobj)
2090                 return false;
2091 
2092             if (get.info)
2093                 getobj->setJitInfo(get.info);
2094 
2095             getter = JS_DATA_TO_FUNC_PTR(GetterOp, getobj);
2096             attrs |= JSPROP_GETTER;
2097         }
2098         if (setter && !(attrs & JSPROP_SETTER)) {
2099             // Root just the getter, since the setter is not yet a JSObject.
2100             AutoRooterGetterSetter getRoot(cx, JSPROP_GETTER, &getter, nullptr);
2101             RootedAtom atom(cx, IdToFunctionName(cx, id, "set"));
2102             if (!atom)
2103                 return false;
2104             JSFunction* setobj = NewNativeFunction(cx, (Native) setter, 1, atom);
2105             if (!setobj)
2106                 return false;
2107 
2108             if (set.info)
2109                 setobj->setJitInfo(set.info);
2110 
2111             setter = JS_DATA_TO_FUNC_PTR(SetterOp, setobj);
2112             attrs |= JSPROP_SETTER;
2113         }
2114     } else {
2115         attrs &= ~JSPROP_PROPOP_ACCESSORS;
2116     }
2117 
2118     AssertHeapIsIdle(cx);
2119     CHECK_REQUEST(cx);
2120     assertSameCompartment(cx, obj, id, value,
2121                           (attrs & JSPROP_GETTER)
2122                           ? JS_FUNC_TO_DATA_PTR(JSObject*, getter)
2123                           : nullptr,
2124                           (attrs & JSPROP_SETTER)
2125                           ? JS_FUNC_TO_DATA_PTR(JSObject*, setter)
2126                           : nullptr);
2127 
2128     // In most places throughout the engine, a property with null getter and
2129     // not JSPROP_GETTER/SETTER/SHARED has no getter, and the same for setters:
2130     // it's just a plain old data property. However the JS_Define* APIs use
2131     // null getter and setter to mean "default to the Class getProperty and
2132     // setProperty ops".
2133     if (!(attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
2134         if (!getter)
2135             getter = obj->getClass()->getGetProperty();
2136         if (!setter)
2137             setter = obj->getClass()->getSetProperty();
2138     }
2139     if (getter == JS_PropertyStub)
2140         getter = nullptr;
2141     if (setter == JS_StrictPropertyStub)
2142         setter = nullptr;
2143     return DefineProperty(cx, obj, id, value, getter, setter, attrs);
2144 }
2145 
2146 /*
2147  * Wrapper functions to create wrappers with no corresponding JSJitInfo from API
2148  * function arguments.
2149  */
2150 static JSNativeWrapper
2151 NativeOpWrapper(Native native)
2152 {
2153     JSNativeWrapper ret;
2154     ret.op = native;
2155     ret.info = nullptr;
2156     return ret;
2157 }
2158 
2159 JS_PUBLIC_API(bool)
2160 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
2161                       unsigned attrs, Native getter, Native setter)
2162 {
2163     return DefinePropertyById(cx, obj, id, value,
2164                               NativeOpWrapper(getter), NativeOpWrapper(setter),
2165                               attrs, 0);
2166 }
2167 
2168 JS_PUBLIC_API(bool)
2169 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleObject valueArg,
2170                       unsigned attrs, Native getter, Native setter)
2171 {
2172     RootedValue value(cx, ObjectValue(*valueArg));
2173     return DefinePropertyById(cx, obj, id, value,
2174                               NativeOpWrapper(getter), NativeOpWrapper(setter),
2175                               attrs, 0);
2176 }
2177 
2178 JS_PUBLIC_API(bool)
2179 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleString valueArg,
2180                       unsigned attrs, Native getter, Native setter)
2181 {
2182     RootedValue value(cx, StringValue(valueArg));
2183     return DefinePropertyById(cx, obj, id, value,
2184                               NativeOpWrapper(getter), NativeOpWrapper(setter),
2185                               attrs, 0);
2186 }
2187 
2188 JS_PUBLIC_API(bool)
2189 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, int32_t valueArg,
2190                       unsigned attrs, Native getter, Native setter)
2191 {
2192     Value value = Int32Value(valueArg);
2193     return DefinePropertyById(cx, obj, id, HandleValue::fromMarkedLocation(&value),
2194                               NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0);
2195 }
2196 
2197 JS_PUBLIC_API(bool)
2198 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, uint32_t valueArg,
2199                       unsigned attrs, Native getter, Native setter)
2200 {
2201     Value value = NumberValue(valueArg);
2202     return DefinePropertyById(cx, obj, id, HandleValue::fromMarkedLocation(&value),
2203                               NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0);
2204 }
2205 
2206 JS_PUBLIC_API(bool)
2207 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, double valueArg,
2208                       unsigned attrs, Native getter, Native setter)
2209 {
2210     Value value = NumberValue(valueArg);
2211     return DefinePropertyById(cx, obj, id, HandleValue::fromMarkedLocation(&value),
2212                               NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0);
2213 }
2214 
2215 static bool
2216 DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleValue value,
2217                const JSNativeWrapper& getter, const JSNativeWrapper& setter,
2218                unsigned attrs, unsigned flags)
2219 {
2220     AutoRooterGetterSetter gsRoot(cx, attrs, const_cast<JSNative*>(&getter.op),
2221                                   const_cast<JSNative*>(&setter.op));
2222 
2223     JSAtom* atom = Atomize(cx, name, strlen(name));
2224     if (!atom)
2225         return false;
2226     RootedId id(cx, AtomToId(atom));
2227 
2228     return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags);
2229 }
2230 
2231 JS_PUBLIC_API(bool)
2232 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleValue value,
2233                   unsigned attrs,
2234                   Native getter /* = nullptr */, Native setter /* = nullptr */)
2235 {
2236     return DefineProperty(cx, obj, name, value, NativeOpWrapper(getter), NativeOpWrapper(setter),
2237                           attrs, 0);
2238 }
2239 
2240 JS_PUBLIC_API(bool)
2241 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleObject valueArg,
2242                   unsigned attrs,
2243                   Native getter /* = nullptr */, Native setter /* = nullptr */)
2244 {
2245     RootedValue value(cx, ObjectValue(*valueArg));
2246     return DefineProperty(cx, obj, name, value, NativeOpWrapper(getter), NativeOpWrapper(setter),
2247                           attrs, 0);
2248 }
2249 
2250 JS_PUBLIC_API(bool)
2251 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleString valueArg,
2252                   unsigned attrs,
2253                   Native getter /* = nullptr */, Native setter /* = nullptr */)
2254 {
2255     RootedValue value(cx, StringValue(valueArg));
2256     return DefineProperty(cx, obj, name, value, NativeOpWrapper(getter), NativeOpWrapper(setter),
2257                           attrs, 0);
2258 }
2259 
2260 JS_PUBLIC_API(bool)
2261 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, int32_t valueArg,
2262                   unsigned attrs,
2263                   Native getter /* = nullptr */, Native setter /* = nullptr */)
2264 {
2265     Value value = Int32Value(valueArg);
2266     return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value),
2267                           NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0);
2268 }
2269 
2270 JS_PUBLIC_API(bool)
2271 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, uint32_t valueArg,
2272                   unsigned attrs,
2273                   Native getter /* = nullptr */, Native setter /* = nullptr */)
2274 {
2275     Value value = NumberValue(valueArg);
2276     return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value),
2277                           NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0);
2278 }
2279 
2280 JS_PUBLIC_API(bool)
2281 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, double valueArg,
2282                   unsigned attrs,
2283                   Native getter /* = nullptr */, Native setter /* = nullptr */)
2284 {
2285     Value value = NumberValue(valueArg);
2286     return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value),
2287                           NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0);
2288 }
2289 
2290 #define AUTO_NAMELEN(s,n)   (((n) == (size_t)-1) ? js_strlen(s) : (n))
2291 
2292 JS_PUBLIC_API(bool)
2293 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2294                     Handle<PropertyDescriptor> desc,
2295                     ObjectOpResult& result)
2296 {
2297     JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2298     if (!atom)
2299         return false;
2300     RootedId id(cx, AtomToId(atom));
2301     return DefinePropertyByDescriptor(cx, obj, id, desc, result);
2302 }
2303 
2304 JS_PUBLIC_API(bool)
2305 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2306                     Handle<PropertyDescriptor> desc)
2307 {
2308     JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2309     if (!atom)
2310         return false;
2311     RootedId id(cx, AtomToId(atom));
2312     ObjectOpResult result;
2313     return DefinePropertyByDescriptor(cx, obj, id, desc, result) &&
2314            result.checkStrict(cx, obj, id);
2315 }
2316 
2317 static bool
2318 DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2319                  const Value& value_, Native getter, Native setter, unsigned attrs,
2320                  unsigned flags)
2321 {
2322     RootedValue value(cx, value_);
2323     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
2324     JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2325     if (!atom)
2326         return false;
2327     RootedId id(cx, AtomToId(atom));
2328     return DefinePropertyById(cx, obj, id, value, NativeOpWrapper(getter), NativeOpWrapper(setter),
2329                               attrs, flags);
2330 }
2331 
2332 JS_PUBLIC_API(bool)
2333 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2334                     HandleValue value, unsigned attrs, Native getter, Native setter)
2335 {
2336     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0);
2337 }
2338 
2339 JS_PUBLIC_API(bool)
2340 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2341                     HandleObject valueArg, unsigned attrs, Native getter, Native setter)
2342 {
2343     RootedValue value(cx, ObjectValue(*valueArg));
2344     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0);
2345 }
2346 
2347 JS_PUBLIC_API(bool)
2348 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2349                     HandleString valueArg, unsigned attrs, Native getter, Native setter)
2350 {
2351     RootedValue value(cx, StringValue(valueArg));
2352     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0);
2353 }
2354 
2355 JS_PUBLIC_API(bool)
2356 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2357                     int32_t valueArg, unsigned attrs, Native getter, Native setter)
2358 {
2359     Value value = Int32Value(valueArg);
2360     return DefineUCProperty(cx, obj, name, namelen, HandleValue::fromMarkedLocation(&value),
2361                             getter, setter, attrs, 0);
2362 }
2363 
2364 JS_PUBLIC_API(bool)
2365 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2366                     uint32_t valueArg, unsigned attrs, Native getter, Native setter)
2367 {
2368     Value value = NumberValue(valueArg);
2369     return DefineUCProperty(cx, obj, name, namelen, HandleValue::fromMarkedLocation(&value),
2370                             getter, setter, attrs, 0);
2371 }
2372 
2373 JS_PUBLIC_API(bool)
2374 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2375                     double valueArg, unsigned attrs, Native getter, Native setter)
2376 {
2377     Value value = NumberValue(valueArg);
2378     return DefineUCProperty(cx, obj, name, namelen, HandleValue::fromMarkedLocation(&value),
2379                             getter, setter, attrs, 0);
2380 }
2381 
2382 static bool
2383 DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
2384               unsigned attrs, Native getter, Native setter)
2385 {
2386     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
2387     AssertHeapIsIdle(cx);
2388     CHECK_REQUEST(cx);
2389     RootedId id(cx);
2390     if (!IndexToId(cx, index, &id))
2391         return false;
2392     return DefinePropertyById(cx, obj, id, value,
2393                               NativeOpWrapper(getter), NativeOpWrapper(setter),
2394                               attrs, 0);
2395 }
2396 
2397 JS_PUBLIC_API(bool)
2398 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
2399                  unsigned attrs, Native getter, Native setter)
2400 {
2401     return DefineElement(cx, obj, index, value, attrs, getter, setter);
2402 }
2403 
2404 JS_PUBLIC_API(bool)
2405 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleObject valueArg,
2406                  unsigned attrs, Native getter, Native setter)
2407 {
2408     RootedValue value(cx, ObjectValue(*valueArg));
2409     return DefineElement(cx, obj, index, value, attrs, getter, setter);
2410 }
2411 
2412 JS_PUBLIC_API(bool)
2413 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleString valueArg,
2414                  unsigned attrs, Native getter, Native setter)
2415 {
2416     RootedValue value(cx, StringValue(valueArg));
2417     return DefineElement(cx, obj, index, value, attrs, getter, setter);
2418 }
2419 
2420 JS_PUBLIC_API(bool)
2421 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, int32_t valueArg,
2422                  unsigned attrs, Native getter, Native setter)
2423 {
2424     Value value = Int32Value(valueArg);
2425     return DefineElement(cx, obj, index, HandleValue::fromMarkedLocation(&value),
2426                          attrs, getter, setter);
2427 }
2428 
2429 JS_PUBLIC_API(bool)
2430 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, uint32_t valueArg,
2431                  unsigned attrs, Native getter, Native setter)
2432 {
2433     Value value = NumberValue(valueArg);
2434     return DefineElement(cx, obj, index, HandleValue::fromMarkedLocation(&value),
2435                          attrs, getter, setter);
2436 }
2437 
2438 JS_PUBLIC_API(bool)
2439 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, double valueArg,
2440                  unsigned attrs, Native getter, Native setter)
2441 {
2442     Value value = NumberValue(valueArg);
2443     return DefineElement(cx, obj, index, HandleValue::fromMarkedLocation(&value),
2444                          attrs, getter, setter);
2445 }
2446 
2447 JS_PUBLIC_API(bool)
2448 JS_HasPropertyById(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
2449 {
2450     AssertHeapIsIdle(cx);
2451     CHECK_REQUEST(cx);
2452 
2453     return HasProperty(cx, obj, id, foundp);
2454 }
2455 
2456 JS_PUBLIC_API(bool)
2457 JS_HasProperty(JSContext* cx, HandleObject obj, const char* name, bool* foundp)
2458 {
2459     JSAtom* atom = Atomize(cx, name, strlen(name));
2460     if (!atom)
2461         return false;
2462     RootedId id(cx, AtomToId(atom));
2463     return JS_HasPropertyById(cx, obj, id, foundp);
2464 }
2465 
2466 JS_PUBLIC_API(bool)
2467 JS_HasUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, bool* foundp)
2468 {
2469     JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2470     if (!atom)
2471         return false;
2472     RootedId id(cx, AtomToId(atom));
2473     return JS_HasPropertyById(cx, obj, id, foundp);
2474 }
2475 
2476 JS_PUBLIC_API(bool)
2477 JS_HasElement(JSContext* cx, HandleObject obj, uint32_t index, bool* foundp)
2478 {
2479     AssertHeapIsIdle(cx);
2480     CHECK_REQUEST(cx);
2481     RootedId id(cx);
2482     if (!IndexToId(cx, index, &id))
2483         return false;
2484     return JS_HasPropertyById(cx, obj, id, foundp);
2485 }
2486 
2487 JS_PUBLIC_API(bool)
2488 JS_HasOwnPropertyById(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
2489 {
2490     AssertHeapIsIdle(cx);
2491     CHECK_REQUEST(cx);
2492     assertSameCompartment(cx, obj, id);
2493 
2494     return HasOwnProperty(cx, obj, id, foundp);
2495 }
2496 
2497 JS_PUBLIC_API(bool)
2498 JS_HasOwnProperty(JSContext* cx, HandleObject obj, const char* name, bool* foundp)
2499 {
2500     JSAtom* atom = Atomize(cx, name, strlen(name));
2501     if (!atom)
2502         return false;
2503     RootedId id(cx, AtomToId(atom));
2504     return JS_HasOwnPropertyById(cx, obj, id, foundp);
2505 }
2506 
2507 JS_PUBLIC_API(bool)
2508 JS_ForwardGetPropertyTo(JSContext* cx, HandleObject obj, HandleId id, HandleValue receiver,
2509                         MutableHandleValue vp)
2510 {
2511     AssertHeapIsIdle(cx);
2512     CHECK_REQUEST(cx);
2513     assertSameCompartment(cx, obj, id, receiver);
2514 
2515     return GetProperty(cx, obj, receiver, id, vp);
2516 }
2517 
2518 JS_PUBLIC_API(bool)
2519 JS_ForwardGetElementTo(JSContext* cx, HandleObject obj, uint32_t index, HandleObject receiver,
2520                        MutableHandleValue vp)
2521 {
2522     AssertHeapIsIdle(cx);
2523     CHECK_REQUEST(cx);
2524     assertSameCompartment(cx, obj);
2525 
2526     return GetElement(cx, obj, receiver, index, vp);
2527 }
2528 
2529 JS_PUBLIC_API(bool)
2530 JS_GetPropertyById(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
2531 {
2532     RootedValue receiver(cx, ObjectValue(*obj));
2533     return JS_ForwardGetPropertyTo(cx, obj, id, receiver, vp);
2534 }
2535 
2536 JS_PUBLIC_API(bool)
2537 JS_GetProperty(JSContext* cx, HandleObject obj, const char* name, MutableHandleValue vp)
2538 {
2539     JSAtom* atom = Atomize(cx, name, strlen(name));
2540     if (!atom)
2541         return false;
2542     RootedId id(cx, AtomToId(atom));
2543     return JS_GetPropertyById(cx, obj, id, vp);
2544 }
2545 
2546 JS_PUBLIC_API(bool)
2547 JS_GetUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2548                  MutableHandleValue vp)
2549 {
2550     JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2551     if (!atom)
2552         return false;
2553     RootedId id(cx, AtomToId(atom));
2554     return JS_GetPropertyById(cx, obj, id, vp);
2555 }
2556 
2557 JS_PUBLIC_API(bool)
2558 JS_GetElement(JSContext* cx, HandleObject objArg, uint32_t index, MutableHandleValue vp)
2559 {
2560     return JS_ForwardGetElementTo(cx, objArg, index, objArg, vp);
2561 }
2562 
2563 JS_PUBLIC_API(bool)
2564 JS_ForwardSetPropertyTo(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
2565                         HandleValue receiver, ObjectOpResult& result)
2566 {
2567     AssertHeapIsIdle(cx);
2568     CHECK_REQUEST(cx);
2569     assertSameCompartment(cx, obj, id, receiver);
2570 
2571     return SetProperty(cx, obj, id, v, receiver, result);
2572 }
2573 
2574 JS_PUBLIC_API(bool)
2575 JS_SetPropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue v)
2576 {
2577     AssertHeapIsIdle(cx);
2578     CHECK_REQUEST(cx);
2579     assertSameCompartment(cx, obj, id);
2580 
2581     RootedValue receiver(cx, ObjectValue(*obj));
2582     ObjectOpResult ignored;
2583     return SetProperty(cx, obj, id, v, receiver, ignored);
2584 }
2585 
2586 JS_PUBLIC_API(bool)
2587 JS_SetProperty(JSContext* cx, HandleObject obj, const char* name, HandleValue v)
2588 {
2589     JSAtom* atom = Atomize(cx, name, strlen(name));
2590     if (!atom)
2591         return false;
2592     RootedId id(cx, AtomToId(atom));
2593     return JS_SetPropertyById(cx, obj, id, v);
2594 }
2595 
2596 JS_PUBLIC_API(bool)
2597 JS_SetUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2598                  HandleValue v)
2599 {
2600     JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2601     if (!atom)
2602         return false;
2603     RootedId id(cx, AtomToId(atom));
2604     return JS_SetPropertyById(cx, obj, id, v);
2605 }
2606 
2607 static bool
2608 SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue v)
2609 {
2610     AssertHeapIsIdle(cx);
2611     CHECK_REQUEST(cx);
2612     assertSameCompartment(cx, obj, v);
2613 
2614     RootedValue receiver(cx, ObjectValue(*obj));
2615     ObjectOpResult ignored;
2616     return SetElement(cx, obj, index, v, receiver, ignored);
2617 }
2618 
2619 JS_PUBLIC_API(bool)
2620 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue v)
2621 {
2622     return SetElement(cx, obj, index, v);
2623 }
2624 
2625 JS_PUBLIC_API(bool)
2626 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleObject v)
2627 {
2628     RootedValue value(cx, ObjectOrNullValue(v));
2629     return SetElement(cx, obj, index, value);
2630 }
2631 
2632 JS_PUBLIC_API(bool)
2633 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleString v)
2634 {
2635     RootedValue value(cx, StringValue(v));
2636     return SetElement(cx, obj, index, value);
2637 }
2638 
2639 JS_PUBLIC_API(bool)
2640 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, int32_t v)
2641 {
2642     RootedValue value(cx, NumberValue(v));
2643     return SetElement(cx, obj, index, value);
2644 }
2645 
2646 JS_PUBLIC_API(bool)
2647 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, uint32_t v)
2648 {
2649     RootedValue value(cx, NumberValue(v));
2650     return SetElement(cx, obj, index, value);
2651 }
2652 
2653 JS_PUBLIC_API(bool)
2654 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, double v)
2655 {
2656     RootedValue value(cx, NumberValue(v));
2657     return SetElement(cx, obj, index, value);
2658 }
2659 
2660 JS_PUBLIC_API(bool)
2661 JS_DeletePropertyById(JSContext* cx, HandleObject obj, HandleId id, ObjectOpResult& result)
2662 {
2663     AssertHeapIsIdle(cx);
2664     CHECK_REQUEST(cx);
2665     assertSameCompartment(cx, obj, id);
2666 
2667     return DeleteProperty(cx, obj, id, result);
2668 }
2669 
2670 JS_PUBLIC_API(bool)
2671 JS_DeleteProperty(JSContext* cx, HandleObject obj, const char* name, ObjectOpResult& result)
2672 {
2673     CHECK_REQUEST(cx);
2674     assertSameCompartment(cx, obj);
2675 
2676     JSAtom* atom = Atomize(cx, name, strlen(name));
2677     if (!atom)
2678         return false;
2679     RootedId id(cx, AtomToId(atom));
2680     return DeleteProperty(cx, obj, id, result);
2681 }
2682 
2683 JS_PUBLIC_API(bool)
2684 JS_DeleteUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2685                     ObjectOpResult& result)
2686 {
2687     CHECK_REQUEST(cx);
2688     assertSameCompartment(cx, obj);
2689 
2690     JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2691     if (!atom)
2692         return false;
2693     RootedId id(cx, AtomToId(atom));
2694     return DeleteProperty(cx, obj, id, result);
2695 }
2696 
2697 JS_PUBLIC_API(bool)
2698 JS_DeleteElement(JSContext* cx, HandleObject obj, uint32_t index, ObjectOpResult& result)
2699 {
2700     AssertHeapIsIdle(cx);
2701     CHECK_REQUEST(cx);
2702     assertSameCompartment(cx, obj);
2703 
2704     return DeleteElement(cx, obj, index, result);
2705 }
2706 
2707 JS_PUBLIC_API(bool)
2708 JS_DeletePropertyById(JSContext* cx, HandleObject obj, HandleId id)
2709 {
2710     ObjectOpResult ignored;
2711     return JS_DeletePropertyById(cx, obj, id, ignored);
2712 }
2713 
2714 JS_PUBLIC_API(bool)
2715 JS_DeleteProperty(JSContext* cx, HandleObject obj, const char* name)
2716 {
2717     ObjectOpResult ignored;
2718     return JS_DeleteProperty(cx, obj, name, ignored);
2719 }
2720 
2721 JS_PUBLIC_API(bool)
2722 JS_DeleteElement(JSContext* cx, HandleObject obj, uint32_t index)
2723 {
2724     ObjectOpResult ignored;
2725     return JS_DeleteElement(cx, obj, index, ignored);
2726 }
2727 
2728 JS_PUBLIC_API(bool)
2729 JS_Enumerate(JSContext* cx, HandleObject obj, JS::MutableHandle<IdVector> props)
2730 {
2731     AssertHeapIsIdle(cx);
2732     CHECK_REQUEST(cx);
2733     assertSameCompartment(cx, obj);
2734     MOZ_ASSERT(props.empty());
2735 
2736     AutoIdVector ids(cx);
2737     if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY, &ids))
2738         return false;
2739 
2740     return props.append(ids.begin(), ids.end());
2741 }
2742 
2743 JS_PUBLIC_API(bool)
2744 JS::IsCallable(JSObject* obj)
2745 {
2746     return obj->isCallable();
2747 }
2748 
2749 JS_PUBLIC_API(bool)
2750 JS::IsConstructor(JSObject* obj)
2751 {
2752     return obj->isConstructor();
2753 }
2754 
2755 JS_PUBLIC_API(bool)
2756 JS_CallFunctionValue(JSContext* cx, HandleObject obj, HandleValue fval, const HandleValueArray& args,
2757                      MutableHandleValue rval)
2758 {
2759     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
2760     AssertHeapIsIdle(cx);
2761     CHECK_REQUEST(cx);
2762     assertSameCompartment(cx, obj, fval, args);
2763 
2764     InvokeArgs iargs(cx);
2765     if (!FillArgumentsFromArraylike(cx, iargs, args))
2766         return false;
2767 
2768     RootedValue thisv(cx, ObjectOrNullValue(obj));
2769     return Call(cx, fval, thisv, iargs, rval);
2770 }
2771 
2772 JS_PUBLIC_API(bool)
2773 JS_CallFunction(JSContext* cx, HandleObject obj, HandleFunction fun, const HandleValueArray& args,
2774                 MutableHandleValue rval)
2775 {
2776     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
2777     AssertHeapIsIdle(cx);
2778     CHECK_REQUEST(cx);
2779     assertSameCompartment(cx, obj, fun, args);
2780 
2781     InvokeArgs iargs(cx);
2782     if (!FillArgumentsFromArraylike(cx, iargs, args))
2783         return false;
2784 
2785     RootedValue fval(cx, ObjectValue(*fun));
2786     RootedValue thisv(cx, ObjectOrNullValue(obj));
2787     return Call(cx, fval, thisv, iargs, rval);
2788 }
2789 
2790 JS_PUBLIC_API(bool)
2791 JS_CallFunctionName(JSContext* cx, HandleObject obj, const char* name, const HandleValueArray& args,
2792                     MutableHandleValue rval)
2793 {
2794     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
2795     AssertHeapIsIdle(cx);
2796     CHECK_REQUEST(cx);
2797     assertSameCompartment(cx, obj, args);
2798 
2799     JSAtom* atom = Atomize(cx, name, strlen(name));
2800     if (!atom)
2801         return false;
2802 
2803     RootedValue fval(cx);
2804     RootedId id(cx, AtomToId(atom));
2805     if (!GetProperty(cx, obj, obj, id, &fval))
2806         return false;
2807 
2808     InvokeArgs iargs(cx);
2809     if (!FillArgumentsFromArraylike(cx, iargs, args))
2810         return false;
2811 
2812     RootedValue thisv(cx, ObjectOrNullValue(obj));
2813     return Call(cx, fval, thisv, iargs, rval);
2814 }
2815 
2816 JS_PUBLIC_API(bool)
2817 JS::Call(JSContext* cx, HandleValue thisv, HandleValue fval, const JS::HandleValueArray& args,
2818          MutableHandleValue rval)
2819 {
2820     AssertHeapIsIdle(cx);
2821     CHECK_REQUEST(cx);
2822     assertSameCompartment(cx, thisv, fval, args);
2823 
2824     InvokeArgs iargs(cx);
2825     if (!FillArgumentsFromArraylike(cx, iargs, args))
2826         return false;
2827 
2828     return Call(cx, fval, thisv, iargs, rval);
2829 }
2830 
2831 JS_PUBLIC_API(bool)
2832 JS::Construct(JSContext* cx, HandleValue fval, HandleObject newTarget, const JS::HandleValueArray& args,
2833               MutableHandleObject objp)
2834 {
2835     AssertHeapIsIdle(cx);
2836     CHECK_REQUEST(cx);
2837     assertSameCompartment(cx, fval, newTarget, args);
2838 
2839     if (!IsConstructor(fval)) {
2840         ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, fval, nullptr);
2841         return false;
2842     }
2843 
2844     RootedValue newTargetVal(cx, ObjectValue(*newTarget));
2845     if (!IsConstructor(newTargetVal)) {
2846         ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, newTargetVal, nullptr);
2847         return false;
2848     }
2849 
2850     ConstructArgs cargs(cx);
2851     if (!FillArgumentsFromArraylike(cx, cargs, args))
2852         return false;
2853 
2854     return js::Construct(cx, fval, cargs, newTargetVal, objp);
2855 }
2856 
2857 JS_PUBLIC_API(bool)
2858 JS::Construct(JSContext* cx, HandleValue fval, const JS::HandleValueArray& args,
2859               MutableHandleObject objp)
2860 {
2861     AssertHeapIsIdle(cx);
2862     CHECK_REQUEST(cx);
2863     assertSameCompartment(cx, fval, args);
2864 
2865     if (!IsConstructor(fval)) {
2866         ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, fval, nullptr);
2867         return false;
2868     }
2869 
2870     ConstructArgs cargs(cx);
2871     if (!FillArgumentsFromArraylike(cx, cargs, args))
2872         return false;
2873 
2874     return js::Construct(cx, fval, cargs, fval, objp);
2875 }
2876 
2877 
2878 /* * */
2879 
2880 JS_PUBLIC_API(bool)
2881 JS_AlreadyHasOwnPropertyById(JSContext* cx, HandleObject obj, HandleId id, bool* foundp)
2882 {
2883     AssertHeapIsIdle(cx);
2884     CHECK_REQUEST(cx);
2885     assertSameCompartment(cx, obj, id);
2886 
2887     if (!obj->isNative())
2888         return js::HasOwnProperty(cx, obj, id, foundp);
2889 
2890     RootedNativeObject nativeObj(cx, &obj->as<NativeObject>());
2891     RootedShape prop(cx);
2892     NativeLookupOwnPropertyNoResolve(cx, nativeObj, id, &prop);
2893     *foundp = !!prop;
2894     return true;
2895 }
2896 
2897 JS_PUBLIC_API(bool)
2898 JS_AlreadyHasOwnProperty(JSContext* cx, HandleObject obj, const char* name, bool* foundp)
2899 {
2900     JSAtom* atom = Atomize(cx, name, strlen(name));
2901     if (!atom)
2902         return false;
2903     RootedId id(cx, AtomToId(atom));
2904     return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
2905 }
2906 
2907 JS_PUBLIC_API(bool)
2908 JS_AlreadyHasOwnUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
2909                            bool* foundp)
2910 {
2911     JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
2912     if (!atom)
2913         return false;
2914     RootedId id(cx, AtomToId(atom));
2915     return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
2916 }
2917 
2918 JS_PUBLIC_API(bool)
2919 JS_AlreadyHasOwnElement(JSContext* cx, HandleObject obj, uint32_t index, bool* foundp)
2920 {
2921     AssertHeapIsIdle(cx);
2922     CHECK_REQUEST(cx);
2923     RootedId id(cx);
2924     if (!IndexToId(cx, index, &id))
2925         return false;
2926     return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
2927 }
2928 
2929 JS_PUBLIC_API(bool)
2930 JS_FreezeObject(JSContext* cx, HandleObject obj)
2931 {
2932     AssertHeapIsIdle(cx);
2933     CHECK_REQUEST(cx);
2934     assertSameCompartment(cx, obj);
2935     return FreezeObject(cx, obj);
2936 }
2937 
2938 static bool
2939 DeepFreezeSlot(JSContext* cx, const Value& v)
2940 {
2941     if (v.isPrimitive())
2942         return true;
2943     RootedObject obj(cx, &v.toObject());
2944     return JS_DeepFreezeObject(cx, obj);
2945 }
2946 
2947 JS_PUBLIC_API(bool)
2948 JS_DeepFreezeObject(JSContext* cx, HandleObject obj)
2949 {
2950     AssertHeapIsIdle(cx);
2951     CHECK_REQUEST(cx);
2952     assertSameCompartment(cx, obj);
2953 
2954     /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
2955     bool extensible;
2956     if (!IsExtensible(cx, obj, &extensible))
2957         return false;
2958     if (!extensible)
2959         return true;
2960 
2961     if (!FreezeObject(cx, obj))
2962         return false;
2963 
2964     /* Walk slots in obj and if any value is a non-null object, seal it. */
2965     if (obj->isNative()) {
2966         RootedNativeObject nobj(cx, &obj->as<NativeObject>());
2967         for (uint32_t i = 0, n = nobj->slotSpan(); i < n; ++i) {
2968             if (!DeepFreezeSlot(cx, nobj->getSlot(i)))
2969                 return false;
2970         }
2971         for (uint32_t i = 0, n = nobj->getDenseInitializedLength(); i < n; ++i) {
2972             if (!DeepFreezeSlot(cx, nobj->getDenseElement(i)))
2973                 return false;
2974         }
2975     }
2976 
2977     return true;
2978 }
2979 
2980 static bool
2981 DefineSelfHostedProperty(JSContext* cx, HandleObject obj, HandleId id,
2982                          const char* getterName, const char* setterName,
2983                          unsigned attrs, unsigned flags)
2984 {
2985     JSAtom* getterNameAtom = Atomize(cx, getterName, strlen(getterName));
2986     if (!getterNameAtom)
2987         return false;
2988     RootedPropertyName getterNameName(cx, getterNameAtom->asPropertyName());
2989 
2990     RootedAtom name(cx, IdToFunctionName(cx, id));
2991     if (!name)
2992         return false;
2993 
2994     RootedValue getterValue(cx);
2995     if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), getterNameName, name, 0,
2996                                              &getterValue))
2997     {
2998         return false;
2999     }
3000     MOZ_ASSERT(getterValue.isObject() && getterValue.toObject().is<JSFunction>());
3001     RootedFunction getterFunc(cx, &getterValue.toObject().as<JSFunction>());
3002     JSNative getterOp = JS_DATA_TO_FUNC_PTR(JSNative, getterFunc.get());
3003 
3004     RootedFunction setterFunc(cx);
3005     if (setterName) {
3006         JSAtom* setterNameAtom = Atomize(cx, setterName, strlen(setterName));
3007         if (!setterNameAtom)
3008             return false;
3009         RootedPropertyName setterNameName(cx, setterNameAtom->asPropertyName());
3010 
3011         RootedValue setterValue(cx);
3012         if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), setterNameName, name, 0,
3013                                                  &setterValue))
3014         {
3015             return false;
3016         }
3017         MOZ_ASSERT(setterValue.isObject() && setterValue.toObject().is<JSFunction>());
3018         setterFunc = &setterValue.toObject().as<JSFunction>();
3019     }
3020     JSNative setterOp = JS_DATA_TO_FUNC_PTR(JSNative, setterFunc.get());
3021 
3022     return DefinePropertyById(cx, obj, id, JS::UndefinedHandleValue,
3023                               NativeOpWrapper(getterOp), NativeOpWrapper(setterOp),
3024                               attrs, flags);
3025 }
3026 
3027 JS_PUBLIC_API(JSObject*)
3028 JS_DefineObject(JSContext* cx, HandleObject obj, const char* name, const JSClass* jsclasp,
3029                 unsigned attrs)
3030 {
3031     AssertHeapIsIdle(cx);
3032     CHECK_REQUEST(cx);
3033     assertSameCompartment(cx, obj);
3034 
3035     const Class* clasp = Valueify(jsclasp);
3036     if (!clasp)
3037         clasp = &PlainObject::class_;    /* default class is Object */
3038 
3039     RootedObject nobj(cx, NewObjectWithClassProto(cx, clasp, nullptr));
3040     if (!nobj)
3041         return nullptr;
3042 
3043     RootedValue nobjValue(cx, ObjectValue(*nobj));
3044     if (!DefineProperty(cx, obj, name, nobjValue, NativeOpWrapper(nullptr), NativeOpWrapper(nullptr),
3045                         attrs, 0)) {
3046         return nullptr;
3047     }
3048 
3049     return nobj;
3050 }
3051 
3052 static inline Value
3053 ValueFromScalar(double x)
3054 {
3055     return DoubleValue(x);
3056 }
3057 static inline Value
3058 ValueFromScalar(int32_t x)
3059 {
3060     return Int32Value(x);
3061 }
3062 
3063 template<typename T>
3064 static bool
3065 DefineConstScalar(JSContext* cx, HandleObject obj, const JSConstScalarSpec<T>* cds)
3066 {
3067     AssertHeapIsIdle(cx);
3068     CHECK_REQUEST(cx);
3069     JSNativeWrapper noget = NativeOpWrapper(nullptr);
3070     JSNativeWrapper noset = NativeOpWrapper(nullptr);
3071     unsigned attrs = JSPROP_READONLY | JSPROP_PERMANENT;
3072     for (; cds->name; cds++) {
3073         RootedValue value(cx, ValueFromScalar(cds->val));
3074         if (!DefineProperty(cx, obj, cds->name, value, noget, noset, attrs, 0))
3075             return false;
3076     }
3077     return true;
3078 }
3079 
3080 JS_PUBLIC_API(bool)
3081 JS_DefineConstDoubles(JSContext* cx, HandleObject obj, const JSConstDoubleSpec* cds)
3082 {
3083     return DefineConstScalar(cx, obj, cds);
3084 }
3085 JS_PUBLIC_API(bool)
3086 JS_DefineConstIntegers(JSContext* cx, HandleObject obj, const JSConstIntegerSpec* cis)
3087 {
3088     return DefineConstScalar(cx, obj, cis);
3089 }
3090 
3091 JS_PUBLIC_API(bool)
3092 JSPropertySpec::getValue(JSContext* cx, MutableHandleValue vp) const
3093 {
3094     MOZ_ASSERT(!isAccessor());
3095 
3096     if (value.type == JSVAL_TYPE_STRING) {
3097         RootedAtom atom(cx, Atomize(cx, value.string, strlen(value.string)));
3098         if (!atom)
3099             return false;
3100         vp.setString(atom);
3101     } else {
3102         MOZ_ASSERT(value.type == JSVAL_TYPE_INT32);
3103         vp.setInt32(value.int32);
3104     }
3105 
3106     return true;
3107 }
3108 
3109 static JS::SymbolCode
3110 PropertySpecNameToSymbolCode(const char* name)
3111 {
3112     MOZ_ASSERT(JS::PropertySpecNameIsSymbol(name));
3113     uintptr_t u = reinterpret_cast<uintptr_t>(name);
3114     return JS::SymbolCode(u - 1);
3115 }
3116 
3117 bool
3118 PropertySpecNameToId(JSContext* cx, const char* name, MutableHandleId id,
3119                      js::PinningBehavior pin = js::DoNotPinAtom)
3120 {
3121     if (JS::PropertySpecNameIsSymbol(name)) {
3122         JS::SymbolCode which = PropertySpecNameToSymbolCode(name);
3123         id.set(SYMBOL_TO_JSID(cx->wellKnownSymbols().get(which)));
3124     } else {
3125         JSAtom* atom = Atomize(cx, name, strlen(name), pin);
3126         if (!atom)
3127             return false;
3128         id.set(AtomToId(atom));
3129     }
3130     return true;
3131 }
3132 
3133 JS_PUBLIC_API(bool)
3134 JS::PropertySpecNameToPermanentId(JSContext* cx, const char* name, jsid* idp)
3135 {
3136     // We are calling fromMarkedLocation(idp) even though idp points to a
3137     // location that will never be marked. This is OK because the whole point
3138     // of this API is to populate *idp with a jsid that does not need to be
3139     // marked.
3140     return PropertySpecNameToId(cx, name, MutableHandleId::fromMarkedLocation(idp),
3141                                 js::PinAtom);
3142 }
3143 
3144 JS_PUBLIC_API(bool)
3145 JS_DefineProperties(JSContext* cx, HandleObject obj, const JSPropertySpec* ps)
3146 {
3147     RootedId id(cx);
3148 
3149     for (; ps->name; ps++) {
3150         if (!PropertySpecNameToId(cx, ps->name, &id))
3151             return false;
3152 
3153         if (ps->isAccessor()) {
3154             if (ps->isSelfHosted()) {
3155                 if (!DefineSelfHostedProperty(cx, obj, id,
3156                                               ps->accessors.getter.selfHosted.funname,
3157                                               ps->accessors.setter.selfHosted.funname,
3158                                               ps->flags, 0))
3159                 {
3160                     return false;
3161                 }
3162             } else {
3163                 if (!DefinePropertyById(cx, obj, id, JS::UndefinedHandleValue,
3164                                         ps->accessors.getter.native, ps->accessors.setter.native,
3165                                         ps->flags, 0))
3166                 {
3167                     return false;
3168                 }
3169             }
3170         } else {
3171             RootedValue v(cx);
3172             if (!ps->getValue(cx, &v))
3173                 return false;
3174 
3175             if (!DefinePropertyById(cx, obj, id, v, NativeOpWrapper(nullptr),
3176                                     NativeOpWrapper(nullptr), ps->flags & ~JSPROP_INTERNAL_USE_BIT, 0))
3177             {
3178                 return false;
3179             }
3180         }
3181     }
3182     return true;
3183 }
3184 
3185 JS_PUBLIC_API(bool)
3186 JS::ObjectToCompletePropertyDescriptor(JSContext* cx,
3187                                        HandleObject obj,
3188                                        HandleValue descObj,
3189                                        MutableHandle<PropertyDescriptor> desc)
3190 {
3191     if (!ToPropertyDescriptor(cx, descObj, true, desc))
3192         return false;
3193     CompletePropertyDescriptor(desc);
3194     desc.object().set(obj);
3195     return true;
3196 }
3197 
3198 JS_PUBLIC_API(void)
3199 JS_SetAllNonReservedSlotsToUndefined(JSContext* cx, JSObject* objArg)
3200 {
3201     RootedObject obj(cx, objArg);
3202     AssertHeapIsIdle(cx);
3203     CHECK_REQUEST(cx);
3204     assertSameCompartment(cx, obj);
3205 
3206     if (!obj->isNative())
3207         return;
3208 
3209     const Class* clasp = obj->getClass();
3210     unsigned numReserved = JSCLASS_RESERVED_SLOTS(clasp);
3211     unsigned numSlots = obj->as<NativeObject>().slotSpan();
3212     for (unsigned i = numReserved; i < numSlots; i++)
3213         obj->as<NativeObject>().setSlot(i, UndefinedValue());
3214 }
3215 
3216 JS_PUBLIC_API(Value)
3217 JS_GetReservedSlot(JSObject* obj, uint32_t index)
3218 {
3219     return obj->as<NativeObject>().getReservedSlot(index);
3220 }
3221 
3222 JS_PUBLIC_API(void)
3223 JS_SetReservedSlot(JSObject* obj, uint32_t index, const Value& value)
3224 {
3225     obj->as<NativeObject>().setReservedSlot(index, value);
3226 }
3227 
3228 JS_PUBLIC_API(JSObject*)
3229 JS_NewArrayObject(JSContext* cx, const JS::HandleValueArray& contents)
3230 {
3231     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
3232     AssertHeapIsIdle(cx);
3233     CHECK_REQUEST(cx);
3234 
3235     assertSameCompartment(cx, contents);
3236     return NewDenseCopiedArray(cx, contents.length(), contents.begin());
3237 }
3238 
3239 JS_PUBLIC_API(JSObject*)
3240 JS_NewArrayObject(JSContext* cx, size_t length)
3241 {
3242     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
3243     AssertHeapIsIdle(cx);
3244     CHECK_REQUEST(cx);
3245 
3246     return NewDenseFullyAllocatedArray(cx, length);
3247 }
3248 
3249 inline bool
3250 IsGivenTypeObject(JSContext* cx, JS::HandleObject obj, const ESClass& typeClass, bool* isType)
3251 {
3252     assertSameCompartment(cx, obj);
3253 
3254     ESClass cls;
3255     if (!GetBuiltinClass(cx, obj, &cls))
3256         return false;
3257 
3258     *isType = cls == typeClass;
3259     return true;
3260 }
3261 
3262 JS_PUBLIC_API(bool)
3263 JS_IsArrayObject(JSContext* cx, JS::HandleObject obj, bool* isArray)
3264 {
3265     return IsGivenTypeObject(cx, obj, ESClass::Array, isArray);
3266 }
3267 
3268 JS_PUBLIC_API(bool)
3269 JS_IsArrayObject(JSContext* cx, JS::HandleValue value, bool* isArray)
3270 {
3271     if (!value.isObject()) {
3272         *isArray = false;
3273         return true;
3274     }
3275 
3276     RootedObject obj(cx, &value.toObject());
3277     return JS_IsArrayObject(cx, obj, isArray);
3278 }
3279 
3280 JS_PUBLIC_API(bool)
3281 JS_GetArrayLength(JSContext* cx, HandleObject obj, uint32_t* lengthp)
3282 {
3283     AssertHeapIsIdle(cx);
3284     CHECK_REQUEST(cx);
3285     assertSameCompartment(cx, obj);
3286     return GetLengthProperty(cx, obj, lengthp);
3287 }
3288 
3289 JS_PUBLIC_API(bool)
3290 JS_SetArrayLength(JSContext* cx, HandleObject obj, uint32_t length)
3291 {
3292     AssertHeapIsIdle(cx);
3293     CHECK_REQUEST(cx);
3294     assertSameCompartment(cx, obj);
3295     return SetLengthProperty(cx, obj, length);
3296 }
3297 
3298 JS_PUBLIC_API(bool)
3299 JS::IsMapObject(JSContext* cx, JS::HandleObject obj, bool* isMap)
3300 {
3301     return IsGivenTypeObject(cx, obj, ESClass::Map, isMap);
3302 }
3303 
3304 JS_PUBLIC_API(bool)
3305 JS::IsSetObject(JSContext* cx, JS::HandleObject obj, bool* isSet)
3306 {
3307     return IsGivenTypeObject(cx, obj, ESClass::Set, isSet);
3308 }
3309 
3310 JS_PUBLIC_API(void)
3311 JS_HoldPrincipals(JSPrincipals* principals)
3312 {
3313     ++principals->refcount;
3314 }
3315 
3316 JS_PUBLIC_API(void)
3317 JS_DropPrincipals(JSContext* cx, JSPrincipals* principals)
3318 {
3319     int rc = --principals->refcount;
3320     if (rc == 0)
3321         cx->destroyPrincipals(principals);
3322 }
3323 
3324 JS_PUBLIC_API(void)
3325 JS_SetSecurityCallbacks(JSContext* cx, const JSSecurityCallbacks* scb)
3326 {
3327     MOZ_ASSERT(scb != &NullSecurityCallbacks);
3328     cx->securityCallbacks = scb ? scb : &NullSecurityCallbacks;
3329 }
3330 
3331 JS_PUBLIC_API(const JSSecurityCallbacks*)
3332 JS_GetSecurityCallbacks(JSContext* cx)
3333 {
3334     return (cx->securityCallbacks != &NullSecurityCallbacks) ? cx->securityCallbacks : nullptr;
3335 }
3336 
3337 JS_PUBLIC_API(void)
3338 JS_SetTrustedPrincipals(JSContext* cx, JSPrincipals* prin)
3339 {
3340     cx->setTrustedPrincipals(prin);
3341 }
3342 
3343 extern JS_PUBLIC_API(void)
3344 JS_InitDestroyPrincipalsCallback(JSContext* cx, JSDestroyPrincipalsOp destroyPrincipals)
3345 {
3346     MOZ_ASSERT(destroyPrincipals);
3347     MOZ_ASSERT(!cx->destroyPrincipals);
3348     cx->destroyPrincipals = destroyPrincipals;
3349 }
3350 
3351 extern JS_PUBLIC_API(void)
3352 JS_InitReadPrincipalsCallback(JSContext* cx, JSReadPrincipalsOp read)
3353 {
3354     MOZ_ASSERT(read);
3355     MOZ_ASSERT(!cx->readPrincipals);
3356     cx->readPrincipals = read;
3357 }
3358 
3359 JS_PUBLIC_API(JSFunction*)
3360 JS_NewFunction(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
3361                const char* name)
3362 {
3363     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
3364 
3365     AssertHeapIsIdle(cx);
3366     CHECK_REQUEST(cx);
3367 
3368     RootedAtom atom(cx);
3369     if (name) {
3370         atom = Atomize(cx, name, strlen(name));
3371         if (!atom)
3372             return nullptr;
3373     }
3374 
3375     return (flags & JSFUN_CONSTRUCTOR)
3376            ? NewNativeConstructor(cx, native, nargs, atom)
3377            : NewNativeFunction(cx, native, nargs, atom);
3378 }
3379 
3380 JS_PUBLIC_API(JSFunction*)
3381 JS::GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id, unsigned nargs)
3382 {
3383     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
3384     AssertHeapIsIdle(cx);
3385     CHECK_REQUEST(cx);
3386 
3387     RootedAtom name(cx, IdToFunctionName(cx, id));
3388     if (!name)
3389         return nullptr;
3390 
3391     JSAtom* shAtom = Atomize(cx, selfHostedName, strlen(selfHostedName));
3392     if (!shAtom)
3393         return nullptr;
3394     RootedPropertyName shName(cx, shAtom->asPropertyName());
3395     RootedValue funVal(cx);
3396     if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), shName, name, nargs, &funVal))
3397         return nullptr;
3398     return &funVal.toObject().as<JSFunction>();
3399 }
3400 
3401 JS_PUBLIC_API(JSFunction*)
3402 JS::NewFunctionFromSpec(JSContext* cx, const JSFunctionSpec* fs, HandleId id)
3403 {
3404     // Delay cloning self-hosted functions until they are called. This is
3405     // achieved by passing DefineFunction a nullptr JSNative which produces an
3406     // interpreted JSFunction where !hasScript. Interpreted call paths then
3407     // call InitializeLazyFunctionScript if !hasScript.
3408     if (fs->selfHostedName) {
3409         MOZ_ASSERT(!fs->call.op);
3410         MOZ_ASSERT(!fs->call.info);
3411 
3412         JSAtom* shAtom = Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName));
3413         if (!shAtom)
3414             return nullptr;
3415         RootedPropertyName shName(cx, shAtom->asPropertyName());
3416         RootedAtom name(cx, IdToFunctionName(cx, id));
3417         if (!name)
3418             return nullptr;
3419         RootedValue funVal(cx);
3420         if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), shName, name, fs->nargs,
3421                                                  &funVal))
3422         {
3423             return nullptr;
3424         }
3425         JSFunction* fun = &funVal.toObject().as<JSFunction>();
3426         if (fs->flags & JSFUN_HAS_REST)
3427             fun->setHasRest();
3428         return fun;
3429     }
3430 
3431     RootedAtom atom(cx, IdToFunctionName(cx, id));
3432     if (!atom)
3433         return nullptr;
3434 
3435     JSFunction* fun;
3436     if (!fs->call.op)
3437         fun = NewScriptedFunction(cx, fs->nargs, JSFunction::INTERPRETED_LAZY, atom);
3438     else if (fs->flags & JSFUN_CONSTRUCTOR)
3439         fun = NewNativeConstructor(cx, fs->call.op, fs->nargs, atom);
3440     else
3441         fun = NewNativeFunction(cx, fs->call.op, fs->nargs, atom);
3442     if (!fun)
3443         return nullptr;
3444 
3445     if (fs->call.info)
3446         fun->setJitInfo(fs->call.info);
3447     return fun;
3448 }
3449 
3450 static bool
3451 CreateNonSyntacticEnvironmentChain(JSContext* cx, AutoObjectVector& envChain,
3452                                    MutableHandleObject env, MutableHandleScope scope)
3453 {
3454     RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
3455     if (!js::CreateObjectsForEnvironmentChain(cx, envChain, globalLexical, env))
3456         return false;
3457 
3458     if (!envChain.empty()) {
3459         scope.set(GlobalScope::createEmpty(cx, ScopeKind::NonSyntactic));
3460         if (!scope)
3461             return false;
3462 
3463         // The XPConnect subscript loader, which may pass in its own
3464         // environments to load scripts in, expects the environment chain to
3465         // be the holder of "var" declarations. In SpiderMonkey, such objects
3466         // are called "qualified varobjs", the "qualified" part meaning the
3467         // declaration was qualified by "var". There is only sadness.
3468         //
3469         // See JSObject::isQualifiedVarObj.
3470         if (!env->setQualifiedVarObj(cx))
3471             return false;
3472 
3473         // Also get a non-syntactic lexical environment to capture 'let' and
3474         // 'const' bindings. To persist lexical bindings, we have a 1-1
3475         // mapping with the final unwrapped environment object (the
3476         // environment that stores the 'var' bindings) and the lexical
3477         // environment.
3478         //
3479         // TODOshu: disallow the subscript loader from using non-distinguished
3480         // objects as dynamic scopes.
3481         env.set(cx->compartment()->getOrCreateNonSyntacticLexicalEnvironment(cx, env));
3482         if (!env)
3483             return false;
3484     } else {
3485         scope.set(&cx->global()->emptyGlobalScope());
3486     }
3487 
3488     return true;
3489 }
3490 
3491 static bool
3492 IsFunctionCloneable(HandleFunction fun)
3493 {
3494     if (!fun->isInterpreted())
3495         return true;
3496 
3497     // If a function was compiled with non-global syntactic environments on
3498     // the environment chain, we could have baked in EnvironmentCoordinates
3499     // into the script. We cannot clone it without breaking the compiler's
3500     // assumptions.
3501     for (ScopeIter si(fun->nonLazyScript()->enclosingScope()); si; si++) {
3502         if (si.scope()->is<GlobalScope>())
3503             return true;
3504         if (si.hasSyntacticEnvironment())
3505             return false;
3506     }
3507 
3508     return true;
3509 }
3510 
3511 static JSObject*
3512 CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject env, HandleScope scope)
3513 {
3514     AssertHeapIsIdle(cx);
3515     CHECK_REQUEST(cx);
3516     assertSameCompartment(cx, env);
3517     MOZ_ASSERT(env);
3518     // Note that funobj can be in a different compartment.
3519 
3520     if (!funobj->is<JSFunction>()) {
3521         AutoCompartment ac(cx, funobj);
3522         RootedValue v(cx, ObjectValue(*funobj));
3523         ReportIsNotFunction(cx, v);
3524         return nullptr;
3525     }
3526 
3527     RootedFunction fun(cx, &funobj->as<JSFunction>());
3528     if (fun->isInterpretedLazy()) {
3529         AutoCompartment ac(cx, funobj);
3530         if (!fun->getOrCreateScript(cx))
3531             return nullptr;
3532     }
3533 
3534     if (!IsFunctionCloneable(fun)) {
3535         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
3536         return nullptr;
3537     }
3538 
3539     if (fun->isBoundFunction()) {
3540         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
3541         return nullptr;
3542     }
3543 
3544     if (IsAsmJSModule(fun)) {
3545         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
3546         return nullptr;
3547     }
3548 
3549     if (IsWrappedAsyncFunction(fun)) {
3550         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
3551         return nullptr;
3552     }
3553 
3554     if (CanReuseScriptForClone(cx->compartment(), fun, env)) {
3555         // If the script is to be reused, either the script can already handle
3556         // non-syntactic scopes, or there is only the standard global lexical
3557         // scope.
3558 #ifdef DEBUG
3559         // Fail here if we OOM during debug asserting.
3560         // CloneFunctionReuseScript will delazify the script anyways, so we
3561         // are not creating an extra failure condition for DEBUG builds.
3562         if (!fun->getOrCreateScript(cx))
3563             return nullptr;
3564         MOZ_ASSERT(scope->as<GlobalScope>().isSyntactic() ||
3565                    fun->nonLazyScript()->hasNonSyntacticScope());
3566 #endif
3567         return CloneFunctionReuseScript(cx, fun, env, fun->getAllocKind());
3568     }
3569 
3570     JSFunction* clone = CloneFunctionAndScript(cx, fun, env, scope, fun->getAllocKind());
3571 
3572 #ifdef DEBUG
3573     // The cloned function should itself be cloneable.
3574     RootedFunction cloneRoot(cx, clone);
3575     MOZ_ASSERT_IF(cloneRoot, IsFunctionCloneable(cloneRoot));
3576 #endif
3577 
3578     return clone;
3579 }
3580 
3581 JS_PUBLIC_API(JSObject*)
3582 JS::CloneFunctionObject(JSContext* cx, HandleObject funobj)
3583 {
3584     RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
3585     RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
3586     return CloneFunctionObject(cx, funobj, globalLexical, emptyGlobalScope);
3587 }
3588 
3589 extern JS_PUBLIC_API(JSObject*)
3590 JS::CloneFunctionObject(JSContext* cx, HandleObject funobj, AutoObjectVector& envChain)
3591 {
3592     RootedObject env(cx);
3593     RootedScope scope(cx);
3594     if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope))
3595         return nullptr;
3596     return CloneFunctionObject(cx, funobj, env, scope);
3597 }
3598 
3599 JS_PUBLIC_API(JSObject*)
3600 JS_GetFunctionObject(JSFunction* fun)
3601 {
3602     return fun;
3603 }
3604 
3605 JS_PUBLIC_API(JSString*)
3606 JS_GetFunctionId(JSFunction* fun)
3607 {
3608     return fun->name();
3609 }
3610 
3611 JS_PUBLIC_API(JSString*)
3612 JS_GetFunctionDisplayId(JSFunction* fun)
3613 {
3614     return fun->displayAtom();
3615 }
3616 
3617 JS_PUBLIC_API(uint16_t)
3618 JS_GetFunctionArity(JSFunction* fun)
3619 {
3620     return fun->nargs();
3621 }
3622 
3623 JS_PUBLIC_API(bool)
3624 JS_ObjectIsFunction(JSContext* cx, JSObject* obj)
3625 {
3626     return obj->is<JSFunction>();
3627 }
3628 
3629 JS_PUBLIC_API(bool)
3630 JS_IsNativeFunction(JSObject* funobj, JSNative call)
3631 {
3632     if (!funobj->is<JSFunction>())
3633         return false;
3634     JSFunction* fun = &funobj->as<JSFunction>();
3635     return fun->isNative() && fun->native() == call;
3636 }
3637 
3638 extern JS_PUBLIC_API(bool)
3639 JS_IsConstructor(JSFunction* fun)
3640 {
3641     return fun->isConstructor();
3642 }
3643 
3644 JS_PUBLIC_API(bool)
3645 JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs)
3646 {
3647     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
3648     AssertHeapIsIdle(cx);
3649     CHECK_REQUEST(cx);
3650     assertSameCompartment(cx, obj);
3651 
3652     return DefineFunctions(cx, obj, fs, NotIntrinsic);
3653 }
3654 
3655 JS_PUBLIC_API(JSFunction*)
3656 JS_DefineFunction(JSContext* cx, HandleObject obj, const char* name, JSNative call,
3657                   unsigned nargs, unsigned attrs)
3658 {
3659     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
3660     AssertHeapIsIdle(cx);
3661     CHECK_REQUEST(cx);
3662     assertSameCompartment(cx, obj);
3663     JSAtom* atom = Atomize(cx, name, strlen(name));
3664     if (!atom)
3665         return nullptr;
3666     Rooted<jsid> id(cx, AtomToId(atom));
3667     return DefineFunction(cx, obj, id, call, nargs, attrs);
3668 }
3669 
3670 JS_PUBLIC_API(JSFunction*)
3671 JS_DefineUCFunction(JSContext* cx, HandleObject obj,
3672                     const char16_t* name, size_t namelen, JSNative call,
3673                     unsigned nargs, unsigned attrs)
3674 {
3675     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
3676     AssertHeapIsIdle(cx);
3677     CHECK_REQUEST(cx);
3678     assertSameCompartment(cx, obj);
3679     JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
3680     if (!atom)
3681         return nullptr;
3682     Rooted<jsid> id(cx, AtomToId(atom));
3683     return DefineFunction(cx, obj, id, call, nargs, attrs);
3684 }
3685 
3686 extern JS_PUBLIC_API(JSFunction*)
3687 JS_DefineFunctionById(JSContext* cx, HandleObject obj, HandleId id, JSNative call,
3688                       unsigned nargs, unsigned attrs)
3689 {
3690     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
3691     AssertHeapIsIdle(cx);
3692     CHECK_REQUEST(cx);
3693     assertSameCompartment(cx, obj);
3694     return DefineFunction(cx, obj, id, call, nargs, attrs);
3695 }
3696 
3697 /* Use the fastest available getc. */
3698 #if defined(HAVE_GETC_UNLOCKED)
3699 # define fast_getc getc_unlocked
3700 #elif defined(HAVE__GETC_NOLOCK)
3701 # define fast_getc _getc_nolock
3702 #else
3703 # define fast_getc getc
3704 #endif
3705 
3706 typedef Vector<char, 8, TempAllocPolicy> FileContents;
3707 
3708 static bool
3709 ReadCompleteFile(JSContext* cx, FILE* fp, FileContents& buffer)
3710 {
3711     /* Get the complete length of the file, if possible. */
3712     struct stat st;
3713     int ok = fstat(fileno(fp), &st);
3714     if (ok != 0)
3715         return false;
3716     if (st.st_size > 0) {
3717         if (!buffer.reserve(st.st_size))
3718             return false;
3719     }
3720 
3721     // Read in the whole file. Note that we can't assume the data's length
3722     // is actually st.st_size, because 1) some files lie about their size
3723     // (/dev/zero and /dev/random), and 2) reading files in text mode on
3724     // Windows collapses "\r\n" pairs to single \n characters.
3725     for (;;) {
3726         int c = fast_getc(fp);
3727         if (c == EOF)
3728             break;
3729         if (!buffer.append(c))
3730             return false;
3731     }
3732 
3733     return true;
3734 }
3735 
3736 namespace {
3737 
3738 class AutoFile
3739 {
3740     FILE* fp_;
3741   public:
3742     AutoFile()
3743       : fp_(nullptr)
3744     {}
3745     ~AutoFile()
3746     {
3747         if (fp_ && fp_ != stdin)
3748             fclose(fp_);
3749     }
3750     FILE* fp() const { return fp_; }
3751     bool open(JSContext* cx, const char* filename);
3752     bool readAll(JSContext* cx, FileContents& buffer)
3753     {
3754         MOZ_ASSERT(fp_);
3755         return ReadCompleteFile(cx, fp_, buffer);
3756     }
3757 };
3758 
3759 } /* anonymous namespace */
3760 
3761 /*
3762  * Open a source file for reading. Supports "-" and nullptr to mean stdin. The
3763  * return value must be fclosed unless it is stdin.
3764  */
3765 bool
3766 AutoFile::open(JSContext* cx, const char* filename)
3767 {
3768     if (!filename || strcmp(filename, "-") == 0) {
3769         fp_ = stdin;
3770     } else {
3771         fp_ = fopen(filename, "r");
3772         if (!fp_) {
3773             /*
3774              * Use Latin1 variant here because the encoding of filename is
3775              * platform dependent.
3776              */
3777             JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_CANT_OPEN,
3778                                        filename, "No such file or directory");
3779             return false;
3780         }
3781     }
3782     return true;
3783 }
3784 
3785 void
3786 JS::TransitiveCompileOptions::copyPODTransitiveOptions(const TransitiveCompileOptions& rhs)
3787 {
3788     mutedErrors_ = rhs.mutedErrors_;
3789     version = rhs.version;
3790     versionSet = rhs.versionSet;
3791     utf8 = rhs.utf8;
3792     selfHostingMode = rhs.selfHostingMode;
3793     canLazilyParse = rhs.canLazilyParse;
3794     strictOption = rhs.strictOption;
3795     extraWarningsOption = rhs.extraWarningsOption;
3796     werrorOption = rhs.werrorOption;
3797     asmJSOption = rhs.asmJSOption;
3798     throwOnAsmJSValidationFailureOption = rhs.throwOnAsmJSValidationFailureOption;
3799     forceAsync = rhs.forceAsync;
3800     installedFile = rhs.installedFile;
3801     sourceIsLazy = rhs.sourceIsLazy;
3802     introductionType = rhs.introductionType;
3803     introductionLineno = rhs.introductionLineno;
3804     introductionOffset = rhs.introductionOffset;
3805     hasIntroductionInfo = rhs.hasIntroductionInfo;
3806 };
3807 
3808 void
3809 JS::ReadOnlyCompileOptions::copyPODOptions(const ReadOnlyCompileOptions& rhs)
3810 {
3811     copyPODTransitiveOptions(rhs);
3812     lineno = rhs.lineno;
3813     column = rhs.column;
3814     isRunOnce = rhs.isRunOnce;
3815     noScriptRval = rhs.noScriptRval;
3816 }
3817 
3818 JS::OwningCompileOptions::OwningCompileOptions(JSContext* cx)
3819     : ReadOnlyCompileOptions(),
3820       elementRoot(cx),
3821       elementAttributeNameRoot(cx),
3822       introductionScriptRoot(cx)
3823 {
3824 }
3825 
3826 JS::OwningCompileOptions::~OwningCompileOptions()
3827 {
3828     // OwningCompileOptions always owns these, so these casts are okay.
3829     js_free(const_cast<char*>(filename_));
3830     js_free(const_cast<char16_t*>(sourceMapURL_));
3831     js_free(const_cast<char*>(introducerFilename_));
3832 }
3833 
3834 bool
3835 JS::OwningCompileOptions::copy(JSContext* cx, const ReadOnlyCompileOptions& rhs)
3836 {
3837     copyPODOptions(rhs);
3838 
3839     setElement(rhs.element());
3840     setElementAttributeName(rhs.elementAttributeName());
3841     setIntroductionScript(rhs.introductionScript());
3842 
3843     return setFileAndLine(cx, rhs.filename(), rhs.lineno) &&
3844            setSourceMapURL(cx, rhs.sourceMapURL()) &&
3845            setIntroducerFilename(cx, rhs.introducerFilename());
3846 }
3847 
3848 bool
3849 JS::OwningCompileOptions::setFile(JSContext* cx, const char* f)
3850 {
3851     char* copy = nullptr;
3852     if (f) {
3853         copy = JS_strdup(cx, f);
3854         if (!copy)
3855             return false;
3856     }
3857 
3858     // OwningCompileOptions always owns filename_, so this cast is okay.
3859     js_free(const_cast<char*>(filename_));
3860 
3861     filename_ = copy;
3862     return true;
3863 }
3864 
3865 bool
3866 JS::OwningCompileOptions::setFileAndLine(JSContext* cx, const char* f, unsigned l)
3867 {
3868     if (!setFile(cx, f))
3869         return false;
3870 
3871     lineno = l;
3872     return true;
3873 }
3874 
3875 bool
3876 JS::OwningCompileOptions::setSourceMapURL(JSContext* cx, const char16_t* s)
3877 {
3878     UniqueTwoByteChars copy;
3879     if (s) {
3880         copy = DuplicateString(cx, s);
3881         if (!copy)
3882             return false;
3883     }
3884 
3885     // OwningCompileOptions always owns sourceMapURL_, so this cast is okay.
3886     js_free(const_cast<char16_t*>(sourceMapURL_));
3887 
3888     sourceMapURL_ = copy.release();
3889     return true;
3890 }
3891 
3892 bool
3893 JS::OwningCompileOptions::setIntroducerFilename(JSContext* cx, const char* s)
3894 {
3895     char* copy = nullptr;
3896     if (s) {
3897         copy = JS_strdup(cx, s);
3898         if (!copy)
3899             return false;
3900     }
3901 
3902     // OwningCompileOptions always owns introducerFilename_, so this cast is okay.
3903     js_free(const_cast<char*>(introducerFilename_));
3904 
3905     introducerFilename_ = copy;
3906     return true;
3907 }
3908 
3909 JS::CompileOptions::CompileOptions(JSContext* cx, JSVersion version)
3910     : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
3911       introductionScriptRoot(cx)
3912 {
3913     this->version = (version != JSVERSION_UNKNOWN) ? version : cx->findVersion();
3914 
3915     strictOption = cx->options().strictMode();
3916     extraWarningsOption = cx->compartment()->behaviors().extraWarnings(cx);
3917     werrorOption = cx->options().werror();
3918     if (!cx->options().asmJS())
3919         asmJSOption = AsmJSOption::Disabled;
3920     else if (cx->compartment()->debuggerObservesAsmJS())
3921         asmJSOption = AsmJSOption::DisabledByDebugger;
3922     else
3923         asmJSOption = AsmJSOption::Enabled;
3924     throwOnAsmJSValidationFailureOption = cx->options().throwOnAsmJSValidationFailure();
3925 }
3926 
3927 static bool
3928 Compile(JSContext* cx, const ReadOnlyCompileOptions& options, ScopeKind scopeKind,
3929         SourceBufferHolder& srcBuf, MutableHandleScript script)
3930 {
3931     MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic);
3932     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
3933     AssertHeapIsIdle(cx);
3934     CHECK_REQUEST(cx);
3935 
3936     script.set(frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), scopeKind, options, srcBuf));
3937     return !!script;
3938 }
3939 
3940 static bool
3941 Compile(JSContext* cx, const ReadOnlyCompileOptions& options, ScopeKind scopeKind,
3942         const char16_t* chars, size_t length, MutableHandleScript script)
3943 {
3944     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
3945     return ::Compile(cx, options, scopeKind, srcBuf, script);
3946 }
3947 
3948 static bool
3949 Compile(JSContext* cx, const ReadOnlyCompileOptions& options, ScopeKind scopeKind,
3950         const char* bytes, size_t length, MutableHandleScript script)
3951 {
3952     UniqueTwoByteChars chars;
3953     if (options.utf8)
3954         chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get());
3955     else
3956         chars.reset(InflateString(cx, bytes, &length));
3957     if (!chars)
3958         return false;
3959 
3960     return ::Compile(cx, options, scopeKind, chars.get(), length, script);
3961 }
3962 
3963 static bool
3964 Compile(JSContext* cx, const ReadOnlyCompileOptions& options, ScopeKind scopeKind,
3965         FILE* fp, MutableHandleScript script)
3966 {
3967     FileContents buffer(cx);
3968     if (!ReadCompleteFile(cx, fp, buffer))
3969         return false;
3970 
3971     return ::Compile(cx, options, scopeKind, buffer.begin(), buffer.length(), script);
3972 }
3973 
3974 static bool
3975 Compile(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, ScopeKind scopeKind,
3976         const char* filename, MutableHandleScript script)
3977 {
3978     AutoFile file;
3979     if (!file.open(cx, filename))
3980         return false;
3981     CompileOptions options(cx, optionsArg);
3982     options.setFileAndLine(filename, 1);
3983     return ::Compile(cx, options, scopeKind, file.fp(), script);
3984 }
3985 
3986 bool
3987 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
3988             SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
3989 {
3990     return ::Compile(cx, options, ScopeKind::Global, srcBuf, script);
3991 }
3992 
3993 bool
3994 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
3995             const char* bytes, size_t length, JS::MutableHandleScript script)
3996 {
3997     return ::Compile(cx, options, ScopeKind::Global, bytes, length, script);
3998 }
3999 
4000 bool
4001 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4002             const char16_t* chars, size_t length, JS::MutableHandleScript script)
4003 {
4004     return ::Compile(cx, options, ScopeKind::Global, chars, length, script);
4005 }
4006 
4007 bool
4008 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4009             FILE* file, JS::MutableHandleScript script)
4010 {
4011     return ::Compile(cx, options, ScopeKind::Global, file, script);
4012 }
4013 
4014 bool
4015 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
4016             const char* filename, JS::MutableHandleScript script)
4017 {
4018     return ::Compile(cx, options, ScopeKind::Global, filename, script);
4019 }
4020 
4021 bool
4022 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
4023                                 SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
4024 {
4025     return ::Compile(cx, options, ScopeKind::NonSyntactic, srcBuf, script);
4026 }
4027 
4028 bool
4029 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
4030                                 const char* bytes, size_t length, JS::MutableHandleScript script)
4031 {
4032     return ::Compile(cx, options, ScopeKind::NonSyntactic, bytes, length, script);
4033 }
4034 
4035 bool
4036 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
4037                                 const char16_t* chars, size_t length,
4038                                 JS::MutableHandleScript script)
4039 {
4040     return ::Compile(cx, options, ScopeKind::NonSyntactic, chars, length, script);
4041 }
4042 
4043 bool
4044 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
4045                                 FILE* file, JS::MutableHandleScript script)
4046 {
4047     return ::Compile(cx, options, ScopeKind::NonSyntactic, file, script);
4048 }
4049 
4050 bool
4051 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
4052                                 const char* filename, JS::MutableHandleScript script)
4053 {
4054     return ::Compile(cx, options, ScopeKind::NonSyntactic, filename, script);
4055 }
4056 
4057 JS_PUBLIC_API(bool)
4058 JS::CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length)
4059 {
4060     static const size_t TINY_LENGTH = 5 * 1000;
4061     static const size_t HUGE_LENGTH = 100 * 1000;
4062 
4063     // These are heuristics which the caller may choose to ignore (e.g., for
4064     // testing purposes).
4065     if (!options.forceAsync) {
4066         // Compiling off the main thread inolves creating a new Zone and other
4067         // significant overheads.  Don't bother if the script is tiny.
4068         if (length < TINY_LENGTH)
4069             return false;
4070 
4071         // If the parsing task would have to wait for GC to complete, it'll probably
4072         // be faster to just start it synchronously on the main thread unless the
4073         // script is huge.
4074         if (OffThreadParsingMustWaitForGC(cx->runtime()) && length < HUGE_LENGTH)
4075             return false;
4076     }
4077 
4078     return cx->runtime()->canUseParallelParsing() && CanUseExtraThreads();
4079 }
4080 
4081 JS_PUBLIC_API(bool)
4082 JS::CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options,
4083                      const char16_t* chars, size_t length,
4084                      OffThreadCompileCallback callback, void* callbackData)
4085 {
4086     MOZ_ASSERT(CanCompileOffThread(cx, options, length));
4087     return StartOffThreadParseScript(cx, options, chars, length, callback, callbackData);
4088 }
4089 
4090 JS_PUBLIC_API(JSScript*)
4091 JS::FinishOffThreadScript(JSContext* cx, void* token)
4092 {
4093     MOZ_ASSERT(cx);
4094     MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx));
4095     return HelperThreadState().finishScriptParseTask(cx, token);
4096 }
4097 
4098 JS_PUBLIC_API(void)
4099 JS::CancelOffThreadScript(JSContext* cx, void* token)
4100 {
4101     MOZ_ASSERT(cx);
4102     MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx));
4103     HelperThreadState().cancelParseTask(cx, ParseTaskKind::Script, token);
4104 }
4105 
4106 JS_PUBLIC_API(bool)
4107 JS::CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
4108                            const char16_t* chars, size_t length,
4109                            OffThreadCompileCallback callback, void* callbackData)
4110 {
4111     MOZ_ASSERT(CanCompileOffThread(cx, options, length));
4112     return StartOffThreadParseModule(cx, options, chars, length, callback, callbackData);
4113 }
4114 
4115 JS_PUBLIC_API(JSObject*)
4116 JS::FinishOffThreadModule(JSContext* cx, void* token)
4117 {
4118     MOZ_ASSERT(cx);
4119     MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx));
4120     return HelperThreadState().finishModuleParseTask(cx, token);
4121 }
4122 
4123 JS_PUBLIC_API(void)
4124 JS::CancelOffThreadModule(JSContext* cx, void* token)
4125 {
4126     MOZ_ASSERT(cx);
4127     MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx));
4128     HelperThreadState().cancelParseTask(cx, ParseTaskKind::Module, token);
4129 }
4130 
4131 JS_PUBLIC_API(bool)
4132 JS_CompileScript(JSContext* cx, const char* ascii, size_t length,
4133                  const JS::CompileOptions& options, MutableHandleScript script)
4134 {
4135     return Compile(cx, options, ascii, length, script);
4136 }
4137 
4138 JS_PUBLIC_API(bool)
4139 JS_CompileUCScript(JSContext* cx, const char16_t* chars, size_t length,
4140                    const JS::CompileOptions& options, MutableHandleScript script)
4141 {
4142     return Compile(cx, options, chars, length, script);
4143 }
4144 
4145 JS_PUBLIC_API(bool)
4146 JS_BufferIsCompilableUnit(JSContext* cx, HandleObject obj, const char* utf8, size_t length)
4147 {
4148     AssertHeapIsIdle(cx);
4149     CHECK_REQUEST(cx);
4150     assertSameCompartment(cx, obj);
4151 
4152     cx->clearPendingException();
4153 
4154     char16_t* chars = JS::UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(utf8, length), &length).get();
4155     if (!chars)
4156         return true;
4157 
4158     // Return true on any out-of-memory error or non-EOF-related syntax error, so our
4159     // caller doesn't try to collect more buffered source.
4160     bool result = true;
4161 
4162     CompileOptions options(cx);
4163     frontend::UsedNameTracker usedNames(cx);
4164     if (!usedNames.init())
4165         return false;
4166     frontend::Parser<frontend::FullParseHandler> parser(cx, cx->tempLifoAlloc(),
4167                                                         options, chars, length,
4168                                                         /* foldConstants = */ true,
4169                                                         usedNames, nullptr, nullptr);
4170     JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr);
4171     if (!parser.checkOptions() || !parser.parse()) {
4172         // We ran into an error. If it was because we ran out of source, we
4173         // return false so our caller knows to try to collect more buffered
4174         // source.
4175         if (parser.isUnexpectedEOF())
4176             result = false;
4177 
4178         cx->clearPendingException();
4179     }
4180     JS::SetWarningReporter(cx, older);
4181 
4182     js_free(chars);
4183     return result;
4184 }
4185 
4186 JS_PUBLIC_API(JSObject*)
4187 JS_GetGlobalFromScript(JSScript* script)
4188 {
4189     MOZ_ASSERT(!script->isCachedEval());
4190     return &script->global();
4191 }
4192 
4193 JS_PUBLIC_API(const char*)
4194 JS_GetScriptFilename(JSScript* script)
4195 {
4196     // This is called from ThreadStackHelper which can be called from another
4197     // thread or inside a signal hander, so we need to be careful in case a
4198     // copmacting GC is currently moving things around.
4199     return script->maybeForwardedFilename();
4200 }
4201 
4202 JS_PUBLIC_API(unsigned)
4203 JS_GetScriptBaseLineNumber(JSContext* cx, JSScript* script)
4204 {
4205     return script->lineno();
4206 }
4207 
4208 JS_PUBLIC_API(JSScript*)
4209 JS_GetFunctionScript(JSContext* cx, HandleFunction fun)
4210 {
4211     if (fun->isNative())
4212         return nullptr;
4213     if (fun->isInterpretedLazy()) {
4214         AutoCompartment funCompartment(cx, fun);
4215         JSScript* script = fun->getOrCreateScript(cx);
4216         if (!script)
4217             MOZ_CRASH();
4218         return script;
4219     }
4220     return fun->nonLazyScript();
4221 }
4222 
4223 /*
4224  * enclosingScope is a static enclosing scope, if any (e.g. a WithScope).  If
4225  * the enclosing scope is the global scope, this must be null.
4226  *
4227  * enclosingDynamicScope is a dynamic scope to use, if it's not the global.
4228  */
4229 static bool
4230 CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4231                 const char* name, unsigned nargs, const char* const* argnames,
4232                 SourceBufferHolder& srcBuf,
4233                 HandleObject enclosingEnv, HandleScope enclosingScope,
4234                 MutableHandleFunction fun)
4235 {
4236     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
4237     AssertHeapIsIdle(cx);
4238     CHECK_REQUEST(cx);
4239     assertSameCompartment(cx, enclosingEnv);
4240     RootedAtom funAtom(cx);
4241 
4242     if (name) {
4243         funAtom = Atomize(cx, name, strlen(name));
4244         if (!funAtom)
4245             return false;
4246     }
4247 
4248     Rooted<PropertyNameVector> formals(cx, PropertyNameVector(cx));
4249     for (unsigned i = 0; i < nargs; i++) {
4250         RootedAtom argAtom(cx, Atomize(cx, argnames[i], strlen(argnames[i])));
4251         if (!argAtom || !formals.append(argAtom->asPropertyName()))
4252             return false;
4253     }
4254 
4255     fun.set(NewScriptedFunction(cx, 0, JSFunction::INTERPRETED_NORMAL, funAtom,
4256                                 /* proto = */ nullptr,
4257                                 gc::AllocKind::FUNCTION, TenuredObject,
4258                                 enclosingEnv));
4259     if (!fun)
4260         return false;
4261 
4262     // Make sure the static scope chain matches up when we have a
4263     // non-syntactic scope.
4264     MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(enclosingEnv),
4265                   enclosingScope->hasOnChain(ScopeKind::NonSyntactic));
4266 
4267     if (!frontend::CompileFunctionBody(cx, fun, optionsArg, formals, srcBuf, enclosingScope))
4268         return false;
4269 
4270     return true;
4271 }
4272 
4273 JS_PUBLIC_API(bool)
4274 JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
4275                     const ReadOnlyCompileOptions& options,
4276                     const char* name, unsigned nargs, const char* const* argnames,
4277                     SourceBufferHolder& srcBuf, MutableHandleFunction fun)
4278 {
4279     RootedObject env(cx);
4280     RootedScope scope(cx);
4281     if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope))
4282         return false;
4283     return CompileFunction(cx, options, name, nargs, argnames, srcBuf, env, scope, fun);
4284 }
4285 
4286 JS_PUBLIC_API(bool)
4287 JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
4288                     const ReadOnlyCompileOptions& options,
4289                     const char* name, unsigned nargs, const char* const* argnames,
4290                     const char16_t* chars, size_t length, MutableHandleFunction fun)
4291 {
4292     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
4293     return CompileFunction(cx, envChain, options, name, nargs, argnames,
4294                            srcBuf, fun);
4295 }
4296 
4297 JS_PUBLIC_API(bool)
4298 JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
4299                     const ReadOnlyCompileOptions& options,
4300                     const char* name, unsigned nargs, const char* const* argnames,
4301                     const char* bytes, size_t length, MutableHandleFunction fun)
4302 {
4303     UniqueTwoByteChars chars;
4304     if (options.utf8)
4305         chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get());
4306     else
4307         chars.reset(InflateString(cx, bytes, &length));
4308     if (!chars)
4309         return false;
4310 
4311     return CompileFunction(cx, envChain, options, name, nargs, argnames,
4312                            chars.get(), length, fun);
4313 }
4314 
4315 JS_PUBLIC_API(JSString*)
4316 JS_DecompileScript(JSContext* cx, HandleScript script, const char* name, unsigned indent)
4317 {
4318     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
4319 
4320     AssertHeapIsIdle(cx);
4321     CHECK_REQUEST(cx);
4322     script->ensureNonLazyCanonicalFunction(cx);
4323     RootedFunction fun(cx, script->functionNonDelazifying());
4324     if (fun)
4325         return JS_DecompileFunction(cx, fun, indent);
4326     bool haveSource = script->scriptSource()->hasSourceData();
4327     if (!haveSource && !JSScript::loadSource(cx, script->scriptSource(), &haveSource))
4328         return nullptr;
4329     return haveSource ? script->sourceData(cx) : NewStringCopyZ<CanGC>(cx, "[no source]");
4330 }
4331 
4332 JS_PUBLIC_API(JSString*)
4333 JS_DecompileFunction(JSContext* cx, HandleFunction fun, unsigned indent)
4334 {
4335     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
4336     AssertHeapIsIdle(cx);
4337     CHECK_REQUEST(cx);
4338     assertSameCompartment(cx, fun);
4339     return FunctionToString(cx, fun, !(indent & JS_DONT_PRETTY_PRINT));
4340 }
4341 
4342 MOZ_NEVER_INLINE static bool
4343 ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, Value* rval)
4344 {
4345     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
4346     AssertHeapIsIdle(cx);
4347     CHECK_REQUEST(cx);
4348     assertSameCompartment(cx, scope, script);
4349     MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(scope), script->hasNonSyntacticScope());
4350     return Execute(cx, script, *scope, rval);
4351 }
4352 
4353 static bool
4354 ExecuteScript(JSContext* cx, AutoObjectVector& envChain, HandleScript scriptArg, Value* rval)
4355 {
4356     RootedObject env(cx);
4357     RootedScope dummy(cx);
4358     if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &dummy))
4359         return false;
4360 
4361     RootedScript script(cx, scriptArg);
4362     if (!script->hasNonSyntacticScope() && !IsGlobalLexicalEnvironment(env)) {
4363         script = CloneGlobalScript(cx, ScopeKind::NonSyntactic, script);
4364         if (!script)
4365             return false;
4366         js::Debugger::onNewScript(cx, script);
4367     }
4368 
4369     return ExecuteScript(cx, env, script, rval);
4370 }
4371 
4372 MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
4373 JS_ExecuteScript(JSContext* cx, HandleScript scriptArg, MutableHandleValue rval)
4374 {
4375     RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4376     return ExecuteScript(cx, globalLexical, scriptArg, rval.address());
4377 }
4378 
4379 MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
4380 JS_ExecuteScript(JSContext* cx, HandleScript scriptArg)
4381 {
4382     RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4383     return ExecuteScript(cx, globalLexical, scriptArg, nullptr);
4384 }
4385 
4386 MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
4387 JS_ExecuteScript(JSContext* cx, AutoObjectVector& envChain,
4388                  HandleScript scriptArg, MutableHandleValue rval)
4389 {
4390     return ExecuteScript(cx, envChain, scriptArg, rval.address());
4391 }
4392 
4393 MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
4394 JS_ExecuteScript(JSContext* cx, AutoObjectVector& envChain, HandleScript scriptArg)
4395 {
4396     return ExecuteScript(cx, envChain, scriptArg, nullptr);
4397 }
4398 
4399 JS_PUBLIC_API(bool)
4400 JS::CloneAndExecuteScript(JSContext* cx, HandleScript scriptArg,
4401                           JS::MutableHandleValue rval)
4402 {
4403     CHECK_REQUEST(cx);
4404     RootedScript script(cx, scriptArg);
4405     RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4406     if (script->compartment() != cx->compartment()) {
4407         script = CloneGlobalScript(cx, ScopeKind::Global, script);
4408         if (!script)
4409             return false;
4410 
4411         js::Debugger::onNewScript(cx, script);
4412     }
4413     return ExecuteScript(cx, globalLexical, script, rval.address());
4414 }
4415 
4416 static const unsigned LARGE_SCRIPT_LENGTH = 500*1024;
4417 
4418 static bool
4419 Evaluate(JSContext* cx, ScopeKind scopeKind, HandleObject env,
4420          const ReadOnlyCompileOptions& optionsArg,
4421          SourceBufferHolder& srcBuf, MutableHandleValue rval)
4422 {
4423     CompileOptions options(cx, optionsArg);
4424     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
4425     AssertHeapIsIdle(cx);
4426     CHECK_REQUEST(cx);
4427     assertSameCompartment(cx, env);
4428     MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(env), scopeKind == ScopeKind::NonSyntactic);
4429 
4430     options.setIsRunOnce(true);
4431     SourceCompressionTask sct(cx);
4432     RootedScript script(cx, frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(),
4433                                                           scopeKind, options, srcBuf, &sct));
4434     if (!script)
4435         return false;
4436 
4437     MOZ_ASSERT(script->getVersion() == options.version);
4438 
4439     bool result = Execute(cx, script, *env,
4440                           options.noScriptRval ? nullptr : rval.address());
4441     if (!sct.complete())
4442         result = false;
4443 
4444     // After evaluation, the compiled script will not be run again.
4445     // script->ensureRanAnalysis allocated 1 analyze::Bytecode for every opcode
4446     // which for large scripts means significant memory. Perform a GC eagerly
4447     // to clear out this analysis data before anything happens to inhibit the
4448     // flushing of this memory (such as setting requestAnimationFrame).
4449     if (script->length() > LARGE_SCRIPT_LENGTH) {
4450         script = nullptr;
4451         PrepareZoneForGC(cx->zone());
4452         cx->runtime()->gc.gc(GC_NORMAL, JS::gcreason::FINISH_LARGE_EVALUATE);
4453     }
4454 
4455     return result;
4456 }
4457 
4458 static bool
4459 Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
4460          SourceBufferHolder& srcBuf, MutableHandleValue rval)
4461 {
4462     RootedObject env(cx);
4463     RootedScope scope(cx);
4464     if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope))
4465         return false;
4466     return ::Evaluate(cx, scope->kind(), env, optionsArg, srcBuf, rval);
4467 }
4468 
4469 static bool
4470 Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4471          const char16_t* chars, size_t length, MutableHandleValue rval)
4472 {
4473   SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
4474   RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4475   return ::Evaluate(cx, ScopeKind::Global, globalLexical, optionsArg, srcBuf, rval);
4476 }
4477 
4478 extern JS_PUBLIC_API(bool)
4479 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
4480              const char* bytes, size_t length, MutableHandleValue rval)
4481 {
4482     char16_t* chars;
4483     if (options.utf8)
4484         chars = UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get();
4485     else
4486         chars = InflateString(cx, bytes, &length);
4487     if (!chars)
4488         return false;
4489 
4490     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership);
4491     RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4492     bool ok = ::Evaluate(cx, ScopeKind::Global, globalLexical, options, srcBuf, rval);
4493     return ok;
4494 }
4495 
4496 static bool
4497 Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4498          const char* filename, MutableHandleValue rval)
4499 {
4500     FileContents buffer(cx);
4501     {
4502         AutoFile file;
4503         if (!file.open(cx, filename) || !file.readAll(cx, buffer))
4504             return false;
4505     }
4506 
4507     CompileOptions options(cx, optionsArg);
4508     options.setFileAndLine(filename, 1);
4509     return Evaluate(cx, options, buffer.begin(), buffer.length(), rval);
4510 }
4511 
4512 JS_PUBLIC_API(bool)
4513 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4514              SourceBufferHolder& srcBuf, MutableHandleValue rval)
4515 {
4516     RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
4517     return ::Evaluate(cx, ScopeKind::Global, globalLexical, optionsArg, srcBuf, rval);
4518 }
4519 
4520 JS_PUBLIC_API(bool)
4521 JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
4522              SourceBufferHolder& srcBuf, MutableHandleValue rval)
4523 {
4524     return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval);
4525 }
4526 
4527 JS_PUBLIC_API(bool)
4528 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4529              const char16_t* chars, size_t length, MutableHandleValue rval)
4530 {
4531     return ::Evaluate(cx, optionsArg, chars, length, rval);
4532 }
4533 
4534 JS_PUBLIC_API(bool)
4535 JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
4536              const char16_t* chars, size_t length, MutableHandleValue rval)
4537 {
4538     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
4539     return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval);
4540 }
4541 
4542 JS_PUBLIC_API(bool)
4543 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
4544              const char* filename, MutableHandleValue rval)
4545 {
4546     return ::Evaluate(cx, optionsArg, filename, rval);
4547 }
4548 
4549 JS_PUBLIC_API(JSFunction*)
4550 JS::GetModuleResolveHook(JSContext* cx)
4551 {
4552     AssertHeapIsIdle(cx);
4553     CHECK_REQUEST(cx);
4554     return cx->global()->moduleResolveHook();
4555 }
4556 
4557 JS_PUBLIC_API(void)
4558 JS::SetModuleResolveHook(JSContext* cx, HandleFunction func)
4559 {
4560     AssertHeapIsIdle(cx);
4561     CHECK_REQUEST(cx);
4562     assertSameCompartment(cx, func);
4563     cx->global()->setModuleResolveHook(func);
4564 }
4565 
4566 JS_PUBLIC_API(bool)
4567 JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
4568                   SourceBufferHolder& srcBuf, JS::MutableHandleObject module)
4569 {
4570     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
4571     AssertHeapIsIdle(cx);
4572     CHECK_REQUEST(cx);
4573 
4574     module.set(frontend::CompileModule(cx, options, srcBuf));
4575     return !!module;
4576 }
4577 
4578 JS_PUBLIC_API(void)
4579 JS::SetModuleHostDefinedField(JSObject* module, const JS::Value& value)
4580 {
4581     module->as<ModuleObject>().setHostDefinedField(value);
4582 }
4583 
4584 JS_PUBLIC_API(JS::Value)
4585 JS::GetModuleHostDefinedField(JSObject* module)
4586 {
4587     return module->as<ModuleObject>().hostDefinedField();
4588 }
4589 
4590 JS_PUBLIC_API(bool)
4591 JS::ModuleDeclarationInstantiation(JSContext* cx, JS::HandleObject moduleArg)
4592 {
4593     AssertHeapIsIdle(cx);
4594     CHECK_REQUEST(cx);
4595     assertSameCompartment(cx, moduleArg);
4596     return ModuleObject::DeclarationInstantiation(cx, moduleArg.as<ModuleObject>());
4597 }
4598 
4599 JS_PUBLIC_API(bool)
4600 JS::ModuleEvaluation(JSContext* cx, JS::HandleObject moduleArg)
4601 {
4602     AssertHeapIsIdle(cx);
4603     CHECK_REQUEST(cx);
4604     assertSameCompartment(cx, moduleArg);
4605     return ModuleObject::Evaluation(cx, moduleArg.as<ModuleObject>());
4606 }
4607 
4608 JS_PUBLIC_API(JSObject*)
4609 JS::GetRequestedModules(JSContext* cx, JS::HandleObject moduleArg)
4610 {
4611     AssertHeapIsIdle(cx);
4612     CHECK_REQUEST(cx);
4613     assertSameCompartment(cx, moduleArg);
4614     return &moduleArg->as<ModuleObject>().requestedModules();
4615 }
4616 
4617 JS_PUBLIC_API(JSScript*)
4618 JS::GetModuleScript(JSContext* cx, JS::HandleObject moduleArg)
4619 {
4620     AssertHeapIsIdle(cx);
4621     CHECK_REQUEST(cx);
4622     assertSameCompartment(cx, moduleArg);
4623     return moduleArg->as<ModuleObject>().script();
4624 }
4625 
4626 JS_PUBLIC_API(JSObject*)
4627 JS_New(JSContext* cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
4628 {
4629     AssertHeapIsIdle(cx);
4630     CHECK_REQUEST(cx);
4631     assertSameCompartment(cx, ctor, inputArgs);
4632 
4633     RootedValue ctorVal(cx, ObjectValue(*ctor));
4634     if (!IsConstructor(ctorVal)) {
4635         ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, ctorVal, nullptr);
4636         return nullptr;
4637     }
4638 
4639     ConstructArgs args(cx);
4640     if (!FillArgumentsFromArraylike(cx, args, inputArgs))
4641         return nullptr;
4642 
4643     RootedObject obj(cx);
4644     if (!js::Construct(cx, ctorVal, args, ctorVal, &obj))
4645         return nullptr;
4646 
4647     return obj;
4648 }
4649 
4650 JS_PUBLIC_API(bool)
4651 JS_CheckForInterrupt(JSContext* cx)
4652 {
4653     return js::CheckForInterrupt(cx);
4654 }
4655 
4656 JS_PUBLIC_API(bool)
4657 JS_AddInterruptCallback(JSContext* cx, JSInterruptCallback callback)
4658 {
4659     return cx->interruptCallbacks.append(callback);
4660 }
4661 
4662 JS_PUBLIC_API(bool)
4663 JS_DisableInterruptCallback(JSContext* cx)
4664 {
4665     bool result = cx->interruptCallbackDisabled;
4666     cx->interruptCallbackDisabled = true;
4667     return result;
4668 }
4669 
4670 JS_PUBLIC_API(void)
4671 JS_ResetInterruptCallback(JSContext* cx, bool enable)
4672 {
4673     cx->interruptCallbackDisabled = enable;
4674 }
4675 
4676 /************************************************************************/
4677 
4678 /*
4679  * Promises.
4680  */
4681 JS_PUBLIC_API(void)
4682 JS::SetGetIncumbentGlobalCallback(JSContext* cx, JSGetIncumbentGlobalCallback callback)
4683 {
4684     cx->getIncumbentGlobalCallback = callback;
4685 }
4686 
4687 JS_PUBLIC_API(void)
4688 JS::SetEnqueuePromiseJobCallback(JSContext* cx, JSEnqueuePromiseJobCallback callback,
4689                                  void* data /* = nullptr */)
4690 {
4691     cx->enqueuePromiseJobCallback = callback;
4692     cx->enqueuePromiseJobCallbackData = data;
4693 }
4694 
4695 extern JS_PUBLIC_API(void)
4696 JS::SetPromiseRejectionTrackerCallback(JSContext* cx, JSPromiseRejectionTrackerCallback callback,
4697                                        void* data /* = nullptr */)
4698 {
4699     cx->promiseRejectionTrackerCallback = callback;
4700     cx->promiseRejectionTrackerCallbackData = data;
4701 }
4702 
4703 JS_PUBLIC_API(JSObject*)
4704 JS::NewPromiseObject(JSContext* cx, HandleObject executor, HandleObject proto /* = nullptr */)
4705 {
4706     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
4707     MOZ_ASSERT(IsCallable(executor));
4708     AssertHeapIsIdle(cx);
4709     CHECK_REQUEST(cx);
4710     assertSameCompartment(cx, executor, proto);
4711 
4712     return PromiseObject::create(cx, executor, proto);
4713 }
4714 
4715 JS_PUBLIC_API(bool)
4716 JS::IsPromiseObject(JS::HandleObject obj)
4717 {
4718     return obj->is<PromiseObject>();
4719 }
4720 
4721 JS_PUBLIC_API(JSObject*)
4722 JS::GetPromiseConstructor(JSContext* cx)
4723 {
4724     CHECK_REQUEST(cx);
4725     Rooted<GlobalObject*> global(cx, cx->global());
4726     return GlobalObject::getOrCreatePromiseConstructor(cx, global);
4727 }
4728 
4729 JS_PUBLIC_API(JSObject*)
4730 JS::GetPromisePrototype(JSContext* cx)
4731 {
4732     CHECK_REQUEST(cx);
4733     Rooted<GlobalObject*> global(cx, cx->global());
4734     return GlobalObject::getOrCreatePromisePrototype(cx, global);
4735 }
4736 
4737 JS_PUBLIC_API(JS::PromiseState)
4738 JS::GetPromiseState(JS::HandleObject promiseObj_)
4739 {
4740     JSObject* promiseObj = CheckedUnwrap(promiseObj_);
4741     if (!promiseObj || !promiseObj->is<PromiseObject>())
4742         return JS::PromiseState::Pending;
4743 
4744     return promiseObj->as<PromiseObject>().state();
4745 }
4746 
4747 JS_PUBLIC_API(uint64_t)
4748 JS::GetPromiseID(JS::HandleObject promise)
4749 {
4750     return promise->as<PromiseObject>().getID();
4751 }
4752 
4753 JS_PUBLIC_API(JS::Value)
4754 JS::GetPromiseResult(JS::HandleObject promiseObj)
4755 {
4756     PromiseObject* promise = &promiseObj->as<PromiseObject>();
4757     MOZ_ASSERT(promise->state() != JS::PromiseState::Pending);
4758     return promise->state() == JS::PromiseState::Fulfilled ? promise->value() : promise->reason();
4759 }
4760 
4761 JS_PUBLIC_API(JSObject*)
4762 JS::GetPromiseAllocationSite(JS::HandleObject promise)
4763 {
4764     return promise->as<PromiseObject>().allocationSite();
4765 }
4766 
4767 JS_PUBLIC_API(JSObject*)
4768 JS::GetPromiseResolutionSite(JS::HandleObject promise)
4769 {
4770     return promise->as<PromiseObject>().resolutionSite();
4771 }
4772 
4773 #ifdef DEBUG
4774 JS_PUBLIC_API(void)
4775 JS::DumpPromiseAllocationSite(JSContext* cx, JS::HandleObject promise)
4776 {
4777     RootedObject stack(cx, promise->as<PromiseObject>().allocationSite());
4778     UniqueChars stackStr(reinterpret_cast<char*>(BuildUTF8StackString(cx, stack).get()));
4779     if (stackStr.get())
4780         fputs(stackStr.get(), stderr);
4781 }
4782 
4783 JS_PUBLIC_API(void)
4784 JS::DumpPromiseResolutionSite(JSContext* cx, JS::HandleObject promise)
4785 {
4786     RootedObject stack(cx, promise->as<PromiseObject>().resolutionSite());
4787     UniqueChars stackStr(reinterpret_cast<char*>(BuildUTF8StackString(cx, stack).get()));
4788     if (stackStr.get())
4789         fputs(stackStr.get(), stderr);
4790 }
4791 #endif
4792 
4793 JS_PUBLIC_API(JSObject*)
4794 JS::CallOriginalPromiseResolve(JSContext* cx, JS::HandleValue resolutionValue)
4795 {
4796     AssertHeapIsIdle(cx);
4797     CHECK_REQUEST(cx);
4798     assertSameCompartment(cx, resolutionValue);
4799 
4800     RootedObject promise(cx, PromiseObject::unforgeableResolve(cx, resolutionValue));
4801     MOZ_ASSERT_IF(promise, promise->is<PromiseObject>());
4802     return promise;
4803 }
4804 
4805 JS_PUBLIC_API(JSObject*)
4806 JS::CallOriginalPromiseReject(JSContext* cx, JS::HandleValue rejectionValue)
4807 {
4808     AssertHeapIsIdle(cx);
4809     CHECK_REQUEST(cx);
4810     assertSameCompartment(cx, rejectionValue);
4811 
4812     RootedObject promise(cx, PromiseObject::unforgeableReject(cx, rejectionValue));
4813     MOZ_ASSERT_IF(promise, promise->is<PromiseObject>());
4814     return promise;
4815 }
4816 
4817 static bool
4818 ResolveOrRejectPromise(JSContext* cx, JS::HandleObject promiseObj, JS::HandleValue resultOrReason_,
4819                        bool reject)
4820 {
4821     AssertHeapIsIdle(cx);
4822     CHECK_REQUEST(cx);
4823     assertSameCompartment(cx, promiseObj, resultOrReason_);
4824 
4825     mozilla::Maybe<AutoCompartment> ac;
4826     Rooted<PromiseObject*> promise(cx);
4827     RootedValue resultOrReason(cx, resultOrReason_);
4828     if (IsWrapper(promiseObj)) {
4829         JSObject* unwrappedPromiseObj = CheckedUnwrap(promiseObj);
4830         if (!unwrappedPromiseObj) {
4831             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_OBJECT_ACCESS_DENIED);
4832             return false;
4833         }
4834         promise = &unwrappedPromiseObj->as<PromiseObject>();
4835         ac.emplace(cx, promise);
4836         if (!cx->compartment()->wrap(cx, &resultOrReason))
4837             return false;
4838     } else {
4839         promise = promiseObj.as<PromiseObject>();
4840     }
4841 
4842     return reject
4843            ? promise->reject(cx, resultOrReason)
4844            : promise->resolve(cx, resultOrReason);
4845 }
4846 
4847 JS_PUBLIC_API(bool)
4848 JS::ResolvePromise(JSContext* cx, JS::HandleObject promiseObj, JS::HandleValue resolutionValue)
4849 {
4850     return ResolveOrRejectPromise(cx, promiseObj, resolutionValue, false);
4851 }
4852 
4853 JS_PUBLIC_API(bool)
4854 JS::RejectPromise(JSContext* cx, JS::HandleObject promiseObj, JS::HandleValue rejectionValue)
4855 {
4856     return ResolveOrRejectPromise(cx, promiseObj, rejectionValue, true);
4857 }
4858 
4859 static bool
4860 CallOriginalPromiseThenImpl(JSContext* cx, JS::HandleObject promiseObj,
4861                             JS::HandleObject onResolvedObj_, JS::HandleObject onRejectedObj_,
4862                             JS::MutableHandleObject resultObj, bool createDependent)
4863 {
4864     AssertHeapIsIdle(cx);
4865     CHECK_REQUEST(cx);
4866     assertSameCompartment(cx, promiseObj, onResolvedObj_, onRejectedObj_);
4867 
4868     MOZ_ASSERT_IF(onResolvedObj_, IsCallable(onResolvedObj_));
4869     MOZ_ASSERT_IF(onRejectedObj_, IsCallable(onRejectedObj_));
4870 
4871     {
4872         mozilla::Maybe<AutoCompartment> ac;
4873         Rooted<PromiseObject*> promise(cx);
4874         RootedObject onResolvedObj(cx, onResolvedObj_);
4875         RootedObject onRejectedObj(cx, onRejectedObj_);
4876         if (IsWrapper(promiseObj)) {
4877             JSObject* unwrappedPromiseObj = CheckedUnwrap(promiseObj);
4878             if (!unwrappedPromiseObj) {
4879                 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_OBJECT_ACCESS_DENIED);
4880                 return false;
4881             }
4882             promise = &unwrappedPromiseObj->as<PromiseObject>();
4883             ac.emplace(cx, promise);
4884             if (!cx->compartment()->wrap(cx, &onResolvedObj) ||
4885                 !cx->compartment()->wrap(cx, &onRejectedObj))
4886             {
4887                 return false;
4888             }
4889         } else {
4890             promise = promiseObj.as<PromiseObject>();
4891         }
4892 
4893         RootedValue onFulfilled(cx, ObjectOrNullValue(onResolvedObj));
4894         RootedValue onRejected(cx, ObjectOrNullValue(onRejectedObj));
4895         if (!OriginalPromiseThen(cx, promise, onFulfilled, onRejected, resultObj, createDependent))
4896             return false;
4897     }
4898 
4899     if (resultObj) {
4900         if (!cx->compartment()->wrap(cx, resultObj))
4901             return false;
4902     }
4903     return true;
4904 
4905 }
4906 
4907 JS_PUBLIC_API(JSObject*)
4908 JS::CallOriginalPromiseThen(JSContext* cx, JS::HandleObject promiseObj,
4909                             JS::HandleObject onResolvedObj, JS::HandleObject onRejectedObj)
4910 {
4911     RootedObject resultPromise(cx);
4912     if (!CallOriginalPromiseThenImpl(cx, promiseObj, onResolvedObj, onRejectedObj, &resultPromise, true))
4913         return nullptr;
4914     return resultPromise;
4915 }
4916 
4917 JS_PUBLIC_API(bool)
4918 JS::AddPromiseReactions(JSContext* cx, JS::HandleObject promiseObj,
4919                         JS::HandleObject onResolvedObj, JS::HandleObject onRejectedObj)
4920 {
4921     RootedObject resultPromise(cx);
4922     bool result = CallOriginalPromiseThenImpl(cx, promiseObj, onResolvedObj, onRejectedObj, &resultPromise, false);
4923     MOZ_ASSERT(!resultPromise);
4924     return result;
4925 }
4926 
4927 /**
4928  * Unforgeable version of Promise.all for internal use.
4929  *
4930  * Takes a dense array of Promise objects and returns a promise that's
4931  * resolved with an array of resolution values when all those promises ahve
4932  * been resolved, or rejected with the rejection value of the first rejected
4933  * promise.
4934  *
4935  * Asserts that the array is dense and all entries are Promise objects.
4936  */
4937 JS_PUBLIC_API(JSObject*)
4938 JS::GetWaitForAllPromise(JSContext* cx, const JS::AutoObjectVector& promises)
4939 {
4940     AssertHeapIsIdle(cx);
4941     CHECK_REQUEST(cx);
4942 
4943     return js::GetWaitForAllPromise(cx, promises);
4944 }
4945 
4946 JS_PUBLIC_API(void)
4947 JS::SetAsyncTaskCallbacks(JSContext* cx, JS::StartAsyncTaskCallback start,
4948                           JS::FinishAsyncTaskCallback finish)
4949 {
4950     cx->startAsyncTaskCallback = start;
4951     cx->finishAsyncTaskCallback = finish;
4952 }
4953 
4954 JS_PUBLIC_API(void)
4955 JS_RequestInterruptCallback(JSContext* cx)
4956 {
4957     cx->requestInterrupt(JSRuntime::RequestInterruptUrgent);
4958 }
4959 
4960 JS_PUBLIC_API(bool)
4961 JS_IsRunning(JSContext* cx)
4962 {
4963     return cx->currentlyRunning();
4964 }
4965 
4966 JS::AutoSetAsyncStackForNewCalls::AutoSetAsyncStackForNewCalls(
4967   JSContext* cx, HandleObject stack, const char* asyncCause,
4968   JS::AutoSetAsyncStackForNewCalls::AsyncCallKind kind)
4969   : cx(cx),
4970     oldAsyncStack(cx, cx->asyncStackForNewActivations),
4971     oldAsyncCause(cx->asyncCauseForNewActivations),
4972     oldAsyncCallIsExplicit(cx->asyncCallIsExplicit)
4973 {
4974     CHECK_REQUEST(cx);
4975 
4976     // The option determines whether we actually use the new values at this
4977     // point. It will not affect restoring the previous values when the object
4978     // is destroyed, so if the option changes it won't cause consistency issues.
4979     if (!cx->options().asyncStack())
4980         return;
4981 
4982     SavedFrame* asyncStack = &stack->as<SavedFrame>();
4983 
4984     cx->asyncStackForNewActivations = asyncStack;
4985     cx->asyncCauseForNewActivations = asyncCause;
4986     cx->asyncCallIsExplicit = kind == AsyncCallKind::EXPLICIT;
4987 }
4988 
4989 JS::AutoSetAsyncStackForNewCalls::~AutoSetAsyncStackForNewCalls()
4990 {
4991     cx->asyncCauseForNewActivations = oldAsyncCause;
4992     cx->asyncStackForNewActivations =
4993       oldAsyncStack ? &oldAsyncStack->as<SavedFrame>() : nullptr;
4994     cx->asyncCallIsExplicit = oldAsyncCallIsExplicit;
4995 }
4996 
4997 /************************************************************************/
4998 JS_PUBLIC_API(JSString*)
4999 JS_NewStringCopyN(JSContext* cx, const char* s, size_t n)
5000 {
5001     AssertHeapIsIdle(cx);
5002     CHECK_REQUEST(cx);
5003     return NewStringCopyN<CanGC>(cx, s, n);
5004 }
5005 
5006 JS_PUBLIC_API(JSString*)
5007 JS_NewStringCopyZ(JSContext* cx, const char* s)
5008 {
5009     AssertHeapIsIdle(cx);
5010     CHECK_REQUEST(cx);
5011     if (!s)
5012         return cx->runtime()->emptyString;
5013     return NewStringCopyZ<CanGC>(cx, s);
5014 }
5015 
5016 JS_PUBLIC_API(JSString*)
5017 JS_NewStringCopyUTF8Z(JSContext* cx, const JS::ConstUTF8CharsZ s)
5018 {
5019     AssertHeapIsIdle(cx);
5020     CHECK_REQUEST(cx);
5021     return NewStringCopyUTF8Z<CanGC>(cx, s);
5022 }
5023 
5024 JS_PUBLIC_API(JSString*)
5025 JS_NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars s)
5026 {
5027     AssertHeapIsIdle(cx);
5028     CHECK_REQUEST(cx);
5029     return NewStringCopyUTF8N<CanGC>(cx, s);
5030 }
5031 
5032 JS_PUBLIC_API(bool)
5033 JS_StringHasBeenPinned(JSContext* cx, JSString* str)
5034 {
5035     AssertHeapIsIdle(cx);
5036     CHECK_REQUEST(cx);
5037 
5038     if (!str->isAtom())
5039         return false;
5040 
5041     return AtomIsPinned(cx, &str->asAtom());
5042 }
5043 
5044 JS_PUBLIC_API(jsid)
5045 INTERNED_STRING_TO_JSID(JSContext* cx, JSString* str)
5046 {
5047     MOZ_ASSERT(str);
5048     MOZ_ASSERT(((size_t)str & JSID_TYPE_MASK) == 0);
5049     MOZ_ASSERT_IF(cx, JS_StringHasBeenPinned(cx, str));
5050     return AtomToId(&str->asAtom());
5051 }
5052 
5053 JS_PUBLIC_API(JSString*)
5054 JS_AtomizeAndPinJSString(JSContext* cx, HandleString str)
5055 {
5056     AssertHeapIsIdle(cx);
5057     CHECK_REQUEST(cx);
5058     JSAtom* atom = AtomizeString(cx, str, PinAtom);
5059     MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom));
5060     return atom;
5061 }
5062 
5063 JS_PUBLIC_API(JSString*)
5064 JS_AtomizeString(JSContext* cx, const char* s)
5065 {
5066     return JS_AtomizeStringN(cx, s, strlen(s));
5067 }
5068 
5069 JS_PUBLIC_API(JSString*)
5070 JS_AtomizeStringN(JSContext* cx, const char* s, size_t length)
5071 {
5072     AssertHeapIsIdle(cx);
5073     CHECK_REQUEST(cx);
5074     return Atomize(cx, s, length, DoNotPinAtom);
5075 }
5076 
5077 JS_PUBLIC_API(JSString*)
5078 JS_AtomizeAndPinString(JSContext* cx, const char* s)
5079 {
5080     return JS_AtomizeAndPinStringN(cx, s, strlen(s));
5081 }
5082 
5083 JS_PUBLIC_API(JSString*)
5084 JS_AtomizeAndPinStringN(JSContext* cx, const char* s, size_t length)
5085 {
5086     AssertHeapIsIdle(cx);
5087     CHECK_REQUEST(cx);
5088     JSAtom* atom = Atomize(cx, s, length, PinAtom);
5089     MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom));
5090     return atom;
5091 }
5092 
5093 JS_PUBLIC_API(JSString*)
5094 JS_NewUCString(JSContext* cx, char16_t* chars, size_t length)
5095 {
5096     AssertHeapIsIdle(cx);
5097     CHECK_REQUEST(cx);
5098     return NewString<CanGC>(cx, chars, length);
5099 }
5100 
5101 JS_PUBLIC_API(JSString*)
5102 JS_NewUCStringCopyN(JSContext* cx, const char16_t* s, size_t n)
5103 {
5104     AssertHeapIsIdle(cx);
5105     CHECK_REQUEST(cx);
5106     if (!n)
5107         return cx->names().empty;
5108     return NewStringCopyN<CanGC>(cx, s, n);
5109 }
5110 
5111 JS_PUBLIC_API(JSString*)
5112 JS_NewUCStringCopyZ(JSContext* cx, const char16_t* s)
5113 {
5114     AssertHeapIsIdle(cx);
5115     CHECK_REQUEST(cx);
5116     if (!s)
5117         return cx->runtime()->emptyString;
5118     return NewStringCopyZ<CanGC>(cx, s);
5119 }
5120 
5121 JS_PUBLIC_API(JSString*)
5122 JS_AtomizeUCString(JSContext* cx, const char16_t* s)
5123 {
5124     return JS_AtomizeUCStringN(cx, s, js_strlen(s));
5125 }
5126 
5127 JS_PUBLIC_API(JSString*)
5128 JS_AtomizeUCStringN(JSContext* cx, const char16_t* s, size_t length)
5129 {
5130     AssertHeapIsIdle(cx);
5131     CHECK_REQUEST(cx);
5132     return AtomizeChars(cx, s, length, DoNotPinAtom);
5133 }
5134 
5135 JS_PUBLIC_API(JSString*)
5136 JS_AtomizeAndPinUCStringN(JSContext* cx, const char16_t* s, size_t length)
5137 {
5138     AssertHeapIsIdle(cx);
5139     CHECK_REQUEST(cx);
5140     JSAtom* atom = AtomizeChars(cx, s, length, PinAtom);
5141     MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom));
5142     return atom;
5143 }
5144 
5145 JS_PUBLIC_API(JSString*)
5146 JS_AtomizeAndPinUCString(JSContext* cx, const char16_t* s)
5147 {
5148     return JS_AtomizeAndPinUCStringN(cx, s, js_strlen(s));
5149 }
5150 
5151 JS_PUBLIC_API(size_t)
5152 JS_GetStringLength(JSString* str)
5153 {
5154     return str->length();
5155 }
5156 
5157 JS_PUBLIC_API(bool)
5158 JS_StringIsFlat(JSString* str)
5159 {
5160     return str->isFlat();
5161 }
5162 
5163 JS_PUBLIC_API(bool)
5164 JS_StringHasLatin1Chars(JSString* str)
5165 {
5166     return str->hasLatin1Chars();
5167 }
5168 
5169 JS_PUBLIC_API(const JS::Latin1Char*)
5170 JS_GetLatin1StringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str,
5171                                  size_t* plength)
5172 {
5173     MOZ_ASSERT(plength);
5174     AssertHeapIsIdleOrStringIsFlat(cx, str);
5175     CHECK_REQUEST(cx);
5176     assertSameCompartment(cx, str);
5177     JSLinearString* linear = str->ensureLinear(cx);
5178     if (!linear)
5179         return nullptr;
5180     *plength = linear->length();
5181     return linear->latin1Chars(nogc);
5182 }
5183 
5184 JS_PUBLIC_API(const char16_t*)
5185 JS_GetTwoByteStringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str,
5186                                   size_t* plength)
5187 {
5188     MOZ_ASSERT(plength);
5189     AssertHeapIsIdleOrStringIsFlat(cx, str);
5190     CHECK_REQUEST(cx);
5191     assertSameCompartment(cx, str);
5192     JSLinearString* linear = str->ensureLinear(cx);
5193     if (!linear)
5194         return nullptr;
5195     *plength = linear->length();
5196     return linear->twoByteChars(nogc);
5197 }
5198 
5199 JS_PUBLIC_API(const char16_t*)
5200 JS_GetTwoByteExternalStringChars(JSString* str)
5201 {
5202     return str->asExternal().twoByteChars();
5203 }
5204 
5205 JS_PUBLIC_API(bool)
5206 JS_GetStringCharAt(JSContext* cx, JSString* str, size_t index, char16_t* res)
5207 {
5208     AssertHeapIsIdleOrStringIsFlat(cx, str);
5209     CHECK_REQUEST(cx);
5210     assertSameCompartment(cx, str);
5211 
5212     JSLinearString* linear = str->ensureLinear(cx);
5213     if (!linear)
5214         return false;
5215 
5216     *res = linear->latin1OrTwoByteChar(index);
5217     return true;
5218 }
5219 
5220 JS_PUBLIC_API(char16_t)
5221 JS_GetFlatStringCharAt(JSFlatString* str, size_t index)
5222 {
5223     return str->latin1OrTwoByteChar(index);
5224 }
5225 
5226 JS_PUBLIC_API(bool)
5227 JS_CopyStringChars(JSContext* cx, mozilla::Range<char16_t> dest, JSString* str)
5228 {
5229     AssertHeapIsIdleOrStringIsFlat(cx, str);
5230     CHECK_REQUEST(cx);
5231     assertSameCompartment(cx, str);
5232 
5233     JSLinearString* linear = str->ensureLinear(cx);
5234     if (!linear)
5235         return false;
5236 
5237     MOZ_ASSERT(linear->length() <= dest.length());
5238     CopyChars(dest.begin().get(), *linear);
5239     return true;
5240 }
5241 
5242 JS_PUBLIC_API(const Latin1Char*)
5243 JS_GetLatin1InternedStringChars(const JS::AutoCheckCannotGC& nogc, JSString* str)
5244 {
5245     MOZ_ASSERT(str->isAtom());
5246     JSFlatString* flat = str->ensureFlat(nullptr);
5247     if (!flat)
5248         return nullptr;
5249     return flat->latin1Chars(nogc);
5250 }
5251 
5252 JS_PUBLIC_API(const char16_t*)
5253 JS_GetTwoByteInternedStringChars(const JS::AutoCheckCannotGC& nogc, JSString* str)
5254 {
5255     MOZ_ASSERT(str->isAtom());
5256     JSFlatString* flat = str->ensureFlat(nullptr);
5257     if (!flat)
5258         return nullptr;
5259     return flat->twoByteChars(nogc);
5260 }
5261 
5262 extern JS_PUBLIC_API(JSFlatString*)
5263 JS_FlattenString(JSContext* cx, JSString* str)
5264 {
5265     AssertHeapIsIdle(cx);
5266     CHECK_REQUEST(cx);
5267     assertSameCompartment(cx, str);
5268     JSFlatString* flat = str->ensureFlat(cx);
5269     if (!flat)
5270         return nullptr;
5271     return flat;
5272 }
5273 
5274 extern JS_PUBLIC_API(const Latin1Char*)
5275 JS_GetLatin1FlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str)
5276 {
5277     return str->latin1Chars(nogc);
5278 }
5279 
5280 extern JS_PUBLIC_API(const char16_t*)
5281 JS_GetTwoByteFlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str)
5282 {
5283     return str->twoByteChars(nogc);
5284 }
5285 
5286 JS_PUBLIC_API(bool)
5287 JS_CompareStrings(JSContext* cx, JSString* str1, JSString* str2, int32_t* result)
5288 {
5289     AssertHeapIsIdle(cx);
5290     CHECK_REQUEST(cx);
5291 
5292     return CompareStrings(cx, str1, str2, result);
5293 }
5294 
5295 JS_PUBLIC_API(bool)
5296 JS_StringEqualsAscii(JSContext* cx, JSString* str, const char* asciiBytes, bool* match)
5297 {
5298     AssertHeapIsIdle(cx);
5299     CHECK_REQUEST(cx);
5300 
5301     JSLinearString* linearStr = str->ensureLinear(cx);
5302     if (!linearStr)
5303         return false;
5304     *match = StringEqualsAscii(linearStr, asciiBytes);
5305     return true;
5306 }
5307 
5308 JS_PUBLIC_API(bool)
5309 JS_FlatStringEqualsAscii(JSFlatString* str, const char* asciiBytes)
5310 {
5311     return StringEqualsAscii(str, asciiBytes);
5312 }
5313 
5314 JS_PUBLIC_API(size_t)
5315 JS_PutEscapedFlatString(char* buffer, size_t size, JSFlatString* str, char quote)
5316 {
5317     return PutEscapedString(buffer, size, str, quote);
5318 }
5319 
5320 JS_PUBLIC_API(size_t)
5321 JS_PutEscapedString(JSContext* cx, char* buffer, size_t size, JSString* str, char quote)
5322 {
5323     AssertHeapIsIdle(cx);
5324     JSLinearString* linearStr = str->ensureLinear(cx);
5325     if (!linearStr)
5326         return size_t(-1);
5327     return PutEscapedString(buffer, size, linearStr, quote);
5328 }
5329 
5330 JS_PUBLIC_API(bool)
5331 JS_FileEscapedString(FILE* fp, JSString* str, char quote)
5332 {
5333     JSLinearString* linearStr = str->ensureLinear(nullptr);
5334     return linearStr && FileEscapedString(fp, linearStr, quote);
5335 }
5336 
5337 JS_PUBLIC_API(JSString*)
5338 JS_NewDependentString(JSContext* cx, HandleString str, size_t start, size_t length)
5339 {
5340     AssertHeapIsIdle(cx);
5341     CHECK_REQUEST(cx);
5342     return NewDependentString(cx, str, start, length);
5343 }
5344 
5345 JS_PUBLIC_API(JSString*)
5346 JS_ConcatStrings(JSContext* cx, HandleString left, HandleString right)
5347 {
5348     AssertHeapIsIdle(cx);
5349     CHECK_REQUEST(cx);
5350     return ConcatStrings<CanGC>(cx, left, right);
5351 }
5352 
5353 JS_PUBLIC_API(bool)
5354 JS_DecodeBytes(JSContext* cx, const char* src, size_t srclen, char16_t* dst, size_t* dstlenp)
5355 {
5356     AssertHeapIsIdle(cx);
5357     CHECK_REQUEST(cx);
5358 
5359     if (!dst) {
5360         *dstlenp = srclen;
5361         return true;
5362     }
5363 
5364     size_t dstlen = *dstlenp;
5365 
5366     if (srclen > dstlen) {
5367         CopyAndInflateChars(dst, src, dstlen);
5368 
5369         AutoSuppressGC suppress(cx);
5370         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BUFFER_TOO_SMALL);
5371         return false;
5372     }
5373 
5374     CopyAndInflateChars(dst, src, srclen);
5375     *dstlenp = srclen;
5376     return true;
5377 }
5378 
5379 static char*
5380 EncodeLatin1(ExclusiveContext* cx, JSString* str)
5381 {
5382     JSLinearString* linear = str->ensureLinear(cx);
5383     if (!linear)
5384         return nullptr;
5385 
5386     JS::AutoCheckCannotGC nogc;
5387     if (linear->hasTwoByteChars())
5388         return JS::LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->twoByteRange(nogc)).c_str();
5389 
5390     size_t len = str->length();
5391     Latin1Char* buf = cx->pod_malloc<Latin1Char>(len + 1);
5392     if (!buf) {
5393         ReportOutOfMemory(cx);
5394         return nullptr;
5395     }
5396 
5397     mozilla::PodCopy(buf, linear->latin1Chars(nogc), len);
5398     buf[len] = '\0';
5399     return reinterpret_cast<char*>(buf);
5400 }
5401 
5402 JS_PUBLIC_API(char*)
5403 JS_EncodeString(JSContext* cx, JSString* str)
5404 {
5405     AssertHeapIsIdle(cx);
5406     CHECK_REQUEST(cx);
5407 
5408     return EncodeLatin1(cx, str);
5409 }
5410 
5411 JS_PUBLIC_API(char*)
5412 JS_EncodeStringToUTF8(JSContext* cx, HandleString str)
5413 {
5414     AssertHeapIsIdle(cx);
5415     CHECK_REQUEST(cx);
5416 
5417     return StringToNewUTF8CharsZ(cx, *str).release();
5418 }
5419 
5420 JS_PUBLIC_API(size_t)
5421 JS_GetStringEncodingLength(JSContext* cx, JSString* str)
5422 {
5423     AssertHeapIsIdle(cx);
5424     CHECK_REQUEST(cx);
5425 
5426     if (!str->ensureLinear(cx))
5427         return size_t(-1);
5428     return str->length();
5429 }
5430 
5431 JS_PUBLIC_API(size_t)
5432 JS_EncodeStringToBuffer(JSContext* cx, JSString* str, char* buffer, size_t length)
5433 {
5434     AssertHeapIsIdle(cx);
5435     CHECK_REQUEST(cx);
5436 
5437     /*
5438      * FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
5439      * would allow to distinguish between insufficient buffer and encoding
5440      * error.
5441      */
5442     size_t writtenLength = length;
5443     JSLinearString* linear = str->ensureLinear(cx);
5444     if (!linear)
5445          return size_t(-1);
5446 
5447     bool res;
5448     if (linear->hasLatin1Chars()) {
5449         JS::AutoCheckCannotGC nogc;
5450         res = DeflateStringToBuffer(nullptr, linear->latin1Chars(nogc), linear->length(), buffer,
5451                                     &writtenLength);
5452     } else {
5453         JS::AutoCheckCannotGC nogc;
5454         res = DeflateStringToBuffer(nullptr, linear->twoByteChars(nogc), linear->length(), buffer,
5455                                     &writtenLength);
5456     }
5457     if (res) {
5458         MOZ_ASSERT(writtenLength <= length);
5459         return writtenLength;
5460     }
5461     MOZ_ASSERT(writtenLength <= length);
5462     size_t necessaryLength = str->length();
5463     if (necessaryLength == size_t(-1))
5464         return size_t(-1);
5465     MOZ_ASSERT(writtenLength == length); // C strings are NOT encoded.
5466     return necessaryLength;
5467 }
5468 
5469 JS_PUBLIC_API(JS::Symbol*)
5470 JS::NewSymbol(JSContext* cx, HandleString description)
5471 {
5472     AssertHeapIsIdle(cx);
5473     CHECK_REQUEST(cx);
5474     if (description)
5475         assertSameCompartment(cx, description);
5476 
5477     return Symbol::new_(cx, SymbolCode::UniqueSymbol, description);
5478 }
5479 
5480 JS_PUBLIC_API(JS::Symbol*)
5481 JS::GetSymbolFor(JSContext* cx, HandleString key)
5482 {
5483     AssertHeapIsIdle(cx);
5484     CHECK_REQUEST(cx);
5485     assertSameCompartment(cx, key);
5486 
5487     return Symbol::for_(cx, key);
5488 }
5489 
5490 JS_PUBLIC_API(JSString*)
5491 JS::GetSymbolDescription(HandleSymbol symbol)
5492 {
5493     return symbol->description();
5494 }
5495 
5496 JS_PUBLIC_API(JS::SymbolCode)
5497 JS::GetSymbolCode(Handle<Symbol*> symbol)
5498 {
5499     return symbol->code();
5500 }
5501 
5502 JS_PUBLIC_API(JS::Symbol*)
5503 JS::GetWellKnownSymbol(JSContext* cx, JS::SymbolCode which)
5504 {
5505     return cx->wellKnownSymbols().get(uint32_t(which));
5506 }
5507 
5508 #ifdef DEBUG
5509 static bool
5510 PropertySpecNameIsDigits(const char* s) {
5511     if (JS::PropertySpecNameIsSymbol(s))
5512         return false;
5513     if (!*s)
5514         return false;
5515     for (; *s; s++) {
5516         if (*s < '0' || *s > '9')
5517             return false;
5518     }
5519     return true;
5520 }
5521 #endif // DEBUG
5522 
5523 JS_PUBLIC_API(bool)
5524 JS::PropertySpecNameEqualsId(const char* name, HandleId id)
5525 {
5526     if (JS::PropertySpecNameIsSymbol(name)) {
5527         if (!JSID_IS_SYMBOL(id))
5528             return false;
5529         Symbol* sym = JSID_TO_SYMBOL(id);
5530         return sym->isWellKnownSymbol() && sym->code() == PropertySpecNameToSymbolCode(name);
5531     }
5532 
5533     MOZ_ASSERT(!PropertySpecNameIsDigits(name));
5534     return JSID_IS_ATOM(id) && JS_FlatStringEqualsAscii(JSID_TO_ATOM(id), name);
5535 }
5536 
5537 JS_PUBLIC_API(bool)
5538 JS_Stringify(JSContext* cx, MutableHandleValue vp, HandleObject replacer,
5539              HandleValue space, JSONWriteCallback callback, void* data)
5540 {
5541     AssertHeapIsIdle(cx);
5542     CHECK_REQUEST(cx);
5543     assertSameCompartment(cx, replacer, space);
5544     StringBuffer sb(cx);
5545     if (!sb.ensureTwoByteChars())
5546         return false;
5547     if (!Stringify(cx, vp, replacer, space, sb, StringifyBehavior::Normal))
5548         return false;
5549     if (sb.empty() && !sb.append(cx->names().null))
5550         return false;
5551     return callback(sb.rawTwoByteBegin(), sb.length(), data);
5552 }
5553 
5554 JS_PUBLIC_API(bool)
5555 JS::ToJSONMaybeSafely(JSContext* cx, JS::HandleObject input,
5556                       JSONWriteCallback callback, void* data)
5557 {
5558     AssertHeapIsIdle(cx);
5559     CHECK_REQUEST(cx);
5560     assertSameCompartment(cx, input);
5561 
5562     StringBuffer sb(cx);
5563     if (!sb.ensureTwoByteChars())
5564         return false;
5565 
5566     RootedValue inputValue(cx, ObjectValue(*input));
5567     if (!Stringify(cx, &inputValue, nullptr, NullHandleValue, sb,
5568                    StringifyBehavior::RestrictedSafe))
5569         return false;
5570 
5571     if (sb.empty() && !sb.append(cx->names().null))
5572         return false;
5573 
5574     return callback(sb.rawTwoByteBegin(), sb.length(), data);
5575 }
5576 
5577 JS_PUBLIC_API(bool)
5578 JS_ParseJSON(JSContext* cx, const char16_t* chars, uint32_t len, MutableHandleValue vp)
5579 {
5580     AssertHeapIsIdle(cx);
5581     CHECK_REQUEST(cx);
5582     return ParseJSONWithReviver(cx, mozilla::Range<const char16_t>(chars, len), NullHandleValue, vp);
5583 }
5584 
5585 JS_PUBLIC_API(bool)
5586 JS_ParseJSON(JSContext* cx, HandleString str, MutableHandleValue vp)
5587 {
5588     return JS_ParseJSONWithReviver(cx, str, NullHandleValue, vp);
5589 }
5590 
5591 JS_PUBLIC_API(bool)
5592 JS_ParseJSONWithReviver(JSContext* cx, const char16_t* chars, uint32_t len, HandleValue reviver, MutableHandleValue vp)
5593 {
5594     AssertHeapIsIdle(cx);
5595     CHECK_REQUEST(cx);
5596     return ParseJSONWithReviver(cx, mozilla::Range<const char16_t>(chars, len), reviver, vp);
5597 }
5598 
5599 JS_PUBLIC_API(bool)
5600 JS_ParseJSONWithReviver(JSContext* cx, HandleString str, HandleValue reviver, MutableHandleValue vp)
5601 {
5602     AssertHeapIsIdle(cx);
5603     CHECK_REQUEST(cx);
5604     assertSameCompartment(cx, str);
5605 
5606     AutoStableStringChars stableChars(cx);
5607     if (!stableChars.init(cx, str))
5608         return false;
5609 
5610     return stableChars.isLatin1()
5611            ? ParseJSONWithReviver(cx, stableChars.latin1Range(), reviver, vp)
5612            : ParseJSONWithReviver(cx, stableChars.twoByteRange(), reviver, vp);
5613 }
5614 
5615 /************************************************************************/
5616 
5617 JS_PUBLIC_API(void)
5618 JS_ReportErrorASCII(JSContext* cx, const char* format, ...)
5619 {
5620     va_list ap;
5621 
5622     AssertHeapIsIdle(cx);
5623     va_start(ap, format);
5624     ReportErrorVA(cx, JSREPORT_ERROR, format, ArgumentsAreASCII, ap);
5625     va_end(ap);
5626 }
5627 
5628 JS_PUBLIC_API(void)
5629 JS_ReportErrorLatin1(JSContext* cx, const char* format, ...)
5630 {
5631     va_list ap;
5632 
5633     AssertHeapIsIdle(cx);
5634     va_start(ap, format);
5635     ReportErrorVA(cx, JSREPORT_ERROR, format, ArgumentsAreLatin1, ap);
5636     va_end(ap);
5637 }
5638 
5639 JS_PUBLIC_API(void)
5640 JS_ReportErrorUTF8(JSContext* cx, const char* format, ...)
5641 {
5642     va_list ap;
5643 
5644     AssertHeapIsIdle(cx);
5645     va_start(ap, format);
5646     ReportErrorVA(cx, JSREPORT_ERROR, format, ArgumentsAreUTF8, ap);
5647     va_end(ap);
5648 }
5649 
5650 JS_PUBLIC_API(void)
5651 JS_ReportErrorNumberASCII(JSContext* cx, JSErrorCallback errorCallback,
5652                           void* userRef, const unsigned errorNumber, ...)
5653 {
5654     va_list ap;
5655     va_start(ap, errorNumber);
5656     JS_ReportErrorNumberASCIIVA(cx, errorCallback, userRef, errorNumber, ap);
5657     va_end(ap);
5658 }
5659 
5660 JS_PUBLIC_API(void)
5661 JS_ReportErrorNumberASCIIVA(JSContext* cx, JSErrorCallback errorCallback,
5662                             void* userRef, const unsigned errorNumber,
5663                             va_list ap)
5664 {
5665     AssertHeapIsIdle(cx);
5666     ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
5667                         errorNumber, ArgumentsAreASCII, ap);
5668 }
5669 
5670 JS_PUBLIC_API(void)
5671 JS_ReportErrorNumberLatin1(JSContext* cx, JSErrorCallback errorCallback,
5672                            void* userRef, const unsigned errorNumber, ...)
5673 {
5674     va_list ap;
5675     va_start(ap, errorNumber);
5676     JS_ReportErrorNumberLatin1VA(cx, errorCallback, userRef, errorNumber, ap);
5677     va_end(ap);
5678 }
5679 
5680 JS_PUBLIC_API(void)
5681 JS_ReportErrorNumberLatin1VA(JSContext* cx, JSErrorCallback errorCallback,
5682                              void* userRef, const unsigned errorNumber,
5683                              va_list ap)
5684 {
5685     AssertHeapIsIdle(cx);
5686     ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
5687                         errorNumber, ArgumentsAreLatin1, ap);
5688 }
5689 
5690 JS_PUBLIC_API(void)
5691 JS_ReportErrorNumberUTF8(JSContext* cx, JSErrorCallback errorCallback,
5692                            void* userRef, const unsigned errorNumber, ...)
5693 {
5694     va_list ap;
5695     va_start(ap, errorNumber);
5696     JS_ReportErrorNumberUTF8VA(cx, errorCallback, userRef, errorNumber, ap);
5697     va_end(ap);
5698 }
5699 
5700 JS_PUBLIC_API(void)
5701 JS_ReportErrorNumberUTF8VA(JSContext* cx, JSErrorCallback errorCallback,
5702                            void* userRef, const unsigned errorNumber,
5703                            va_list ap)
5704 {
5705     AssertHeapIsIdle(cx);
5706     ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
5707                         errorNumber, ArgumentsAreUTF8, ap);
5708 }
5709 
5710 JS_PUBLIC_API(void)
5711 JS_ReportErrorNumberUC(JSContext* cx, JSErrorCallback errorCallback,
5712                        void* userRef, const unsigned errorNumber, ...)
5713 {
5714     va_list ap;
5715 
5716     AssertHeapIsIdle(cx);
5717     va_start(ap, errorNumber);
5718     ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
5719                         errorNumber, ArgumentsAreUnicode, ap);
5720     va_end(ap);
5721 }
5722 
5723 JS_PUBLIC_API(void)
5724 JS_ReportErrorNumberUCArray(JSContext* cx, JSErrorCallback errorCallback,
5725                             void* userRef, const unsigned errorNumber,
5726                             const char16_t** args)
5727 {
5728     AssertHeapIsIdle(cx);
5729     ReportErrorNumberUCArray(cx, JSREPORT_ERROR, errorCallback, userRef,
5730                              errorNumber, args);
5731 }
5732 
5733 JS_PUBLIC_API(bool)
5734 JS_ReportWarningASCII(JSContext* cx, const char* format, ...)
5735 {
5736     va_list ap;
5737     bool ok;
5738 
5739     AssertHeapIsIdle(cx);
5740     va_start(ap, format);
5741     ok = ReportErrorVA(cx, JSREPORT_WARNING, format, ArgumentsAreASCII, ap);
5742     va_end(ap);
5743     return ok;
5744 }
5745 
5746 JS_PUBLIC_API(bool)
5747 JS_ReportWarningLatin1(JSContext* cx, const char* format, ...)
5748 {
5749     va_list ap;
5750     bool ok;
5751 
5752     AssertHeapIsIdle(cx);
5753     va_start(ap, format);
5754     ok = ReportErrorVA(cx, JSREPORT_WARNING, format, ArgumentsAreLatin1, ap);
5755     va_end(ap);
5756     return ok;
5757 }
5758 
5759 JS_PUBLIC_API(bool)
5760 JS_ReportWarningUTF8(JSContext* cx, const char* format, ...)
5761 {
5762     va_list ap;
5763     bool ok;
5764 
5765     AssertHeapIsIdle(cx);
5766     va_start(ap, format);
5767     ok = ReportErrorVA(cx, JSREPORT_WARNING, format, ArgumentsAreUTF8, ap);
5768     va_end(ap);
5769     return ok;
5770 }
5771 
5772 JS_PUBLIC_API(bool)
5773 JS_ReportErrorFlagsAndNumberASCII(JSContext* cx, unsigned flags,
5774                                   JSErrorCallback errorCallback, void* userRef,
5775                                   const unsigned errorNumber, ...)
5776 {
5777     va_list ap;
5778     bool ok;
5779 
5780     AssertHeapIsIdle(cx);
5781     va_start(ap, errorNumber);
5782     ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef,
5783                              errorNumber, ArgumentsAreASCII, ap);
5784     va_end(ap);
5785     return ok;
5786 }
5787 
5788 JS_PUBLIC_API(bool)
5789 JS_ReportErrorFlagsAndNumberLatin1(JSContext* cx, unsigned flags,
5790                                    JSErrorCallback errorCallback, void* userRef,
5791                                    const unsigned errorNumber, ...)
5792 {
5793     va_list ap;
5794     bool ok;
5795 
5796     AssertHeapIsIdle(cx);
5797     va_start(ap, errorNumber);
5798     ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef,
5799                              errorNumber, ArgumentsAreLatin1, ap);
5800     va_end(ap);
5801     return ok;
5802 }
5803 
5804 JS_PUBLIC_API(bool)
5805 JS_ReportErrorFlagsAndNumberUTF8(JSContext* cx, unsigned flags,
5806                                  JSErrorCallback errorCallback, void* userRef,
5807                                  const unsigned errorNumber, ...)
5808 {
5809     va_list ap;
5810     bool ok;
5811 
5812     AssertHeapIsIdle(cx);
5813     va_start(ap, errorNumber);
5814     ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef,
5815                              errorNumber, ArgumentsAreUTF8, ap);
5816     va_end(ap);
5817     return ok;
5818 }
5819 
5820 JS_PUBLIC_API(bool)
5821 JS_ReportErrorFlagsAndNumberUC(JSContext* cx, unsigned flags,
5822                                JSErrorCallback errorCallback, void* userRef,
5823                                const unsigned errorNumber, ...)
5824 {
5825     va_list ap;
5826     bool ok;
5827 
5828     AssertHeapIsIdle(cx);
5829     va_start(ap, errorNumber);
5830     ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef,
5831                              errorNumber, ArgumentsAreUnicode, ap);
5832     va_end(ap);
5833     return ok;
5834 }
5835 
5836 JS_PUBLIC_API(void)
5837 JS_ReportOutOfMemory(JSContext* cx)
5838 {
5839     ReportOutOfMemory(cx);
5840 }
5841 
5842 JS_PUBLIC_API(void)
5843 JS_ReportAllocationOverflow(JSContext* cx)
5844 {
5845     ReportAllocationOverflow(cx);
5846 }
5847 
5848 JS_PUBLIC_API(JS::WarningReporter)
5849 JS::GetWarningReporter(JSContext* cx)
5850 {
5851     return cx->warningReporter;
5852 }
5853 
5854 JS_PUBLIC_API(JS::WarningReporter)
5855 JS::SetWarningReporter(JSContext* cx, JS::WarningReporter reporter)
5856 {
5857     WarningReporter older = cx->warningReporter;
5858     cx->warningReporter = reporter;
5859     return older;
5860 }
5861 
5862 /************************************************************************/
5863 
5864 /*
5865  * Dates.
5866  */
5867 JS_PUBLIC_API(JSObject*)
5868 JS_NewDateObject(JSContext* cx, int year, int mon, int mday, int hour, int min, int sec)
5869 {
5870     AssertHeapIsIdle(cx);
5871     CHECK_REQUEST(cx);
5872     return NewDateObject(cx, year, mon, mday, hour, min, sec);
5873 }
5874 
5875 JS_PUBLIC_API(JSObject*)
5876 JS::NewDateObject(JSContext* cx, JS::ClippedTime time)
5877 {
5878     AssertHeapIsIdle(cx);
5879     CHECK_REQUEST(cx);
5880     return NewDateObjectMsec(cx, time);
5881 }
5882 
5883 JS_PUBLIC_API(bool)
5884 JS_ObjectIsDate(JSContext* cx, HandleObject obj, bool* isDate)
5885 {
5886     assertSameCompartment(cx, obj);
5887 
5888     ESClass cls;
5889     if (!GetBuiltinClass(cx, obj, &cls))
5890         return false;
5891 
5892     *isDate = cls == ESClass::Date;
5893     return true;
5894 }
5895 
5896 /************************************************************************/
5897 
5898 /*
5899  * Regular Expressions.
5900  */
5901 JS_PUBLIC_API(JSObject*)
5902 JS_NewRegExpObject(JSContext* cx, const char* bytes, size_t length, unsigned flags)
5903 {
5904     AssertHeapIsIdle(cx);
5905     CHECK_REQUEST(cx);
5906     ScopedJSFreePtr<char16_t> chars(InflateString(cx, bytes, &length));
5907     if (!chars)
5908         return nullptr;
5909 
5910     RegExpObject* reobj = RegExpObject::create(cx, chars, length,
5911                                                RegExpFlag(flags), nullptr, cx->tempLifoAlloc());
5912     return reobj;
5913 }
5914 
5915 JS_PUBLIC_API(JSObject*)
5916 JS_NewUCRegExpObject(JSContext* cx, const char16_t* chars, size_t length, unsigned flags)
5917 {
5918     AssertHeapIsIdle(cx);
5919     CHECK_REQUEST(cx);
5920     return RegExpObject::create(cx, chars, length,
5921                                 RegExpFlag(flags), nullptr, cx->tempLifoAlloc());
5922 }
5923 
5924 JS_PUBLIC_API(bool)
5925 JS_SetRegExpInput(JSContext* cx, HandleObject obj, HandleString input)
5926 {
5927     AssertHeapIsIdle(cx);
5928     CHECK_REQUEST(cx);
5929     assertSameCompartment(cx, input);
5930 
5931     RegExpStatics* res = obj->as<GlobalObject>().getRegExpStatics(cx);
5932     if (!res)
5933         return false;
5934 
5935     res->reset(cx, input);
5936     return true;
5937 }
5938 
5939 JS_PUBLIC_API(bool)
5940 JS_ClearRegExpStatics(JSContext* cx, HandleObject obj)
5941 {
5942     AssertHeapIsIdle(cx);
5943     CHECK_REQUEST(cx);
5944     MOZ_ASSERT(obj);
5945 
5946     RegExpStatics* res = obj->as<GlobalObject>().getRegExpStatics(cx);
5947     if (!res)
5948         return false;
5949 
5950     res->clear();
5951     return true;
5952 }
5953 
5954 JS_PUBLIC_API(bool)
5955 JS_ExecuteRegExp(JSContext* cx, HandleObject obj, HandleObject reobj, char16_t* chars,
5956                  size_t length, size_t* indexp, bool test, MutableHandleValue rval)
5957 {
5958     AssertHeapIsIdle(cx);
5959     CHECK_REQUEST(cx);
5960 
5961     RegExpStatics* res = obj->as<GlobalObject>().getRegExpStatics(cx);
5962     if (!res)
5963         return false;
5964 
5965     RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
5966     if (!input)
5967         return false;
5968 
5969     return ExecuteRegExpLegacy(cx, res, reobj->as<RegExpObject>(), input, indexp, test, rval);
5970 }
5971 
5972 JS_PUBLIC_API(bool)
5973 JS_ExecuteRegExpNoStatics(JSContext* cx, HandleObject obj, char16_t* chars, size_t length,
5974                           size_t* indexp, bool test, MutableHandleValue rval)
5975 {
5976     AssertHeapIsIdle(cx);
5977     CHECK_REQUEST(cx);
5978 
5979     RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
5980     if (!input)
5981         return false;
5982 
5983     return ExecuteRegExpLegacy(cx, nullptr, obj->as<RegExpObject>(), input, indexp, test,
5984                                rval);
5985 }
5986 
5987 JS_PUBLIC_API(bool)
5988 JS_ObjectIsRegExp(JSContext* cx, HandleObject obj, bool* isRegExp)
5989 {
5990     assertSameCompartment(cx, obj);
5991 
5992     ESClass cls;
5993     if (!GetBuiltinClass(cx, obj, &cls))
5994         return false;
5995 
5996     *isRegExp = cls == ESClass::RegExp;
5997     return true;
5998 }
5999 
6000 JS_PUBLIC_API(unsigned)
6001 JS_GetRegExpFlags(JSContext* cx, HandleObject obj)
6002 {
6003     AssertHeapIsIdle(cx);
6004     CHECK_REQUEST(cx);
6005 
6006     RegExpGuard shared(cx);
6007     if (!RegExpToShared(cx, obj, &shared))
6008         return false;
6009     return shared.re()->getFlags();
6010 }
6011 
6012 JS_PUBLIC_API(JSString*)
6013 JS_GetRegExpSource(JSContext* cx, HandleObject obj)
6014 {
6015     AssertHeapIsIdle(cx);
6016     CHECK_REQUEST(cx);
6017 
6018     RegExpGuard shared(cx);
6019     if (!RegExpToShared(cx, obj, &shared))
6020         return nullptr;
6021     return shared.re()->getSource();
6022 }
6023 
6024 /************************************************************************/
6025 
6026 JS_PUBLIC_API(bool)
6027 JS_SetDefaultLocale(JSContext* cx, const char* locale)
6028 {
6029     AssertHeapIsIdle(cx);
6030     return cx->setDefaultLocale(locale);
6031 }
6032 
6033 JS_PUBLIC_API(UniqueChars)
6034 JS_GetDefaultLocale(JSContext* cx)
6035 {
6036     AssertHeapIsIdle(cx);
6037     if (const char* locale = cx->getDefaultLocale())
6038         return UniqueChars(JS_strdup(cx, locale));
6039 
6040     return nullptr;
6041 }
6042 
6043 JS_PUBLIC_API(void)
6044 JS_ResetDefaultLocale(JSContext* cx)
6045 {
6046     AssertHeapIsIdle(cx);
6047     cx->resetDefaultLocale();
6048 }
6049 
6050 JS_PUBLIC_API(void)
6051 JS_SetLocaleCallbacks(JSContext* cx, const JSLocaleCallbacks* callbacks)
6052 {
6053     AssertHeapIsIdle(cx);
6054     cx->localeCallbacks = callbacks;
6055 }
6056 
6057 JS_PUBLIC_API(const JSLocaleCallbacks*)
6058 JS_GetLocaleCallbacks(JSContext* cx)
6059 {
6060     /* This function can be called by a finalizer. */
6061     return cx->localeCallbacks;
6062 }
6063 
6064 /************************************************************************/
6065 
6066 JS_PUBLIC_API(bool)
6067 JS_IsExceptionPending(JSContext* cx)
6068 {
6069     /* This function can be called by a finalizer. */
6070     return (bool) cx->isExceptionPending();
6071 }
6072 
6073 JS_PUBLIC_API(bool)
6074 JS_GetPendingException(JSContext* cx, MutableHandleValue vp)
6075 {
6076     AssertHeapIsIdle(cx);
6077     CHECK_REQUEST(cx);
6078     if (!cx->isExceptionPending())
6079         return false;
6080     return cx->getPendingException(vp);
6081 }
6082 
6083 JS_PUBLIC_API(void)
6084 JS_SetPendingException(JSContext* cx, HandleValue value)
6085 {
6086     AssertHeapIsIdle(cx);
6087     CHECK_REQUEST(cx);
6088     assertSameCompartment(cx, value);
6089     cx->setPendingException(value);
6090 }
6091 
6092 JS_PUBLIC_API(void)
6093 JS_ClearPendingException(JSContext* cx)
6094 {
6095     AssertHeapIsIdle(cx);
6096     cx->clearPendingException();
6097 }
6098 
6099 JS::AutoSaveExceptionState::AutoSaveExceptionState(JSContext* cx)
6100   : context(cx),
6101     wasPropagatingForcedReturn(cx->propagatingForcedReturn_),
6102     wasOverRecursed(cx->overRecursed_),
6103     wasThrowing(cx->throwing),
6104     exceptionValue(cx)
6105 {
6106     AssertHeapIsIdle(cx);
6107     CHECK_REQUEST(cx);
6108     if (wasPropagatingForcedReturn)
6109         cx->clearPropagatingForcedReturn();
6110     if (wasOverRecursed)
6111         cx->overRecursed_ = false;
6112     if (wasThrowing) {
6113         exceptionValue = cx->unwrappedException_;
6114         cx->clearPendingException();
6115     }
6116 }
6117 
6118 void
6119 JS::AutoSaveExceptionState::restore()
6120 {
6121     context->propagatingForcedReturn_ = wasPropagatingForcedReturn;
6122     context->overRecursed_ = wasOverRecursed;
6123     context->throwing = wasThrowing;
6124     context->unwrappedException_ = exceptionValue;
6125     drop();
6126 }
6127 
6128 JS::AutoSaveExceptionState::~AutoSaveExceptionState()
6129 {
6130     if (!context->isExceptionPending()) {
6131         if (wasPropagatingForcedReturn)
6132             context->setPropagatingForcedReturn();
6133         if (wasThrowing) {
6134             context->overRecursed_ = wasOverRecursed;
6135             context->throwing = true;
6136             context->unwrappedException_ = exceptionValue;
6137         }
6138     }
6139 }
6140 
6141 struct JSExceptionState {
6142     explicit JSExceptionState(JSContext* cx) : exception(cx) {}
6143     bool throwing;
6144     PersistentRootedValue exception;
6145 };
6146 
6147 JS_PUBLIC_API(JSExceptionState*)
6148 JS_SaveExceptionState(JSContext* cx)
6149 {
6150     JSExceptionState* state;
6151 
6152     AssertHeapIsIdle(cx);
6153     CHECK_REQUEST(cx);
6154     state = cx->new_<JSExceptionState>(cx);
6155     if (state)
6156         state->throwing = JS_GetPendingException(cx, &state->exception);
6157     return state;
6158 }
6159 
6160 JS_PUBLIC_API(void)
6161 JS_RestoreExceptionState(JSContext* cx, JSExceptionState* state)
6162 {
6163     AssertHeapIsIdle(cx);
6164     CHECK_REQUEST(cx);
6165     if (state) {
6166         if (state->throwing)
6167             JS_SetPendingException(cx, state->exception);
6168         else
6169             JS_ClearPendingException(cx);
6170         JS_DropExceptionState(cx, state);
6171     }
6172 }
6173 
6174 JS_PUBLIC_API(void)
6175 JS_DropExceptionState(JSContext* cx, JSExceptionState* state)
6176 {
6177     AssertHeapIsIdle(cx);
6178     CHECK_REQUEST(cx);
6179     js_delete(state);
6180 }
6181 
6182 JS_PUBLIC_API(JSErrorReport*)
6183 JS_ErrorFromException(JSContext* cx, HandleObject obj)
6184 {
6185     AssertHeapIsIdle(cx);
6186     CHECK_REQUEST(cx);
6187     assertSameCompartment(cx, obj);
6188     return ErrorFromException(cx, obj);
6189 }
6190 
6191 void
6192 JSErrorReport::initBorrowedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg,
6193                                    size_t tokenOffsetArg)
6194 {
6195     MOZ_ASSERT(linebufArg);
6196     MOZ_ASSERT(tokenOffsetArg <= linebufLengthArg);
6197     MOZ_ASSERT(linebufArg[linebufLengthArg] == '\0');
6198 
6199     linebuf_ = linebufArg;
6200     linebufLength_ = linebufLengthArg;
6201     tokenOffset_ = tokenOffsetArg;
6202 }
6203 
6204 void
6205 JSErrorReport::freeLinebuf()
6206 {
6207     if (ownsLinebuf_ && linebuf_) {
6208         js_free((void*)linebuf_);
6209         ownsLinebuf_ = false;
6210     }
6211     linebuf_ = nullptr;
6212 }
6213 
6214 JSString*
6215 JSErrorReport::newMessageString(JSContext* cx)
6216 {
6217     if (!message_)
6218         return cx->runtime()->emptyString;
6219 
6220     return JS_NewStringCopyUTF8Z(cx, message_);
6221 }
6222 
6223 void
6224 JSErrorReport::freeMessage()
6225 {
6226     if (ownsMessage_) {
6227         js_free((void*)message_.get());
6228         ownsMessage_ = false;
6229     }
6230     message_ = JS::ConstUTF8CharsZ();
6231 }
6232 
6233 JS_PUBLIC_API(bool)
6234 JS_ThrowStopIteration(JSContext* cx)
6235 {
6236     AssertHeapIsIdle(cx);
6237     return ThrowStopIteration(cx);
6238 }
6239 
6240 JS_PUBLIC_API(bool)
6241 JS_IsStopIteration(const Value& v)
6242 {
6243     return v.isObject() && v.toObject().is<StopIterationObject>();
6244 }
6245 
6246 extern MOZ_NEVER_INLINE JS_PUBLIC_API(void)
6247 JS_AbortIfWrongThread(JSContext* cx)
6248 {
6249     if (!CurrentThreadCanAccessRuntime(cx))
6250         MOZ_CRASH();
6251     if (!js::TlsPerThreadData.get()->associatedWith(cx))
6252         MOZ_CRASH();
6253 }
6254 
6255 #ifdef JS_GC_ZEAL
6256 JS_PUBLIC_API(void)
6257 JS_GetGCZealBits(JSContext* cx, uint32_t* zealBits, uint32_t* frequency, uint32_t* nextScheduled)
6258 {
6259     cx->runtime()->gc.getZealBits(zealBits, frequency, nextScheduled);
6260 }
6261 
6262 JS_PUBLIC_API(void)
6263 JS_SetGCZeal(JSContext* cx, uint8_t zeal, uint32_t frequency)
6264 {
6265     cx->gc.setZeal(zeal, frequency);
6266 }
6267 
6268 JS_PUBLIC_API(void)
6269 JS_ScheduleGC(JSContext* cx, uint32_t count)
6270 {
6271     cx->runtime()->gc.setNextScheduled(count);
6272 }
6273 #endif
6274 
6275 JS_PUBLIC_API(void)
6276 JS_SetParallelParsingEnabled(JSContext* cx, bool enabled)
6277 {
6278     cx->setParallelParsingEnabled(enabled);
6279 }
6280 
6281 JS_PUBLIC_API(void)
6282 JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled)
6283 {
6284     cx->setOffthreadIonCompilationEnabled(enabled);
6285 }
6286 
6287 JS_PUBLIC_API(void)
6288 JS_SetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t value)
6289 {
6290     JSRuntime* rt = cx->runtime();
6291     switch (opt) {
6292       case JSJITCOMPILER_BASELINE_WARMUP_TRIGGER:
6293         if (value == uint32_t(-1)) {
6294             jit::DefaultJitOptions defaultValues;
6295             value = defaultValues.baselineWarmUpThreshold;
6296         }
6297         jit::JitOptions.baselineWarmUpThreshold = value;
6298         break;
6299       case JSJITCOMPILER_ION_WARMUP_TRIGGER:
6300         if (value == uint32_t(-1)) {
6301             jit::JitOptions.resetCompilerWarmUpThreshold();
6302             break;
6303         }
6304         jit::JitOptions.setCompilerWarmUpThreshold(value);
6305         if (value == 0)
6306             jit::JitOptions.setEagerCompilation();
6307         break;
6308       case JSJITCOMPILER_ION_GVN_ENABLE:
6309         if (value == 0) {
6310             jit::JitOptions.enableGvn(false);
6311             JitSpew(js::jit::JitSpew_IonScripts, "Disable ion's GVN");
6312         } else {
6313             jit::JitOptions.enableGvn(true);
6314             JitSpew(js::jit::JitSpew_IonScripts, "Enable ion's GVN");
6315         }
6316         break;
6317       case JSJITCOMPILER_ION_FORCE_IC:
6318         if (value == 0) {
6319             jit::JitOptions.forceInlineCaches = false;
6320             JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Enable non-IC optimizations.");
6321         } else {
6322             jit::JitOptions.forceInlineCaches = true;
6323             JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Disable non-IC optimizations.");
6324         }
6325         break;
6326       case JSJITCOMPILER_ION_CHECK_RANGE_ANALYSIS:
6327         if (value == 0) {
6328             jit::JitOptions.checkRangeAnalysis = false;
6329             JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Enable range analysis checks.");
6330         } else {
6331             jit::JitOptions.checkRangeAnalysis = true;
6332             JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Disable range analysis checks.");
6333         }
6334         break;
6335       case JSJITCOMPILER_ION_ENABLE:
6336         if (value == 1) {
6337             JS::ContextOptionsRef(cx).setIon(true);
6338             JitSpew(js::jit::JitSpew_IonScripts, "Enable ion");
6339         } else if (value == 0) {
6340             JS::ContextOptionsRef(cx).setIon(false);
6341             JitSpew(js::jit::JitSpew_IonScripts, "Disable ion");
6342         }
6343         break;
6344       case JSJITCOMPILER_BASELINE_ENABLE:
6345         if (value == 1) {
6346             JS::ContextOptionsRef(cx).setBaseline(true);
6347             ReleaseAllJITCode(rt->defaultFreeOp());
6348             JitSpew(js::jit::JitSpew_BaselineScripts, "Enable baseline");
6349         } else if (value == 0) {
6350             JS::ContextOptionsRef(cx).setBaseline(false);
6351             ReleaseAllJITCode(rt->defaultFreeOp());
6352             JitSpew(js::jit::JitSpew_BaselineScripts, "Disable baseline");
6353         }
6354         break;
6355       case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE:
6356         if (value == 1) {
6357             rt->setOffthreadIonCompilationEnabled(true);
6358             JitSpew(js::jit::JitSpew_IonScripts, "Enable offthread compilation");
6359         } else if (value == 0) {
6360             rt->setOffthreadIonCompilationEnabled(false);
6361             JitSpew(js::jit::JitSpew_IonScripts, "Disable offthread compilation");
6362         }
6363         break;
6364       case JSJITCOMPILER_JUMP_THRESHOLD:
6365         if (value == uint32_t(-1)) {
6366             jit::DefaultJitOptions defaultValues;
6367             value = defaultValues.jumpThreshold;
6368         }
6369         jit::JitOptions.jumpThreshold = value;
6370         break;
6371       case JSJITCOMPILER_ASMJS_ATOMICS_ENABLE:
6372         jit::JitOptions.asmJSAtomicsEnable = !!value;
6373         break;
6374       case JSJITCOMPILER_WASM_TEST_MODE:
6375         jit::JitOptions.wasmTestMode = !!value;
6376         break;
6377       case JSJITCOMPILER_WASM_FOLD_OFFSETS:
6378         jit::JitOptions.wasmFoldOffsets = !!value;
6379         break;
6380       case JSJITCOMPILER_ION_INTERRUPT_WITHOUT_SIGNAL:
6381         jit::JitOptions.ionInterruptWithoutSignals = !!value;
6382         break;
6383       default:
6384         break;
6385     }
6386 }
6387 
6388 JS_PUBLIC_API(bool)
6389 JS_GetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t* valueOut)
6390 {
6391     MOZ_ASSERT(valueOut);
6392 #ifndef JS_CODEGEN_NONE
6393     JSRuntime* rt = cx->runtime();
6394     switch (opt) {
6395       case JSJITCOMPILER_BASELINE_WARMUP_TRIGGER:
6396         *valueOut = jit::JitOptions.baselineWarmUpThreshold;
6397         break;
6398       case JSJITCOMPILER_ION_WARMUP_TRIGGER:
6399         *valueOut = jit::JitOptions.forcedDefaultIonWarmUpThreshold.isSome()
6400                   ? jit::JitOptions.forcedDefaultIonWarmUpThreshold.ref()
6401                   : jit::OptimizationInfo::CompilerWarmupThreshold;
6402         break;
6403       case JSJITCOMPILER_ION_FORCE_IC:
6404         *valueOut = jit::JitOptions.forceInlineCaches;
6405         break;
6406       case JSJITCOMPILER_ION_CHECK_RANGE_ANALYSIS:
6407         *valueOut = jit::JitOptions.checkRangeAnalysis;
6408         break;
6409       case JSJITCOMPILER_ION_ENABLE:
6410         *valueOut = JS::ContextOptionsRef(cx).ion();
6411         break;
6412       case JSJITCOMPILER_BASELINE_ENABLE:
6413         *valueOut = JS::ContextOptionsRef(cx).baseline();
6414         break;
6415       case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE:
6416         *valueOut = rt->canUseOffthreadIonCompilation();
6417         break;
6418       case JSJITCOMPILER_ASMJS_ATOMICS_ENABLE:
6419         *valueOut = jit::JitOptions.asmJSAtomicsEnable ? 1 : 0;
6420         break;
6421       case JSJITCOMPILER_WASM_TEST_MODE:
6422         *valueOut = jit::JitOptions.wasmTestMode ? 1 : 0;
6423         break;
6424       case JSJITCOMPILER_WASM_FOLD_OFFSETS:
6425         *valueOut = jit::JitOptions.wasmFoldOffsets ? 1 : 0;
6426         break;
6427       case JSJITCOMPILER_ION_INTERRUPT_WITHOUT_SIGNAL:
6428         *valueOut = jit::JitOptions.ionInterruptWithoutSignals ? 1 : 0;
6429         break;
6430       default:
6431         return false;
6432     }
6433 #else
6434     *valueOut = 0;
6435 #endif
6436     return true;
6437 }
6438 
6439 /************************************************************************/
6440 
6441 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN)
6442 
6443 #include "jswin.h"
6444 
6445 /*
6446  * Initialization routine for the JS DLL.
6447  */
6448 BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
6449 {
6450     return TRUE;
6451 }
6452 
6453 #endif
6454 
6455 JS_PUBLIC_API(bool)
6456 JS_IndexToId(JSContext* cx, uint32_t index, MutableHandleId id)
6457 {
6458     return IndexToId(cx, index, id);
6459 }
6460 
6461 JS_PUBLIC_API(bool)
6462 JS_CharsToId(JSContext* cx, JS::TwoByteChars chars, MutableHandleId idp)
6463 {
6464     RootedAtom atom(cx, AtomizeChars(cx, chars.begin().get(), chars.length()));
6465     if (!atom)
6466         return false;
6467 #ifdef DEBUG
6468     uint32_t dummy;
6469     MOZ_ASSERT(!atom->isIndex(&dummy), "API misuse: |chars| must not encode an index");
6470 #endif
6471     idp.set(AtomToId(atom));
6472     return true;
6473 }
6474 
6475 JS_PUBLIC_API(bool)
6476 JS_IsIdentifier(JSContext* cx, HandleString str, bool* isIdentifier)
6477 {
6478     assertSameCompartment(cx, str);
6479 
6480     JSLinearString* linearStr = str->ensureLinear(cx);
6481     if (!linearStr)
6482         return false;
6483 
6484     *isIdentifier = js::frontend::IsIdentifier(linearStr);
6485     return true;
6486 }
6487 
6488 JS_PUBLIC_API(bool)
6489 JS_IsIdentifier(const char16_t* chars, size_t length)
6490 {
6491     return js::frontend::IsIdentifier(chars, length);
6492 }
6493 
6494 namespace JS {
6495 
6496 void AutoFilename::reset()
6497 {
6498     if (ss_) {
6499         ss_->decref();
6500         ss_ = nullptr;
6501     }
6502     if (filename_.is<const char*>())
6503         filename_.as<const char*>() = nullptr;
6504     else
6505         filename_.as<UniqueChars>().reset();
6506 }
6507 
6508 void AutoFilename::setScriptSource(js::ScriptSource* p)
6509 {
6510     MOZ_ASSERT(!ss_);
6511     MOZ_ASSERT(!get());
6512     ss_ = p;
6513     if (p) {
6514         p->incref();
6515         setUnowned(p->filename());
6516     }
6517 }
6518 
6519 void AutoFilename::setUnowned(const char* filename)
6520 {
6521     MOZ_ASSERT(!get());
6522     filename_.as<const char*>() = filename ? filename : "";
6523 }
6524 
6525 void AutoFilename::setOwned(UniqueChars&& filename)
6526 {
6527     MOZ_ASSERT(!get());
6528     filename_ = AsVariant(Move(filename));
6529 }
6530 
6531 const char* AutoFilename::get() const
6532 {
6533     if (filename_.is<const char*>())
6534         return filename_.as<const char*>();
6535     return filename_.as<UniqueChars>().get();
6536 }
6537 
6538 JS_PUBLIC_API(bool)
6539 DescribeScriptedCaller(JSContext* cx, AutoFilename* filename, unsigned* lineno,
6540                        unsigned* column)
6541 {
6542     if (filename)
6543         filename->reset();
6544     if (lineno)
6545         *lineno = 0;
6546     if (column)
6547         *column = 0;
6548 
6549     if (!cx->compartment())
6550         return false;
6551 
6552     NonBuiltinFrameIter i(cx, cx->compartment()->principals());
6553     if (i.done())
6554         return false;
6555 
6556     // If the caller is hidden, the embedding wants us to return false here so
6557     // that it can check its own stack (see HideScriptedCaller).
6558     if (i.activation()->scriptedCallerIsHidden())
6559         return false;
6560 
6561     if (filename) {
6562         if (i.isWasm()) {
6563             // For Wasm, copy out the filename, there is no script source.
6564             UniqueChars copy = DuplicateString(i.filename() ? i.filename() : "");
6565             if (!copy)
6566                 filename->setUnowned("out of memory");
6567             else
6568                 filename->setOwned(Move(copy));
6569         } else {
6570             // All other frames have a script source to read the filename from.
6571             filename->setScriptSource(i.scriptSource());
6572         }
6573     }
6574 
6575     if (lineno)
6576         *lineno = i.computeLine(column);
6577     else if (column)
6578         i.computeLine(column);
6579 
6580     return true;
6581 }
6582 
6583 // Fast path to get the activation to use for GetScriptedCallerGlobal. If this
6584 // returns false, the fast path didn't work out and the caller has to use the
6585 // (much slower) NonBuiltinFrameIter path.
6586 //
6587 // The optimization here is that we skip Ion-inlined frames and only look at
6588 // 'outer' frames. That's fine: each activation is tied to a single compartment,
6589 // so if an activation contains at least one non-self-hosted frame, we can use
6590 // the activation's global for GetScriptedCallerGlobal. If, however, all 'outer'
6591 // frames are self-hosted, it's possible Ion inlined a non-self-hosted script,
6592 // so we must return false and use the slower path.
6593 static bool
6594 GetScriptedCallerActivationFast(JSContext* cx, Activation** activation)
6595 {
6596     ActivationIterator activationIter(cx->runtime());
6597 
6598     if (activationIter.done()) {
6599         *activation = nullptr;
6600         return true;
6601     }
6602 
6603     *activation = activationIter.activation();
6604 
6605     if (activationIter->isJit()) {
6606         for (jit::JitFrameIterator iter(activationIter); !iter.done(); ++iter) {
6607             if (iter.isScripted() && !iter.script()->selfHosted())
6608                 return true;
6609         }
6610     } else if (activationIter->isInterpreter()) {
6611         for (InterpreterFrameIterator iter((*activation)->asInterpreter()); !iter.done(); ++iter) {
6612             if (!iter.frame()->script()->selfHosted())
6613                 return true;
6614         }
6615     }
6616 
6617     return false;
6618 }
6619 
6620 JS_PUBLIC_API(JSObject*)
6621 GetScriptedCallerGlobal(JSContext* cx)
6622 {
6623     Activation* activation;
6624 
6625     if (GetScriptedCallerActivationFast(cx, &activation)) {
6626         if (!activation)
6627             return nullptr;
6628     } else {
6629         NonBuiltinFrameIter i(cx);
6630         if (i.done())
6631             return nullptr;
6632         activation = i.activation();
6633     }
6634 
6635     // If the caller is hidden, the embedding wants us to return null here so
6636     // that it can check its own stack (see HideScriptedCaller).
6637     if (activation->scriptedCallerIsHidden())
6638         return nullptr;
6639 
6640     GlobalObject* global = activation->compartment()->maybeGlobal();
6641 
6642     // Noone should be running code in the atoms compartment or running code in
6643     // a compartment without any live objects, so there should definitely be a
6644     // live global.
6645     MOZ_ASSERT(global);
6646 
6647     return global;
6648 }
6649 
6650 JS_PUBLIC_API(void)
6651 HideScriptedCaller(JSContext* cx)
6652 {
6653     MOZ_ASSERT(cx);
6654 
6655     // If there's no accessible activation on the stack, we'll return null from
6656     // DescribeScriptedCaller anyway, so there's no need to annotate anything.
6657     Activation* act = cx->runtime()->activation();
6658     if (!act)
6659         return;
6660     act->hideScriptedCaller();
6661 }
6662 
6663 JS_PUBLIC_API(void)
6664 UnhideScriptedCaller(JSContext* cx)
6665 {
6666     Activation* act = cx->runtime()->activation();
6667     if (!act)
6668         return;
6669     act->unhideScriptedCaller();
6670 }
6671 
6672 } /* namespace JS */
6673 
6674 AutoGCRooter::AutoGCRooter(JSContext* cx, ptrdiff_t tag)
6675   : AutoGCRooter(JS::RootingContext::get(cx), tag)
6676 {}
6677 
6678 AutoGCRooter::AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag)
6679   : down(cx->roots.autoGCRooters_),
6680     tag_(tag),
6681     stackTop(&cx->roots.autoGCRooters_)
6682 {
6683     MOZ_ASSERT(this != *stackTop);
6684     *stackTop = this;
6685 }
6686 
6687 #ifdef JS_DEBUG
6688 JS_PUBLIC_API(void)
6689 JS::detail::AssertArgumentsAreSane(JSContext* cx, HandleValue value)
6690 {
6691     AssertHeapIsIdle(cx);
6692     CHECK_REQUEST(cx);
6693     assertSameCompartment(cx, value);
6694 }
6695 #endif /* JS_DEBUG */
6696 
6697 JS_PUBLIC_API(JS::TranscodeResult)
6698 JS::EncodeScript(JSContext* cx, TranscodeBuffer& buffer, HandleScript scriptArg)
6699 {
6700     XDREncoder encoder(cx, buffer, buffer.length());
6701     RootedScript script(cx, scriptArg);
6702     if (!encoder.codeScript(&script))
6703         buffer.clearAndFree();
6704     MOZ_ASSERT(!buffer.empty() == (encoder.resultCode() == TranscodeResult_Ok));
6705     return encoder.resultCode();
6706 }
6707 
6708 JS_PUBLIC_API(JS::TranscodeResult)
6709 JS::EncodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, HandleObject funobjArg)
6710 {
6711     XDREncoder encoder(cx, buffer, buffer.length());
6712     RootedFunction funobj(cx, &funobjArg->as<JSFunction>());
6713     if (!encoder.codeFunction(&funobj))
6714         buffer.clearAndFree();
6715     MOZ_ASSERT(!buffer.empty() == (encoder.resultCode() == TranscodeResult_Ok));
6716     return encoder.resultCode();
6717 }
6718 
6719 JS_PUBLIC_API(JS::TranscodeResult)
6720 JS::DecodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleScript scriptp,
6721                  size_t cursorIndex)
6722 {
6723     XDRDecoder decoder(cx, buffer, cursorIndex);
6724     decoder.codeScript(scriptp);
6725     MOZ_ASSERT(bool(scriptp) == (decoder.resultCode() == TranscodeResult_Ok));
6726     return decoder.resultCode();
6727 }
6728 
6729 JS_PUBLIC_API(JS::TranscodeResult)
6730 JS::DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer,
6731                               JS::MutableHandleFunction funp,
6732                               size_t cursorIndex)
6733 {
6734     XDRDecoder decoder(cx, buffer, cursorIndex);
6735     decoder.codeFunction(funp);
6736     MOZ_ASSERT(bool(funp) == (decoder.resultCode() == TranscodeResult_Ok));
6737     return decoder.resultCode();
6738 }
6739 
6740 JS_PUBLIC_API(void)
6741 JS::SetBuildIdOp(JSContext* cx, JS::BuildIdOp buildIdOp)
6742 {
6743     cx->runtime()->buildIdOp = buildIdOp;
6744 }
6745 
6746 JS_PUBLIC_API(void)
6747 JS::SetAsmJSCacheOps(JSContext* cx, const JS::AsmJSCacheOps* ops)
6748 {
6749     cx->runtime()->asmJSCacheOps = *ops;
6750 }
6751 
6752 bool
6753 JS::IsWasmModuleObject(HandleObject obj)
6754 {
6755     JSObject* unwrapped = CheckedUnwrap(obj);
6756     if (!unwrapped)
6757         return false;
6758     return unwrapped->is<WasmModuleObject>();
6759 }
6760 
6761 JS_PUBLIC_API(RefPtr<JS::WasmModule>)
6762 JS::GetWasmModule(HandleObject obj)
6763 {
6764     MOZ_ASSERT(JS::IsWasmModuleObject(obj));
6765     return &CheckedUnwrap(obj)->as<WasmModuleObject>().module();
6766 }
6767 
6768 JS_PUBLIC_API(bool)
6769 JS::CompiledWasmModuleAssumptionsMatch(PRFileDesc* compiled, JS::BuildIdCharVector&& buildId)
6770 {
6771     return wasm::CompiledModuleAssumptionsMatch(compiled, Move(buildId));
6772 }
6773 
6774 JS_PUBLIC_API(RefPtr<JS::WasmModule>)
6775 JS::DeserializeWasmModule(PRFileDesc* bytecode, PRFileDesc* maybeCompiled,
6776                           JS::BuildIdCharVector&& buildId, UniqueChars file,
6777                           unsigned line, unsigned column)
6778 {
6779     return wasm::DeserializeModule(bytecode, maybeCompiled, Move(buildId), Move(file), line, column);
6780 }
6781 
6782 char*
6783 JSAutoByteString::encodeLatin1(ExclusiveContext* cx, JSString* str)
6784 {
6785     mBytes = EncodeLatin1(cx, str);
6786     return mBytes;
6787 }
6788 
6789 JS_PUBLIC_API(void)
6790 JS::SetLargeAllocationFailureCallback(JSContext* cx, JS::LargeAllocationFailureCallback lafc,
6791                                       void* data)
6792 {
6793     cx->largeAllocationFailureCallback = lafc;
6794     cx->largeAllocationFailureCallbackData = data;
6795 }
6796 
6797 JS_PUBLIC_API(void)
6798 JS::SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data)
6799 {
6800     cx->oomCallback = cb;
6801     cx->oomCallbackData = data;
6802 }
6803 
6804 JS::FirstSubsumedFrame::FirstSubsumedFrame(JSContext* cx,
6805                                            bool ignoreSelfHostedFrames /* = true */)
6806   : JS::FirstSubsumedFrame(cx, cx->compartment()->principals(), ignoreSelfHostedFrames)
6807 { }
6808 
6809 JS_PUBLIC_API(bool)
6810 JS::CaptureCurrentStack(JSContext* cx, JS::MutableHandleObject stackp,
6811                         JS::StackCapture&& capture /* = JS::StackCapture(JS::AllFrames()) */)
6812 {
6813     AssertHeapIsIdle(cx);
6814     CHECK_REQUEST(cx);
6815     MOZ_RELEASE_ASSERT(cx->compartment());
6816 
6817     JSCompartment* compartment = cx->compartment();
6818     Rooted<SavedFrame*> frame(cx);
6819     if (!compartment->savedStacks().saveCurrentStack(cx, &frame, mozilla::Move(capture)))
6820         return false;
6821     stackp.set(frame.get());
6822     return true;
6823 }
6824 
6825 JS_PUBLIC_API(bool)
6826 JS::CopyAsyncStack(JSContext* cx, JS::HandleObject asyncStack,
6827                    JS::HandleString asyncCause, JS::MutableHandleObject stackp,
6828                    unsigned maxFrameCount)
6829 {
6830     AssertHeapIsIdle(cx);
6831     CHECK_REQUEST(cx);
6832     MOZ_RELEASE_ASSERT(cx->compartment());
6833 
6834     js::AssertObjectIsSavedFrameOrWrapper(cx, asyncStack);
6835     JSCompartment* compartment = cx->compartment();
6836     Rooted<SavedFrame*> frame(cx);
6837     if (!compartment->savedStacks().copyAsyncStack(cx, asyncStack, asyncCause,
6838                                                    &frame, maxFrameCount))
6839         return false;
6840     stackp.set(frame.get());
6841     return true;
6842 }
6843 
6844 JS_PUBLIC_API(Zone*)
6845 JS::GetObjectZone(JSObject* obj)
6846 {
6847     return obj->zone();
6848 }
6849 
6850 JS_PUBLIC_API(JS::TraceKind)
6851 JS::GCThingTraceKind(void* thing)
6852 {
6853     MOZ_ASSERT(thing);
6854     return static_cast<js::gc::Cell*>(thing)->getTraceKind();
6855 }
6856 
6857 JS_PUBLIC_API(void)
6858 js::SetStackFormat(JSContext* cx, js::StackFormat format)
6859 {
6860     cx->setStackFormat(format);
6861 }
6862 
6863 JS_PUBLIC_API(js::StackFormat)
6864 js::GetStackFormat(JSContext* cx)
6865 {
6866     return cx->stackFormat();
6867 }
6868