tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SelfHosting.cpp (94178B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "vm/SelfHosting.h"
      8 
      9 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
     10 #  include "builtin/AsyncDisposableStackObject.h"
     11 #  include "builtin/DisposableStackObject.h"
     12 #endif
     13 #include "mozilla/BinarySearch.h"
     14 #include "mozilla/Maybe.h"
     15 #include "mozilla/ScopeExit.h"  // mozilla::MakeScopeExit
     16 #include "mozilla/Utf8.h"       // mozilla::Utf8Unit
     17 
     18 #include <algorithm>
     19 #include <iterator>
     20 
     21 #include "jsfriendapi.h"
     22 #include "jsmath.h"
     23 #include "jsnum.h"
     24 #include "selfhosted.out.h"
     25 
     26 #include "builtin/Array.h"
     27 #include "builtin/BigInt.h"
     28 #ifdef JS_HAS_INTL_API
     29 #  include "builtin/intl/Collator.h"
     30 #  include "builtin/intl/DateTimeFormat.h"
     31 #  include "builtin/intl/DisplayNames.h"
     32 #  include "builtin/intl/DurationFormat.h"
     33 #  include "builtin/intl/IntlObject.h"
     34 #  include "builtin/intl/ListFormat.h"
     35 #  include "builtin/intl/Locale.h"
     36 #  include "builtin/intl/NumberFormat.h"
     37 #  include "builtin/intl/PluralRules.h"
     38 #  include "builtin/intl/RelativeTimeFormat.h"
     39 #  include "builtin/intl/Segmenter.h"
     40 #endif
     41 #include "builtin/MapObject.h"
     42 #include "builtin/Object.h"
     43 #include "builtin/Promise.h"
     44 #include "builtin/Reflect.h"
     45 #include "builtin/RegExp.h"
     46 #include "builtin/SelfHostingDefines.h"
     47 #include "builtin/String.h"
     48 #ifdef JS_HAS_INTL_API
     49 #  include "builtin/temporal/Duration.h"
     50 #  include "builtin/temporal/TimeZone.h"
     51 #endif
     52 #include "builtin/WeakMapObject.h"
     53 #include "frontend/BytecodeCompiler.h"    // CompileGlobalScriptToStencil
     54 #include "frontend/CompilationStencil.h"  // js::frontend::CompilationStencil
     55 #include "frontend/FrontendContext.h"     // AutoReportFrontendContext
     56 #include "frontend/StencilXdr.h"  // js::EncodeStencil, js::DecodeStencil
     57 #include "jit/AtomicOperations.h"
     58 #include "jit/BaselineJIT.h"
     59 #include "jit/InlinableNatives.h"
     60 #include "jit/TrampolineNatives.h"
     61 #include "js/CompilationAndEvaluation.h"
     62 #include "js/Conversions.h"
     63 #include "js/ErrorReport.h"  // JS::PrintError
     64 #include "js/experimental/JSStencil.h"
     65 #include "js/experimental/TypedData.h"  // JS_GetArrayBufferViewType
     66 #include "js/friend/ErrorMessages.h"    // js::GetErrorMessage, JSMSG_*
     67 #include "js/HashTable.h"
     68 #include "js/Printer.h"
     69 #include "js/PropertySpec.h"
     70 #include "js/ScalarType.h"  // js::Scalar::Type
     71 #include "js/SourceText.h"  // JS::SourceText
     72 #include "js/TracingAPI.h"
     73 #include "js/Transcoding.h"
     74 #include "js/Warnings.h"  // JS::{,Set}WarningReporter
     75 #include "js/Wrapper.h"
     76 #include "vm/ArgumentsObject.h"
     77 #include "vm/AsyncFunction.h"
     78 #include "vm/AsyncIteration.h"
     79 #include "vm/BigIntType.h"
     80 #include "vm/Compression.h"
     81 #include "vm/DateObject.h"
     82 #include "vm/ErrorReporting.h"  // js::MaybePrintAndClearPendingException
     83 #include "vm/Float16.h"
     84 #include "vm/FrameIter.h"  // js::ScriptFrameIter
     85 #include "vm/GeneratorObject.h"
     86 #include "vm/Interpreter.h"
     87 #include "vm/Iteration.h"
     88 #include "vm/JSAtomUtils.h"  // Atomize
     89 #include "vm/JSContext.h"
     90 #include "vm/JSFunction.h"
     91 #include "vm/JSObject.h"
     92 #include "vm/Logging.h"
     93 #include "vm/PlainObject.h"  // js::PlainObject
     94 #include "vm/Realm.h"
     95 #include "vm/RegExpObject.h"
     96 #include "vm/StringType.h"
     97 #include "vm/ToSource.h"  // js::ValueToSource
     98 #include "vm/TypedArrayObject.h"
     99 #include "vm/Uint8Clamped.h"
    100 #include "vm/Warnings.h"
    101 #include "vm/WrapperObject.h"
    102 
    103 #include "gc/WeakMap-inl.h"
    104 #include "vm/Compartment-inl.h"
    105 #include "vm/JSAtomUtils-inl.h"  // PrimitiveValueToId
    106 #include "vm/JSFunction-inl.h"
    107 #include "vm/JSObject-inl.h"
    108 #include "vm/NativeObject-inl.h"
    109 #include "vm/TypedArrayObject-inl.h"
    110 
    111 using namespace js;
    112 using namespace js::selfhosted;
    113 
    114 using JS::CompileOptions;
    115 
    116 static bool intrinsic_ToObject(JSContext* cx, unsigned argc, Value* vp) {
    117  CallArgs args = CallArgsFromVp(argc, vp);
    118  JSObject* obj = ToObject(cx, args[0]);
    119  if (!obj) {
    120    return false;
    121  }
    122  args.rval().setObject(*obj);
    123  return true;
    124 }
    125 
    126 static bool intrinsic_IsObject(JSContext* cx, unsigned argc, Value* vp) {
    127  CallArgs args = CallArgsFromVp(argc, vp);
    128  Value val = args[0];
    129  bool isObject = val.isObject();
    130  args.rval().setBoolean(isObject);
    131  return true;
    132 }
    133 
    134 static bool intrinsic_IsArray(JSContext* cx, unsigned argc, Value* vp) {
    135  CallArgs args = CallArgsFromVp(argc, vp);
    136  MOZ_ASSERT(args.length() == 1);
    137  RootedValue val(cx, args[0]);
    138  if (val.isObject()) {
    139    RootedObject obj(cx, &val.toObject());
    140    bool isArray = false;
    141    if (!IsArray(cx, obj, &isArray)) {
    142      return false;
    143    }
    144    args.rval().setBoolean(isArray);
    145  } else {
    146    args.rval().setBoolean(false);
    147  }
    148  return true;
    149 }
    150 
    151 static bool intrinsic_IsCrossRealmArrayConstructor(JSContext* cx, unsigned argc,
    152                                                   Value* vp) {
    153  CallArgs args = CallArgsFromVp(argc, vp);
    154  MOZ_ASSERT(args.length() == 1);
    155  MOZ_ASSERT(args[0].isObject());
    156 
    157  bool result = false;
    158  if (!IsCrossRealmArrayConstructor(cx, &args[0].toObject(), &result)) {
    159    return false;
    160  }
    161  args.rval().setBoolean(result);
    162  return true;
    163 }
    164 
    165 static bool intrinsic_ToLength(JSContext* cx, unsigned argc, Value* vp) {
    166  CallArgs args = CallArgsFromVp(argc, vp);
    167  MOZ_ASSERT(args.length() == 1);
    168 
    169  // Inline fast path for the common case.
    170  if (args[0].isInt32()) {
    171    int32_t i = args[0].toInt32();
    172    args.rval().setInt32(i < 0 ? 0 : i);
    173    return true;
    174  }
    175 
    176  uint64_t length = 0;
    177  if (!ToLength(cx, args[0], &length)) {
    178    return false;
    179  }
    180 
    181  args.rval().setNumber(double(length));
    182  return true;
    183 }
    184 
    185 static bool intrinsic_ToInteger(JSContext* cx, unsigned argc, Value* vp) {
    186  CallArgs args = CallArgsFromVp(argc, vp);
    187  double result;
    188  if (!ToInteger(cx, args[0], &result)) {
    189    return false;
    190  }
    191  args.rval().setNumber(result);
    192  return true;
    193 }
    194 
    195 static bool intrinsic_ToSource(JSContext* cx, unsigned argc, Value* vp) {
    196  CallArgs args = CallArgsFromVp(argc, vp);
    197  JSString* str = ValueToSource(cx, args[0]);
    198  if (!str) {
    199    return false;
    200  }
    201  args.rval().setString(str);
    202  return true;
    203 }
    204 
    205 static bool intrinsic_ToPropertyKey(JSContext* cx, unsigned argc, Value* vp) {
    206  CallArgs args = CallArgsFromVp(argc, vp);
    207  RootedId id(cx);
    208  if (!ToPropertyKey(cx, args[0], &id)) {
    209    return false;
    210  }
    211 
    212  args.rval().set(IdToValue(id));
    213  return true;
    214 }
    215 
    216 static bool intrinsic_IsCallable(JSContext* cx, unsigned argc, Value* vp) {
    217  CallArgs args = CallArgsFromVp(argc, vp);
    218  args.rval().setBoolean(IsCallable(args[0]));
    219  return true;
    220 }
    221 
    222 static bool intrinsic_IsConstructor(JSContext* cx, unsigned argc, Value* vp) {
    223  CallArgs args = CallArgsFromVp(argc, vp);
    224  MOZ_ASSERT(args.length() == 1);
    225  args.rval().setBoolean(IsConstructor(args[0]));
    226  return true;
    227 }
    228 
    229 template <typename T>
    230 static bool intrinsic_IsInstanceOfBuiltin(JSContext* cx, unsigned argc,
    231                                          Value* vp) {
    232  CallArgs args = CallArgsFromVp(argc, vp);
    233  MOZ_ASSERT(args.length() == 1);
    234  MOZ_ASSERT(args[0].isObject());
    235 
    236  args.rval().setBoolean(args[0].toObject().is<T>());
    237  return true;
    238 }
    239 
    240 template <typename T>
    241 static bool intrinsic_GuardToBuiltin(JSContext* cx, unsigned argc, Value* vp) {
    242  CallArgs args = CallArgsFromVp(argc, vp);
    243  MOZ_ASSERT(args.length() == 1);
    244  MOZ_ASSERT(args[0].isObject());
    245 
    246  if (args[0].toObject().is<T>()) {
    247    args.rval().setObject(args[0].toObject());
    248    return true;
    249  }
    250  args.rval().setNull();
    251  return true;
    252 }
    253 
    254 template <typename T>
    255 static bool intrinsic_IsWrappedInstanceOfBuiltin(JSContext* cx, unsigned argc,
    256                                                 Value* vp) {
    257  CallArgs args = CallArgsFromVp(argc, vp);
    258  MOZ_ASSERT(args.length() == 1);
    259  MOZ_ASSERT(args[0].isObject());
    260 
    261  JSObject* obj = &args[0].toObject();
    262  if (!obj->is<WrapperObject>()) {
    263    args.rval().setBoolean(false);
    264    return true;
    265  }
    266 
    267  JSObject* unwrapped = CheckedUnwrapDynamic(obj, cx);
    268  if (!unwrapped) {
    269    ReportAccessDenied(cx);
    270    return false;
    271  }
    272 
    273  args.rval().setBoolean(unwrapped->is<T>());
    274  return true;
    275 }
    276 
    277 template <typename T>
    278 static bool intrinsic_IsPossiblyWrappedInstanceOfBuiltin(JSContext* cx,
    279                                                         unsigned argc,
    280                                                         Value* vp) {
    281  CallArgs args = CallArgsFromVp(argc, vp);
    282  MOZ_ASSERT(args.length() == 1);
    283  MOZ_ASSERT(args[0].isObject());
    284 
    285  JSObject* obj = CheckedUnwrapDynamic(&args[0].toObject(), cx);
    286  if (!obj) {
    287    ReportAccessDenied(cx);
    288    return false;
    289  }
    290 
    291  args.rval().setBoolean(obj->is<T>());
    292  return true;
    293 }
    294 
    295 static bool intrinsic_SubstringKernel(JSContext* cx, unsigned argc, Value* vp) {
    296  CallArgs args = CallArgsFromVp(argc, vp);
    297  MOZ_ASSERT(args[0].isString());
    298  MOZ_RELEASE_ASSERT(args[1].isInt32());
    299  MOZ_RELEASE_ASSERT(args[2].isInt32());
    300 
    301  RootedString str(cx, args[0].toString());
    302  int32_t begin = args[1].toInt32();
    303  int32_t length = args[2].toInt32();
    304 
    305  JSString* substr = SubstringKernel(cx, str, begin, length);
    306  if (!substr) {
    307    return false;
    308  }
    309 
    310  args.rval().setString(substr);
    311  return true;
    312 }
    313 
    314 static bool PrepareErrorArguments(JSContext* cx, JSExnType type,
    315                                  const CallArgs& args,
    316                                  UniqueChars (&errorArgs)[3]) {
    317 #ifdef DEBUG
    318  MOZ_ASSERT(args[0].isInt32());
    319  uint32_t errorNumber = args[0].toInt32();
    320 
    321  const JSErrorFormatString* efs = GetErrorMessage(nullptr, errorNumber);
    322  MOZ_ASSERT(efs->argCount == args.length() - 1);
    323  MOZ_ASSERT(efs->exnType == type,
    324             "error-throwing intrinsic and error number are inconsistent");
    325 #endif
    326 
    327  for (unsigned i = 1; i < 4 && i < args.length(); i++) {
    328    HandleValue val = args[i];
    329    if (val.isInt32() || val.isString()) {
    330      JSString* str = ToString<CanGC>(cx, val);
    331      if (!str) {
    332        return false;
    333      }
    334      errorArgs[i - 1] = QuoteString(cx, str);
    335    } else {
    336      errorArgs[i - 1] =
    337          DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, val, nullptr);
    338    }
    339    if (!errorArgs[i - 1]) {
    340      return false;
    341    }
    342  }
    343  return true;
    344 }
    345 
    346 static void ThrowErrorWithType(JSContext* cx, JSExnType type,
    347                               const CallArgs& args) {
    348  MOZ_RELEASE_ASSERT(args[0].isInt32());
    349  uint32_t errorNumber = args[0].toInt32();
    350 
    351  UniqueChars errorArgs[3];
    352  if (!PrepareErrorArguments(cx, type, args, errorArgs)) {
    353    return;
    354  }
    355 
    356  JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, errorNumber,
    357                           errorArgs[0].get(), errorArgs[1].get(),
    358                           errorArgs[2].get());
    359 }
    360 
    361 static bool intrinsic_ThrowRangeError(JSContext* cx, unsigned argc, Value* vp) {
    362  CallArgs args = CallArgsFromVp(argc, vp);
    363  MOZ_ASSERT(args.length() >= 1);
    364 
    365  ThrowErrorWithType(cx, JSEXN_RANGEERR, args);
    366  return false;
    367 }
    368 
    369 static bool intrinsic_ThrowTypeError(JSContext* cx, unsigned argc, Value* vp) {
    370  CallArgs args = CallArgsFromVp(argc, vp);
    371  MOZ_ASSERT(args.length() >= 1);
    372 
    373  ThrowErrorWithType(cx, JSEXN_TYPEERR, args);
    374  return false;
    375 }
    376 
    377 static bool intrinsic_ThrowAggregateError(JSContext* cx, unsigned argc,
    378                                          Value* vp) {
    379  CallArgs args = CallArgsFromVp(argc, vp);
    380  MOZ_ASSERT(args.length() >= 1);
    381 
    382  ThrowErrorWithType(cx, JSEXN_AGGREGATEERR, args);
    383  return false;
    384 }
    385 
    386 static bool intrinsic_ThrowInternalError(JSContext* cx, unsigned argc,
    387                                         Value* vp) {
    388  CallArgs args = CallArgsFromVp(argc, vp);
    389  MOZ_ASSERT(args.length() >= 1);
    390 
    391  ThrowErrorWithType(cx, JSEXN_INTERNALERR, args);
    392  return false;
    393 }
    394 
    395 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    396 static bool intrinsic_CreateSuppressedError(JSContext* cx, unsigned argc,
    397                                            Value* vp) {
    398  CallArgs args = CallArgsFromVp(argc, vp);
    399  MOZ_ASSERT(args.length() == 2);
    400 
    401  JS::Handle<JS::Value> error = args[0];
    402  JS::Handle<JS::Value> suppressed = args[1];
    403 
    404  ErrorObject* suppressedError = CreateSuppressedError(cx, error, suppressed);
    405  if (!suppressedError) {
    406    return false;
    407  }
    408  args.rval().setObject(*suppressedError);
    409  return true;
    410 }
    411 #endif
    412 
    413 static bool intrinsic_ReportWarning(JSContext* cx, unsigned argc, Value* vp) {
    414  CallArgs args = CallArgsFromVp(argc, vp);
    415  MOZ_ASSERT(args.length() >= 1);
    416 
    417  MOZ_RELEASE_ASSERT(args[0].isInt32());
    418  uint32_t errorNumber = args[0].toInt32();
    419 
    420  UniqueChars errorArgs[3];
    421  if (!PrepareErrorArguments(cx, JSEXN_WARN, args, errorArgs)) {
    422    return false;
    423  }
    424 
    425  if (!WarnNumberUTF8(cx, errorNumber, errorArgs[0].get(), errorArgs[1].get(),
    426                      errorArgs[2].get())) {
    427    return false;
    428  }
    429 
    430  args.rval().setUndefined();
    431  return true;
    432 }
    433 
    434 /**
    435 * Handles an assertion failure in self-hosted code just like an assertion
    436 * failure in C++ code. Information about the failure can be provided in
    437 * args[0].
    438 */
    439 static bool intrinsic_AssertionFailed(JSContext* cx, unsigned argc, Value* vp) {
    440 #ifdef DEBUG
    441  CallArgs args = CallArgsFromVp(argc, vp);
    442  if (args.length() > 0) {
    443    // try to dump the informative string
    444    JSString* str = ToString<CanGC>(cx, args[0]);
    445    if (str) {
    446      js::Fprinter out(stderr);
    447      out.put("Self-hosted JavaScript assertion info: ");
    448      str->dumpCharsNoQuote(out);
    449      out.putChar('\n');
    450    }
    451  }
    452 #endif
    453  MOZ_ASSERT(false);
    454  return false;
    455 }
    456 
    457 /**
    458 * Dumps a message to stderr, after stringifying it. Doesn't append a newline.
    459 */
    460 static bool intrinsic_DumpMessage(JSContext* cx, unsigned argc, Value* vp) {
    461  CallArgs args = CallArgsFromVp(argc, vp);
    462 #ifdef DEBUG
    463  if (args.length() > 0) {
    464    // try to dump the informative string
    465    js::Fprinter out(stderr);
    466    JSString* str = ToString<CanGC>(cx, args[0]);
    467    if (str) {
    468      str->dumpCharsNoQuote(out);
    469      out.putChar('\n');
    470    } else {
    471      cx->recoverFromOutOfMemory();
    472    }
    473  }
    474 #endif
    475  args.rval().setUndefined();
    476  return true;
    477 }
    478 
    479 /*
    480 * Used to decompile values in the nearest non-builtin stack frame, falling
    481 * back to decompiling in the current frame. Helpful for printing higher-order
    482 * function arguments.
    483 *
    484 * The user must supply the argument number of the value in question; it
    485 * _cannot_ be automatically determined.
    486 */
    487 static bool intrinsic_DecompileArg(JSContext* cx, unsigned argc, Value* vp) {
    488  CallArgs args = CallArgsFromVp(argc, vp);
    489  MOZ_ASSERT(args.length() == 2);
    490  MOZ_RELEASE_ASSERT(args[0].isInt32());
    491 
    492  HandleValue value = args[1];
    493  JSString* str = DecompileArgument(cx, args[0].toInt32(), value);
    494  if (!str) {
    495    return false;
    496  }
    497  args.rval().setString(str);
    498  return true;
    499 }
    500 
    501 static bool intrinsic_DefineDataProperty(JSContext* cx, unsigned argc,
    502                                         Value* vp) {
    503  CallArgs args = CallArgsFromVp(argc, vp);
    504 
    505  // When DefineDataProperty is called with 3 arguments, it's compiled to
    506  // JSOp::InitElem in the bytecode emitter so we shouldn't get here.
    507  MOZ_ASSERT(args.length() == 4);
    508  MOZ_ASSERT(args[0].isObject());
    509  MOZ_RELEASE_ASSERT(args[3].isInt32());
    510 
    511  RootedObject obj(cx, &args[0].toObject());
    512  RootedId id(cx);
    513  if (!ToPropertyKey(cx, args[1], &id)) {
    514    return false;
    515  }
    516  RootedValue value(cx, args[2]);
    517 
    518  JS::PropertyAttributes attrs;
    519  unsigned attributes = args[3].toInt32();
    520 
    521  MOZ_ASSERT(bool(attributes & ATTR_ENUMERABLE) !=
    522                 bool(attributes & ATTR_NONENUMERABLE),
    523             "DefineDataProperty must receive either ATTR_ENUMERABLE xor "
    524             "ATTR_NONENUMERABLE");
    525  if (attributes & ATTR_ENUMERABLE) {
    526    attrs += JS::PropertyAttribute::Enumerable;
    527  }
    528 
    529  MOZ_ASSERT(bool(attributes & ATTR_CONFIGURABLE) !=
    530                 bool(attributes & ATTR_NONCONFIGURABLE),
    531             "DefineDataProperty must receive either ATTR_CONFIGURABLE xor "
    532             "ATTR_NONCONFIGURABLE");
    533  if (attributes & ATTR_CONFIGURABLE) {
    534    attrs += JS::PropertyAttribute::Configurable;
    535  }
    536 
    537  MOZ_ASSERT(
    538      bool(attributes & ATTR_WRITABLE) != bool(attributes & ATTR_NONWRITABLE),
    539      "DefineDataProperty must receive either ATTR_WRITABLE xor "
    540      "ATTR_NONWRITABLE");
    541  if (attributes & ATTR_WRITABLE) {
    542    attrs += JS::PropertyAttribute::Writable;
    543  }
    544 
    545  Rooted<PropertyDescriptor> desc(cx, PropertyDescriptor::Data(value, attrs));
    546  if (!DefineProperty(cx, obj, id, desc)) {
    547    return false;
    548  }
    549 
    550  args.rval().setUndefined();
    551  return true;
    552 }
    553 
    554 static bool intrinsic_DefineProperty(JSContext* cx, unsigned argc, Value* vp) {
    555  // _DefineProperty(object, propertyKey, attributes,
    556  //                 valueOrGetter, setter, strict)
    557  CallArgs args = CallArgsFromVp(argc, vp);
    558  MOZ_ASSERT(args.length() == 6);
    559  MOZ_ASSERT(args[0].isObject());
    560  MOZ_ASSERT(args[1].isString() || args[1].isNumber() || args[1].isSymbol());
    561  MOZ_RELEASE_ASSERT(args[2].isInt32());
    562  MOZ_ASSERT(args[5].isBoolean());
    563 
    564  RootedObject obj(cx, &args[0].toObject());
    565  RootedId id(cx);
    566  if (!PrimitiveValueToId<CanGC>(cx, args[1], &id)) {
    567    return false;
    568  }
    569 
    570  Rooted<PropertyDescriptor> desc(cx, PropertyDescriptor::Empty());
    571 
    572  unsigned attributes = args[2].toInt32();
    573  if (attributes & (ATTR_ENUMERABLE | ATTR_NONENUMERABLE)) {
    574    desc.setEnumerable(attributes & ATTR_ENUMERABLE);
    575  }
    576 
    577  if (attributes & (ATTR_CONFIGURABLE | ATTR_NONCONFIGURABLE)) {
    578    desc.setConfigurable(attributes & ATTR_CONFIGURABLE);
    579  }
    580 
    581  if (attributes & (ATTR_WRITABLE | ATTR_NONWRITABLE)) {
    582    desc.setWritable(attributes & ATTR_WRITABLE);
    583  }
    584 
    585  // When args[4] is |null|, the data descriptor has a value component.
    586  if ((attributes & DATA_DESCRIPTOR_KIND) && args[4].isNull()) {
    587    desc.setValue(args[3]);
    588  }
    589 
    590  if (attributes & ACCESSOR_DESCRIPTOR_KIND) {
    591    Value getter = args[3];
    592    if (getter.isObject()) {
    593      desc.setGetter(&getter.toObject());
    594    } else if (getter.isUndefined()) {
    595      desc.setGetter(nullptr);
    596    } else {
    597      MOZ_ASSERT(getter.isNull());
    598    }
    599 
    600    Value setter = args[4];
    601    if (setter.isObject()) {
    602      desc.setSetter(&setter.toObject());
    603    } else if (setter.isUndefined()) {
    604      desc.setSetter(nullptr);
    605    } else {
    606      MOZ_ASSERT(setter.isNull());
    607    }
    608  }
    609 
    610  desc.assertValid();
    611 
    612  ObjectOpResult result;
    613  if (!DefineProperty(cx, obj, id, desc, result)) {
    614    return false;
    615  }
    616 
    617  bool strict = args[5].toBoolean();
    618  if (strict && !result.ok()) {
    619    // We need to tell our caller Object.defineProperty,
    620    // that this operation failed, without actually throwing
    621    // for web-compatibility reasons.
    622    if (result.failureCode() == JSMSG_CANT_DEFINE_WINDOW_NC) {
    623      args.rval().setBoolean(false);
    624      return true;
    625    }
    626 
    627    return result.reportError(cx, obj, id);
    628  }
    629 
    630  args.rval().setBoolean(result.ok());
    631  return true;
    632 }
    633 
    634 static bool intrinsic_UnsafeSetReservedSlot(JSContext* cx, unsigned argc,
    635                                            Value* vp) {
    636  CallArgs args = CallArgsFromVp(argc, vp);
    637  MOZ_ASSERT(args.length() == 3);
    638  MOZ_ASSERT(args[0].isObject());
    639  MOZ_RELEASE_ASSERT(args[1].isInt32());
    640  MOZ_ASSERT(args[1].toInt32() >= 0);
    641 
    642  uint32_t slot = uint32_t(args[1].toInt32());
    643  args[0].toObject().as<NativeObject>().setReservedSlot(slot, args[2]);
    644  args.rval().setUndefined();
    645  return true;
    646 }
    647 
    648 static bool intrinsic_UnsafeGetReservedSlot(JSContext* cx, unsigned argc,
    649                                            Value* vp) {
    650  CallArgs args = CallArgsFromVp(argc, vp);
    651  MOZ_ASSERT(args.length() == 2);
    652  MOZ_ASSERT(args[0].isObject());
    653  MOZ_RELEASE_ASSERT(args[1].isInt32());
    654  MOZ_ASSERT(args[1].toInt32() >= 0);
    655 
    656  uint32_t slot = uint32_t(args[1].toInt32());
    657  args.rval().set(args[0].toObject().as<NativeObject>().getReservedSlot(slot));
    658  return true;
    659 }
    660 
    661 static bool intrinsic_UnsafeGetObjectFromReservedSlot(JSContext* cx,
    662                                                      unsigned argc,
    663                                                      Value* vp) {
    664  if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp)) {
    665    return false;
    666  }
    667  MOZ_ASSERT(vp->isObject());
    668  return true;
    669 }
    670 
    671 static bool intrinsic_UnsafeGetInt32FromReservedSlot(JSContext* cx,
    672                                                     unsigned argc, Value* vp) {
    673  if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp)) {
    674    return false;
    675  }
    676  MOZ_ASSERT(vp->isInt32());
    677  return true;
    678 }
    679 
    680 static bool intrinsic_UnsafeGetStringFromReservedSlot(JSContext* cx,
    681                                                      unsigned argc,
    682                                                      Value* vp) {
    683  if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp)) {
    684    return false;
    685  }
    686  MOZ_ASSERT(vp->isString());
    687  return true;
    688 }
    689 
    690 static bool intrinsic_IsPackedArray(JSContext* cx, unsigned argc, Value* vp) {
    691  CallArgs args = CallArgsFromVp(argc, vp);
    692  MOZ_ASSERT(args.length() == 1);
    693  MOZ_ASSERT(args[0].isObject());
    694  args.rval().setBoolean(IsPackedArray(&args[0].toObject()));
    695  return true;
    696 }
    697 
    698 bool js::intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, Value* vp) {
    699  CallArgs args = CallArgsFromVp(argc, vp);
    700  MOZ_ASSERT(args.length() == 0);
    701 
    702  JSObject* obj = NewArrayIterator(cx);
    703  if (!obj) {
    704    return false;
    705  }
    706 
    707  args.rval().setObject(*obj);
    708  return true;
    709 }
    710 
    711 static bool intrinsic_ArrayIteratorPrototypeOptimizable(JSContext* cx,
    712                                                        unsigned argc,
    713                                                        Value* vp) {
    714  CallArgs args = CallArgsFromVp(argc, vp);
    715  MOZ_ASSERT(args.length() == 0);
    716 
    717  bool optimized = HasOptimizableArrayIteratorPrototype(cx);
    718  args.rval().setBoolean(optimized);
    719  return true;
    720 }
    721 
    722 static bool intrinsic_GetNextMapEntryForIterator(JSContext* cx, unsigned argc,
    723                                                 Value* vp) {
    724  CallArgs args = CallArgsFromVp(argc, vp);
    725  MOZ_ASSERT(args.length() == 2);
    726  MOZ_ASSERT(args[0].toObject().is<MapIteratorObject>());
    727  MOZ_ASSERT(args[1].isObject());
    728 
    729  MapIteratorObject* mapIterator = &args[0].toObject().as<MapIteratorObject>();
    730  ArrayObject* result = &args[1].toObject().as<ArrayObject>();
    731 
    732  args.rval().setBoolean(MapIteratorObject::next(mapIterator, result));
    733  return true;
    734 }
    735 
    736 static bool intrinsic_CreateMapIterationResultPair(JSContext* cx, unsigned argc,
    737                                                   Value* vp) {
    738  CallArgs args = CallArgsFromVp(argc, vp);
    739  MOZ_ASSERT(args.length() == 0);
    740 
    741  JSObject* result = MapIteratorObject::createResultPair(cx);
    742  if (!result) {
    743    return false;
    744  }
    745 
    746  args.rval().setObject(*result);
    747  return true;
    748 }
    749 
    750 static bool intrinsic_GetNextSetEntryForIterator(JSContext* cx, unsigned argc,
    751                                                 Value* vp) {
    752  CallArgs args = CallArgsFromVp(argc, vp);
    753  MOZ_ASSERT(args.length() == 2);
    754  MOZ_ASSERT(args[0].toObject().is<SetIteratorObject>());
    755  MOZ_ASSERT(args[1].isObject());
    756 
    757  SetIteratorObject* setIterator = &args[0].toObject().as<SetIteratorObject>();
    758  ArrayObject* result = &args[1].toObject().as<ArrayObject>();
    759 
    760  args.rval().setBoolean(SetIteratorObject::next(setIterator, result));
    761  return true;
    762 }
    763 
    764 static bool intrinsic_CreateSetIterationResult(JSContext* cx, unsigned argc,
    765                                               Value* vp) {
    766  CallArgs args = CallArgsFromVp(argc, vp);
    767  MOZ_ASSERT(args.length() == 0);
    768 
    769  JSObject* result = SetIteratorObject::createResult(cx);
    770  if (!result) {
    771    return false;
    772  }
    773 
    774  args.rval().setObject(*result);
    775  return true;
    776 }
    777 
    778 bool js::intrinsic_NewStringIterator(JSContext* cx, unsigned argc, Value* vp) {
    779  CallArgs args = CallArgsFromVp(argc, vp);
    780  MOZ_ASSERT(args.length() == 0);
    781 
    782  JSObject* obj = NewStringIterator(cx);
    783  if (!obj) {
    784    return false;
    785  }
    786 
    787  args.rval().setObject(*obj);
    788  return true;
    789 }
    790 
    791 bool js::intrinsic_NewRegExpStringIterator(JSContext* cx, unsigned argc,
    792                                           Value* vp) {
    793  CallArgs args = CallArgsFromVp(argc, vp);
    794  MOZ_ASSERT(args.length() == 0);
    795 
    796  JSObject* obj = NewRegExpStringIterator(cx);
    797  if (!obj) {
    798    return false;
    799  }
    800 
    801  args.rval().setObject(*obj);
    802  return true;
    803 }
    804 
    805 js::PropertyName* js::GetClonedSelfHostedFunctionName(const JSFunction* fun) {
    806  if (!fun->isExtended()) {
    807    return nullptr;
    808  }
    809  Value name = fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT);
    810  if (!name.isString()) {
    811    return nullptr;
    812  }
    813  return name.toString()->asAtom().asPropertyName();
    814 }
    815 
    816 bool js::IsExtendedUnclonedSelfHostedFunctionName(JSAtom* name) {
    817  if (name->length() < 2) {
    818    return false;
    819  }
    820  return name->latin1OrTwoByteChar(0) ==
    821         ExtendedUnclonedSelfHostedFunctionNamePrefix;
    822 }
    823 
    824 void js::SetClonedSelfHostedFunctionName(JSFunction* fun,
    825                                         js::PropertyName* name) {
    826  fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(name));
    827 }
    828 
    829 static bool intrinsic_GeneratorObjectIsClosed(JSContext* cx, unsigned argc,
    830                                              Value* vp) {
    831  CallArgs args = CallArgsFromVp(argc, vp);
    832  MOZ_ASSERT(args.length() == 1);
    833  MOZ_ASSERT(args[0].isObject());
    834 
    835  GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
    836  args.rval().setBoolean(genObj->isClosed());
    837  return true;
    838 }
    839 
    840 static bool intrinsic_IsSuspendedGenerator(JSContext* cx, unsigned argc,
    841                                           Value* vp) {
    842  CallArgs args = CallArgsFromVp(argc, vp);
    843  MOZ_ASSERT(args.length() == 1);
    844 
    845  if (!args[0].isObject() || !args[0].toObject().is<GeneratorObject>()) {
    846    args.rval().setBoolean(false);
    847    return true;
    848  }
    849 
    850  GeneratorObject& genObj = args[0].toObject().as<GeneratorObject>();
    851  MOZ_ASSERT_IF(genObj.isSuspended(), !genObj.isClosed());
    852  args.rval().setBoolean(genObj.isSuspended());
    853  return true;
    854 }
    855 
    856 static bool intrinsic_GeneratorIsRunning(JSContext* cx, unsigned argc,
    857                                         Value* vp) {
    858  CallArgs args = CallArgsFromVp(argc, vp);
    859  MOZ_ASSERT(args.length() == 1);
    860  MOZ_ASSERT(args[0].isObject());
    861 
    862  GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
    863  args.rval().setBoolean(genObj->isRunning());
    864  return true;
    865 }
    866 
    867 static bool intrinsic_GeneratorSetClosed(JSContext* cx, unsigned argc,
    868                                         Value* vp) {
    869  CallArgs args = CallArgsFromVp(argc, vp);
    870  MOZ_ASSERT(args.length() == 1);
    871  MOZ_ASSERT(args[0].isObject());
    872 
    873  GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
    874  genObj->setClosed(cx);
    875  return true;
    876 }
    877 
    878 static bool intrinsic_IsTypedArrayConstructor(JSContext* cx, unsigned argc,
    879                                              Value* vp) {
    880  CallArgs args = CallArgsFromVp(argc, vp);
    881  MOZ_ASSERT(args.length() == 1);
    882  MOZ_ASSERT(args[0].isObject());
    883 
    884  args.rval().setBoolean(js::IsTypedArrayConstructor(&args[0].toObject()));
    885  return true;
    886 }
    887 
    888 // Return the value of [[ArrayLength]] internal slot of the TypedArray
    889 static bool intrinsic_TypedArrayLength(JSContext* cx, unsigned argc,
    890                                       Value* vp) {
    891  CallArgs args = CallArgsFromVp(argc, vp);
    892  MOZ_ASSERT(args.length() == 1);
    893  MOZ_ASSERT(args[0].toObject().is<TypedArrayObject>());
    894 
    895  auto* tarr = &args[0].toObject().as<TypedArrayObject>();
    896 
    897  mozilla::Maybe<size_t> length = tarr->length();
    898  if (!length) {
    899    // Return zero for detached buffers to match JIT code.
    900    if (tarr->hasDetachedBuffer()) {
    901      args.rval().setInt32(0);
    902      return true;
    903    }
    904 
    905    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    906                              JSMSG_TYPED_ARRAY_RESIZED_BOUNDS);
    907    return false;
    908  }
    909 
    910  args.rval().setNumber(*length);
    911  return true;
    912 }
    913 
    914 static bool intrinsic_PossiblyWrappedTypedArrayLength(JSContext* cx,
    915                                                      unsigned argc,
    916                                                      Value* vp) {
    917  CallArgs args = CallArgsFromVp(argc, vp);
    918  MOZ_ASSERT(args.length() == 1);
    919  MOZ_ASSERT(args[0].isObject());
    920 
    921  TypedArrayObject* obj = args[0].toObject().maybeUnwrapAs<TypedArrayObject>();
    922  if (!obj) {
    923    ReportAccessDenied(cx);
    924    return false;
    925  }
    926 
    927  mozilla::Maybe<size_t> length = obj->length();
    928  if (!length) {
    929    // Return zero for detached buffers to match JIT code.
    930    if (obj->hasDetachedBuffer()) {
    931      args.rval().setInt32(0);
    932      return true;
    933    }
    934 
    935    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    936                              JSMSG_TYPED_ARRAY_RESIZED_BOUNDS);
    937    return false;
    938  }
    939 
    940  args.rval().setNumber(*length);
    941  return true;
    942 }
    943 
    944 static bool intrinsic_PossiblyWrappedTypedArrayHasDetachedBuffer(JSContext* cx,
    945                                                                 unsigned argc,
    946                                                                 Value* vp) {
    947  CallArgs args = CallArgsFromVp(argc, vp);
    948  MOZ_ASSERT(args.length() == 1);
    949  MOZ_ASSERT(args[0].isObject());
    950 
    951  TypedArrayObject* obj = args[0].toObject().maybeUnwrapAs<TypedArrayObject>();
    952  if (!obj) {
    953    ReportAccessDenied(cx);
    954    return false;
    955  }
    956 
    957  bool detached = obj->hasDetachedBuffer();
    958  args.rval().setBoolean(detached);
    959  return true;
    960 }
    961 
    962 static bool intrinsic_PossiblyWrappedTypedArrayHasImmutableBuffer(JSContext* cx,
    963                                                                  unsigned argc,
    964                                                                  Value* vp) {
    965  CallArgs args = CallArgsFromVp(argc, vp);
    966  MOZ_ASSERT(args.length() == 1);
    967  MOZ_ASSERT(args[0].isObject());
    968 
    969  auto* obj = args[0].toObject().maybeUnwrapAs<TypedArrayObject>();
    970  if (!obj) {
    971    ReportAccessDenied(cx);
    972    return false;
    973  }
    974 
    975  bool immutable = obj->is<ImmutableTypedArrayObject>();
    976  args.rval().setBoolean(immutable);
    977  return true;
    978 }
    979 
    980 static bool intrinsic_TypedArrayInitFromPackedArray(JSContext* cx,
    981                                                    unsigned argc, Value* vp) {
    982  CallArgs args = CallArgsFromVp(argc, vp);
    983  MOZ_ASSERT(args.length() == 2);
    984  MOZ_ASSERT(args[0].isObject());
    985  MOZ_ASSERT(args[1].isObject());
    986 
    987  Rooted<FixedLengthTypedArrayObject*> target(
    988      cx, &args[0].toObject().as<FixedLengthTypedArrayObject>());
    989  MOZ_ASSERT(!target->hasDetachedBuffer());
    990  MOZ_ASSERT(!target->isSharedMemory());
    991 
    992  Rooted<ArrayObject*> source(cx, &args[1].toObject().as<ArrayObject>());
    993  MOZ_ASSERT(IsPackedArray(source));
    994  MOZ_ASSERT(source->length() == target->length());
    995 
    996  switch (target->type()) {
    997 #define INIT_TYPED_ARRAY(_, T, N)                                      \
    998  case Scalar::N: {                                                    \
    999    if (!ElementSpecific<T, UnsharedOps>::initFromIterablePackedArray( \
   1000            cx, target, source)) {                                     \
   1001      return false;                                                    \
   1002    }                                                                  \
   1003    break;                                                             \
   1004  }
   1005    JS_FOR_EACH_TYPED_ARRAY(INIT_TYPED_ARRAY)
   1006 #undef INIT_TYPED_ARRAY
   1007 
   1008    default:
   1009      MOZ_CRASH(
   1010          "TypedArrayInitFromPackedArray with a typed array with bogus type");
   1011  }
   1012 
   1013  args.rval().setUndefined();
   1014  return true;
   1015 }
   1016 
   1017 template <bool ForTest>
   1018 static bool intrinsic_RegExpBuiltinExec(JSContext* cx, unsigned argc,
   1019                                        Value* vp) {
   1020  CallArgs args = CallArgsFromVp(argc, vp);
   1021  MOZ_ASSERT(args.length() == 2);
   1022  MOZ_ASSERT(args[0].isObject());
   1023  MOZ_ASSERT(args[0].toObject().is<RegExpObject>());
   1024  MOZ_ASSERT(args[1].isString());
   1025 
   1026  Rooted<RegExpObject*> obj(cx, &args[0].toObject().as<RegExpObject>());
   1027  Rooted<JSString*> string(cx, args[1].toString());
   1028  return RegExpBuiltinExec(cx, obj, string, ForTest, args.rval());
   1029 }
   1030 
   1031 template <bool ForTest>
   1032 static bool intrinsic_RegExpExec(JSContext* cx, unsigned argc, Value* vp) {
   1033  CallArgs args = CallArgsFromVp(argc, vp);
   1034  MOZ_ASSERT(args.length() == 2);
   1035  MOZ_ASSERT(args[0].isObject());
   1036  MOZ_ASSERT(args[1].isString());
   1037 
   1038  Rooted<JSObject*> obj(cx, &args[0].toObject());
   1039  Rooted<JSString*> string(cx, args[1].toString());
   1040  return RegExpExec(cx, obj, string, ForTest, args.rval());
   1041 }
   1042 
   1043 static bool intrinsic_RegExpCreate(JSContext* cx, unsigned argc, Value* vp) {
   1044  CallArgs args = CallArgsFromVp(argc, vp);
   1045 
   1046  MOZ_ASSERT(args.length() == 1 || args.length() == 2);
   1047  MOZ_ASSERT_IF(args.length() == 2,
   1048                args[1].isString() || args[1].isUndefined());
   1049  MOZ_ASSERT(!args.isConstructing());
   1050 
   1051  return RegExpCreate(cx, args[0], args.get(1), args.rval(), nullptr);
   1052 }
   1053 
   1054 static bool intrinsic_RegExpGetSubstitution(JSContext* cx, unsigned argc,
   1055                                            Value* vp) {
   1056  CallArgs args = CallArgsFromVp(argc, vp);
   1057  MOZ_ASSERT(args.length() == 6);
   1058 
   1059  Rooted<ArrayObject*> matchResult(cx, &args[0].toObject().as<ArrayObject>());
   1060 
   1061  Rooted<JSLinearString*> string(cx, args[1].toString()->ensureLinear(cx));
   1062  if (!string) {
   1063    return false;
   1064  }
   1065 
   1066  int32_t position = int32_t(args[2].toNumber());
   1067  MOZ_ASSERT(position >= 0);
   1068 
   1069  Rooted<JSLinearString*> replacement(cx, args[3].toString()->ensureLinear(cx));
   1070  if (!replacement) {
   1071    return false;
   1072  }
   1073 
   1074  int32_t firstDollarIndex = int32_t(args[4].toNumber());
   1075  MOZ_ASSERT(firstDollarIndex >= 0);
   1076 
   1077  RootedValue namedCaptures(cx, args[5]);
   1078  MOZ_ASSERT(namedCaptures.isUndefined() || namedCaptures.isObject());
   1079 
   1080  return RegExpGetSubstitution(cx, matchResult, string, size_t(position),
   1081                               replacement, size_t(firstDollarIndex),
   1082                               namedCaptures, args.rval());
   1083 }
   1084 
   1085 static bool intrinsic_RegExpHasCaptureGroups(JSContext* cx, unsigned argc,
   1086                                             Value* vp) {
   1087  CallArgs args = CallArgsFromVp(argc, vp);
   1088  MOZ_ASSERT(args.length() == 2);
   1089  MOZ_ASSERT(args[0].isObject());
   1090  MOZ_ASSERT(args[1].isString());
   1091 
   1092  Rooted<RegExpObject*> obj(cx, &args[0].toObject().as<RegExpObject>());
   1093  Rooted<JSString*> string(cx, args[1].toString());
   1094 
   1095  bool result;
   1096  if (!RegExpHasCaptureGroups(cx, obj, string, &result)) {
   1097    return false;
   1098  }
   1099 
   1100  args.rval().setBoolean(result);
   1101  return true;
   1102 }
   1103 
   1104 static bool intrinsic_StringReplaceString(JSContext* cx, unsigned argc,
   1105                                          Value* vp) {
   1106  CallArgs args = CallArgsFromVp(argc, vp);
   1107  MOZ_ASSERT(args.length() == 3);
   1108 
   1109  RootedString string(cx, args[0].toString());
   1110  RootedString pattern(cx, args[1].toString());
   1111  RootedString replacement(cx, args[2].toString());
   1112  JSString* result = str_replace_string_raw(cx, string, pattern, replacement);
   1113  if (!result) {
   1114    return false;
   1115  }
   1116 
   1117  args.rval().setString(result);
   1118  return true;
   1119 }
   1120 
   1121 static bool intrinsic_StringReplaceAllString(JSContext* cx, unsigned argc,
   1122                                             Value* vp) {
   1123  CallArgs args = CallArgsFromVp(argc, vp);
   1124  MOZ_ASSERT(args.length() == 3);
   1125 
   1126  RootedString string(cx, args[0].toString());
   1127  RootedString pattern(cx, args[1].toString());
   1128  RootedString replacement(cx, args[2].toString());
   1129  JSString* result =
   1130      str_replaceAll_string_raw(cx, string, pattern, replacement);
   1131  if (!result) {
   1132    return false;
   1133  }
   1134 
   1135  args.rval().setString(result);
   1136  return true;
   1137 }
   1138 
   1139 static bool intrinsic_StringSplitString(JSContext* cx, unsigned argc,
   1140                                        Value* vp) {
   1141  CallArgs args = CallArgsFromVp(argc, vp);
   1142  MOZ_ASSERT(args.length() == 2);
   1143 
   1144  RootedString string(cx, args[0].toString());
   1145  RootedString sep(cx, args[1].toString());
   1146 
   1147  JSObject* aobj = StringSplitString(cx, string, sep, INT32_MAX);
   1148  if (!aobj) {
   1149    return false;
   1150  }
   1151 
   1152  args.rval().setObject(*aobj);
   1153  return true;
   1154 }
   1155 
   1156 static bool intrinsic_StringSplitStringLimit(JSContext* cx, unsigned argc,
   1157                                             Value* vp) {
   1158  CallArgs args = CallArgsFromVp(argc, vp);
   1159  MOZ_ASSERT(args.length() == 3);
   1160 
   1161  RootedString string(cx, args[0].toString());
   1162  RootedString sep(cx, args[1].toString());
   1163 
   1164  // args[2] should be already in UInt32 range, but it could be double typed,
   1165  // because of Ion optimization.
   1166  uint32_t limit = uint32_t(args[2].toNumber());
   1167  MOZ_ASSERT(limit > 0,
   1168             "Zero limit case is already handled in self-hosted code.");
   1169 
   1170  JSObject* aobj = StringSplitString(cx, string, sep, limit);
   1171  if (!aobj) {
   1172    return false;
   1173  }
   1174 
   1175  args.rval().setObject(*aobj);
   1176  return true;
   1177 }
   1178 
   1179 bool CallSelfHostedNonGenericMethod(JSContext* cx, const CallArgs& args) {
   1180  // This function is called when a self-hosted method is invoked on a
   1181  // wrapper object, like a CrossCompartmentWrapper. The last argument is
   1182  // the name of the self-hosted function. The other arguments are the
   1183  // arguments to pass to this function.
   1184 
   1185  MOZ_ASSERT(args.length() > 0);
   1186  Rooted<PropertyName*> name(
   1187      cx, args[args.length() - 1].toString()->asAtom().asPropertyName());
   1188 
   1189  InvokeArgs args2(cx);
   1190  if (!args2.init(cx, args.length() - 1)) {
   1191    return false;
   1192  }
   1193 
   1194  for (size_t i = 0; i < args.length() - 1; i++) {
   1195    args2[i].set(args[i]);
   1196  }
   1197 
   1198  return CallSelfHostedFunction(cx, name, args.thisv(), args2, args.rval());
   1199 }
   1200 
   1201 #ifdef DEBUG
   1202 bool js::CallSelfHostedFunction(JSContext* cx, const char* name,
   1203                                HandleValue thisv, const AnyInvokeArgs& args,
   1204                                MutableHandleValue rval) {
   1205  JSAtom* funAtom = Atomize(cx, name, strlen(name));
   1206  if (!funAtom) {
   1207    return false;
   1208  }
   1209  Rooted<PropertyName*> funName(cx, funAtom->asPropertyName());
   1210  return CallSelfHostedFunction(cx, funName, thisv, args, rval);
   1211 }
   1212 #endif
   1213 
   1214 bool js::CallSelfHostedFunction(JSContext* cx, Handle<PropertyName*> name,
   1215                                HandleValue thisv, const AnyInvokeArgs& args,
   1216                                MutableHandleValue rval) {
   1217  RootedValue fun(cx);
   1218  if (!GlobalObject::getIntrinsicValue(cx, cx->global(), name, &fun)) {
   1219    return false;
   1220  }
   1221  MOZ_ASSERT(fun.toObject().is<JSFunction>());
   1222 
   1223  return Call(cx, fun, thisv, args, rval);
   1224 }
   1225 
   1226 template <typename T>
   1227 bool Is(HandleValue v) {
   1228  return v.isObject() && v.toObject().is<T>();
   1229 }
   1230 
   1231 template <IsAcceptableThis Test>
   1232 static bool CallNonGenericSelfhostedMethod(JSContext* cx, unsigned argc,
   1233                                           Value* vp) {
   1234  CallArgs args = CallArgsFromVp(argc, vp);
   1235  return CallNonGenericMethod<Test, CallSelfHostedNonGenericMethod>(cx, args);
   1236 }
   1237 
   1238 bool js::IsCallSelfHostedNonGenericMethod(NativeImpl impl) {
   1239  return impl == CallSelfHostedNonGenericMethod;
   1240 }
   1241 
   1242 bool js::ReportIncompatibleSelfHostedMethod(
   1243    JSContext* cx, Handle<Value> thisValue,
   1244    IncompatibleContext incompatibleContext) {
   1245  // The contract for this function is the same as
   1246  // CallSelfHostedNonGenericMethod. The normal ReportIncompatible function
   1247  // doesn't work for selfhosted functions, because they always call the
   1248  // different CallXXXMethodIfWrapped methods, which would be reported as the
   1249  // called function instead.
   1250 
   1251  // Lookup the selfhosted method that was invoked.  But skip over
   1252  // internal self-hosted function frames, because those are never the
   1253  // actual self-hosted callee from external code.  We can't just skip
   1254  // self-hosted things until we find a non-self-hosted one because of cases
   1255  // like array.sort(somethingSelfHosted), where we want to report the error
   1256  // in the somethingSelfHosted, not in the sort() call.
   1257 
   1258  static const char* const internalNames[] = {
   1259      "EnsureTypedArrayWithArrayBuffer",
   1260      "RegExpSearchSlowPath",
   1261      "RegExpReplaceSlowPath",
   1262      "RegExpMatchSlowPath",
   1263  };
   1264 
   1265  ScriptFrameIter iter(cx);
   1266  MOZ_ASSERT(iter.isFunctionFrame());
   1267 
   1268  while (!iter.done()) {
   1269    MOZ_ASSERT(iter.callee(cx)->isSelfHostedOrIntrinsic());
   1270    UniqueChars funNameBytes;
   1271    const char* funName =
   1272        GetFunctionNameBytes(cx, iter.callee(cx), &funNameBytes);
   1273    if (!funName) {
   1274      return false;
   1275    }
   1276    if (std::all_of(
   1277            std::begin(internalNames), std::end(internalNames),
   1278            [funName](auto* name) { return strcmp(funName, name) != 0; })) {
   1279      if (incompatibleContext == IncompatibleContext::RegExpExec) {
   1280        JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
   1281                                 JSMSG_INCOMPATIBLE_REGEXP_METHOD, funName,
   1282                                 InformalValueTypeName(thisValue));
   1283      } else {
   1284        JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
   1285                                 JSMSG_INCOMPATIBLE_METHOD, funName, "method",
   1286                                 InformalValueTypeName(thisValue));
   1287      }
   1288      return false;
   1289    }
   1290    ++iter;
   1291  }
   1292 
   1293  MOZ_ASSERT_UNREACHABLE("How did we not find a useful self-hosted frame?");
   1294  return false;
   1295 }
   1296 
   1297 #ifdef JS_HAS_INTL_API
   1298 static bool intrinsic_DefaultLocale(JSContext* cx, unsigned argc, Value* vp) {
   1299  CallArgs args = CallArgsFromVp(argc, vp);
   1300  MOZ_ASSERT(args.length() == 0);
   1301 
   1302  auto* locale = cx->global()->globalIntlData().defaultLocale(cx);
   1303  if (!locale) {
   1304    return false;
   1305  }
   1306 
   1307  args.rval().setString(locale);
   1308  return true;
   1309 }
   1310 
   1311 static bool intrinsic_DefaultTimeZone(JSContext* cx, unsigned argc, Value* vp) {
   1312  CallArgs args = CallArgsFromVp(argc, vp);
   1313  MOZ_ASSERT(args.length() == 0);
   1314 
   1315  auto* timeZone = cx->global()->globalIntlData().defaultTimeZone(cx);
   1316  if (!timeZone) {
   1317    return false;
   1318  }
   1319 
   1320  args.rval().setString(timeZone);
   1321  return true;
   1322 }
   1323 
   1324 static bool intl_ValidateAndCanonicalizeTimeZone(JSContext* cx, unsigned argc,
   1325                                                 Value* vp) {
   1326  CallArgs args = CallArgsFromVp(argc, vp);
   1327  MOZ_ASSERT(args.length() == 1);
   1328 
   1329  Rooted<JSString*> timeZone(cx, args[0].toString());
   1330  auto* timeZoneId = temporal::ToValidCanonicalTimeZoneIdentifier(cx, timeZone);
   1331  if (!timeZoneId) {
   1332    return false;
   1333  }
   1334 
   1335  args.rval().setString(timeZoneId);
   1336  return true;
   1337 }
   1338 #endif  // JS_HAS_INTL_API
   1339 
   1340 static bool intrinsic_ConstructFunction(JSContext* cx, unsigned argc,
   1341                                        Value* vp) {
   1342  CallArgs args = CallArgsFromVp(argc, vp);
   1343  MOZ_ASSERT(args.length() == 3);
   1344  MOZ_ASSERT(IsConstructor(args[0]));
   1345  MOZ_ASSERT(IsConstructor(args[1]));
   1346  MOZ_ASSERT(args[2].toObject().is<ArrayObject>());
   1347 
   1348  Rooted<ArrayObject*> argsList(cx, &args[2].toObject().as<ArrayObject>());
   1349  uint32_t len = argsList->length();
   1350  ConstructArgs constructArgs(cx);
   1351  if (!constructArgs.init(cx, len)) {
   1352    return false;
   1353  }
   1354  for (uint32_t index = 0; index < len; index++) {
   1355    constructArgs[index].set(argsList->getDenseElement(index));
   1356  }
   1357 
   1358  RootedObject res(cx);
   1359  if (!Construct(cx, args[0], constructArgs, args[1], &res)) {
   1360    return false;
   1361  }
   1362 
   1363  args.rval().setObject(*res);
   1364  return true;
   1365 }
   1366 
   1367 static bool intrinsic_IsConstructing(JSContext* cx, unsigned argc, Value* vp) {
   1368  CallArgs args = CallArgsFromVp(argc, vp);
   1369  MOZ_ASSERT(args.length() == 0);
   1370 
   1371  ScriptFrameIter iter(cx);
   1372  bool isConstructing = iter.isConstructing();
   1373  args.rval().setBoolean(isConstructing);
   1374  return true;
   1375 }
   1376 
   1377 static bool intrinsic_ConstructorForTypedArray(JSContext* cx, unsigned argc,
   1378                                               Value* vp) {
   1379  CallArgs args = CallArgsFromVp(argc, vp);
   1380  MOZ_ASSERT(args.length() == 1);
   1381  MOZ_ASSERT(args[0].isObject());
   1382 
   1383  auto* object = UnwrapAndDowncastValue<TypedArrayObject>(cx, args[0]);
   1384  if (!object) {
   1385    return false;
   1386  }
   1387 
   1388  JSProtoKey protoKey = StandardProtoKeyOrNull(object);
   1389  MOZ_ASSERT(protoKey);
   1390 
   1391  // While it may seem like an invariant that in any compartment,
   1392  // seeing a typed array object implies that the TypedArray constructor
   1393  // for that type is initialized on the compartment's global, this is not
   1394  // the case. When we construct a typed array given a cross-compartment
   1395  // ArrayBuffer, we put the constructed TypedArray in the same compartment
   1396  // as the ArrayBuffer. Since we use the prototype from the initial
   1397  // compartment, and never call the constructor in the ArrayBuffer's
   1398  // compartment from script, we are not guaranteed to have initialized
   1399  // the constructor.
   1400  JSObject* ctor = GlobalObject::getOrCreateConstructor(cx, protoKey);
   1401  if (!ctor) {
   1402    return false;
   1403  }
   1404 
   1405  args.rval().setObject(*ctor);
   1406  return true;
   1407 }
   1408 
   1409 static bool intrinsic_PromiseResolve(JSContext* cx, unsigned argc, Value* vp) {
   1410  CallArgs args = CallArgsFromVp(argc, vp);
   1411  MOZ_ASSERT(args.length() == 2);
   1412 
   1413  RootedObject constructor(cx, &args[0].toObject());
   1414  JSObject* promise = js::PromiseResolve(cx, constructor, args[1]);
   1415  if (!promise) {
   1416    return false;
   1417  }
   1418 
   1419  args.rval().setObject(*promise);
   1420  return true;
   1421 }
   1422 
   1423 static bool intrinsic_CopyDataPropertiesOrGetOwnKeys(JSContext* cx,
   1424                                                     unsigned argc, Value* vp) {
   1425  CallArgs args = CallArgsFromVp(argc, vp);
   1426  MOZ_ASSERT(args.length() == 3);
   1427  MOZ_ASSERT(args[0].isObject());
   1428  MOZ_ASSERT(args[1].isObject());
   1429  MOZ_ASSERT(args[2].isObjectOrNull());
   1430 
   1431  RootedObject target(cx, &args[0].toObject());
   1432  RootedObject from(cx, &args[1].toObject());
   1433  RootedObject excludedItems(cx, args[2].toObjectOrNull());
   1434 
   1435  if (from->is<NativeObject>() && target->is<PlainObject>() &&
   1436      (!excludedItems || excludedItems->is<PlainObject>())) {
   1437    bool optimized;
   1438    if (!CopyDataPropertiesNative(
   1439            cx, target.as<PlainObject>(), from.as<NativeObject>(),
   1440            (excludedItems ? excludedItems.as<PlainObject>() : nullptr),
   1441            &optimized)) {
   1442      return false;
   1443    }
   1444 
   1445    if (optimized) {
   1446      args.rval().setNull();
   1447      return true;
   1448    }
   1449  }
   1450 
   1451  return GetOwnPropertyKeys(
   1452      cx, from, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, args.rval());
   1453 }
   1454 
   1455 static bool intrinsic_NewWrapForValidIterator(JSContext* cx, unsigned argc,
   1456                                              Value* vp) {
   1457  CallArgs args = CallArgsFromVp(argc, vp);
   1458  MOZ_ASSERT(args.length() == 0);
   1459 
   1460  JSObject* obj = NewWrapForValidIterator(cx);
   1461  if (!obj) {
   1462    return false;
   1463  }
   1464 
   1465  args.rval().setObject(*obj);
   1466  return true;
   1467 }
   1468 
   1469 static bool intrinsic_NewIteratorHelper(JSContext* cx, unsigned argc,
   1470                                        Value* vp) {
   1471  CallArgs args = CallArgsFromVp(argc, vp);
   1472  MOZ_ASSERT(args.length() == 0);
   1473 
   1474  JSObject* obj = NewIteratorHelper(cx);
   1475  if (!obj) {
   1476    return false;
   1477  }
   1478 
   1479  args.rval().setObject(*obj);
   1480  return true;
   1481 }
   1482 
   1483 static bool intrinsic_NewAsyncIteratorHelper(JSContext* cx, unsigned argc,
   1484                                             Value* vp) {
   1485  CallArgs args = CallArgsFromVp(argc, vp);
   1486  MOZ_ASSERT(args.length() == 0);
   1487 
   1488  JSObject* obj = NewAsyncIteratorHelper(cx);
   1489  if (!obj) {
   1490    return false;
   1491  }
   1492 
   1493  args.rval().setObject(*obj);
   1494  return true;
   1495 }
   1496 
   1497 #ifdef NIGHTLY_BUILD
   1498 static bool intrinsic_NewIteratorRange(JSContext* cx, unsigned argc,
   1499                                       Value* vp) {
   1500  CallArgs args = CallArgsFromVp(argc, vp);
   1501  MOZ_ASSERT(args.length() == 0);
   1502 
   1503  JSObject* obj = NewIteratorRange(cx);
   1504  if (!obj) {
   1505    return false;
   1506  }
   1507 
   1508  args.rval().setObject(*obj);
   1509  return true;
   1510 }
   1511 #endif
   1512 
   1513 static JSObject* NewIteratorRecord(JSContext* cx, HandleObject iterator,
   1514                                   HandleValue nextMethod) {
   1515  gc::AllocKind allocKind = gc::GetGCObjectKind(3);
   1516  Rooted<PlainObject*> obj(
   1517      cx, NewPlainObjectWithProtoAndAllocKind(cx, nullptr, allocKind));
   1518  if (!obj) {
   1519    return nullptr;
   1520  }
   1521 
   1522  RootedId propid(cx, NameToId(cx->names().iterator));
   1523  RootedValue value(cx, ObjectValue(*iterator));
   1524  if (!NativeDefineDataProperty(cx, obj, propid, value, JSPROP_ENUMERATE)) {
   1525    return nullptr;
   1526  }
   1527 
   1528  propid = NameToId(cx->names().nextMethod);
   1529  value.set(nextMethod);
   1530  if (!NativeDefineDataProperty(cx, obj, propid, value, JSPROP_ENUMERATE)) {
   1531    return nullptr;
   1532  }
   1533 
   1534  propid = NameToId(cx->names().done);
   1535  value.setBoolean(false);
   1536  if (!NativeDefineDataProperty(cx, obj, propid, value, JSPROP_ENUMERATE)) {
   1537    return nullptr;
   1538  }
   1539 
   1540  return obj;
   1541 }
   1542 
   1543 static bool intrinsic_CreateAsyncFromSyncIterator(JSContext* cx, unsigned argc,
   1544                                                  Value* vp) {
   1545  CallArgs args = CallArgsFromVp(argc, vp);
   1546  MOZ_ASSERT(args.length() == 2);
   1547 
   1548  RootedObject iterator(cx, &args[0].toObject());
   1549  RootedObject asyncIterator(
   1550      cx, CreateAsyncFromSyncIterator(cx, iterator, args[1]));
   1551  if (!asyncIterator) {
   1552    return false;
   1553  }
   1554 
   1555  RootedValue nextMethod(cx);
   1556  if (!GetProperty(cx, asyncIterator, asyncIterator, cx->names().next,
   1557                   &nextMethod)) {
   1558    return false;
   1559  }
   1560 
   1561  RootedObject iteratorRecord(cx,
   1562                              NewIteratorRecord(cx, asyncIterator, nextMethod));
   1563  if (!iteratorRecord) {
   1564    return false;
   1565  }
   1566 
   1567  args.rval().setObject(*iteratorRecord);
   1568  return true;
   1569 }
   1570 
   1571 static bool intrinsic_NoPrivateGetter(JSContext* cx, unsigned argc, Value* vp) {
   1572  CallArgs args = CallArgsFromVp(argc, vp);
   1573  MOZ_ASSERT(args.length() == 0);
   1574 
   1575  JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
   1576                            JSMSG_PRIVATE_SETTER_ONLY);
   1577 
   1578  args.rval().setUndefined();
   1579  return false;
   1580 }
   1581 
   1582 static bool intrinsic_newList(JSContext* cx, unsigned argc, js::Value* vp) {
   1583  CallArgs args = CallArgsFromVp(argc, vp);
   1584  MOZ_ASSERT(args.length() == 0);
   1585 
   1586  ArrayObject* list = NewArrayWithNullProto(cx);
   1587  if (!list) {
   1588    return false;
   1589  }
   1590 
   1591  args.rval().setObject(*list);
   1592  return true;
   1593 }
   1594 
   1595 static bool intrinsic_CanBeHeldWeakly(JSContext* cx, unsigned argc, Value* vp) {
   1596  CallArgs args = CallArgsFromVp(argc, vp);
   1597  MOZ_ASSERT(args.length() == 1);
   1598 
   1599  args.rval().setBoolean(CanBeHeldWeakly(args[0]));
   1600  return true;
   1601 }
   1602 
   1603 static const JSFunctionSpec intrinsic_functions[] = {
   1604    // Intrinsic helper functions
   1605    JS_INLINABLE_FN("ArrayIteratorPrototypeOptimizable",
   1606                    intrinsic_ArrayIteratorPrototypeOptimizable, 0, 0,
   1607                    IntrinsicArrayIteratorPrototypeOptimizable),
   1608    JS_FN("AssertionFailed", intrinsic_AssertionFailed, 1, 0),
   1609    JS_FN("CallArrayIteratorMethodIfWrapped",
   1610          CallNonGenericSelfhostedMethod<Is<ArrayIteratorObject>>, 2, 0),
   1611 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1612    JS_FN("CallAsyncDisposableStackMethodIfWrapped",
   1613          CallNonGenericSelfhostedMethod<Is<AsyncDisposableStackObject>>, 2, 0),
   1614 #endif
   1615    JS_FN("CallAsyncIteratorHelperMethodIfWrapped",
   1616          CallNonGenericSelfhostedMethod<Is<AsyncIteratorHelperObject>>, 2, 0),
   1617 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1618    JS_FN("CallDisposableStackMethodIfWrapped",
   1619          CallNonGenericSelfhostedMethod<Is<DisposableStackObject>>, 2, 0),
   1620 #endif
   1621    JS_FN("CallGeneratorMethodIfWrapped",
   1622          CallNonGenericSelfhostedMethod<Is<GeneratorObject>>, 2, 0),
   1623    JS_FN("CallIteratorHelperMethodIfWrapped",
   1624          CallNonGenericSelfhostedMethod<Is<IteratorHelperObject>>, 2, 0),
   1625 #ifdef NIGHTLY_BUILD
   1626    JS_FN("CallIteratorRangeMethodIfWrapped",
   1627          CallNonGenericSelfhostedMethod<Is<IteratorRangeObject>>, 2, 0),
   1628 #endif
   1629    JS_FN("CallMapIteratorMethodIfWrapped",
   1630          CallNonGenericSelfhostedMethod<Is<MapIteratorObject>>, 2, 0),
   1631    JS_FN("CallMapMethodIfWrapped",
   1632          CallNonGenericSelfhostedMethod<Is<MapObject>>, 2, 0),
   1633    JS_FN("CallRegExpMethodIfWrapped",
   1634          CallNonGenericSelfhostedMethod<Is<RegExpObject>>, 2, 0),
   1635    JS_FN("CallRegExpStringIteratorMethodIfWrapped",
   1636          CallNonGenericSelfhostedMethod<Is<RegExpStringIteratorObject>>, 2, 0),
   1637    JS_FN("CallSetIteratorMethodIfWrapped",
   1638          CallNonGenericSelfhostedMethod<Is<SetIteratorObject>>, 2, 0),
   1639    JS_FN("CallSetMethodIfWrapped",
   1640          CallNonGenericSelfhostedMethod<Is<SetObject>>, 2, 0),
   1641    JS_FN("CallStringIteratorMethodIfWrapped",
   1642          CallNonGenericSelfhostedMethod<Is<StringIteratorObject>>, 2, 0),
   1643    JS_FN("CallTypedArrayMethodIfWrapped",
   1644          CallNonGenericSelfhostedMethod<Is<TypedArrayObject>>, 2, 0),
   1645    JS_FN("CallWeakMapMethodIfWrapped",
   1646          CallNonGenericSelfhostedMethod<Is<WeakMapObject>>, 2, 0),
   1647    JS_FN("CallWrapForValidIteratorMethodIfWrapped",
   1648          CallNonGenericSelfhostedMethod<Is<WrapForValidIteratorObject>>, 2, 0),
   1649    JS_FN("CanBeHeldWeakly", intrinsic_CanBeHeldWeakly, 1, 0),
   1650    JS_INLINABLE_FN("CanOptimizeArraySpecies",
   1651                    intrinsic_CanOptimizeArraySpecies, 1, 0,
   1652                    IntrinsicCanOptimizeArraySpecies),
   1653    JS_FN("ConstructFunction", intrinsic_ConstructFunction, 2, 0),
   1654    JS_FN("ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1, 0),
   1655    JS_FN("CopyDataPropertiesOrGetOwnKeys",
   1656          intrinsic_CopyDataPropertiesOrGetOwnKeys, 3, 0),
   1657    JS_FN("CreateAsyncFromSyncIterator", intrinsic_CreateAsyncFromSyncIterator,
   1658          2, 0),
   1659    JS_FN("CreateMapIterationResultPair",
   1660          intrinsic_CreateMapIterationResultPair, 0, 0),
   1661    JS_FN("CreateSetIterationResult", intrinsic_CreateSetIterationResult, 0, 0),
   1662 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1663    JS_FN("CreateSuppressedError", intrinsic_CreateSuppressedError, 2, 0),
   1664 #endif
   1665    JS_FN("DecompileArg", intrinsic_DecompileArg, 2, 0),
   1666    JS_FN("DefineDataProperty", intrinsic_DefineDataProperty, 4, 0),
   1667    JS_FN("DefineProperty", intrinsic_DefineProperty, 6, 0),
   1668    JS_FN("DumpMessage", intrinsic_DumpMessage, 1, 0),
   1669    JS_FN("FlatStringMatch", FlatStringMatch, 2, 0),
   1670    JS_FN("FlatStringSearch", FlatStringSearch, 2, 0),
   1671    JS_FN("GeneratorIsRunning", intrinsic_GeneratorIsRunning, 1, 0),
   1672    JS_FN("GeneratorObjectIsClosed", intrinsic_GeneratorObjectIsClosed, 1, 0),
   1673    JS_FN("GeneratorSetClosed", intrinsic_GeneratorSetClosed, 1, 0),
   1674    JS_FN("GetElemBaseForLambda", intrinsic_GetElemBaseForLambda, 1, 0),
   1675    JS_INLINABLE_FN("GetFirstDollarIndex", GetFirstDollarIndex, 1, 0,
   1676                    GetFirstDollarIndex),
   1677    JS_INLINABLE_FN("GetNextMapEntryForIterator",
   1678                    intrinsic_GetNextMapEntryForIterator, 2, 0,
   1679                    IntrinsicGetNextMapEntryForIterator),
   1680    JS_INLINABLE_FN("GetNextSetEntryForIterator",
   1681                    intrinsic_GetNextSetEntryForIterator, 2, 0,
   1682                    IntrinsicGetNextSetEntryForIterator),
   1683    JS_FN("GetOwnPropertyDescriptorToArray", GetOwnPropertyDescriptorToArray, 2,
   1684          0),
   1685    JS_FN("GetStringDataProperty", intrinsic_GetStringDataProperty, 2, 0),
   1686    JS_INLINABLE_FN("GuardToArrayBuffer",
   1687                    intrinsic_GuardToBuiltin<ArrayBufferObject>, 1, 0,
   1688                    IntrinsicGuardToArrayBuffer),
   1689    JS_INLINABLE_FN("GuardToArrayIterator",
   1690                    intrinsic_GuardToBuiltin<ArrayIteratorObject>, 1, 0,
   1691                    IntrinsicGuardToArrayIterator),
   1692 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1693    JS_INLINABLE_FN("GuardToAsyncDisposableStackHelper",
   1694                    intrinsic_GuardToBuiltin<AsyncDisposableStackObject>, 1, 0,
   1695                    IntrinsicGuardToAsyncDisposableStack),
   1696 #endif
   1697    JS_INLINABLE_FN("GuardToAsyncIteratorHelper",
   1698                    intrinsic_GuardToBuiltin<AsyncIteratorHelperObject>, 1, 0,
   1699                    IntrinsicGuardToAsyncIteratorHelper),
   1700 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
   1701    JS_INLINABLE_FN("GuardToDisposableStackHelper",
   1702                    intrinsic_GuardToBuiltin<DisposableStackObject>, 1, 0,
   1703                    IntrinsicGuardToDisposableStack),
   1704 #endif
   1705    JS_INLINABLE_FN("GuardToIteratorHelper",
   1706                    intrinsic_GuardToBuiltin<IteratorHelperObject>, 1, 0,
   1707                    IntrinsicGuardToIteratorHelper),
   1708 #ifdef NIGHTLY_BUILD
   1709    JS_INLINABLE_FN("GuardToIteratorRange",
   1710                    intrinsic_GuardToBuiltin<IteratorRangeObject>, 1, 0,
   1711                    IntrinsicGuardToIteratorRange),
   1712 #endif
   1713    JS_INLINABLE_FN("GuardToMapIterator",
   1714                    intrinsic_GuardToBuiltin<MapIteratorObject>, 1, 0,
   1715                    IntrinsicGuardToMapIterator),
   1716    JS_INLINABLE_FN("GuardToMapObject", intrinsic_GuardToBuiltin<MapObject>, 1,
   1717                    0, IntrinsicGuardToMapObject),
   1718    JS_INLINABLE_FN("GuardToRegExpStringIterator",
   1719                    intrinsic_GuardToBuiltin<RegExpStringIteratorObject>, 1, 0,
   1720                    IntrinsicGuardToRegExpStringIterator),
   1721    JS_INLINABLE_FN("GuardToSetIterator",
   1722                    intrinsic_GuardToBuiltin<SetIteratorObject>, 1, 0,
   1723                    IntrinsicGuardToSetIterator),
   1724    JS_INLINABLE_FN("GuardToSetObject", intrinsic_GuardToBuiltin<SetObject>, 1,
   1725                    0, IntrinsicGuardToSetObject),
   1726    JS_INLINABLE_FN("GuardToSharedArrayBuffer",
   1727                    intrinsic_GuardToBuiltin<SharedArrayBufferObject>, 1, 0,
   1728                    IntrinsicGuardToSharedArrayBuffer),
   1729    JS_INLINABLE_FN("GuardToStringIterator",
   1730                    intrinsic_GuardToBuiltin<StringIteratorObject>, 1, 0,
   1731                    IntrinsicGuardToStringIterator),
   1732    JS_FN("GuardToWeakMapObject", intrinsic_GuardToBuiltin<WeakMapObject>, 1,
   1733          0),
   1734    JS_INLINABLE_FN("GuardToWrapForValidIterator",
   1735                    intrinsic_GuardToBuiltin<WrapForValidIteratorObject>, 1, 0,
   1736                    IntrinsicGuardToWrapForValidIterator),
   1737    JS_FN("IntrinsicAsyncGeneratorNext", AsyncGeneratorNext, 1, 0),
   1738    JS_FN("IntrinsicAsyncGeneratorReturn", AsyncGeneratorReturn, 1, 0),
   1739    JS_FN("IntrinsicAsyncGeneratorThrow", AsyncGeneratorThrow, 1, 0),
   1740    JS_INLINABLE_FN("IsArray", intrinsic_IsArray, 1, 0, ArrayIsArray),
   1741    JS_FN("IsAsyncFunctionGeneratorObject",
   1742          intrinsic_IsInstanceOfBuiltin<AsyncFunctionGeneratorObject>, 1, 0),
   1743    JS_FN("IsAsyncGeneratorObject",
   1744          intrinsic_IsInstanceOfBuiltin<AsyncGeneratorObject>, 1, 0),
   1745    JS_INLINABLE_FN("IsCallable", intrinsic_IsCallable, 1, 0,
   1746                    IntrinsicIsCallable),
   1747    JS_INLINABLE_FN("IsConstructing", intrinsic_IsConstructing, 0, 0,
   1748                    IntrinsicIsConstructing),
   1749    JS_INLINABLE_FN("IsConstructor", intrinsic_IsConstructor, 1, 0,
   1750                    IntrinsicIsConstructor),
   1751    JS_INLINABLE_FN("IsCrossRealmArrayConstructor",
   1752                    intrinsic_IsCrossRealmArrayConstructor, 1, 0,
   1753                    IntrinsicIsCrossRealmArrayConstructor),
   1754    JS_FN("IsGeneratorObject", intrinsic_IsInstanceOfBuiltin<GeneratorObject>,
   1755          1, 0),
   1756    JS_INLINABLE_FN("IsObject", intrinsic_IsObject, 1, 0, IntrinsicIsObject),
   1757    JS_INLINABLE_FN("IsOptimizableRegExpObject", IsOptimizableRegExpObject, 1,
   1758                    0, IsOptimizableRegExpObject),
   1759    JS_INLINABLE_FN("IsPackedArray", intrinsic_IsPackedArray, 1, 0,
   1760                    IntrinsicIsPackedArray),
   1761    JS_INLINABLE_FN("IsPossiblyWrappedRegExpObject",
   1762                    intrinsic_IsPossiblyWrappedInstanceOfBuiltin<RegExpObject>,
   1763                    1, 0, IsPossiblyWrappedRegExpObject),
   1764    JS_INLINABLE_FN(
   1765        "IsPossiblyWrappedTypedArray",
   1766        intrinsic_IsPossiblyWrappedInstanceOfBuiltin<TypedArrayObject>, 1, 0,
   1767        IntrinsicIsPossiblyWrappedTypedArray),
   1768    JS_INLINABLE_FN("IsRegExpObject",
   1769                    intrinsic_IsInstanceOfBuiltin<RegExpObject>, 1, 0,
   1770                    IsRegExpObject),
   1771    JS_INLINABLE_FN("IsRegExpPrototypeOptimizable",
   1772                    IsRegExpPrototypeOptimizable, 0, 0,
   1773                    IsRegExpPrototypeOptimizable),
   1774    JS_INLINABLE_FN("IsSuspendedGenerator", intrinsic_IsSuspendedGenerator, 1,
   1775                    0, IntrinsicIsSuspendedGenerator),
   1776    JS_INLINABLE_FN("IsTypedArray",
   1777                    intrinsic_IsInstanceOfBuiltin<TypedArrayObject>, 1, 0,
   1778                    IntrinsicIsTypedArray),
   1779    JS_INLINABLE_FN("IsTypedArrayConstructor",
   1780                    intrinsic_IsTypedArrayConstructor, 1, 0,
   1781                    IntrinsicIsTypedArrayConstructor),
   1782    JS_INLINABLE_FN("NewArrayIterator", intrinsic_NewArrayIterator, 0, 0,
   1783                    IntrinsicNewArrayIterator),
   1784    JS_FN("NewAsyncIteratorHelper", intrinsic_NewAsyncIteratorHelper, 0, 0),
   1785    JS_FN("NewIteratorHelper", intrinsic_NewIteratorHelper, 0, 0),
   1786 #ifdef NIGHTLY_BUILD
   1787    JS_FN("NewIteratorRange", intrinsic_NewIteratorRange, 0, 0),
   1788 #endif
   1789    JS_INLINABLE_FN("NewRegExpStringIterator",
   1790                    intrinsic_NewRegExpStringIterator, 0, 0,
   1791                    IntrinsicNewRegExpStringIterator),
   1792    JS_INLINABLE_FN("NewStringIterator", intrinsic_NewStringIterator, 0, 0,
   1793                    IntrinsicNewStringIterator),
   1794    JS_FN("NewWrapForValidIterator", intrinsic_NewWrapForValidIterator, 0, 0),
   1795    JS_FN("NoPrivateGetter", intrinsic_NoPrivateGetter, 1, 0),
   1796    JS_FN("PossiblyWrappedTypedArrayHasDetachedBuffer",
   1797          intrinsic_PossiblyWrappedTypedArrayHasDetachedBuffer, 1, 0),
   1798    JS_FN("PossiblyWrappedTypedArrayHasImmutableBuffer",
   1799          intrinsic_PossiblyWrappedTypedArrayHasImmutableBuffer, 1, 0),
   1800    JS_INLINABLE_FN("PossiblyWrappedTypedArrayLength",
   1801                    intrinsic_PossiblyWrappedTypedArrayLength, 1, 0,
   1802                    IntrinsicPossiblyWrappedTypedArrayLength),
   1803    JS_FN("PromiseResolve", intrinsic_PromiseResolve, 2, 0),
   1804    JS_INLINABLE_FN("RegExpBuiltinExec", intrinsic_RegExpBuiltinExec<false>, 2,
   1805                    0, IntrinsicRegExpBuiltinExec),
   1806    JS_INLINABLE_FN("RegExpBuiltinExecForTest",
   1807                    intrinsic_RegExpBuiltinExec<true>, 2, 0,
   1808                    IntrinsicRegExpBuiltinExecForTest),
   1809    JS_FN("RegExpConstructRaw", regexp_construct_raw_flags, 2, 0),
   1810    JS_FN("RegExpCreate", intrinsic_RegExpCreate, 2, 0),
   1811    JS_INLINABLE_FN("RegExpExec", intrinsic_RegExpExec<false>, 2, 0,
   1812                    IntrinsicRegExpExec),
   1813    JS_INLINABLE_FN("RegExpExecForTest", intrinsic_RegExpExec<true>, 2, 0,
   1814                    IntrinsicRegExpExecForTest),
   1815    JS_FN("RegExpGetSubstitution", intrinsic_RegExpGetSubstitution, 5, 0),
   1816    JS_INLINABLE_FN("RegExpHasCaptureGroups", intrinsic_RegExpHasCaptureGroups,
   1817                    2, 0, RegExpHasCaptureGroups),
   1818    JS_INLINABLE_FN("RegExpMatcher", RegExpMatcher, 3, 0, RegExpMatcher),
   1819    JS_INLINABLE_FN("RegExpSearcher", RegExpSearcher, 3, 0, RegExpSearcher),
   1820    JS_INLINABLE_FN("RegExpSearcherLastLimit", RegExpSearcherLastLimit, 0, 0,
   1821                    RegExpSearcherLastLimit),
   1822    JS_FN("ReportWarning", intrinsic_ReportWarning, 4, 0),
   1823    JS_INLINABLE_FN("SameValue", js::obj_is, 2, 0, ObjectIs),
   1824    JS_FN("SetCopy", SetObject::copy, 1, 0),
   1825    JS_FN("StringReplaceAllString", intrinsic_StringReplaceAllString, 3, 0),
   1826    JS_INLINABLE_FN("StringReplaceString", intrinsic_StringReplaceString, 3, 0,
   1827                    IntrinsicStringReplaceString),
   1828    JS_INLINABLE_FN("StringSplitString", intrinsic_StringSplitString, 2, 0,
   1829                    IntrinsicStringSplitString),
   1830    JS_FN("StringSplitStringLimit", intrinsic_StringSplitStringLimit, 3, 0),
   1831    JS_INLINABLE_FN("SubstringKernel", intrinsic_SubstringKernel, 3, 0,
   1832                    IntrinsicSubstringKernel),
   1833    JS_FN("ThrowAggregateError", intrinsic_ThrowAggregateError, 4, 0),
   1834    JS_FN("ThrowInternalError", intrinsic_ThrowInternalError, 4, 0),
   1835    JS_FN("ThrowRangeError", intrinsic_ThrowRangeError, 4, 0),
   1836    JS_FN("ThrowTypeError", intrinsic_ThrowTypeError, 4, 0),
   1837    JS_INLINABLE_FN("ToInteger", intrinsic_ToInteger, 1, 0, IntrinsicToInteger),
   1838    JS_INLINABLE_FN("ToLength", intrinsic_ToLength, 1, 0, IntrinsicToLength),
   1839    JS_INLINABLE_FN("ToObject", intrinsic_ToObject, 1, 0, IntrinsicToObject),
   1840    JS_FN("ToPropertyKey", intrinsic_ToPropertyKey, 1, 0),
   1841    JS_FN("ToSource", intrinsic_ToSource, 1, 0),
   1842    JS_FN("TypedArrayInitFromPackedArray",
   1843          intrinsic_TypedArrayInitFromPackedArray, 2, 0),
   1844    JS_INLINABLE_FN("TypedArrayLength", intrinsic_TypedArrayLength, 1, 0,
   1845                    IntrinsicTypedArrayLength),
   1846    JS_INLINABLE_FN("UnsafeGetInt32FromReservedSlot",
   1847                    intrinsic_UnsafeGetInt32FromReservedSlot, 2, 0,
   1848                    IntrinsicUnsafeGetInt32FromReservedSlot),
   1849    JS_INLINABLE_FN("UnsafeGetObjectFromReservedSlot",
   1850                    intrinsic_UnsafeGetObjectFromReservedSlot, 2, 0,
   1851                    IntrinsicUnsafeGetObjectFromReservedSlot),
   1852    JS_INLINABLE_FN("UnsafeGetReservedSlot", intrinsic_UnsafeGetReservedSlot, 2,
   1853                    0, IntrinsicUnsafeGetReservedSlot),
   1854    JS_INLINABLE_FN("UnsafeGetStringFromReservedSlot",
   1855                    intrinsic_UnsafeGetStringFromReservedSlot, 2, 0,
   1856                    IntrinsicUnsafeGetStringFromReservedSlot),
   1857    JS_INLINABLE_FN("UnsafeSetReservedSlot", intrinsic_UnsafeSetReservedSlot, 3,
   1858                    0, IntrinsicUnsafeSetReservedSlot),
   1859 
   1860 // Intrinsics and standard functions used by Intl API implementation.
   1861 #ifdef JS_HAS_INTL_API
   1862    JS_FN("intl_BestAvailableLocale", intl_BestAvailableLocale, 3, 0),
   1863    JS_FN("intl_CallCollatorMethodIfWrapped",
   1864          CallNonGenericSelfhostedMethod<Is<CollatorObject>>, 2, 0),
   1865    JS_FN("intl_CallDateTimeFormatMethodIfWrapped",
   1866          CallNonGenericSelfhostedMethod<Is<DateTimeFormatObject>>, 2, 0),
   1867    JS_FN("intl_CallDisplayNamesMethodIfWrapped",
   1868          CallNonGenericSelfhostedMethod<Is<DisplayNamesObject>>, 2, 0),
   1869    JS_FN("intl_CallDurationFormatMethodIfWrapped",
   1870          CallNonGenericSelfhostedMethod<Is<DurationFormatObject>>, 2, 0),
   1871    JS_FN("intl_CallListFormatMethodIfWrapped",
   1872          CallNonGenericSelfhostedMethod<Is<ListFormatObject>>, 2, 0),
   1873    JS_FN("intl_CallNumberFormatMethodIfWrapped",
   1874          CallNonGenericSelfhostedMethod<Is<NumberFormatObject>>, 2, 0),
   1875    JS_FN("intl_CallPluralRulesMethodIfWrapped",
   1876          CallNonGenericSelfhostedMethod<Is<PluralRulesObject>>, 2, 0),
   1877    JS_FN("intl_CallRelativeTimeFormatMethodIfWrapped",
   1878          CallNonGenericSelfhostedMethod<Is<RelativeTimeFormatObject>>, 2, 0),
   1879    JS_FN("intl_CallSegmentIteratorMethodIfWrapped",
   1880          CallNonGenericSelfhostedMethod<Is<SegmentIteratorObject>>, 2, 0),
   1881    JS_FN("intl_CallSegmenterMethodIfWrapped",
   1882          CallNonGenericSelfhostedMethod<Is<SegmenterObject>>, 2, 0),
   1883    JS_FN("intl_CallSegmentsMethodIfWrapped",
   1884          CallNonGenericSelfhostedMethod<Is<SegmentsObject>>, 2, 0),
   1885    JS_FN("intl_CompareStrings", intl_CompareStrings, 3, 0),
   1886    JS_FN("intl_ComputeDisplayName", intl_ComputeDisplayName, 6, 0),
   1887    JS_FN("intl_CreateSegmentIterator", intl_CreateSegmentIterator, 1, 0),
   1888    JS_FN("intl_CreateSegmentsObject", intl_CreateSegmentsObject, 2, 0),
   1889    JS_FN("intl_DefaultLocale", intrinsic_DefaultLocale, 0, 0),
   1890    JS_FN("intl_DefaultTimeZone", intrinsic_DefaultTimeZone, 0, 0),
   1891    JS_FN("intl_FindNextSegmentBoundaries", intl_FindNextSegmentBoundaries, 1,
   1892          0),
   1893    JS_FN("intl_FindSegmentBoundaries", intl_FindSegmentBoundaries, 2, 0),
   1894    JS_FN("intl_FormatDateTime", intl_FormatDateTime, 2, 0),
   1895    JS_FN("intl_FormatDateTimeRange", intl_FormatDateTimeRange, 4, 0),
   1896    JS_FN("intl_FormatList", intl_FormatList, 3, 0),
   1897    JS_FN("intl_FormatNumber", intl_FormatNumber, 3, 0),
   1898    JS_FN("intl_FormatNumberRange", intl_FormatNumberRange, 4, 0),
   1899    JS_FN("intl_FormatRelativeTime", intl_FormatRelativeTime, 4, 0),
   1900    JS_FN("intl_GetCalendarInfo", intl_GetCalendarInfo, 1, 0),
   1901    JS_FN("intl_GetPluralCategories", intl_GetPluralCategories, 1, 0),
   1902    JS_INLINABLE_FN("intl_GuardToCollator",
   1903                    intrinsic_GuardToBuiltin<CollatorObject>, 1, 0,
   1904                    IntlGuardToCollator),
   1905    JS_INLINABLE_FN("intl_GuardToDateTimeFormat",
   1906                    intrinsic_GuardToBuiltin<DateTimeFormatObject>, 1, 0,
   1907                    IntlGuardToDateTimeFormat),
   1908    JS_INLINABLE_FN("intl_GuardToDisplayNames",
   1909                    intrinsic_GuardToBuiltin<DisplayNamesObject>, 1, 0,
   1910                    IntlGuardToDisplayNames),
   1911    JS_INLINABLE_FN("intl_GuardToDurationFormat",
   1912                    intrinsic_GuardToBuiltin<DurationFormatObject>, 1, 0,
   1913                    IntlGuardToDurationFormat),
   1914    JS_INLINABLE_FN("intl_GuardToListFormat",
   1915                    intrinsic_GuardToBuiltin<ListFormatObject>, 1, 0,
   1916                    IntlGuardToListFormat),
   1917    JS_INLINABLE_FN("intl_GuardToNumberFormat",
   1918                    intrinsic_GuardToBuiltin<NumberFormatObject>, 1, 0,
   1919                    IntlGuardToNumberFormat),
   1920    JS_INLINABLE_FN("intl_GuardToPluralRules",
   1921                    intrinsic_GuardToBuiltin<PluralRulesObject>, 1, 0,
   1922                    IntlGuardToPluralRules),
   1923    JS_INLINABLE_FN("intl_GuardToRelativeTimeFormat",
   1924                    intrinsic_GuardToBuiltin<RelativeTimeFormatObject>, 1, 0,
   1925                    IntlGuardToRelativeTimeFormat),
   1926    JS_INLINABLE_FN("intl_GuardToSegmentIterator",
   1927                    intrinsic_GuardToBuiltin<SegmentIteratorObject>, 1, 0,
   1928                    IntlGuardToSegmentIterator),
   1929    JS_INLINABLE_FN("intl_GuardToSegmenter",
   1930                    intrinsic_GuardToBuiltin<SegmenterObject>, 1, 0,
   1931                    IntlGuardToSegmenter),
   1932    JS_INLINABLE_FN("intl_GuardToSegments",
   1933                    intrinsic_GuardToBuiltin<SegmentsObject>, 1, 0,
   1934                    IntlGuardToSegments),
   1935    JS_FN("intl_IsWrappedDateTimeFormat",
   1936          intrinsic_IsWrappedInstanceOfBuiltin<DateTimeFormatObject>, 1, 0),
   1937    JS_FN("intl_IsWrappedNumberFormat",
   1938          intrinsic_IsWrappedInstanceOfBuiltin<NumberFormatObject>, 1, 0),
   1939    JS_FN("intl_NumberFormat", intl_NumberFormat, 2, 0),
   1940    JS_FN("intl_SelectPluralRule", intl_SelectPluralRule, 2, 0),
   1941    JS_FN("intl_SelectPluralRuleRange", intl_SelectPluralRuleRange, 3, 0),
   1942    JS_FN("intl_TryValidateAndCanonicalizeLanguageTag",
   1943          intl_TryValidateAndCanonicalizeLanguageTag, 1, 0),
   1944    JS_FN("intl_ValidateAndCanonicalizeLanguageTag",
   1945          intl_ValidateAndCanonicalizeLanguageTag, 2, 0),
   1946    JS_FN("intl_ValidateAndCanonicalizeTimeZone",
   1947          intl_ValidateAndCanonicalizeTimeZone, 1, 0),
   1948    JS_FN("intl_ValidateAndCanonicalizeUnicodeExtensionType",
   1949          intl_ValidateAndCanonicalizeUnicodeExtensionType, 3, 0),
   1950    JS_FN("intl_availableCalendars", intl_availableCalendars, 1, 0),
   1951    JS_FN("intl_availableCollations", intl_availableCollations, 1, 0),
   1952 #  if DEBUG || MOZ_SYSTEM_ICU
   1953    JS_FN("intl_availableMeasurementUnits", intl_availableMeasurementUnits, 0,
   1954          0),
   1955 #  endif
   1956    JS_FN("intl_defaultCalendar", intl_defaultCalendar, 1, 0),
   1957    JS_FN("intl_isIgnorePunctuation", intl_isIgnorePunctuation, 1, 0),
   1958    JS_FN("intl_isUpperCaseFirst", intl_isUpperCaseFirst, 1, 0),
   1959    JS_FN("intl_numberingSystem", intl_numberingSystem, 1, 0),
   1960    JS_FN("intl_resolveDateTimeFormatComponents",
   1961          intl_resolveDateTimeFormatComponents, 3, 0),
   1962 #endif  // JS_HAS_INTL_API
   1963 
   1964    // Standard builtins used by self-hosting.
   1965    JS_FN("new_List", intrinsic_newList, 0, 0),
   1966    JS_INLINABLE_FN("std_Array", array_construct, 1, 0, Array),
   1967    JS_FN("std_Array_includes", array_includes, 1, 0),
   1968    JS_FN("std_Array_indexOf", array_indexOf, 1, 0),
   1969    JS_FN("std_Array_lastIndexOf", array_lastIndexOf, 1, 0),
   1970    JS_INLINABLE_FN("std_Array_pop", array_pop, 0, 0, ArrayPop),
   1971    JS_TRAMPOLINE_FN("std_Array_sort", array_sort, 1, 0, ArraySort),
   1972    JS_FN("std_Function_apply", fun_apply, 2, 0),
   1973    JS_FN("std_Map_entries", MapObject::entries, 0, 0),
   1974    JS_INLINABLE_FN("std_Map_get", MapObject::get, 1, 0, MapGet),
   1975    JS_INLINABLE_FN("std_Map_has", MapObject::has, 1, 0, MapHas),
   1976    JS_INLINABLE_FN("std_Map_set", MapObject::set, 2, 0, MapSet),
   1977    JS_INLINABLE_FN("std_Math_abs", math_abs, 1, 0, MathAbs),
   1978    JS_INLINABLE_FN("std_Math_floor", math_floor, 1, 0, MathFloor),
   1979    JS_INLINABLE_FN("std_Math_max", math_max, 2, 0, MathMax),
   1980    JS_INLINABLE_FN("std_Math_min", math_min, 2, 0, MathMin),
   1981    JS_INLINABLE_FN("std_Math_trunc", math_trunc, 1, 0, MathTrunc),
   1982    JS_INLINABLE_FN("std_Object_create", obj_create, 2, 0, ObjectCreate),
   1983    JS_INLINABLE_FN("std_Object_isPrototypeOf", obj_isPrototypeOf, 1, 0,
   1984                    ObjectIsPrototypeOf),
   1985    JS_FN("std_Object_propertyIsEnumerable", obj_propertyIsEnumerable, 1, 0),
   1986    JS_FN("std_Object_setProto", obj_setProto, 1, 0),
   1987    JS_INLINABLE_FN("std_Object_toString", obj_toString, 0, 0, ObjectToString),
   1988    JS_INLINABLE_FN("std_Reflect_getPrototypeOf", Reflect_getPrototypeOf, 1, 0,
   1989                    ReflectGetPrototypeOf),
   1990    JS_FN("std_Reflect_isExtensible", Reflect_isExtensible, 1, 0),
   1991    JS_FN("std_Reflect_ownKeys", Reflect_ownKeys, 1, 0),
   1992    JS_INLINABLE_FN("std_Set_add", SetObject::add, 1, 0, SetAdd),
   1993    JS_INLINABLE_FN("std_Set_delete", SetObject::delete_, 1, 0, SetDelete),
   1994    JS_INLINABLE_FN("std_Set_has", SetObject::has, 1, 0, SetHas),
   1995    JS_INLINABLE_FN("std_Set_size", SetObject::size, 1, 0, SetSize),
   1996    JS_FN("std_Set_values", SetObject::values, 0, 0),
   1997    JS_INLINABLE_FN("std_String_charCodeAt", str_charCodeAt, 1, 0,
   1998                    StringCharCodeAt),
   1999    JS_INLINABLE_FN("std_String_codePointAt", str_codePointAt, 1, 0,
   2000                    StringCodePointAt),
   2001    JS_INLINABLE_FN("std_String_endsWith", str_endsWith, 1, 0, StringEndsWith),
   2002    JS_INLINABLE_FN("std_String_fromCharCode", str_fromCharCode, 1, 0,
   2003                    StringFromCharCode),
   2004    JS_INLINABLE_FN("std_String_fromCodePoint", str_fromCodePoint, 1, 0,
   2005                    StringFromCodePoint),
   2006    JS_INLINABLE_FN("std_String_includes", str_includes, 1, 0, StringIncludes),
   2007    JS_INLINABLE_FN("std_String_indexOf", str_indexOf, 1, 0, StringIndexOf),
   2008    JS_INLINABLE_FN("std_String_startsWith", str_startsWith, 1, 0,
   2009                    StringStartsWith),
   2010    JS_TRAMPOLINE_FN("std_TypedArray_sort", TypedArrayObject::sort, 1, 0,
   2011                     TypedArraySort),
   2012    JS_INLINABLE_FN("std_WeakMap_get", WeakMapObject::get, 1, 0, WeakMapGet),
   2013    JS_INLINABLE_FN("std_WeakMap_has", WeakMapObject::has, 1, 0, WeakMapHas),
   2014    JS_FN("std_WeakMap_set", WeakMapObject::set, 2, 0),
   2015 
   2016    JS_FS_END,
   2017 };
   2018 
   2019 #ifdef DEBUG
   2020 
   2021 static void CheckSelfHostedIntrinsics() {
   2022  // The `intrinsic_functions` list must be sorted so that we can use
   2023  // mozilla::BinarySearch to do lookups on demand.
   2024  const char* prev = "";
   2025  for (JSFunctionSpec spec : intrinsic_functions) {
   2026    if (spec.name.string()) {
   2027      MOZ_ASSERT(strcmp(prev, spec.name.string()) < 0,
   2028                 "Self-hosted intrinsics must be sorted");
   2029      prev = spec.name.string();
   2030    }
   2031  }
   2032 }
   2033 
   2034 class CheckTenuredTracer : public JS::CallbackTracer {
   2035  HashSet<gc::Cell*, DefaultHasher<gc::Cell*>, SystemAllocPolicy> visited;
   2036  Vector<JS::GCCellPtr, 0, SystemAllocPolicy> stack;
   2037 
   2038 public:
   2039  explicit CheckTenuredTracer(JSRuntime* rt) : JS::CallbackTracer(rt) {}
   2040  void check() {
   2041    while (!stack.empty()) {
   2042      JS::TraceChildren(this, stack.popCopy());
   2043    }
   2044  }
   2045  void onChild(JS::GCCellPtr thing, const char* name) override {
   2046    gc::Cell* cell = thing.asCell();
   2047    MOZ_RELEASE_ASSERT(cell->isTenured(), "Expected tenured cell");
   2048    if (!visited.has(cell)) {
   2049      if (!visited.put(cell) || !stack.append(thing)) {
   2050        // Ignore OOM. This can happen during fuzzing.
   2051        return;
   2052      }
   2053    }
   2054  }
   2055 };
   2056 
   2057 static void CheckSelfHostingDataIsTenured(JSRuntime* rt) {
   2058  // Check everything is tenured as we don't trace it when collecting the
   2059  // nursery.
   2060  CheckTenuredTracer trc(rt);
   2061  rt->traceSelfHostingStencil(&trc);
   2062  trc.check();
   2063 }
   2064 
   2065 #endif
   2066 
   2067 const JSFunctionSpec* js::FindIntrinsicSpec(js::PropertyName* name) {
   2068  size_t limit = std::size(intrinsic_functions) - 1;
   2069  MOZ_ASSERT(!intrinsic_functions[limit].name);
   2070 
   2071  MOZ_ASSERT(name->hasLatin1Chars());
   2072 
   2073  JS::AutoCheckCannotGC nogc;
   2074  const char* chars = reinterpret_cast<const char*>(name->latin1Chars(nogc));
   2075  size_t len = name->length();
   2076 
   2077  // NOTE: CheckSelfHostedIntrinsics checks that the intrinsic_functions list is
   2078  // sorted appropriately so that we can use binary search here.
   2079 
   2080  size_t loc = 0;
   2081  bool match = mozilla::BinarySearchIf(
   2082      intrinsic_functions, 0, limit,
   2083      [chars, len](const JSFunctionSpec& spec) {
   2084        // The spec string is null terminated but the `name` string is not, so
   2085        // compare chars up until the length of `name`. Since the `name` string
   2086        // does not contain any nulls, seeing the null terminator of the spec
   2087        // string will terminate the loop appropriately. A final comparison
   2088        // against null is needed to determine if the spec string has an extra
   2089        // suffix.
   2090        const char* spec_chars = spec.name.string();
   2091        for (size_t i = 0; i < len; ++i) {
   2092          if (auto cmp_result = int(chars[i]) - int(spec_chars[i])) {
   2093            return cmp_result;
   2094          }
   2095        }
   2096        return int('\0') - int(spec_chars[len]);
   2097      },
   2098      &loc);
   2099  if (match) {
   2100    return &intrinsic_functions[loc];
   2101  }
   2102  return nullptr;
   2103 }
   2104 
   2105 void js::FillSelfHostingCompileOptions(CompileOptions& options) {
   2106  /*
   2107   * In self-hosting mode, scripts use JSOp::GetIntrinsic instead of
   2108   * JSOp::GetName or JSOp::GetGName to access unbound variables.
   2109   * JSOp::GetIntrinsic does a name lookup on a special object, whose
   2110   * properties are filled in lazily upon first access for a given global.
   2111   *
   2112   * As that object is inaccessible to client code, the lookups are
   2113   * guaranteed to return the original objects, ensuring safe implementation
   2114   * of self-hosted builtins.
   2115   *
   2116   * Additionally, the special syntax callFunction(fun, receiver, ...args)
   2117   * is supported, for which bytecode is emitted that invokes |fun| with
   2118   * |receiver| as the this-object and ...args as the arguments.
   2119   */
   2120  options.setIntroductionType("self-hosted");
   2121  options.setFileAndLine("self-hosted", 1);
   2122  options.setSkipFilenameValidation(true);
   2123  options.setSelfHostingMode(true);
   2124  options.setForceFullParse();
   2125  options.setForceStrictMode();
   2126  options.setDiscardSource();
   2127  options.setIsRunOnce(true);
   2128  options.setNoScriptRval(true);
   2129 }
   2130 
   2131 // Report all errors and warnings to stderr because it is too early in the
   2132 // startup process for any other error reporting to be used, and we don't want
   2133 // errors in self-hosted code to be silently swallowed.
   2134 class MOZ_STACK_CLASS AutoPrintSelfHostingFrontendContext
   2135    : public FrontendContext {
   2136  JSContext* cx_;
   2137 
   2138 public:
   2139  explicit AutoPrintSelfHostingFrontendContext(JSContext* cx) : cx_(cx) {
   2140    setCurrentJSContext(cx_);
   2141  }
   2142  ~AutoPrintSelfHostingFrontendContext() {
   2143    // TODO: Remove this once JSContext is removed from frontend.
   2144    MaybePrintAndClearPendingException(cx_);
   2145 
   2146    if (hadOutOfMemory()) {
   2147      fprintf(stderr, "Out of memory\n");
   2148    }
   2149 
   2150    if (maybeError()) {
   2151      JS::PrintError(stderr, &*maybeError(), true);
   2152    }
   2153    for (CompileError& error : warnings()) {
   2154      JS::PrintError(stderr, &error, true);
   2155    }
   2156    if (hadOverRecursed()) {
   2157      fprintf(stderr, "Over recursed\n");
   2158    }
   2159    if (hadAllocationOverflow()) {
   2160      fprintf(stderr, "Allocation overflow\n");
   2161    }
   2162  }
   2163 };
   2164 
   2165 [[nodiscard]] static bool InitSelfHostingFromStencil(
   2166    JSContext* cx, frontend::CompilationAtomCache& atomCache,
   2167    const frontend::CompilationStencil& stencil) {
   2168  // Build the JSAtom -> ScriptIndexRange mapping and save on the runtime.
   2169  {
   2170    auto& scriptMap = cx->runtime()->selfHostScriptMap.ref();
   2171 
   2172    // We don't easily know the number of top-level functions, so use the total
   2173    // number of stencil functions instead. There is very little nesting of
   2174    // functions in self-hosted code so this is a good approximation.
   2175    size_t numSelfHostedScripts = stencil.scriptData.size();
   2176    if (!scriptMap.reserve(numSelfHostedScripts)) {
   2177      ReportOutOfMemory(cx);
   2178      return false;
   2179    }
   2180 
   2181    auto topLevelThings =
   2182        stencil.scriptData[frontend::CompilationStencil::TopLevelIndex]
   2183            .gcthings(stencil);
   2184 
   2185    // Iterate over the (named) top-level functions. We record the ScriptIndex
   2186    // as well as the ScriptIndex of the next top-level function. Scripts
   2187    // between these two indices are the inner functions of the first one. We
   2188    // only record named scripts here since they are what might be looked up.
   2189    Rooted<JSAtom*> prevAtom(cx);
   2190    frontend::ScriptIndex prevIndex;
   2191    for (frontend::TaggedScriptThingIndex thing : topLevelThings) {
   2192      if (!thing.isFunction()) {
   2193        continue;
   2194      }
   2195 
   2196      frontend::ScriptIndex index = thing.toFunction();
   2197      const auto& script = stencil.scriptData[index];
   2198 
   2199      if (prevAtom) {
   2200        frontend::ScriptIndexRange range{prevIndex, index};
   2201        scriptMap.putNewInfallible(prevAtom, range);
   2202      }
   2203 
   2204      prevAtom = script.functionAtom
   2205                     ? atomCache.getExistingAtomAt(cx, script.functionAtom)
   2206                     : nullptr;
   2207      prevIndex = index;
   2208    }
   2209    if (prevAtom) {
   2210      frontend::ScriptIndexRange range{
   2211          prevIndex, frontend::ScriptIndex(stencil.scriptData.size())};
   2212      scriptMap.putNewInfallible(prevAtom, range);
   2213    }
   2214 
   2215    // We over-estimated the capacity of `scriptMap`, so check that the estimate
   2216    // hasn't drifted too hasn't drifted too far since this was written. If this
   2217    // assert fails, we may need a new way to size the `scriptMap`.
   2218    MOZ_ASSERT(numSelfHostedScripts < (scriptMap.count() * 1.15));
   2219  }
   2220 
   2221 #ifdef DEBUG
   2222  // Check that the list of intrinsics is well-formed.
   2223  CheckSelfHostedIntrinsics();
   2224  CheckSelfHostingDataIsTenured(cx->runtime());
   2225 #endif
   2226 
   2227  return true;
   2228 }
   2229 
   2230 bool JSRuntime::initSelfHostingStencil(JSContext* cx,
   2231                                       JS::SelfHostedCache xdrCache,
   2232                                       JS::SelfHostedWriter xdrWriter) {
   2233  if (parentRuntime) {
   2234    MOZ_RELEASE_ASSERT(
   2235        parentRuntime->hasInitializedSelfHosting(),
   2236        "Parent runtime must initialize self-hosting before workers");
   2237 
   2238    selfHostStencilInput_ = parentRuntime->selfHostStencilInput_;
   2239    selfHostStencil_ = parentRuntime->selfHostStencil_;
   2240    return true;
   2241  }
   2242  auto start = mozilla::TimeStamp::Now();
   2243 
   2244  // Variables used to instantiate scripts.
   2245  CompileOptions options(cx);
   2246  FillSelfHostingCompileOptions(options);
   2247 
   2248  // Try initializing from Stencil XDR.
   2249  AutoPrintSelfHostingFrontendContext fc(cx);
   2250  if (xdrCache.Length() > 0) {
   2251    // Allow the VM to directly use bytecode from the XDR buffer without
   2252    // copying it. The buffer must outlive all runtimes (including workers).
   2253    options.borrowBuffer = true;
   2254    options.usePinnedBytecode = true;
   2255 
   2256    Rooted<UniquePtr<frontend::CompilationInput>> input(
   2257        cx, cx->new_<frontend::CompilationInput>(options));
   2258    if (!input) {
   2259      return false;
   2260    }
   2261    {
   2262      AutoReportFrontendContext fc(cx);
   2263      if (!input->initForSelfHostingGlobal(&fc)) {
   2264        return false;
   2265      }
   2266    }
   2267 
   2268    JS::DecodeOptions decodeOption(options);
   2269    RefPtr<frontend::CompilationStencil> stencil;
   2270    JS::TranscodeResult result =
   2271        js::DecodeStencil(&fc, decodeOption, xdrCache, getter_AddRefs(stencil));
   2272    if (result == JS::TranscodeResult::Ok) {
   2273      MOZ_ASSERT(input->atomCache.empty());
   2274 
   2275      MOZ_ASSERT(!hasSelfHostStencil());
   2276 
   2277      // Move it to the runtime.
   2278      setSelfHostingStencil(&input, std::move(stencil));
   2279 
   2280      auto end = mozilla::TimeStamp::Now();
   2281      JS_LOG(startup, Info,
   2282             "Used XDR for process self-hosted startup. Took %f us",
   2283             (end - start).ToMicroseconds());
   2284      return true;
   2285    }
   2286  }
   2287 
   2288  // If script wasn't generated, it means XDR was either not provided or that it
   2289  // failed the decoding phase. Parse from text as before.
   2290  uint32_t srcLen = GetRawScriptsSize();
   2291  const unsigned char* compressed = compressedSources;
   2292  uint32_t compressedLen = GetCompressedSize();
   2293  auto src = cx->make_pod_array<char>(srcLen);
   2294  if (!src) {
   2295    return false;
   2296  }
   2297  if (!DecompressString(compressed, compressedLen,
   2298                        reinterpret_cast<unsigned char*>(src.get()), srcLen)) {
   2299    return false;
   2300  }
   2301 
   2302  JS::SourceText<mozilla::Utf8Unit> srcBuf;
   2303  if (!srcBuf.init(cx, std::move(src), srcLen)) {
   2304    return false;
   2305  }
   2306 
   2307  Rooted<UniquePtr<frontend::CompilationInput>> input(
   2308      cx, cx->new_<frontend::CompilationInput>(options));
   2309  if (!input) {
   2310    return false;
   2311  }
   2312  frontend::NoScopeBindingCache scopeCache;
   2313  RefPtr<frontend::CompilationStencil> stencil =
   2314      frontend::CompileGlobalScriptToStencilWithInput(
   2315          cx, &fc, cx->tempLifoAlloc(), *input, &scopeCache, srcBuf,
   2316          ScopeKind::Global);
   2317  if (!stencil) {
   2318    return false;
   2319  }
   2320 
   2321  mozilla::TimeDuration xdrDuration;
   2322  // Serialize the stencil to XDR.
   2323  if (xdrWriter) {
   2324    auto encodeStart = mozilla::TimeStamp::Now();
   2325    JS::TranscodeBuffer xdrBuffer;
   2326    JS::TranscodeResult result = js::EncodeStencil(cx, stencil, xdrBuffer);
   2327    if (result != JS::TranscodeResult::Ok) {
   2328      JS_ReportErrorASCII(cx, "Encoding failure");
   2329      return false;
   2330    }
   2331 
   2332    if (!xdrWriter(cx, xdrBuffer)) {
   2333      return false;
   2334    }
   2335    auto encodeEnd = mozilla::TimeStamp::Now();
   2336    xdrDuration = (encodeEnd - encodeStart);
   2337    JS_LOG(startup, Info, "Saved XDR Buffer. Took %f us",
   2338           xdrDuration.ToMicroseconds());
   2339  }
   2340 
   2341  MOZ_ASSERT(input->atomCache.empty());
   2342 
   2343  MOZ_ASSERT(!hasSelfHostStencil());
   2344 
   2345  // Move it to the runtime.
   2346  setSelfHostingStencil(&input, std::move(stencil));
   2347 
   2348  auto end = mozilla::TimeStamp::Now();
   2349  JS_LOG(startup, Info,
   2350         "Used source text for process self-hosted startup. Took %f us (%f us "
   2351         "XDR encode)",
   2352         (end - start).ToMicroseconds(), xdrDuration.ToMicroseconds());
   2353  return true;
   2354 }
   2355 
   2356 void JSRuntime::setSelfHostingStencil(
   2357    MutableHandle<UniquePtr<frontend::CompilationInput>> input,
   2358    RefPtr<frontend::CompilationStencil>&& stencil) {
   2359  MOZ_ASSERT(!selfHostStencilInput_);
   2360  MOZ_ASSERT(!selfHostStencil_);
   2361 
   2362  selfHostStencilInput_ = input.release();
   2363  selfHostStencil_ = stencil.forget().take();
   2364 
   2365 #ifdef DEBUG
   2366  CheckSelfHostingDataIsTenured(this);
   2367 #endif
   2368 }
   2369 
   2370 bool JSRuntime::initSelfHostingFromStencil(JSContext* cx) {
   2371  return InitSelfHostingFromStencil(
   2372      cx, cx->runtime()->selfHostStencilInput_->atomCache,
   2373      *cx->runtime()->selfHostStencil_);
   2374 }
   2375 
   2376 void JSRuntime::finishSelfHosting() {
   2377  if (!parentRuntime) {
   2378    js_delete(selfHostStencilInput_.ref());
   2379    if (selfHostStencil_) {
   2380      // delete selfHostStencil_ by decrementing the ref-count of the last
   2381      // instance.
   2382      RefPtr<frontend::CompilationStencil> stencil;
   2383      *getter_AddRefs(stencil) = selfHostStencil_;
   2384      MOZ_ASSERT(!stencil->hasMultipleReference());
   2385    }
   2386  }
   2387 
   2388  selfHostStencilInput_ = nullptr;
   2389  selfHostStencil_ = nullptr;
   2390 
   2391  selfHostScriptMap.ref().clear();
   2392  clearSelfHostedJitCache();
   2393 }
   2394 
   2395 void JSRuntime::clearSelfHostedJitCache() {
   2396  for (auto iter = selfHostJitCache.ref().iter(); !iter.done(); iter.next()) {
   2397    jit::BaselineScript* baselineScript = iter.get().value();
   2398    jit::BaselineScript::Destroy(gcContext(), baselineScript);
   2399  }
   2400  selfHostJitCache.ref().clear();
   2401 }
   2402 
   2403 void JSRuntime::traceSelfHostingStencil(JSTracer* trc) {
   2404  if (selfHostStencilInput_.ref()) {
   2405    selfHostStencilInput_->trace(trc);
   2406  }
   2407  selfHostScriptMap.ref().trace(trc);
   2408  selfHostJitCache.ref().trace(trc);
   2409 }
   2410 
   2411 GeneratorKind JSRuntime::getSelfHostedFunctionGeneratorKind(
   2412    js::PropertyName* name) {
   2413  frontend::ScriptIndex index = getSelfHostedScriptIndexRange(name)->start;
   2414  auto flags = selfHostStencil().scriptExtra[index].immutableFlags;
   2415  return flags.hasFlag(js::ImmutableScriptFlagsEnum::IsGenerator)
   2416             ? GeneratorKind::Generator
   2417             : GeneratorKind::NotGenerator;
   2418 }
   2419 
   2420 // Returns the ScriptSourceObject to use for cloned self-hosted scripts in the
   2421 // current realm.
   2422 ScriptSourceObject* js::SelfHostingScriptSourceObject(JSContext* cx) {
   2423  return GlobalObject::getOrCreateSelfHostingScriptSourceObject(cx,
   2424                                                                cx->global());
   2425 }
   2426 
   2427 /* static */
   2428 ScriptSourceObject* GlobalObject::getOrCreateSelfHostingScriptSourceObject(
   2429    JSContext* cx, Handle<GlobalObject*> global) {
   2430  MOZ_ASSERT(cx->global() == global);
   2431 
   2432  if (ScriptSourceObject* sso = global->data().selfHostingScriptSource) {
   2433    return sso;
   2434  }
   2435 
   2436  CompileOptions options(cx);
   2437  FillSelfHostingCompileOptions(options);
   2438 
   2439  RefPtr<ScriptSource> source(cx->new_<ScriptSource>());
   2440  if (!source) {
   2441    return nullptr;
   2442  }
   2443 
   2444  Rooted<ScriptSourceObject*> sourceObject(cx);
   2445  {
   2446    AutoReportFrontendContext fc(cx);
   2447    if (!source->initFromOptions(&fc, options)) {
   2448      return nullptr;
   2449    }
   2450 
   2451    sourceObject = ScriptSourceObject::create(cx, source.get());
   2452    if (!sourceObject) {
   2453      return nullptr;
   2454    }
   2455 
   2456    JS::InstantiateOptions instantiateOptions(options);
   2457    if (!ScriptSourceObject::initFromOptions(cx, sourceObject,
   2458                                             instantiateOptions)) {
   2459      return nullptr;
   2460    }
   2461 
   2462    global->data().selfHostingScriptSource.init(sourceObject);
   2463  }
   2464 
   2465  return sourceObject;
   2466 }
   2467 
   2468 bool JSRuntime::delazifySelfHostedFunction(JSContext* cx,
   2469                                           Handle<PropertyName*> name,
   2470                                           HandleFunction targetFun) {
   2471  MOZ_ASSERT(targetFun->isExtended());
   2472  MOZ_ASSERT(targetFun->hasSelfHostedLazyScript());
   2473 
   2474  auto indexRange = *getSelfHostedScriptIndexRange(name);
   2475  auto& stencil = cx->runtime()->selfHostStencil();
   2476 
   2477  if (!stencil.delazifySelfHostedFunction(
   2478          cx, cx->runtime()->selfHostStencilInput().atomCache, indexRange, name,
   2479          targetFun)) {
   2480    return false;
   2481  }
   2482 
   2483  // Relazifiable self-hosted functions may be relazified later into a
   2484  // SelfHostedLazyScript, dropping the BaseScript entirely. This only applies
   2485  // to named function being delazified. Inner functions used by self-hosting
   2486  // are never relazified.
   2487  BaseScript* targetScript = targetFun->baseScript();
   2488  if (targetScript->isRelazifiable()) {
   2489    targetScript->setAllowRelazify();
   2490  }
   2491 
   2492  return true;
   2493 }
   2494 
   2495 mozilla::Maybe<frontend::ScriptIndexRange>
   2496 JSRuntime::getSelfHostedScriptIndexRange(js::PropertyName* name) {
   2497  if (parentRuntime) {
   2498    return parentRuntime->getSelfHostedScriptIndexRange(name);
   2499  }
   2500  MOZ_ASSERT(name->isPermanentAndMayBeShared());
   2501  if (auto ptr = selfHostScriptMap.ref().readonlyThreadsafeLookup(name)) {
   2502    return mozilla::Some(ptr->value());
   2503  }
   2504  return mozilla::Nothing();
   2505 }
   2506 
   2507 static bool GetComputedIntrinsic(JSContext* cx, Handle<PropertyName*> name,
   2508                                 MutableHandleValue vp) {
   2509  // If the intrinsic was not in hardcoded set, run the top-level of the
   2510  // selfhosted script. This will generate values and call `SetIntrinsic` to
   2511  // save them on a special "computed intrinsics holder". We then can check for
   2512  // our required values and cache on the normal intrinsics holder.
   2513 
   2514  Rooted<NativeObject*> computedIntrinsicsHolder(
   2515      cx, cx->global()->getComputedIntrinsicsHolder());
   2516  if (!computedIntrinsicsHolder) {
   2517    auto computedIntrinsicHolderGuard = mozilla::MakeScopeExit(
   2518        [cx]() { cx->global()->setComputedIntrinsicsHolder(nullptr); });
   2519 
   2520    // Instantiate a script in current realm from the shared Stencil.
   2521    JSRuntime* runtime = cx->runtime();
   2522    RootedScript script(
   2523        cx, runtime->selfHostStencil().instantiateSelfHostedTopLevelForRealm(
   2524                cx, runtime->selfHostStencilInput()));
   2525    if (!script) {
   2526      return false;
   2527    }
   2528 
   2529    // Attach the computed intrinsics holder to the global now to capture
   2530    // generated values.
   2531    computedIntrinsicsHolder =
   2532        NewPlainObjectWithProto(cx, nullptr, TenuredObject);
   2533    if (!computedIntrinsicsHolder) {
   2534      return false;
   2535    }
   2536    cx->global()->setComputedIntrinsicsHolder(computedIntrinsicsHolder);
   2537 
   2538    // Disable the interrupt callback while executing the top-level script.
   2539    // This prevents recursive calls to GetComputedIntrinsic through the
   2540    // interrupt callback.
   2541    bool hadInterruptsDisabled = JS_DisableInterruptCallback(cx);
   2542    auto resetInterrupts = mozilla::MakeScopeExit(
   2543        [&]() { JS_ResetInterruptCallback(cx, hadInterruptsDisabled); });
   2544 
   2545    // Attempt to execute the top-level script. If they fails to run to
   2546    // successful completion, throw away the holder to avoid a partial
   2547    // initialization state.
   2548    if (!JS_ExecuteScript(cx, script)) {
   2549      return false;
   2550    }
   2551 
   2552    // Successfully ran the self-host top-level in current realm, so these
   2553    // computed intrinsic values are now source of truth for the realm.
   2554    computedIntrinsicHolderGuard.release();
   2555  }
   2556 
   2557  // Cache the individual intrinsic on the standard holder object so that we
   2558  // only have to look for it in one place when performing `GetIntrinsic`.
   2559  mozilla::Maybe<PropertyInfo> prop =
   2560      computedIntrinsicsHolder->lookup(cx, name);
   2561 #ifdef DEBUG
   2562  if (!prop) {
   2563    Fprinter out(stderr);
   2564    out.printf("SelfHosted intrinsic not found: ");
   2565    name->dumpPropertyName(out);
   2566    out.printf("\n");
   2567  }
   2568 #endif
   2569  MOZ_RELEASE_ASSERT(prop, "SelfHosted intrinsic not found");
   2570  RootedValue value(cx, computedIntrinsicsHolder->getSlot(prop->slot()));
   2571  return GlobalObject::addIntrinsicValue(cx, cx->global(), name, value);
   2572 }
   2573 
   2574 bool JSRuntime::getSelfHostedValue(JSContext* cx, Handle<PropertyName*> name,
   2575                                   MutableHandleValue vp) {
   2576  // If the self-hosted value we want is a function in the stencil, instantiate
   2577  // a lazy self-hosted function for it. This is typical when a self-hosted
   2578  // function calls other self-hosted helper functions.
   2579  if (auto index = getSelfHostedScriptIndexRange(name)) {
   2580    JSFunction* fun =
   2581        cx->runtime()->selfHostStencil().instantiateSelfHostedLazyFunction(
   2582            cx, cx->runtime()->selfHostStencilInput().atomCache, index->start,
   2583            name);
   2584    if (!fun) {
   2585      return false;
   2586    }
   2587    vp.setObject(*fun);
   2588    return true;
   2589  }
   2590 
   2591  return GetComputedIntrinsic(cx, name, vp);
   2592 }
   2593 
   2594 void JSRuntime::assertSelfHostedFunctionHasCanonicalName(
   2595    Handle<PropertyName*> name) {
   2596 #ifdef DEBUG
   2597  frontend::ScriptIndex index = getSelfHostedScriptIndexRange(name)->start;
   2598  MOZ_ASSERT(selfHostStencil().scriptData[index].hasSelfHostedCanonicalName());
   2599 #endif
   2600 }
   2601 
   2602 bool js::IsSelfHostedFunctionWithName(JSFunction* fun, JSAtom* name) {
   2603  return fun->isSelfHostedBuiltin() && fun->isExtended() &&
   2604         GetClonedSelfHostedFunctionName(fun) == name;
   2605 }
   2606 
   2607 bool js::IsSelfHostedFunctionWithName(const Value& v, JSAtom* name) {
   2608  if (!v.isObject() || !v.toObject().is<JSFunction>()) {
   2609    return false;
   2610  }
   2611  JSFunction* fun = &v.toObject().as<JSFunction>();
   2612  return IsSelfHostedFunctionWithName(fun, name);
   2613 }
   2614 
   2615 static_assert(
   2616    JSString::MAX_LENGTH <= INT32_MAX,
   2617    "StringIteratorNext in builtin/String.js assumes the stored index "
   2618    "into the string is an Int32Value");
   2619 
   2620 static_assert(JSString::MAX_LENGTH == MAX_STRING_LENGTH,
   2621              "JSString::MAX_LENGTH matches self-hosted constant for maximum "
   2622              "string length");
   2623 
   2624 static_assert(ARGS_LENGTH_MAX == MAX_ARGS_LENGTH,
   2625              "ARGS_LENGTH_MAX matches self-hosted constant for maximum "
   2626              "arguments length");