LCOV - code coverage report
Current view: top level - js/src - jsapi.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 960 3548 27.1 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13-14-ga5dd952