LCOV - code coverage report
Current view: top level - js/src/vm - SelfHosting.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 489 1453 33.7 %
Date: 2017-07-14 16:53:18 Functions: 59 272 21.7 %
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             : #include "vm/SelfHosting.h"
       8             : 
       9             : #include "mozilla/ArrayUtils.h"
      10             : #include "mozilla/Casting.h"
      11             : #include "mozilla/DebugOnly.h"
      12             : #include "mozilla/Maybe.h"
      13             : 
      14             : #include "jsarray.h"
      15             : #include "jscntxt.h"
      16             : #include "jscompartment.h"
      17             : #include "jsdate.h"
      18             : #include "jsfriendapi.h"
      19             : #include "jsfun.h"
      20             : #include "jshashutil.h"
      21             : #include "jsiter.h"
      22             : #include "jsstr.h"
      23             : #include "jsweakmap.h"
      24             : #include "jswrapper.h"
      25             : #include "selfhosted.out.h"
      26             : 
      27             : #include "builtin/Intl.h"
      28             : #include "builtin/MapObject.h"
      29             : #include "builtin/ModuleObject.h"
      30             : #include "builtin/Object.h"
      31             : #include "builtin/Promise.h"
      32             : #include "builtin/Reflect.h"
      33             : #include "builtin/RegExp.h"
      34             : #include "builtin/SelfHostingDefines.h"
      35             : #include "builtin/SIMD.h"
      36             : #include "builtin/TypedObject.h"
      37             : #include "builtin/WeakSetObject.h"
      38             : #include "gc/Marking.h"
      39             : #include "gc/Policy.h"
      40             : #include "jit/AtomicOperations.h"
      41             : #include "jit/InlinableNatives.h"
      42             : #include "js/CharacterEncoding.h"
      43             : #include "js/Date.h"
      44             : #include "vm/Compression.h"
      45             : #include "vm/GeneratorObject.h"
      46             : #include "vm/Interpreter.h"
      47             : #include "vm/RegExpObject.h"
      48             : #include "vm/String.h"
      49             : #include "vm/StringBuffer.h"
      50             : #include "vm/TypedArrayObject.h"
      51             : #include "vm/WrapperObject.h"
      52             : 
      53             : #include "jsatominlines.h"
      54             : #include "jsfuninlines.h"
      55             : #include "jsobjinlines.h"
      56             : #include "jsscriptinlines.h"
      57             : 
      58             : #include "vm/BooleanObject-inl.h"
      59             : #include "vm/NativeObject-inl.h"
      60             : #include "vm/NumberObject-inl.h"
      61             : #include "vm/StringObject-inl.h"
      62             : 
      63             : using namespace js;
      64             : using namespace js::selfhosted;
      65             : 
      66             : using JS::AutoCheckCannotGC;
      67             : using mozilla::IsInRange;
      68             : using mozilla::Maybe;
      69             : using mozilla::PodMove;
      70             : using mozilla::Maybe;
      71             : 
      72             : static void
      73           0 : selfHosting_WarningReporter(JSContext* cx, JSErrorReport* report)
      74             : {
      75           0 :     MOZ_ASSERT(report);
      76           0 :     MOZ_ASSERT(JSREPORT_IS_WARNING(report->flags));
      77             : 
      78           0 :     PrintError(cx, stderr, JS::ConstUTF8CharsZ(), report, true);
      79           0 : }
      80             : 
      81             : static bool
      82        2903 : intrinsic_ToObject(JSContext* cx, unsigned argc, Value* vp)
      83             : {
      84        2903 :     CallArgs args = CallArgsFromVp(argc, vp);
      85        2903 :     JSObject* obj = ToObject(cx, args[0]);
      86        2903 :     if (!obj)
      87           0 :         return false;
      88        2903 :     args.rval().setObject(*obj);
      89        2903 :     return true;
      90             : }
      91             : 
      92             : static bool
      93        7131 : intrinsic_IsObject(JSContext* cx, unsigned argc, Value* vp)
      94             : {
      95        7131 :     CallArgs args = CallArgsFromVp(argc, vp);
      96        7131 :     Value val = args[0];
      97        7131 :     bool isObject = val.isObject();
      98        7131 :     args.rval().setBoolean(isObject);
      99        7131 :     return true;
     100             : }
     101             : 
     102             : static bool
     103         264 : intrinsic_IsArray(JSContext* cx, unsigned argc, Value* vp)
     104             : {
     105         264 :     CallArgs args = CallArgsFromVp(argc, vp);
     106         264 :     MOZ_ASSERT(args.length() == 1);
     107         528 :     RootedValue val(cx, args[0]);
     108         264 :     if (val.isObject()) {
     109         528 :         RootedObject obj(cx, &val.toObject());
     110         264 :         bool isArray = false;
     111         264 :         if (!IsArray(cx, obj, &isArray))
     112           0 :             return false;
     113         264 :         args.rval().setBoolean(isArray);
     114             :     } else {
     115           0 :         args.rval().setBoolean(false);
     116             :     }
     117         264 :     return true;
     118             : }
     119             : 
     120             : static bool
     121         151 : intrinsic_IsWrappedArrayConstructor(JSContext* cx, unsigned argc, Value* vp)
     122             : {
     123         151 :     CallArgs args = CallArgsFromVp(argc, vp);
     124         151 :     bool result = false;
     125         151 :     if (!IsWrappedArrayConstructor(cx, args[0], &result))
     126           0 :         return false;
     127         151 :     args.rval().setBoolean(result);
     128         151 :     return true;
     129             : }
     130             : 
     131             : static bool
     132        5515 : intrinsic_ToInteger(JSContext* cx, unsigned argc, Value* vp)
     133             : {
     134        5515 :     CallArgs args = CallArgsFromVp(argc, vp);
     135             :     double result;
     136        5515 :     if (!ToInteger(cx, args[0], &result))
     137           0 :         return false;
     138        5515 :     args.rval().setNumber(result);
     139        5515 :     return true;
     140             : }
     141             : 
     142             : static bool
     143         459 : intrinsic_ToString(JSContext* cx, unsigned argc, Value* vp)
     144             : {
     145         459 :     CallArgs args = CallArgsFromVp(argc, vp);
     146         459 :     JSString* str = ToString<CanGC>(cx, args[0]);
     147         459 :     if (!str)
     148           0 :         return false;
     149         459 :     args.rval().setString(str);
     150         459 :     return true;
     151             : }
     152             : 
     153             : static bool
     154           0 : intrinsic_ToSource(JSContext* cx, unsigned argc, Value* vp)
     155             : {
     156           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     157           0 :     JSString* str = ValueToSource(cx, args[0]);
     158           0 :     if (!str)
     159           0 :         return false;
     160           0 :     args.rval().setString(str);
     161           0 :     return true;
     162             : }
     163             : 
     164             : static bool
     165          76 : intrinsic_ToPropertyKey(JSContext* cx, unsigned argc, Value* vp)
     166             : {
     167          76 :     CallArgs args = CallArgsFromVp(argc, vp);
     168         152 :     RootedId id(cx);
     169          76 :     if (!ToPropertyKey(cx, args[0], &id))
     170           0 :         return false;
     171             : 
     172          76 :     args.rval().set(IdToValue(id));
     173          76 :     return true;
     174             : }
     175             : 
     176             : static bool
     177         892 : intrinsic_IsCallable(JSContext* cx, unsigned argc, Value* vp)
     178             : {
     179         892 :     CallArgs args = CallArgsFromVp(argc, vp);
     180         892 :     args.rval().setBoolean(IsCallable(args[0]));
     181         892 :     return true;
     182             : }
     183             : 
     184             : static bool
     185         450 : intrinsic_IsConstructor(JSContext* cx, unsigned argc, Value* vp)
     186             : {
     187         450 :     CallArgs args = CallArgsFromVp(argc, vp);
     188         450 :     MOZ_ASSERT(args.length() == 1);
     189             : 
     190         900 :     RootedValue val(cx, args[0]);
     191         450 :     if (!IsConstructor(val)) {
     192           0 :         args.rval().setBoolean(false);
     193           0 :         return true;
     194             :     }
     195             : 
     196         900 :     RootedObject obj(cx, &val.toObject());
     197         450 :     if (!IsWrapper(obj)) {
     198         450 :         args.rval().setBoolean(true);
     199         450 :         return true;
     200             :     }
     201             : 
     202           0 :     obj = UncheckedUnwrap(obj);
     203           0 :     args.rval().setBoolean(obj && obj->isConstructor());
     204           0 :     return true;
     205             : }
     206             : 
     207             : template<typename T>
     208             : static bool
     209        6180 : intrinsic_IsInstanceOfBuiltin(JSContext* cx, unsigned argc, Value* vp)
     210             : {
     211        6180 :     CallArgs args = CallArgsFromVp(argc, vp);
     212        6180 :     MOZ_ASSERT(args.length() == 1);
     213        6180 :     MOZ_ASSERT(args[0].isObject());
     214             : 
     215        6180 :     args.rval().setBoolean(args[0].toObject().is<T>());
     216        6180 :     return true;
     217             : }
     218             : 
     219             : /**
     220             :  * Self-hosting intrinsic returning the original constructor for a builtin
     221             :  * the name of which is the first and only argument.
     222             :  *
     223             :  * The return value is guaranteed to be the original constructor even if
     224             :  * content code changed the named binding on the global object.
     225             :  *
     226             :  * This intrinsic shouldn't be called directly. Instead, the
     227             :  * `GetBuiltinConstructor` and `GetBuiltinPrototype` helper functions in
     228             :  * Utilities.js should be used, as they cache results, improving performance.
     229             :  */
     230             : static bool
     231          59 : intrinsic_GetBuiltinConstructor(JSContext* cx, unsigned argc, Value* vp)
     232             : {
     233          59 :     CallArgs args = CallArgsFromVp(argc, vp);
     234          59 :     MOZ_ASSERT(args.length() == 1);
     235         118 :     RootedString str(cx, args[0].toString());
     236             :     JSAtom* atom;
     237          59 :     if (str->isAtom()) {
     238          59 :         atom = &str->asAtom();
     239             :     } else {
     240           0 :         atom = AtomizeString(cx, str);
     241           0 :         if (!atom)
     242           0 :             return false;
     243             :     }
     244         118 :     RootedId id(cx, AtomToId(atom));
     245          59 :     JSProtoKey key = JS_IdToProtoKey(cx, id);
     246          59 :     MOZ_ASSERT(key != JSProto_Null);
     247         118 :     RootedObject ctor(cx);
     248          59 :     if (!GetBuiltinConstructor(cx, key, &ctor))
     249           0 :         return false;
     250          59 :     args.rval().setObject(*ctor);
     251          59 :     return true;
     252             : }
     253             : 
     254             : static bool
     255         177 : intrinsic_SubstringKernel(JSContext* cx, unsigned argc, Value* vp)
     256             : {
     257         177 :     CallArgs args = CallArgsFromVp(argc, vp);
     258         177 :     MOZ_ASSERT(args[0].isString());
     259         177 :     MOZ_ASSERT(args[1].isInt32());
     260         177 :     MOZ_ASSERT(args[2].isInt32());
     261             : 
     262         354 :     RootedString str(cx, args[0].toString());
     263         177 :     int32_t begin = args[1].toInt32();
     264         177 :     int32_t length = args[2].toInt32();
     265             : 
     266         177 :     JSString* substr = SubstringKernel(cx, str, begin, length);
     267         177 :     if (!substr)
     268           0 :         return false;
     269             : 
     270         177 :     args.rval().setString(substr);
     271         177 :     return true;
     272             : }
     273             : 
     274             : static bool
     275           0 : intrinsic_OwnPropertyKeys(JSContext* cx, unsigned argc, Value* vp)
     276             : {
     277           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     278           0 :     MOZ_ASSERT(args[0].isObject());
     279           0 :     MOZ_ASSERT(args[1].isInt32());
     280           0 :     return GetOwnPropertyKeys(cx, args, args[1].toInt32());
     281             : }
     282             : 
     283             : static void
     284           0 : ThrowErrorWithType(JSContext* cx, JSExnType type, const CallArgs& args)
     285             : {
     286           0 :     uint32_t errorNumber = args[0].toInt32();
     287             : 
     288             : #ifdef DEBUG
     289           0 :     const JSErrorFormatString* efs = GetErrorMessage(nullptr, errorNumber);
     290           0 :     MOZ_ASSERT(efs->argCount == args.length() - 1);
     291           0 :     MOZ_ASSERT(efs->exnType == type, "error-throwing intrinsic and error number are inconsistent");
     292             : #endif
     293             : 
     294           0 :     JSAutoByteString errorArgs[3];
     295           0 :     for (unsigned i = 1; i < 4 && i < args.length(); i++) {
     296           0 :         RootedValue val(cx, args[i]);
     297           0 :         if (val.isInt32()) {
     298           0 :             JSString* str = ToString<CanGC>(cx, val);
     299           0 :             if (!str)
     300           0 :                 return;
     301           0 :             errorArgs[i - 1].encodeLatin1(cx, str);
     302           0 :         } else if (val.isString()) {
     303           0 :             errorArgs[i - 1].encodeLatin1(cx, val.toString());
     304             :         } else {
     305           0 :             UniqueChars bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, val, nullptr);
     306           0 :             if (!bytes)
     307           0 :                 return;
     308           0 :             errorArgs[i - 1].initBytes(Move(bytes));
     309             :         }
     310           0 :         if (!errorArgs[i - 1])
     311           0 :             return;
     312             :     }
     313             : 
     314           0 :     JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, errorNumber,
     315           0 :                                errorArgs[0].ptr(), errorArgs[1].ptr(), errorArgs[2].ptr());
     316             : }
     317             : 
     318             : static bool
     319           0 : intrinsic_ThrowRangeError(JSContext* cx, unsigned argc, Value* vp)
     320             : {
     321           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     322           0 :     MOZ_ASSERT(args.length() >= 1);
     323             : 
     324           0 :     ThrowErrorWithType(cx, JSEXN_RANGEERR, args);
     325           0 :     return false;
     326             : }
     327             : 
     328             : static bool
     329           0 : intrinsic_ThrowTypeError(JSContext* cx, unsigned argc, Value* vp)
     330             : {
     331           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     332           0 :     MOZ_ASSERT(args.length() >= 1);
     333             : 
     334           0 :     ThrowErrorWithType(cx, JSEXN_TYPEERR, args);
     335           0 :     return false;
     336             : }
     337             : 
     338             : static bool
     339           0 : intrinsic_ThrowSyntaxError(JSContext* cx, unsigned argc, Value* vp)
     340             : {
     341           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     342           0 :     MOZ_ASSERT(args.length() >= 1);
     343             : 
     344           0 :     ThrowErrorWithType(cx, JSEXN_SYNTAXERR, args);
     345           0 :     return false;
     346             : }
     347             : 
     348             : static bool
     349           0 : intrinsic_ThrowInternalError(JSContext* cx, unsigned argc, Value* vp)
     350             : {
     351           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     352           0 :     MOZ_ASSERT(args.length() >= 1);
     353             : 
     354           0 :     ThrowErrorWithType(cx, JSEXN_INTERNALERR, args);
     355           0 :     return false;
     356             : }
     357             : 
     358             : /**
     359             :  * Handles an assertion failure in self-hosted code just like an assertion
     360             :  * failure in C++ code. Information about the failure can be provided in args[0].
     361             :  */
     362             : static bool
     363           0 : intrinsic_AssertionFailed(JSContext* cx, unsigned argc, Value* vp)
     364             : {
     365             : #ifdef DEBUG
     366           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     367           0 :     if (args.length() > 0) {
     368             :         // try to dump the informative string
     369           0 :         JSString* str = ToString<CanGC>(cx, args[0]);
     370           0 :         if (str) {
     371           0 :             fprintf(stderr, "Self-hosted JavaScript assertion info: ");
     372           0 :             str->dumpCharsNoNewline();
     373           0 :             fputc('\n', stderr);
     374             :         }
     375             :     }
     376             : #endif
     377           0 :     MOZ_ASSERT(false);
     378             :     return false;
     379             : }
     380             : 
     381             : /**
     382             :  * Dumps a message to stderr, after stringifying it. Doesn't append a newline.
     383             :  */
     384             : static bool
     385           0 : intrinsic_DumpMessage(JSContext* cx, unsigned argc, Value* vp)
     386             : {
     387           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     388             : #ifdef DEBUG
     389           0 :     if (args.length() > 0) {
     390             :         // try to dump the informative string
     391           0 :         JSString* str = ToString<CanGC>(cx, args[0]);
     392           0 :         if (str) {
     393           0 :             str->dumpCharsNoNewline();
     394           0 :             fputc('\n', stderr);
     395             :         } else {
     396           0 :             cx->recoverFromOutOfMemory();
     397             :         }
     398             :     }
     399             : #endif
     400           0 :     args.rval().setUndefined();
     401           0 :     return true;
     402             : }
     403             : 
     404             : static bool
     405           6 : intrinsic_MakeConstructible(JSContext* cx, unsigned argc, Value* vp)
     406             : {
     407           6 :     CallArgs args = CallArgsFromVp(argc, vp);
     408           6 :     MOZ_ASSERT(args.length() == 2);
     409           6 :     MOZ_ASSERT(args[0].isObject());
     410           6 :     MOZ_ASSERT(args[0].toObject().is<JSFunction>());
     411           6 :     MOZ_ASSERT(args[0].toObject().as<JSFunction>().isSelfHostedBuiltin());
     412           6 :     MOZ_ASSERT(args[1].isObjectOrNull());
     413             : 
     414             :     // Normal .prototype properties aren't enumerable.  But for this to clone
     415             :     // correctly, it must be enumerable.
     416          12 :     RootedObject ctor(cx, &args[0].toObject());
     417           6 :     if (!DefineProperty(cx, ctor, cx->names().prototype, args[1],
     418             :                         nullptr, nullptr,
     419             :                         JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT))
     420             :     {
     421           0 :         return false;
     422             :     }
     423             : 
     424           6 :     ctor->as<JSFunction>().setIsConstructor();
     425           6 :     args.rval().setUndefined();
     426           6 :     return true;
     427             : }
     428             : 
     429             : static bool
     430           6 : intrinsic_MakeDefaultConstructor(JSContext* cx, unsigned argc, Value* vp)
     431             : {
     432           6 :     CallArgs args = CallArgsFromVp(argc, vp);
     433           6 :     MOZ_ASSERT(args.length() == 1);
     434           6 :     MOZ_ASSERT(args[0].toObject().as<JSFunction>().isSelfHostedBuiltin());
     435             : 
     436          12 :     RootedFunction ctor(cx, &args[0].toObject().as<JSFunction>());
     437             : 
     438           6 :     ctor->nonLazyScript()->setIsDefaultClassConstructor();
     439             : 
     440             :     // Because self-hosting code does not allow top-level lexicals,
     441             :     // class constructors are class expressions in top-level vars.
     442             :     // Because of this, we give them a guessed atom. Since they
     443             :     // will always be cloned, and given an explicit atom, instead
     444             :     // overrule that.
     445           6 :     ctor->clearGuessedAtom();
     446             : 
     447           6 :     args.rval().setUndefined();
     448          12 :     return true;
     449             : }
     450             : 
     451             : static bool
     452         330 : intrinsic_FinishBoundFunctionInit(JSContext* cx, unsigned argc, Value* vp)
     453             : {
     454         330 :     CallArgs args = CallArgsFromVp(argc, vp);
     455         330 :     MOZ_ASSERT(args.length() == 3);
     456         330 :     MOZ_ASSERT(IsCallable(args[1]));
     457         330 :     MOZ_ASSERT(args[2].isInt32());
     458             : 
     459         660 :     RootedFunction bound(cx, &args[0].toObject().as<JSFunction>());
     460         660 :     RootedObject targetObj(cx, &args[1].toObject());
     461         330 :     int32_t argCount = args[2].toInt32();
     462             : 
     463         330 :     args.rval().setUndefined();
     464         660 :     return JSFunction::finishBoundFunctionInit(cx, bound, targetObj, argCount);
     465             : }
     466             : 
     467             : /*
     468             :  * Used to decompile values in the nearest non-builtin stack frame, falling
     469             :  * back to decompiling in the current frame. Helpful for printing higher-order
     470             :  * function arguments.
     471             :  *
     472             :  * The user must supply the argument number of the value in question; it
     473             :  * _cannot_ be automatically determined.
     474             :  */
     475             : static bool
     476           0 : intrinsic_DecompileArg(JSContext* cx, unsigned argc, Value* vp)
     477             : {
     478           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     479           0 :     MOZ_ASSERT(args.length() == 2);
     480             : 
     481           0 :     RootedValue value(cx, args[1]);
     482           0 :     ScopedJSFreePtr<char> str(DecompileArgument(cx, args[0].toInt32(), value));
     483           0 :     if (!str)
     484           0 :         return false;
     485           0 :     JSAtom* atom = Atomize(cx, str, strlen(str));
     486           0 :     if (!atom)
     487           0 :         return false;
     488           0 :     args.rval().setString(atom);
     489           0 :     return true;
     490             : }
     491             : 
     492             : static bool
     493           0 : intrinsic_DefineDataProperty(JSContext* cx, unsigned argc, Value* vp)
     494             : {
     495           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     496             : 
     497             :     // When DefineDataProperty is called with 3 arguments, it's compiled to
     498             :     // JSOP_INITELEM in the bytecode emitter so we shouldn't get here.
     499           0 :     MOZ_ASSERT(args.length() == 4);
     500           0 :     MOZ_ASSERT(args[0].isObject());
     501             : 
     502           0 :     RootedObject obj(cx, &args[0].toObject());
     503           0 :     RootedId id(cx);
     504           0 :     if (!ValueToId<CanGC>(cx, args[1], &id))
     505           0 :         return false;
     506           0 :     RootedValue value(cx, args[2]);
     507             : 
     508           0 :     unsigned attrs = 0;
     509           0 :     unsigned attributes = args[3].toInt32();
     510             : 
     511           0 :     MOZ_ASSERT(bool(attributes & ATTR_ENUMERABLE) != bool(attributes & ATTR_NONENUMERABLE),
     512             :                "_DefineDataProperty must receive either ATTR_ENUMERABLE xor ATTR_NONENUMERABLE");
     513           0 :     if (attributes & ATTR_ENUMERABLE)
     514           0 :         attrs |= JSPROP_ENUMERATE;
     515             : 
     516           0 :     MOZ_ASSERT(bool(attributes & ATTR_CONFIGURABLE) != bool(attributes & ATTR_NONCONFIGURABLE),
     517             :                "_DefineDataProperty must receive either ATTR_CONFIGURABLE xor "
     518             :                "ATTR_NONCONFIGURABLE");
     519           0 :     if (attributes & ATTR_NONCONFIGURABLE)
     520           0 :         attrs |= JSPROP_PERMANENT;
     521             : 
     522           0 :     MOZ_ASSERT(bool(attributes & ATTR_WRITABLE) != bool(attributes & ATTR_NONWRITABLE),
     523             :                "_DefineDataProperty must receive either ATTR_WRITABLE xor ATTR_NONWRITABLE");
     524           0 :     if (attributes & ATTR_NONWRITABLE)
     525           0 :         attrs |= JSPROP_READONLY;
     526             : 
     527           0 :     Rooted<PropertyDescriptor> desc(cx);
     528           0 :     desc.setDataDescriptor(value, attrs);
     529           0 :     if (!DefineProperty(cx, obj, id, desc))
     530           0 :         return false;
     531             : 
     532           0 :     args.rval().setUndefined();
     533           0 :     return true;
     534             : }
     535             : 
     536             : static bool
     537         137 : intrinsic_ObjectHasPrototype(JSContext* cx, unsigned argc, Value* vp)
     538             : {
     539         137 :     CallArgs args = CallArgsFromVp(argc, vp);
     540         137 :     MOZ_ASSERT(args.length() == 2);
     541         274 :     RootedObject obj(cx, &args[0].toObject());
     542         274 :     RootedObject proto(cx, &args[1].toObject());
     543             : 
     544         274 :     RootedObject actualProto(cx);
     545         137 :     if (!GetPrototype(cx, obj, &actualProto))
     546           0 :         return false;
     547             : 
     548         137 :     args.rval().setBoolean(actualProto == proto);
     549         137 :     return true;
     550             : }
     551             : 
     552             : static bool
     553       10859 : intrinsic_UnsafeSetReservedSlot(JSContext* cx, unsigned argc, Value* vp)
     554             : {
     555       10859 :     CallArgs args = CallArgsFromVp(argc, vp);
     556       10859 :     MOZ_ASSERT(args.length() == 3);
     557       10859 :     MOZ_ASSERT(args[0].isObject());
     558       10859 :     MOZ_ASSERT(args[1].isInt32());
     559             : 
     560       10859 :     args[0].toObject().as<NativeObject>().setReservedSlot(args[1].toPrivateUint32(), args[2]);
     561       10859 :     args.rval().setUndefined();
     562       10859 :     return true;
     563             : }
     564             : 
     565             : static bool
     566       15086 : intrinsic_UnsafeGetReservedSlot(JSContext* cx, unsigned argc, Value* vp)
     567             : {
     568       15086 :     CallArgs args = CallArgsFromVp(argc, vp);
     569       15086 :     MOZ_ASSERT(args.length() == 2);
     570       15086 :     MOZ_ASSERT(args[0].isObject());
     571       15086 :     MOZ_ASSERT(args[1].isInt32());
     572             : 
     573       15086 :     args.rval().set(args[0].toObject().as<NativeObject>().getReservedSlot(args[1].toPrivateUint32()));
     574       15086 :     return true;
     575             : }
     576             : 
     577             : static bool
     578           0 : intrinsic_UnsafeGetObjectFromReservedSlot(JSContext* cx, unsigned argc, Value* vp)
     579             : {
     580           0 :     if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp))
     581           0 :         return false;
     582           0 :     MOZ_ASSERT(vp->isObject());
     583           0 :     return true;
     584             : }
     585             : 
     586             : static bool
     587        5938 : intrinsic_UnsafeGetInt32FromReservedSlot(JSContext* cx, unsigned argc, Value* vp)
     588             : {
     589        5938 :     if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp))
     590           0 :         return false;
     591        5938 :     MOZ_ASSERT(vp->isInt32());
     592        5938 :     return true;
     593             : }
     594             : 
     595             : static bool
     596          17 : intrinsic_UnsafeGetStringFromReservedSlot(JSContext* cx, unsigned argc, Value* vp)
     597             : {
     598          17 :     if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp))
     599           0 :         return false;
     600          17 :     MOZ_ASSERT(vp->isString());
     601          17 :     return true;
     602             : }
     603             : 
     604             : static bool
     605           0 : intrinsic_UnsafeGetBooleanFromReservedSlot(JSContext* cx, unsigned argc, Value* vp)
     606             : {
     607           0 :     if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp))
     608           0 :         return false;
     609           0 :     MOZ_ASSERT(vp->isBoolean());
     610           0 :     return true;
     611             : }
     612             : 
     613             : static bool
     614         214 : intrinsic_IsPackedArray(JSContext* cx, unsigned argc, Value* vp)
     615             : {
     616         214 :     CallArgs args = CallArgsFromVp(argc, vp);
     617         214 :     MOZ_ASSERT(args.length() == 1);
     618         214 :     MOZ_ASSERT(args[0].isObject());
     619         214 :     args.rval().setBoolean(IsPackedArray(&args[0].toObject()));
     620         214 :     return true;
     621             : }
     622             : 
     623             : static bool
     624           0 : intrinsic_GetIteratorPrototype(JSContext* cx, unsigned argc, Value* vp)
     625             : {
     626           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     627           0 :     MOZ_ASSERT(args.length() == 0);
     628             : 
     629           0 :     JSObject* obj = GlobalObject::getOrCreateIteratorPrototype(cx, cx->global());
     630           0 :     if (!obj)
     631           0 :         return false;
     632             : 
     633           0 :     args.rval().setObject(*obj);
     634           0 :     return true;
     635             : }
     636             : 
     637             : bool
     638        2098 : js::intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, Value* vp)
     639             : {
     640        2098 :     CallArgs args = CallArgsFromVp(argc, vp);
     641        2098 :     MOZ_ASSERT(args.length() == 0);
     642             : 
     643        2098 :     JSObject* obj = NewArrayIteratorObject(cx);
     644        2098 :     if (!obj)
     645           0 :         return false;
     646             : 
     647        2098 :     args.rval().setObject(*obj);
     648        2098 :     return true;
     649             : }
     650             : 
     651             : static bool
     652        1070 : intrinsic_GetNextMapEntryForIterator(JSContext* cx, unsigned argc, Value* vp)
     653             : {
     654        1070 :     CallArgs args = CallArgsFromVp(argc, vp);
     655        1070 :     MOZ_ASSERT(args.length() == 2);
     656        1070 :     MOZ_ASSERT(args[0].toObject().is<MapIteratorObject>());
     657        1070 :     MOZ_ASSERT(args[1].isObject());
     658             : 
     659        2140 :     Rooted<MapIteratorObject*> mapIterator(cx, &args[0].toObject().as<MapIteratorObject>());
     660        2140 :     RootedArrayObject result(cx, &args[1].toObject().as<ArrayObject>());
     661             : 
     662        1070 :     args.rval().setBoolean(MapIteratorObject::next(mapIterator, result, cx));
     663        2140 :     return true;
     664             : }
     665             : 
     666             : static bool
     667          15 : intrinsic_CreateMapIterationResultPair(JSContext* cx, unsigned argc, Value* vp)
     668             : {
     669          15 :     CallArgs args = CallArgsFromVp(argc, vp);
     670          15 :     MOZ_ASSERT(args.length() == 0);
     671             : 
     672          15 :     JSObject* result = MapIteratorObject::createResultPair(cx);
     673          15 :     if (!result)
     674           0 :         return false;
     675             : 
     676          15 :     args.rval().setObject(*result);
     677          15 :     return true;
     678             : }
     679             : 
     680             : static bool
     681         255 : intrinsic_GetNextSetEntryForIterator(JSContext* cx, unsigned argc, Value* vp)
     682             : {
     683         255 :     CallArgs args = CallArgsFromVp(argc, vp);
     684         255 :     MOZ_ASSERT(args.length() == 2);
     685         255 :     MOZ_ASSERT(args[0].toObject().is<SetIteratorObject>());
     686         255 :     MOZ_ASSERT(args[1].isObject());
     687             : 
     688         510 :     Rooted<SetIteratorObject*> setIterator(cx, &args[0].toObject().as<SetIteratorObject>());
     689         510 :     RootedArrayObject result(cx, &args[1].toObject().as<ArrayObject>());
     690             : 
     691         255 :     args.rval().setBoolean(SetIteratorObject::next(setIterator, result, cx));
     692         510 :     return true;
     693             : }
     694             : 
     695             : static bool
     696           8 : intrinsic_CreateSetIterationResult(JSContext* cx, unsigned argc, Value* vp)
     697             : {
     698           8 :     CallArgs args = CallArgsFromVp(argc, vp);
     699           8 :     MOZ_ASSERT(args.length() == 0);
     700             : 
     701           8 :     JSObject* result = SetIteratorObject::createResult(cx);
     702           8 :     if (!result)
     703           0 :         return false;
     704             : 
     705           8 :     args.rval().setObject(*result);
     706           8 :     return true;
     707             : }
     708             : 
     709             : bool
     710           0 : js::intrinsic_NewStringIterator(JSContext* cx, unsigned argc, Value* vp)
     711             : {
     712           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     713           0 :     MOZ_ASSERT(args.length() == 0);
     714             : 
     715           0 :     JSObject* obj = NewStringIteratorObject(cx);
     716           0 :     if (!obj)
     717           0 :         return false;
     718             : 
     719           0 :     args.rval().setObject(*obj);
     720           0 :     return true;
     721             : }
     722             : 
     723             : static bool
     724          63 : intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp)
     725             : {
     726          63 :     CallArgs args = CallArgsFromVp(argc, vp);
     727          63 :     MOZ_ASSERT(args.length() == 2);
     728             : 
     729         126 :     RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
     730          63 :     MOZ_ASSERT(fun->isSelfHostedBuiltin());
     731          63 :     JSAtom* atom = AtomizeString(cx, args[1].toString());
     732          63 :     if (!atom)
     733           0 :         return false;
     734             : 
     735          63 :     fun->setAtom(atom);
     736             : #ifdef DEBUG
     737          63 :     fun->setExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT, BooleanValue(true));
     738             : #endif
     739          63 :     args.rval().setUndefined();
     740          63 :     return true;
     741             : }
     742             : 
     743             : static bool
     744           0 : intrinsic_StarGeneratorObjectIsClosed(JSContext* cx, unsigned argc, Value* vp)
     745             : {
     746           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     747           0 :     MOZ_ASSERT(args.length() == 1);
     748           0 :     MOZ_ASSERT(args[0].isObject());
     749             : 
     750           0 :     StarGeneratorObject* genObj = &args[0].toObject().as<StarGeneratorObject>();
     751           0 :     args.rval().setBoolean(genObj->isClosed());
     752           0 :     return true;
     753             : }
     754             : 
     755             : bool
     756         126 : js::intrinsic_IsSuspendedStarGenerator(JSContext* cx, unsigned argc, Value* vp)
     757             : {
     758         126 :     CallArgs args = CallArgsFromVp(argc, vp);
     759         126 :     MOZ_ASSERT(args.length() == 1);
     760             : 
     761         126 :     if (!args[0].isObject() || !args[0].toObject().is<StarGeneratorObject>()) {
     762           0 :         args.rval().setBoolean(false);
     763           0 :         return true;
     764             :     }
     765             : 
     766         126 :     StarGeneratorObject& genObj = args[0].toObject().as<StarGeneratorObject>();
     767         126 :     args.rval().setBoolean(!genObj.isClosed() && genObj.isSuspended());
     768         126 :     return true;
     769             : }
     770             : 
     771             : static bool
     772           0 : intrinsic_LegacyGeneratorObjectIsClosed(JSContext* cx, unsigned argc, Value* vp)
     773             : {
     774           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     775           0 :     MOZ_ASSERT(args.length() == 1);
     776           0 :     MOZ_ASSERT(args[0].isObject());
     777             : 
     778           0 :     LegacyGeneratorObject* genObj = &args[0].toObject().as<LegacyGeneratorObject>();
     779           0 :     args.rval().setBoolean(genObj->isClosed());
     780           0 :     return true;
     781             : }
     782             : 
     783             : static bool
     784           0 : intrinsic_CloseClosingLegacyGeneratorObject(JSContext* cx, unsigned argc, Value* vp)
     785             : {
     786           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     787           0 :     MOZ_ASSERT(args.length() == 1);
     788           0 :     MOZ_ASSERT(args[0].isObject());
     789             : 
     790           0 :     LegacyGeneratorObject* genObj = &args[0].toObject().as<LegacyGeneratorObject>();
     791           0 :     MOZ_ASSERT(genObj->isClosing());
     792           0 :     genObj->setClosed();
     793           0 :     return true;
     794             : }
     795             : 
     796             : static bool
     797           0 : intrinsic_ThrowStopIteration(JSContext* cx, unsigned argc, Value* vp)
     798             : {
     799           0 :     MOZ_ASSERT(CallArgsFromVp(argc, vp).length() == 0);
     800             : 
     801           0 :     return ThrowStopIteration(cx);
     802             : }
     803             : 
     804             : static bool
     805           0 : intrinsic_GeneratorIsRunning(JSContext* cx, unsigned argc, Value* vp)
     806             : {
     807           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     808           0 :     MOZ_ASSERT(args.length() == 1);
     809           0 :     MOZ_ASSERT(args[0].isObject());
     810             : 
     811           0 :     GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
     812           0 :     args.rval().setBoolean(genObj->isRunning() || genObj->isClosing());
     813           0 :     return true;
     814             : }
     815             : 
     816             : static bool
     817           0 : intrinsic_GeneratorSetClosed(JSContext* cx, unsigned argc, Value* vp)
     818             : {
     819           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     820           0 :     MOZ_ASSERT(args.length() == 1);
     821           0 :     MOZ_ASSERT(args[0].isObject());
     822             : 
     823           0 :     GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
     824           0 :     genObj->setClosed();
     825           0 :     return true;
     826             : }
     827             : 
     828             : template<typename T>
     829             : static bool
     830           0 : intrinsic_IsWrappedArrayBuffer(JSContext* cx, unsigned argc, Value* vp)
     831             : {
     832           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     833           0 :     MOZ_ASSERT(args.length() == 1);
     834             : 
     835           0 :     if (!args[0].isObject()) {
     836           0 :         args.rval().setBoolean(false);
     837           0 :         return true;
     838             :     }
     839             : 
     840           0 :     JSObject* obj = &args[0].toObject();
     841           0 :     if (!obj->is<WrapperObject>()) {
     842           0 :         args.rval().setBoolean(false);
     843           0 :         return true;
     844             :     }
     845             : 
     846           0 :     JSObject* unwrapped = CheckedUnwrap(obj);
     847           0 :     if (!unwrapped) {
     848           0 :         ReportAccessDenied(cx);
     849           0 :         return false;
     850             :     }
     851             : 
     852           0 :     args.rval().setBoolean(unwrapped->is<T>());
     853           0 :     return true;
     854             : }
     855             : 
     856             : template<typename T>
     857             : static bool
     858           0 : intrinsic_ArrayBufferByteLength(JSContext* cx, unsigned argc, Value* vp)
     859             : {
     860           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     861           0 :     MOZ_ASSERT(args.length() == 1);
     862           0 :     MOZ_ASSERT(args[0].isObject());
     863           0 :     MOZ_ASSERT(args[0].toObject().is<T>());
     864             : 
     865           0 :     size_t byteLength = args[0].toObject().as<T>().byteLength();
     866           0 :     args.rval().setInt32(mozilla::AssertedCast<int32_t>(byteLength));
     867           0 :     return true;
     868             : }
     869             : 
     870             : template<typename T>
     871             : static bool
     872           0 : intrinsic_PossiblyWrappedArrayBufferByteLength(JSContext* cx, unsigned argc, Value* vp)
     873             : {
     874           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     875           0 :     MOZ_ASSERT(args.length() == 1);
     876             : 
     877           0 :     JSObject* obj = CheckedUnwrap(&args[0].toObject());
     878           0 :     if (!obj) {
     879           0 :         ReportAccessDenied(cx);
     880           0 :         return false;
     881             :     }
     882             : 
     883           0 :     uint32_t length = obj->as<T>().byteLength();
     884           0 :     args.rval().setInt32(mozilla::AssertedCast<int32_t>(length));
     885           0 :     return true;
     886             : }
     887             : 
     888             : template<typename T>
     889             : static bool
     890           0 : intrinsic_ArrayBufferCopyData(JSContext* cx, unsigned argc, Value* vp)
     891             : {
     892           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     893           0 :     MOZ_ASSERT(args.length() == 6);
     894             : 
     895           0 :     bool isWrapped = args[5].toBoolean();
     896           0 :     Rooted<T*> toBuffer(cx);
     897           0 :     if (!isWrapped) {
     898           0 :         toBuffer = &args[0].toObject().as<T>();
     899             :     } else {
     900           0 :         JSObject* wrapped = &args[0].toObject();
     901           0 :         MOZ_ASSERT(wrapped->is<WrapperObject>());
     902           0 :         RootedObject toBufferObj(cx, CheckedUnwrap(wrapped));
     903           0 :         if (!toBufferObj) {
     904           0 :             ReportAccessDenied(cx);
     905           0 :             return false;
     906             :         }
     907           0 :         toBuffer = toBufferObj.as<T>();
     908             :     }
     909           0 :     uint32_t toIndex = uint32_t(args[1].toInt32());
     910           0 :     Rooted<T*> fromBuffer(cx, &args[2].toObject().as<T>());
     911           0 :     uint32_t fromIndex = uint32_t(args[3].toInt32());
     912           0 :     uint32_t count = uint32_t(args[4].toInt32());
     913             : 
     914           0 :     T::copyData(toBuffer, toIndex, fromBuffer, fromIndex, count);
     915             : 
     916           0 :     args.rval().setUndefined();
     917           0 :     return true;
     918             : }
     919             : 
     920             : // Arguments must both be SharedArrayBuffer or wrapped SharedArrayBuffer.
     921             : static bool
     922           0 : intrinsic_SharedArrayBuffersMemorySame(JSContext* cx, unsigned argc, Value* vp)
     923             : {
     924           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     925           0 :     MOZ_ASSERT(args.length() == 2);
     926             : 
     927           0 :     JSObject* lhs = CheckedUnwrap(&args[0].toObject());
     928           0 :     if (!lhs) {
     929           0 :         ReportAccessDenied(cx);
     930           0 :         return false;
     931             :     }
     932           0 :     JSObject* rhs = CheckedUnwrap(&args[1].toObject());
     933           0 :     if (!rhs) {
     934           0 :         ReportAccessDenied(cx);
     935           0 :         return false;
     936             :     }
     937             : 
     938           0 :     args.rval().setBoolean(lhs->as<SharedArrayBufferObject>().rawBufferObject() ==
     939           0 :                            rhs->as<SharedArrayBufferObject>().rawBufferObject());
     940           0 :     return true;
     941             : }
     942             : 
     943             : static bool
     944           0 : intrinsic_IsSpecificTypedArray(JSContext* cx, unsigned argc, Value* vp, Scalar::Type type)
     945             : {
     946           0 :     CallArgs args = CallArgsFromVp(argc, vp);
     947           0 :     MOZ_ASSERT(args.length() == 1);
     948           0 :     MOZ_ASSERT(args[0].isObject());
     949             : 
     950           0 :     JSObject* obj = &args[0].toObject();
     951             : 
     952           0 :     bool isArray = JS_GetArrayBufferViewType(obj) == type;
     953             : 
     954           0 :     args.rval().setBoolean(isArray);
     955           0 :     return true;
     956             : }
     957             : 
     958             : static bool
     959           0 : intrinsic_IsUint8TypedArray(JSContext* cx, unsigned argc, Value* vp)
     960             : {
     961           0 :     return intrinsic_IsSpecificTypedArray(cx, argc, vp, Scalar::Uint8) ||
     962           0 :            intrinsic_IsSpecificTypedArray(cx, argc, vp, Scalar::Uint8Clamped);
     963             : }
     964             : 
     965             : static bool
     966           0 : intrinsic_IsInt8TypedArray(JSContext* cx, unsigned argc, Value* vp)
     967             : {
     968           0 :     return intrinsic_IsSpecificTypedArray(cx, argc, vp, Scalar::Int8);
     969             : }
     970             : 
     971             : static bool
     972           0 : intrinsic_IsUint16TypedArray(JSContext* cx, unsigned argc, Value* vp)
     973             : {
     974           0 :     return intrinsic_IsSpecificTypedArray(cx, argc, vp, Scalar::Uint16);
     975             : }
     976             : 
     977             : static bool
     978           0 : intrinsic_IsInt16TypedArray(JSContext* cx, unsigned argc, Value* vp)
     979             : {
     980           0 :     return intrinsic_IsSpecificTypedArray(cx, argc, vp, Scalar::Int16);
     981             : }
     982             : 
     983             : static bool
     984           0 : intrinsic_IsUint32TypedArray(JSContext* cx, unsigned argc, Value* vp)
     985             : {
     986           0 :     return intrinsic_IsSpecificTypedArray(cx, argc, vp, Scalar::Uint32);
     987             : }
     988             : 
     989             : static bool
     990           0 : intrinsic_IsInt32TypedArray(JSContext* cx, unsigned argc, Value* vp)
     991             : {
     992           0 :     return intrinsic_IsSpecificTypedArray(cx, argc, vp, Scalar::Int32);
     993             : }
     994             : 
     995             : static bool
     996           0 : intrinsic_IsFloat32TypedArray(JSContext* cx, unsigned argc, Value* vp)
     997             : {
     998           0 :     return intrinsic_IsSpecificTypedArray(cx, argc, vp, Scalar::Float32);
     999             : }
    1000             : 
    1001             : static bool
    1002        6488 : intrinsic_IsPossiblyWrappedTypedArray(JSContext* cx, unsigned argc, Value* vp)
    1003             : {
    1004        6488 :     CallArgs args = CallArgsFromVp(argc, vp);
    1005        6488 :     MOZ_ASSERT(args.length() == 1);
    1006             : 
    1007        6488 :     bool isTypedArray = false;
    1008        6488 :     if (args[0].isObject()) {
    1009        6488 :         JSObject* obj = CheckedUnwrap(&args[0].toObject());
    1010        6488 :         if (!obj) {
    1011           0 :             ReportAccessDenied(cx);
    1012           0 :             return false;
    1013             :         }
    1014             : 
    1015        6488 :         isTypedArray = obj->is<TypedArrayObject>();
    1016             :     }
    1017             : 
    1018        6488 :     args.rval().setBoolean(isTypedArray);
    1019        6488 :     return true;
    1020             : }
    1021             : 
    1022             : static bool
    1023           0 : intrinsic_TypedArrayBuffer(JSContext* cx, unsigned argc, Value* vp)
    1024             : {
    1025           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1026           0 :     MOZ_ASSERT(args.length() == 1);
    1027           0 :     MOZ_ASSERT(TypedArrayObject::is(args[0]));
    1028             : 
    1029           0 :     Rooted<TypedArrayObject*> tarray(cx, &args[0].toObject().as<TypedArrayObject>());
    1030           0 :     if (!TypedArrayObject::ensureHasBuffer(cx, tarray))
    1031           0 :         return false;
    1032             : 
    1033           0 :     args.rval().set(TypedArrayObject::bufferValue(tarray));
    1034           0 :     return true;
    1035             : }
    1036             : 
    1037             : static bool
    1038           0 : intrinsic_TypedArrayByteOffset(JSContext* cx, unsigned argc, Value* vp)
    1039             : {
    1040           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1041           0 :     MOZ_ASSERT(args.length() == 1);
    1042           0 :     MOZ_ASSERT(TypedArrayObject::is(args[0]));
    1043             : 
    1044           0 :     args.rval().set(TypedArrayObject::byteOffsetValue(&args[0].toObject().as<TypedArrayObject>()));
    1045           0 :     return true;
    1046             : }
    1047             : 
    1048             : static bool
    1049           0 : intrinsic_TypedArrayElementShift(JSContext* cx, unsigned argc, Value* vp)
    1050             : {
    1051           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1052           0 :     MOZ_ASSERT(args.length() == 1);
    1053           0 :     MOZ_ASSERT(TypedArrayObject::is(args[0]));
    1054             : 
    1055           0 :     unsigned shift = TypedArrayShift(args[0].toObject().as<TypedArrayObject>().type());
    1056           0 :     MOZ_ASSERT(shift == 0 || shift == 1 || shift == 2 || shift == 3);
    1057             : 
    1058           0 :     args.rval().setInt32(mozilla::AssertedCast<int32_t>(shift));
    1059           0 :     return true;
    1060             : }
    1061             : 
    1062             : // Return the value of [[ArrayLength]] internal slot of the TypedArray
    1063             : static bool
    1064           0 : intrinsic_TypedArrayLength(JSContext* cx, unsigned argc, Value* vp)
    1065             : {
    1066           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1067           0 :     MOZ_ASSERT(args.length() == 1);
    1068             : 
    1069           0 :     JSObject* obj = &args[0].toObject();
    1070           0 :     MOZ_ASSERT(obj->is<TypedArrayObject>());
    1071           0 :     args.rval().setInt32(obj->as<TypedArrayObject>().length());
    1072           0 :     return true;
    1073             : }
    1074             : 
    1075             : static bool
    1076           0 : intrinsic_PossiblyWrappedTypedArrayLength(JSContext* cx, unsigned argc, Value* vp)
    1077             : {
    1078           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1079           0 :     MOZ_ASSERT(args.length() == 1);
    1080           0 :     MOZ_ASSERT(args[0].isObject());
    1081             : 
    1082           0 :     JSObject* obj = CheckedUnwrap(&args[0].toObject());
    1083           0 :     if (!obj) {
    1084           0 :         ReportAccessDenied(cx);
    1085           0 :         return false;
    1086             :     }
    1087             : 
    1088           0 :     MOZ_ASSERT(obj->is<TypedArrayObject>());
    1089           0 :     uint32_t typedArrayLength = obj->as<TypedArrayObject>().length();
    1090           0 :     args.rval().setInt32(mozilla::AssertedCast<int32_t>(typedArrayLength));
    1091           0 :     return true;
    1092             : }
    1093             : 
    1094             : static bool
    1095           0 : intrinsic_PossiblyWrappedTypedArrayHasDetachedBuffer(JSContext* cx, unsigned argc, Value* vp)
    1096             : {
    1097           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1098           0 :     MOZ_ASSERT(args.length() == 1);
    1099           0 :     MOZ_ASSERT(args[0].isObject());
    1100             : 
    1101           0 :     JSObject* obj = CheckedUnwrap(&args[0].toObject());
    1102           0 :     if (!obj) {
    1103           0 :         ReportAccessDenied(cx);
    1104           0 :         return false;
    1105             :     }
    1106             : 
    1107           0 :     MOZ_ASSERT(obj->is<TypedArrayObject>());
    1108           0 :     bool detached = obj->as<TypedArrayObject>().hasDetachedBuffer();
    1109           0 :     args.rval().setBoolean(detached);
    1110           0 :     return true;
    1111             : }
    1112             : 
    1113             : static bool
    1114           0 : intrinsic_MoveTypedArrayElements(JSContext* cx, unsigned argc, Value* vp)
    1115             : {
    1116           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1117           0 :     MOZ_ASSERT(args.length() == 4);
    1118             : 
    1119           0 :     Rooted<TypedArrayObject*> tarray(cx, &args[0].toObject().as<TypedArrayObject>());
    1120           0 :     uint32_t to = uint32_t(args[1].toInt32());
    1121           0 :     uint32_t from = uint32_t(args[2].toInt32());
    1122           0 :     uint32_t count = uint32_t(args[3].toInt32());
    1123             : 
    1124           0 :     MOZ_ASSERT(count > 0,
    1125             :                "don't call this method if copying no elements, because then "
    1126             :                "the not-detached requirement is wrong");
    1127             : 
    1128           0 :     if (tarray->hasDetachedBuffer()) {
    1129           0 :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
    1130           0 :         return false;
    1131             :     }
    1132             : 
    1133             :     // Don't multiply by |tarray->bytesPerElement()| in case the compiler can't
    1134             :     // strength-reduce multiplication by 1/2/4/8 into the equivalent shift.
    1135           0 :     const size_t ElementShift = TypedArrayShift(tarray->type());
    1136             : 
    1137           0 :     MOZ_ASSERT((UINT32_MAX >> ElementShift) > to);
    1138           0 :     uint32_t byteDest = to << ElementShift;
    1139             : 
    1140           0 :     MOZ_ASSERT((UINT32_MAX >> ElementShift) > from);
    1141           0 :     uint32_t byteSrc = from << ElementShift;
    1142             : 
    1143           0 :     MOZ_ASSERT((UINT32_MAX >> ElementShift) >= count);
    1144           0 :     uint32_t byteSize = count << ElementShift;
    1145             : 
    1146             : #ifdef DEBUG
    1147             :     {
    1148           0 :         uint32_t viewByteLength = tarray->byteLength();
    1149           0 :         MOZ_ASSERT(byteSize <= viewByteLength);
    1150           0 :         MOZ_ASSERT(byteDest < viewByteLength);
    1151           0 :         MOZ_ASSERT(byteSrc < viewByteLength);
    1152           0 :         MOZ_ASSERT(byteDest <= viewByteLength - byteSize);
    1153           0 :         MOZ_ASSERT(byteSrc <= viewByteLength - byteSize);
    1154             :     }
    1155             : #endif
    1156             : 
    1157           0 :     SharedMem<uint8_t*> data = tarray->viewDataEither().cast<uint8_t*>();
    1158           0 :     jit::AtomicOperations::memmoveSafeWhenRacy(data + byteDest, data + byteSrc, byteSize);
    1159             : 
    1160           0 :     args.rval().setUndefined();
    1161           0 :     return true;
    1162             : }
    1163             : 
    1164             : // Extract the TypedArrayObject* underlying |obj| and return it.  This method,
    1165             : // in a TOTALLY UNSAFE manner, completely violates the normal compartment
    1166             : // boundaries, returning an object not necessarily in the current compartment
    1167             : // or in |obj|'s compartment.
    1168             : //
    1169             : // All callers of this method are expected to sigil this TypedArrayObject*, and
    1170             : // all values and information derived from it, with an "unsafe" prefix, to
    1171             : // indicate the extreme caution required when dealing with such values.
    1172             : //
    1173             : // If calling code discipline ever fails to be maintained, it's gonna have a
    1174             : // bad time.
    1175             : static TypedArrayObject*
    1176           0 : DangerouslyUnwrapTypedArray(JSContext* cx, JSObject* obj)
    1177             : {
    1178             :     // An unwrapped pointer to an object potentially on the other side of a
    1179             :     // compartment boundary!  Isn't this such fun?
    1180           0 :     JSObject* unwrapped = CheckedUnwrap(obj);
    1181           0 :     if (!unwrapped->is<TypedArrayObject>()) {
    1182             :         // By *appearances* this can't happen, as self-hosted TypedArraySet
    1183             :         // checked this.  But.  Who's to say a GC couldn't happen between
    1184             :         // the check that this value was a typed array, and this extraction
    1185             :         // occurring?  A GC might turn a cross-compartment wrapper |obj| into
    1186             :         // |unwrapped == obj|, a dead object no longer connected its typed
    1187             :         // array.
    1188             :         //
    1189             :         // Yeah, yeah, it's pretty unlikely.  Are you willing to stake a
    1190             :         // sec-critical bug on that assessment, now and forever, against
    1191             :         // all changes those pesky GC and JIT people might make?
    1192           0 :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
    1193           0 :         return nullptr;
    1194             :     }
    1195             : 
    1196             :     // Be super-duper careful using this, as we've just punched through
    1197             :     // the compartment boundary, and things like buffer() on this aren't
    1198             :     // same-compartment with anything else in the calling method.
    1199           0 :     return &unwrapped->as<TypedArrayObject>();
    1200             : }
    1201             : 
    1202             : // ES6 draft 20150403 22.2.3.22.2, steps 12-24, 29.
    1203             : static bool
    1204           0 : intrinsic_SetFromTypedArrayApproach(JSContext* cx, unsigned argc, Value* vp)
    1205             : {
    1206           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1207           0 :     MOZ_ASSERT(args.length() == 4);
    1208             : 
    1209           0 :     Rooted<TypedArrayObject*> target(cx, &args[0].toObject().as<TypedArrayObject>());
    1210           0 :     MOZ_ASSERT(!target->hasDetachedBuffer(),
    1211             :                "something should have defended against a target viewing a "
    1212             :                "detached buffer");
    1213             : 
    1214             :     // As directed by |DangerouslyUnwrapTypedArray|, sigil this pointer and all
    1215             :     // variables derived from it to counsel extreme caution here.
    1216           0 :     Rooted<TypedArrayObject*> unsafeTypedArrayCrossCompartment(cx);
    1217           0 :     unsafeTypedArrayCrossCompartment = DangerouslyUnwrapTypedArray(cx, &args[1].toObject());
    1218           0 :     if (!unsafeTypedArrayCrossCompartment)
    1219           0 :         return false;
    1220             : 
    1221           0 :     double doubleTargetOffset = args[2].toNumber();
    1222           0 :     MOZ_ASSERT(doubleTargetOffset >= 0, "caller failed to ensure |targetOffset >= 0|");
    1223             : 
    1224           0 :     uint32_t targetLength = uint32_t(args[3].toInt32());
    1225             : 
    1226             :     // Handle all checks preceding the actual element-setting.  A visual skim
    1227             :     // of 22.2.3.22.2 should confirm these are the only steps after steps 1-11
    1228             :     // that might abort processing (other than for reason of internal error.)
    1229             : 
    1230             :     // Steps 12-13.
    1231           0 :     if (unsafeTypedArrayCrossCompartment->hasDetachedBuffer()) {
    1232           0 :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
    1233           0 :         return false;
    1234             :     }
    1235             : 
    1236             :     // Steps 21, 23.
    1237           0 :     uint32_t unsafeSrcLengthCrossCompartment = unsafeTypedArrayCrossCompartment->length();
    1238           0 :     if (unsafeSrcLengthCrossCompartment + doubleTargetOffset > targetLength) {
    1239           0 :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_INDEX);
    1240           0 :         return false;
    1241             :     }
    1242             : 
    1243             :     // Now that that's confirmed, we can use |targetOffset| of a sane type.
    1244           0 :     uint32_t targetOffset = uint32_t(doubleTargetOffset);
    1245             : 
    1246             :     // The remaining steps are unobservable *except* through their effect on
    1247             :     // which elements are copied and how.
    1248             : 
    1249           0 :     Scalar::Type targetType = target->type();
    1250           0 :     Scalar::Type unsafeSrcTypeCrossCompartment = unsafeTypedArrayCrossCompartment->type();
    1251             : 
    1252           0 :     size_t targetElementSize = TypedArrayElemSize(targetType);
    1253             :     SharedMem<uint8_t*> targetData =
    1254           0 :         target->viewDataEither().cast<uint8_t*>() + targetOffset * targetElementSize;
    1255             : 
    1256             :     SharedMem<uint8_t*> unsafeSrcDataCrossCompartment =
    1257           0 :         unsafeTypedArrayCrossCompartment->viewDataEither().cast<uint8_t*>();
    1258             : 
    1259             :     uint32_t unsafeSrcElementSizeCrossCompartment =
    1260           0 :         TypedArrayElemSize(unsafeSrcTypeCrossCompartment);
    1261             :     uint32_t unsafeSrcByteLengthCrossCompartment =
    1262           0 :         unsafeSrcLengthCrossCompartment * unsafeSrcElementSizeCrossCompartment;
    1263             : 
    1264             :     // Step 29.
    1265             :     //
    1266             :     // The same-type case requires exact copying preserving the bit-level
    1267             :     // encoding of the source data, so move the values.  (We could PodCopy if
    1268             :     // we knew the buffers differed, but it's doubtful the work to check
    1269             :     // wouldn't swap any minor wins PodCopy would afford.  Because of the
    1270             :     // TOTALLY UNSAFE CROSS-COMPARTMENT NONSENSE here, comparing buffer
    1271             :     // pointers directly could give an incorrect answer.)  If this occurs,
    1272             :     // the %TypedArray%.prototype.set operation is completely finished.
    1273           0 :     if (targetType == unsafeSrcTypeCrossCompartment) {
    1274           0 :         jit::AtomicOperations::memmoveSafeWhenRacy(targetData,
    1275             :                                                    unsafeSrcDataCrossCompartment,
    1276           0 :                                                    unsafeSrcByteLengthCrossCompartment);
    1277           0 :         args.rval().setInt32(JS_SETTYPEDARRAY_SAME_TYPE);
    1278           0 :         return true;
    1279             :     }
    1280             : 
    1281             :     // Every other bit of element-copying is handled by step 28.  Indicate
    1282             :     // whether such copying must take care not to overlap, so that self-hosted
    1283             :     // code may correctly perform the copying.
    1284             : 
    1285             :     SharedMem<uint8_t*> unsafeSrcDataLimitCrossCompartment =
    1286           0 :         unsafeSrcDataCrossCompartment + unsafeSrcByteLengthCrossCompartment;
    1287             :     SharedMem<uint8_t*> targetDataLimit =
    1288           0 :         target->viewDataEither().cast<uint8_t*>() + targetLength * targetElementSize;
    1289             : 
    1290             :     // Step 24 test (but not steps 24a-d -- the caller handles those).
    1291             :     bool overlap =
    1292           0 :         IsInRange(targetData.unwrap(/*safe - used for ptr value*/),
    1293           0 :                   unsafeSrcDataCrossCompartment.unwrap(/*safe - ditto*/),
    1294           0 :                   unsafeSrcDataLimitCrossCompartment.unwrap(/*safe - ditto*/)) ||
    1295           0 :         IsInRange(unsafeSrcDataCrossCompartment.unwrap(/*safe - ditto*/),
    1296           0 :                   targetData.unwrap(/*safe - ditto*/),
    1297           0 :                   targetDataLimit.unwrap(/*safe - ditto*/));
    1298             : 
    1299           0 :     args.rval().setInt32(overlap ? JS_SETTYPEDARRAY_OVERLAPPING : JS_SETTYPEDARRAY_DISJOINT);
    1300           0 :     return true;
    1301             : }
    1302             : 
    1303             : template <typename From, typename To>
    1304             : static void
    1305           0 : CopyValues(SharedMem<To*> dest, SharedMem<From*> src, uint32_t count)
    1306             : {
    1307             : #ifdef DEBUG
    1308           0 :     void* destVoid = dest.template cast<void*>().unwrap(/*safe - used for ptr value*/);
    1309           0 :     void* destVoidEnd = (dest + count).template cast<void*>().unwrap(/*safe - ditto*/);
    1310           0 :     const void* srcVoid = src.template cast<void*>().unwrap(/*safe - ditto*/);
    1311           0 :     const void* srcVoidEnd = (src + count).template cast<void*>().unwrap(/*safe - ditto*/);
    1312           0 :     MOZ_ASSERT(!IsInRange(destVoid, srcVoid, srcVoidEnd));
    1313           0 :     MOZ_ASSERT(!IsInRange(srcVoid, destVoid, destVoidEnd));
    1314             : #endif
    1315             : 
    1316             :     using namespace jit;
    1317             : 
    1318           0 :     for (; count > 0; count--) {
    1319           0 :         AtomicOperations::storeSafeWhenRacy(dest++,
    1320           0 :                                             To(AtomicOperations::loadSafeWhenRacy(src++)));
    1321             :     }
    1322           0 : }
    1323             : 
    1324             : struct DisjointElements
    1325             : {
    1326             :     template <typename To>
    1327             :     static void
    1328           0 :     copy(SharedMem<To*> dest, SharedMem<void*> src, Scalar::Type fromType, uint32_t count) {
    1329           0 :         switch (fromType) {
    1330             :           case Scalar::Int8:
    1331           0 :             CopyValues(dest, src.cast<int8_t*>(), count);
    1332           0 :             return;
    1333             : 
    1334             :           case Scalar::Uint8:
    1335           0 :             CopyValues(dest, src.cast<uint8_t*>(), count);
    1336           0 :             return;
    1337             : 
    1338             :           case Scalar::Int16:
    1339           0 :             CopyValues(dest, src.cast<int16_t*>(), count);
    1340           0 :             return;
    1341             : 
    1342             :           case Scalar::Uint16:
    1343           0 :             CopyValues(dest, src.cast<uint16_t*>(), count);
    1344           0 :             return;
    1345             : 
    1346             :           case Scalar::Int32:
    1347           0 :             CopyValues(dest, src.cast<int32_t*>(), count);
    1348           0 :             return;
    1349             : 
    1350             :           case Scalar::Uint32:
    1351           0 :             CopyValues(dest, src.cast<uint32_t*>(), count);
    1352           0 :             return;
    1353             : 
    1354             :           case Scalar::Float32:
    1355           0 :             CopyValues(dest, src.cast<float*>(), count);
    1356           0 :             return;
    1357             : 
    1358             :           case Scalar::Float64:
    1359           0 :             CopyValues(dest, src.cast<double*>(), count);
    1360           0 :             return;
    1361             : 
    1362             :           case Scalar::Uint8Clamped:
    1363           0 :             CopyValues(dest, src.cast<uint8_clamped*>(), count);
    1364           0 :             return;
    1365             : 
    1366             :           default:
    1367           0 :             MOZ_CRASH("NonoverlappingSet with bogus from-type");
    1368             :         }
    1369             :     }
    1370             : };
    1371             : 
    1372             : static void
    1373           0 : CopyToDisjointArray(TypedArrayObject* target, uint32_t targetOffset, SharedMem<void*> src,
    1374             :                     Scalar::Type srcType, uint32_t count)
    1375             : {
    1376           0 :     Scalar::Type destType = target->type();
    1377           0 :     SharedMem<uint8_t*> dest = target->viewDataEither().cast<uint8_t*>() + targetOffset * TypedArrayElemSize(destType);
    1378             : 
    1379           0 :     switch (destType) {
    1380             :       case Scalar::Int8: {
    1381           0 :         DisjointElements::copy(dest.cast<int8_t*>(), src, srcType, count);
    1382           0 :         break;
    1383             :       }
    1384             : 
    1385             :       case Scalar::Uint8: {
    1386           0 :         DisjointElements::copy(dest.cast<uint8_t*>(), src, srcType, count);
    1387           0 :         break;
    1388             :       }
    1389             : 
    1390             :       case Scalar::Int16: {
    1391           0 :         DisjointElements::copy(dest.cast<int16_t*>(), src, srcType, count);
    1392           0 :         break;
    1393             :       }
    1394             : 
    1395             :       case Scalar::Uint16: {
    1396           0 :         DisjointElements::copy(dest.cast<uint16_t*>(), src, srcType, count);
    1397           0 :         break;
    1398             :       }
    1399             : 
    1400             :       case Scalar::Int32: {
    1401           0 :         DisjointElements::copy(dest.cast<int32_t*>(), src, srcType, count);
    1402           0 :         break;
    1403             :       }
    1404             : 
    1405             :       case Scalar::Uint32: {
    1406           0 :         DisjointElements::copy(dest.cast<uint32_t*>(), src, srcType, count);
    1407           0 :         break;
    1408             :       }
    1409             : 
    1410             :       case Scalar::Float32: {
    1411           0 :         DisjointElements::copy(dest.cast<float*>(), src, srcType, count);
    1412           0 :         break;
    1413             :       }
    1414             : 
    1415             :       case Scalar::Float64: {
    1416           0 :         DisjointElements::copy(dest.cast<double*>(), src, srcType, count);
    1417           0 :         break;
    1418             :       }
    1419             : 
    1420             :       case Scalar::Uint8Clamped: {
    1421           0 :         DisjointElements::copy(dest.cast<uint8_clamped*>(), src, srcType, count);
    1422           0 :         break;
    1423             :       }
    1424             : 
    1425             :       default:
    1426           0 :         MOZ_CRASH("setFromTypedArray with a typed array with bogus type");
    1427             :     }
    1428           0 : }
    1429             : 
    1430             : // |unsafeSrcCrossCompartment| is produced by |DangerouslyUnwrapTypedArray|,
    1431             : // counseling extreme caution when using it.  As directed by
    1432             : // |DangerouslyUnwrapTypedArray|, sigil this pointer and all variables derived
    1433             : // from it to counsel extreme caution here.
    1434             : void
    1435           0 : js::SetDisjointTypedElements(TypedArrayObject* target, uint32_t targetOffset,
    1436             :                              TypedArrayObject* unsafeSrcCrossCompartment)
    1437             : {
    1438           0 :     Scalar::Type unsafeSrcTypeCrossCompartment = unsafeSrcCrossCompartment->type();
    1439             : 
    1440           0 :     SharedMem<void*> unsafeSrcDataCrossCompartment = unsafeSrcCrossCompartment->viewDataEither();
    1441           0 :     uint32_t count = unsafeSrcCrossCompartment->length();
    1442             : 
    1443             :     CopyToDisjointArray(target, targetOffset,
    1444             :                         unsafeSrcDataCrossCompartment,
    1445           0 :                         unsafeSrcTypeCrossCompartment, count);
    1446           0 : }
    1447             : 
    1448             : static bool
    1449           0 : intrinsic_SetDisjointTypedElements(JSContext* cx, unsigned argc, Value* vp)
    1450             : {
    1451           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1452           0 :     MOZ_ASSERT(args.length() == 3);
    1453             : 
    1454           0 :     Rooted<TypedArrayObject*> target(cx, &args[0].toObject().as<TypedArrayObject>());
    1455           0 :     MOZ_ASSERT(!target->hasDetachedBuffer(),
    1456             :                "a typed array viewing a detached buffer has no elements to "
    1457             :                "set, so it's nonsensical to be setting them");
    1458             : 
    1459           0 :     uint32_t targetOffset = uint32_t(args[1].toInt32());
    1460             : 
    1461             :     // As directed by |DangerouslyUnwrapTypedArray|, sigil this pointer and all
    1462             :     // variables derived from it to counsel extreme caution here.
    1463           0 :     Rooted<TypedArrayObject*> unsafeSrcCrossCompartment(cx);
    1464           0 :     unsafeSrcCrossCompartment = DangerouslyUnwrapTypedArray(cx, &args[2].toObject());
    1465           0 :     if (!unsafeSrcCrossCompartment)
    1466           0 :         return false;
    1467             : 
    1468           0 :     SetDisjointTypedElements(target, targetOffset, unsafeSrcCrossCompartment);
    1469             : 
    1470           0 :     args.rval().setUndefined();
    1471           0 :     return true;
    1472             : }
    1473             : 
    1474             : static bool
    1475           0 : intrinsic_SetOverlappingTypedElements(JSContext* cx, unsigned argc, Value* vp)
    1476             : {
    1477           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1478           0 :     MOZ_ASSERT(args.length() == 3);
    1479             : 
    1480           0 :     Rooted<TypedArrayObject*> target(cx, &args[0].toObject().as<TypedArrayObject>());
    1481           0 :     MOZ_ASSERT(!target->hasDetachedBuffer(),
    1482             :                "shouldn't set elements if underlying buffer is detached");
    1483             : 
    1484           0 :     uint32_t targetOffset = uint32_t(args[1].toInt32());
    1485             : 
    1486             :     // As directed by |DangerouslyUnwrapTypedArray|, sigil this pointer and all
    1487             :     // variables derived from it to counsel extreme caution here.
    1488           0 :     Rooted<TypedArrayObject*> unsafeSrcCrossCompartment(cx);
    1489           0 :     unsafeSrcCrossCompartment = DangerouslyUnwrapTypedArray(cx, &args[2].toObject());
    1490           0 :     if (!unsafeSrcCrossCompartment)
    1491           0 :         return false;
    1492             : 
    1493             :     // Smarter algorithms exist to perform overlapping transfers of the sort
    1494             :     // this method performs (for example, v8's self-hosted implementation).
    1495             :     // But it seems likely deliberate overlapping transfers are rare enough
    1496             :     // that it's not worth the trouble to implement one (and worry about its
    1497             :     // safety/correctness!).  Make a copy and do a disjoint set from that.
    1498           0 :     uint32_t count = unsafeSrcCrossCompartment->length();
    1499           0 :     Scalar::Type unsafeSrcTypeCrossCompartment = unsafeSrcCrossCompartment->type();
    1500           0 :     size_t sourceByteLen = count * TypedArrayElemSize(unsafeSrcTypeCrossCompartment);
    1501             : 
    1502           0 :     auto copyOfSrcData = target->zone()->make_pod_array<uint8_t>(sourceByteLen);
    1503           0 :     if (!copyOfSrcData)
    1504           0 :         return false;
    1505             : 
    1506           0 :     jit::AtomicOperations::memcpySafeWhenRacy(SharedMem<uint8_t*>::unshared(copyOfSrcData.get()),
    1507           0 :                                               unsafeSrcCrossCompartment->viewDataEither().cast<uint8_t*>(),
    1508           0 :                                               sourceByteLen);
    1509             : 
    1510           0 :     CopyToDisjointArray(target, targetOffset, SharedMem<void*>::unshared(copyOfSrcData.get()),
    1511           0 :                         unsafeSrcTypeCrossCompartment, count);
    1512             : 
    1513           0 :     args.rval().setUndefined();
    1514           0 :     return true;
    1515             : }
    1516             : 
    1517             : static bool
    1518           0 : intrinsic_RegExpCreate(JSContext* cx, unsigned argc, Value* vp)
    1519             : {
    1520           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1521             : 
    1522           0 :     MOZ_ASSERT(args.length() == 1 || args.length() == 2);
    1523           0 :     MOZ_ASSERT_IF(args.length() == 2, args[1].isString() || args[1].isUndefined());
    1524           0 :     MOZ_ASSERT(!args.isConstructing());
    1525             : 
    1526           0 :     return RegExpCreate(cx, args[0], args.get(1), args.rval());
    1527             : }
    1528             : 
    1529             : static bool
    1530           0 : intrinsic_RegExpGetSubstitution(JSContext* cx, unsigned argc, Value* vp)
    1531             : {
    1532           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1533             : 
    1534           0 :     MOZ_ASSERT(args.length() == 6);
    1535             : 
    1536           0 :     RootedString matched(cx, args[0].toString());
    1537           0 :     RootedString string(cx, args[1].toString());
    1538             : 
    1539           0 :     int32_t position = int32_t(args[2].toNumber());
    1540           0 :     MOZ_ASSERT(position >= 0);
    1541             : 
    1542           0 :     RootedObject captures(cx, &args[3].toObject());
    1543             : #ifdef DEBUG
    1544           0 :     bool isArray = false;
    1545           0 :     MOZ_ALWAYS_TRUE(IsArray(cx, captures, &isArray));
    1546           0 :     MOZ_ASSERT(isArray);
    1547             : #endif
    1548             : 
    1549           0 :     RootedString replacement(cx, args[4].toString());
    1550             : 
    1551           0 :     int32_t firstDollarIndex = int32_t(args[5].toNumber());
    1552           0 :     MOZ_ASSERT(firstDollarIndex >= 0);
    1553             : 
    1554           0 :     RootedLinearString matchedLinear(cx, matched->ensureLinear(cx));
    1555           0 :     if (!matchedLinear)
    1556           0 :         return false;
    1557           0 :     RootedLinearString stringLinear(cx, string->ensureLinear(cx));
    1558           0 :     if (!stringLinear)
    1559           0 :         return false;
    1560           0 :     RootedLinearString replacementLinear(cx, replacement->ensureLinear(cx));
    1561           0 :     if (!replacementLinear)
    1562           0 :         return false;
    1563             : 
    1564           0 :     return RegExpGetSubstitution(cx, matchedLinear, stringLinear, size_t(position), captures,
    1565           0 :                                  replacementLinear, size_t(firstDollarIndex), args.rval());
    1566             : }
    1567             : 
    1568             : static bool
    1569          28 : intrinsic_StringReplaceString(JSContext* cx, unsigned argc, Value* vp)
    1570             : {
    1571          28 :     CallArgs args = CallArgsFromVp(argc, vp);
    1572          28 :     MOZ_ASSERT(args.length() == 3);
    1573             : 
    1574          56 :     RootedString string(cx, args[0].toString());
    1575          56 :     RootedString pattern(cx, args[1].toString());
    1576          56 :     RootedString replacement(cx, args[2].toString());
    1577          28 :     JSString* result = str_replace_string_raw(cx, string, pattern, replacement);
    1578          28 :     if (!result)
    1579           0 :         return false;
    1580             : 
    1581          28 :     args.rval().setString(result);
    1582          28 :     return true;
    1583             : }
    1584             : 
    1585             : bool
    1586          67 : js::intrinsic_StringSplitString(JSContext* cx, unsigned argc, Value* vp)
    1587             : {
    1588          67 :     CallArgs args = CallArgsFromVp(argc, vp);
    1589          67 :     MOZ_ASSERT(args.length() == 2);
    1590             : 
    1591         134 :     RootedString string(cx, args[0].toString());
    1592         134 :     RootedString sep(cx, args[1].toString());
    1593             : 
    1594         134 :     RootedObjectGroup group(cx, ObjectGroupCompartment::getStringSplitStringGroup(cx));
    1595          67 :     if (!group)
    1596           0 :         return false;
    1597             : 
    1598          67 :     JSObject* aobj = str_split_string(cx, group, string, sep, INT32_MAX);
    1599          67 :     if (!aobj)
    1600           0 :         return false;
    1601             : 
    1602          67 :     args.rval().setObject(*aobj);
    1603          67 :     return true;
    1604             : }
    1605             : 
    1606             : static bool
    1607           1 : intrinsic_StringSplitStringLimit(JSContext* cx, unsigned argc, Value* vp)
    1608             : {
    1609           1 :     CallArgs args = CallArgsFromVp(argc, vp);
    1610           1 :     MOZ_ASSERT(args.length() == 3);
    1611             : 
    1612           2 :     RootedString string(cx, args[0].toString());
    1613           2 :     RootedString sep(cx, args[1].toString());
    1614             : 
    1615             :     // args[2] should be already in UInt32 range, but it could be double typed,
    1616             :     // because of Ion optimization.
    1617           1 :     uint32_t limit = uint32_t(args[2].toNumber());
    1618             : 
    1619           2 :     RootedObjectGroup group(cx, ObjectGroupCompartment::getStringSplitStringGroup(cx));
    1620           1 :     if (!group)
    1621           0 :         return false;
    1622             : 
    1623           1 :     JSObject* aobj = str_split_string(cx, group, string, sep, limit);
    1624           1 :     if (!aobj)
    1625           0 :         return false;
    1626             : 
    1627           1 :     args.rval().setObject(*aobj);
    1628           1 :     return true;
    1629             : }
    1630             : 
    1631             : bool
    1632           0 : CallSelfHostedNonGenericMethod(JSContext* cx, const CallArgs& args)
    1633             : {
    1634             :     // This function is called when a self-hosted method is invoked on a
    1635             :     // wrapper object, like a CrossCompartmentWrapper. The last argument is
    1636             :     // the name of the self-hosted function. The other arguments are the
    1637             :     // arguments to pass to this function.
    1638             : 
    1639           0 :     MOZ_ASSERT(args.length() > 0);
    1640           0 :     RootedPropertyName name(cx, args[args.length() - 1].toString()->asAtom().asPropertyName());
    1641             : 
    1642           0 :     RootedValue selfHostedFun(cx);
    1643           0 :     if (!GlobalObject::getIntrinsicValue(cx, cx->global(), name, &selfHostedFun))
    1644           0 :         return false;
    1645             : 
    1646           0 :     MOZ_ASSERT(selfHostedFun.toObject().is<JSFunction>());
    1647             : 
    1648           0 :     InvokeArgs args2(cx);
    1649           0 :     if (!args2.init(cx, args.length() - 1))
    1650           0 :         return false;
    1651             : 
    1652           0 :     for (size_t i = 0; i < args.length() - 1; i++)
    1653           0 :         args2[i].set(args[i]);
    1654             : 
    1655           0 :     return js::Call(cx, selfHostedFun, args.thisv(), args2, args.rval());
    1656             : }
    1657             : 
    1658             : bool
    1659           0 : js::CallSelfHostedFunction(JSContext* cx, const char* name, HandleValue thisv,
    1660             :                            const AnyInvokeArgs& args, MutableHandleValue rval)
    1661             : {
    1662           0 :     RootedAtom funAtom(cx, Atomize(cx, name, strlen(name)));
    1663           0 :     if (!funAtom)
    1664           0 :         return false;
    1665           0 :     RootedPropertyName funName(cx, funAtom->asPropertyName());
    1666           0 :     return CallSelfHostedFunction(cx, funName, thisv, args, rval);
    1667             : }
    1668             : 
    1669             : bool
    1670         143 : js::CallSelfHostedFunction(JSContext* cx, HandlePropertyName name, HandleValue thisv,
    1671             :                            const AnyInvokeArgs& args, MutableHandleValue rval)
    1672             : {
    1673         286 :     RootedValue fun(cx);
    1674         143 :     if (!GlobalObject::getIntrinsicValue(cx, cx->global(), name, &fun))
    1675           0 :         return false;
    1676         143 :     MOZ_ASSERT(fun.toObject().is<JSFunction>());
    1677             : 
    1678         143 :     return Call(cx, fun, thisv, args, rval);
    1679             : }
    1680             : 
    1681             : template<typename T>
    1682             : bool
    1683           0 : Is(HandleValue v)
    1684             : {
    1685           0 :     return v.isObject() && v.toObject().is<T>();
    1686             : }
    1687             : 
    1688             : template<IsAcceptableThis Test>
    1689             : static bool
    1690           0 : CallNonGenericSelfhostedMethod(JSContext* cx, unsigned argc, Value* vp)
    1691             : {
    1692           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1693           0 :     return CallNonGenericMethod<Test, CallSelfHostedNonGenericMethod>(cx, args);
    1694             : }
    1695             : 
    1696             : bool
    1697           0 : js::IsCallSelfHostedNonGenericMethod(NativeImpl impl)
    1698             : {
    1699           0 :     return impl == CallSelfHostedNonGenericMethod;
    1700             : }
    1701             : 
    1702             : bool
    1703           0 : js::ReportIncompatibleSelfHostedMethod(JSContext* cx, const CallArgs& args)
    1704             : {
    1705             :     // The contract for this function is the same as CallSelfHostedNonGenericMethod.
    1706             :     // The normal ReportIncompatible function doesn't work for selfhosted functions,
    1707             :     // because they always call the different CallXXXMethodIfWrapped methods,
    1708             :     // which would be reported as the called function instead.
    1709             : 
    1710             :     // Lookup the selfhosted method that was invoked.  But skip over
    1711             :     // IsTypedArrayEnsuringArrayBuffer frames, because those are never the
    1712             :     // actual self-hosted callee from external code.  We can't just skip
    1713             :     // self-hosted things until we find a non-self-hosted one because of cases
    1714             :     // like array.sort(somethingSelfHosted), where we want to report the error
    1715             :     // in the somethingSelfHosted, not in the sort() call.
    1716           0 :     ScriptFrameIter iter(cx);
    1717           0 :     MOZ_ASSERT(iter.isFunctionFrame());
    1718             : 
    1719           0 :     while (!iter.done()) {
    1720           0 :         MOZ_ASSERT(iter.callee(cx)->isSelfHostedOrIntrinsic() &&
    1721             :                    !iter.callee(cx)->isBoundFunction());
    1722           0 :         JSAutoByteString funNameBytes;
    1723           0 :         const char* funName = GetFunctionNameBytes(cx, iter.callee(cx), &funNameBytes);
    1724           0 :         if (!funName)
    1725           0 :             return false;
    1726           0 :         if (strcmp(funName, "IsTypedArrayEnsuringArrayBuffer") != 0) {
    1727           0 :             JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_METHOD,
    1728           0 :                                        funName, "method", InformalValueTypeName(args.thisv()));
    1729           0 :             return false;
    1730             :         }
    1731           0 :         ++iter;
    1732             :     }
    1733             : 
    1734           0 :     MOZ_ASSERT_UNREACHABLE("How did we not find a useful self-hosted frame?");
    1735             :     return false;
    1736             : }
    1737             : 
    1738             : /**
    1739             :  * Returns the default locale as a well-formed, but not necessarily canonicalized,
    1740             :  * BCP-47 language tag.
    1741             :  */
    1742             : static bool
    1743           0 : intrinsic_RuntimeDefaultLocale(JSContext* cx, unsigned argc, Value* vp)
    1744             : {
    1745           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1746             : 
    1747           0 :     const char* locale = cx->runtime()->getDefaultLocale();
    1748           0 :     if (!locale) {
    1749           0 :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEFAULT_LOCALE_ERROR);
    1750           0 :         return false;
    1751             :     }
    1752             : 
    1753           0 :     JSString* jslocale = JS_NewStringCopyZ(cx, locale);
    1754           0 :     if (!jslocale)
    1755           0 :         return false;
    1756             : 
    1757           0 :     args.rval().setString(jslocale);
    1758           0 :     return true;
    1759             : }
    1760             : 
    1761             : using GetOrCreateIntlConstructor = JSFunction* (*)(JSContext*, Handle<GlobalObject*>);
    1762             : 
    1763             : template <GetOrCreateIntlConstructor getOrCreateIntlConstructor>
    1764             : static bool
    1765           0 : intrinsic_GetBuiltinIntlConstructor(JSContext* cx, unsigned argc, Value* vp)
    1766             : {
    1767           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1768           0 :     MOZ_ASSERT(args.length() == 0);
    1769             : 
    1770           0 :     JSFunction* constructor = getOrCreateIntlConstructor(cx, cx->global());
    1771           0 :     if (!constructor)
    1772           0 :         return false;
    1773             : 
    1774           0 :     args.rval().setObject(*constructor);
    1775           0 :     return true;
    1776             : }
    1777             : 
    1778             : static bool
    1779           0 : intrinsic_AddContentTelemetry(JSContext* cx, unsigned argc, Value* vp)
    1780             : {
    1781           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1782           0 :     MOZ_ASSERT(args.length() == 2);
    1783             : 
    1784           0 :     int id = args[0].toInt32();
    1785           0 :     MOZ_ASSERT(id < JS_TELEMETRY_END);
    1786           0 :     MOZ_ASSERT(id >= 0);
    1787             : 
    1788           0 :     if (!cx->compartment()->isProbablySystemOrAddonCode())
    1789           0 :         cx->runtime()->addTelemetry(id, args[1].toInt32());
    1790             : 
    1791           0 :     args.rval().setUndefined();
    1792           0 :     return true;
    1793             : }
    1794             : 
    1795             : static bool
    1796           0 : intrinsic_WarnDeprecatedStringMethod(JSContext* cx, unsigned argc, Value* vp)
    1797             : {
    1798           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1799           0 :     MOZ_ASSERT(args.length() == 2);
    1800           0 :     MOZ_ASSERT(args[0].isInt32());
    1801           0 :     MOZ_ASSERT(args[1].isString());
    1802             : 
    1803           0 :     uint32_t id = uint32_t(args[0].toInt32());
    1804           0 :     MOZ_ASSERT(id < STRING_GENERICS_METHODS_LIMIT);
    1805             : 
    1806           0 :     uint32_t mask = (1 << id);
    1807           0 :     if (!(cx->compartment()->warnedAboutStringGenericsMethods & mask)) {
    1808           0 :         JSFlatString* name = args[1].toString()->ensureFlat(cx);
    1809           0 :         if (!name)
    1810           0 :             return false;
    1811             : 
    1812           0 :         AutoStableStringChars stableChars(cx);
    1813           0 :         if (!stableChars.initTwoByte(cx, name))
    1814           0 :             return false;
    1815           0 :         const char16_t* nameChars = stableChars.twoByteRange().begin().get();
    1816             : 
    1817           0 :         if (!JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_WARNING, GetErrorMessage, nullptr,
    1818             :                                             JSMSG_DEPRECATED_STRING_METHOD, nameChars, nameChars))
    1819             :         {
    1820           0 :             return false;
    1821             :         }
    1822           0 :         cx->compartment()->warnedAboutStringGenericsMethods |= mask;
    1823             :     }
    1824             : 
    1825           0 :     args.rval().setUndefined();
    1826           0 :     return true;
    1827             : }
    1828             : 
    1829             : static bool
    1830           0 : intrinsic_ConstructFunction(JSContext* cx, unsigned argc, Value* vp)
    1831             : {
    1832           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1833           0 :     MOZ_ASSERT(args.length() == 3);
    1834           0 :     MOZ_ASSERT(IsConstructor(args[0]));
    1835           0 :     MOZ_ASSERT(IsConstructor(args[1]));
    1836           0 :     MOZ_ASSERT(args[2].toObject().is<ArrayObject>());
    1837             : 
    1838           0 :     RootedArrayObject argsList(cx, &args[2].toObject().as<ArrayObject>());
    1839           0 :     uint32_t len = argsList->length();
    1840           0 :     ConstructArgs constructArgs(cx);
    1841           0 :     if (!constructArgs.init(cx, len))
    1842           0 :         return false;
    1843           0 :     for (uint32_t index = 0; index < len; index++)
    1844           0 :         constructArgs[index].set(argsList->getDenseElement(index));
    1845             : 
    1846           0 :     RootedObject res(cx);
    1847           0 :     if (!Construct(cx, args[0], constructArgs, args[1], &res))
    1848           0 :         return false;
    1849             : 
    1850           0 :     args.rval().setObject(*res);
    1851           0 :     return true;
    1852             : }
    1853             : 
    1854             : 
    1855             : static bool
    1856         118 : intrinsic_IsConstructing(JSContext* cx, unsigned argc, Value* vp)
    1857             : {
    1858         118 :     CallArgs args = CallArgsFromVp(argc, vp);
    1859         118 :     MOZ_ASSERT(args.length() == 0);
    1860             : 
    1861         236 :     ScriptFrameIter iter(cx);
    1862         118 :     bool isConstructing = iter.isConstructing();
    1863         118 :     args.rval().setBoolean(isConstructing);
    1864         236 :     return true;
    1865             : }
    1866             : 
    1867             : static bool
    1868           0 : intrinsic_ConstructorForTypedArray(JSContext* cx, unsigned argc, Value* vp)
    1869             : {
    1870           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1871           0 :     MOZ_ASSERT(args.length() == 1);
    1872           0 :     MOZ_ASSERT(args[0].isObject());
    1873             : 
    1874           0 :     RootedObject object(cx, &args[0].toObject());
    1875           0 :     object = CheckedUnwrap(object);
    1876           0 :     MOZ_ASSERT(object->is<TypedArrayObject>());
    1877             : 
    1878           0 :     JSProtoKey protoKey = StandardProtoKeyOrNull(object);
    1879           0 :     MOZ_ASSERT(protoKey);
    1880             : 
    1881             :     // While it may seem like an invariant that in any compartment,
    1882             :     // seeing a typed array object implies that the TypedArray constructor
    1883             :     // for that type is initialized on the compartment's global, this is not
    1884             :     // the case. When we construct a typed array given a cross-compartment
    1885             :     // ArrayBuffer, we put the constructed TypedArray in the same compartment
    1886             :     // as the ArrayBuffer. Since we use the prototype from the initial
    1887             :     // compartment, and never call the constructor in the ArrayBuffer's
    1888             :     // compartment from script, we are not guaranteed to have initialized
    1889             :     // the constructor.
    1890           0 :     RootedObject ctor(cx);
    1891           0 :     if (!GetBuiltinConstructor(cx, protoKey, &ctor))
    1892           0 :         return false;
    1893             : 
    1894           0 :     args.rval().setObject(*ctor);
    1895           0 :     return true;
    1896             : }
    1897             : 
    1898             : static bool
    1899           0 : intrinsic_NameForTypedArray(JSContext* cx, unsigned argc, Value* vp)
    1900             : {
    1901           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1902           0 :     MOZ_ASSERT(args.length() == 1);
    1903           0 :     MOZ_ASSERT(args[0].isObject());
    1904             : 
    1905           0 :     RootedObject object(cx, &args[0].toObject());
    1906           0 :     MOZ_ASSERT(object->is<TypedArrayObject>());
    1907             : 
    1908           0 :     JSProtoKey protoKey = StandardProtoKeyOrNull(object);
    1909           0 :     MOZ_ASSERT(protoKey);
    1910             : 
    1911           0 :     args.rval().setString(ClassName(protoKey, cx));
    1912           0 :     return true;
    1913             : }
    1914             : 
    1915             : static bool
    1916           0 : intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc, Value* vp)
    1917             : {
    1918           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1919           0 :     MOZ_ASSERT(args.length() == 2);
    1920           0 :     MOZ_ASSERT(args[0].toObject().is<ModuleObject>());
    1921           0 :     MOZ_ASSERT(args[1].isString());
    1922             : 
    1923           0 :     RootedFunction moduleResolveHook(cx, cx->global()->moduleResolveHook());
    1924           0 :     if (!moduleResolveHook) {
    1925           0 :         JS_ReportErrorASCII(cx, "Module resolve hook not set");
    1926           0 :         return false;
    1927             :     }
    1928             : 
    1929           0 :     RootedValue result(cx);
    1930           0 :     if (!JS_CallFunction(cx, nullptr, moduleResolveHook, args, &result))
    1931           0 :         return false;
    1932             : 
    1933           0 :     if (!result.isObject() || !result.toObject().is<ModuleObject>()) {
    1934           0 :         JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
    1935           0 :         return false;
    1936             :     }
    1937             : 
    1938           0 :     args.rval().set(result);
    1939           0 :     return true;
    1940             : }
    1941             : 
    1942             : static bool
    1943           0 : intrinsic_CreateModuleEnvironment(JSContext* cx, unsigned argc, Value* vp)
    1944             : {
    1945           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1946           0 :     MOZ_ASSERT(args.length() == 1);
    1947           0 :     RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
    1948           0 :     module->createEnvironment();
    1949           0 :     args.rval().setUndefined();
    1950           0 :     return true;
    1951             : }
    1952             : 
    1953             : static bool
    1954           0 : intrinsic_CreateImportBinding(JSContext* cx, unsigned argc, Value* vp)
    1955             : {
    1956           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1957           0 :     MOZ_ASSERT(args.length() == 4);
    1958           0 :     RootedModuleEnvironmentObject environment(cx, &args[0].toObject().as<ModuleEnvironmentObject>());
    1959           0 :     RootedAtom importedName(cx, &args[1].toString()->asAtom());
    1960           0 :     RootedModuleObject module(cx, &args[2].toObject().as<ModuleObject>());
    1961           0 :     RootedAtom localName(cx, &args[3].toString()->asAtom());
    1962           0 :     if (!environment->createImportBinding(cx, importedName, module, localName))
    1963           0 :         return false;
    1964             : 
    1965           0 :     args.rval().setUndefined();
    1966           0 :     return true;
    1967             : }
    1968             : 
    1969             : static bool
    1970           0 : intrinsic_CreateNamespaceBinding(JSContext* cx, unsigned argc, Value* vp)
    1971             : {
    1972           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1973           0 :     MOZ_ASSERT(args.length() == 3);
    1974           0 :     RootedModuleEnvironmentObject environment(cx, &args[0].toObject().as<ModuleEnvironmentObject>());
    1975           0 :     RootedId name(cx, AtomToId(&args[1].toString()->asAtom()));
    1976           0 :     MOZ_ASSERT(args[2].toObject().is<ModuleNamespaceObject>());
    1977             :     // The property already exists in the evironment but is not writable, so set
    1978             :     // the slot directly.
    1979           0 :     RootedShape shape(cx, environment->lookup(cx, name));
    1980           0 :     MOZ_ASSERT(shape);
    1981           0 :     MOZ_ASSERT(environment->getSlot(shape->slot()).isMagic(JS_UNINITIALIZED_LEXICAL));
    1982           0 :     environment->setSlot(shape->slot(), args[2]);
    1983           0 :     args.rval().setUndefined();
    1984           0 :     return true;
    1985             : }
    1986             : 
    1987             : static bool
    1988           0 : intrinsic_InstantiateModuleFunctionDeclarations(JSContext* cx, unsigned argc, Value* vp)
    1989             : {
    1990           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    1991           0 :     MOZ_ASSERT(args.length() == 1);
    1992           0 :     RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
    1993           0 :     args.rval().setUndefined();
    1994           0 :     return ModuleObject::instantiateFunctionDeclarations(cx, module);
    1995             : }
    1996             : 
    1997             : static bool
    1998           0 : intrinsic_SetModuleState(JSContext* cx, unsigned argc, Value* vp)
    1999             : {
    2000           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2001           0 :     MOZ_ASSERT(args.length() == 2);
    2002           0 :     RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
    2003           0 :     ModuleState newState = args[1].toInt32();
    2004           0 :     module->setState(newState);
    2005           0 :     args.rval().setUndefined();
    2006           0 :     return true;
    2007             : }
    2008             : 
    2009             : static bool
    2010           0 : intrinsic_EvaluateModule(JSContext* cx, unsigned argc, Value* vp)
    2011             : {
    2012           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2013           0 :     MOZ_ASSERT(args.length() == 1);
    2014           0 :     RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
    2015           0 :     return ModuleObject::evaluate(cx, module, args.rval());
    2016             : }
    2017             : 
    2018             : static bool
    2019           0 : intrinsic_NewModuleNamespace(JSContext* cx, unsigned argc, Value* vp)
    2020             : {
    2021           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2022           0 :     MOZ_ASSERT(args.length() == 2);
    2023           0 :     RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
    2024           0 :     RootedObject exports(cx, &args[1].toObject());
    2025           0 :     JSObject* namespace_ = ModuleObject::createNamespace(cx, module, exports);
    2026           0 :     if (!namespace_)
    2027           0 :         return false;
    2028             : 
    2029           0 :     args.rval().setObject(*namespace_);
    2030           0 :     return true;
    2031             : }
    2032             : 
    2033             : static bool
    2034           0 : intrinsic_AddModuleNamespaceBinding(JSContext* cx, unsigned argc, Value* vp)
    2035             : {
    2036           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2037           0 :     MOZ_ASSERT(args.length() == 4);
    2038           0 :     RootedModuleNamespaceObject namespace_(cx, &args[0].toObject().as<ModuleNamespaceObject>());
    2039           0 :     RootedAtom exportedName(cx, &args[1].toString()->asAtom());
    2040           0 :     RootedModuleObject targetModule(cx, &args[2].toObject().as<ModuleObject>());
    2041           0 :     RootedAtom localName(cx, &args[3].toString()->asAtom());
    2042           0 :     if (!namespace_->addBinding(cx, exportedName, targetModule, localName))
    2043           0 :         return false;
    2044             : 
    2045           0 :     args.rval().setUndefined();
    2046           0 :     return true;
    2047             : }
    2048             : 
    2049             : static bool
    2050           0 : intrinsic_ModuleNamespaceExports(JSContext* cx, unsigned argc, Value* vp)
    2051             : {
    2052           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2053           0 :     MOZ_ASSERT(args.length() == 1);
    2054           0 :     RootedModuleNamespaceObject namespace_(cx, &args[0].toObject().as<ModuleNamespaceObject>());
    2055           0 :     args.rval().setObject(namespace_->exports());
    2056           0 :     return true;
    2057             : }
    2058             : 
    2059             : static bool
    2060           0 : intrinsic_CreatePendingPromise(JSContext* cx, unsigned argc, Value* vp)
    2061             : {
    2062           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2063           0 :     MOZ_ASSERT(args.length() == 0);
    2064           0 :     JSObject* promise = PromiseObject::createSkippingExecutor(cx);
    2065           0 :     if (!promise)
    2066           0 :         return false;
    2067           0 :     args.rval().setObject(*promise);
    2068           0 :     return true;
    2069             : }
    2070             : 
    2071             : static bool
    2072           0 : intrinsic_CreatePromiseResolvedWith(JSContext* cx, unsigned argc, Value* vp)
    2073             : {
    2074           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2075           0 :     MOZ_ASSERT(args.length() == 1);
    2076           0 :     JSObject* promise = PromiseObject::unforgeableResolve(cx, args[0]);
    2077           0 :     if (!promise)
    2078           0 :         return false;
    2079           0 :     args.rval().setObject(*promise);
    2080           0 :     return true;
    2081             : }
    2082             : 
    2083             : static bool
    2084           0 : intrinsic_CreatePromiseRejectedWith(JSContext* cx, unsigned argc, Value* vp)
    2085             : {
    2086           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2087           0 :     MOZ_ASSERT(args.length() == 1);
    2088           0 :     JSObject* promise = PromiseObject::unforgeableReject(cx, args[0]);
    2089           0 :     if (!promise)
    2090           0 :         return false;
    2091           0 :     args.rval().setObject(*promise);
    2092           0 :     return true;
    2093             : }
    2094             : 
    2095             : static bool
    2096           0 : intrinsic_ResolvePromise(JSContext* cx, unsigned argc, Value* vp)
    2097             : {
    2098           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2099           0 :     MOZ_ASSERT(args.length() == 2);
    2100           0 :     Rooted<PromiseObject*> promise(cx, &args[0].toObject().as<PromiseObject>());
    2101           0 :     if (!PromiseObject::resolve(cx, promise, args[1]))
    2102           0 :         return false;
    2103           0 :     args.rval().setUndefined();
    2104           0 :     return true;
    2105             : }
    2106             : 
    2107             : static bool
    2108           0 : intrinsic_RejectPromise(JSContext* cx, unsigned argc, Value* vp)
    2109             : {
    2110           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2111           0 :     MOZ_ASSERT(args.length() == 2);
    2112           0 :     Rooted<PromiseObject*> promise(cx, &args[0].toObject().as<PromiseObject>());
    2113           0 :     if (!PromiseObject::reject(cx, promise, args[1]))
    2114           0 :         return false;
    2115           0 :     args.rval().setUndefined();
    2116           0 :     return true;
    2117             : }
    2118             : 
    2119             : static bool
    2120           0 : intrinsic_CallOriginalPromiseThen(JSContext* cx, unsigned argc, Value* vp)
    2121             : {
    2122           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2123           0 :     MOZ_ASSERT(args.length() >= 2);
    2124             : 
    2125           0 :     RootedObject promise(cx, &args[0].toObject());
    2126           0 :     Value val = args[1];
    2127           0 :     RootedObject onResolvedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
    2128           0 :     val = args.get(2);
    2129           0 :     RootedObject onRejectedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
    2130             : 
    2131           0 :     JSObject* resultPromise = JS::CallOriginalPromiseThen(cx, promise, onResolvedObj,
    2132           0 :                                                           onRejectedObj);
    2133           0 :     if (!resultPromise)
    2134           0 :         return false;
    2135           0 :     args.rval().setObject(*resultPromise);
    2136           0 :     return true;
    2137             : }
    2138             : 
    2139             : static bool
    2140           0 : intrinsic_AddPromiseReactions(JSContext* cx, unsigned argc, Value* vp)
    2141             : {
    2142           0 :     CallArgs args = CallArgsFromVp(argc, vp);
    2143           0 :     MOZ_ASSERT(args.length() >= 2);
    2144             : 
    2145           0 :     RootedObject promise(cx, &args[0].toObject());
    2146           0 :     Value val = args[1];
    2147           0 :     RootedObject onResolvedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
    2148           0 :     val = args.get(2);
    2149           0 :     RootedObject onRejectedObj(cx, val.isUndefined() ? nullptr : val.toObjectOrNull());
    2150             : 
    2151           0 :     if (!JS::AddPromiseReactions(cx, promise, onResolvedObj, onRejectedObj))
    2152           0 :         return false;
    2153           0 :     args.rval().setUndefined();
    2154           0 :     return true;
    2155             : }
    2156             : 
    2157             : // The self-hosting global isn't initialized with the normal set of builtins.
    2158             : // Instead, individual C++-implemented functions that're required by
    2159             : // self-hosted code are defined as global functions. Accessing these
    2160             : // functions via a content compartment's builtins would be unsafe, because
    2161             : // content script might have changed the builtins' prototypes' members.
    2162             : // Installing the whole set of builtins in the self-hosting compartment, OTOH,
    2163             : // would be wasteful: it increases memory usage and initialization time for
    2164             : // self-hosting compartment.
    2165             : //
    2166             : // Additionally, a set of C++-implemented helper functions is defined on the
    2167             : // self-hosting global.
    2168             : static const JSFunctionSpec intrinsic_functions[] = {
    2169             :     JS_INLINABLE_FN("std_Array",                 array_construct,              1,0, Array),
    2170             :     JS_FN("std_Array_join",                      array_join,                   1,0),
    2171             :     JS_INLINABLE_FN("std_Array_push",            array_push,                   1,0, ArrayPush),
    2172             :     JS_INLINABLE_FN("std_Array_pop",             array_pop,                    0,0, ArrayPop),
    2173             :     JS_INLINABLE_FN("std_Array_shift",           array_shift,                  0,0, ArrayShift),
    2174             :     JS_FN("std_Array_unshift",                   array_unshift,                1,0),
    2175             :     JS_INLINABLE_FN("std_Array_slice",           array_slice,                  2,0, ArraySlice),
    2176             :     JS_FN("std_Array_sort",                      array_sort,                   1,0),
    2177             :     JS_FN("std_Array_reverse",                   array_reverse,                0,0),
    2178             :     JS_FNINFO("std_Array_splice",                array_splice, &array_splice_info, 2,0),
    2179             : 
    2180             :     JS_FN("std_Date_now",                        date_now,                     0,0),
    2181             :     JS_FN("std_Date_valueOf",                    date_valueOf,                 0,0),
    2182             : 
    2183             :     JS_FN("std_Function_apply",                  fun_apply,                    2,0),
    2184             : 
    2185             :     JS_INLINABLE_FN("std_Math_floor",            math_floor,                   1,0, MathFloor),
    2186             :     JS_INLINABLE_FN("std_Math_max",              math_max,                     2,0, MathMax),
    2187             :     JS_INLINABLE_FN("std_Math_min",              math_min,                     2,0, MathMin),
    2188             :     JS_INLINABLE_FN("std_Math_abs",              math_abs,                     1,0, MathAbs),
    2189             : 
    2190             :     JS_FN("std_Map_has",                         MapObject::has,               1,0),
    2191             :     JS_FN("std_Map_iterator",                    MapObject::entries,           0,0),
    2192             : 
    2193             :     JS_FN("std_Number_valueOf",                  num_valueOf,                  0,0),
    2194             : 
    2195             :     JS_INLINABLE_FN("std_Object_create",         obj_create,                   2, 0, ObjectCreate),
    2196             :     JS_FN("std_Object_propertyIsEnumerable",     obj_propertyIsEnumerable,     1,0),
    2197             :     JS_FN("std_Object_defineProperty",           obj_defineProperty,           3,0),
    2198             :     JS_FN("std_Object_getOwnPropertyNames",      obj_getOwnPropertyNames,      1,0),
    2199             :     JS_FN("std_Object_getOwnPropertyDescriptor", obj_getOwnPropertyDescriptor, 2,0),
    2200             :     JS_FN("std_Object_toString",                 obj_toString,                 0,0),
    2201             : 
    2202             :     JS_FN("std_Reflect_getPrototypeOf",          Reflect_getPrototypeOf,       1,0),
    2203             :     JS_FN("std_Reflect_isExtensible",            Reflect_isExtensible,         1,0),
    2204             : 
    2205             :     JS_FN("std_Set_has",                         SetObject::has,               1,0),
    2206             :     JS_FN("std_Set_iterator",                    SetObject::values,            0,0),
    2207             : 
    2208             :     JS_INLINABLE_FN("std_String_fromCharCode",   str_fromCharCode,             1,0, StringFromCharCode),
    2209             :     JS_INLINABLE_FN("std_String_fromCodePoint",  str_fromCodePoint,            1,0, StringFromCodePoint),
    2210             :     JS_INLINABLE_FN("std_String_charCodeAt",     str_charCodeAt,               1,0, StringCharCodeAt),
    2211             :     JS_FN("std_String_includes",                 str_includes,                 1,0),
    2212             :     JS_FN("std_String_indexOf",                  str_indexOf,                  1,0),
    2213             :     JS_FN("std_String_lastIndexOf",              str_lastIndexOf,              1,0),
    2214             :     JS_FN("std_String_startsWith",               str_startsWith,               1,0),
    2215             :     JS_FN("std_String_toLowerCase",              str_toLowerCase,              0,0),
    2216             :     JS_FN("std_String_toUpperCase",              str_toUpperCase,              0,0),
    2217             : 
    2218             :     JS_INLINABLE_FN("std_String_charAt",         str_charAt,                   1,0, StringCharAt),
    2219             :     JS_FN("std_String_endsWith",                 str_endsWith,                 1,0),
    2220             :     JS_FN("std_String_trim",                     str_trim,                     0,0),
    2221             :     JS_FN("std_String_trimLeft",                 str_trimLeft,                 0,0),
    2222             :     JS_FN("std_String_trimRight",                str_trimRight,                0,0),
    2223             : #if !EXPOSE_INTL_API
    2224             :     JS_FN("std_String_toLocaleLowerCase",        str_toLocaleLowerCase,        0,0),
    2225             :     JS_FN("std_String_toLocaleUpperCase",        str_toLocaleUpperCase,        0,0),
    2226             :     JS_FN("std_String_localeCompare",            str_localeCompare,            1,0),
    2227             : #else
    2228             :     JS_FN("std_String_normalize",                str_normalize,                0,0),
    2229             : #endif
    2230             :     JS_FN("std_String_concat",                   str_concat,                   1,0),
    2231             : 
    2232             :     JS_FN("std_TypedArray_buffer",               js::TypedArray_bufferGetter,  1,0),
    2233             : 
    2234             :     JS_FN("std_WeakMap_has",                     WeakMap_has,                  1,0),
    2235             :     JS_FN("std_WeakMap_get",                     WeakMap_get,                  2,0),
    2236             :     JS_FN("std_WeakMap_set",                     WeakMap_set,                  2,0),
    2237             :     JS_FN("std_WeakMap_delete",                  WeakMap_delete,               1,0),
    2238             : 
    2239             :     JS_FN("std_SIMD_Int8x16_extractLane",        simd_int8x16_extractLane,     2,0),
    2240             :     JS_FN("std_SIMD_Int16x8_extractLane",        simd_int16x8_extractLane,     2,0),
    2241             :     JS_INLINABLE_FN("std_SIMD_Int32x4_extractLane",   simd_int32x4_extractLane,  2,0, SimdInt32x4_extractLane),
    2242             :     JS_FN("std_SIMD_Uint8x16_extractLane",       simd_uint8x16_extractLane,    2,0),
    2243             :     JS_FN("std_SIMD_Uint16x8_extractLane",       simd_uint16x8_extractLane,    2,0),
    2244             :     JS_FN("std_SIMD_Uint32x4_extractLane",       simd_uint32x4_extractLane,    2,0),
    2245             :     JS_INLINABLE_FN("std_SIMD_Float32x4_extractLane", simd_float32x4_extractLane,2,0, SimdFloat32x4_extractLane),
    2246             :     JS_FN("std_SIMD_Float64x2_extractLane",      simd_float64x2_extractLane,   2,0),
    2247             :     JS_FN("std_SIMD_Bool8x16_extractLane",       simd_bool8x16_extractLane,    2,0),
    2248             :     JS_FN("std_SIMD_Bool16x8_extractLane",       simd_bool16x8_extractLane,    2,0),
    2249             :     JS_FN("std_SIMD_Bool32x4_extractLane",       simd_bool32x4_extractLane,    2,0),
    2250             :     JS_FN("std_SIMD_Bool64x2_extractLane",       simd_bool64x2_extractLane,    2,0),
    2251             : 
    2252             :     // Helper funtions after this point.
    2253             :     JS_INLINABLE_FN("ToObject",      intrinsic_ToObject,                1,0, IntrinsicToObject),
    2254             :     JS_INLINABLE_FN("IsObject",      intrinsic_IsObject,                1,0, IntrinsicIsObject),
    2255             :     JS_INLINABLE_FN("IsArray",       intrinsic_IsArray,                 1,0, ArrayIsArray),
    2256             :     JS_INLINABLE_FN("IsWrappedArrayConstructor", intrinsic_IsWrappedArrayConstructor, 1,0,
    2257             :                     IntrinsicIsWrappedArrayConstructor),
    2258             :     JS_INLINABLE_FN("ToInteger",     intrinsic_ToInteger,               1,0, IntrinsicToInteger),
    2259             :     JS_INLINABLE_FN("ToString",      intrinsic_ToString,                1,0, IntrinsicToString),
    2260             :     JS_FN("ToSource",                intrinsic_ToSource,                1,0),
    2261             :     JS_FN("ToPropertyKey",           intrinsic_ToPropertyKey,           1,0),
    2262             :     JS_INLINABLE_FN("IsCallable",    intrinsic_IsCallable,              1,0, IntrinsicIsCallable),
    2263             :     JS_INLINABLE_FN("IsConstructor", intrinsic_IsConstructor,           1,0,
    2264             :                     IntrinsicIsConstructor),
    2265             :     JS_FN("GetBuiltinConstructorImpl", intrinsic_GetBuiltinConstructor, 1,0),
    2266             :     JS_FN("MakeConstructible",       intrinsic_MakeConstructible,       2,0),
    2267             :     JS_FN("_ConstructFunction",      intrinsic_ConstructFunction,       2,0),
    2268             :     JS_FN("ThrowRangeError",         intrinsic_ThrowRangeError,         4,0),
    2269             :     JS_FN("ThrowTypeError",          intrinsic_ThrowTypeError,          4,0),
    2270             :     JS_FN("ThrowSyntaxError",        intrinsic_ThrowSyntaxError,        4,0),
    2271             :     JS_FN("ThrowInternalError",      intrinsic_ThrowInternalError,      4,0),
    2272             :     JS_FN("AssertionFailed",         intrinsic_AssertionFailed,         1,0),
    2273             :     JS_FN("DumpMessage",             intrinsic_DumpMessage,             1,0),
    2274             :     JS_FN("OwnPropertyKeys",         intrinsic_OwnPropertyKeys,         1,0),
    2275             :     JS_FN("MakeDefaultConstructor",  intrinsic_MakeDefaultConstructor,  2,0),
    2276             :     JS_FN("_ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1,0),
    2277             :     JS_FN("_NameForTypedArray",      intrinsic_NameForTypedArray, 1,0),
    2278             :     JS_FN("DecompileArg",            intrinsic_DecompileArg,            2,0),
    2279             :     JS_INLINABLE_FN("_FinishBoundFunctionInit", intrinsic_FinishBoundFunctionInit, 3,0,
    2280             :                     IntrinsicFinishBoundFunctionInit),
    2281             :     JS_FN("RuntimeDefaultLocale",    intrinsic_RuntimeDefaultLocale,    0,0),
    2282             :     JS_FN("AddContentTelemetry",     intrinsic_AddContentTelemetry,     2,0),
    2283             :     JS_FN("_DefineDataProperty",     intrinsic_DefineDataProperty,      4,0),
    2284             : 
    2285             :     JS_INLINABLE_FN("_IsConstructing", intrinsic_IsConstructing,        0,0,
    2286             :                     IntrinsicIsConstructing),
    2287             :     JS_INLINABLE_FN("SubstringKernel", intrinsic_SubstringKernel,       3,0,
    2288             :                     IntrinsicSubstringKernel),
    2289             :     JS_INLINABLE_FN("ObjectHasPrototype",               intrinsic_ObjectHasPrototype,      2,0,
    2290             :                     IntrinsicObjectHasPrototype),
    2291             :     JS_INLINABLE_FN("UnsafeSetReservedSlot",            intrinsic_UnsafeSetReservedSlot,   3,0,
    2292             :                     IntrinsicUnsafeSetReservedSlot),
    2293             :     JS_INLINABLE_FN("UnsafeGetReservedSlot",            intrinsic_UnsafeGetReservedSlot,   2,0,
    2294             :                     IntrinsicUnsafeGetReservedSlot),
    2295             :     JS_INLINABLE_FN("UnsafeGetObjectFromReservedSlot",  intrinsic_UnsafeGetObjectFromReservedSlot, 2,0,
    2296             :                     IntrinsicUnsafeGetObjectFromReservedSlot),
    2297             :     JS_INLINABLE_FN("UnsafeGetInt32FromReservedSlot",   intrinsic_UnsafeGetInt32FromReservedSlot,  2,0,
    2298             :                     IntrinsicUnsafeGetInt32FromReservedSlot),
    2299             :     JS_INLINABLE_FN("UnsafeGetStringFromReservedSlot",  intrinsic_UnsafeGetStringFromReservedSlot, 2,0,
    2300             :                     IntrinsicUnsafeGetStringFromReservedSlot),
    2301             :     JS_INLINABLE_FN("UnsafeGetBooleanFromReservedSlot", intrinsic_UnsafeGetBooleanFromReservedSlot,2,0,
    2302             :                     IntrinsicUnsafeGetBooleanFromReservedSlot),
    2303             : 
    2304             :     JS_FN("IsPackedArray",           intrinsic_IsPackedArray,           1,0),
    2305             : 
    2306             :     JS_FN("GetIteratorPrototype",    intrinsic_GetIteratorPrototype,    0,0),
    2307             : 
    2308             :     JS_INLINABLE_FN("NewArrayIterator", intrinsic_NewArrayIterator,     0,0,
    2309             :                     IntrinsicNewArrayIterator),
    2310             : 
    2311             :     JS_FN("CallArrayIteratorMethodIfWrapped",
    2312             :           CallNonGenericSelfhostedMethod<Is<ArrayIteratorObject>>,      2,0),
    2313             : 
    2314             :     JS_FN("_SetCanonicalName",       intrinsic_SetCanonicalName,        2,0),
    2315             : 
    2316             :     JS_INLINABLE_FN("IsArrayIterator",
    2317             :                     intrinsic_IsInstanceOfBuiltin<ArrayIteratorObject>, 1,0,
    2318             :                     IntrinsicIsArrayIterator),
    2319             :     JS_INLINABLE_FN("IsMapIterator",
    2320             :                     intrinsic_IsInstanceOfBuiltin<MapIteratorObject>,   1,0,
    2321             :                     IntrinsicIsMapIterator),
    2322             :     JS_INLINABLE_FN("IsSetIterator",
    2323             :                     intrinsic_IsInstanceOfBuiltin<SetIteratorObject>,   1,0,
    2324             :                     IntrinsicIsSetIterator),
    2325             :     JS_INLINABLE_FN("IsStringIterator",
    2326             :                     intrinsic_IsInstanceOfBuiltin<StringIteratorObject>, 1,0,
    2327             :                     IntrinsicIsStringIterator),
    2328             : 
    2329             :     JS_FN("_CreateMapIterationResultPair", intrinsic_CreateMapIterationResultPair, 0, 0),
    2330             :     JS_INLINABLE_FN("_GetNextMapEntryForIterator", intrinsic_GetNextMapEntryForIterator, 2,0,
    2331             :                     IntrinsicGetNextMapEntryForIterator),
    2332             :     JS_FN("CallMapIteratorMethodIfWrapped",
    2333             :           CallNonGenericSelfhostedMethod<Is<MapIteratorObject>>,        2,0),
    2334             : 
    2335             :     JS_FN("_CreateSetIterationResult", intrinsic_CreateSetIterationResult, 0, 0),
    2336             :     JS_INLINABLE_FN("_GetNextSetEntryForIterator", intrinsic_GetNextSetEntryForIterator, 2,0,
    2337             :                     IntrinsicGetNextSetEntryForIterator),
    2338             :     JS_FN("CallSetIteratorMethodIfWrapped",
    2339             :           CallNonGenericSelfhostedMethod<Is<SetIteratorObject>>,        2,0),
    2340             : 
    2341             : 
    2342             :     JS_INLINABLE_FN("NewStringIterator", intrinsic_NewStringIterator,   0,0,
    2343             :                     IntrinsicNewStringIterator),
    2344             :     JS_FN("CallStringIteratorMethodIfWrapped",
    2345             :           CallNonGenericSelfhostedMethod<Is<StringIteratorObject>>,     2,0),
    2346             : 
    2347             :     JS_FN("IsStarGeneratorObject",
    2348             :           intrinsic_IsInstanceOfBuiltin<StarGeneratorObject>,           1,0),
    2349             :     JS_FN("StarGeneratorObjectIsClosed", intrinsic_StarGeneratorObjectIsClosed, 1,0),
    2350             :     JS_FN("IsSuspendedStarGenerator",intrinsic_IsSuspendedStarGenerator,1,0),
    2351             : 
    2352             :     JS_FN("IsLegacyGeneratorObject",
    2353             :           intrinsic_IsInstanceOfBuiltin<LegacyGeneratorObject>,         1,0),
    2354             :     JS_FN("LegacyGeneratorObjectIsClosed", intrinsic_LegacyGeneratorObjectIsClosed, 1,0),
    2355             :     JS_FN("CloseClosingLegacyGeneratorObject", intrinsic_CloseClosingLegacyGeneratorObject, 1,0),
    2356             :     JS_FN("ThrowStopIteration",      intrinsic_ThrowStopIteration,      0,0),
    2357             : 
    2358             :     JS_FN("GeneratorIsRunning",      intrinsic_GeneratorIsRunning,      1,0),
    2359             :     JS_FN("GeneratorSetClosed",      intrinsic_GeneratorSetClosed,      1,0),
    2360             : 
    2361             :     JS_FN("IsArrayBuffer",
    2362             :           intrinsic_IsInstanceOfBuiltin<ArrayBufferObject>,             1,0),
    2363             :     JS_FN("IsSharedArrayBuffer",
    2364             :           intrinsic_IsInstanceOfBuiltin<SharedArrayBufferObject>,       1,0),
    2365             :     JS_FN("IsWrappedArrayBuffer",
    2366             :           intrinsic_IsWrappedArrayBuffer<ArrayBufferObject>,            1,0),
    2367             :     JS_FN("IsWrappedSharedArrayBuffer",
    2368             :           intrinsic_IsWrappedArrayBuffer<SharedArrayBufferObject>,      1,0),
    2369             : 
    2370             :     JS_INLINABLE_FN("ArrayBufferByteLength",
    2371             :                     intrinsic_ArrayBufferByteLength<ArrayBufferObject>, 1,0,
    2372             :                     IntrinsicArrayBufferByteLength),
    2373             :     JS_INLINABLE_FN("PossiblyWrappedArrayBufferByteLength",
    2374             :                     intrinsic_PossiblyWrappedArrayBufferByteLength<ArrayBufferObject>, 1,0,
    2375             :                     IntrinsicPossiblyWrappedArrayBufferByteLength),
    2376             :     JS_FN("ArrayBufferCopyData",
    2377             :           intrinsic_ArrayBufferCopyData<ArrayBufferObject>,             6,0),
    2378             : 
    2379             :     JS_FN("SharedArrayBufferByteLength",
    2380             :           intrinsic_ArrayBufferByteLength<SharedArrayBufferObject>,     1,0),
    2381             :     JS_FN("PossiblyWrappedSharedArrayBufferByteLength",
    2382             :           intrinsic_PossiblyWrappedArrayBufferByteLength<SharedArrayBufferObject>, 1,0),
    2383             :     JS_FN("SharedArrayBufferCopyData",
    2384             :           intrinsic_ArrayBufferCopyData<SharedArrayBufferObject>,       6,0),
    2385             :     JS_FN("SharedArrayBuffersMemorySame",
    2386             :           intrinsic_SharedArrayBuffersMemorySame,                       2,0),
    2387             : 
    2388             :     JS_FN("IsUint8TypedArray",        intrinsic_IsUint8TypedArray,      1,0),
    2389             :     JS_FN("IsInt8TypedArray",         intrinsic_IsInt8TypedArray,       1,0),
    2390             :     JS_FN("IsUint16TypedArray",       intrinsic_IsUint16TypedArray,     1,0),
    2391             :     JS_FN("IsInt16TypedArray",        intrinsic_IsInt16TypedArray,      1,0),
    2392             :     JS_FN("IsUint32TypedArray",       intrinsic_IsUint32TypedArray,     1,0),
    2393             :     JS_FN("IsInt32TypedArray",        intrinsic_IsInt32TypedArray,      1,0),
    2394             :     JS_FN("IsFloat32TypedArray",      intrinsic_IsFloat32TypedArray,    1,0),
    2395             :     JS_INLINABLE_FN("IsTypedArray",
    2396             :                     intrinsic_IsInstanceOfBuiltin<TypedArrayObject>,    1,0,
    2397             :                     IntrinsicIsTypedArray),
    2398             :     JS_INLINABLE_FN("IsPossiblyWrappedTypedArray",intrinsic_IsPossiblyWrappedTypedArray,1,0,
    2399             :                     IntrinsicIsPossiblyWrappedTypedArray),
    2400             : 
    2401             :     JS_FN("TypedArrayBuffer",        intrinsic_TypedArrayBuffer,        1,0),
    2402             :     JS_FN("TypedArrayByteOffset",    intrinsic_TypedArrayByteOffset,    1,0),
    2403             :     JS_FN("TypedArrayElementShift",  intrinsic_TypedArrayElementShift,  1,0),
    2404             : 
    2405             :     JS_INLINABLE_FN("TypedArrayLength", intrinsic_TypedArrayLength,     1,0,
    2406             :                     IntrinsicTypedArrayLength),
    2407             :     JS_INLINABLE_FN("PossiblyWrappedTypedArrayLength", intrinsic_PossiblyWrappedTypedArrayLength,
    2408             :                     1, 0, IntrinsicPossiblyWrappedTypedArrayLength),
    2409             :     JS_FN("PossiblyWrappedTypedArrayHasDetachedBuffer",
    2410             :           intrinsic_PossiblyWrappedTypedArrayHasDetachedBuffer, 1, 0),
    2411             : 
    2412             :     JS_FN("MoveTypedArrayElements",  intrinsic_MoveTypedArrayElements,  4,0),
    2413             :     JS_FN("SetFromTypedArrayApproach",intrinsic_SetFromTypedArrayApproach, 4, 0),
    2414             :     JS_FN("SetOverlappingTypedElements",intrinsic_SetOverlappingTypedElements,3,0),
    2415             : 
    2416             :     JS_INLINABLE_FN("SetDisjointTypedElements",intrinsic_SetDisjointTypedElements,3,0,
    2417             :                     IntrinsicSetDisjointTypedElements),
    2418             : 
    2419             :     JS_FN("CallArrayBufferMethodIfWrapped",
    2420             :           CallNonGenericSelfhostedMethod<Is<ArrayBufferObject>>, 2, 0),
    2421             :     JS_FN("CallSharedArrayBufferMethodIfWrapped",
    2422             :           CallNonGenericSelfhostedMethod<Is<SharedArrayBufferObject>>, 2, 0),
    2423             :     JS_FN("CallTypedArrayMethodIfWrapped",
    2424             :           CallNonGenericSelfhostedMethod<Is<TypedArrayObject>>, 2, 0),
    2425             : 
    2426             :     JS_FN("CallLegacyGeneratorMethodIfWrapped",
    2427             :           CallNonGenericSelfhostedMethod<Is<LegacyGeneratorObject>>, 2, 0),
    2428             :     JS_FN("CallStarGeneratorMethodIfWrapped",
    2429             :           CallNonGenericSelfhostedMethod<Is<StarGeneratorObject>>, 2, 0),
    2430             : 
    2431             :     JS_FN("IsWeakSet", intrinsic_IsInstanceOfBuiltin<WeakSetObject>, 1,0),
    2432             :     JS_FN("CallWeakSetMethodIfWrapped",
    2433             :           CallNonGenericSelfhostedMethod<Is<WeakSetObject>>, 2, 0),
    2434             : 
    2435             :     // See builtin/TypedObject.h for descriptors of the typedobj functions.
    2436             :     JS_FN("NewOpaqueTypedObject",           js::NewOpaqueTypedObject, 1, 0),
    2437             :     JS_FN("NewDerivedTypedObject",          js::NewDerivedTypedObject, 3, 0),
    2438             :     JS_FN("TypedObjectBuffer",              TypedObject::GetBuffer, 1, 0),
    2439             :     JS_FN("TypedObjectByteOffset",          TypedObject::GetByteOffset, 1, 0),
    2440             :     JS_FN("AttachTypedObject",              js::AttachTypedObject, 3, 0),
    2441             :     JS_FN("TypedObjectIsAttached",          js::TypedObjectIsAttached, 1, 0),
    2442             :     JS_FN("TypedObjectTypeDescr",           js::TypedObjectTypeDescr, 1, 0),
    2443             :     JS_FN("ClampToUint8",                   js::ClampToUint8, 1, 0),
    2444             :     JS_FN("GetTypedObjectModule",           js::GetTypedObjectModule, 0, 0),
    2445             :     JS_FN("GetSimdTypeDescr",               js::GetSimdTypeDescr, 1, 0),
    2446             : 
    2447             :     JS_INLINABLE_FN("ObjectIsTypeDescr"    ,          js::ObjectIsTypeDescr, 1, 0,
    2448             :                     IntrinsicObjectIsTypeDescr),
    2449             :     JS_INLINABLE_FN("ObjectIsTypedObject",            js::ObjectIsTypedObject, 1, 0,
    2450             :                     IntrinsicObjectIsTypedObject),
    2451             :     JS_INLINABLE_FN("ObjectIsOpaqueTypedObject",      js::ObjectIsOpaqueTypedObject, 1, 0,
    2452             :                     IntrinsicObjectIsOpaqueTypedObject),
    2453             :     JS_INLINABLE_FN("ObjectIsTransparentTypedObject", js::ObjectIsTransparentTypedObject, 1, 0,
    2454             :                     IntrinsicObjectIsTransparentTypedObject),
    2455             :     JS_INLINABLE_FN("TypeDescrIsArrayType",           js::TypeDescrIsArrayType, 1, 0,
    2456             :                     IntrinsicTypeDescrIsArrayType),
    2457             :     JS_INLINABLE_FN("TypeDescrIsSimpleType",          js::TypeDescrIsSimpleType, 1, 0,
    2458             :                     IntrinsicTypeDescrIsSimpleType),
    2459             :     JS_INLINABLE_FN("SetTypedObjectOffset",           js::SetTypedObjectOffset, 2, 0,
    2460             :                     IntrinsicSetTypedObjectOffset),
    2461             : 
    2462             : #define LOAD_AND_STORE_SCALAR_FN_DECLS(_constant, _type, _name)         \
    2463             :     JS_FN("Store_" #_name, js::StoreScalar##_type::Func, 3, 0),         \
    2464             :     JS_FN("Load_" #_name,  js::LoadScalar##_type::Func, 3, 0),
    2465             :     JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(LOAD_AND_STORE_SCALAR_FN_DECLS)
    2466             : #undef LOAD_AND_STORE_SCALAR_FN_DECLS
    2467             : 
    2468             : #define LOAD_AND_STORE_REFERENCE_FN_DECLS(_constant, _type, _name)      \
    2469             :     JS_FN("Store_" #_name, js::StoreReference##_name::Func, 3, 0),      \
    2470             :     JS_FN("Load_" #_name,  js::LoadReference##_name::Func, 3, 0),
    2471             :     JS_FOR_EACH_REFERENCE_TYPE_REPR(LOAD_AND_STORE_REFERENCE_FN_DECLS)
    2472             : #undef LOAD_AND_STORE_REFERENCE_FN_DECLS
    2473             : 
    2474             :     // See builtin/Intl.h for descriptions of the intl_* functions.
    2475             :     JS_FN("intl_availableCalendars", intl_availableCalendars, 1,0),
    2476             :     JS_FN("intl_availableCollations", intl_availableCollations, 1,0),
    2477             :     JS_FN("intl_canonicalizeTimeZone", intl_canonicalizeTimeZone, 1,0),
    2478             :     JS_FN("intl_Collator", intl_Collator, 2,0),
    2479             :     JS_FN("intl_Collator_availableLocales", intl_Collator_availableLocales, 0,0),
    2480             :     JS_FN("intl_CompareStrings", intl_CompareStrings, 3,0),
    2481             :     JS_FN("intl_DateTimeFormat", intl_DateTimeFormat, 2,0),
    2482             :     JS_FN("intl_DateTimeFormat_availableLocales", intl_DateTimeFormat_availableLocales, 0,0),
    2483             :     JS_FN("intl_defaultCalendar", intl_defaultCalendar, 1,0),
    2484             :     JS_FN("intl_defaultTimeZone", intl_defaultTimeZone, 0,0),
    2485             :     JS_FN("intl_defaultTimeZoneOffset", intl_defaultTimeZoneOffset, 0,0),
    2486             :     JS_FN("intl_FormatDateTime", intl_FormatDateTime, 2,0),
    2487             :     JS_FN("intl_FormatNumber", intl_FormatNumber, 2,0),
    2488             :     JS_FN("intl_GetCalendarInfo", intl_GetCalendarInfo, 1,0),
    2489             :     JS_FN("intl_GetLocaleInfo", intl_GetLocaleInfo, 1,0),
    2490             :     JS_FN("intl_ComputeDisplayNames", intl_ComputeDisplayNames, 3,0),
    2491             :     JS_FN("intl_isUpperCaseFirst", intl_isUpperCaseFirst, 1,0),
    2492             :     JS_FN("intl_IsValidTimeZoneName", intl_IsValidTimeZoneName, 1,0),
    2493             :     JS_FN("intl_NumberFormat", intl_NumberFormat, 2,0),
    2494             :     JS_FN("intl_NumberFormat_availableLocales", intl_NumberFormat_availableLocales, 0,0),
    2495             :     JS_FN("intl_numberingSystem", intl_numberingSystem, 1,0),
    2496             :     JS_FN("intl_patternForSkeleton", intl_patternForSkeleton, 2,0),
    2497             :     JS_FN("intl_patternForStyle", intl_patternForStyle, 3,0),
    2498             :     JS_FN("intl_PluralRules_availableLocales", intl_PluralRules_availableLocales, 0,0),
    2499             :     JS_FN("intl_GetPluralCategories", intl_GetPluralCategories, 2, 0),
    2500             :     JS_FN("intl_SelectPluralRule", intl_SelectPluralRule, 2,0),
    2501             :     JS_FN("intl_toLocaleLowerCase", intl_toLocaleLowerCase, 2,0),
    2502             :     JS_FN("intl_toLocaleUpperCase", intl_toLocaleUpperCase, 2,0),
    2503             : 
    2504             :     JS_INLINABLE_FN("IsCollator",
    2505             :                     intrinsic_IsInstanceOfBuiltin<CollatorObject>, 1,0,
    2506             :                     IntlIsCollator),
    2507             :     JS_INLINABLE_FN("IsDateTimeFormat",
    2508             :                     intrinsic_IsInstanceOfBuiltin<DateTimeFormatObject>, 1,0,
    2509             :                     IntlIsDateTimeFormat),
    2510             :     JS_INLINABLE_FN("IsNumberFormat",
    2511             :                     intrinsic_IsInstanceOfBuiltin<NumberFormatObject>, 1,0,
    2512             :                     IntlIsNumberFormat),
    2513             :     JS_INLINABLE_FN("IsPluralRules",
    2514             :                     intrinsic_IsInstanceOfBuiltin<PluralRulesObject>, 1,0,
    2515             :                     IntlIsPluralRules),
    2516             :     JS_FN("GetDateTimeFormatConstructor",
    2517             :           intrinsic_GetBuiltinIntlConstructor<GlobalObject::getOrCreateDateTimeFormatConstructor>,
    2518             :           0,0),
    2519             :     JS_FN("GetNumberFormatConstructor",
    2520             :           intrinsic_GetBuiltinIntlConstructor<GlobalObject::getOrCreateNumberFormatConstructor>,
    2521             :           0,0),
    2522             : 
    2523             :     JS_INLINABLE_FN("IsRegExpObject",
    2524             :                     intrinsic_IsInstanceOfBuiltin<RegExpObject>, 1,0,
    2525             :                     IsRegExpObject),
    2526             :     JS_FN("CallRegExpMethodIfWrapped",
    2527             :           CallNonGenericSelfhostedMethod<Is<RegExpObject>>, 2,0),
    2528             :     JS_INLINABLE_FN("RegExpMatcher", RegExpMatcher, 3,0,
    2529             :                     RegExpMatcher),
    2530             :     JS_INLINABLE_FN("RegExpSearcher", RegExpSearcher, 3,0,
    2531             :                     RegExpSearcher),
    2532             :     JS_INLINABLE_FN("RegExpTester", RegExpTester, 3,0,
    2533             :                     RegExpTester),
    2534             :     JS_FN("RegExpCreate", intrinsic_RegExpCreate, 2,0),
    2535             :     JS_INLINABLE_FN("RegExpPrototypeOptimizable", RegExpPrototypeOptimizable, 1,0,
    2536             :                     RegExpPrototypeOptimizable),
    2537             :     JS_INLINABLE_FN("RegExpInstanceOptimizable", RegExpInstanceOptimizable, 1,0,
    2538             :                     RegExpInstanceOptimizable),
    2539             :     JS_FN("RegExpGetSubstitution", intrinsic_RegExpGetSubstitution, 6,0),
    2540             :     JS_FN("GetElemBaseForLambda", intrinsic_GetElemBaseForLambda, 1,0),
    2541             :     JS_FN("GetStringDataProperty", intrinsic_GetStringDataProperty, 2,0),
    2542             :     JS_INLINABLE_FN("GetFirstDollarIndex", GetFirstDollarIndex, 1,0,
    2543             :                     GetFirstDollarIndex),
    2544             : 
    2545             :     JS_FN("FlatStringMatch", FlatStringMatch, 2,0),
    2546             :     JS_FN("FlatStringSearch", FlatStringSearch, 2,0),
    2547             :     JS_INLINABLE_FN("StringReplaceString", intrinsic_StringReplaceString, 3, 0,
    2548             :                     IntrinsicStringReplaceString),
    2549             :     JS_INLINABLE_FN("StringSplitString", intrinsic_StringSplitString, 2, 0,
    2550             :                     IntrinsicStringSplitString),
    2551             :     JS_FN("StringSplitStringLimit", intrinsic_StringSplitStringLimit, 3, 0),
    2552             :     JS_FN("WarnDeprecatedStringMethod", intrinsic_WarnDeprecatedStringMethod, 2, 0),
    2553             : 
    2554             :     // See builtin/RegExp.h for descriptions of the regexp_* functions.
    2555             :     JS_FN("regexp_exec_no_statics", regexp_exec_no_statics, 2,0),
    2556             :     JS_FN("regexp_test_no_statics", regexp_test_no_statics, 2,0),
    2557             :     JS_FN("regexp_construct_raw_flags", regexp_construct_raw_flags, 2,0),
    2558             : 
    2559             :     JS_FN("IsModule", intrinsic_IsInstanceOfBuiltin<ModuleObject>, 1, 0),
    2560             :     JS_FN("CallModuleMethodIfWrapped",
    2561             :           CallNonGenericSelfhostedMethod<Is<ModuleObject>>, 2, 0),
    2562             :     JS_FN("HostResolveImportedModule", intrinsic_HostResolveImportedModule, 2, 0),
    2563             :     JS_FN("IsModuleEnvironment", intrinsic_IsInstanceOfBuiltin<ModuleEnvironmentObject>, 1, 0),
    2564             :     JS_FN("CreateModuleEnvironment", intrinsic_CreateModuleEnvironment, 1, 0),
    2565             :     JS_FN("CreateImportBinding", intrinsic_CreateImportBinding, 4, 0),
    2566             :     JS_FN("CreateNamespaceBinding", intrinsic_CreateNamespaceBinding, 3, 0),
    2567             :     JS_FN("InstantiateModuleFunctionDeclarations",
    2568             :           intrinsic_InstantiateModuleFunctionDeclarations, 1, 0),
    2569             :     JS_FN("SetModuleState", intrinsic_SetModuleState, 1, 0),
    2570             :     JS_FN("EvaluateModule", intrinsic_EvaluateModule, 1, 0),
    2571             :     JS_FN("NewModuleNamespace", intrinsic_NewModuleNamespace, 2, 0),
    2572             :     JS_FN("AddModuleNamespaceBinding", intrinsic_AddModuleNamespaceBinding, 4, 0),
    2573             :     JS_FN("ModuleNamespaceExports", intrinsic_ModuleNamespaceExports, 1, 0),
    2574             : 
    2575             :     JS_FN("CreatePendingPromise", intrinsic_CreatePendingPromise, 0, 0),
    2576             :     JS_FN("CreatePromiseResolvedWith", intrinsic_CreatePromiseResolvedWith, 1, 0),
    2577             :     JS_FN("CreatePromiseRejectedWith", intrinsic_CreatePromiseRejectedWith, 1, 0),
    2578             :     JS_FN("ResolvePromise", intrinsic_ResolvePromise, 2, 0),
    2579             :     JS_FN("RejectPromise", intrinsic_RejectPromise, 2, 0),
    2580             :     JS_FN("AddPromiseReactions", intrinsic_AddPromiseReactions, 3, 0),
    2581             :     JS_FN("CallOriginalPromiseThen", intrinsic_CallOriginalPromiseThen, 3, 0),
    2582             : 
    2583             :     JS_FS_END
    2584             : };
    2585             : 
    2586             : void
    2587         144 : js::FillSelfHostingCompileOptions(CompileOptions& options)
    2588             : {
    2589             :     /*
    2590             :      * In self-hosting mode, scripts use JSOP_GETINTRINSIC instead of
    2591             :      * JSOP_GETNAME or JSOP_GETGNAME to access unbound variables.
    2592             :      * JSOP_GETINTRINSIC does a name lookup on a special object, whose
    2593             :      * properties are filled in lazily upon first access for a given global.
    2594             :      *
    2595             :      * As that object is inaccessible to client code, the lookups are
    2596             :      * guaranteed to return the original objects, ensuring safe implementation
    2597             :      * of self-hosted builtins.
    2598             :      *
    2599             :      * Additionally, the special syntax callFunction(fun, receiver, ...args)
    2600             :      * is supported, for which bytecode is emitted that invokes |fun| with
    2601             :      * |receiver| as the this-object and ...args as the arguments.
    2602             :      */
    2603         144 :     options.setIntroductionType("self-hosted");
    2604         144 :     options.setFileAndLine("self-hosted", 1);
    2605         144 :     options.setSelfHostingMode(true);
    2606         144 :     options.setCanLazilyParse(false);
    2607         144 :     options.setVersion(JSVERSION_LATEST);
    2608         144 :     options.werrorOption = true;
    2609         144 :     options.strictOption = true;
    2610             : 
    2611             : #ifdef DEBUG
    2612         144 :     options.extraWarningsOption = true;
    2613             : #endif
    2614         144 : }
    2615             : 
    2616             : GlobalObject*
    2617           3 : JSRuntime::createSelfHostingGlobal(JSContext* cx)
    2618             : {
    2619           3 :     MOZ_ASSERT(!cx->isExceptionPending());
    2620           3 :     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
    2621             : 
    2622           3 :     JS::CompartmentOptions options;
    2623           3 :     options.creationOptions().setNewZoneInSystemZoneGroup();
    2624           3 :     options.behaviors().setDiscardSource(true);
    2625             : 
    2626           3 :     JSCompartment* compartment = NewCompartment(cx, nullptr, options);
    2627           3 :     if (!compartment)
    2628           0 :         return nullptr;
    2629             : 
    2630             :     static const ClassOps shgClassOps = {
    2631             :         nullptr, nullptr, nullptr, nullptr,
    2632             :         nullptr, nullptr, nullptr, nullptr,
    2633             :         nullptr, nullptr, nullptr, nullptr,
    2634             :         JS_GlobalObjectTraceHook
    2635             :     };
    2636             : 
    2637             :     static const Class shgClass = {
    2638             :         "self-hosting-global", JSCLASS_GLOBAL_FLAGS,
    2639             :         &shgClassOps
    2640             :     };
    2641             : 
    2642           6 :     AutoCompartmentUnchecked ac(cx, compartment);
    2643           6 :     Rooted<GlobalObject*> shg(cx, GlobalObject::createInternal(cx, &shgClass));
    2644           3 :     if (!shg)
    2645           0 :         return nullptr;
    2646             : 
    2647           3 :     cx->runtime()->selfHostingGlobal_ = shg;
    2648           3 :     compartment->isSelfHosting = true;
    2649           3 :     compartment->setIsSystem(true);
    2650             : 
    2651           3 :     if (!GlobalObject::initSelfHostingBuiltins(cx, shg, intrinsic_functions))
    2652           0 :         return nullptr;
    2653             : 
    2654           3 :     JS_FireOnNewGlobalObject(cx, shg);
    2655             : 
    2656           3 :     return shg;
    2657             : }
    2658             : 
    2659             : static void
    2660           3 : MaybePrintAndClearPendingException(JSContext* cx, FILE* file)
    2661             : {
    2662           3 :     if (!cx->isExceptionPending())
    2663           6 :         return;
    2664             : 
    2665           0 :     AutoClearPendingException acpe(cx);
    2666             : 
    2667           0 :     RootedValue exn(cx);
    2668           0 :     if (!cx->getPendingException(&exn)) {
    2669           0 :         fprintf(file, "error getting pending exception\n");
    2670           0 :         return;
    2671             :     }
    2672           0 :     cx->clearPendingException();
    2673             : 
    2674           0 :     ErrorReport report(cx);
    2675           0 :     if (!report.init(cx, exn, js::ErrorReport::WithSideEffects)) {
    2676           0 :         fprintf(file, "out of memory initializing ErrorReport\n");
    2677           0 :         return;
    2678             :     }
    2679             : 
    2680           0 :     MOZ_ASSERT(!JSREPORT_IS_WARNING(report.report()->flags));
    2681           0 :     PrintError(cx, file, report.toStringResult(), report.report(), true);
    2682             : }
    2683             : 
    2684             : class MOZ_STACK_CLASS AutoSelfHostingErrorReporter
    2685             : {
    2686             :     JSContext* cx_;
    2687             :     JS::WarningReporter oldReporter_;
    2688             : 
    2689             :   public:
    2690           3 :     explicit AutoSelfHostingErrorReporter(JSContext* cx)
    2691           3 :       : cx_(cx)
    2692             :     {
    2693           3 :         oldReporter_ = JS::SetWarningReporter(cx_, selfHosting_WarningReporter);
    2694           3 :     }
    2695           6 :     ~AutoSelfHostingErrorReporter() {
    2696           3 :         JS::SetWarningReporter(cx_, oldReporter_);
    2697             : 
    2698             :         // Exceptions in self-hosted code will usually be printed to stderr in
    2699             :         // ErrorToException, but not all exceptions are handled there. For
    2700             :         // instance, ReportOutOfMemory will throw the "out of memory" string
    2701             :         // without going through ErrorToException. We handle these other
    2702             :         // exceptions here.
    2703           3 :         MaybePrintAndClearPendingException(cx_, stderr);
    2704           3 :     }
    2705             : };
    2706             : 
    2707             : static bool
    2708           3 : VerifyGlobalNames(JSContext* cx, Handle<GlobalObject*> shg)
    2709             : {
    2710             : #ifdef DEBUG
    2711           6 :     RootedId id(cx);
    2712           3 :     bool nameMissing = false;
    2713             : 
    2714        2802 :     for (auto iter = cx->zone()->cellIter<JSScript>();
    2715        1401 :          !iter.done() && !nameMissing;
    2716        1398 :          iter.next())
    2717             :     {
    2718        1398 :         JSScript* script = iter;
    2719        1398 :         jsbytecode* end = script->codeEnd();
    2720             :         jsbytecode* nextpc;
    2721      127314 :         for (jsbytecode* pc = script->code(); pc < end; pc = nextpc) {
    2722      125916 :             JSOp op = JSOp(*pc);
    2723      125916 :             nextpc = pc + GetBytecodeLength(pc);
    2724             : 
    2725      125916 :             if (op == JSOP_GETINTRINSIC) {
    2726        9273 :                 PropertyName* name = script->getName(pc);
    2727        9273 :                 id = NameToId(name);
    2728             : 
    2729        9273 :                 if (!shg->lookupPure(id)) {
    2730             :                     // cellIter disallows GCs, but error reporting wants to
    2731             :                     // have them, so we need to move it out of the loop.
    2732           0 :                     nameMissing = true;
    2733           0 :                     break;
    2734             :                 }
    2735             :             }
    2736             :         }
    2737             :     }
    2738             : 
    2739           3 :     if (nameMissing) {
    2740           0 :         RootedValue value(cx, IdToValue(id));
    2741           0 :         return ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_NO_SUCH_SELF_HOSTED_PROP,
    2742           0 :                                      JSDVG_IGNORE_STACK, value, nullptr, nullptr, nullptr);
    2743             :     }
    2744             : #endif // DEBUG
    2745             : 
    2746           3 :     return true;
    2747             : }
    2748             : 
    2749             : bool
    2750           4 : JSRuntime::initSelfHosting(JSContext* cx)
    2751             : {
    2752           4 :     MOZ_ASSERT(!selfHostingGlobal_);
    2753             : 
    2754           4 :     if (cx->runtime()->parentRuntime) {
    2755           1 :         selfHostingGlobal_ = cx->runtime()->parentRuntime->selfHostingGlobal_;
    2756           1 :         return true;
    2757             :     }
    2758             : 
    2759             :     /*
    2760             :      * Self hosted state can be accessed from threads for other runtimes
    2761             :      * parented to this one, so cannot include state in the nursery.
    2762             :      */
    2763           6 :     JS::AutoDisableGenerationalGC disable(cx);
    2764             : 
    2765           6 :     Rooted<GlobalObject*> shg(cx, JSRuntime::createSelfHostingGlobal(cx));
    2766           3 :     if (!shg)
    2767           0 :         return false;
    2768             : 
    2769           6 :     JSAutoCompartment ac(cx, shg);
    2770             : 
    2771             :     /*
    2772             :      * Set a temporary error reporter printing to stderr because it is too
    2773             :      * early in the startup process for any other reporter to be registered
    2774             :      * and we don't want errors in self-hosted code to be silently swallowed.
    2775             :      *
    2776             :      * This class also overrides the warning reporter to print warnings to
    2777             :      * stderr. See selfHosting_WarningReporter.
    2778             :      */
    2779           6 :     AutoSelfHostingErrorReporter errorReporter(cx);
    2780             : 
    2781           6 :     CompileOptions options(cx);
    2782           3 :     FillSelfHostingCompileOptions(options);
    2783             : 
    2784           6 :     RootedValue rv(cx);
    2785             : 
    2786           3 :     uint32_t srcLen = GetRawScriptsSize();
    2787             : 
    2788           3 :     const unsigned char* compressed = compressedSources;
    2789           3 :     uint32_t compressedLen = GetCompressedSize();
    2790           6 :     ScopedJSFreePtr<char> src(selfHostingGlobal_->zone()->pod_malloc<char>(srcLen));
    2791           6 :     if (!src || !DecompressString(compressed, compressedLen,
    2792           3 :                                   reinterpret_cast<unsigned char*>(src.get()), srcLen))
    2793             :     {
    2794           0 :         return false;
    2795             :     }
    2796             : 
    2797           3 :     if (!Evaluate(cx, options, src, srcLen, &rv))
    2798           0 :         return false;
    2799             : 
    2800           3 :     if (!VerifyGlobalNames(cx, shg))
    2801           0 :         return false;
    2802             : 
    2803           3 :     return true;
    2804             : }
    2805             : 
    2806             : void
    2807           0 : JSRuntime::finishSelfHosting()
    2808             : {
    2809           0 :     selfHostingGlobal_ = nullptr;
    2810           0 : }
    2811             : 
    2812             : void
    2813          22 : JSRuntime::traceSelfHostingGlobal(JSTracer* trc)
    2814             : {
    2815          22 :     if (selfHostingGlobal_ && !parentRuntime)
    2816          22 :         TraceRoot(trc, const_cast<NativeObject**>(&selfHostingGlobal_.ref()), "self-hosting global");
    2817          22 : }
    2818             : 
    2819             : bool
    2820        9634 : JSRuntime::isSelfHostingCompartment(JSCompartment* comp) const
    2821             : {
    2822        9634 :     return selfHostingGlobal_->compartment() == comp;
    2823             : }
    2824             : 
    2825             : bool
    2826           0 : JSRuntime::isSelfHostingZone(const JS::Zone* zone) const
    2827             : {
    2828           0 :     return selfHostingGlobal_ && selfHostingGlobal_->zoneFromAnyThread() == zone;
    2829             : }
    2830             : 
    2831             : static bool
    2832             : CloneValue(JSContext* cx, HandleValue selfHostedValue, MutableHandleValue vp);
    2833             : 
    2834             : static bool
    2835       22898 : GetUnclonedValue(JSContext* cx, HandleNativeObject selfHostedObject,
    2836             :                  HandleId id, MutableHandleValue vp)
    2837             : {
    2838       22898 :     vp.setUndefined();
    2839             : 
    2840       22898 :     if (JSID_IS_INT(id)) {
    2841           0 :         size_t index = JSID_TO_INT(id);
    2842           0 :         if (index < selfHostedObject->getDenseInitializedLength() &&
    2843           0 :             !selfHostedObject->getDenseElement(index).isMagic(JS_ELEMENTS_HOLE))
    2844             :         {
    2845           0 :             vp.set(selfHostedObject->getDenseElement(JSID_TO_INT(id)));
    2846           0 :             return true;
    2847             :         }
    2848             :     }
    2849             : 
    2850             :     // Since all atoms used by self-hosting are marked as permanent, the only
    2851             :     // reason we'd see a non-permanent atom here is code looking for
    2852             :     // properties on the self hosted global which aren't present.
    2853             :     // Since we ensure that that can't happen during startup, encountering
    2854             :     // non-permanent atoms here should be impossible.
    2855       22898 :     MOZ_ASSERT_IF(JSID_IS_STRING(id), JSID_TO_STRING(id)->isPermanentAtom());
    2856             : 
    2857       45796 :     RootedShape shape(cx, selfHostedObject->lookupPure(id));
    2858       22898 :     MOZ_ASSERT(shape);
    2859       22898 :     MOZ_ASSERT(shape->hasSlot() && shape->hasDefaultGetter());
    2860       22898 :     vp.set(selfHostedObject->getSlot(shape->slot()));
    2861       22898 :     return true;
    2862             : }
    2863             : 
    2864             : static bool
    2865        2092 : CloneProperties(JSContext* cx, HandleNativeObject selfHostedObject, HandleObject clone)
    2866             : {
    2867        4184 :     AutoIdVector ids(cx);
    2868        4184 :     Vector<uint8_t, 16> attrs(cx);
    2869             : 
    2870        2092 :     for (size_t i = 0; i < selfHostedObject->getDenseInitializedLength(); i++) {
    2871           0 :         if (!selfHostedObject->getDenseElement(i).isMagic(JS_ELEMENTS_HOLE)) {
    2872           0 :             if (!ids.append(INT_TO_JSID(i)))
    2873           0 :                 return false;
    2874           0 :             if (!attrs.append(JSPROP_ENUMERATE))
    2875           0 :                 return false;
    2876             :         }
    2877             :     }
    2878             : 
    2879        4184 :     Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
    2880        2118 :     for (Shape::Range<NoGC> range(selfHostedObject->lastProperty()); !range.empty(); range.popFront()) {
    2881          26 :         Shape& shape = range.front();
    2882          26 :         if (shape.enumerable() && !shapes.append(&shape))
    2883           0 :             return false;
    2884             :     }
    2885             : 
    2886             :     // Now our shapes are in last-to-first order, so....
    2887        2092 :     Reverse(shapes.begin(), shapes.end());
    2888        2118 :     for (size_t i = 0; i < shapes.length(); ++i) {
    2889          26 :         MOZ_ASSERT(!shapes[i]->isAccessorShape(),
    2890             :                    "Can't handle cloning accessors here yet.");
    2891          26 :         if (!ids.append(shapes[i]->propid()))
    2892           0 :             return false;
    2893             :         uint8_t shapeAttrs =
    2894          26 :             shapes[i]->attributes() & (JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
    2895          26 :         if (!attrs.append(shapeAttrs))
    2896           0 :             return false;
    2897             :     }
    2898             : 
    2899        4184 :     RootedId id(cx);
    2900        4184 :     RootedValue val(cx);
    2901        4184 :     RootedValue selfHostedValue(cx);
    2902        2118 :     for (uint32_t i = 0; i < ids.length(); i++) {
    2903          26 :         id = ids[i];
    2904          26 :         if (!GetUnclonedValue(cx, selfHostedObject, id, &selfHostedValue))
    2905           0 :             return false;
    2906         130 :         if (!CloneValue(cx, selfHostedValue, &val) ||
    2907         104 :             !JS_DefinePropertyById(cx, clone, id, val, attrs[i]))
    2908             :         {
    2909           0 :             return false;
    2910             :         }
    2911             :     }
    2912             : 
    2913        2092 :     return true;
    2914             : }
    2915             : 
    2916             : static JSString*
    2917           0 : CloneString(JSContext* cx, JSFlatString* selfHostedString)
    2918             : {
    2919           0 :     size_t len = selfHostedString->length();
    2920             :     {
    2921           0 :         JS::AutoCheckCannotGC nogc;
    2922             :         JSString* clone;
    2923           0 :         if (selfHostedString->hasLatin1Chars())
    2924           0 :             clone = NewStringCopyN<NoGC>(cx, selfHostedString->latin1Chars(nogc), len);
    2925             :         else
    2926           0 :             clone = NewStringCopyNDontDeflate<NoGC>(cx, selfHostedString->twoByteChars(nogc), len);
    2927           0 :         if (clone)
    2928           0 :             return clone;
    2929             :     }
    2930             : 
    2931           0 :     AutoStableStringChars chars(cx);
    2932           0 :     if (!chars.init(cx, selfHostedString))
    2933           0 :         return nullptr;
    2934             : 
    2935           0 :     return chars.isLatin1()
    2936           0 :            ? NewStringCopyN<CanGC>(cx, chars.latin1Range().begin().get(), len)
    2937           0 :            : NewStringCopyNDontDeflate<CanGC>(cx, chars.twoByteRange().begin().get(), len);
    2938             : }
    2939             : 
    2940             : static JSObject*
    2941        2092 : CloneObject(JSContext* cx, HandleNativeObject selfHostedObject)
    2942             : {
    2943             : #ifdef DEBUG
    2944             :     // Object hash identities are owned by the hashed object, which may be on a
    2945             :     // different thread than the clone target. In theory, these objects are all
    2946             :     // tenured and will not be compacted; however, we simply avoid the issue
    2947             :     // altogether by skipping the cycle-detection when off thread.
    2948        4184 :     mozilla::Maybe<AutoCycleDetector> detect;
    2949        2092 :     if (js::CurrentThreadCanAccessZone(selfHostedObject->zoneFromAnyThread())) {
    2950        2086 :         detect.emplace(cx, selfHostedObject);
    2951        2086 :         if (!detect->init())
    2952           0 :             return nullptr;
    2953        2086 :         if (detect->foundCycle())
    2954           0 :             MOZ_CRASH("SelfHosted cloning cannot handle cyclic object graphs.");
    2955             :     }
    2956             : #endif
    2957             : 
    2958        4184 :     RootedObject clone(cx);
    2959        2092 :     if (selfHostedObject->is<JSFunction>()) {
    2960        4060 :         RootedFunction selfHostedFunction(cx, &selfHostedObject->as<JSFunction>());
    2961        2030 :         bool hasName = selfHostedFunction->explicitName() != nullptr;
    2962             : 
    2963             :         // Arrow functions use the first extended slot for their lexical |this| value.
    2964        2030 :         MOZ_ASSERT(!selfHostedFunction->isArrow());
    2965             :         js::gc::AllocKind kind = hasName
    2966        2030 :                                  ? gc::AllocKind::FUNCTION_EXTENDED
    2967        2030 :                                  : selfHostedFunction->getAllocKind();
    2968        2030 :         MOZ_ASSERT(!CanReuseScriptForClone(cx->compartment(), selfHostedFunction, cx->global()));
    2969        4060 :         Rooted<LexicalEnvironmentObject*> globalLexical(cx, &cx->global()->lexicalEnvironment());
    2970        4060 :         RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
    2971        4060 :         clone = CloneFunctionAndScript(cx, selfHostedFunction, globalLexical, emptyGlobalScope,
    2972        2030 :                                        kind);
    2973             :         // To be able to re-lazify the cloned function, its name in the
    2974             :         // self-hosting compartment has to be stored on the clone.
    2975        2030 :         if (clone && hasName) {
    2976        2030 :             clone->as<JSFunction>().setExtendedSlot(LAZY_FUNCTION_NAME_SLOT,
    2977        4060 :                                                     StringValue(selfHostedFunction->explicitName()));
    2978             :         }
    2979          62 :     } else if (selfHostedObject->is<RegExpObject>()) {
    2980           0 :         RegExpObject& reobj = selfHostedObject->as<RegExpObject>();
    2981           0 :         RootedAtom source(cx, reobj.getSource());
    2982           0 :         MOZ_ASSERT(source->isPermanentAtom());
    2983           0 :         clone = RegExpObject::create(cx, source, reobj.getFlags(),
    2984             :                                      nullptr, nullptr, cx->tempLifoAlloc(),
    2985           0 :                                      TenuredObject);
    2986          62 :     } else if (selfHostedObject->is<DateObject>()) {
    2987           0 :         clone = JS::NewDateObject(cx, selfHostedObject->as<DateObject>().clippedTime());
    2988          62 :     } else if (selfHostedObject->is<BooleanObject>()) {
    2989           0 :         clone = BooleanObject::create(cx, selfHostedObject->as<BooleanObject>().unbox());
    2990          62 :     } else if (selfHostedObject->is<NumberObject>()) {
    2991           0 :         clone = NumberObject::create(cx, selfHostedObject->as<NumberObject>().unbox());
    2992          62 :     } else if (selfHostedObject->is<StringObject>()) {
    2993           0 :         JSString* selfHostedString = selfHostedObject->as<StringObject>().unbox();
    2994           0 :         if (!selfHostedString->isFlat())
    2995           0 :             MOZ_CRASH();
    2996           0 :         RootedString str(cx, CloneString(cx, &selfHostedString->asFlat()));
    2997           0 :         if (!str)
    2998           0 :             return nullptr;
    2999           0 :         clone = StringObject::create(cx, str);
    3000          62 :     } else if (selfHostedObject->is<ArrayObject>()) {
    3001           0 :         clone = NewDenseEmptyArray(cx, nullptr, TenuredObject);
    3002             :     } else {
    3003          62 :         MOZ_ASSERT(selfHostedObject->isNative());
    3004         124 :         clone = NewObjectWithGivenProto(cx, selfHostedObject->getClass(), nullptr,
    3005          62 :                                         selfHostedObject->asTenured().getAllocKind(),
    3006          62 :                                         SingletonObject);
    3007             :     }
    3008        2092 :     if (!clone)
    3009           0 :         return nullptr;
    3010             : 
    3011        2092 :     if (!CloneProperties(cx, selfHostedObject, clone))
    3012           0 :         return nullptr;
    3013        2092 :     return clone;
    3014             : }
    3015             : 
    3016             : static bool
    3017        2307 : CloneValue(JSContext* cx, HandleValue selfHostedValue, MutableHandleValue vp)
    3018             : {
    3019        2307 :     if (selfHostedValue.isObject()) {
    3020        4184 :         RootedNativeObject selfHostedObject(cx, &selfHostedValue.toObject().as<NativeObject>());
    3021        2092 :         JSObject* clone = CloneObject(cx, selfHostedObject);
    3022        2092 :         if (!clone)
    3023           0 :             return false;
    3024        2092 :         vp.setObject(*clone);
    3025         215 :     } else if (selfHostedValue.isBoolean() || selfHostedValue.isNumber() || selfHostedValue.isNullOrUndefined()) {
    3026             :         // Nothing to do here: these are represented inline in the value.
    3027         129 :         vp.set(selfHostedValue);
    3028          86 :     } else if (selfHostedValue.isString()) {
    3029           0 :         if (!selfHostedValue.toString()->isFlat())
    3030           0 :             MOZ_CRASH();
    3031           0 :         JSFlatString* selfHostedString = &selfHostedValue.toString()->asFlat();
    3032           0 :         JSString* clone = CloneString(cx, selfHostedString);
    3033           0 :         if (!clone)
    3034           0 :             return false;
    3035           0 :         vp.setString(clone);
    3036          86 :     } else if (selfHostedValue.isSymbol()) {
    3037             :         // Well-known symbols are shared.
    3038         172 :         mozilla::DebugOnly<JS::Symbol*> sym = selfHostedValue.toSymbol();
    3039          86 :         MOZ_ASSERT(sym->isWellKnownSymbol());
    3040          86 :         MOZ_ASSERT(cx->wellKnownSymbols().get(size_t(sym->code())) == sym);
    3041          86 :         vp.set(selfHostedValue);
    3042             :     } else {
    3043           0 :         MOZ_CRASH("Self-hosting CloneValue can't clone given value.");
    3044             :     }
    3045        2307 :     return true;
    3046             : }
    3047             : 
    3048             : bool
    3049       19856 : JSRuntime::createLazySelfHostedFunctionClone(JSContext* cx, HandlePropertyName selfHostedName,
    3050             :                                              HandleAtom name, unsigned nargs,
    3051             :                                              HandleObject proto, NewObjectKind newKind,
    3052             :                                              MutableHandleFunction fun)
    3053             : {
    3054       19856 :     MOZ_ASSERT(newKind != GenericObject);
    3055             : 
    3056       39712 :     RootedAtom funName(cx, name);
    3057       19856 :     JSFunction* selfHostedFun = getUnclonedSelfHostedFunction(cx, selfHostedName);
    3058       19856 :     if (!selfHostedFun)
    3059           0 :         return false;
    3060             : 
    3061       39709 :     if (!selfHostedFun->isClassConstructor() && !selfHostedFun->hasGuessedAtom() &&
    3062       19853 :         selfHostedFun->explicitName() != selfHostedName)
    3063             :     {
    3064        1151 :         MOZ_ASSERT(selfHostedFun->getExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT).toBoolean());
    3065        1151 :         funName = selfHostedFun->explicitName();
    3066             :     }
    3067             : 
    3068       39712 :     fun.set(NewScriptedFunction(cx, nargs, JSFunction::INTERPRETED_LAZY,
    3069       19856 :                                 funName, proto, gc::AllocKind::FUNCTION_EXTENDED, newKind));
    3070       19856 :     if (!fun)
    3071           0 :         return false;
    3072       19856 :     fun->setIsSelfHostedBuiltin();
    3073       19856 :     fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(selfHostedName));
    3074       19856 :     return true;
    3075             : }
    3076             : 
    3077             : bool
    3078         556 : JSRuntime::cloneSelfHostedFunctionScript(JSContext* cx, HandlePropertyName name,
    3079             :                                          HandleFunction targetFun)
    3080             : {
    3081        1112 :     RootedFunction sourceFun(cx, getUnclonedSelfHostedFunction(cx, name));
    3082         556 :     if (!sourceFun)
    3083           0 :         return false;
    3084             :     // JSFunction::generatorKind can't handle lazy self-hosted functions, so we make sure there
    3085             :     // aren't any.
    3086         556 :     MOZ_ASSERT(!sourceFun->isStarGenerator() && !sourceFun->isLegacyGenerator() &&
    3087             :                !sourceFun->isAsync());
    3088         556 :     MOZ_ASSERT(targetFun->isExtended());
    3089         556 :     MOZ_ASSERT(targetFun->isInterpretedLazy());
    3090         556 :     MOZ_ASSERT(targetFun->isSelfHostedBuiltin());
    3091             : 
    3092        1112 :     RootedScript sourceScript(cx, JSFunction::getOrCreateScript(cx, sourceFun));
    3093         556 :     if (!sourceScript)
    3094           0 :         return false;
    3095             : 
    3096             :     // Assert that there are no intervening scopes between the global scope
    3097             :     // and the self-hosted script. Toplevel lexicals are explicitly forbidden
    3098             :     // by the parser when parsing self-hosted code. The fact they have the
    3099             :     // global lexical scope on the scope chain is for uniformity and engine
    3100             :     // invariants.
    3101         556 :     MOZ_ASSERT(sourceScript->outermostScope()->enclosing()->kind() == ScopeKind::Global);
    3102        1112 :     RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope());
    3103         556 :     if (!CloneScriptIntoFunction(cx, emptyGlobalScope, targetFun, sourceScript))
    3104           0 :         return false;
    3105         556 :     MOZ_ASSERT(!targetFun->isInterpretedLazy());
    3106             : 
    3107         556 :     MOZ_ASSERT(sourceFun->nargs() == targetFun->nargs());
    3108         556 :     MOZ_ASSERT(sourceScript->hasRest() == targetFun->nonLazyScript()->hasRest());
    3109             : 
    3110             :     // The target function might have been relazified after its flags changed.
    3111         556 :     targetFun->setFlags(targetFun->flags() | sourceFun->flags());
    3112         556 :     return true;
    3113             : }
    3114             : 
    3115             : bool
    3116       22872 : JSRuntime::getUnclonedSelfHostedValue(JSContext* cx, HandlePropertyName name,
    3117             :                                       MutableHandleValue vp)
    3118             : {
    3119       45744 :     RootedId id(cx, NameToId(name));
    3120       45744 :     return GetUnclonedValue(cx, HandleNativeObject::fromMarkedLocation(&selfHostingGlobal_.ref()), id, vp);
    3121             : }
    3122             : 
    3123             : JSFunction*
    3124       20591 : JSRuntime::getUnclonedSelfHostedFunction(JSContext* cx, HandlePropertyName name)
    3125             : {
    3126       41182 :     RootedValue selfHostedValue(cx);
    3127       20591 :     if (!getUnclonedSelfHostedValue(cx, name, &selfHostedValue))
    3128           0 :         return nullptr;
    3129             : 
    3130       20591 :     return &selfHostedValue.toObject().as<JSFunction>();
    3131             : }
    3132             : 
    3133             : bool
    3134        2281 : JSRuntime::cloneSelfHostedValue(JSContext* cx, HandlePropertyName name, MutableHandleValue vp)
    3135             : {
    3136        4562 :     RootedValue selfHostedValue(cx);
    3137        2281 :     if (!getUnclonedSelfHostedValue(cx, name, &selfHostedValue))
    3138           0 :         return false;
    3139             : 
    3140             :     /*
    3141             :      * We don't clone if we're operating in the self-hosting global, as that
    3142             :      * means we're currently executing the self-hosting script while
    3143             :      * initializing the runtime (see JSRuntime::initSelfHosting).
    3144             :      */
    3145        2281 :     if (cx->global() == selfHostingGlobal_) {
    3146           0 :         vp.set(selfHostedValue);
    3147           0 :         return true;
    3148             :     }
    3149             : 
    3150        2281 :     return CloneValue(cx, selfHostedValue, vp);
    3151             : }
    3152             : 
    3153             : void
    3154         179 : JSRuntime::assertSelfHostedFunctionHasCanonicalName(JSContext* cx, HandlePropertyName name)
    3155             : {
    3156             : #ifdef DEBUG
    3157         179 :     JSFunction* selfHostedFun = getUnclonedSelfHostedFunction(cx, name);
    3158         179 :     MOZ_ASSERT(selfHostedFun);
    3159         179 :     MOZ_ASSERT(selfHostedFun->getExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT).toBoolean());
    3160             : #endif
    3161         179 : }
    3162             : 
    3163             : JSFunction*
    3164           0 : js::SelfHostedFunction(JSContext* cx, HandlePropertyName propName)
    3165             : {
    3166           0 :     RootedValue func(cx);
    3167           0 :     if (!GlobalObject::getIntrinsicValue(cx, cx->global(), propName, &func))
    3168           0 :         return nullptr;
    3169             : 
    3170           0 :     MOZ_ASSERT(func.isObject());
    3171           0 :     MOZ_ASSERT(func.toObject().is<JSFunction>());
    3172           0 :     return &func.toObject().as<JSFunction>();
    3173             : }
    3174             : 
    3175             : bool
    3176          67 : js::IsSelfHostedFunctionWithName(JSFunction* fun, JSAtom* name)
    3177             : {
    3178          67 :     return fun->isSelfHostedBuiltin() && GetSelfHostedFunctionName(fun) == name;
    3179             : }
    3180             : 
    3181             : JSAtom*
    3182          67 : js::GetSelfHostedFunctionName(JSFunction* fun)
    3183             : {
    3184          67 :     Value name = fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT);
    3185          67 :     if (!name.isString())
    3186           0 :         return nullptr;
    3187          67 :     return &name.toString()->asAtom();
    3188             : }
    3189             : 
    3190             : static_assert(JSString::MAX_LENGTH <= INT32_MAX,
    3191             :               "StringIteratorNext in builtin/String.js assumes the stored index "
    3192             :               "into the string is an Int32Value");

Generated by: LCOV version 1.13