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

Generated by: LCOV version 1.13