tor-browser

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

Object.cpp (82138B)


      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 "debugger/Object-inl.h"
      8 
      9 #include "mozilla/Maybe.h"   // for Maybe, Nothing, Some
     10 #include "mozilla/Range.h"   // for Range
     11 #include "mozilla/Result.h"  // for Result
     12 #include "mozilla/Vector.h"  // for Vector
     13 
     14 #include <algorithm>
     15 #include <string.h>  // for size_t, strlen
     16 #include <utility>   // for move
     17 
     18 #include "jsapi.h"  // for CallArgs, RootedObject, Rooted
     19 
     20 #include "builtin/Array.h"       // for NewDenseCopiedArray
     21 #include "builtin/Promise.h"     // for PromiseReactionRecordBuilder
     22 #include "debugger/Debugger.h"   // for Completion, Debugger
     23 #include "debugger/Frame.h"      // for DebuggerFrame
     24 #include "debugger/NoExecute.h"  // for LeaveDebuggeeNoExecute
     25 #include "debugger/Script.h"     // for DebuggerScript
     26 #include "debugger/Source.h"     // for DebuggerSource
     27 #include "gc/Tracer.h"        // for TraceManuallyBarrieredCrossCompartmentEdge
     28 #include "js/ColumnNumber.h"  // JS::ColumnNumberOneOrigin
     29 #include "js/CompilationAndEvaluation.h"  //  for Compile
     30 #include "js/Conversions.h"               // for ToObject
     31 #include "js/experimental/JitInfo.h"      // for JSJitInfo
     32 #include "js/friend/ErrorMessages.h"      // for GetErrorMessage, JSMSG_*
     33 #include "js/friend/WindowProxy.h"  // for IsWindow, IsWindowProxy, ToWindowIfWindowProxy
     34 #include "js/HeapAPI.h"             // for IsInsideNursery
     35 #include "js/Promise.h"             // for PromiseState
     36 #include "js/PropertyAndElement.h"       // for JS_GetProperty
     37 #include "js/Proxy.h"                    // for PropertyDescriptor
     38 #include "js/SourceText.h"               // for SourceText
     39 #include "js/StableStringChars.h"        // for AutoStableStringChars
     40 #include "js/String.h"                   // for JS::StringHasLatin1Chars
     41 #include "proxy/ScriptedProxyHandler.h"  // for ScriptedProxyHandler
     42 #include "vm/ArgumentsObject.h"          // for ARGS_LENGTH_MAX
     43 #include "vm/ArrayObject.h"              // for ArrayObject
     44 #include "vm/AsyncFunction.h"            // for AsyncGeneratorObject
     45 #include "vm/AsyncIteration.h"           // for AsyncFunctionGeneratorObject
     46 #include "vm/BoundFunctionObject.h"      // for BoundFunctionObject
     47 #include "vm/BytecodeUtil.h"             // for JSDVG_SEARCH_STACK
     48 #include "vm/Compartment.h"              // for Compartment
     49 #include "vm/EnvironmentObject.h"        // for GetDebugEnvironmentForFunction
     50 #include "vm/ErrorObject.h"              // for JSObject::is, ErrorObject
     51 #include "vm/GeneratorObject.h"          // for AbstractGeneratorObject
     52 #include "vm/GlobalObject.h"             // for JSObject::is, GlobalObject
     53 #include "vm/Interpreter.h"              // for Call
     54 #include "vm/JSAtomUtils.h"              // for Atomize, AtomizeString
     55 #include "vm/JSContext.h"                // for JSContext, ReportValueError
     56 #include "vm/JSFunction.h"               // for JSFunction
     57 #include "vm/JSObject.h"                 // for GenericObject, NewObjectKind
     58 #include "vm/JSScript.h"                 // for JSScript
     59 #include "vm/NativeObject.h"             // for NativeObject, JSObject::is
     60 #include "vm/ObjectOperations.h"         // for DefineProperty
     61 #include "vm/PlainObject.h"              // for js::PlainObject
     62 #include "vm/PromiseObject.h"            // for js::PromiseObject
     63 #include "vm/Realm.h"                    // for AutoRealm, ErrorCopier, Realm
     64 #include "vm/Runtime.h"                  // for JSAtomState
     65 #include "vm/SavedFrame.h"               // for SavedFrame
     66 #include "vm/Scope.h"                    // for PositionalFormalParameterIter
     67 #include "vm/SelfHosting.h"              // for GetClonedSelfHostedFunctionName
     68 #include "vm/Shape.h"                    // for Shape
     69 #include "vm/Stack.h"                    // for InvokeArgs
     70 #include "vm/StringType.h"               // for JSAtom, PropertyName
     71 #include "vm/WrapperObject.h"            // for JSObject::is, WrapperObject
     72 
     73 #include "gc/StableCellHasher-inl.h"
     74 #include "vm/Compartment-inl.h"  // for Compartment::wrap
     75 #include "vm/JSObject-inl.h"  // for GetObjectClassName, InitClass, NewObjectWithGivenProtoAndKind, ToPropertyKey
     76 #include "vm/NativeObject-inl.h"      // for NativeObject::global
     77 #include "vm/ObjectOperations-inl.h"  // for DeleteProperty, GetProperty
     78 #include "vm/Realm-inl.h"             // for AutoRealm::AutoRealm
     79 
     80 using namespace js;
     81 
     82 using JS::AutoStableStringChars;
     83 using mozilla::Maybe;
     84 using mozilla::Nothing;
     85 using mozilla::Some;
     86 
     87 const JSClassOps DebuggerObject::classOps_ = {
     88    nullptr,                          // addProperty
     89    nullptr,                          // delProperty
     90    nullptr,                          // enumerate
     91    nullptr,                          // newEnumerate
     92    nullptr,                          // resolve
     93    nullptr,                          // mayResolve
     94    nullptr,                          // finalize
     95    nullptr,                          // call
     96    nullptr,                          // construct
     97    CallTraceMethod<DebuggerObject>,  // trace
     98 };
     99 
    100 const JSClass DebuggerObject::class_ = {
    101    "Object",
    102    JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS),
    103    &classOps_,
    104 };
    105 
    106 void DebuggerObject::trace(JSTracer* trc) {
    107  // There is a barrier on private pointers, so the Unbarriered marking
    108  // is okay.
    109  if (JSObject* referent = maybeReferent()) {
    110    TraceManuallyBarrieredCrossCompartmentEdge(trc, this, &referent,
    111                                               "Debugger.Object referent");
    112    if (referent != maybeReferent()) {
    113      setReservedSlotGCThingAsPrivateUnbarriered(OBJECT_SLOT, referent);
    114    }
    115  }
    116 }
    117 
    118 static DebuggerObject* DebuggerObject_checkThis(JSContext* cx,
    119                                                const CallArgs& args) {
    120  JSObject* thisobj = RequireObject(cx, args.thisv());
    121  if (!thisobj) {
    122    return nullptr;
    123  }
    124  if (!thisobj->is<DebuggerObject>()) {
    125    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    126                              JSMSG_INCOMPATIBLE_PROTO, "Debugger.Object",
    127                              "method", thisobj->getClass()->name);
    128    return nullptr;
    129  }
    130 
    131  return &thisobj->as<DebuggerObject>();
    132 }
    133 
    134 /* static */
    135 bool DebuggerObject::construct(JSContext* cx, unsigned argc, Value* vp) {
    136  JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
    137                            "Debugger.Object");
    138  return false;
    139 }
    140 
    141 struct MOZ_STACK_CLASS DebuggerObject::CallData {
    142  JSContext* cx;
    143  const CallArgs& args;
    144 
    145  Handle<DebuggerObject*> object;
    146  RootedObject referent;
    147 
    148  CallData(JSContext* cx, const CallArgs& args, Handle<DebuggerObject*> obj)
    149      : cx(cx), args(args), object(obj), referent(cx, obj->referent()) {}
    150 
    151  // JSNative properties
    152  bool callableGetter();
    153  bool isBoundFunctionGetter();
    154  bool isArrowFunctionGetter();
    155  bool isAsyncFunctionGetter();
    156  bool isClassConstructorGetter();
    157  bool isGeneratorFunctionGetter();
    158  bool protoGetter();
    159  bool classGetter();
    160  bool nameGetter();
    161  bool displayNameGetter();
    162  bool parameterNamesGetter();
    163  bool scriptGetter();
    164  bool environmentGetter();
    165  bool boundTargetFunctionGetter();
    166  bool boundThisGetter();
    167  bool boundArgumentsGetter();
    168  bool allocationSiteGetter();
    169  bool isErrorGetter();
    170  bool isMutedErrorGetter();
    171  bool errorMessageNameGetter();
    172  bool errorNotesGetter();
    173  bool errorLineNumberGetter();
    174  bool errorColumnNumberGetter();
    175  bool isProxyGetter();
    176  bool proxyTargetGetter();
    177  bool proxyHandlerGetter();
    178  bool isPromiseGetter();
    179  bool promiseStateGetter();
    180  bool promiseValueGetter();
    181  bool promiseReasonGetter();
    182  bool promiseLifetimeGetter();
    183  bool promiseTimeToResolutionGetter();
    184  bool promiseAllocationSiteGetter();
    185  bool promiseResolutionSiteGetter();
    186  bool promiseIDGetter();
    187  bool promiseDependentPromisesGetter();
    188 
    189  // JSNative methods
    190  bool isExtensibleMethod();
    191  bool isSealedMethod();
    192  bool isFrozenMethod();
    193  bool getPropertyMethod();
    194  bool setPropertyMethod();
    195  bool getOwnPropertyNamesMethod();
    196  bool getOwnPropertyNamesLengthMethod();
    197  bool getOwnPropertySymbolsMethod();
    198  bool getOwnPrivatePropertiesMethod();
    199  bool getOwnPropertyDescriptorMethod();
    200  bool preventExtensionsMethod();
    201  bool sealMethod();
    202  bool freezeMethod();
    203  bool definePropertyMethod();
    204  bool definePropertiesMethod();
    205  bool deletePropertyMethod();
    206  bool callMethod();
    207  bool applyMethod();
    208  bool asEnvironmentMethod();
    209  bool forceLexicalInitializationByNameMethod();
    210  bool executeInGlobalMethod();
    211  bool executeInGlobalWithBindingsMethod();
    212  bool createSource();
    213  bool makeDebuggeeValueMethod();
    214  bool isSameNativeMethod();
    215  bool isSameNativeWithJitInfoMethod();
    216  bool isNativeGetterWithJitInfo();
    217  bool unsafeDereferenceMethod();
    218  bool unwrapMethod();
    219  bool getPromiseReactionsMethod();
    220 
    221  using Method = bool (CallData::*)();
    222 
    223  template <Method MyMethod>
    224  static bool ToNative(JSContext* cx, unsigned argc, Value* vp);
    225 };
    226 
    227 template <DebuggerObject::CallData::Method MyMethod>
    228 /* static */
    229 bool DebuggerObject::CallData::ToNative(JSContext* cx, unsigned argc,
    230                                        Value* vp) {
    231  CallArgs args = CallArgsFromVp(argc, vp);
    232 
    233  Rooted<DebuggerObject*> obj(cx, DebuggerObject_checkThis(cx, args));
    234  if (!obj) {
    235    return false;
    236  }
    237 
    238  CallData data(cx, args, obj);
    239  return (data.*MyMethod)();
    240 }
    241 
    242 bool DebuggerObject::CallData::callableGetter() {
    243  args.rval().setBoolean(object->isCallable());
    244  return true;
    245 }
    246 
    247 bool DebuggerObject::CallData::isBoundFunctionGetter() {
    248  args.rval().setBoolean(object->isBoundFunction());
    249  return true;
    250 }
    251 
    252 bool DebuggerObject::CallData::isArrowFunctionGetter() {
    253  if (!object->isDebuggeeFunction()) {
    254    args.rval().setUndefined();
    255    return true;
    256  }
    257 
    258  args.rval().setBoolean(object->isArrowFunction());
    259  return true;
    260 }
    261 
    262 bool DebuggerObject::CallData::isAsyncFunctionGetter() {
    263  if (!object->isDebuggeeFunction()) {
    264    args.rval().setUndefined();
    265    return true;
    266  }
    267 
    268  args.rval().setBoolean(object->isAsyncFunction());
    269  return true;
    270 }
    271 
    272 bool DebuggerObject::CallData::isGeneratorFunctionGetter() {
    273  if (!object->isDebuggeeFunction()) {
    274    args.rval().setUndefined();
    275    return true;
    276  }
    277 
    278  args.rval().setBoolean(object->isGeneratorFunction());
    279  return true;
    280 }
    281 
    282 bool DebuggerObject::CallData::isClassConstructorGetter() {
    283  if (!object->isDebuggeeFunction()) {
    284    args.rval().setUndefined();
    285    return true;
    286  }
    287 
    288  args.rval().setBoolean(object->isClassConstructor());
    289  return true;
    290 }
    291 
    292 bool DebuggerObject::CallData::protoGetter() {
    293  Rooted<DebuggerObject*> result(cx);
    294  if (!DebuggerObject::getPrototypeOf(cx, object, &result)) {
    295    return false;
    296  }
    297 
    298  args.rval().setObjectOrNull(result);
    299  return true;
    300 }
    301 
    302 bool DebuggerObject::CallData::classGetter() {
    303  RootedString result(cx);
    304  if (!DebuggerObject::getClassName(cx, object, &result)) {
    305    return false;
    306  }
    307 
    308  args.rval().setString(result);
    309  return true;
    310 }
    311 
    312 bool DebuggerObject::CallData::nameGetter() {
    313  if (!object->isFunction() && !object->isBoundFunction()) {
    314    args.rval().setUndefined();
    315    return true;
    316  }
    317 
    318  JS::Rooted<JSAtom*> result(cx);
    319  if (!object->name(cx, &result)) {
    320    return false;
    321  }
    322 
    323  if (result) {
    324    args.rval().setString(result);
    325  } else {
    326    args.rval().setUndefined();
    327  }
    328  return true;
    329 }
    330 
    331 bool DebuggerObject::CallData::displayNameGetter() {
    332  if (!object->isFunction() && !object->isBoundFunction()) {
    333    args.rval().setUndefined();
    334    return true;
    335  }
    336 
    337  JS::Rooted<JSAtom*> result(cx);
    338  if (!object->displayName(cx, &result)) {
    339    return false;
    340  }
    341  if (result) {
    342    args.rval().setString(result);
    343  } else {
    344    args.rval().setUndefined();
    345  }
    346  return true;
    347 }
    348 
    349 bool DebuggerObject::CallData::parameterNamesGetter() {
    350  if (!object->isDebuggeeFunction()) {
    351    args.rval().setUndefined();
    352    return true;
    353  }
    354 
    355  RootedFunction referent(cx, &object->referent()->as<JSFunction>());
    356 
    357  ArrayObject* arr = GetFunctionParameterNamesArray(cx, referent);
    358  if (!arr) {
    359    return false;
    360  }
    361 
    362  args.rval().setObject(*arr);
    363  return true;
    364 }
    365 
    366 bool DebuggerObject::CallData::scriptGetter() {
    367  Debugger* dbg = object->owner();
    368 
    369  if (!referent->is<JSFunction>()) {
    370    args.rval().setUndefined();
    371    return true;
    372  }
    373 
    374  RootedFunction fun(cx, &referent->as<JSFunction>());
    375  if (!IsInterpretedNonSelfHostedFunction(fun)) {
    376    args.rval().setUndefined();
    377    return true;
    378  }
    379 
    380  RootedScript script(cx, GetOrCreateFunctionScript(cx, fun));
    381  if (!script) {
    382    return false;
    383  }
    384 
    385  // Only hand out debuggee scripts.
    386  if (!dbg->observesScript(script)) {
    387    args.rval().setNull();
    388    return true;
    389  }
    390 
    391  Rooted<DebuggerScript*> scriptObject(cx, dbg->wrapScript(cx, script));
    392  if (!scriptObject) {
    393    return false;
    394  }
    395 
    396  args.rval().setObject(*scriptObject);
    397  return true;
    398 }
    399 
    400 bool DebuggerObject::CallData::environmentGetter() {
    401  Debugger* dbg = object->owner();
    402 
    403  // Don't bother switching compartments just to check obj's type and get its
    404  // env.
    405  if (!referent->is<JSFunction>()) {
    406    args.rval().setUndefined();
    407    return true;
    408  }
    409 
    410  RootedFunction fun(cx, &referent->as<JSFunction>());
    411  if (!IsInterpretedNonSelfHostedFunction(fun)) {
    412    args.rval().setUndefined();
    413    return true;
    414  }
    415 
    416  // Only hand out environments of debuggee functions.
    417  if (!dbg->observesGlobal(&fun->global())) {
    418    args.rval().setNull();
    419    return true;
    420  }
    421 
    422  Rooted<Env*> env(cx);
    423  {
    424    AutoRealm ar(cx, fun);
    425    env = GetDebugEnvironmentForFunction(cx, fun);
    426    if (!env) {
    427      return false;
    428    }
    429  }
    430 
    431  return dbg->wrapEnvironment(cx, env, args.rval());
    432 }
    433 
    434 bool DebuggerObject::CallData::boundTargetFunctionGetter() {
    435  if (!object->isDebuggeeBoundFunction()) {
    436    args.rval().setUndefined();
    437    return true;
    438  }
    439 
    440  Rooted<DebuggerObject*> result(cx);
    441  if (!DebuggerObject::getBoundTargetFunction(cx, object, &result)) {
    442    return false;
    443  }
    444 
    445  args.rval().setObject(*result);
    446  return true;
    447 }
    448 
    449 bool DebuggerObject::CallData::boundThisGetter() {
    450  if (!object->isDebuggeeBoundFunction()) {
    451    args.rval().setUndefined();
    452    return true;
    453  }
    454 
    455  return DebuggerObject::getBoundThis(cx, object, args.rval());
    456 }
    457 
    458 bool DebuggerObject::CallData::boundArgumentsGetter() {
    459  if (!object->isDebuggeeBoundFunction()) {
    460    args.rval().setUndefined();
    461    return true;
    462  }
    463 
    464  Rooted<ValueVector> result(cx, ValueVector(cx));
    465  if (!DebuggerObject::getBoundArguments(cx, object, &result)) {
    466    return false;
    467  }
    468 
    469  RootedObject obj(cx,
    470                   NewDenseCopiedArray(cx, result.length(), result.begin()));
    471  if (!obj) {
    472    return false;
    473  }
    474 
    475  args.rval().setObject(*obj);
    476  return true;
    477 }
    478 
    479 bool DebuggerObject::CallData::allocationSiteGetter() {
    480  RootedObject result(cx);
    481  if (!DebuggerObject::getAllocationSite(cx, object, &result)) {
    482    return false;
    483  }
    484 
    485  args.rval().setObjectOrNull(result);
    486  return true;
    487 }
    488 
    489 // Returns the "name" field (see js/public/friend/ErrorNumbers.msg), which may
    490 // be used as a unique identifier, for any error object with a JSErrorReport or
    491 // undefined if the object has no JSErrorReport.
    492 bool DebuggerObject::CallData::errorMessageNameGetter() {
    493  RootedString result(cx);
    494  if (!DebuggerObject::getErrorMessageName(cx, object, &result)) {
    495    return false;
    496  }
    497 
    498  if (result) {
    499    args.rval().setString(result);
    500  } else {
    501    args.rval().setUndefined();
    502  }
    503  return true;
    504 }
    505 
    506 bool DebuggerObject::CallData::isErrorGetter() {
    507  args.rval().setBoolean(object->isError());
    508  return true;
    509 }
    510 
    511 bool DebuggerObject::CallData::isMutedErrorGetter() {
    512  args.rval().setBoolean(object->isMutedError(cx));
    513  return true;
    514 }
    515 
    516 bool DebuggerObject::CallData::errorNotesGetter() {
    517  return DebuggerObject::getErrorNotes(cx, object, args.rval());
    518 }
    519 
    520 bool DebuggerObject::CallData::errorLineNumberGetter() {
    521  return DebuggerObject::getErrorLineNumber(cx, object, args.rval());
    522 }
    523 
    524 bool DebuggerObject::CallData::errorColumnNumberGetter() {
    525  return DebuggerObject::getErrorColumnNumber(cx, object, args.rval());
    526 }
    527 
    528 bool DebuggerObject::CallData::isProxyGetter() {
    529  args.rval().setBoolean(object->isScriptedProxy());
    530  return true;
    531 }
    532 
    533 bool DebuggerObject::CallData::proxyTargetGetter() {
    534  if (!object->isScriptedProxy()) {
    535    args.rval().setUndefined();
    536    return true;
    537  }
    538 
    539  Rooted<DebuggerObject*> result(cx);
    540  if (!DebuggerObject::getScriptedProxyTarget(cx, object, &result)) {
    541    return false;
    542  }
    543 
    544  args.rval().setObjectOrNull(result);
    545  return true;
    546 }
    547 
    548 bool DebuggerObject::CallData::proxyHandlerGetter() {
    549  if (!object->isScriptedProxy()) {
    550    args.rval().setUndefined();
    551    return true;
    552  }
    553  Rooted<DebuggerObject*> result(cx);
    554  if (!DebuggerObject::getScriptedProxyHandler(cx, object, &result)) {
    555    return false;
    556  }
    557 
    558  args.rval().setObjectOrNull(result);
    559  return true;
    560 }
    561 
    562 bool DebuggerObject::CallData::isPromiseGetter() {
    563  args.rval().setBoolean(object->isPromise());
    564  return true;
    565 }
    566 
    567 bool DebuggerObject::CallData::promiseStateGetter() {
    568  if (!DebuggerObject::requirePromise(cx, object)) {
    569    return false;
    570  }
    571 
    572  RootedValue result(cx);
    573  switch (object->promiseState()) {
    574    case JS::PromiseState::Pending:
    575      result.setString(cx->names().pending);
    576      break;
    577    case JS::PromiseState::Fulfilled:
    578      result.setString(cx->names().fulfilled);
    579      break;
    580    case JS::PromiseState::Rejected:
    581      result.setString(cx->names().rejected);
    582      break;
    583  }
    584 
    585  args.rval().set(result);
    586  return true;
    587 }
    588 
    589 bool DebuggerObject::CallData::promiseValueGetter() {
    590  if (!DebuggerObject::requirePromise(cx, object)) {
    591    return false;
    592  }
    593 
    594  if (object->promiseState() != JS::PromiseState::Fulfilled) {
    595    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    596                              JSMSG_DEBUG_PROMISE_NOT_FULFILLED);
    597    return false;
    598  }
    599 
    600  return DebuggerObject::getPromiseValue(cx, object, args.rval());
    601  ;
    602 }
    603 
    604 bool DebuggerObject::CallData::promiseReasonGetter() {
    605  if (!DebuggerObject::requirePromise(cx, object)) {
    606    return false;
    607  }
    608 
    609  if (object->promiseState() != JS::PromiseState::Rejected) {
    610    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    611                              JSMSG_DEBUG_PROMISE_NOT_REJECTED);
    612    return false;
    613  }
    614 
    615  return DebuggerObject::getPromiseReason(cx, object, args.rval());
    616 }
    617 
    618 bool DebuggerObject::CallData::promiseLifetimeGetter() {
    619  if (!DebuggerObject::requirePromise(cx, object)) {
    620    return false;
    621  }
    622 
    623  args.rval().setNumber(object->promiseLifetime());
    624  return true;
    625 }
    626 
    627 bool DebuggerObject::CallData::promiseTimeToResolutionGetter() {
    628  if (!DebuggerObject::requirePromise(cx, object)) {
    629    return false;
    630  }
    631 
    632  if (object->promiseState() == JS::PromiseState::Pending) {
    633    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    634                              JSMSG_DEBUG_PROMISE_NOT_RESOLVED);
    635    return false;
    636  }
    637 
    638  args.rval().setNumber(object->promiseTimeToResolution());
    639  return true;
    640 }
    641 
    642 static PromiseObject* EnsurePromise(JSContext* cx, HandleObject referent) {
    643  // We only care about promises, so CheckedUnwrapStatic is OK.
    644  RootedObject obj(cx, CheckedUnwrapStatic(referent));
    645  if (!obj) {
    646    ReportAccessDenied(cx);
    647    return nullptr;
    648  }
    649  if (!obj->is<PromiseObject>()) {
    650    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    651                              JSMSG_NOT_EXPECTED_TYPE, "Debugger", "Promise",
    652                              obj->getClass()->name);
    653    return nullptr;
    654  }
    655  return &obj->as<PromiseObject>();
    656 }
    657 
    658 bool DebuggerObject::CallData::promiseAllocationSiteGetter() {
    659  Rooted<PromiseObject*> promise(cx, EnsurePromise(cx, referent));
    660  if (!promise) {
    661    return false;
    662  }
    663 
    664  RootedObject allocSite(cx, promise->allocationSite());
    665  if (!allocSite) {
    666    args.rval().setNull();
    667    return true;
    668  }
    669 
    670  if (!cx->compartment()->wrap(cx, &allocSite)) {
    671    return false;
    672  }
    673  args.rval().set(ObjectValue(*allocSite));
    674  return true;
    675 }
    676 
    677 bool DebuggerObject::CallData::promiseResolutionSiteGetter() {
    678  Rooted<PromiseObject*> promise(cx, EnsurePromise(cx, referent));
    679  if (!promise) {
    680    return false;
    681  }
    682 
    683  if (promise->state() == JS::PromiseState::Pending) {
    684    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
    685                              JSMSG_DEBUG_PROMISE_NOT_RESOLVED);
    686    return false;
    687  }
    688 
    689  RootedObject resolutionSite(cx, promise->resolutionSite());
    690  if (!resolutionSite) {
    691    args.rval().setNull();
    692    return true;
    693  }
    694 
    695  if (!cx->compartment()->wrap(cx, &resolutionSite)) {
    696    return false;
    697  }
    698  args.rval().set(ObjectValue(*resolutionSite));
    699  return true;
    700 }
    701 
    702 bool DebuggerObject::CallData::promiseIDGetter() {
    703  Rooted<PromiseObject*> promise(cx, EnsurePromise(cx, referent));
    704  if (!promise) {
    705    return false;
    706  }
    707 
    708  args.rval().setNumber(double(promise->getID()));
    709  return true;
    710 }
    711 
    712 bool DebuggerObject::CallData::promiseDependentPromisesGetter() {
    713  Debugger* dbg = object->owner();
    714 
    715  Rooted<PromiseObject*> promise(cx, EnsurePromise(cx, referent));
    716  if (!promise) {
    717    return false;
    718  }
    719 
    720  Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
    721  {
    722    JSAutoRealm ar(cx, promise);
    723    if (!promise->dependentPromises(cx, &values)) {
    724      return false;
    725    }
    726  }
    727  for (size_t i = 0; i < values.length(); i++) {
    728    if (!dbg->wrapDebuggeeValue(cx, values[i])) {
    729      return false;
    730    }
    731  }
    732  Rooted<ArrayObject*> promises(cx);
    733  if (values.length() == 0) {
    734    promises = NewDenseEmptyArray(cx);
    735  } else {
    736    promises = NewDenseCopiedArray(cx, values.length(), values[0].address());
    737  }
    738  if (!promises) {
    739    return false;
    740  }
    741  args.rval().setObject(*promises);
    742  return true;
    743 }
    744 
    745 bool DebuggerObject::CallData::isExtensibleMethod() {
    746  bool result;
    747  if (!DebuggerObject::isExtensible(cx, object, result)) {
    748    return false;
    749  }
    750 
    751  args.rval().setBoolean(result);
    752  return true;
    753 }
    754 
    755 bool DebuggerObject::CallData::isSealedMethod() {
    756  bool result;
    757  if (!DebuggerObject::isSealed(cx, object, result)) {
    758    return false;
    759  }
    760 
    761  args.rval().setBoolean(result);
    762  return true;
    763 }
    764 
    765 bool DebuggerObject::CallData::isFrozenMethod() {
    766  bool result;
    767  if (!DebuggerObject::isFrozen(cx, object, result)) {
    768    return false;
    769  }
    770 
    771  args.rval().setBoolean(result);
    772  return true;
    773 }
    774 
    775 bool DebuggerObject::CallData::getOwnPropertyNamesMethod() {
    776  RootedIdVector ids(cx);
    777  if (!DebuggerObject::getOwnPropertyNames(cx, object, &ids)) {
    778    return false;
    779  }
    780 
    781  JSObject* obj = IdVectorToArray(cx, ids);
    782  if (!obj) {
    783    return false;
    784  }
    785 
    786  args.rval().setObject(*obj);
    787  return true;
    788 }
    789 
    790 bool DebuggerObject::CallData::getOwnPropertyNamesLengthMethod() {
    791  size_t ownPropertiesLength;
    792  if (!DebuggerObject::getOwnPropertyNamesLength(cx, object,
    793                                                 &ownPropertiesLength)) {
    794    return false;
    795  }
    796 
    797  args.rval().setNumber(ownPropertiesLength);
    798  return true;
    799 }
    800 
    801 bool DebuggerObject::CallData::getOwnPropertySymbolsMethod() {
    802  RootedIdVector ids(cx);
    803  if (!DebuggerObject::getOwnPropertySymbols(cx, object, &ids)) {
    804    return false;
    805  }
    806 
    807  JSObject* obj = IdVectorToArray(cx, ids);
    808  if (!obj) {
    809    return false;
    810  }
    811 
    812  args.rval().setObject(*obj);
    813  return true;
    814 }
    815 
    816 bool DebuggerObject::CallData::getOwnPrivatePropertiesMethod() {
    817  RootedIdVector ids(cx);
    818  if (!DebuggerObject::getOwnPrivateProperties(cx, object, &ids)) {
    819    return false;
    820  }
    821 
    822  JSObject* obj = IdVectorToArray(cx, ids);
    823  if (!obj) {
    824    return false;
    825  }
    826 
    827  args.rval().setObject(*obj);
    828  return true;
    829 }
    830 
    831 bool DebuggerObject::CallData::getOwnPropertyDescriptorMethod() {
    832  RootedId id(cx);
    833  if (!ToPropertyKey(cx, args.get(0), &id)) {
    834    return false;
    835  }
    836 
    837  Rooted<Maybe<PropertyDescriptor>> desc(cx);
    838  if (!DebuggerObject::getOwnPropertyDescriptor(cx, object, id, &desc)) {
    839    return false;
    840  }
    841 
    842  return JS::FromPropertyDescriptor(cx, desc, args.rval());
    843 }
    844 
    845 bool DebuggerObject::CallData::preventExtensionsMethod() {
    846  if (!DebuggerObject::preventExtensions(cx, object)) {
    847    return false;
    848  }
    849 
    850  args.rval().setUndefined();
    851  return true;
    852 }
    853 
    854 bool DebuggerObject::CallData::sealMethod() {
    855  if (!DebuggerObject::seal(cx, object)) {
    856    return false;
    857  }
    858 
    859  args.rval().setUndefined();
    860  return true;
    861 }
    862 
    863 bool DebuggerObject::CallData::freezeMethod() {
    864  if (!DebuggerObject::freeze(cx, object)) {
    865    return false;
    866  }
    867 
    868  args.rval().setUndefined();
    869  return true;
    870 }
    871 
    872 bool DebuggerObject::CallData::definePropertyMethod() {
    873  if (!args.requireAtLeast(cx, "Debugger.Object.defineProperty", 2)) {
    874    return false;
    875  }
    876 
    877  RootedId id(cx);
    878  if (!ToPropertyKey(cx, args[0], &id)) {
    879    return false;
    880  }
    881 
    882  Rooted<PropertyDescriptor> desc(cx);
    883  if (!ToPropertyDescriptor(cx, args[1], false, &desc)) {
    884    return false;
    885  }
    886 
    887  if (!DebuggerObject::defineProperty(cx, object, id, desc)) {
    888    return false;
    889  }
    890 
    891  args.rval().setUndefined();
    892  return true;
    893 }
    894 
    895 bool DebuggerObject::CallData::definePropertiesMethod() {
    896  if (!args.requireAtLeast(cx, "Debugger.Object.defineProperties", 1)) {
    897    return false;
    898  }
    899 
    900  RootedValue arg(cx, args[0]);
    901  RootedObject props(cx, ToObject(cx, arg));
    902  if (!props) {
    903    return false;
    904  }
    905  RootedIdVector ids(cx);
    906  Rooted<PropertyDescriptorVector> descs(cx, PropertyDescriptorVector(cx));
    907  if (!ReadPropertyDescriptors(cx, props, false, &ids, &descs)) {
    908    return false;
    909  }
    910  Rooted<IdVector> ids2(cx, IdVector(cx));
    911  if (!ids2.append(ids.begin(), ids.end())) {
    912    return false;
    913  }
    914 
    915  if (!DebuggerObject::defineProperties(cx, object, ids2, descs)) {
    916    return false;
    917  }
    918 
    919  args.rval().setUndefined();
    920  return true;
    921 }
    922 
    923 /*
    924 * This does a non-strict delete, as a matter of API design. The case where the
    925 * property is non-configurable isn't necessarily exceptional here.
    926 */
    927 bool DebuggerObject::CallData::deletePropertyMethod() {
    928  RootedId id(cx);
    929  if (!ToPropertyKey(cx, args.get(0), &id)) {
    930    return false;
    931  }
    932 
    933  ObjectOpResult result;
    934  if (!DebuggerObject::deleteProperty(cx, object, id, result)) {
    935    return false;
    936  }
    937 
    938  args.rval().setBoolean(result.ok());
    939  return true;
    940 }
    941 
    942 bool DebuggerObject::CallData::callMethod() {
    943  RootedValue thisv(cx, args.get(0));
    944 
    945  Rooted<ValueVector> nargs(cx, ValueVector(cx));
    946  if (args.length() >= 2) {
    947    if (!nargs.growBy(args.length() - 1)) {
    948      return false;
    949    }
    950    for (size_t i = 1; i < args.length(); ++i) {
    951      nargs[i - 1].set(args[i]);
    952    }
    953  }
    954 
    955  Rooted<Maybe<Completion>> completion(
    956      cx, DebuggerObject::call(cx, object, thisv, nargs));
    957  if (!completion.get()) {
    958    return false;
    959  }
    960 
    961  return completion->buildCompletionValue(cx, object->owner(), args.rval());
    962 }
    963 
    964 bool DebuggerObject::CallData::getPropertyMethod() {
    965  Debugger* dbg = object->owner();
    966 
    967  RootedId id(cx);
    968  if (!ToPropertyKey(cx, args.get(0), &id)) {
    969    return false;
    970  }
    971 
    972  RootedValue receiver(cx,
    973                       args.length() < 2 ? ObjectValue(*object) : args.get(1));
    974 
    975  Rooted<Completion> comp(cx);
    976  JS_TRY_VAR_OR_RETURN_FALSE(cx, comp, getProperty(cx, object, id, receiver));
    977  return comp.get().buildCompletionValue(cx, dbg, args.rval());
    978 }
    979 
    980 bool DebuggerObject::CallData::setPropertyMethod() {
    981  Debugger* dbg = object->owner();
    982 
    983  RootedId id(cx);
    984  if (!ToPropertyKey(cx, args.get(0), &id)) {
    985    return false;
    986  }
    987 
    988  RootedValue value(cx, args.get(1));
    989 
    990  RootedValue receiver(cx,
    991                       args.length() < 3 ? ObjectValue(*object) : args.get(2));
    992 
    993  Rooted<Completion> comp(cx);
    994  JS_TRY_VAR_OR_RETURN_FALSE(cx, comp,
    995                             setProperty(cx, object, id, value, receiver));
    996  return comp.get().buildCompletionValue(cx, dbg, args.rval());
    997 }
    998 
    999 bool DebuggerObject::CallData::applyMethod() {
   1000  RootedValue thisv(cx, args.get(0));
   1001 
   1002  Rooted<ValueVector> nargs(cx, ValueVector(cx));
   1003  if (args.length() >= 2 && !args[1].isNullOrUndefined()) {
   1004    if (!args[1].isObject()) {
   1005      JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
   1006                                JSMSG_BAD_APPLY_ARGS, "apply");
   1007      return false;
   1008    }
   1009 
   1010    RootedObject argsobj(cx, &args[1].toObject());
   1011 
   1012    uint64_t argc = 0;
   1013    if (!GetLengthProperty(cx, argsobj, &argc)) {
   1014      return false;
   1015    }
   1016    argc = std::min(argc, uint64_t(ARGS_LENGTH_MAX));
   1017 
   1018    if (!nargs.growBy(argc) || !GetElements(cx, argsobj, argc, nargs.begin())) {
   1019      return false;
   1020    }
   1021  }
   1022 
   1023  Rooted<Maybe<Completion>> completion(
   1024      cx, DebuggerObject::call(cx, object, thisv, nargs));
   1025  if (!completion.get()) {
   1026    return false;
   1027  }
   1028 
   1029  return completion->buildCompletionValue(cx, object->owner(), args.rval());
   1030 }
   1031 
   1032 static void EnterDebuggeeObjectRealm(JSContext* cx, Maybe<AutoRealm>& ar,
   1033                                     JSObject* referent) {
   1034  // |referent| may be a cross-compartment wrapper and CCWs normally
   1035  // shouldn't be used with AutoRealm, but here we use an arbitrary realm for
   1036  // now because we don't really have another option.
   1037  ar.emplace(cx, referent->maybeCCWRealm()->maybeGlobal());
   1038 }
   1039 
   1040 static bool RequireGlobalObject(JSContext* cx, HandleValue dbgobj,
   1041                                HandleObject referent) {
   1042  RootedObject obj(cx, referent);
   1043 
   1044  if (!obj->is<GlobalObject>()) {
   1045    const char* isWrapper = "";
   1046    const char* isWindowProxy = "";
   1047 
   1048    // Help the poor programmer by pointing out wrappers around globals...
   1049    if (obj->is<WrapperObject>()) {
   1050      obj = js::UncheckedUnwrap(obj);
   1051      isWrapper = "a wrapper around ";
   1052    }
   1053 
   1054    // ... and WindowProxies around Windows.
   1055    if (IsWindowProxy(obj)) {
   1056      obj = ToWindowIfWindowProxy(obj);
   1057      isWindowProxy = "a WindowProxy referring to ";
   1058    }
   1059 
   1060    if (obj->is<GlobalObject>()) {
   1061      ReportValueError(cx, JSMSG_DEBUG_WRAPPER_IN_WAY, JSDVG_SEARCH_STACK,
   1062                       dbgobj, nullptr, isWrapper, isWindowProxy);
   1063    } else {
   1064      ReportValueError(cx, JSMSG_DEBUG_BAD_REFERENT, JSDVG_SEARCH_STACK, dbgobj,
   1065                       nullptr, "a global object");
   1066    }
   1067    return false;
   1068  }
   1069 
   1070  return true;
   1071 }
   1072 
   1073 bool DebuggerObject::CallData::asEnvironmentMethod() {
   1074  Debugger* dbg = object->owner();
   1075 
   1076  if (!RequireGlobalObject(cx, args.thisv(), referent)) {
   1077    return false;
   1078  }
   1079 
   1080  Rooted<Env*> env(cx);
   1081  {
   1082    AutoRealm ar(cx, referent);
   1083    env = GetDebugEnvironmentForGlobalLexicalEnvironment(cx);
   1084    if (!env) {
   1085      return false;
   1086    }
   1087  }
   1088 
   1089  return dbg->wrapEnvironment(cx, env, args.rval());
   1090 }
   1091 
   1092 // Lookup a binding on the referent's global scope and change it to undefined
   1093 // if it is an uninitialized lexical, otherwise do nothing. The method's
   1094 // JavaScript return value is true _only_ when an uninitialized lexical has been
   1095 // altered, otherwise it is false.
   1096 bool DebuggerObject::CallData::forceLexicalInitializationByNameMethod() {
   1097  if (!args.requireAtLeast(
   1098          cx, "Debugger.Object.prototype.forceLexicalInitializationByName",
   1099          1)) {
   1100    return false;
   1101  }
   1102 
   1103  if (!DebuggerObject::requireGlobal(cx, object)) {
   1104    return false;
   1105  }
   1106 
   1107  RootedId id(cx);
   1108  if (!ValueToIdentifier(cx, args[0], &id)) {
   1109    return false;
   1110  }
   1111 
   1112  bool result;
   1113  if (!DebuggerObject::forceLexicalInitializationByName(cx, object, id,
   1114                                                        result)) {
   1115    return false;
   1116  }
   1117 
   1118  args.rval().setBoolean(result);
   1119  return true;
   1120 }
   1121 
   1122 bool DebuggerObject::CallData::executeInGlobalMethod() {
   1123  if (!args.requireAtLeast(cx, "Debugger.Object.prototype.executeInGlobal",
   1124                           1)) {
   1125    return false;
   1126  }
   1127 
   1128  if (!DebuggerObject::requireGlobal(cx, object)) {
   1129    return false;
   1130  }
   1131 
   1132  AutoStableStringChars stableChars(cx);
   1133  if (!ValueToStableChars(cx, "Debugger.Object.prototype.executeInGlobal",
   1134                          args[0], stableChars)) {
   1135    return false;
   1136  }
   1137  mozilla::Range<const char16_t> chars = stableChars.twoByteRange();
   1138 
   1139  EvalOptions options(EvalOptions::EnvKind::Global);
   1140  if (!ParseEvalOptions(cx, args.get(1), options)) {
   1141    return false;
   1142  }
   1143 
   1144  Rooted<Completion> comp(cx);
   1145  JS_TRY_VAR_OR_RETURN_FALSE(
   1146      cx, comp,
   1147      DebuggerObject::executeInGlobal(cx, object, chars, nullptr, options));
   1148  return comp.get().buildCompletionValue(cx, object->owner(), args.rval());
   1149 }
   1150 
   1151 bool DebuggerObject::CallData::executeInGlobalWithBindingsMethod() {
   1152  if (!args.requireAtLeast(
   1153          cx, "Debugger.Object.prototype.executeInGlobalWithBindings", 2)) {
   1154    return false;
   1155  }
   1156 
   1157  if (!DebuggerObject::requireGlobal(cx, object)) {
   1158    return false;
   1159  }
   1160 
   1161  AutoStableStringChars stableChars(cx);
   1162  if (!ValueToStableChars(
   1163          cx, "Debugger.Object.prototype.executeInGlobalWithBindings", args[0],
   1164          stableChars)) {
   1165    return false;
   1166  }
   1167  mozilla::Range<const char16_t> chars = stableChars.twoByteRange();
   1168 
   1169  RootedObject bindings(cx, RequireObject(cx, args[1]));
   1170  if (!bindings) {
   1171    return false;
   1172  }
   1173 
   1174  EvalOptions options(EvalOptions::EnvKind::GlobalWithExtraOuterBindings);
   1175  if (!ParseEvalOptions(cx, args.get(2), options)) {
   1176    return false;
   1177  }
   1178 
   1179  Rooted<Completion> comp(cx);
   1180  JS_TRY_VAR_OR_RETURN_FALSE(
   1181      cx, comp,
   1182      DebuggerObject::executeInGlobal(cx, object, chars, bindings, options));
   1183  return comp.get().buildCompletionValue(cx, object->owner(), args.rval());
   1184 }
   1185 
   1186 // Copy a narrow or wide string to a vector, appending a null terminator.
   1187 template <typename T>
   1188 static bool CopyStringToVector(JSContext* cx, JSString* str, Vector<T>& chars) {
   1189  JSLinearString* linear = str->ensureLinear(cx);
   1190  if (!linear) {
   1191    return false;
   1192  }
   1193  if (!chars.appendN(0, linear->length() + 1)) {
   1194    return false;
   1195  }
   1196  CopyChars(chars.begin(), *linear);
   1197  return true;
   1198 }
   1199 
   1200 bool DebuggerObject::CallData::createSource() {
   1201  if (!args.requireAtLeast(cx, "Debugger.Object.prototype.createSource", 1)) {
   1202    return false;
   1203  }
   1204 
   1205  if (!DebuggerObject::requireGlobal(cx, object)) {
   1206    return false;
   1207  }
   1208 
   1209  Debugger* dbg = object->owner();
   1210  if (!dbg->isDebuggeeUnbarriered(referent->as<GlobalObject>().realm())) {
   1211    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
   1212                              JSMSG_DEBUG_NOT_DEBUGGEE, "Debugger.Object",
   1213                              "global");
   1214    return false;
   1215  }
   1216 
   1217  RootedObject options(cx, ToObject(cx, args[0]));
   1218  if (!options) {
   1219    return false;
   1220  }
   1221 
   1222  RootedValue v(cx);
   1223  if (!JS_GetProperty(cx, options, "text", &v)) {
   1224    return false;
   1225  }
   1226 
   1227  RootedString text(cx, ToString<CanGC>(cx, v));
   1228  if (!text) {
   1229    return false;
   1230  }
   1231 
   1232  if (!JS_GetProperty(cx, options, "url", &v)) {
   1233    return false;
   1234  }
   1235 
   1236  RootedString url(cx, ToString<CanGC>(cx, v));
   1237  if (!url) {
   1238    return false;
   1239  }
   1240 
   1241  if (!JS_GetProperty(cx, options, "startLine", &v)) {
   1242    return false;
   1243  }
   1244 
   1245  uint32_t startLine;
   1246  if (!ToUint32(cx, v, &startLine)) {
   1247    return false;
   1248  }
   1249 
   1250  if (!JS_GetProperty(cx, options, "startColumn", &v)) {
   1251    return false;
   1252  }
   1253 
   1254  uint32_t startColumn;
   1255  if (!ToUint32(cx, v, &startColumn)) {
   1256    return false;
   1257  }
   1258  if (startColumn == 0) {
   1259    startColumn = 1;
   1260  }
   1261 
   1262  if (!JS_GetProperty(cx, options, "sourceMapURL", &v)) {
   1263    return false;
   1264  }
   1265 
   1266  RootedString sourceMapURL(cx);
   1267  if (!v.isUndefined()) {
   1268    sourceMapURL = ToString<CanGC>(cx, v);
   1269    if (!sourceMapURL) {
   1270      return false;
   1271    }
   1272  }
   1273 
   1274  if (!JS_GetProperty(cx, options, "isScriptElement", &v)) {
   1275    return false;
   1276  }
   1277 
   1278  bool isScriptElement = ToBoolean(v);
   1279 
   1280  if (!JS_GetProperty(cx, options, "forceEnableAsmJS", &v)) {
   1281    return false;
   1282  }
   1283 
   1284  bool forceEnableAsmJS = ToBoolean(v);
   1285 
   1286  RootedScript script(cx);
   1287  {
   1288    AutoRealm ar(cx, referent);
   1289 
   1290    JS::CompileOptions compileOptions(cx);
   1291    compileOptions.lineno = startLine;
   1292    compileOptions.column = JS::ColumnNumberOneOrigin(startColumn);
   1293    if (forceEnableAsmJS) {
   1294      compileOptions.setAsmJSOption(JS::AsmJSOption::Enabled);
   1295    }
   1296 
   1297    if (!JS::StringHasLatin1Chars(url)) {
   1298      JS_ReportErrorASCII(cx, "URL must be a narrow string");
   1299      return false;
   1300    }
   1301 
   1302    UniqueChars urlChars = JS_EncodeStringToUTF8(cx, url);
   1303    if (!urlChars) {
   1304      return false;
   1305    }
   1306    compileOptions.setFile(urlChars.get());
   1307 
   1308    Vector<char16_t> sourceMapURLChars(cx);
   1309    if (sourceMapURL) {
   1310      if (!CopyStringToVector(cx, sourceMapURL, sourceMapURLChars)) {
   1311        return false;
   1312      }
   1313      compileOptions.setSourceMapURL(sourceMapURLChars.begin());
   1314    }
   1315 
   1316    if (isScriptElement) {
   1317      // The introduction type must be a statically allocated string.
   1318      compileOptions.setIntroductionType("inlineScript");
   1319    }
   1320 
   1321    AutoStableStringChars linearChars(cx);
   1322    if (!linearChars.initTwoByte(cx, text)) {
   1323      return false;
   1324    }
   1325    JS::SourceText<char16_t> srcBuf;
   1326    if (!srcBuf.initMaybeBorrowed(cx, linearChars)) {
   1327      return false;
   1328    }
   1329 
   1330    script = JS::Compile(cx, compileOptions, srcBuf);
   1331    if (!script) {
   1332      return false;
   1333    }
   1334  }
   1335 
   1336  Rooted<ScriptSourceObject*> sso(cx, script->sourceObject());
   1337  RootedObject wrapped(cx, dbg->wrapSource(cx, sso));
   1338  if (!wrapped) {
   1339    return false;
   1340  }
   1341 
   1342  args.rval().setObject(*wrapped);
   1343  return true;
   1344 }
   1345 
   1346 bool DebuggerObject::CallData::makeDebuggeeValueMethod() {
   1347  if (!args.requireAtLeast(cx, "Debugger.Object.prototype.makeDebuggeeValue",
   1348                           1)) {
   1349    return false;
   1350  }
   1351 
   1352  return DebuggerObject::makeDebuggeeValue(cx, object, args[0], args.rval());
   1353 }
   1354 
   1355 bool DebuggerObject::CallData::isSameNativeMethod() {
   1356  if (!args.requireAtLeast(cx, "Debugger.Object.prototype.isSameNative", 1)) {
   1357    return false;
   1358  }
   1359 
   1360  return DebuggerObject::isSameNative(cx, object, args[0], CheckJitInfo::No,
   1361                                      args.rval());
   1362 }
   1363 
   1364 bool DebuggerObject::CallData::isSameNativeWithJitInfoMethod() {
   1365  if (!args.requireAtLeast(
   1366          cx, "Debugger.Object.prototype.isSameNativeWithJitInfo", 1)) {
   1367    return false;
   1368  }
   1369 
   1370  return DebuggerObject::isSameNative(cx, object, args[0], CheckJitInfo::Yes,
   1371                                      args.rval());
   1372 }
   1373 
   1374 bool DebuggerObject::CallData::isNativeGetterWithJitInfo() {
   1375  return DebuggerObject::isNativeGetterWithJitInfo(cx, object, args.rval());
   1376 }
   1377 
   1378 bool DebuggerObject::CallData::unsafeDereferenceMethod() {
   1379  RootedObject result(cx);
   1380  if (!DebuggerObject::unsafeDereference(cx, object, &result)) {
   1381    return false;
   1382  }
   1383 
   1384  args.rval().setObject(*result);
   1385  return true;
   1386 }
   1387 
   1388 bool DebuggerObject::CallData::unwrapMethod() {
   1389  Rooted<DebuggerObject*> result(cx);
   1390  if (!DebuggerObject::unwrap(cx, object, &result)) {
   1391    return false;
   1392  }
   1393 
   1394  args.rval().setObjectOrNull(result);
   1395  return true;
   1396 }
   1397 
   1398 struct DebuggerObject::PromiseReactionRecordBuilder
   1399    : js::PromiseReactionRecordBuilder {
   1400  Debugger* dbg;
   1401  Handle<ArrayObject*> records;
   1402 
   1403  PromiseReactionRecordBuilder(Debugger* dbg, Handle<ArrayObject*> records)
   1404      : dbg(dbg), records(records) {}
   1405 
   1406  bool then(JSContext* cx, HandleObject resolve, HandleObject reject,
   1407            HandleObject result) override {
   1408    Rooted<PlainObject*> record(cx, NewPlainObject(cx));
   1409    if (!record) {
   1410      return false;
   1411    }
   1412 
   1413    if (!setIfNotNull(cx, record, cx->names().resolve, resolve) ||
   1414        !setIfNotNull(cx, record, cx->names().reject, reject) ||
   1415        !setIfNotNull(cx, record, cx->names().result, result)) {
   1416      return false;
   1417    }
   1418 
   1419    return push(cx, record);
   1420  }
   1421 
   1422  bool direct(JSContext* cx, Handle<PromiseObject*> unwrappedPromise) override {
   1423    RootedValue v(cx, ObjectValue(*unwrappedPromise));
   1424    return dbg->wrapDebuggeeValue(cx, &v) && push(cx, v);
   1425  }
   1426 
   1427  bool asyncFunction(
   1428      JSContext* cx,
   1429      Handle<AsyncFunctionGeneratorObject*> unwrappedGenerator) override {
   1430    return maybePushGenerator(cx, unwrappedGenerator);
   1431  }
   1432 
   1433  bool asyncGenerator(
   1434      JSContext* cx,
   1435      Handle<AsyncGeneratorObject*> unwrappedGenerator) override {
   1436    return maybePushGenerator(cx, unwrappedGenerator);
   1437  }
   1438 
   1439 private:
   1440  bool push(JSContext* cx, HandleObject record) {
   1441    RootedValue recordVal(cx, ObjectValue(*record));
   1442    return push(cx, recordVal);
   1443  }
   1444 
   1445  bool push(JSContext* cx, HandleValue recordVal) {
   1446    return NewbornArrayPush(cx, records, recordVal);
   1447  }
   1448 
   1449  bool maybePushGenerator(JSContext* cx,
   1450                          Handle<AbstractGeneratorObject*> unwrappedGenerator) {
   1451    Rooted<DebuggerFrame*> frame(cx);
   1452    if (unwrappedGenerator->isClosed()) {
   1453      // If the generator is closed, we can't generate a DebuggerFrame for it,
   1454      // so we ignore it.
   1455      return true;
   1456    }
   1457    if (!unwrappedGenerator->realm()->isDebuggee()) {
   1458      // Caller can keep the reference to the debugger object even after
   1459      // removing the realm from debuggee.  Do nothing for this case.
   1460      return true;
   1461    }
   1462    return dbg->getFrame(cx, unwrappedGenerator, &frame) && push(cx, frame);
   1463  }
   1464 
   1465  bool setIfNotNull(JSContext* cx, Handle<PlainObject*> obj,
   1466                    Handle<PropertyName*> name, HandleObject prop) {
   1467    if (!prop) {
   1468      return true;
   1469    }
   1470 
   1471    RootedValue v(cx, ObjectValue(*prop));
   1472    if (!dbg->wrapDebuggeeValue(cx, &v) ||
   1473        !DefineDataProperty(cx, obj, name, v)) {
   1474      return false;
   1475    }
   1476 
   1477    return true;
   1478  }
   1479 };
   1480 
   1481 bool DebuggerObject::CallData::getPromiseReactionsMethod() {
   1482  Debugger* dbg = object->owner();
   1483 
   1484  Rooted<PromiseObject*> unwrappedPromise(cx, EnsurePromise(cx, referent));
   1485  if (!unwrappedPromise) {
   1486    return false;
   1487  }
   1488 
   1489  Rooted<ArrayObject*> holder(cx, NewDenseEmptyArray(cx));
   1490  if (!holder) {
   1491    return false;
   1492  }
   1493 
   1494  PromiseReactionRecordBuilder builder(dbg, holder);
   1495  if (!unwrappedPromise->forEachReactionRecord(cx, builder)) {
   1496    return false;
   1497  }
   1498 
   1499  args.rval().setObject(*builder.records);
   1500  return true;
   1501 }
   1502 
   1503 const JSPropertySpec DebuggerObject::properties_[] = {
   1504    JS_DEBUG_PSG("callable", callableGetter),
   1505    JS_DEBUG_PSG("isBoundFunction", isBoundFunctionGetter),
   1506    JS_DEBUG_PSG("isArrowFunction", isArrowFunctionGetter),
   1507    JS_DEBUG_PSG("isGeneratorFunction", isGeneratorFunctionGetter),
   1508    JS_DEBUG_PSG("isAsyncFunction", isAsyncFunctionGetter),
   1509    JS_DEBUG_PSG("isClassConstructor", isClassConstructorGetter),
   1510    JS_DEBUG_PSG("proto", protoGetter),
   1511    JS_DEBUG_PSG("class", classGetter),
   1512    JS_DEBUG_PSG("name", nameGetter),
   1513    JS_DEBUG_PSG("displayName", displayNameGetter),
   1514    JS_DEBUG_PSG("parameterNames", parameterNamesGetter),
   1515    JS_DEBUG_PSG("script", scriptGetter),
   1516    JS_DEBUG_PSG("environment", environmentGetter),
   1517    JS_DEBUG_PSG("boundTargetFunction", boundTargetFunctionGetter),
   1518    JS_DEBUG_PSG("boundThis", boundThisGetter),
   1519    JS_DEBUG_PSG("boundArguments", boundArgumentsGetter),
   1520    JS_DEBUG_PSG("allocationSite", allocationSiteGetter),
   1521    JS_DEBUG_PSG("isError", isErrorGetter),
   1522    JS_DEBUG_PSG("isMutedError", isMutedErrorGetter),
   1523    JS_DEBUG_PSG("errorMessageName", errorMessageNameGetter),
   1524    JS_DEBUG_PSG("errorNotes", errorNotesGetter),
   1525    JS_DEBUG_PSG("errorLineNumber", errorLineNumberGetter),
   1526    JS_DEBUG_PSG("errorColumnNumber", errorColumnNumberGetter),
   1527    JS_DEBUG_PSG("isProxy", isProxyGetter),
   1528    JS_DEBUG_PSG("proxyTarget", proxyTargetGetter),
   1529    JS_DEBUG_PSG("proxyHandler", proxyHandlerGetter),
   1530    JS_PS_END,
   1531 };
   1532 
   1533 const JSPropertySpec DebuggerObject::promiseProperties_[] = {
   1534    JS_DEBUG_PSG("isPromise", isPromiseGetter),
   1535    JS_DEBUG_PSG("promiseState", promiseStateGetter),
   1536    JS_DEBUG_PSG("promiseValue", promiseValueGetter),
   1537    JS_DEBUG_PSG("promiseReason", promiseReasonGetter),
   1538    JS_DEBUG_PSG("promiseLifetime", promiseLifetimeGetter),
   1539    JS_DEBUG_PSG("promiseTimeToResolution", promiseTimeToResolutionGetter),
   1540    JS_DEBUG_PSG("promiseAllocationSite", promiseAllocationSiteGetter),
   1541    JS_DEBUG_PSG("promiseResolutionSite", promiseResolutionSiteGetter),
   1542    JS_DEBUG_PSG("promiseID", promiseIDGetter),
   1543    JS_DEBUG_PSG("promiseDependentPromises", promiseDependentPromisesGetter),
   1544    JS_PS_END,
   1545 };
   1546 
   1547 const JSFunctionSpec DebuggerObject::methods_[] = {
   1548    JS_DEBUG_FN("isExtensible", isExtensibleMethod, 0),
   1549    JS_DEBUG_FN("isSealed", isSealedMethod, 0),
   1550    JS_DEBUG_FN("isFrozen", isFrozenMethod, 0),
   1551    JS_DEBUG_FN("getProperty", getPropertyMethod, 0),
   1552    JS_DEBUG_FN("setProperty", setPropertyMethod, 0),
   1553    JS_DEBUG_FN("getOwnPropertyNames", getOwnPropertyNamesMethod, 0),
   1554    JS_DEBUG_FN("getOwnPropertyNamesLength", getOwnPropertyNamesLengthMethod,
   1555                0),
   1556    JS_DEBUG_FN("getOwnPropertySymbols", getOwnPropertySymbolsMethod, 0),
   1557    JS_DEBUG_FN("getOwnPrivateProperties", getOwnPrivatePropertiesMethod, 0),
   1558    JS_DEBUG_FN("getOwnPropertyDescriptor", getOwnPropertyDescriptorMethod, 1),
   1559    JS_DEBUG_FN("preventExtensions", preventExtensionsMethod, 0),
   1560    JS_DEBUG_FN("seal", sealMethod, 0),
   1561    JS_DEBUG_FN("freeze", freezeMethod, 0),
   1562    JS_DEBUG_FN("defineProperty", definePropertyMethod, 2),
   1563    JS_DEBUG_FN("defineProperties", definePropertiesMethod, 1),
   1564    JS_DEBUG_FN("deleteProperty", deletePropertyMethod, 1),
   1565    JS_DEBUG_FN("call", callMethod, 0),
   1566    JS_DEBUG_FN("apply", applyMethod, 0),
   1567    JS_DEBUG_FN("asEnvironment", asEnvironmentMethod, 0),
   1568    JS_DEBUG_FN("forceLexicalInitializationByName",
   1569                forceLexicalInitializationByNameMethod, 1),
   1570    JS_DEBUG_FN("executeInGlobal", executeInGlobalMethod, 1),
   1571    JS_DEBUG_FN("executeInGlobalWithBindings",
   1572                executeInGlobalWithBindingsMethod, 2),
   1573    JS_DEBUG_FN("createSource", createSource, 1),
   1574    JS_DEBUG_FN("makeDebuggeeValue", makeDebuggeeValueMethod, 1),
   1575    JS_DEBUG_FN("isSameNative", isSameNativeMethod, 1),
   1576    JS_DEBUG_FN("isSameNativeWithJitInfo", isSameNativeWithJitInfoMethod, 1),
   1577    JS_DEBUG_FN("isNativeGetterWithJitInfo", isNativeGetterWithJitInfo, 1),
   1578    JS_DEBUG_FN("unsafeDereference", unsafeDereferenceMethod, 0),
   1579    JS_DEBUG_FN("unwrap", unwrapMethod, 0),
   1580    JS_DEBUG_FN("getPromiseReactions", getPromiseReactionsMethod, 0),
   1581    JS_FS_END,
   1582 };
   1583 
   1584 /* static */
   1585 NativeObject* DebuggerObject::initClass(JSContext* cx,
   1586                                        Handle<GlobalObject*> global,
   1587                                        HandleObject debugCtor) {
   1588  Rooted<NativeObject*> objectProto(
   1589      cx, InitClass(cx, debugCtor, nullptr, nullptr, "Object", construct, 0,
   1590                    properties_, methods_, nullptr, nullptr));
   1591 
   1592  if (!objectProto) {
   1593    return nullptr;
   1594  }
   1595 
   1596  if (!DefinePropertiesAndFunctions(cx, objectProto, promiseProperties_,
   1597                                    nullptr)) {
   1598    return nullptr;
   1599  }
   1600 
   1601  return objectProto;
   1602 }
   1603 
   1604 /* static */
   1605 DebuggerObject* DebuggerObject::create(JSContext* cx, HandleObject proto,
   1606                                       HandleObject referent,
   1607                                       Handle<NativeObject*> debugger) {
   1608  DebuggerObject* obj =
   1609      IsInsideNursery(referent)
   1610          ? NewObjectWithGivenProto<DebuggerObject>(cx, proto)
   1611          : NewTenuredObjectWithGivenProto<DebuggerObject>(cx, proto);
   1612  if (!obj) {
   1613    return nullptr;
   1614  }
   1615 
   1616  obj->setReservedSlotGCThingAsPrivate(OBJECT_SLOT, referent);
   1617  obj->setReservedSlot(OWNER_SLOT, ObjectValue(*debugger));
   1618 
   1619  return obj;
   1620 }
   1621 
   1622 bool DebuggerObject::isCallable() const { return referent()->isCallable(); }
   1623 
   1624 bool DebuggerObject::isFunction() const { return referent()->is<JSFunction>(); }
   1625 
   1626 bool DebuggerObject::isDebuggeeFunction() const {
   1627  return referent()->is<JSFunction>() &&
   1628         owner()->observesGlobal(&referent()->as<JSFunction>().global());
   1629 }
   1630 
   1631 bool DebuggerObject::isBoundFunction() const {
   1632  return referent()->is<BoundFunctionObject>();
   1633 }
   1634 
   1635 bool DebuggerObject::isDebuggeeBoundFunction() const {
   1636  return referent()->is<BoundFunctionObject>() &&
   1637         owner()->observesGlobal(
   1638             &referent()->as<BoundFunctionObject>().global());
   1639 }
   1640 
   1641 bool DebuggerObject::isArrowFunction() const {
   1642  MOZ_ASSERT(isDebuggeeFunction());
   1643 
   1644  return referent()->as<JSFunction>().isArrow();
   1645 }
   1646 
   1647 bool DebuggerObject::isAsyncFunction() const {
   1648  MOZ_ASSERT(isDebuggeeFunction());
   1649 
   1650  return referent()->as<JSFunction>().isAsync();
   1651 }
   1652 
   1653 bool DebuggerObject::isGeneratorFunction() const {
   1654  MOZ_ASSERT(isDebuggeeFunction());
   1655 
   1656  return referent()->as<JSFunction>().isGenerator();
   1657 }
   1658 
   1659 bool DebuggerObject::isClassConstructor() const {
   1660  MOZ_ASSERT(isDebuggeeFunction());
   1661 
   1662  return referent()->as<JSFunction>().isClassConstructor();
   1663 }
   1664 
   1665 bool DebuggerObject::isGlobal() const { return referent()->is<GlobalObject>(); }
   1666 
   1667 bool DebuggerObject::isScriptedProxy() const {
   1668  return js::IsScriptedProxy(referent());
   1669 }
   1670 
   1671 bool DebuggerObject::isPromise() const {
   1672  JSObject* referent = this->referent();
   1673 
   1674  if (IsCrossCompartmentWrapper(referent)) {
   1675    // We only care about promises, so CheckedUnwrapStatic is OK.
   1676    referent = CheckedUnwrapStatic(referent);
   1677    if (!referent) {
   1678      return false;
   1679    }
   1680  }
   1681 
   1682  return referent->is<PromiseObject>();
   1683 }
   1684 
   1685 bool DebuggerObject::isError() const {
   1686  JSObject* referent = this->referent();
   1687 
   1688  if (IsCrossCompartmentWrapper(referent)) {
   1689    // We only check for error classes, so CheckedUnwrapStatic is OK.
   1690    referent = CheckedUnwrapStatic(referent);
   1691    if (!referent) {
   1692      return false;
   1693    }
   1694  }
   1695 
   1696  return referent->is<ErrorObject>();
   1697 }
   1698 
   1699 bool DebuggerObject::isMutedError(JSContext* cx) const {
   1700  JS::Rooted<JSObject*> referent(cx, this->referent());
   1701 
   1702  if (IsCrossCompartmentWrapper(referent)) {
   1703    // We only check for error classes, so CheckedUnwrapStatic is OK.
   1704    referent = CheckedUnwrapStatic(referent);
   1705    if (!referent) {
   1706      return false;
   1707    }
   1708  }
   1709 
   1710  if (!referent->is<ErrorObject>()) {
   1711    return false;
   1712  }
   1713 
   1714  JSErrorReport* report = referent->as<ErrorObject>().getErrorReport();
   1715  if (!report) {
   1716    // If the error report was missing, isMuted field can never be true,
   1717    // and just returning false is OK.
   1718    return false;
   1719  }
   1720 
   1721  return report->isMuted;
   1722 }
   1723 
   1724 /* static */
   1725 bool DebuggerObject::getClassName(JSContext* cx, Handle<DebuggerObject*> object,
   1726                                  MutableHandleString result) {
   1727  RootedObject referent(cx, object->referent());
   1728 
   1729  const char* className;
   1730  {
   1731    Maybe<AutoRealm> ar;
   1732    EnterDebuggeeObjectRealm(cx, ar, referent);
   1733    className = GetObjectClassName(cx, referent);
   1734  }
   1735 
   1736  JSAtom* str = Atomize(cx, className, strlen(className));
   1737  if (!str) {
   1738    return false;
   1739  }
   1740 
   1741  result.set(str);
   1742  return true;
   1743 }
   1744 
   1745 bool DebuggerObject::name(JSContext* cx,
   1746                          JS::MutableHandle<JSAtom*> result) const {
   1747  if (isFunction()) {
   1748    JSFunction* fun = &referent()->as<JSFunction>();
   1749    if (!fun->isAccessorWithLazyName()) {
   1750      result.set(fun->fullExplicitName());
   1751      if (result) {
   1752        cx->markAtom(result);
   1753      }
   1754      return true;
   1755    }
   1756 
   1757    {
   1758      Maybe<AutoRealm> ar;
   1759      EnterDebuggeeObjectRealm(cx, ar, fun);
   1760 
   1761      result.set(fun->getAccessorNameForLazy(cx));
   1762      if (!result) {
   1763        return false;
   1764      }
   1765    }
   1766    cx->markAtom(result);
   1767    return true;
   1768  }
   1769 
   1770  MOZ_ASSERT(isBoundFunction());
   1771 
   1772  // Bound functions have a configurable `name` data property and currently
   1773  // don't store the original name. Try a pure lookup to get this name and if
   1774  // this fails use "bound".
   1775  Rooted<BoundFunctionObject*> bound(cx,
   1776                                     &referent()->as<BoundFunctionObject>());
   1777  {
   1778    Maybe<AutoRealm> ar;
   1779    EnterDebuggeeObjectRealm(cx, ar, bound);
   1780 
   1781    Value v;
   1782    bool found;
   1783    if (GetOwnPropertyPure(cx, bound, NameToId(cx->names().name), &v, &found) &&
   1784        found && v.isString()) {
   1785      result.set(AtomizeString(cx, v.toString()));
   1786      if (!result) {
   1787        return false;
   1788      }
   1789    } else {
   1790      result.set(cx->names().bound);
   1791    }
   1792  }
   1793 
   1794  cx->markAtom(result);
   1795  return true;
   1796 }
   1797 
   1798 bool DebuggerObject::displayName(JSContext* cx,
   1799                                 JS::MutableHandle<JSAtom*> result) const {
   1800  if (isFunction()) {
   1801    {
   1802      JS::Rooted<JSFunction*> fun(cx, &referent()->as<JSFunction>());
   1803 
   1804      Maybe<AutoRealm> ar;
   1805      EnterDebuggeeObjectRealm(cx, ar, fun);
   1806 
   1807      if (!fun->getDisplayAtom(cx, result)) {
   1808        return false;
   1809      }
   1810    }
   1811    if (result) {
   1812      cx->markAtom(result);
   1813    }
   1814    return true;
   1815  }
   1816 
   1817  MOZ_ASSERT(isBoundFunction());
   1818  return name(cx, result);
   1819 }
   1820 
   1821 JS::PromiseState DebuggerObject::promiseState() const {
   1822  return promise()->state();
   1823 }
   1824 
   1825 double DebuggerObject::promiseLifetime() const { return promise()->lifetime(); }
   1826 
   1827 double DebuggerObject::promiseTimeToResolution() const {
   1828  MOZ_ASSERT(promiseState() != JS::PromiseState::Pending);
   1829 
   1830  return promise()->timeToResolution();
   1831 }
   1832 
   1833 /* static */
   1834 bool DebuggerObject::getBoundTargetFunction(
   1835    JSContext* cx, Handle<DebuggerObject*> object,
   1836    MutableHandle<DebuggerObject*> result) {
   1837  MOZ_ASSERT(object->isBoundFunction());
   1838 
   1839  Rooted<BoundFunctionObject*> referent(
   1840      cx, &object->referent()->as<BoundFunctionObject>());
   1841  Debugger* dbg = object->owner();
   1842 
   1843  RootedObject target(cx, referent->getTarget());
   1844  return dbg->wrapDebuggeeObject(cx, target, result);
   1845 }
   1846 
   1847 /* static */
   1848 bool DebuggerObject::getBoundThis(JSContext* cx, Handle<DebuggerObject*> object,
   1849                                  MutableHandleValue result) {
   1850  MOZ_ASSERT(object->isBoundFunction());
   1851 
   1852  Rooted<BoundFunctionObject*> referent(
   1853      cx, &object->referent()->as<BoundFunctionObject>());
   1854  Debugger* dbg = object->owner();
   1855 
   1856  result.set(referent->getBoundThis());
   1857  return dbg->wrapDebuggeeValue(cx, result);
   1858 }
   1859 
   1860 /* static */
   1861 bool DebuggerObject::getBoundArguments(JSContext* cx,
   1862                                       Handle<DebuggerObject*> object,
   1863                                       MutableHandle<ValueVector> result) {
   1864  MOZ_ASSERT(object->isBoundFunction());
   1865 
   1866  Rooted<BoundFunctionObject*> referent(
   1867      cx, &object->referent()->as<BoundFunctionObject>());
   1868  Debugger* dbg = object->owner();
   1869 
   1870  size_t length = referent->numBoundArgs();
   1871  if (!result.resize(length)) {
   1872    return false;
   1873  }
   1874  for (size_t i = 0; i < length; i++) {
   1875    result[i].set(referent->getBoundArg(i));
   1876    if (!dbg->wrapDebuggeeValue(cx, result[i])) {
   1877      return false;
   1878    }
   1879  }
   1880  return true;
   1881 }
   1882 
   1883 /* static */
   1884 SavedFrame* Debugger::getObjectAllocationSite(JSObject& obj) {
   1885  JSObject* metadata = GetAllocationMetadata(&obj);
   1886  if (!metadata) {
   1887    return nullptr;
   1888  }
   1889 
   1890  MOZ_ASSERT(!metadata->is<WrapperObject>());
   1891  return metadata->is<SavedFrame>() ? &metadata->as<SavedFrame>() : nullptr;
   1892 }
   1893 
   1894 /* static */
   1895 bool DebuggerObject::getAllocationSite(JSContext* cx,
   1896                                       Handle<DebuggerObject*> object,
   1897                                       MutableHandleObject result) {
   1898  RootedObject referent(cx, object->referent());
   1899 
   1900  RootedObject allocSite(cx, Debugger::getObjectAllocationSite(*referent));
   1901  if (!cx->compartment()->wrap(cx, &allocSite)) {
   1902    return false;
   1903  }
   1904 
   1905  result.set(allocSite);
   1906  return true;
   1907 }
   1908 
   1909 /* static */
   1910 bool DebuggerObject::getErrorReport(JSContext* cx, HandleObject maybeError,
   1911                                    JSErrorReport*& report) {
   1912  JSObject* obj = maybeError;
   1913  if (IsCrossCompartmentWrapper(obj)) {
   1914    /* We only care about Error objects, so CheckedUnwrapStatic is OK. */
   1915    obj = CheckedUnwrapStatic(obj);
   1916  }
   1917 
   1918  if (!obj) {
   1919    ReportAccessDenied(cx);
   1920    return false;
   1921  }
   1922 
   1923  if (!obj->is<ErrorObject>()) {
   1924    report = nullptr;
   1925    return true;
   1926  }
   1927 
   1928  report = obj->as<ErrorObject>().getErrorReport();
   1929  return true;
   1930 }
   1931 
   1932 /* static */
   1933 bool DebuggerObject::getErrorMessageName(JSContext* cx,
   1934                                         Handle<DebuggerObject*> object,
   1935                                         MutableHandleString result) {
   1936  RootedObject referent(cx, object->referent());
   1937  JSErrorReport* report;
   1938  if (!getErrorReport(cx, referent, report)) {
   1939    return false;
   1940  }
   1941 
   1942  if (!report || !report->errorMessageName) {
   1943    result.set(nullptr);
   1944    return true;
   1945  }
   1946 
   1947  RootedString str(cx, JS_NewStringCopyZ(cx, report->errorMessageName));
   1948  if (!str) {
   1949    return false;
   1950  }
   1951  result.set(str);
   1952  return true;
   1953 }
   1954 
   1955 /* static */
   1956 bool DebuggerObject::getErrorNotes(JSContext* cx,
   1957                                   Handle<DebuggerObject*> object,
   1958                                   MutableHandleValue result) {
   1959  RootedObject referent(cx, object->referent());
   1960  JSErrorReport* report;
   1961  if (!getErrorReport(cx, referent, report)) {
   1962    return false;
   1963  }
   1964 
   1965  if (!report) {
   1966    result.setUndefined();
   1967    return true;
   1968  }
   1969 
   1970  RootedObject errorNotesArray(cx, CreateErrorNotesArray(cx, report));
   1971  if (!errorNotesArray) {
   1972    return false;
   1973  }
   1974 
   1975  if (!cx->compartment()->wrap(cx, &errorNotesArray)) {
   1976    return false;
   1977  }
   1978  result.setObject(*errorNotesArray);
   1979  return true;
   1980 }
   1981 
   1982 /* static */
   1983 bool DebuggerObject::getErrorLineNumber(JSContext* cx,
   1984                                        Handle<DebuggerObject*> object,
   1985                                        MutableHandleValue result) {
   1986  RootedObject referent(cx, object->referent());
   1987  JSErrorReport* report;
   1988  if (!getErrorReport(cx, referent, report)) {
   1989    return false;
   1990  }
   1991 
   1992  if (!report) {
   1993    result.setUndefined();
   1994    return true;
   1995  }
   1996 
   1997  result.setNumber(report->lineno);
   1998  return true;
   1999 }
   2000 
   2001 /* static */
   2002 bool DebuggerObject::getErrorColumnNumber(JSContext* cx,
   2003                                          Handle<DebuggerObject*> object,
   2004                                          MutableHandleValue result) {
   2005  RootedObject referent(cx, object->referent());
   2006  JSErrorReport* report;
   2007  if (!getErrorReport(cx, referent, report)) {
   2008    return false;
   2009  }
   2010 
   2011  if (!report) {
   2012    result.setUndefined();
   2013    return true;
   2014  }
   2015 
   2016  result.setNumber(report->column.oneOriginValue());
   2017  return true;
   2018 }
   2019 
   2020 /* static */
   2021 bool DebuggerObject::getPromiseValue(JSContext* cx,
   2022                                     Handle<DebuggerObject*> object,
   2023                                     MutableHandleValue result) {
   2024  MOZ_ASSERT(object->promiseState() == JS::PromiseState::Fulfilled);
   2025 
   2026  result.set(object->promise()->value());
   2027  return object->owner()->wrapDebuggeeValue(cx, result);
   2028 }
   2029 
   2030 /* static */
   2031 bool DebuggerObject::getPromiseReason(JSContext* cx,
   2032                                      Handle<DebuggerObject*> object,
   2033                                      MutableHandleValue result) {
   2034  MOZ_ASSERT(object->promiseState() == JS::PromiseState::Rejected);
   2035 
   2036  result.set(object->promise()->reason());
   2037  return object->owner()->wrapDebuggeeValue(cx, result);
   2038 }
   2039 
   2040 /* static */
   2041 bool DebuggerObject::isExtensible(JSContext* cx, Handle<DebuggerObject*> object,
   2042                                  bool& result) {
   2043  RootedObject referent(cx, object->referent());
   2044 
   2045  Maybe<AutoRealm> ar;
   2046  EnterDebuggeeObjectRealm(cx, ar, referent);
   2047 
   2048  ErrorCopier ec(ar);
   2049  return IsExtensible(cx, referent, &result);
   2050 }
   2051 
   2052 /* static */
   2053 bool DebuggerObject::isSealed(JSContext* cx, Handle<DebuggerObject*> object,
   2054                              bool& result) {
   2055  RootedObject referent(cx, object->referent());
   2056 
   2057  Maybe<AutoRealm> ar;
   2058  EnterDebuggeeObjectRealm(cx, ar, referent);
   2059 
   2060  ErrorCopier ec(ar);
   2061  return TestIntegrityLevel(cx, referent, IntegrityLevel::Sealed, &result);
   2062 }
   2063 
   2064 /* static */
   2065 bool DebuggerObject::isFrozen(JSContext* cx, Handle<DebuggerObject*> object,
   2066                              bool& result) {
   2067  RootedObject referent(cx, object->referent());
   2068 
   2069  Maybe<AutoRealm> ar;
   2070  EnterDebuggeeObjectRealm(cx, ar, referent);
   2071 
   2072  ErrorCopier ec(ar);
   2073  return TestIntegrityLevel(cx, referent, IntegrityLevel::Frozen, &result);
   2074 }
   2075 
   2076 /* static */
   2077 bool DebuggerObject::getPrototypeOf(JSContext* cx,
   2078                                    Handle<DebuggerObject*> object,
   2079                                    MutableHandle<DebuggerObject*> result) {
   2080  RootedObject referent(cx, object->referent());
   2081  Debugger* dbg = object->owner();
   2082 
   2083  RootedObject proto(cx);
   2084  {
   2085    Maybe<AutoRealm> ar;
   2086    EnterDebuggeeObjectRealm(cx, ar, referent);
   2087    if (!GetPrototype(cx, referent, &proto)) {
   2088      return false;
   2089    }
   2090  }
   2091 
   2092  return dbg->wrapNullableDebuggeeObject(cx, proto, result);
   2093 }
   2094 
   2095 /* static */
   2096 bool DebuggerObject::getOwnPropertyNames(JSContext* cx,
   2097                                         Handle<DebuggerObject*> object,
   2098                                         MutableHandleIdVector result) {
   2099  MOZ_ASSERT(result.empty());
   2100 
   2101  RootedObject referent(cx, object->referent());
   2102  {
   2103    Maybe<AutoRealm> ar;
   2104    EnterDebuggeeObjectRealm(cx, ar, referent);
   2105 
   2106    ErrorCopier ec(ar);
   2107    if (!GetPropertyKeys(cx, referent, JSITER_OWNONLY | JSITER_HIDDEN,
   2108                         result)) {
   2109      return false;
   2110    }
   2111  }
   2112 
   2113  for (size_t i = 0; i < result.length(); i++) {
   2114    cx->markId(result[i]);
   2115  }
   2116 
   2117  return true;
   2118 }
   2119 
   2120 /* static */
   2121 bool DebuggerObject::getOwnPropertyNamesLength(JSContext* cx,
   2122                                               Handle<DebuggerObject*> object,
   2123                                               size_t* result) {
   2124  RootedObject referent(cx, object->referent());
   2125 
   2126  RootedIdVector ids(cx);
   2127  {
   2128    Maybe<AutoRealm> ar;
   2129    EnterDebuggeeObjectRealm(cx, ar, referent);
   2130 
   2131    ErrorCopier ec(ar);
   2132    if (!GetPropertyKeys(cx, referent, JSITER_OWNONLY | JSITER_HIDDEN, &ids)) {
   2133      return false;
   2134    }
   2135  }
   2136 
   2137  *result = ids.length();
   2138  return true;
   2139 }
   2140 
   2141 static bool GetSymbolPropertyKeys(JSContext* cx, Handle<DebuggerObject*> object,
   2142                                  JS::MutableHandleIdVector props,
   2143                                  bool includePrivate) {
   2144  RootedObject referent(cx, object->referent());
   2145 
   2146  {
   2147    Maybe<AutoRealm> ar;
   2148    EnterDebuggeeObjectRealm(cx, ar, referent);
   2149 
   2150    ErrorCopier ec(ar);
   2151 
   2152    unsigned flags =
   2153        JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS | JSITER_SYMBOLSONLY;
   2154    if (includePrivate) {
   2155      flags = flags | JSITER_PRIVATE;
   2156    }
   2157    if (!GetPropertyKeys(cx, referent, flags, props)) {
   2158      return false;
   2159    }
   2160  }
   2161 
   2162  return true;
   2163 }
   2164 
   2165 /* static */
   2166 bool DebuggerObject::getOwnPropertySymbols(JSContext* cx,
   2167                                           Handle<DebuggerObject*> object,
   2168                                           MutableHandleIdVector result) {
   2169  MOZ_ASSERT(result.empty());
   2170 
   2171  if (!GetSymbolPropertyKeys(cx, object, result, false)) {
   2172    return false;
   2173  }
   2174 
   2175  for (size_t i = 0; i < result.length(); i++) {
   2176    cx->markAtom(result[i].toSymbol());
   2177  }
   2178 
   2179  return true;
   2180 }
   2181 
   2182 /* static */
   2183 bool DebuggerObject::getOwnPrivateProperties(JSContext* cx,
   2184                                             Handle<DebuggerObject*> object,
   2185                                             MutableHandleIdVector result) {
   2186  MOZ_ASSERT(result.empty());
   2187 
   2188  if (!GetSymbolPropertyKeys(cx, object, result, true)) {
   2189    return false;
   2190  }
   2191 
   2192  result.eraseIf([](PropertyKey key) {
   2193    if (!key.isPrivateName()) {
   2194      return true;
   2195    }
   2196    // Private *methods* create a Private Brand, a special private name
   2197    // stamped onto the symbol, to indicate it is possible to execute private
   2198    // methods from the class on this object. We don't want to return such
   2199    // items here, so we check if we're dealing with a private property, e.g.
   2200    // the Symbol description starts with a "#" character.
   2201    JSAtom* privateDescription = key.toSymbol()->description();
   2202    if (privateDescription->length() == 0) {
   2203      return true;
   2204    }
   2205    char16_t firstChar = privateDescription->latin1OrTwoByteChar(0);
   2206    return firstChar != '#';
   2207  });
   2208 
   2209  for (size_t i = 0; i < result.length(); i++) {
   2210    cx->markAtom(result[i].toSymbol());
   2211  }
   2212 
   2213  return true;
   2214 }
   2215 
   2216 /* static */
   2217 bool DebuggerObject::getOwnPropertyDescriptor(
   2218    JSContext* cx, Handle<DebuggerObject*> object, HandleId id,
   2219    MutableHandle<Maybe<PropertyDescriptor>> desc_) {
   2220  RootedObject referent(cx, object->referent());
   2221  Debugger* dbg = object->owner();
   2222 
   2223  // Bug: This can cause the debuggee to run!
   2224  {
   2225    Maybe<AutoRealm> ar;
   2226    EnterDebuggeeObjectRealm(cx, ar, referent);
   2227 
   2228    cx->markId(id);
   2229 
   2230    ErrorCopier ec(ar);
   2231    if (!GetOwnPropertyDescriptor(cx, referent, id, desc_)) {
   2232      return false;
   2233    }
   2234  }
   2235 
   2236  if (desc_.isSome()) {
   2237    Rooted<PropertyDescriptor> desc(cx, *desc_);
   2238 
   2239    if (desc.hasValue()) {
   2240      // Rewrap the debuggee values in desc for the debugger.
   2241      if (!dbg->wrapDebuggeeValue(cx, desc.value())) {
   2242        return false;
   2243      }
   2244    }
   2245    if (desc.hasGetter()) {
   2246      RootedValue get(cx, ObjectOrNullValue(desc.getter()));
   2247      if (!dbg->wrapDebuggeeValue(cx, &get)) {
   2248        return false;
   2249      }
   2250      desc.setGetter(get.toObjectOrNull());
   2251    }
   2252    if (desc.hasSetter()) {
   2253      RootedValue set(cx, ObjectOrNullValue(desc.setter()));
   2254      if (!dbg->wrapDebuggeeValue(cx, &set)) {
   2255        return false;
   2256      }
   2257      desc.setSetter(set.toObjectOrNull());
   2258    }
   2259 
   2260    desc_.set(mozilla::Some(desc.get()));
   2261  }
   2262 
   2263  return true;
   2264 }
   2265 
   2266 /* static */
   2267 bool DebuggerObject::preventExtensions(JSContext* cx,
   2268                                       Handle<DebuggerObject*> object) {
   2269  RootedObject referent(cx, object->referent());
   2270 
   2271  Maybe<AutoRealm> ar;
   2272  EnterDebuggeeObjectRealm(cx, ar, referent);
   2273 
   2274  ErrorCopier ec(ar);
   2275  return PreventExtensions(cx, referent);
   2276 }
   2277 
   2278 /* static */
   2279 bool DebuggerObject::seal(JSContext* cx, Handle<DebuggerObject*> object) {
   2280  RootedObject referent(cx, object->referent());
   2281 
   2282  Maybe<AutoRealm> ar;
   2283  EnterDebuggeeObjectRealm(cx, ar, referent);
   2284 
   2285  ErrorCopier ec(ar);
   2286  return SetIntegrityLevel(cx, referent, IntegrityLevel::Sealed);
   2287 }
   2288 
   2289 /* static */
   2290 bool DebuggerObject::freeze(JSContext* cx, Handle<DebuggerObject*> object) {
   2291  RootedObject referent(cx, object->referent());
   2292 
   2293  Maybe<AutoRealm> ar;
   2294  EnterDebuggeeObjectRealm(cx, ar, referent);
   2295 
   2296  ErrorCopier ec(ar);
   2297  return SetIntegrityLevel(cx, referent, IntegrityLevel::Frozen);
   2298 }
   2299 
   2300 /* static */
   2301 bool DebuggerObject::defineProperty(JSContext* cx,
   2302                                    Handle<DebuggerObject*> object, HandleId id,
   2303                                    Handle<PropertyDescriptor> desc_) {
   2304  RootedObject referent(cx, object->referent());
   2305  Debugger* dbg = object->owner();
   2306 
   2307  Rooted<PropertyDescriptor> desc(cx, desc_);
   2308  if (!dbg->unwrapPropertyDescriptor(cx, referent, &desc)) {
   2309    return false;
   2310  }
   2311  JS_TRY_OR_RETURN_FALSE(cx, CheckPropertyDescriptorAccessors(cx, desc));
   2312 
   2313  Maybe<AutoRealm> ar;
   2314  EnterDebuggeeObjectRealm(cx, ar, referent);
   2315 
   2316  if (!cx->compartment()->wrap(cx, &desc)) {
   2317    return false;
   2318  }
   2319  cx->markId(id);
   2320 
   2321  ErrorCopier ec(ar);
   2322  return DefineProperty(cx, referent, id, desc);
   2323 }
   2324 
   2325 /* static */
   2326 bool DebuggerObject::defineProperties(JSContext* cx,
   2327                                      Handle<DebuggerObject*> object,
   2328                                      Handle<IdVector> ids,
   2329                                      Handle<PropertyDescriptorVector> descs_) {
   2330  RootedObject referent(cx, object->referent());
   2331  Debugger* dbg = object->owner();
   2332 
   2333  Rooted<PropertyDescriptorVector> descs(cx, PropertyDescriptorVector(cx));
   2334  if (!descs.append(descs_.begin(), descs_.end())) {
   2335    return false;
   2336  }
   2337  for (size_t i = 0; i < descs.length(); i++) {
   2338    if (!dbg->unwrapPropertyDescriptor(cx, referent, descs[i])) {
   2339      return false;
   2340    }
   2341    JS_TRY_OR_RETURN_FALSE(cx, CheckPropertyDescriptorAccessors(cx, descs[i]));
   2342  }
   2343 
   2344  Maybe<AutoRealm> ar;
   2345  EnterDebuggeeObjectRealm(cx, ar, referent);
   2346 
   2347  for (size_t i = 0; i < descs.length(); i++) {
   2348    if (!cx->compartment()->wrap(cx, descs[i])) {
   2349      return false;
   2350    }
   2351    cx->markId(ids[i]);
   2352  }
   2353 
   2354  ErrorCopier ec(ar);
   2355  for (size_t i = 0; i < descs.length(); i++) {
   2356    if (!DefineProperty(cx, referent, ids[i], descs[i])) {
   2357      return false;
   2358    }
   2359  }
   2360 
   2361  return true;
   2362 }
   2363 
   2364 /* static */
   2365 bool DebuggerObject::deleteProperty(JSContext* cx,
   2366                                    Handle<DebuggerObject*> object, HandleId id,
   2367                                    ObjectOpResult& result) {
   2368  RootedObject referent(cx, object->referent());
   2369 
   2370  Maybe<AutoRealm> ar;
   2371  EnterDebuggeeObjectRealm(cx, ar, referent);
   2372 
   2373  cx->markId(id);
   2374 
   2375  ErrorCopier ec(ar);
   2376  return DeleteProperty(cx, referent, id, result);
   2377 }
   2378 
   2379 /* static */
   2380 Result<Completion> DebuggerObject::getProperty(JSContext* cx,
   2381                                               Handle<DebuggerObject*> object,
   2382                                               HandleId id,
   2383                                               HandleValue receiver_) {
   2384  RootedObject referent(cx, object->referent());
   2385  Debugger* dbg = object->owner();
   2386 
   2387  // Unwrap Debugger.Objects. This happens in the debugger's compartment since
   2388  // that is where any exceptions must be reported.
   2389  RootedValue receiver(cx, receiver_);
   2390  if (!dbg->unwrapDebuggeeValue(cx, &receiver)) {
   2391    return cx->alreadyReportedError();
   2392  }
   2393 
   2394  // Enter the debuggee compartment and rewrap all input value for that
   2395  // compartment. (Rewrapping always takes place in the destination
   2396  // compartment.)
   2397  Maybe<AutoRealm> ar;
   2398  EnterDebuggeeObjectRealm(cx, ar, referent);
   2399  if (!cx->compartment()->wrap(cx, &referent) ||
   2400      !cx->compartment()->wrap(cx, &receiver)) {
   2401    return cx->alreadyReportedError();
   2402  }
   2403  cx->markId(id);
   2404 
   2405  LeaveDebuggeeNoExecute nnx(cx);
   2406 
   2407  RootedValue result(cx);
   2408  bool ok = GetProperty(cx, referent, receiver, id, &result);
   2409  return Completion::fromJSResult(cx, ok, result);
   2410 }
   2411 
   2412 /* static */
   2413 Result<Completion> DebuggerObject::setProperty(JSContext* cx,
   2414                                               Handle<DebuggerObject*> object,
   2415                                               HandleId id, HandleValue value_,
   2416                                               HandleValue receiver_) {
   2417  RootedObject referent(cx, object->referent());
   2418  Debugger* dbg = object->owner();
   2419 
   2420  // Unwrap Debugger.Objects. This happens in the debugger's compartment since
   2421  // that is where any exceptions must be reported.
   2422  RootedValue value(cx, value_);
   2423  RootedValue receiver(cx, receiver_);
   2424  if (!dbg->unwrapDebuggeeValue(cx, &value) ||
   2425      !dbg->unwrapDebuggeeValue(cx, &receiver)) {
   2426    return cx->alreadyReportedError();
   2427  }
   2428 
   2429  // Enter the debuggee compartment and rewrap all input value for that
   2430  // compartment. (Rewrapping always takes place in the destination
   2431  // compartment.)
   2432  Maybe<AutoRealm> ar;
   2433  EnterDebuggeeObjectRealm(cx, ar, referent);
   2434  if (!cx->compartment()->wrap(cx, &referent) ||
   2435      !cx->compartment()->wrap(cx, &value) ||
   2436      !cx->compartment()->wrap(cx, &receiver)) {
   2437    return cx->alreadyReportedError();
   2438  }
   2439  cx->markId(id);
   2440 
   2441  LeaveDebuggeeNoExecute nnx(cx);
   2442 
   2443  ObjectOpResult opResult;
   2444  bool ok = SetProperty(cx, referent, id, value, receiver, opResult);
   2445 
   2446  return Completion::fromJSResult(cx, ok, BooleanValue(ok && opResult.ok()));
   2447 }
   2448 
   2449 /* static */
   2450 Maybe<Completion> DebuggerObject::call(JSContext* cx,
   2451                                       Handle<DebuggerObject*> object,
   2452                                       HandleValue thisv_,
   2453                                       Handle<ValueVector> args) {
   2454  RootedObject referent(cx, object->referent());
   2455  Debugger* dbg = object->owner();
   2456 
   2457  if (!referent->isCallable()) {
   2458    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
   2459                              JSMSG_INCOMPATIBLE_PROTO, "Debugger.Object",
   2460                              "call", referent->getClass()->name);
   2461    return Nothing();
   2462  }
   2463 
   2464  RootedValue calleev(cx, ObjectValue(*referent));
   2465 
   2466  // Unwrap Debugger.Objects. This happens in the debugger's compartment since
   2467  // that is where any exceptions must be reported.
   2468  RootedValue thisv(cx, thisv_);
   2469  if (!dbg->unwrapDebuggeeValue(cx, &thisv)) {
   2470    return Nothing();
   2471  }
   2472  Rooted<ValueVector> args2(cx, ValueVector(cx));
   2473  if (!args2.append(args.begin(), args.end())) {
   2474    return Nothing();
   2475  }
   2476  for (size_t i = 0; i < args2.length(); ++i) {
   2477    if (!dbg->unwrapDebuggeeValue(cx, args2[i])) {
   2478      return Nothing();
   2479    }
   2480  }
   2481 
   2482  // Enter the debuggee compartment and rewrap all input value for that
   2483  // compartment. (Rewrapping always takes place in the destination
   2484  // compartment.)
   2485  Maybe<AutoRealm> ar;
   2486  EnterDebuggeeObjectRealm(cx, ar, referent);
   2487  if (!cx->compartment()->wrap(cx, &calleev) ||
   2488      !cx->compartment()->wrap(cx, &thisv)) {
   2489    return Nothing();
   2490  }
   2491  for (size_t i = 0; i < args2.length(); ++i) {
   2492    if (!cx->compartment()->wrap(cx, args2[i])) {
   2493      return Nothing();
   2494    }
   2495  }
   2496 
   2497  // Note whether we are in an evaluation that might invoke the OnNativeCall
   2498  // hook, so that the JITs will be disabled.
   2499  Maybe<AutoNoteExclusiveDebuggerOnEval> noteEvaluation;
   2500  if (dbg->isExclusiveDebuggerOnEval()) {
   2501    noteEvaluation.emplace(cx, dbg);
   2502  }
   2503 
   2504  // Call the function.
   2505  LeaveDebuggeeNoExecute nnx(cx);
   2506 
   2507  RootedValue result(cx);
   2508  bool ok;
   2509  {
   2510    InvokeArgs invokeArgs(cx);
   2511 
   2512    ok = invokeArgs.init(cx, args2.length());
   2513    if (ok) {
   2514      for (size_t i = 0; i < args2.length(); ++i) {
   2515        invokeArgs[i].set(args2[i]);
   2516      }
   2517 
   2518      ok = js::Call(cx, calleev, thisv, invokeArgs, &result);
   2519    }
   2520  }
   2521 
   2522  Rooted<Completion> completion(cx, Completion::fromJSResult(cx, ok, result));
   2523  ar.reset();
   2524  return Some(std::move(completion.get()));
   2525 }
   2526 
   2527 /* static */
   2528 bool DebuggerObject::forceLexicalInitializationByName(
   2529    JSContext* cx, Handle<DebuggerObject*> object, HandleId id, bool& result) {
   2530  if (!id.isString()) {
   2531    JS_ReportErrorNumberASCII(
   2532        cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
   2533        "Debugger.Object.prototype.forceLexicalInitializationByName", "string",
   2534        InformalValueTypeName(IdToValue(id)));
   2535    return false;
   2536  }
   2537 
   2538  MOZ_ASSERT(object->isGlobal());
   2539 
   2540  Rooted<GlobalObject*> referent(cx, &object->referent()->as<GlobalObject>());
   2541 
   2542  // Shape::search can end up allocating a new BaseShape in Shape::cachify so
   2543  // we need to be in the right compartment here.
   2544  Maybe<AutoRealm> ar;
   2545  EnterDebuggeeObjectRealm(cx, ar, referent);
   2546 
   2547  RootedObject globalLexical(cx, &referent->lexicalEnvironment());
   2548  RootedObject pobj(cx);
   2549  PropertyResult prop;
   2550  if (!LookupProperty(cx, globalLexical, id, &pobj, &prop)) {
   2551    return false;
   2552  }
   2553 
   2554  result = false;
   2555  if (prop.isFound()) {
   2556    MOZ_ASSERT(prop.isNativeProperty());
   2557    PropertyInfo propInfo = prop.propertyInfo();
   2558    Value v = globalLexical->as<NativeObject>().getSlot(propInfo.slot());
   2559    if (propInfo.isDataProperty() && v.isMagic() &&
   2560        v.whyMagic() == JS_UNINITIALIZED_LEXICAL) {
   2561      globalLexical->as<NativeObject>().setSlot(propInfo.slot(),
   2562                                                UndefinedValue());
   2563      result = true;
   2564    }
   2565  }
   2566 
   2567  return true;
   2568 }
   2569 
   2570 /* static */
   2571 Result<Completion> DebuggerObject::executeInGlobal(
   2572    JSContext* cx, Handle<DebuggerObject*> object,
   2573    mozilla::Range<const char16_t> chars, HandleObject bindings,
   2574    const EvalOptions& options) {
   2575  MOZ_ASSERT(object->isGlobal());
   2576 
   2577  Rooted<GlobalObject*> referent(cx, &object->referent()->as<GlobalObject>());
   2578  Debugger* dbg = object->owner();
   2579 
   2580  RootedObject globalLexical(cx, &referent->lexicalEnvironment());
   2581  return DebuggerGenericEval(cx, chars, bindings, options, dbg, globalLexical,
   2582                             nullptr);
   2583 }
   2584 
   2585 /* static */
   2586 bool DebuggerObject::makeDebuggeeValue(JSContext* cx,
   2587                                       Handle<DebuggerObject*> object,
   2588                                       HandleValue value_,
   2589                                       MutableHandleValue result) {
   2590  RootedObject referent(cx, object->referent());
   2591  Debugger* dbg = object->owner();
   2592 
   2593  RootedValue value(cx, value_);
   2594 
   2595  // Non-objects are already debuggee values.
   2596  if (value.isObject()) {
   2597    // Enter this Debugger.Object's referent's compartment, and wrap the
   2598    // argument as appropriate for references from there.
   2599    {
   2600      Maybe<AutoRealm> ar;
   2601      EnterDebuggeeObjectRealm(cx, ar, referent);
   2602      if (!cx->compartment()->wrap(cx, &value)) {
   2603        return false;
   2604      }
   2605    }
   2606 
   2607    // Back in the debugger's compartment, produce a new Debugger.Object
   2608    // instance referring to the wrapped argument.
   2609    if (!dbg->wrapDebuggeeValue(cx, &value)) {
   2610      return false;
   2611    }
   2612  }
   2613 
   2614  result.set(value);
   2615  return true;
   2616 }
   2617 
   2618 static JSFunction* EnsureNativeFunction(const Value& value) {
   2619  if (!value.isObject() || !value.toObject().is<JSFunction>()) {
   2620    return nullptr;
   2621  }
   2622 
   2623  JSFunction* fun = &value.toObject().as<JSFunction>();
   2624  if (!fun->isNativeFun()) {
   2625    return nullptr;
   2626  }
   2627 
   2628  return fun;
   2629 }
   2630 
   2631 static JSAtom* MaybeGetSelfHostedFunctionName(const Value& v) {
   2632  if (!v.isObject() || !v.toObject().is<JSFunction>()) {
   2633    return nullptr;
   2634  }
   2635 
   2636  JSFunction* fun = &v.toObject().as<JSFunction>();
   2637  if (!fun->isSelfHostedBuiltin()) {
   2638    return nullptr;
   2639  }
   2640 
   2641  return GetClonedSelfHostedFunctionName(fun);
   2642 }
   2643 
   2644 static bool IsSameNative(JSFunction* a, JSFunction* b,
   2645                         DebuggerObject::CheckJitInfo checkJitInfo) {
   2646  if (a->native() != b->native()) {
   2647    return false;
   2648  }
   2649 
   2650  if (checkJitInfo == DebuggerObject::CheckJitInfo::No) {
   2651    return true;
   2652  }
   2653 
   2654  // Both function should agree with the existence of JitInfo.
   2655 
   2656  if (a->hasJitInfo() != b->hasJitInfo()) {
   2657    return false;
   2658  }
   2659 
   2660  if (!a->hasJitInfo()) {
   2661    return true;
   2662  }
   2663 
   2664  if (a->jitInfo() == b->jitInfo()) {
   2665    return true;
   2666  }
   2667 
   2668  return false;
   2669 }
   2670 
   2671 /* static */
   2672 bool DebuggerObject::isSameNative(JSContext* cx, Handle<DebuggerObject*> object,
   2673                                  HandleValue value, CheckJitInfo checkJitInfo,
   2674                                  MutableHandleValue result) {
   2675  RootedValue referentValue(cx, ObjectValue(*object->referent()));
   2676 
   2677  RootedValue nonCCWValue(
   2678      cx, value.isObject() ? ObjectValue(*UncheckedUnwrap(&value.toObject()))
   2679                           : value);
   2680 
   2681  RootedFunction fun(cx, EnsureNativeFunction(nonCCWValue));
   2682  if (!fun) {
   2683    Rooted<JSAtom*> selfHostedName(cx,
   2684                                   MaybeGetSelfHostedFunctionName(nonCCWValue));
   2685    if (!selfHostedName) {
   2686      JS_ReportErrorASCII(cx, "Need native function");
   2687      return false;
   2688    }
   2689 
   2690    result.setBoolean(selfHostedName ==
   2691                      MaybeGetSelfHostedFunctionName(referentValue));
   2692    return true;
   2693  }
   2694 
   2695  RootedFunction referentFun(cx, EnsureNativeFunction(referentValue));
   2696 
   2697  result.setBoolean(referentFun &&
   2698                    IsSameNative(referentFun, fun, checkJitInfo));
   2699  return true;
   2700 }
   2701 
   2702 static bool IsNativeGetterWithJitInfo(JSFunction* fun) {
   2703  return fun->isNativeFun() && fun->hasJitInfo() &&
   2704         fun->jitInfo()->type() == JSJitInfo::Getter;
   2705 }
   2706 
   2707 /* static */
   2708 bool DebuggerObject::isNativeGetterWithJitInfo(JSContext* cx,
   2709                                               Handle<DebuggerObject*> object,
   2710                                               MutableHandleValue result) {
   2711  RootedValue referentValue(cx, ObjectValue(*object->referent()));
   2712  RootedFunction referentFun(cx, EnsureNativeFunction(referentValue));
   2713  result.setBoolean(referentFun && IsNativeGetterWithJitInfo(referentFun));
   2714  return true;
   2715 }
   2716 
   2717 /* static */
   2718 bool DebuggerObject::unsafeDereference(JSContext* cx,
   2719                                       Handle<DebuggerObject*> object,
   2720                                       MutableHandleObject result) {
   2721  RootedObject referent(cx, object->referent());
   2722 
   2723  if (!cx->compartment()->wrap(cx, &referent)) {
   2724    return false;
   2725  }
   2726 
   2727  // Wrapping should return the WindowProxy.
   2728  MOZ_ASSERT(!IsWindow(referent));
   2729 
   2730  result.set(referent);
   2731  return true;
   2732 }
   2733 
   2734 /* static */
   2735 bool DebuggerObject::unwrap(JSContext* cx, Handle<DebuggerObject*> object,
   2736                            MutableHandle<DebuggerObject*> result) {
   2737  RootedObject referent(cx, object->referent());
   2738  Debugger* dbg = object->owner();
   2739 
   2740  RootedObject unwrapped(cx, UnwrapOneCheckedStatic(referent));
   2741 
   2742  // Don't allow unwrapping to create a D.O whose referent is in an
   2743  // invisible-to-Debugger compartment. (If our referent is a *wrapper* to such,
   2744  // and the wrapper is in a visible compartment, that's fine.)
   2745  if (unwrapped && unwrapped->compartment()->invisibleToDebugger()) {
   2746    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
   2747                              JSMSG_DEBUG_INVISIBLE_COMPARTMENT);
   2748    return false;
   2749  }
   2750 
   2751  return dbg->wrapNullableDebuggeeObject(cx, unwrapped, result);
   2752 }
   2753 
   2754 /* static */
   2755 bool DebuggerObject::requireGlobal(JSContext* cx,
   2756                                   Handle<DebuggerObject*> object) {
   2757  if (!object->isGlobal()) {
   2758    RootedObject referent(cx, object->referent());
   2759 
   2760    const char* isWrapper = "";
   2761    const char* isWindowProxy = "";
   2762 
   2763    // Help the poor programmer by pointing out wrappers around globals...
   2764    if (referent->is<WrapperObject>()) {
   2765      referent = js::UncheckedUnwrap(referent);
   2766      isWrapper = "a wrapper around ";
   2767    }
   2768 
   2769    // ... and WindowProxies around Windows.
   2770    if (IsWindowProxy(referent)) {
   2771      referent = ToWindowIfWindowProxy(referent);
   2772      isWindowProxy = "a WindowProxy referring to ";
   2773    }
   2774 
   2775    RootedValue dbgobj(cx, ObjectValue(*object));
   2776    if (referent->is<GlobalObject>()) {
   2777      ReportValueError(cx, JSMSG_DEBUG_WRAPPER_IN_WAY, JSDVG_SEARCH_STACK,
   2778                       dbgobj, nullptr, isWrapper, isWindowProxy);
   2779    } else {
   2780      ReportValueError(cx, JSMSG_DEBUG_BAD_REFERENT, JSDVG_SEARCH_STACK, dbgobj,
   2781                       nullptr, "a global object");
   2782    }
   2783    return false;
   2784  }
   2785 
   2786  return true;
   2787 }
   2788 
   2789 /* static */
   2790 bool DebuggerObject::requirePromise(JSContext* cx,
   2791                                    Handle<DebuggerObject*> object) {
   2792  RootedObject referent(cx, object->referent());
   2793 
   2794  if (IsCrossCompartmentWrapper(referent)) {
   2795    /* We only care about promises, so CheckedUnwrapStatic is OK. */
   2796    referent = CheckedUnwrapStatic(referent);
   2797    if (!referent) {
   2798      ReportAccessDenied(cx);
   2799      return false;
   2800    }
   2801  }
   2802 
   2803  if (!referent->is<PromiseObject>()) {
   2804    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
   2805                              JSMSG_NOT_EXPECTED_TYPE, "Debugger", "Promise",
   2806                              object->getClass()->name);
   2807    return false;
   2808  }
   2809 
   2810  return true;
   2811 }
   2812 
   2813 /* static */
   2814 bool DebuggerObject::getScriptedProxyTarget(
   2815    JSContext* cx, Handle<DebuggerObject*> object,
   2816    MutableHandle<DebuggerObject*> result) {
   2817  MOZ_ASSERT(object->isScriptedProxy());
   2818  RootedObject referent(cx, object->referent());
   2819  Debugger* dbg = object->owner();
   2820  RootedObject unwrapped(cx, js::GetProxyTargetObject(referent));
   2821 
   2822  return dbg->wrapNullableDebuggeeObject(cx, unwrapped, result);
   2823 }
   2824 
   2825 /* static */
   2826 bool DebuggerObject::getScriptedProxyHandler(
   2827    JSContext* cx, Handle<DebuggerObject*> object,
   2828    MutableHandle<DebuggerObject*> result) {
   2829  MOZ_ASSERT(object->isScriptedProxy());
   2830  RootedObject referent(cx, object->referent());
   2831  Debugger* dbg = object->owner();
   2832  RootedObject unwrapped(cx, ScriptedProxyHandler::handlerObject(referent));
   2833  return dbg->wrapNullableDebuggeeObject(cx, unwrapped, result);
   2834 }