Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/js/src/vm/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 105 kB image not shown  

SSL SelfHosting.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "vm/SelfHosting.h"

#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
#  include "builtin/AsyncDisposableStackObject.h"
#  include "builtin/DisposableStackObject.h"
#endif
#include "mozilla/BinarySearch.h"
#include "mozilla/Casting.h"
#include "mozilla/Maybe.h"
#include "mozilla/ScopeExit.h"  // mozilla::MakeScopeExit
#include "mozilla/Utf8.h"       // mozilla::Utf8Unit

#include <algorithm>
#include <iterator>

#include "jsfriendapi.h"
#include "jsmath.h"
#include "jsnum.h"
#include "selfhosted.out.h"

#include "builtin/Array.h"
#include "builtin/BigInt.h"
#ifdef JS_HAS_INTL_API
#  include "builtin/intl/Collator.h"
#  include "builtin/intl/DateTimeFormat.h"
#  include "builtin/intl/DisplayNames.h"
#  include "builtin/intl/DurationFormat.h"
#  include "builtin/intl/IntlObject.h"
#  include "builtin/intl/ListFormat.h"
#  include "builtin/intl/Locale.h"
#  include "builtin/intl/NumberFormat.h"
#  include "builtin/intl/PluralRules.h"
#  include "builtin/intl/RelativeTimeFormat.h"
#  include "builtin/intl/Segmenter.h"
#endif
#include "builtin/MapObject.h"
#include "builtin/Object.h"
#include "builtin/Promise.h"
#include "builtin/Reflect.h"
#include "builtin/RegExp.h"
#include "builtin/SelfHostingDefines.h"
#include "builtin/String.h"
#include "builtin/WeakMapObject.h"
#ifdef ENABLE_RECORD_TUPLE
#  include "builtin/TupleObject.h"
#endif
#include "frontend/BytecodeCompiler.h"    // CompileGlobalScriptToStencil
#include "frontend/CompilationStencil.h"  // js::frontend::CompilationStencil
#include "frontend/FrontendContext.h"     // AutoReportFrontendContext
#include "frontend/StencilXdr.h"  // js::EncodeStencil, js::DecodeStencil
#include "jit/AtomicOperations.h"
#include "jit/InlinableNatives.h"
#include "jit/TrampolineNatives.h"
#include "js/CompilationAndEvaluation.h"
#include "js/Conversions.h"
#include "js/ErrorReport.h"  // JS::PrintError
#include "js/experimental/JSStencil.h"
#include "js/experimental/TypedData.h"  // JS_GetArrayBufferViewType
#include "js/friend/ErrorMessages.h"    // js::GetErrorMessage, JSMSG_*
#include "js/HashTable.h"
#include "js/Printer.h"
#include "js/PropertySpec.h"
#include "js/ScalarType.h"  // js::Scalar::Type
#include "js/SourceText.h"  // JS::SourceText
#include "js/TracingAPI.h"
#include "js/Transcoding.h"
#include "js/Warnings.h"  // JS::{,Set}WarningReporter
#include "js/Wrapper.h"
#include "vm/ArgumentsObject.h"
#include "vm/AsyncFunction.h"
#include "vm/AsyncIteration.h"
#include "vm/BigIntType.h"
#include "vm/Compression.h"
#include "vm/DateObject.h"
#include "vm/ErrorReporting.h"  // js::MaybePrintAndClearPendingException
#include "vm/Float16.h"
#include "vm/FrameIter.h"  // js::ScriptFrameIter
#include "vm/GeneratorObject.h"
#include "vm/Interpreter.h"
#include "vm/Iteration.h"
#include "vm/JSAtomUtils.h"  // Atomize
#include "vm/JSContext.h"
#include "vm/JSFunction.h"
#include "vm/JSObject.h"
#include "vm/Logging.h"
#include "vm/PIC.h"
#include "vm/PlainObject.h"  // js::PlainObject
#include "vm/Realm.h"
#include "vm/RegExpObject.h"
#include "vm/StringType.h"
#include "vm/ToSource.h"  // js::ValueToSource
#include "vm/TypedArrayObject.h"
#include "vm/Uint8Clamped.h"
#include "vm/WrapperObject.h"

#include "vm/Compartment-inl.h"
#include "vm/JSAtomUtils-inl.h"  // PrimitiveValueToId
#include "vm/JSFunction-inl.h"
#include "vm/JSObject-inl.h"
#include "vm/NativeObject-inl.h"
#include "vm/TypedArrayObject-inl.h"

using namespace js;
using namespace js::selfhosted;

using JS::CompileOptions;

static bool intrinsic_ToObject(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  JSObject* obj = ToObject(cx, args[0]);
  if (!obj) {
    return false;
  }
  args.rval().setObject(*obj);
  return true;
}

#ifdef ENABLE_RECORD_TUPLE

bool intrinsic_ThisTupleValue(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  mozilla::Maybe<TupleType&> result = js::ThisTupleValue(cx, args[0]);
  if (!result) {
    return false;
  }
  args.rval().setExtendedPrimitive(*result);
  return true;
}

bool intrinsic_TupleLength(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  mozilla::Maybe<TupleType&> result = js::ThisTupleValue(cx, args[0]);
  if (!result) {
    return false;
  }
  args.rval().setInt32((*result).getDenseInitializedLength());
  return true;
}
#endif

static bool intrinsic_IsObject(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  Value val = args[0];
  bool isObject = val.isObject();
  args.rval().setBoolean(isObject);
  return true;
}

static bool intrinsic_IsArray(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  RootedValue val(cx, args[0]);
  if (val.isObject()) {
    RootedObject obj(cx, &val.toObject());
    bool isArray = false;
    if (!IsArray(cx, obj, &isArray)) {
      return false;
    }
    args.rval().setBoolean(isArray);
  } else {
    args.rval().setBoolean(false);
  }
  return true;
}

#ifdef ENABLE_RECORD_TUPLE
// returns true for TupleTypes and TupleObjects
bool js::IsTupleUnchecked(JSContext* cx, const CallArgs& args) {
  args.rval().setBoolean(IsTuple(args.get(0)));
  return true;
}

/* Identical to Tuple.prototype.isTuple, but with an
 * added check that args.length() is 1
 */

bool js::intrinsic_IsTuple(JSContext* cx, unsigned argc, JS::Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  return js::IsTupleUnchecked(cx, args);
}
#endif

static bool intrinsic_IsCrossRealmArrayConstructor(JSContext* cx, unsigned argc,
                                                   Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  bool result = false;
  if (!IsCrossRealmArrayConstructor(cx, &args[0].toObject(), &result)) {
    return false;
  }
  args.rval().setBoolean(result);
  return true;
}

static bool intrinsic_ToLength(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);

  // Inline fast path for the common case.
  if (args[0].isInt32()) {
    int32_t i = args[0].toInt32();
    args.rval().setInt32(i < 0 ? 0 : i);
    return true;
  }

  uint64_t length = 0;
  if (!ToLength(cx, args[0], &length)) {
    return false;
  }

  args.rval().setNumber(double(length));
  return true;
}

static bool intrinsic_ToInteger(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  double result;
  if (!ToInteger(cx, args[0], &result)) {
    return false;
  }
  args.rval().setNumber(result);
  return true;
}

static bool intrinsic_ToSource(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  JSString* str = ValueToSource(cx, args[0]);
  if (!str) {
    return false;
  }
  args.rval().setString(str);
  return true;
}

static bool intrinsic_ToPropertyKey(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  RootedId id(cx);
  if (!ToPropertyKey(cx, args[0], &id)) {
    return false;
  }

  args.rval().set(IdToValue(id));
  return true;
}

static bool intrinsic_IsCallable(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  args.rval().setBoolean(IsCallable(args[0]));
  return true;
}

static bool intrinsic_IsConstructor(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  args.rval().setBoolean(IsConstructor(args[0]));
  return true;
}

template <typename T>
static bool intrinsic_IsInstanceOfBuiltin(JSContext* cx, unsigned argc,
                                          Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  args.rval().setBoolean(args[0].toObject().is<T>());
  return true;
}

template <typename T>
static bool intrinsic_GuardToBuiltin(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  if (args[0].toObject().is<T>()) {
    args.rval().setObject(args[0].toObject());
    return true;
  }
  args.rval().setNull();
  return true;
}

template <typename T>
static bool intrinsic_IsWrappedInstanceOfBuiltin(JSContext* cx, unsigned argc,
                                                 Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  JSObject* obj = &args[0].toObject();
  if (!obj->is<WrapperObject>()) {
    args.rval().setBoolean(false);
    return true;
  }

  JSObject* unwrapped = CheckedUnwrapDynamic(obj, cx);
  if (!unwrapped) {
    ReportAccessDenied(cx);
    return false;
  }

  args.rval().setBoolean(unwrapped->is<T>());
  return true;
}

template <typename T>
static bool intrinsic_IsPossiblyWrappedInstanceOfBuiltin(JSContext* cx,
                                                         unsigned argc,
                                                         Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  JSObject* obj = CheckedUnwrapDynamic(&args[0].toObject(), cx);
  if (!obj) {
    ReportAccessDenied(cx);
    return false;
  }

  args.rval().setBoolean(obj->is<T>());
  return true;
}

static bool intrinsic_SubstringKernel(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args[0].isString());
  MOZ_RELEASE_ASSERT(args[1].isInt32());
  MOZ_RELEASE_ASSERT(args[2].isInt32());

  RootedString str(cx, args[0].toString());
  int32_t begin = args[1].toInt32();
  int32_t length = args[2].toInt32();

  JSString* substr = SubstringKernel(cx, str, begin, length);
  if (!substr) {
    return false;
  }

  args.rval().setString(substr);
  return true;
}

static void ThrowErrorWithType(JSContext* cx, JSExnType type,
                               const CallArgs& args) {
  MOZ_RELEASE_ASSERT(args[0].isInt32());
  uint32_t errorNumber = args[0].toInt32();

#ifdef DEBUG
  const JSErrorFormatString* efs = GetErrorMessage(nullptr, errorNumber);
  MOZ_ASSERT(efs->argCount == args.length() - 1);
  MOZ_ASSERT(efs->exnType == type,
             "error-throwing intrinsic and error number are inconsistent");
#endif

  UniqueChars errorArgs[3];
  for (unsigned i = 1; i < 4 && i < args.length(); i++) {
    HandleValue val = args[i];
    if (val.isInt32() || val.isString()) {
      JSString* str = ToString<CanGC>(cx, val);
      if (!str) {
        return;
      }
      errorArgs[i - 1] = QuoteString(cx, str);
    } else {
      errorArgs[i - 1] =
          DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, val, nullptr);
    }
    if (!errorArgs[i - 1]) {
      return;
    }
  }

  JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, errorNumber,
                           errorArgs[0].get(), errorArgs[1].get(),
                           errorArgs[2].get());
}

static bool intrinsic_ThrowRangeError(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() >= 1);

  ThrowErrorWithType(cx, JSEXN_RANGEERR, args);
  return false;
}

static bool intrinsic_ThrowTypeError(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() >= 1);

  ThrowErrorWithType(cx, JSEXN_TYPEERR, args);
  return false;
}

static bool intrinsic_ThrowAggregateError(JSContext* cx, unsigned argc,
                                          Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() >= 1);

  ThrowErrorWithType(cx, JSEXN_AGGREGATEERR, args);
  return false;
}

static bool intrinsic_ThrowInternalError(JSContext* cx, unsigned argc,
                                         Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() >= 1);

  ThrowErrorWithType(cx, JSEXN_INTERNALERR, args);
  return false;
}

#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
static bool intrinsic_CreateSuppressedError(JSContext* cx, unsigned argc,
                                            Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);

  JS::Rooted<JS::Value> error(cx, args[0]);
  JS::Rooted<JS::Value> suppressed(cx, args[1]);

  ErrorObject* suppressedError = CreateSuppressedError(cx, error, suppressed);
  if (!suppressedError) {
    return false;
  }
  args.rval().setObject(*suppressedError);
  return true;
}
#endif

/**
 * Handles an assertion failure in self-hosted code just like an assertion
 * failure in C++ code. Information about the failure can be provided in
 * args[0].
 */

static bool intrinsic_AssertionFailed(JSContext* cx, unsigned argc, Value* vp) {
#ifdef DEBUG
  CallArgs args = CallArgsFromVp(argc, vp);
  if (args.length() > 0) {
    // try to dump the informative string
    JSString* str = ToString<CanGC>(cx, args[0]);
    if (str) {
      js::Fprinter out(stderr);
      out.put("Self-hosted JavaScript assertion info: ");
      str->dumpCharsNoQuote(out);
      out.putChar('\n');
    }
  }
#endif
  MOZ_ASSERT(false);
  return false;
}

/**
 * Dumps a message to stderr, after stringifying it. Doesn't append a newline.
 */

static bool intrinsic_DumpMessage(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
#ifdef DEBUG
  if (args.length() > 0) {
    // try to dump the informative string
    js::Fprinter out(stderr);
    JSString* str = ToString<CanGC>(cx, args[0]);
    if (str) {
      str->dumpCharsNoQuote(out);
      out.putChar('\n');
    } else {
      cx->recoverFromOutOfMemory();
    }
  }
#endif
  args.rval().setUndefined();
  return true;
}

/*
 * Used to decompile values in the nearest non-builtin stack frame, falling
 * back to decompiling in the current frame. Helpful for printing higher-order
 * function arguments.
 *
 * The user must supply the argument number of the value in question; it
 * _cannot_ be automatically determined.
 */

static bool intrinsic_DecompileArg(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);
  MOZ_RELEASE_ASSERT(args[0].isInt32());

  HandleValue value = args[1];
  JSString* str = DecompileArgument(cx, args[0].toInt32(), value);
  if (!str) {
    return false;
  }
  args.rval().setString(str);
  return true;
}

static bool intrinsic_DefineDataProperty(JSContext* cx, unsigned argc,
                                         Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);

  // When DefineDataProperty is called with 3 arguments, it's compiled to
  // JSOp::InitElem in the bytecode emitter so we shouldn't get here.
  MOZ_ASSERT(args.length() == 4);
  MOZ_ASSERT(args[0].isObject());
  MOZ_RELEASE_ASSERT(args[3].isInt32());

  RootedObject obj(cx, &args[0].toObject());
  RootedId id(cx);
  if (!ToPropertyKey(cx, args[1], &id)) {
    return false;
  }
  RootedValue value(cx, args[2]);

  JS::PropertyAttributes attrs;
  unsigned attributes = args[3].toInt32();

  MOZ_ASSERT(bool(attributes & ATTR_ENUMERABLE) !=
                 bool(attributes & ATTR_NONENUMERABLE),
             "DefineDataProperty must receive either ATTR_ENUMERABLE xor "
             "ATTR_NONENUMERABLE");
  if (attributes & ATTR_ENUMERABLE) {
    attrs += JS::PropertyAttribute::Enumerable;
  }

  MOZ_ASSERT(bool(attributes & ATTR_CONFIGURABLE) !=
                 bool(attributes & ATTR_NONCONFIGURABLE),
             "DefineDataProperty must receive either ATTR_CONFIGURABLE xor "
             "ATTR_NONCONFIGURABLE");
  if (attributes & ATTR_CONFIGURABLE) {
    attrs += JS::PropertyAttribute::Configurable;
  }

  MOZ_ASSERT(
      bool(attributes & ATTR_WRITABLE) != bool(attributes & ATTR_NONWRITABLE),
      "DefineDataProperty must receive either ATTR_WRITABLE xor "
      "ATTR_NONWRITABLE");
  if (attributes & ATTR_WRITABLE) {
    attrs += JS::PropertyAttribute::Writable;
  }

  Rooted<PropertyDescriptor> desc(cx, PropertyDescriptor::Data(value, attrs));
  if (!DefineProperty(cx, obj, id, desc)) {
    return false;
  }

  args.rval().setUndefined();
  return true;
}

static bool intrinsic_DefineProperty(JSContext* cx, unsigned argc, Value* vp) {
  // _DefineProperty(object, propertyKey, attributes,
  //                 valueOrGetter, setter, strict)
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 6);
  MOZ_ASSERT(args[0].isObject());
  MOZ_ASSERT(args[1].isString() || args[1].isNumber() || args[1].isSymbol());
  MOZ_RELEASE_ASSERT(args[2].isInt32());
  MOZ_ASSERT(args[5].isBoolean());

  RootedObject obj(cx, &args[0].toObject());
  RootedId id(cx);
  if (!PrimitiveValueToId<CanGC>(cx, args[1], &id)) {
    return false;
  }

  Rooted<PropertyDescriptor> desc(cx, PropertyDescriptor::Empty());

  unsigned attributes = args[2].toInt32();
  if (attributes & (ATTR_ENUMERABLE | ATTR_NONENUMERABLE)) {
    desc.setEnumerable(attributes & ATTR_ENUMERABLE);
  }

  if (attributes & (ATTR_CONFIGURABLE | ATTR_NONCONFIGURABLE)) {
    desc.setConfigurable(attributes & ATTR_CONFIGURABLE);
  }

  if (attributes & (ATTR_WRITABLE | ATTR_NONWRITABLE)) {
    desc.setWritable(attributes & ATTR_WRITABLE);
  }

  // When args[4] is |null|, the data descriptor has a value component.
  if ((attributes & DATA_DESCRIPTOR_KIND) && args[4].isNull()) {
    desc.setValue(args[3]);
  }

  if (attributes & ACCESSOR_DESCRIPTOR_KIND) {
    Value getter = args[3];
    if (getter.isObject()) {
      desc.setGetter(&getter.toObject());
    } else if (getter.isUndefined()) {
      desc.setGetter(nullptr);
    } else {
      MOZ_ASSERT(getter.isNull());
    }

    Value setter = args[4];
    if (setter.isObject()) {
      desc.setSetter(&setter.toObject());
    } else if (setter.isUndefined()) {
      desc.setSetter(nullptr);
    } else {
      MOZ_ASSERT(setter.isNull());
    }
  }

  desc.assertValid();

  ObjectOpResult result;
  if (!DefineProperty(cx, obj, id, desc, result)) {
    return false;
  }

  bool strict = args[5].toBoolean();
  if (strict && !result.ok()) {
    // We need to tell our caller Object.defineProperty,
    // that this operation failed, without actually throwing
    // for web-compatibility reasons.
    if (result.failureCode() == JSMSG_CANT_DEFINE_WINDOW_NC) {
      args.rval().setBoolean(false);
      return true;
    }

    return result.reportError(cx, obj, id);
  }

  args.rval().setBoolean(result.ok());
  return true;
}

static bool intrinsic_ObjectHasPrototype(JSContext* cx, unsigned argc,
                                         Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);

  // Self-hosted code calls this intrinsic with builtin prototypes. These are
  // always native objects.
  auto* obj = &args[0].toObject().as<NativeObject>();
  auto* proto = &args[1].toObject().as<NativeObject>();

  JSObject* actualProto = obj->staticPrototype();
  args.rval().setBoolean(actualProto == proto);
  return true;
}

static bool intrinsic_UnsafeSetReservedSlot(JSContext* cx, unsigned argc,
                                            Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 3);
  MOZ_ASSERT(args[0].isObject());
  MOZ_RELEASE_ASSERT(args[1].isInt32());
  MOZ_ASSERT(args[1].toInt32() >= 0);

  uint32_t slot = uint32_t(args[1].toInt32());
  args[0].toObject().as<NativeObject>().setReservedSlot(slot, args[2]);
  args.rval().setUndefined();
  return true;
}

static bool intrinsic_UnsafeGetReservedSlot(JSContext* cx, unsigned argc,
                                            Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);
  MOZ_ASSERT(args[0].isObject());
  MOZ_RELEASE_ASSERT(args[1].isInt32());
  MOZ_ASSERT(args[1].toInt32() >= 0);

  uint32_t slot = uint32_t(args[1].toInt32());
  args.rval().set(args[0].toObject().as<NativeObject>().getReservedSlot(slot));
  return true;
}

static bool intrinsic_UnsafeGetObjectFromReservedSlot(JSContext* cx,
                                                      unsigned argc,
                                                      Value* vp) {
  if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp)) {
    return false;
  }
  MOZ_ASSERT(vp->isObject());
  return true;
}

static bool intrinsic_UnsafeGetInt32FromReservedSlot(JSContext* cx,
                                                     unsigned argc, Value* vp) {
  if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp)) {
    return false;
  }
  MOZ_ASSERT(vp->isInt32());
  return true;
}

static bool intrinsic_UnsafeGetStringFromReservedSlot(JSContext* cx,
                                                      unsigned argc,
                                                      Value* vp) {
  if (!intrinsic_UnsafeGetReservedSlot(cx, argc, vp)) {
    return false;
  }
  MOZ_ASSERT(vp->isString());
  return true;
}

static bool intrinsic_ThisTimeValue(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isInt32());

  const char* name = nullptr;

  int32_t method = args[0].toInt32();
  if (method == DATE_METHOD_LOCALE_TIME_STRING) {
    name = "toLocaleTimeString";
  } else if (method == DATE_METHOD_LOCALE_DATE_STRING) {
    name = "toLocaleDateString";
  } else {
    MOZ_ASSERT(method == DATE_METHOD_LOCALE_STRING);
    name = "toLocaleString";
  }

  auto* unwrapped = UnwrapAndTypeCheckThis<DateObject>(cx, args, name);
  if (!unwrapped) {
    return false;
  }

  args.rval().set(unwrapped->UTCTime());
  return true;
}

static bool intrinsic_IsPackedArray(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());
  args.rval().setBoolean(IsPackedArray(&args[0].toObject()));
  return true;
}

bool js::intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  JSObject* obj = NewArrayIterator(cx);
  if (!obj) {
    return false;
  }

  args.rval().setObject(*obj);
  return true;
}

static bool intrinsic_ArrayIteratorPrototypeOptimizable(JSContext* cx,
                                                        unsigned argc,
                                                        Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  ForOfPIC::Chain* stubChain = ForOfPIC::getOrCreate(cx);
  if (!stubChain) {
    return false;
  }

  bool optimized;
  if (!stubChain->tryOptimizeArrayIteratorNext(cx, &optimized)) {
    return false;
  }
  args.rval().setBoolean(optimized);
  return true;
}

static bool intrinsic_GetNextMapEntryForIterator(JSContext* cx, unsigned argc,
                                                 Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);
  MOZ_ASSERT(args[0].toObject().is<MapIteratorObject>());
  MOZ_ASSERT(args[1].isObject());

  MapIteratorObject* mapIterator = &args[0].toObject().as<MapIteratorObject>();
  ArrayObject* result = &args[1].toObject().as<ArrayObject>();

  args.rval().setBoolean(MapIteratorObject::next(mapIterator, result));
  return true;
}

static bool intrinsic_CreateMapIterationResultPair(JSContext* cx, unsigned argc,
                                                   Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  JSObject* result = MapIteratorObject::createResultPair(cx);
  if (!result) {
    return false;
  }

  args.rval().setObject(*result);
  return true;
}

static bool intrinsic_GetNextSetEntryForIterator(JSContext* cx, unsigned argc,
                                                 Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);
  MOZ_ASSERT(args[0].toObject().is<SetIteratorObject>());
  MOZ_ASSERT(args[1].isObject());

  SetIteratorObject* setIterator = &args[0].toObject().as<SetIteratorObject>();
  ArrayObject* result = &args[1].toObject().as<ArrayObject>();

  args.rval().setBoolean(SetIteratorObject::next(setIterator, result));
  return true;
}

static bool intrinsic_CreateSetIterationResult(JSContext* cx, unsigned argc,
                                               Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  JSObject* result = SetIteratorObject::createResult(cx);
  if (!result) {
    return false;
  }

  args.rval().setObject(*result);
  return true;
}

bool js::intrinsic_NewStringIterator(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  JSObject* obj = NewStringIterator(cx);
  if (!obj) {
    return false;
  }

  args.rval().setObject(*obj);
  return true;
}

bool js::intrinsic_NewRegExpStringIterator(JSContext* cx, unsigned argc,
                                           Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  JSObject* obj = NewRegExpStringIterator(cx);
  if (!obj) {
    return false;
  }

  args.rval().setObject(*obj);
  return true;
}

js::PropertyName* js::GetClonedSelfHostedFunctionName(const JSFunction* fun) {
  if (!fun->isExtended()) {
    return nullptr;
  }
  Value name = fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT);
  if (!name.isString()) {
    return nullptr;
  }
  return name.toString()->asAtom().asPropertyName();
}

bool js::IsExtendedUnclonedSelfHostedFunctionName(JSAtom* name) {
  if (name->length() < 2) {
    return false;
  }
  return name->latin1OrTwoByteChar(0) ==
         ExtendedUnclonedSelfHostedFunctionNamePrefix;
}

void js::SetClonedSelfHostedFunctionName(JSFunction* fun,
                                         js::PropertyName* name) {
  fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(name));
}

static bool intrinsic_GeneratorObjectIsClosed(JSContext* cx, unsigned argc,
                                              Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
  args.rval().setBoolean(genObj->isClosed());
  return true;
}

static bool intrinsic_IsSuspendedGenerator(JSContext* cx, unsigned argc,
                                           Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);

  if (!args[0].isObject() || !args[0].toObject().is<GeneratorObject>()) {
    args.rval().setBoolean(false);
    return true;
  }

  GeneratorObject& genObj = args[0].toObject().as<GeneratorObject>();
  args.rval().setBoolean(!genObj.isClosed() && genObj.isSuspended());
  return true;
}

static bool intrinsic_GeneratorIsRunning(JSContext* cx, unsigned argc,
                                         Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
  args.rval().setBoolean(genObj->isRunning());
  return true;
}

static bool intrinsic_GeneratorSetClosed(JSContext* cx, unsigned argc,
                                         Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  GeneratorObject* genObj = &args[0].toObject().as<GeneratorObject>();
  genObj->setClosed(cx);
  return true;
}

template <typename T>
static bool intrinsic_ArrayBufferByteLength(JSContext* cx, unsigned argc,
                                            Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());
  MOZ_ASSERT(args[0].toObject().is<T>());

  size_t byteLength = args[0].toObject().as<T>().byteLength();
  args.rval().setNumber(byteLength);
  return true;
}

template <typename T>
static bool intrinsic_PossiblyWrappedArrayBufferByteLength(JSContext* cx,
                                                           unsigned argc,
                                                           Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);

  T* obj = args[0].toObject().maybeUnwrapAs<T>();
  if (!obj) {
    ReportAccessDenied(cx);
    return false;
  }

  size_t byteLength = obj->byteLength();
  args.rval().setNumber(byteLength);
  return true;
}

static void AssertNonNegativeInteger(const Value& v) {
  MOZ_ASSERT(v.isNumber());
  MOZ_ASSERT(v.toNumber() >= 0);
  MOZ_ASSERT(v.toNumber() < DOUBLE_INTEGRAL_PRECISION_LIMIT);
  MOZ_ASSERT(JS::ToInteger(v.toNumber()) == v.toNumber());
}

template <typename T>
static bool intrinsic_ArrayBufferCopyData(JSContext* cx, unsigned argc,
                                          Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 6);
  AssertNonNegativeInteger(args[1]);
  AssertNonNegativeInteger(args[3]);
  AssertNonNegativeInteger(args[4]);

  bool isWrapped = args[5].toBoolean();
  Rooted<T*> toBuffer(cx);
  if (!isWrapped) {
    toBuffer = &args[0].toObject().as<T>();
  } else {
    JSObject* wrapped = &args[0].toObject();
    MOZ_ASSERT(wrapped->is<WrapperObject>());
    toBuffer = wrapped->maybeUnwrapAs<T>();
    if (!toBuffer) {
      ReportAccessDenied(cx);
      return false;
    }
  }
  size_t toIndex = size_t(args[1].toNumber());
  Rooted<T*> fromBuffer(cx, &args[2].toObject().as<T>());
  size_t fromIndex = size_t(args[3].toNumber());
  size_t count = size_t(args[4].toNumber());

  T::copyData(toBuffer, toIndex, fromBuffer, fromIndex, count);

  args.rval().setUndefined();
  return true;
}

// Arguments must both be SharedArrayBuffer or wrapped SharedArrayBuffer.
static bool intrinsic_SharedArrayBuffersMemorySame(JSContext* cx, unsigned argc,
                                                   Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);

  auto* lhs = args[0].toObject().maybeUnwrapAs<SharedArrayBufferObject>();
  if (!lhs) {
    ReportAccessDenied(cx);
    return false;
  }
  auto* rhs = args[1].toObject().maybeUnwrapAs<SharedArrayBufferObject>();
  if (!rhs) {
    ReportAccessDenied(cx);
    return false;
  }

  args.rval().setBoolean(lhs->rawBufferObject() == rhs->rawBufferObject());
  return true;
}

static bool intrinsic_IsTypedArrayConstructor(JSContext* cx, unsigned argc,
                                              Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  args.rval().setBoolean(js::IsTypedArrayConstructor(&args[0].toObject()));
  return true;
}

static bool intrinsic_TypedArrayBuffer(JSContext* cx, unsigned argc,
                                       Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].toObject().is<TypedArrayObject>());

  Rooted<TypedArrayObject*> tarray(cx,
                                   &args[0].toObject().as<TypedArrayObject>());
  if (!TypedArrayObject::ensureHasBuffer(cx, tarray)) {
    return false;
  }

  args.rval().set(tarray->bufferValue());
  return true;
}

static bool intrinsic_TypedArrayByteOffset(JSContext* cx, unsigned argc,
                                           Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].toObject().is<TypedArrayObject>());

  auto* tarr = &args[0].toObject().as<TypedArrayObject>();
  args.rval().setNumber(tarr->byteOffsetMaybeOutOfBounds());
  return true;
}

static bool intrinsic_TypedArrayElementSize(JSContext* cx, unsigned argc,
                                            Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].toObject().is<TypedArrayObject>());

  unsigned size =
      TypedArrayElemSize(args[0].toObject().as<TypedArrayObject>().type());
  MOZ_ASSERT(size == 1 || size == 2 || size == 4 || size == 8);

  args.rval().setInt32(mozilla::AssertedCast<int32_t>(size));
  return true;
}

// Return the value of [[ArrayLength]] internal slot of the TypedArray
static bool intrinsic_TypedArrayLength(JSContext* cx, unsigned argc,
                                       Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].toObject().is<TypedArrayObject>());

  auto* tarr = &args[0].toObject().as<TypedArrayObject>();

  mozilla::Maybe<size_t> length = tarr->length();
  if (!length) {
    // Return zero for detached buffers to match JIT code.
    if (tarr->hasDetachedBuffer()) {
      args.rval().setInt32(0);
      return true;
    }

    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                              JSMSG_TYPED_ARRAY_RESIZED_BOUNDS);
    return false;
  }

  args.rval().setNumber(*length);
  return true;
}

// Return the value of [[ArrayLength]] internal slot of the TypedArray. If the
// length is out-of-bounds, always return zero.
static bool intrinsic_TypedArrayLengthZeroOnOutOfBounds(JSContext* cx,
                                                        unsigned argc,
                                                        Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].toObject().is<TypedArrayObject>());

  auto* tarr = &args[0].toObject().as<TypedArrayObject>();
  args.rval().setNumber(tarr->length().valueOr(0));
  return true;
}

static bool intrinsic_PossiblyWrappedTypedArrayLength(JSContext* cx,
                                                      unsigned argc,
                                                      Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  TypedArrayObject* obj = args[0].toObject().maybeUnwrapAs<TypedArrayObject>();
  if (!obj) {
    ReportAccessDenied(cx);
    return false;
  }

  mozilla::Maybe<size_t> length = obj->length();
  if (!length) {
    // Return zero for detached buffers to match JIT code.
    if (obj->hasDetachedBuffer()) {
      args.rval().setInt32(0);
      return true;
    }

    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                              JSMSG_TYPED_ARRAY_RESIZED_BOUNDS);
    return false;
  }

  args.rval().setNumber(*length);
  return true;
}

static bool intrinsic_PossiblyWrappedTypedArrayHasDetachedBuffer(JSContext* cx,
                                                                 unsigned argc,
                                                                 Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  TypedArrayObject* obj = args[0].toObject().maybeUnwrapAs<TypedArrayObject>();
  if (!obj) {
    ReportAccessDenied(cx);
    return false;
  }

  bool detached = obj->hasDetachedBuffer();
  args.rval().setBoolean(detached);
  return true;
}

static bool intrinsic_TypedArrayIsAutoLength(JSContext* cx, unsigned argc,
                                             Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].toObject().is<TypedArrayObject>());

  JSObject* obj = &args[0].toObject();
  bool isAutoLength = obj->is<ResizableTypedArrayObject>() &&
                      obj->as<ResizableTypedArrayObject>().isAutoLength();
  args.rval().setBoolean(isAutoLength);
  return true;
}

// Extract the TypedArrayObject* underlying |obj| and return it.  This method,
// in a TOTALLY UNSAFE manner, completely violates the normal compartment
// boundaries, returning an object not necessarily in the current compartment
// or in |obj|'s compartment.
//
// All callers of this method are expected to sigil this TypedArrayObject*, and
// all values and information derived from it, with an "unsafe" prefix, to
// indicate the extreme caution required when dealing with such values.
//
// If calling code discipline ever fails to be maintained, it's gonna have a
// bad time.
static TypedArrayObject* DangerouslyUnwrapTypedArray(JSContext* cx,
                                                     JSObject* obj) {
  // An unwrapped pointer to an object potentially on the other side of a
  // compartment boundary!  Isn't this such fun?
  TypedArrayObject* unwrapped = obj->maybeUnwrapAs<TypedArrayObject>();
  if (!unwrapped) {
    ReportAccessDenied(cx);
    return nullptr;
  }

  // Be super-duper careful using this, as we've just punched through
  // the compartment boundary, and things like buffer() on this aren't
  // same-compartment with anything else in the calling method.
  return unwrapped;
}

static bool intrinsic_TypedArrayBitwiseSlice(JSContext* cx, unsigned argc,
                                             Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 4);
  MOZ_ASSERT(args[0].isObject());
  MOZ_ASSERT(args[1].isObject());
  AssertNonNegativeInteger(args[2]);
  AssertNonNegativeInteger(args[3]);

  Rooted<TypedArrayObject*> source(cx,
                                   &args[0].toObject().as<TypedArrayObject>());

  auto sourceLength = source->length();
  if (!sourceLength) {
    if (source->hasDetachedBuffer()) {
      JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                                JSMSG_TYPED_ARRAY_DETACHED);
    } else {
      JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                                JSMSG_TYPED_ARRAY_RESIZED_BOUNDS);
    }
    return false;
  }
  MOZ_ASSERT(!source->hasDetachedBuffer());

  // As directed by |DangerouslyUnwrapTypedArray|, sigil this pointer and all
  // variables derived from it to counsel extreme caution here.
  Rooted<TypedArrayObject*> unsafeTypedArrayCrossCompartment(cx);
  unsafeTypedArrayCrossCompartment =
      DangerouslyUnwrapTypedArray(cx, &args[1].toObject());
  if (!unsafeTypedArrayCrossCompartment) {
    return false;
  }
  MOZ_ASSERT(!unsafeTypedArrayCrossCompartment->hasDetachedBuffer());

  // The specification requires us to perform bitwise copying when |sourceType|
  // and |targetType| are the same (ES2017, §22.2.3.24, step 15). Additionally,
  // as an optimization, we can also perform bitwise copying when |sourceType|
  // and |targetType| have compatible bit-level representations.
  Scalar::Type sourceType = source->type();
  if (!CanUseBitwiseCopy(unsafeTypedArrayCrossCompartment->type(),
                         sourceType)) {
    args.rval().setBoolean(false);
    return true;
  }

  size_t sourceOffset = size_t(args[2].toNumber());
  size_t count = size_t(args[3].toNumber());

  MOZ_ASSERT(count > 0);
  MOZ_ASSERT(count <= unsafeTypedArrayCrossCompartment->length().valueOr(0));

  size_t elementSize = TypedArrayElemSize(sourceType);
  MOZ_ASSERT(elementSize ==
             TypedArrayElemSize(unsafeTypedArrayCrossCompartment->type()));

  SharedMem<uint8_t*> sourceData =
      source->dataPointerEither().cast<uint8_t*>() + sourceOffset * elementSize;

  SharedMem<uint8_t*> unsafeTargetDataCrossCompartment =
      unsafeTypedArrayCrossCompartment->dataPointerEither().cast<uint8_t*>();

  size_t byteLength = std::min(count, *sourceLength) * elementSize;

  // The same-type case requires exact copying preserving the bit-level
  // encoding of the source data, so use memcpy if possible. If source and
  // target are the same buffer, we can't use memcpy (or memmove), because
  // the specification requires sequential copying of the values. This case
  // is only possible if a @@species constructor created a specifically
  // crafted typed array. It won't happen in normal code and hence doesn't
  // need to be optimized.
  if (!TypedArrayObject::sameBuffer(source, unsafeTypedArrayCrossCompartment)) {
    if (source->isSharedMemory() ||
        unsafeTypedArrayCrossCompartment->isSharedMemory()) {
      jit::AtomicOperations::memcpySafeWhenRacy(
          unsafeTargetDataCrossCompartment, sourceData, byteLength);
    } else {
      memcpy(unsafeTargetDataCrossCompartment.unwrapUnshared(),
             sourceData.unwrapUnshared(), byteLength);
    }
  } else {
    using namespace jit;

    for (; byteLength > 0; byteLength--) {
      AtomicOperations::storeSafeWhenRacy(
          unsafeTargetDataCrossCompartment++,
          AtomicOperations::loadSafeWhenRacy(sourceData++));
    }
  }

  args.rval().setBoolean(true);
  return true;
}

static bool intrinsic_TypedArrayInitFromPackedArray(JSContext* cx,
                                                    unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);
  MOZ_ASSERT(args[0].isObject());
  MOZ_ASSERT(args[1].isObject());

  Rooted<FixedLengthTypedArrayObject*> target(
      cx, &args[0].toObject().as<FixedLengthTypedArrayObject>());
  MOZ_ASSERT(!target->hasDetachedBuffer());
  MOZ_ASSERT(!target->isSharedMemory());

  Rooted<ArrayObject*> source(cx, &args[1].toObject().as<ArrayObject>());
  MOZ_ASSERT(IsPackedArray(source));
  MOZ_ASSERT(source->length() == target->length());

  switch (target->type()) {
#define INIT_TYPED_ARRAY(_, T, N)                                      \
  case Scalar::N: {                                                    \
    if (!ElementSpecific<T, UnsharedOps>::initFromIterablePackedArray( \
            cx, target, source)) {                                     \
      return false;                                                    \
    }                                                                  \
    break;                                                             \
  }
    JS_FOR_EACH_TYPED_ARRAY(INIT_TYPED_ARRAY)
#undef INIT_TYPED_ARRAY

    default:
      MOZ_CRASH(
          "TypedArrayInitFromPackedArray with a typed array with bogus type");
  }

  args.rval().setUndefined();
  return true;
}

template <bool ForTest>
static bool intrinsic_RegExpBuiltinExec(JSContext* cx, unsigned argc,
                                        Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);
  MOZ_ASSERT(args[0].isObject());
  MOZ_ASSERT(args[0].toObject().is<RegExpObject>());
  MOZ_ASSERT(args[1].isString());

  Rooted<RegExpObject*> obj(cx, &args[0].toObject().as<RegExpObject>());
  Rooted<JSString*> string(cx, args[1].toString());
  return RegExpBuiltinExec(cx, obj, string, ForTest, args.rval());
}

template <bool ForTest>
static bool intrinsic_RegExpExec(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);
  MOZ_ASSERT(args[0].isObject());
  MOZ_ASSERT(args[1].isString());

  Rooted<JSObject*> obj(cx, &args[0].toObject());
  Rooted<JSString*> string(cx, args[1].toString());
  return RegExpExec(cx, obj, string, ForTest, args.rval());
}

static bool intrinsic_RegExpCreate(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);

  MOZ_ASSERT(args.length() == 1 || args.length() == 2);
  MOZ_ASSERT_IF(args.length() == 2,
                args[1].isString() || args[1].isUndefined());
  MOZ_ASSERT(!args.isConstructing());

  return RegExpCreate(cx, args[0], args.get(1), args.rval());
}

static bool intrinsic_RegExpGetSubstitution(JSContext* cx, unsigned argc,
                                            Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 6);

  Rooted<ArrayObject*> matchResult(cx, &args[0].toObject().as<ArrayObject>());

  Rooted<JSLinearString*> string(cx, args[1].toString()->ensureLinear(cx));
  if (!string) {
    return false;
  }

  int32_t position = int32_t(args[2].toNumber());
  MOZ_ASSERT(position >= 0);

  Rooted<JSLinearString*> replacement(cx, args[3].toString()->ensureLinear(cx));
  if (!replacement) {
    return false;
  }

  int32_t firstDollarIndex = int32_t(args[4].toNumber());
  MOZ_ASSERT(firstDollarIndex >= 0);

  RootedValue namedCaptures(cx, args[5]);
  MOZ_ASSERT(namedCaptures.isUndefined() || namedCaptures.isObject());

  return RegExpGetSubstitution(cx, matchResult, string, size_t(position),
                               replacement, size_t(firstDollarIndex),
                               namedCaptures, args.rval());
}

static bool intrinsic_RegExpHasCaptureGroups(JSContext* cx, unsigned argc,
                                             Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);
  MOZ_ASSERT(args[0].isObject());
  MOZ_ASSERT(args[1].isString());

  Rooted<RegExpObject*> obj(cx, &args[0].toObject().as<RegExpObject>());
  Rooted<JSString*> string(cx, args[1].toString());

  bool result;
  if (!RegExpHasCaptureGroups(cx, obj, string, &result)) {
    return false;
  }

  args.rval().setBoolean(result);
  return true;
}

static bool intrinsic_StringReplaceString(JSContext* cx, unsigned argc,
                                          Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 3);

  RootedString string(cx, args[0].toString());
  RootedString pattern(cx, args[1].toString());
  RootedString replacement(cx, args[2].toString());
  JSString* result = str_replace_string_raw(cx, string, pattern, replacement);
  if (!result) {
    return false;
  }

  args.rval().setString(result);
  return true;
}

static bool intrinsic_StringReplaceAllString(JSContext* cx, unsigned argc,
                                             Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 3);

  RootedString string(cx, args[0].toString());
  RootedString pattern(cx, args[1].toString());
  RootedString replacement(cx, args[2].toString());
  JSString* result =
      str_replaceAll_string_raw(cx, string, pattern, replacement);
  if (!result) {
    return false;
  }

  args.rval().setString(result);
  return true;
}

static bool intrinsic_StringSplitString(JSContext* cx, unsigned argc,
                                        Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);

  RootedString string(cx, args[0].toString());
  RootedString sep(cx, args[1].toString());

  JSObject* aobj = StringSplitString(cx, string, sep, INT32_MAX);
  if (!aobj) {
    return false;
  }

  args.rval().setObject(*aobj);
  return true;
}

static bool intrinsic_StringSplitStringLimit(JSContext* cx, unsigned argc,
                                             Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 3);

  RootedString string(cx, args[0].toString());
  RootedString sep(cx, args[1].toString());

  // args[2] should be already in UInt32 range, but it could be double typed,
  // because of Ion optimization.
  uint32_t limit = uint32_t(args[2].toNumber());
  MOZ_ASSERT(limit > 0,
             "Zero limit case is already handled in self-hosted code.");

  JSObject* aobj = StringSplitString(cx, string, sep, limit);
  if (!aobj) {
    return false;
  }

  args.rval().setObject(*aobj);
  return true;
}

bool CallSelfHostedNonGenericMethod(JSContext* cx, const CallArgs& args) {
  // This function is called when a self-hosted method is invoked on a
  // wrapper object, like a CrossCompartmentWrapper. The last argument is
  // the name of the self-hosted function. The other arguments are the
  // arguments to pass to this function.

  MOZ_ASSERT(args.length() > 0);
  Rooted<PropertyName*> name(
      cx, args[args.length() - 1].toString()->asAtom().asPropertyName());

  InvokeArgs args2(cx);
  if (!args2.init(cx, args.length() - 1)) {
    return false;
  }

  for (size_t i = 0; i < args.length() - 1; i++) {
    args2[i].set(args[i]);
  }

  return CallSelfHostedFunction(cx, name, args.thisv(), args2, args.rval());
}

#ifdef DEBUG
bool js::CallSelfHostedFunction(JSContext* cx, const char* name,
                                HandleValue thisv, const AnyInvokeArgs& args,
                                MutableHandleValue rval) {
  JSAtom* funAtom = Atomize(cx, name, strlen(name));
  if (!funAtom) {
    return false;
  }
  Rooted<PropertyName*> funName(cx, funAtom->asPropertyName());
  return CallSelfHostedFunction(cx, funName, thisv, args, rval);
}
#endif

bool js::CallSelfHostedFunction(JSContext* cx, Handle<PropertyName*> name,
                                HandleValue thisv, const AnyInvokeArgs& args,
                                MutableHandleValue rval) {
  RootedValue fun(cx);
  if (!GlobalObject::getIntrinsicValue(cx, cx->global(), name, &fun)) {
    return false;
  }
  MOZ_ASSERT(fun.toObject().is<JSFunction>());

  return Call(cx, fun, thisv, args, rval);
}

template <typename T>
bool Is(HandleValue v) {
  return v.isObject() && v.toObject().is<T>();
}

template <IsAcceptableThis Test>
static bool CallNonGenericSelfhostedMethod(JSContext* cx, unsigned argc,
                                           Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<Test, CallSelfHostedNonGenericMethod>(cx, args);
}

bool js::IsCallSelfHostedNonGenericMethod(NativeImpl impl) {
  return impl == CallSelfHostedNonGenericMethod;
}

bool js::ReportIncompatibleSelfHostedMethod(JSContext* cx,
                                            Handle<Value> thisValue) {
  // The contract for this function is the same as
  // CallSelfHostedNonGenericMethod. The normal ReportIncompatible function
  // doesn't work for selfhosted functions, because they always call the
  // different CallXXXMethodIfWrapped methods, which would be reported as the
  // called function instead.

  // Lookup the selfhosted method that was invoked.  But skip over
  // internal self-hosted function frames, because those are never the
  // actual self-hosted callee from external code.  We can't just skip
  // self-hosted things until we find a non-self-hosted one because of cases
  // like array.sort(somethingSelfHosted), where we want to report the error
  // in the somethingSelfHosted, not in the sort() call.

  static const charconst internalNames[] = {
      "EnsureTypedArrayWithArrayBuffer",
      "RegExpSearchSlowPath",
      "RegExpReplaceSlowPath",
      "RegExpMatchSlowPath",
  };

  ScriptFrameIter iter(cx);
  MOZ_ASSERT(iter.isFunctionFrame());

  while (!iter.done()) {
    MOZ_ASSERT(iter.callee(cx)->isSelfHostedOrIntrinsic());
    UniqueChars funNameBytes;
    const char* funName =
        GetFunctionNameBytes(cx, iter.callee(cx), &funNameBytes);
    if (!funName) {
      return false;
    }
    if (std::all_of(
            std::begin(internalNames), std::end(internalNames),
            [funName](auto* name) { return strcmp(funName, name) != 0; })) {
      JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
                               JSMSG_INCOMPATIBLE_METHOD, funName, "method",
                               InformalValueTypeName(thisValue));
      return false;
    }
    ++iter;
  }

  MOZ_ASSERT_UNREACHABLE("How did we not find a useful self-hosted frame?");
  return false;
}

#ifdef JS_HAS_INTL_API
/**
 * Returns the default locale as a well-formed, but not necessarily
 * canonicalized, BCP-47 language tag.
 */

static bool intrinsic_RuntimeDefaultLocale(JSContext* cx, unsigned argc,
                                           Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  const char* locale = cx->realm()->getLocale();
  if (!locale) {
    return false;
  }

  JSString* jslocale = NewStringCopyZ<CanGC>(cx, locale);
  if (!jslocale) {
    return false;
  }

  args.rval().setString(jslocale);
  return true;
}

static bool intrinsic_IsRuntimeDefaultLocale(JSContext* cx, unsigned argc,
                                             Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isString() || args[0].isUndefined());

  // |undefined| is the default value when the Intl runtime caches haven't
  // yet been initialized. Handle it the same way as a cache miss.
  if (args[0].isUndefined()) {
    args.rval().setBoolean(false);
    return true;
  }

  const char* locale = cx->realm()->getLocale();
  if (!locale) {
    return false;
  }

  JSLinearString* str = args[0].toString()->ensureLinear(cx);
  if (!str) {
    return false;
  }

  bool equals = StringEqualsAscii(str, locale);
  args.rval().setBoolean(equals);
  return true;
}
#endif  // JS_HAS_INTL_API

static bool intrinsic_ConstructFunction(JSContext* cx, unsigned argc,
                                        Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 3);
  MOZ_ASSERT(IsConstructor(args[0]));
  MOZ_ASSERT(IsConstructor(args[1]));
  MOZ_ASSERT(args[2].toObject().is<ArrayObject>());

  Rooted<ArrayObject*> argsList(cx, &args[2].toObject().as<ArrayObject>());
  uint32_t len = argsList->length();
  ConstructArgs constructArgs(cx);
  if (!constructArgs.init(cx, len)) {
    return false;
  }
  for (uint32_t index = 0; index < len; index++) {
    constructArgs[index].set(argsList->getDenseElement(index));
  }

  RootedObject res(cx);
  if (!Construct(cx, args[0], constructArgs, args[1], &res)) {
    return false;
  }

  args.rval().setObject(*res);
  return true;
}

static bool intrinsic_IsConstructing(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  ScriptFrameIter iter(cx);
  bool isConstructing = iter.isConstructing();
  args.rval().setBoolean(isConstructing);
  return true;
}

static bool intrinsic_ConstructorForTypedArray(JSContext* cx, unsigned argc,
                                               Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isObject());

  auto* object = UnwrapAndDowncastValue<TypedArrayObject>(cx, args[0]);
  if (!object) {
    return false;
  }

  JSProtoKey protoKey = StandardProtoKeyOrNull(object);
  MOZ_ASSERT(protoKey);

  // While it may seem like an invariant that in any compartment,
  // seeing a typed array object implies that the TypedArray constructor
  // for that type is initialized on the compartment's global, this is not
  // the case. When we construct a typed array given a cross-compartment
  // ArrayBuffer, we put the constructed TypedArray in the same compartment
  // as the ArrayBuffer. Since we use the prototype from the initial
  // compartment, and never call the constructor in the ArrayBuffer's
  // compartment from script, we are not guaranteed to have initialized
  // the constructor.
  JSObject* ctor = GlobalObject::getOrCreateConstructor(cx, protoKey);
  if (!ctor) {
    return false;
  }

  args.rval().setObject(*ctor);
  return true;
}

static bool intrinsic_PromiseResolve(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);

  RootedObject constructor(cx, &args[0].toObject());
  JSObject* promise = js::PromiseResolve(cx, constructor, args[1]);
  if (!promise) {
    return false;
  }

  args.rval().setObject(*promise);
  return true;
}

static bool intrinsic_CopyDataPropertiesOrGetOwnKeys(JSContext* cx,
                                                     unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 3);
  MOZ_ASSERT(args[0].isObject());
  MOZ_ASSERT(args[1].isObject());
  MOZ_ASSERT(args[2].isObjectOrNull());

  RootedObject target(cx, &args[0].toObject());
  RootedObject from(cx, &args[1].toObject());
  RootedObject excludedItems(cx, args[2].toObjectOrNull());

  if (from->is<NativeObject>() && target->is<PlainObject>() &&
      (!excludedItems || excludedItems->is<PlainObject>())) {
    bool optimized;
    if (!CopyDataPropertiesNative(
            cx, target.as<PlainObject>(), from.as<NativeObject>(),
            (excludedItems ? excludedItems.as<PlainObject>() : nullptr),
            &optimized)) {
      return false;
    }

    if (optimized) {
      args.rval().setNull();
      return true;
    }
  }

  return GetOwnPropertyKeys(
      cx, from, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, args.rval());
}

static bool intrinsic_ToBigInt(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  BigInt* res = ToBigInt(cx, args[0]);
  if (!res) {
    return false;
  }
  args.rval().setBigInt(res);
  return true;
}

static bool intrinsic_NumberToBigInt(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isNumber());
  BigInt* res = NumberToBigInt(cx, args[0].toNumber());
  if (!res) {
    return false;
  }
  args.rval().setBigInt(res);
  return true;
}

static bool intrinsic_BigIntToNumber(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 1);
  MOZ_ASSERT(args[0].isBigInt());
  args.rval().setNumber(BigInt::numberValue(args[0].toBigInt()));
  return true;
}

static bool intrinsic_NewWrapForValidIterator(JSContext* cx, unsigned argc,
                                              Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  JSObject* obj = NewWrapForValidIterator(cx);
  if (!obj) {
    return false;
  }

  args.rval().setObject(*obj);
  return true;
}

static bool intrinsic_NewIteratorHelper(JSContext* cx, unsigned argc,
                                        Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  JSObject* obj = NewIteratorHelper(cx);
  if (!obj) {
    return false;
  }

  args.rval().setObject(*obj);
  return true;
}

static bool intrinsic_NewAsyncIteratorHelper(JSContext* cx, unsigned argc,
                                             Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  JSObject* obj = NewAsyncIteratorHelper(cx);
  if (!obj) {
    return false;
  }

  args.rval().setObject(*obj);
  return true;
}

static JSObject* NewIteratorRecord(JSContext* cx, HandleObject iterator,
                                   HandleValue nextMethod) {
  gc::AllocKind allocKind = gc::GetGCObjectKind(3);
  Rooted<PlainObject*> obj(
      cx, NewPlainObjectWithProtoAndAllocKind(cx, nullptr, allocKind));
  if (!obj) {
    return nullptr;
  }

  RootedId propid(cx, NameToId(cx->names().iterator));
  RootedValue value(cx, ObjectValue(*iterator));
  if (!NativeDefineDataProperty(cx, obj, propid, value, JSPROP_ENUMERATE)) {
    return nullptr;
  }

  propid = NameToId(cx->names().nextMethod);
  value.set(nextMethod);
  if (!NativeDefineDataProperty(cx, obj, propid, value, JSPROP_ENUMERATE)) {
    return nullptr;
  }

  propid = NameToId(cx->names().done);
  value.setBoolean(false);
  if (!NativeDefineDataProperty(cx, obj, propid, value, JSPROP_ENUMERATE)) {
    return nullptr;
  }

  return obj;
}

static bool intrinsic_CreateAsyncFromSyncIterator(JSContext* cx, unsigned argc,
                                                  Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 2);

  RootedObject iterator(cx, &args[0].toObject());
  RootedObject asyncIterator(
      cx, CreateAsyncFromSyncIterator(cx, iterator, args[1]));
  if (!asyncIterator) {
    return false;
  }

  RootedValue nextMethod(cx);
  if (!GetProperty(cx, asyncIterator, asyncIterator, cx->names().next,
                   &nextMethod)) {
    return false;
  }

  RootedObject iteratorRecord(cx,
                              NewIteratorRecord(cx, asyncIterator, nextMethod));
  if (!iteratorRecord) {
    return false;
  }

  args.rval().setObject(*iteratorRecord);
  return true;
}

static bool intrinsic_NoPrivateGetter(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                            JSMSG_PRIVATE_SETTER_ONLY);

  args.rval().setUndefined();
  return false;
}

static bool intrinsic_newList(JSContext* cx, unsigned argc, js::Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);
  MOZ_ASSERT(args.length() == 0);

  ArrayObject* list = NewArrayWithNullProto(cx);
  if (!list) {
    return false;
  }

  args.rval().setObject(*list);
  return true;
}

static const JSFunctionSpec intrinsic_functions[] = {
    // Intrinsic helper functions
    JS_INLINABLE_FN("ArrayBufferByteLength",
                    intrinsic_ArrayBufferByteLength<ArrayBufferObject>, 1, 0,
                    IntrinsicArrayBufferByteLength),
    JS_FN("ArrayBufferCopyData",
          intrinsic_ArrayBufferCopyData<ArrayBufferObject>, 6, 0),
    JS_INLINABLE_FN("ArrayIteratorPrototypeOptimizable",
                    intrinsic_ArrayIteratorPrototypeOptimizable, 0, 0,
                    IntrinsicArrayIteratorPrototypeOptimizable),
    JS_FN("AssertionFailed", intrinsic_AssertionFailed, 1, 0),
    JS_FN("BigIntToNumber", intrinsic_BigIntToNumber, 1, 0),
    JS_FN("CallArrayBufferMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<ArrayBufferObject>>, 2, 0),
    JS_FN("CallArrayIteratorMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<ArrayIteratorObject>>, 2, 0),
#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    JS_FN("CallAsyncDisposableStackMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<AsyncDisposableStackObject>>, 2, 0),
#endif
    JS_FN("CallAsyncIteratorHelperMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<AsyncIteratorHelperObject>>, 2, 0),
#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    JS_FN("CallDisposableStackMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<DisposableStackObject>>, 2, 0),
#endif
    JS_FN("CallGeneratorMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<GeneratorObject>>, 2, 0),
    JS_FN("CallIteratorHelperMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<IteratorHelperObject>>, 2, 0),
    JS_FN("CallMapIteratorMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<MapIteratorObject>>, 2, 0),
    JS_FN("CallMapMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<MapObject>>, 2, 0),
    JS_FN("CallRegExpMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<RegExpObject>>, 2, 0),
    JS_FN("CallRegExpStringIteratorMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<RegExpStringIteratorObject>>, 2, 0),
    JS_FN("CallSetIteratorMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<SetIteratorObject>>, 2, 0),
    JS_FN("CallSetMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<SetObject>>, 2, 0),
    JS_FN("CallSharedArrayBufferMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<SharedArrayBufferObject>>, 2, 0),
    JS_FN("CallStringIteratorMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<StringIteratorObject>>, 2, 0),
    JS_FN("CallTypedArrayMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<TypedArrayObject>>, 2, 0),
    JS_FN("CallWeakMapMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<WeakMapObject>>, 2, 0),
    JS_FN("CallWrapForValidIteratorMethodIfWrapped",
          CallNonGenericSelfhostedMethod<Is<WrapForValidIteratorObject>>, 2, 0),
    JS_FN("ConstructFunction", intrinsic_ConstructFunction, 2, 0),
    JS_FN("ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1, 0),
    JS_FN("CopyDataPropertiesOrGetOwnKeys",
          intrinsic_CopyDataPropertiesOrGetOwnKeys, 3, 0),
    JS_FN("CreateAsyncFromSyncIterator", intrinsic_CreateAsyncFromSyncIterator,
          2, 0),
    JS_FN("CreateMapIterationResultPair",
          intrinsic_CreateMapIterationResultPair, 0, 0),
    JS_FN("CreateSetIterationResult", intrinsic_CreateSetIterationResult, 0, 0),
#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    JS_FN("CreateSuppressedError", intrinsic_CreateSuppressedError, 2, 0),
#endif
    JS_FN("DecompileArg", intrinsic_DecompileArg, 2, 0),
    JS_FN("DefineDataProperty", intrinsic_DefineDataProperty, 4, 0),
    JS_FN("DefineProperty", intrinsic_DefineProperty, 6, 0),
    JS_FN("DumpMessage", intrinsic_DumpMessage, 1, 0),
    JS_FN("FlatStringMatch", FlatStringMatch, 2, 0),
    JS_FN("FlatStringSearch", FlatStringSearch, 2, 0),
    JS_FN("GeneratorIsRunning", intrinsic_GeneratorIsRunning, 1, 0),
    JS_FN("GeneratorObjectIsClosed", intrinsic_GeneratorObjectIsClosed, 1, 0),
    JS_FN("GeneratorSetClosed", intrinsic_GeneratorSetClosed, 1, 0),
    JS_FN("GetElemBaseForLambda", intrinsic_GetElemBaseForLambda, 1, 0),
    JS_INLINABLE_FN("GetFirstDollarIndex", GetFirstDollarIndex, 1, 0,
                    GetFirstDollarIndex),
    JS_INLINABLE_FN("GetNextMapEntryForIterator",
                    intrinsic_GetNextMapEntryForIterator, 2, 0,
                    IntrinsicGetNextMapEntryForIterator),
    JS_INLINABLE_FN("GetNextSetEntryForIterator",
                    intrinsic_GetNextSetEntryForIterator, 2, 0,
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=99 G=96

¤ Dauer der Verarbeitung: 0.74 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.