tor-browser

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

Debugger.h (62760B)


      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 #ifndef debugger_Debugger_h
      8 #define debugger_Debugger_h
      9 
     10 #include "mozilla/Assertions.h"        // for MOZ_ASSERT_HELPER1
     11 #include "mozilla/Attributes.h"        // for MOZ_RAII
     12 #include "mozilla/DoublyLinkedList.h"  // for DoublyLinkedListElement
     13 #include "mozilla/HashTable.h"         // for HashSet, DefaultHasher (ptr only)
     14 #include "mozilla/LinkedList.h"        // for LinkedList (ptr only)
     15 #include "mozilla/Maybe.h"             // for Maybe, Nothing
     16 #include "mozilla/Range.h"             // for Range
     17 #include "mozilla/Result.h"            // for Result
     18 #include "mozilla/TimeStamp.h"         // for TimeStamp
     19 #include "mozilla/Variant.h"           // for Variant
     20 
     21 #include <stddef.h>  // for size_t
     22 #include <stdint.h>  // for uint32_t, uint64_t, uintptr_t
     23 #include <utility>   // for std::move
     24 
     25 #include "jstypes.h"           // for JS_GC_ZEAL
     26 #include "NamespaceImports.h"  // for Value, HandleObject
     27 
     28 #include "debugger/DebugAPI.h"      // for DebugAPI
     29 #include "debugger/Object.h"        // for DebuggerObject
     30 #include "ds/TraceableFifo.h"       // for TraceableFifo
     31 #include "gc/Barrier.h"             //
     32 #include "gc/Tracer.h"              // for TraceNullableEdge, TraceEdge
     33 #include "gc/WeakMap.h"             // for WeakMap
     34 #include "gc/ZoneAllocator.h"       // for ZoneAllocPolicy
     35 #include "js/Debug.h"               // JS_DefineDebuggerObject
     36 #include "js/GCAPI.h"               // for GarbageCollectionEvent
     37 #include "js/GCVariant.h"           // for GCVariant
     38 #include "js/Proxy.h"               // for PropertyDescriptor
     39 #include "js/RootingAPI.h"          // for Handle
     40 #include "js/TracingAPI.h"          // for TraceRoot
     41 #include "js/Wrapper.h"             // for UncheckedUnwrap
     42 #include "proxy/DeadObjectProxy.h"  // for IsDeadProxyObject
     43 #include "vm/GeneratorObject.h"     // for AbstractGeneratorObject
     44 #include "vm/GlobalObject.h"        // for GlobalObject
     45 #include "vm/JSContext.h"           // for JSContext
     46 #include "vm/JSObject.h"            // for JSObject
     47 #include "vm/JSScript.h"            // for JSScript, ScriptSourceObject
     48 #include "vm/NativeObject.h"        // for NativeObject
     49 #include "vm/Runtime.h"             // for JSRuntime
     50 #include "vm/SavedFrame.h"          // for SavedFrame
     51 #include "vm/Stack.h"               // for AbstractFramePtr, FrameIter
     52 #include "vm/StringType.h"          // for JSAtom
     53 #include "wasm/WasmJS.h"            // for WasmInstanceObject
     54 
     55 class JS_PUBLIC_API JSFunction;
     56 
     57 namespace JS {
     58 class JS_PUBLIC_API AutoStableStringChars;
     59 class JS_PUBLIC_API Compartment;
     60 class JS_PUBLIC_API Realm;
     61 class JS_PUBLIC_API Zone;
     62 } /* namespace JS */
     63 
     64 namespace js {
     65 class AutoRealm;
     66 class CrossCompartmentKey;
     67 class Debugger;
     68 class DebuggerEnvironment;
     69 class PromiseObject;
     70 namespace gc {
     71 struct Cell;
     72 } /* namespace gc */
     73 namespace wasm {
     74 class Instance;
     75 } /* namespace wasm */
     76 } /* namespace js */
     77 
     78 /*
     79 * Windows 3.x used a cooperative multitasking model, with a Yield macro that
     80 * let you relinquish control to other cooperative threads. Microsoft replaced
     81 * it with an empty macro long ago. We should be free to use it in our code.
     82 */
     83 #undef Yield
     84 
     85 namespace js {
     86 
     87 class Breakpoint;
     88 class DebuggerFrame;
     89 class DebuggerScript;
     90 class DebuggerSource;
     91 class DebuggerMemory;
     92 class ScriptedOnStepHandler;
     93 class ScriptedOnPopHandler;
     94 class DebuggerDebuggeeLink;
     95 
     96 /**
     97 * Tells how the JS engine should resume debuggee execution after firing a
     98 * debugger hook.  Most debugger hooks get to choose how the debuggee proceeds;
     99 * see js/src/doc/Debugger/Conventions.md under "Resumption Values".
    100 *
    101 * Debugger::processHandlerResult() translates between JavaScript values and
    102 * this enum.
    103 */
    104 enum class ResumeMode {
    105  /**
    106   * The debuggee should continue unchanged.
    107   *
    108   * This corresponds to a resumption value of `undefined`.
    109   */
    110  Continue,
    111 
    112  /**
    113   * Throw an exception in the debuggee.
    114   *
    115   * This corresponds to a resumption value of `{throw: <value>}`.
    116   */
    117  Throw,
    118 
    119  /**
    120   * Terminate the debuggee, as if it had been cancelled via the "slow
    121   * script" ribbon.
    122   *
    123   * This corresponds to a resumption value of `null`.
    124   */
    125  Terminate,
    126 
    127  /**
    128   * Force the debuggee to return from the current frame.
    129   *
    130   * This corresponds to a resumption value of `{return: <value>}`.
    131   */
    132  Return,
    133 };
    134 
    135 /**
    136 * A completion value, describing how some sort of JavaScript evaluation
    137 * completed. This is used to tell an onPop handler what's going on with the
    138 * frame, and to report the outcome of call, apply, setProperty, and getProperty
    139 * operations.
    140 *
    141 * Local variables of type Completion should be held in Rooted locations,
    142 * and passed using Handle and MutableHandle.
    143 */
    144 class Completion {
    145 public:
    146  struct Return {
    147    explicit Return(const Value& value) : value(value) {}
    148    Value value;
    149 
    150    void trace(JSTracer* trc) {
    151      JS::TraceRoot(trc, &value, "js::Completion::Return::value");
    152    }
    153  };
    154 
    155  struct Throw {
    156    Throw(const Value& exception, SavedFrame* stack)
    157        : exception(exception), stack(stack) {}
    158    Value exception;
    159    SavedFrame* stack;
    160 
    161    void trace(JSTracer* trc) {
    162      JS::TraceRoot(trc, &exception, "js::Completion::Throw::exception");
    163      JS::TraceRoot(trc, &stack, "js::Completion::Throw::stack");
    164    }
    165  };
    166 
    167  struct Terminate {
    168    void trace(JSTracer* trc) {}
    169  };
    170 
    171  struct InitialYield {
    172    explicit InitialYield(AbstractGeneratorObject* generatorObject)
    173        : generatorObject(generatorObject) {}
    174    AbstractGeneratorObject* generatorObject;
    175 
    176    void trace(JSTracer* trc) {
    177      JS::TraceRoot(trc, &generatorObject,
    178                    "js::Completion::InitialYield::generatorObject");
    179    }
    180  };
    181 
    182  struct Yield {
    183    Yield(AbstractGeneratorObject* generatorObject, const Value& iteratorResult)
    184        : generatorObject(generatorObject), iteratorResult(iteratorResult) {}
    185    AbstractGeneratorObject* generatorObject;
    186    Value iteratorResult;
    187 
    188    void trace(JSTracer* trc) {
    189      JS::TraceRoot(trc, &generatorObject,
    190                    "js::Completion::Yield::generatorObject");
    191      JS::TraceRoot(trc, &iteratorResult,
    192                    "js::Completion::Yield::iteratorResult");
    193    }
    194  };
    195 
    196  struct Await {
    197    Await(AbstractGeneratorObject* generatorObject, const Value& awaitee)
    198        : generatorObject(generatorObject), awaitee(awaitee) {}
    199    AbstractGeneratorObject* generatorObject;
    200    Value awaitee;
    201 
    202    void trace(JSTracer* trc) {
    203      JS::TraceRoot(trc, &generatorObject,
    204                    "js::Completion::Await::generatorObject");
    205      JS::TraceRoot(trc, &awaitee, "js::Completion::Await::awaitee");
    206    }
    207  };
    208 
    209  // The JS::Result macros want to assign to an existing variable, so having a
    210  // default constructor is handy.
    211  Completion() : variant(Terminate()) {}
    212 
    213  // Construct a completion from a specific variant.
    214  //
    215  // Unfortunately, using a template here would prevent the implicit definitions
    216  // of the copy and move constructor and assignment operators, which is icky.
    217  explicit Completion(Return&& variant)
    218      : variant(std::forward<Return>(variant)) {}
    219  explicit Completion(Throw&& variant)
    220      : variant(std::forward<Throw>(variant)) {}
    221  explicit Completion(Terminate&& variant)
    222      : variant(std::forward<Terminate>(variant)) {}
    223  explicit Completion(InitialYield&& variant)
    224      : variant(std::forward<InitialYield>(variant)) {}
    225  explicit Completion(Yield&& variant)
    226      : variant(std::forward<Yield>(variant)) {}
    227  explicit Completion(Await&& variant)
    228      : variant(std::forward<Await>(variant)) {}
    229 
    230  // Capture a JavaScript operation result as a Completion value. This clears
    231  // any exception and stack from cx, taking ownership of them itself.
    232  static Completion fromJSResult(JSContext* cx, bool ok, const Value& rv);
    233 
    234  // Construct a completion given an AbstractFramePtr that is being popped. This
    235  // clears any exception and stack from cx, taking ownership of them itself.
    236  static Completion fromJSFramePop(JSContext* cx, AbstractFramePtr frame,
    237                                   const jsbytecode* pc, bool ok);
    238 
    239  template <typename V>
    240  bool is() const {
    241    return variant.template is<V>();
    242  }
    243 
    244  template <typename V>
    245  V& as() {
    246    return variant.template as<V>();
    247  }
    248 
    249  template <typename V>
    250  const V& as() const {
    251    return variant.template as<V>();
    252  }
    253 
    254  void trace(JSTracer* trc);
    255 
    256  /* True if this completion is a suspension of a generator or async call. */
    257  bool suspending() const {
    258    return variant.is<InitialYield>() || variant.is<Yield>() ||
    259           variant.is<Await>();
    260  }
    261 
    262  /* Set `result` to a Debugger API completion value describing this completion.
    263   */
    264  bool buildCompletionValue(JSContext* cx, Debugger* dbg,
    265                            MutableHandleValue result) const;
    266 
    267  /*
    268   * Set `resumeMode`, `value`, and `exnStack` to values describing this
    269   * completion.
    270   */
    271  void toResumeMode(ResumeMode& resumeMode, MutableHandleValue value,
    272                    MutableHandle<SavedFrame*> exnStack) const;
    273  /*
    274   * Given a `ResumeMode` and value (typically derived from a resumption value
    275   * returned by a Debugger hook), update this completion as requested.
    276   */
    277  void updateFromHookResult(ResumeMode resumeMode, HandleValue value);
    278 
    279 private:
    280  using Variant =
    281      mozilla::Variant<Return, Throw, Terminate, InitialYield, Yield, Await>;
    282  struct BuildValueMatcher;
    283  struct ToResumeModeMatcher;
    284 
    285  Variant variant;
    286 };
    287 
    288 using WeakGlobalObjectSet =
    289    HashSet<WeakHeapPtr<GlobalObject*>,
    290            StableCellHasher<WeakHeapPtr<GlobalObject*>>, ZoneAllocPolicy>;
    291 
    292 #ifdef DEBUG
    293 extern void CheckDebuggeeThing(BaseScript* script, bool invisibleOk);
    294 
    295 extern void CheckDebuggeeThing(JSObject* obj, bool invisibleOk);
    296 #endif
    297 
    298 /*
    299 * [SMDOC] Cross-compartment weakmap entries for Debugger API objects
    300 *
    301 * The Debugger API creates objects like Debugger.Object, Debugger.Script,
    302 * Debugger.Environment, etc. to refer to things in the debuggee. Each Debugger
    303 * gets at most one Debugger.Mumble for each referent: Debugger.Mumbles are
    304 * unique per referent per Debugger. This is accomplished by storing the
    305 * debugger objects in a DebuggerWeakMap, using the debuggee thing as the key.
    306 *
    307 * Since a Debugger and its debuggee must be in different compartments, a
    308 * Debugger.Mumble's pointer to its referent is a cross-compartment edge, from
    309 * the debugger's compartment into the debuggee compartment. Like any other sort
    310 * of cross-compartment edge, the GC needs to be able to find all of these edges
    311 * readily. The GC therefore consults the debugger's weakmap tables as
    312 * necessary.  This allows the garbage collector to easily find edges between
    313 * debuggee object compartments and debugger compartments when calculating the
    314 * zone sweep groups.
    315 *
    316 * The current implementation results in all debuggee object compartments being
    317 * swept in the same group as the debugger. This is a conservative approach, and
    318 * compartments may be unnecessarily grouped. However this results in a simpler
    319 * and faster implementation.
    320 */
    321 
    322 /*
    323 * A weakmap from GC thing keys to JSObject values that supports the keys being
    324 * in different compartments to the values. All values must be in the same
    325 * compartment.
    326 *
    327 * If InvisibleKeysOk is true, then the map can have keys in invisible-to-
    328 * debugger compartments. If it is false, we assert that such entries are never
    329 * created.
    330 *
    331 * Note that keys in these weakmaps can be in any compartment, debuggee or not,
    332 * because they are not deleted when a compartment is no longer a debuggee: the
    333 * values need to maintain object identity across add/remove/add
    334 * transitions. (Frames are an exception to the rule. Existing Debugger.Frame
    335 * objects are killed if their realm is removed as a debugger; if the realm
    336 * beacomes a debuggee again later, new Frame objects are created.)
    337 */
    338 template <class Referent, class Wrapper, bool InvisibleKeysOk = false>
    339 class DebuggerWeakMap : private WeakMap<Referent*, Wrapper*, ZoneAllocPolicy> {
    340 private:
    341  using Key = Referent*;
    342  using Value = Wrapper*;
    343 
    344  JS::Compartment* compartment;
    345 
    346 public:
    347  using Base = WeakMap<Key, Value, ZoneAllocPolicy>;
    348  using ReferentType = Referent;
    349  using WrapperType = Wrapper;
    350 
    351  explicit DebuggerWeakMap(JSContext* cx)
    352      : Base(cx), compartment(cx->compartment()) {}
    353 
    354 public:
    355  // Expose those parts of HashMap public interface that are used by Debugger
    356  // methods.
    357 
    358  using Entry = typename Base::Entry;
    359  using Ptr = typename Base::Ptr;
    360  using AddPtr = typename Base::AddPtr;
    361  using Range = typename Base::Range;
    362  using Lookup = typename Base::Lookup;
    363 
    364  // Expose WeakMap public interface.
    365 
    366  using Base::all;
    367  using Base::has;
    368  using Base::lookup;
    369  using Base::lookupForAdd;
    370  using Base::lookupUnbarriered;
    371  using Base::remove;
    372  using Base::trace;
    373  using Base::zone;
    374 #ifdef DEBUG
    375  using Base::hasEntry;
    376 #endif
    377 
    378  class Enum : public Base::Enum {
    379   public:
    380    explicit Enum(DebuggerWeakMap& map) : Base::Enum(map) {}
    381  };
    382 
    383  template <typename KeyInput, typename ValueInput>
    384  bool relookupOrAdd(AddPtr& p, const KeyInput& k, const ValueInput& v) {
    385    MOZ_ASSERT(v->compartment() == this->compartment);
    386 #ifdef DEBUG
    387    CheckDebuggeeThing(k, InvisibleKeysOk);
    388 #endif
    389    MOZ_ASSERT(!Base::has(k));
    390    bool ok = Base::relookupOrAdd(p, k, v);
    391    return ok;
    392  }
    393 
    394 public:
    395  void traceCrossCompartmentEdges(JSTracer* tracer) {
    396    for (Enum e(*this); !e.empty(); e.popFront()) {
    397      // The values are debugger objects which contain a cross-compartment
    398      // debuggee pointer, so trace their contents.
    399      e.front().value()->trace(tracer);
    400 
    401      // Trace the keys, which are cross compartment debuggee pointers.
    402      // This can rekey the entry and invalidate |e.front()|.
    403      Base::traceKey(tracer, e);
    404    }
    405  }
    406 
    407  bool findSweepGroupEdges(JS::Zone* atomsZone) override;
    408 
    409 private:
    410 #ifdef JS_GC_ZEAL
    411  // Let the weak map marking verifier know that this map can
    412  // contain keys in other zones.
    413  virtual bool allowKeysInOtherZones() const override { return true; }
    414 #endif
    415 };
    416 
    417 class LeaveDebuggeeNoExecute;
    418 
    419 class MOZ_RAII EvalOptions {
    420 public:
    421  enum class EnvKind {
    422    Frame,
    423    FrameWithExtraBindings,
    424    Global,
    425    GlobalWithExtraOuterBindings,
    426    GlobalWithExtraInnerBindings,
    427  };
    428 
    429 private:
    430  JS::UniqueChars filename_;
    431  unsigned lineno_ = 1;
    432  bool hideFromDebugger_ = false;
    433  bool bypassCSP_ = false;
    434  EnvKind kind_;
    435 
    436 public:
    437  explicit EvalOptions(EnvKind kind) : kind_(kind) {};
    438  ~EvalOptions() = default;
    439  const char* filename() const { return filename_.get(); }
    440  unsigned lineno() const { return lineno_; }
    441  bool hideFromDebugger() const { return hideFromDebugger_; }
    442  bool bypassCSP() const { return bypassCSP_; }
    443  EnvKind kind() const { return kind_; }
    444  void setUseInnerBindings() {
    445    MOZ_ASSERT(kind_ == EvalOptions::EnvKind::GlobalWithExtraOuterBindings);
    446    kind_ = EvalOptions::EnvKind::GlobalWithExtraInnerBindings;
    447  }
    448  [[nodiscard]] bool setFilename(JSContext* cx, const char* filename);
    449  void setLineno(unsigned lineno) { lineno_ = lineno; }
    450  void setHideFromDebugger(bool hide) { hideFromDebugger_ = hide; }
    451  void setBypassCSP(bool bypass) { bypassCSP_ = bypass; }
    452 };
    453 
    454 /*
    455 * Env is the type of what ECMA-262 calls "lexical environments" (the records
    456 * that represent scopes and bindings). See vm/EnvironmentObject.h.
    457 *
    458 * This is JSObject rather than js::EnvironmentObject because GlobalObject and
    459 * some proxies, despite not being in the EnvironmentObject class hierarchy,
    460 * can be in environment chains.
    461 */
    462 using Env = JSObject;
    463 
    464 // The referent of a Debugger.Script.
    465 //
    466 // - For most scripts, we point at their BaseScript.
    467 //
    468 // - For Web Assembly instances for which we are presenting a script-like
    469 //   interface, we point at their WasmInstanceObject.
    470 //
    471 // The DebuggerScript object itself simply stores a Cell* in its private
    472 // pointer, but when we're working with that pointer in C++ code, we'd rather
    473 // not pass around a Cell* and be constantly asserting that, yes, this really
    474 // does point to something okay. Instead, we immediately build an instance of
    475 // this type from the Cell* and use that instead, so we can benefit from
    476 // Variant's static checks.
    477 using DebuggerScriptReferent =
    478    mozilla::Variant<BaseScript*, WasmInstanceObject*>;
    479 
    480 // The referent of a Debugger.Source.
    481 //
    482 // - For most sources, this is a ScriptSourceObject.
    483 //
    484 // - For Web Assembly instances for which we are presenting a source-like
    485 //   interface, we point at their WasmInstanceObject.
    486 //
    487 // The DebuggerSource object actually simply stores a Cell* in its private
    488 // pointer. See the comments for DebuggerScriptReferent for the rationale for
    489 // this type.
    490 using DebuggerSourceReferent =
    491    mozilla::Variant<ScriptSourceObject*, WasmInstanceObject*>;
    492 
    493 template <typename HookIsEnabledFun /* bool (Debugger*) */>
    494 class MOZ_RAII DebuggerList {
    495 private:
    496  // Note: In the general case, 'debuggers' contains references to objects in
    497  // different compartments--every compartment *except* the debugger's.
    498  RootedValueVector debuggers;
    499  HookIsEnabledFun hookIsEnabled;
    500 
    501 public:
    502  /**
    503   * The hook function will be called during `init()` to build the list of
    504   * active debuggers, and again during dispatch to validate that the hook is
    505   * still active for the given debugger.
    506   */
    507  DebuggerList(JSContext* cx, HookIsEnabledFun hookIsEnabled)
    508      : debuggers(cx), hookIsEnabled(hookIsEnabled) {}
    509 
    510  [[nodiscard]] bool init(JSContext* cx);
    511 
    512  bool empty() { return debuggers.empty(); }
    513 
    514  template <typename FireHookFun /* ResumeMode (Debugger*) */>
    515  bool dispatchHook(JSContext* cx, FireHookFun fireHook);
    516 
    517  template <typename FireHookFun /* void (Debugger*) */>
    518  void dispatchQuietHook(JSContext* cx, FireHookFun fireHook);
    519 
    520  template <typename FireHookFun /* bool (Debugger*, ResumeMode&, MutableHandleValue) */>
    521  [[nodiscard]] bool dispatchResumptionHook(JSContext* cx,
    522                                           AbstractFramePtr frame,
    523                                           FireHookFun fireHook);
    524 };
    525 
    526 // The Debugger.prototype object.
    527 class DebuggerPrototypeObject : public NativeObject {
    528 public:
    529  static const JSClass class_;
    530 };
    531 
    532 class DebuggerInstanceObject : public NativeObject {
    533 private:
    534  static const JSClassOps classOps_;
    535 
    536 public:
    537  static const JSClass class_;
    538 };
    539 
    540 class Debugger : private mozilla::LinkedListElement<Debugger> {
    541  friend class DebugAPI;
    542  friend class Breakpoint;
    543  friend class DebuggerFrame;
    544  friend class DebuggerMemory;
    545  friend class DebuggerInstanceObject;
    546 
    547  template <typename>
    548  friend class DebuggerList;
    549  friend struct JSRuntime::GlobalObjectWatchersLinkAccess<Debugger>;
    550  friend struct JSRuntime::GarbageCollectionWatchersLinkAccess<Debugger>;
    551  friend class SavedStacks;
    552  friend class ScriptedOnStepHandler;
    553  friend class ScriptedOnPopHandler;
    554  friend class mozilla::LinkedListElement<Debugger>;
    555  friend class mozilla::LinkedList<Debugger>;
    556  friend bool(::JS_DefineDebuggerObject)(JSContext* cx, JS::HandleObject obj);
    557  friend bool(::JS::dbg::IsDebugger)(JSObject&);
    558  friend bool(::JS::dbg::GetDebuggeeGlobals)(JSContext*, JSObject&,
    559                                             MutableHandleObjectVector);
    560  friend bool JS::dbg::FireOnGarbageCollectionHookRequired(JSContext* cx);
    561  friend bool JS::dbg::FireOnGarbageCollectionHook(
    562      JSContext* cx, JS::dbg::GarbageCollectionEvent::Ptr&& data);
    563 
    564 public:
    565  enum Hook {
    566    OnDebuggerStatement,
    567    OnExceptionUnwind,
    568    OnNewScript,
    569    OnEnterFrame,
    570    OnNativeCall,
    571    OnNewGlobalObject,
    572    OnNewPromise,
    573    OnPromiseSettled,
    574    OnGarbageCollection,
    575    HookCount
    576  };
    577  enum {
    578    JSSLOT_DEBUG_PROTO_START,
    579    JSSLOT_DEBUG_FRAME_PROTO = JSSLOT_DEBUG_PROTO_START,
    580    JSSLOT_DEBUG_ENV_PROTO,
    581    JSSLOT_DEBUG_OBJECT_PROTO,
    582    JSSLOT_DEBUG_SCRIPT_PROTO,
    583    JSSLOT_DEBUG_SOURCE_PROTO,
    584    JSSLOT_DEBUG_MEMORY_PROTO,
    585    JSSLOT_DEBUG_PROTO_STOP,
    586    JSSLOT_DEBUG_DEBUGGER = JSSLOT_DEBUG_PROTO_STOP,
    587    JSSLOT_DEBUG_HOOK_START,
    588    JSSLOT_DEBUG_HOOK_STOP = JSSLOT_DEBUG_HOOK_START + HookCount,
    589    JSSLOT_DEBUG_MEMORY_INSTANCE = JSSLOT_DEBUG_HOOK_STOP,
    590    JSSLOT_DEBUG_DEBUGGEE_LINK,
    591    JSSLOT_DEBUG_COUNT
    592  };
    593 
    594  // Bring DebugAPI::IsObserving into the Debugger namespace.
    595  using IsObserving = DebugAPI::IsObserving;
    596  static const IsObserving Observing = DebugAPI::Observing;
    597  static const IsObserving NotObserving = DebugAPI::NotObserving;
    598 
    599  // Return true if the given realm is a debuggee of this debugger,
    600  // false otherwise.
    601  bool isDebuggeeUnbarriered(const Realm* realm) const;
    602 
    603  // Return true if this Debugger observed a debuggee that participated in the
    604  // GC identified by the given GC number. Return false otherwise.
    605  // May return false negatives if we have hit OOM.
    606  bool observedGC(uint64_t majorGCNumber) const {
    607    return observedGCs.has(majorGCNumber);
    608  }
    609 
    610  // Notify this Debugger that one or more of its debuggees is participating
    611  // in the GC identified by the given GC number.
    612  bool debuggeeIsBeingCollected(uint64_t majorGCNumber) {
    613    return observedGCs.put(majorGCNumber);
    614  }
    615 
    616  static SavedFrame* getObjectAllocationSite(JSObject& obj);
    617 
    618  struct AllocationsLogEntry {
    619    AllocationsLogEntry(HandleObject frame, mozilla::TimeStamp when,
    620                        const char* className, size_t size, bool inNursery)
    621        : frame(frame),
    622          when(when),
    623          className(className),
    624          size(size),
    625          inNursery(inNursery) {
    626      MOZ_ASSERT_IF(frame, UncheckedUnwrap(frame)->is<SavedFrame>() ||
    627                               IsDeadProxyObject(frame));
    628    }
    629 
    630    HeapPtr<JSObject*> frame;
    631    mozilla::TimeStamp when;
    632    const char* className;
    633    size_t size;
    634    bool inNursery;
    635 
    636    void trace(JSTracer* trc) {
    637      TraceNullableEdge(trc, &frame, "Debugger::AllocationsLogEntry::frame");
    638    }
    639  };
    640 
    641 private:
    642  HeapPtr<NativeObject*> object; /* The Debugger object. Strong reference. */
    643  WeakGlobalObjectSet
    644      debuggees; /* Debuggee globals. Cross-compartment weak references. */
    645  JS::ZoneSet debuggeeZones; /* Set of zones that we have debuggees in. */
    646  HeapPtr<JSObject*> uncaughtExceptionHook; /* Strong reference. */
    647  bool allowUnobservedAsmJS;
    648  bool allowUnobservedWasm;
    649 
    650  // When this flag is true, this debugger should be the only one to have its
    651  // hooks called when it evaluates via Frame.evalWithBindings,
    652  // Object.executeInGlobalWithBindings or Object.call.
    653  bool exclusiveDebuggerOnEval;
    654 
    655  // When this flag is true, the onNativeCall hook is called with additional
    656  // arguments which are the native function call arguments and well as a
    657  // reference to the object on which the function call (if any).
    658  bool inspectNativeCallArguments;
    659 
    660  // Whether to enable code coverage on the Debuggee.
    661  bool collectCoverageInfo;
    662 
    663  // Whether to ask avoid side-effects in the native code.
    664  // See JS::dbg::ShouldAvoidSideEffects.
    665  bool shouldAvoidSideEffects;
    666 
    667  template <typename T>
    668  struct DebuggerLinkAccess {
    669    static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) {
    670      return aThis->debuggerLink;
    671    }
    672    static const mozilla::DoublyLinkedListElement<T>& Get(const T* aThis) {
    673      return aThis->debuggerLink;
    674    }
    675  };
    676 
    677  // List of all js::Breakpoints in this debugger.
    678  using BreakpointList =
    679      mozilla::DoublyLinkedList<js::Breakpoint,
    680                                DebuggerLinkAccess<js::Breakpoint>>;
    681  BreakpointList breakpoints;
    682 
    683  // The set of GC numbers for which one or more of this Debugger's observed
    684  // debuggees participated in.
    685  using GCNumberSet =
    686      HashSet<uint64_t, DefaultHasher<uint64_t>, ZoneAllocPolicy>;
    687  GCNumberSet observedGCs;
    688 
    689  using AllocationsLog = js::TraceableFifo<AllocationsLogEntry>;
    690 
    691  AllocationsLog allocationsLog;
    692  bool trackingAllocationSites;
    693  double allocationSamplingProbability;
    694  size_t maxAllocationsLogLength;
    695  bool allocationsLogOverflowed;
    696 
    697  static const size_t DEFAULT_MAX_LOG_LENGTH = 5000;
    698 
    699  [[nodiscard]] bool appendAllocationSite(JSContext* cx, HandleObject obj,
    700                                          Handle<SavedFrame*> frame,
    701                                          mozilla::TimeStamp when);
    702 
    703  /*
    704   * Recompute the set of debuggee zones based on the set of debuggee globals.
    705   */
    706  void recomputeDebuggeeZoneSet();
    707 
    708  /*
    709   * Return true if there is an existing object metadata callback for the
    710   * given global's compartment that will prevent our instrumentation of
    711   * allocations.
    712   */
    713  static bool cannotTrackAllocations(const GlobalObject& global);
    714 
    715  /*
    716   * Add allocations tracking for objects allocated within the given
    717   * debuggee's compartment. The given debuggee global must be observed by at
    718   * least one Debugger that is tracking allocations.
    719   */
    720  [[nodiscard]] static bool addAllocationsTracking(
    721      JSContext* cx, Handle<GlobalObject*> debuggee);
    722 
    723  /*
    724   * Remove allocations tracking for objects allocated within the given
    725   * global's compartment. This is a no-op if there are still Debuggers
    726   * observing this global and who are tracking allocations.
    727   */
    728  static void removeAllocationsTracking(GlobalObject& global);
    729 
    730  /*
    731   * Add or remove allocations tracking for all debuggees.
    732   */
    733  [[nodiscard]] bool addAllocationsTrackingForAllDebuggees(JSContext* cx);
    734  void removeAllocationsTrackingForAllDebuggees();
    735 
    736  /*
    737   * If this Debugger has a onNewGlobalObject handler, then
    738   * this link is inserted into the list headed by
    739   * JSRuntime::onNewGlobalObjectWatchers.
    740   */
    741  mozilla::DoublyLinkedListElement<Debugger> onNewGlobalObjectWatchersLink;
    742 
    743  /*
    744   * If this Debugger has a onGarbageCollection handler, then
    745   * this link is inserted into the list headed by
    746   * JSRuntime::onGarbageCollectionWatchers.
    747   */
    748  mozilla::DoublyLinkedListElement<Debugger> onGarbageCollectionWatchersLink;
    749 
    750  /*
    751   * Map from stack frames that are currently on the stack to Debugger.Frame
    752   * instances.
    753   *
    754   * The keys are always live stack frames. We drop them from this map as
    755   * soon as they leave the stack (see slowPathOnLeaveFrame) and in
    756   * removeDebuggee.
    757   *
    758   * Wasm JS PI allows suspending/resuming a portion of the stack, only
    759   * frame pointers and activations are changed. The stack frames are still
    760   * live, and shall be present in the frames map if DebuggerFrame is created.
    761   *
    762   * We don't trace the keys of this map (the frames are on the stack and
    763   * thus necessarily live), but we do trace the values. It's like a WeakMap
    764   * that way, but since stack frames are not gc-things, the implementation
    765   * has to be different.
    766   */
    767  using FrameMap = HashMap<AbstractFramePtr, HeapPtr<DebuggerFrame*>,
    768                           DefaultHasher<AbstractFramePtr>, ZoneAllocPolicy>;
    769  FrameMap frames;
    770 
    771  /*
    772   * Map from generator objects to their Debugger.Frame instances.
    773   *
    774   * When a Debugger.Frame is created for a generator frame, it is added to
    775   * this map and remains there for the lifetime of the generator, whether
    776   * that frame is on the stack at the moment or not.  This is in addition to
    777   * the entry in `frames` that exists as long as the generator frame is on
    778   * the stack.
    779   *
    780   * We need to keep the Debugger.Frame object alive to deliver it to the
    781   * onEnterFrame handler on resume, and to retain onStep and onPop hooks.
    782   *
    783   * An entry is present in this table when:
    784   *  - both the debuggee generator object and the Debugger.Frame object exists
    785   *  - the debuggee generator object belongs to a realm that is a debuggee of
    786   *    the Debugger.Frame's owner.
    787   *
    788   * regardless of whether the frame is currently suspended. (This list is
    789   * meant to explain why we update the table in the particular places where
    790   * we do so.)
    791   *
    792   * An entry in this table exists if and only if the Debugger.Frame's
    793   * GENERATOR_INFO_SLOT is set.
    794   */
    795  using GeneratorWeakMap =
    796      DebuggerWeakMap<AbstractGeneratorObject, DebuggerFrame>;
    797  GeneratorWeakMap generatorFrames;
    798 
    799  // An ephemeral map from BaseScript* to Debugger.Script instances.
    800  using ScriptWeakMap = DebuggerWeakMap<BaseScript, DebuggerScript>;
    801  ScriptWeakMap scripts;
    802 
    803  using BaseScriptVector = JS::GCVector<BaseScript*>;
    804 
    805  // The map from debuggee source script objects to their Debugger.Source
    806  // instances.
    807  using SourceWeakMap =
    808      DebuggerWeakMap<ScriptSourceObject, DebuggerSource, true>;
    809  SourceWeakMap sources;
    810 
    811  // The map from debuggee objects to their Debugger.Object instances.
    812  using ObjectWeakMap = DebuggerWeakMap<JSObject, DebuggerObject>;
    813  ObjectWeakMap objects;
    814 
    815  // The map from debuggee Envs to Debugger.Environment instances.
    816  using EnvironmentWeakMap = DebuggerWeakMap<JSObject, DebuggerEnvironment>;
    817  EnvironmentWeakMap environments;
    818 
    819  // The map from WasmInstanceObjects to synthesized Debugger.Script
    820  // instances.
    821  using WasmInstanceScriptWeakMap =
    822      DebuggerWeakMap<WasmInstanceObject, DebuggerScript>;
    823  WasmInstanceScriptWeakMap wasmInstanceScripts;
    824 
    825  // The map from WasmInstanceObjects to synthesized Debugger.Source
    826  // instances.
    827  using WasmInstanceSourceWeakMap =
    828      DebuggerWeakMap<WasmInstanceObject, DebuggerSource>;
    829  WasmInstanceSourceWeakMap wasmInstanceSources;
    830 
    831  class QueryBase;
    832  class ScriptQuery;
    833  class SourceQuery;
    834  class ObjectQuery;
    835 
    836  enum class FromSweep { No, Yes };
    837 
    838  [[nodiscard]] bool addDebuggeeGlobal(JSContext* cx,
    839                                       Handle<GlobalObject*> obj);
    840  void removeDebuggeeGlobal(JS::GCContext* gcx, GlobalObject* global,
    841                            WeakGlobalObjectSet::Enum* debugEnum,
    842                            FromSweep fromSweep);
    843 
    844  /*
    845   * Handle the result of a hook that is expected to return a resumption
    846   * value <https://wiki.mozilla.org/Debugger#Resumption_Values>. This is
    847   * called when we return from a debugging hook to debuggee code.
    848   *
    849   * If `success` is false, the hook failed. If an exception is pending in
    850   * ar.context(), attempt to handle it via the uncaught exception hook,
    851   * otherwise report it to the AutoRealm's global.
    852   *
    853   * If `success` is true, there must be no exception pending in ar.context().
    854   * `rv` may be:
    855   *
    856   *     undefined - Set `resultMode` to `ResumeMode::Continue` to continue
    857   *         execution normally.
    858   *
    859   *     {return: value} or {throw: value} - Call unwrapDebuggeeValue to
    860   *         unwrap `value`. Store the result in `vp` and set `resultMode` to
    861   *         `ResumeMode::Return` or `ResumeMode::Throw`. The interpreter
    862   *         will force the current frame to return or throw an exception.
    863   *
    864   *     null - Set `resultMode` to `ResumeMode::Terminate` to terminate the
    865   *         debuggee with an uncatchable error.
    866   *
    867   *     anything else - Make a new TypeError the pending exception and
    868   *         attempt to handle it with the uncaught exception handler.
    869   */
    870  [[nodiscard]] bool processHandlerResult(
    871      JSContext* cx, bool success, HandleValue rv, AbstractFramePtr frame,
    872      jsbytecode* pc, ResumeMode& resultMode, MutableHandleValue vp);
    873 
    874  [[nodiscard]] bool processParsedHandlerResult(
    875      JSContext* cx, AbstractFramePtr frame, const jsbytecode* pc, bool success,
    876      ResumeMode resumeMode, HandleValue value, ResumeMode& resultMode,
    877      MutableHandleValue vp);
    878 
    879  /**
    880   * Given a resumption return value from a hook, parse and validate it based
    881   * on the given frame, and split the result into a ResumeMode and Value.
    882   */
    883  [[nodiscard]] bool prepareResumption(JSContext* cx, AbstractFramePtr frame,
    884                                       const jsbytecode* pc,
    885                                       ResumeMode& resumeMode,
    886                                       MutableHandleValue vp);
    887 
    888  /**
    889   * If there is a pending exception and a handler, call the handler with the
    890   * exception so that it can attempt to resolve the error.
    891   */
    892  [[nodiscard]] bool callUncaughtExceptionHandler(JSContext* cx,
    893                                                  MutableHandleValue vp);
    894 
    895  /**
    896   * If the context has a pending exception, report it to the current global.
    897   */
    898  void reportUncaughtException(JSContext* cx);
    899 
    900  /*
    901   * Call the uncaught exception handler if there is one, returning true
    902   * if it handled the error, or false otherwise.
    903   */
    904  [[nodiscard]] bool handleUncaughtException(JSContext* cx);
    905 
    906  GlobalObject* unwrapDebuggeeArgument(JSContext* cx, const Value& v);
    907 
    908  static void traceObject(JSTracer* trc, JSObject* obj);
    909 
    910  void trace(JSTracer* trc);
    911 
    912  void traceForMovingGC(JSTracer* trc);
    913  void traceCrossCompartmentEdges(JSTracer* tracer);
    914 
    915 private:
    916  template <typename F>
    917  void forEachWeakMap(const F& f);
    918 
    919  [[nodiscard]] static bool getHookImpl(JSContext* cx, const CallArgs& args,
    920                                        Debugger& dbg, Hook which);
    921  [[nodiscard]] static bool setHookImpl(JSContext* cx, const CallArgs& args,
    922                                        Debugger& dbg, Hook which);
    923 
    924  [[nodiscard]] static bool getGarbageCollectionHook(JSContext* cx,
    925                                                     const CallArgs& args,
    926                                                     Debugger& dbg);
    927  [[nodiscard]] static bool setGarbageCollectionHook(JSContext* cx,
    928                                                     const CallArgs& args,
    929                                                     Debugger& dbg);
    930 
    931  static bool isCompilableUnit(JSContext* cx, unsigned argc, Value* vp);
    932  static bool recordReplayProcessKind(JSContext* cx, unsigned argc, Value* vp);
    933  static bool construct(JSContext* cx, unsigned argc, Value* vp);
    934 
    935  struct CallData;
    936 
    937  static const JSPropertySpec properties[];
    938  static const JSFunctionSpec methods[];
    939  static const JSPropertySpec static_properties[];
    940  static const JSFunctionSpec static_methods[];
    941 
    942  /**
    943   * Suspend the DebuggerFrame, clearing on-stack data but leaving it linked
    944   * with the AbstractGeneratorObject so it can be re-used later.
    945   */
    946  static void suspendGeneratorDebuggerFrames(JSContext* cx,
    947                                             AbstractFramePtr frame);
    948 
    949  /**
    950   * Terminate the DebuggerFrame, clearing all data associated with the frame
    951   * so that it cannot be used to introspect stack frame data.
    952   */
    953  static void terminateDebuggerFrames(JSContext* cx, AbstractFramePtr frame);
    954 
    955  /**
    956   * Terminate a given DebuggerFrame, removing all internal state and all
    957   * references to the frame from the Debugger itself. If the frame is being
    958   * terminated while 'frames' or 'generatorFrames' are being iterated, pass a
    959   * pointer to the iteration Enum to remove the entry and ensure that iteration
    960   * behaves properly.
    961   *
    962   * The AbstractFramePtr may be omited in a call so long as it is either
    963   * called again later with the correct 'frame', or the frame itself has never
    964   * had on-stack data or a 'frames' entry and has never had an onStep handler.
    965   */
    966  static void terminateDebuggerFrame(
    967      JS::GCContext* gcx, Debugger* dbg, DebuggerFrame* dbgFrame,
    968      AbstractFramePtr frame, FrameMap::Enum* maybeFramesEnum = nullptr,
    969      GeneratorWeakMap::Enum* maybeGeneratorFramesEnum = nullptr);
    970 
    971  static bool updateExecutionObservabilityOfFrames(
    972      JSContext* cx, const DebugAPI::ExecutionObservableSet& obs,
    973      IsObserving observing);
    974  static bool updateExecutionObservabilityOfScripts(
    975      JSContext* cx, const DebugAPI::ExecutionObservableSet& obs,
    976      IsObserving observing);
    977  static bool updateExecutionObservability(
    978      JSContext* cx, DebugAPI::ExecutionObservableSet& obs,
    979      IsObserving observing);
    980 
    981  template <typename FrameFn /* void (Debugger*, DebuggerFrame*) */>
    982  static void forEachOnStackDebuggerFrame(AbstractFramePtr frame,
    983                                          const JS::AutoRequireNoGC& nogc,
    984                                          FrameFn fn);
    985  template <typename FrameFn /* void (Debugger*, DebuggerFrame*) */>
    986  static void forEachOnStackOrSuspendedDebuggerFrame(
    987      JSContext* cx, AbstractFramePtr frame, const JS::AutoRequireNoGC& nogc,
    988      FrameFn fn);
    989 
    990  /*
    991   * Return a vector containing all Debugger.Frame instances referring to
    992   * |frame|. |global| is |frame|'s global object; if nullptr or omitted, we
    993   * compute it ourselves from |frame|.
    994   */
    995  using DebuggerFrameVector = GCVector<DebuggerFrame*, 0, SystemAllocPolicy>;
    996  [[nodiscard]] static bool getDebuggerFrames(
    997      AbstractFramePtr frame, MutableHandle<DebuggerFrameVector> frames);
    998 
    999 public:
   1000  // Public for DebuggerScript::setBreakpoint.
   1001  [[nodiscard]] static bool ensureExecutionObservabilityOfScript(
   1002      JSContext* cx, JSScript* script);
   1003 
   1004  // Whether the Debugger instance needs to observe all non-AOT JS
   1005  // execution of its debugees.
   1006  IsObserving observesAllExecution() const;
   1007 
   1008  // Whether the Debugger instance needs to observe AOT-compiled asm.js
   1009  // execution of its debuggees.
   1010  IsObserving observesAsmJS() const;
   1011 
   1012  // Whether the Debugger instance needs to observe compiled Wasm
   1013  // execution of its debuggees.
   1014  IsObserving observesWasm() const;
   1015 
   1016  // Whether the Debugger instance needs to observe coverage of any JavaScript
   1017  // execution.
   1018  IsObserving observesCoverage() const;
   1019 
   1020  // Whether the Debugger instance needs to observe native call invocations.
   1021  IsObserving observesNativeCalls() const;
   1022 
   1023  bool isExclusiveDebuggerOnEval() const;
   1024 
   1025 private:
   1026  [[nodiscard]] static bool ensureExecutionObservabilityOfFrame(
   1027      JSContext* cx, AbstractFramePtr frame);
   1028  [[nodiscard]] static bool ensureExecutionObservabilityOfRealm(
   1029      JSContext* cx, JS::Realm* realm);
   1030 
   1031  static bool hookObservesAllExecution(Hook which);
   1032 
   1033  [[nodiscard]] bool updateObservesAllExecutionOnDebuggees(
   1034      JSContext* cx, IsObserving observing);
   1035  [[nodiscard]] bool updateObservesCoverageOnDebuggees(JSContext* cx,
   1036                                                       IsObserving observing);
   1037  void updateObservesAsmJSOnDebuggees(IsObserving observing);
   1038  void updateObservesWasmOnDebuggees(IsObserving observing);
   1039  void updateObservesNativeCallOnDebuggees(IsObserving observing);
   1040 
   1041  JSObject* getHook(Hook hook) const;
   1042  bool hasAnyLiveHooks() const;
   1043  inline bool isHookCallAllowed(JSContext* cx) const;
   1044 
   1045  static void slowPathPromiseHook(JSContext* cx, Hook hook,
   1046                                  Handle<PromiseObject*> promise);
   1047 
   1048  template <typename HookIsEnabledFun /* bool (Debugger*) */,
   1049            typename FireHookFun /* void (Debugger*) */>
   1050  static void dispatchQuietHook(JSContext* cx, HookIsEnabledFun hookIsEnabled,
   1051                                FireHookFun fireHook);
   1052  template <
   1053      typename HookIsEnabledFun /* bool (Debugger*) */, typename FireHookFun /* bool (Debugger*, ResumeMode&, MutableHandleValue) */>
   1054  [[nodiscard]] static bool dispatchResumptionHook(
   1055      JSContext* cx, AbstractFramePtr frame, HookIsEnabledFun hookIsEnabled,
   1056      FireHookFun fireHook);
   1057 
   1058  template <typename RunImpl /* bool () */>
   1059  [[nodiscard]] bool enterDebuggerHook(JSContext* cx, RunImpl runImpl) {
   1060    if (!isHookCallAllowed(cx)) {
   1061      return true;
   1062    }
   1063 
   1064    AutoRealm ar(cx, object);
   1065 
   1066    if (!runImpl()) {
   1067      // We do not want errors within one hook to effect errors in other hooks,
   1068      // so the only errors that we allow to propagate out of a debugger hook
   1069      // are OOM errors and general terminations.
   1070      if (!cx->isExceptionPending() || cx->isThrowingOutOfMemory()) {
   1071        return false;
   1072      }
   1073 
   1074      reportUncaughtException(cx);
   1075    }
   1076    MOZ_ASSERT(!cx->isExceptionPending());
   1077    return true;
   1078  }
   1079 
   1080  [[nodiscard]] bool fireDebuggerStatement(JSContext* cx,
   1081                                           ResumeMode& resumeMode,
   1082                                           MutableHandleValue vp);
   1083  [[nodiscard]] bool fireExceptionUnwind(JSContext* cx, HandleValue exc,
   1084                                         ResumeMode& resumeMode,
   1085                                         MutableHandleValue vp);
   1086  [[nodiscard]] bool fireEnterFrame(JSContext* cx, ResumeMode& resumeMode,
   1087                                    MutableHandleValue vp);
   1088  [[nodiscard]] bool fireNativeCall(JSContext* cx, const CallArgs& args,
   1089                                    CallReason reason, ResumeMode& resumeMode,
   1090                                    MutableHandleValue vp);
   1091  [[nodiscard]] bool fireNewGlobalObject(JSContext* cx,
   1092                                         Handle<GlobalObject*> global);
   1093  [[nodiscard]] bool firePromiseHook(JSContext* cx, Hook hook,
   1094                                     HandleObject promise);
   1095 
   1096  DebuggerScript* newVariantWrapper(JSContext* cx,
   1097                                    Handle<DebuggerScriptReferent> referent) {
   1098    return newDebuggerScript(cx, referent);
   1099  }
   1100  DebuggerSource* newVariantWrapper(JSContext* cx,
   1101                                    Handle<DebuggerSourceReferent> referent) {
   1102    return newDebuggerSource(cx, referent);
   1103  }
   1104 
   1105  /*
   1106   * Helper function to help wrap Debugger objects whose referents may be
   1107   * variants. Currently Debugger.Script and Debugger.Source referents may
   1108   * be variants.
   1109   *
   1110   * Prefer using wrapScript, wrapWasmScript, wrapSource, and wrapWasmSource
   1111   * whenever possible.
   1112   */
   1113  template <typename ReferentType, typename Map>
   1114  typename Map::WrapperType* wrapVariantReferent(
   1115      JSContext* cx, Map& map,
   1116      Handle<typename Map::WrapperType::ReferentVariant> referent);
   1117  DebuggerScript* wrapVariantReferent(JSContext* cx,
   1118                                      Handle<DebuggerScriptReferent> referent);
   1119  DebuggerSource* wrapVariantReferent(JSContext* cx,
   1120                                      Handle<DebuggerSourceReferent> referent);
   1121 
   1122  /*
   1123   * Allocate and initialize a Debugger.Script instance whose referent is
   1124   * |referent|.
   1125   */
   1126  DebuggerScript* newDebuggerScript(JSContext* cx,
   1127                                    Handle<DebuggerScriptReferent> referent);
   1128 
   1129  /*
   1130   * Allocate and initialize a Debugger.Source instance whose referent is
   1131   * |referent|.
   1132   */
   1133  DebuggerSource* newDebuggerSource(JSContext* cx,
   1134                                    Handle<DebuggerSourceReferent> referent);
   1135 
   1136  /*
   1137   * Receive a "new script" event from the engine. A new script was compiled
   1138   * or deserialized.
   1139   */
   1140  [[nodiscard]] bool fireNewScript(
   1141      JSContext* cx, Handle<DebuggerScriptReferent> scriptReferent);
   1142 
   1143  /*
   1144   * Receive a "garbage collection" event from the engine. A GC cycle with the
   1145   * given data was recently completed.
   1146   */
   1147  [[nodiscard]] bool fireOnGarbageCollectionHook(
   1148      JSContext* cx, const JS::dbg::GarbageCollectionEvent::Ptr& gcData);
   1149 
   1150  inline Breakpoint* firstBreakpoint() const;
   1151 
   1152  [[nodiscard]] static bool replaceFrameGuts(JSContext* cx,
   1153                                             AbstractFramePtr from,
   1154                                             AbstractFramePtr to,
   1155                                             ScriptFrameIter& iter);
   1156 
   1157 public:
   1158  Debugger(JSContext* cx, NativeObject* dbg);
   1159  ~Debugger();
   1160 
   1161  inline const js::HeapPtr<NativeObject*>& toJSObject() const;
   1162  inline js::HeapPtr<NativeObject*>& toJSObjectRef();
   1163  static inline Debugger* fromJSObject(const JSObject* obj);
   1164 
   1165 #ifdef DEBUG
   1166  static bool isChildJSObject(JSObject* obj);
   1167 #endif
   1168 
   1169  Zone* zone() const { return toJSObject()->zone(); }
   1170 
   1171  bool hasMemory() const;
   1172  DebuggerMemory& memory() const;
   1173 
   1174  WeakGlobalObjectSet::Range allDebuggees() const { return debuggees.all(); }
   1175 
   1176 #ifdef DEBUG
   1177  static bool isDebuggerCrossCompartmentEdge(JSObject* obj,
   1178                                             const js::gc::Cell* cell);
   1179 #endif
   1180 
   1181  static bool hasLiveHook(GlobalObject* global, Hook which);
   1182 
   1183  /*** Functions for use by Debugger.cpp. *********************************/
   1184 
   1185  inline bool observesEnterFrame() const;
   1186  inline bool observesNewScript() const;
   1187  inline bool observesNewGlobalObject() const;
   1188  inline bool observesGlobal(GlobalObject* global) const;
   1189  bool observesFrame(AbstractFramePtr frame) const;
   1190  bool observesFrame(const FrameIter& iter) const;
   1191  bool observesScript(JSScript* script) const;
   1192  bool observesWasm(wasm::Instance* instance) const;
   1193 
   1194  /*
   1195   * If env is nullptr, call vp->setNull() and return true. Otherwise, find
   1196   * or create a Debugger.Environment object for the given Env. On success,
   1197   * store the Environment object in *vp and return true.
   1198   */
   1199  [[nodiscard]] bool wrapEnvironment(JSContext* cx, Handle<Env*> env,
   1200                                     MutableHandleValue vp);
   1201  [[nodiscard]] bool wrapEnvironment(
   1202      JSContext* cx, Handle<Env*> env,
   1203      MutableHandle<DebuggerEnvironment*> result);
   1204 
   1205  /*
   1206   * Like cx->compartment()->wrap(cx, vp), but for the debugger realm.
   1207   *
   1208   * Preconditions: *vp is a value from a debuggee realm; cx is in the
   1209   * debugger's compartment.
   1210   *
   1211   * If *vp is an object, this produces a (new or existing) Debugger.Object
   1212   * wrapper for it. Otherwise this is the same as Compartment::wrap.
   1213   *
   1214   * If *vp is a magic JS_OPTIMIZED_OUT value, this produces a plain object
   1215   * of the form { optimizedOut: true }.
   1216   *
   1217   * If *vp is a magic JS_MISSING_ARGUMENTS value signifying missing
   1218   * arguments, this produces a plain object of the form { missingArguments:
   1219   * true }.
   1220   *
   1221   * If *vp is a magic JS_UNINITIALIZED_LEXICAL value signifying an
   1222   * unaccessible uninitialized binding, this produces a plain object of the
   1223   * form { uninitialized: true }.
   1224   */
   1225  [[nodiscard]] bool wrapDebuggeeValue(JSContext* cx, MutableHandleValue vp);
   1226  [[nodiscard]] bool wrapDebuggeeObject(JSContext* cx, HandleObject obj,
   1227                                        MutableHandle<DebuggerObject*> result);
   1228  [[nodiscard]] bool wrapNullableDebuggeeObject(
   1229      JSContext* cx, HandleObject obj, MutableHandle<DebuggerObject*> result);
   1230 
   1231  /*
   1232   * Unwrap a Debug.Object, without rewrapping it for any particular debuggee
   1233   * compartment.
   1234   *
   1235   * Preconditions: cx is in the debugger compartment. *vp is a value in that
   1236   * compartment. (*vp should be a "debuggee value", meaning it is the
   1237   * debugger's reflection of a value in the debuggee.)
   1238   *
   1239   * If *vp is a Debugger.Object, store the referent in *vp. Otherwise, if *vp
   1240   * is an object, throw a TypeError, because it is not a debuggee
   1241   * value. Otherwise *vp is a primitive, so leave it alone.
   1242   *
   1243   * When passing values from the debuggee to the debugger:
   1244   *     enter debugger compartment;
   1245   *     call wrapDebuggeeValue;  // compartment- and debugger-wrapping
   1246   *
   1247   * When passing values from the debugger to the debuggee:
   1248   *     call unwrapDebuggeeValue;  // debugger-unwrapping
   1249   *     enter debuggee realm;
   1250   *     call cx->compartment()->wrap;  // compartment-rewrapping
   1251   *
   1252   * (Extreme nerd sidebar: Unwrapping happens in two steps because there are
   1253   * two different kinds of symmetry at work: regardless of which direction
   1254   * we're going, we want any exceptions to be created and thrown in the
   1255   * debugger compartment--mirror symmetry. But compartment wrapping always
   1256   * happens in the target compartment--rotational symmetry.)
   1257   */
   1258  [[nodiscard]] bool unwrapDebuggeeValue(JSContext* cx, MutableHandleValue vp);
   1259  [[nodiscard]] bool unwrapDebuggeeObject(JSContext* cx,
   1260                                          MutableHandleObject obj);
   1261  [[nodiscard]] bool unwrapPropertyDescriptor(
   1262      JSContext* cx, HandleObject obj, MutableHandle<PropertyDescriptor> desc);
   1263 
   1264  /*
   1265   * Store the Debugger.Frame object for iter in *vp/result.
   1266   *
   1267   * If this Debugger does not already have a Frame object for the frame
   1268   * `iter` points to, a new Frame object is created, and `iter`'s private
   1269   * data is copied into it.
   1270   */
   1271  [[nodiscard]] bool getFrame(JSContext* cx, const FrameIter& iter,
   1272                              MutableHandleValue vp);
   1273  [[nodiscard]] bool getFrame(JSContext* cx,
   1274                              MutableHandle<DebuggerFrame*> result);
   1275  [[nodiscard]] bool getFrame(JSContext* cx, const FrameIter& iter,
   1276                              MutableHandle<DebuggerFrame*> result);
   1277  [[nodiscard]] bool getFrame(JSContext* cx,
   1278                              Handle<AbstractGeneratorObject*> genObj,
   1279                              MutableHandle<DebuggerFrame*> result);
   1280 
   1281  /*
   1282   * Return the Debugger.Script object for |script|, or create a new one if
   1283   * needed. The context |cx| must be in the debugger realm; |script| must be
   1284   * a script in a debuggee realm.
   1285   */
   1286  DebuggerScript* wrapScript(JSContext* cx, Handle<BaseScript*> script);
   1287 
   1288  /*
   1289   * Return the Debugger.Script object for |wasmInstance| (the toplevel
   1290   * script), synthesizing a new one if needed. The context |cx| must be in
   1291   * the debugger compartment; |wasmInstance| must be a WasmInstanceObject in
   1292   * the debuggee realm.
   1293   */
   1294  DebuggerScript* wrapWasmScript(JSContext* cx,
   1295                                 Handle<WasmInstanceObject*> wasmInstance);
   1296 
   1297  /*
   1298   * Return the Debugger.Source object for |source|, or create a new one if
   1299   * needed. The context |cx| must be in the debugger compartment; |source|
   1300   * must be a script source object in a debuggee realm.
   1301   */
   1302  DebuggerSource* wrapSource(JSContext* cx,
   1303                             js::Handle<ScriptSourceObject*> source);
   1304 
   1305  /*
   1306   * Return the Debugger.Source object for |wasmInstance| (the entire module),
   1307   * synthesizing a new one if needed. The context |cx| must be in the
   1308   * debugger compartment; |wasmInstance| must be a WasmInstanceObject in the
   1309   * debuggee realm.
   1310   */
   1311  DebuggerSource* wrapWasmSource(JSContext* cx,
   1312                                 Handle<WasmInstanceObject*> wasmInstance);
   1313 
   1314  DebuggerDebuggeeLink* getDebuggeeLink();
   1315 
   1316 private:
   1317  Debugger(const Debugger&) = delete;
   1318  Debugger& operator=(const Debugger&) = delete;
   1319 };
   1320 
   1321 // Specialize InternalBarrierMethods so we can have WeakHeapPtr<Debugger*>.
   1322 template <>
   1323 struct InternalBarrierMethods<Debugger*> {
   1324  static bool isMarkable(Debugger* dbg) { return dbg->toJSObject(); }
   1325 
   1326  static void postBarrier(Debugger** vp, Debugger* prev, Debugger* next) {}
   1327 
   1328  static void readBarrier(Debugger* dbg) {
   1329    InternalBarrierMethods<JSObject*>::readBarrier(dbg->toJSObject());
   1330  }
   1331 
   1332 #ifdef DEBUG
   1333  static void assertThingIsNotGray(Debugger* dbg) {}
   1334 #endif
   1335 };
   1336 
   1337 /**
   1338 * This class exists for one specific reason. If a given Debugger object is in
   1339 * a state where:
   1340 *
   1341 *   a) nothing in the system has a reference to the object
   1342 *   b) the debugger is currently attached to a live debuggee
   1343 *   c) the debugger has hooks like 'onEnterFrame'
   1344 *
   1345 * then we don't want the GC to delete the Debugger, because the system could
   1346 * still call the hooks. This means we need to ensure that, whenever the global
   1347 * gets marked, the Debugger will get marked as well. Critically, we _only_
   1348 * want that to happen if the debugger has hooks. If it doesn't, then GCing
   1349 * the debugger is the right think to do.
   1350 *
   1351 * Note that there are _other_ cases where the debugger may be held live, but
   1352 * those are not addressed by this case.
   1353 *
   1354 * To accomplish this, we use a bit of roundabout link approach. Both the
   1355 * Debugger and the debuggees can reach the link object:
   1356 *
   1357 *   Debugger  -> DebuggerDebuggeeLink  <- CCW <- Debuggee Global #1
   1358 *      |                  |    ^   ^---<- CCW <- Debuggee Global #2
   1359 *      \--<<-optional-<<--/     \------<- CCW <- Debuggee Global #3
   1360 *
   1361 * and critically, the Debugger is able to conditionally add or remove the link
   1362 * going from the DebuggerDebuggeeLink _back_ to the Debugger. When this link
   1363 * exists, the GC can trace all the way from the global to the Debugger,
   1364 * meaning that any Debugger with this link will be kept alive as long as any
   1365 * of its debuggees are alive.
   1366 */
   1367 class DebuggerDebuggeeLink : public NativeObject {
   1368 private:
   1369  enum {
   1370    DEBUGGER_LINK_SLOT,
   1371    RESERVED_SLOTS,
   1372  };
   1373 
   1374 public:
   1375  static const JSClass class_;
   1376 
   1377  void setLinkSlot(Debugger& dbg);
   1378  void clearLinkSlot();
   1379 };
   1380 
   1381 /*
   1382 * A Handler represents a Debugger API reflection object's handler function,
   1383 * like a Debugger.Frame's onStep handler. These handler functions are called by
   1384 * the Debugger API to notify the user of certain events. For each event type,
   1385 * we define a separate subclass of Handler.
   1386 *
   1387 * When a reflection object accepts a Handler, it calls its 'hold' method; and
   1388 * if the Handler is replaced by another, or the reflection object is finalized,
   1389 * the reflection object calls the Handler's 'drop' method. The reflection
   1390 * object does not otherwise manage the Handler's lifetime, say, by calling its
   1391 * destructor or freeing its memory. A simple Handler implementation might have
   1392 * an empty 'hold' method, and have its 'drop' method delete the Handler. A more
   1393 * complex Handler might process many kinds of events, and thus inherit from
   1394 * many Handler subclasses and be held by many reflection objects
   1395 * simultaneously; a handler like this could use 'hold' and 'drop' to manage a
   1396 * reference count.
   1397 *
   1398 * To support SpiderMonkey's memory use tracking, 'hold' and 'drop' also require
   1399 * a pointer to the owning reflection object, so that the Holder implementation
   1400 * can properly report changes in ownership to functions using the
   1401 * js::gc::MemoryUse categories.
   1402 */
   1403 struct Handler {
   1404  virtual ~Handler() = default;
   1405 
   1406  /*
   1407   * If this Handler is a reference to a callable JSObject, return that
   1408   * JSObject. Otherwise, this method returns nullptr.
   1409   *
   1410   * The JavaScript getters for handler properties on reflection objects use
   1411   * this method to obtain the callable the handler represents. When a Handler's
   1412   * 'object' method returns nullptr, that handler is simply not visible to
   1413   * JavaScript.
   1414   */
   1415  virtual JSObject* object() const = 0;
   1416 
   1417  /* Report that this Handler is now held by owner. See comment above. */
   1418  virtual void hold(JSObject* owner) = 0;
   1419 
   1420  /* Report that this Handler is no longer held by owner. See comment above. */
   1421  virtual void drop(JS::GCContext* gcx, JSObject* owner) = 0;
   1422 
   1423  /*
   1424   * Trace the reference to the handler. This method will be called by the
   1425   * reflection object holding this Handler whenever the former is traced.
   1426   */
   1427  virtual void trace(JSTracer* tracer) = 0;
   1428 
   1429  /* Allocation size in bytes for memory accounting purposes. */
   1430  virtual size_t allocSize() const = 0;
   1431 };
   1432 
   1433 class JSBreakpointSite;
   1434 class WasmBreakpointSite;
   1435 
   1436 /**
   1437 * Breakpoint GC rules:
   1438 *
   1439 * BreakpointSites and Breakpoints are owned by the code in which they are set.
   1440 * Tracing a JSScript or WasmInstance traces all BreakpointSites set in it,
   1441 * which traces all Breakpoints; and if the code is garbage collected, the
   1442 * BreakpointSite and the Breakpoints set at it are freed as well. Doing so is
   1443 * not observable to JS, since the handlers would never fire, and there is no
   1444 * way to enumerate all breakpoints without specifying a specific script, in
   1445 * which case it must not have been GC'd.
   1446 *
   1447 * Although BreakpointSites and Breakpoints are not GC things, they should be
   1448 * treated as belonging to the code's compartment. This means that the
   1449 * BreakpointSite concrete subclasses' pointers to the code are not
   1450 * cross-compartment references, but a Breakpoint's pointers to its handler and
   1451 * owning Debugger are cross-compartment references, and go through
   1452 * cross-compartment wrappers.
   1453 */
   1454 
   1455 /**
   1456 * A location in a JSScript or WasmInstance at which we have breakpoints. A
   1457 * BreakpointSite owns a linked list of all the breakpoints set at its location.
   1458 * In general, this list contains breakpoints set by multiple Debuggers in
   1459 * various compartments.
   1460 *
   1461 * BreakpointSites are created only as needed, for locations at which
   1462 * breakpoints are currently set. When the last breakpoint is removed from a
   1463 * location, the BreakpointSite is removed as well.
   1464 *
   1465 * This is an abstract base class, with subclasses specialized for the different
   1466 * sorts of code a breakpoint might be set in. JSBreakpointSite manages sites in
   1467 * JSScripts, and WasmBreakpointSite manages sites in WasmInstances.
   1468 */
   1469 class BreakpointSite {
   1470  friend class DebugAPI;
   1471  friend class Breakpoint;
   1472  friend class Debugger;
   1473 
   1474 private:
   1475  template <typename T>
   1476  struct SiteLinkAccess {
   1477    static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) {
   1478      return aThis->siteLink;
   1479    }
   1480    static const mozilla::DoublyLinkedListElement<T>& Get(const T* aThis) {
   1481      return aThis->siteLink;
   1482    }
   1483  };
   1484 
   1485  // List of all js::Breakpoints at this instruction.
   1486  using BreakpointList =
   1487      mozilla::DoublyLinkedList<js::Breakpoint, SiteLinkAccess<js::Breakpoint>>;
   1488  BreakpointList breakpoints;
   1489 
   1490 protected:
   1491  BreakpointSite() = default;
   1492  virtual ~BreakpointSite() = default;
   1493  void finalize(JS::GCContext* gcx);
   1494  virtual gc::Cell* owningCell() = 0;
   1495 
   1496 public:
   1497  Breakpoint* firstBreakpoint() const;
   1498  bool hasBreakpoint(Breakpoint* bp);
   1499 
   1500  bool isEmpty() const;
   1501  virtual void trace(JSTracer* trc);
   1502  virtual void remove(JS::GCContext* gcx) = 0;
   1503  void destroyIfEmpty(JS::GCContext* gcx) {
   1504    if (isEmpty()) {
   1505      remove(gcx);
   1506    }
   1507  }
   1508  virtual Realm* realm() const = 0;
   1509 };
   1510 
   1511 /*
   1512 * A breakpoint set at a given BreakpointSite, indicating the owning debugger
   1513 * and the handler object. A Breakpoint is a member of two linked lists: its
   1514 * owning debugger's list and its site's list.
   1515 */
   1516 class Breakpoint {
   1517  friend class DebugAPI;
   1518  friend class Debugger;
   1519  friend class BreakpointSite;
   1520 
   1521 public:
   1522  /* Our owning debugger. */
   1523  Debugger* const debugger;
   1524 
   1525  /**
   1526   * A cross-compartment wrapper for our owning debugger's object, a CCW in the
   1527   * code's compartment to the Debugger object in its own compartment. Holding
   1528   * this lets the GC know about the effective cross-compartment reference from
   1529   * the code to the debugger; see "Breakpoint GC Rules", above.
   1530   *
   1531   * This is almost redundant with the `debugger` field, except that we need
   1532   * access to our owning `Debugger` regardless of the relative privilege levels
   1533   * of debugger and debuggee, regardless of whether we're in the midst of a GC,
   1534   * and so on - unwrapping is just too entangled.
   1535   */
   1536  const HeapPtr<JSObject*> wrappedDebugger;
   1537 
   1538  /* The site at which we're inserted. */
   1539  BreakpointSite* const site;
   1540 
   1541 private:
   1542  /**
   1543   * The breakpoint handler object, via a cross-compartment wrapper in the
   1544   * code's compartment.
   1545   *
   1546   * Although eventually we would like this to be a `js::Handler` instance, for
   1547   * now it is just cross-compartment wrapper for the JS object supplied to
   1548   * `setBreakpoint`, hopefully with a callable `hit` property.
   1549   */
   1550  const HeapPtr<JSObject*> handler;
   1551 
   1552  /**
   1553   * Link elements for each list this breakpoint can be in.
   1554   */
   1555  mozilla::DoublyLinkedListElement<Breakpoint> debuggerLink;
   1556  mozilla::DoublyLinkedListElement<Breakpoint> siteLink;
   1557 
   1558  void trace(JSTracer* trc);
   1559 
   1560 public:
   1561  Breakpoint(Debugger* debugger, HandleObject wrappedDebugger,
   1562             BreakpointSite* site, HandleObject handler);
   1563 
   1564  enum MayDestroySite { False, True };
   1565 
   1566  /**
   1567   * Unlink this breakpoint from its Debugger's and and BreakpointSite's lists,
   1568   * and free its memory.
   1569   *
   1570   * This is the low-level primitive shared by breakpoint removal and script
   1571   * finalization code. It is only concerned with cleaning up this Breakpoint;
   1572   * it does not check for now-empty BreakpointSites, unneeded DebugScripts, or
   1573   * the like.
   1574   */
   1575  void delete_(JS::GCContext* gcx);
   1576 
   1577  /**
   1578   * Remove this breakpoint. Unlink it from its Debugger's and BreakpointSite's
   1579   * lists, and if the BreakpointSite is now empty, clean that up and update JIT
   1580   * code as necessary.
   1581   */
   1582  void remove(JS::GCContext* gcx);
   1583 
   1584  Breakpoint* nextInDebugger();
   1585  Breakpoint* nextInSite();
   1586  JSObject* getHandler() const { return handler; }
   1587 };
   1588 
   1589 class JSBreakpointSite : public BreakpointSite {
   1590 public:
   1591  const HeapPtr<JSScript*> script;
   1592  jsbytecode* const pc;
   1593 
   1594 public:
   1595  JSBreakpointSite(JSScript* script, jsbytecode* pc);
   1596 
   1597  void trace(JSTracer* trc) override;
   1598  void delete_(JS::GCContext* gcx);
   1599  void remove(JS::GCContext* gcx) override;
   1600  Realm* realm() const override;
   1601 
   1602 private:
   1603  gc::Cell* owningCell() override;
   1604 };
   1605 
   1606 class WasmBreakpointSite : public BreakpointSite {
   1607 public:
   1608  const HeapPtr<WasmInstanceObject*> instanceObject;
   1609  uint32_t offset;
   1610 
   1611 public:
   1612  WasmBreakpointSite(WasmInstanceObject* instanceObject, uint32_t offset);
   1613 
   1614  void trace(JSTracer* trc) override;
   1615  void delete_(JS::GCContext* gcx);
   1616  void remove(JS::GCContext* gcx) override;
   1617  Realm* realm() const override;
   1618 
   1619 private:
   1620  gc::Cell* owningCell() override;
   1621 };
   1622 
   1623 Breakpoint* Debugger::firstBreakpoint() const {
   1624  if (breakpoints.isEmpty()) {
   1625    return nullptr;
   1626  }
   1627  return &(*breakpoints.begin());
   1628 }
   1629 
   1630 const js::HeapPtr<NativeObject*>& Debugger::toJSObject() const {
   1631  MOZ_ASSERT(object);
   1632  return object;
   1633 }
   1634 
   1635 js::HeapPtr<NativeObject*>& Debugger::toJSObjectRef() {
   1636  MOZ_ASSERT(object);
   1637  return object;
   1638 }
   1639 
   1640 bool Debugger::observesEnterFrame() const { return getHook(OnEnterFrame); }
   1641 
   1642 bool Debugger::observesNewScript() const { return getHook(OnNewScript); }
   1643 
   1644 bool Debugger::observesNewGlobalObject() const {
   1645  return getHook(OnNewGlobalObject);
   1646 }
   1647 
   1648 bool Debugger::observesGlobal(GlobalObject* global) const {
   1649  WeakHeapPtr<GlobalObject*> debuggee(global);
   1650  return debuggees.has(debuggee);
   1651 }
   1652 
   1653 [[nodiscard]] bool ReportObjectRequired(JSContext* cx);
   1654 
   1655 JSObject* IdVectorToArray(JSContext* cx, HandleIdVector ids);
   1656 bool IsInterpretedNonSelfHostedFunction(JSFunction* fun);
   1657 JSScript* GetOrCreateFunctionScript(JSContext* cx, HandleFunction fun);
   1658 ArrayObject* GetFunctionParameterNamesArray(JSContext* cx, HandleFunction fun);
   1659 bool ValueToIdentifier(JSContext* cx, HandleValue v, MutableHandleId id);
   1660 bool ValueToStableChars(JSContext* cx, const char* fnname, HandleValue value,
   1661                        JS::AutoStableStringChars& stableChars);
   1662 bool ParseEvalOptions(JSContext* cx, HandleValue value, EvalOptions& options);
   1663 
   1664 Result<Completion> DebuggerGenericEval(
   1665    JSContext* cx, const mozilla::Range<const char16_t> chars,
   1666    HandleObject bindings, const EvalOptions& options, Debugger* dbg,
   1667    HandleObject envArg, FrameIter* iter);
   1668 
   1669 bool ParseResumptionValue(JSContext* cx, HandleValue rval,
   1670                          ResumeMode& resumeMode, MutableHandleValue vp);
   1671 
   1672 #define JS_DEBUG_PSG(Name, Getter) \
   1673  JS_PSG(Name, CallData::ToNative<&CallData::Getter>, 0)
   1674 
   1675 #define JS_DEBUG_PSGS(Name, Getter, Setter)            \
   1676  JS_PSGS(Name, CallData::ToNative<&CallData::Getter>, \
   1677          CallData::ToNative<&CallData::Setter>, 0)
   1678 
   1679 #define JS_DEBUG_FN(Name, Method, NumArgs) \
   1680  JS_FN(Name, CallData::ToNative<&CallData::Method>, NumArgs, 0)
   1681 
   1682 } /* namespace js */
   1683 
   1684 #endif /* debugger_Debugger_h */