LCOV - code coverage report
Current view: top level - js/src/vm - Debugger.h (source / functions) Hit Total Coverage
Test: output.info Lines: 10 137 7.3 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef vm_Debugger_h
       8             : #define vm_Debugger_h
       9             : 
      10             : #include "mozilla/DoublyLinkedList.h"
      11             : #include "mozilla/GuardObjects.h"
      12             : #include "mozilla/LinkedList.h"
      13             : #include "mozilla/Range.h"
      14             : #include "mozilla/TimeStamp.h"
      15             : #include "mozilla/Vector.h"
      16             : 
      17             : #include "builtin/Promise.h"
      18             : #include "ds/TraceableFifo.h"
      19             : #include "gc/Barrier.h"
      20             : #include "gc/WeakMap.h"
      21             : #include "js/Debug.h"
      22             : #include "js/GCVariant.h"
      23             : #include "js/HashTable.h"
      24             : #include "js/Utility.h"
      25             : #include "js/Wrapper.h"
      26             : #include "vm/GlobalObject.h"
      27             : #include "vm/JSContext.h"
      28             : #include "vm/Realm.h"
      29             : #include "vm/SavedStacks.h"
      30             : #include "vm/Stack.h"
      31             : #include "wasm/WasmJS.h"
      32             : 
      33             : namespace js {
      34             : 
      35             : /**
      36             :  * Tells how the JS engine should resume debuggee execution after firing a
      37             :  * debugger hook.  Most debugger hooks get to choose how the debuggee proceeds;
      38             :  * see js/src/doc/Debugger/Conventions.md under "Resumption Values".
      39             :  *
      40             :  * Debugger::processHandlerResult() translates between JavaScript values and
      41             :  * this enum.
      42             :  *
      43             :  * The values `ResumeMode::Throw` and `ResumeMode::Return` are always
      44             :  * associated with a value (the exception value or return value). Sometimes
      45             :  * this is represented as an explicit `JS::Value` variable or parameter,
      46             :  * declared alongside the `ResumeMode`. In other cases, especially when
      47             :  * ResumeMode is used as a return type (as in Debugger::onEnterFrame), the
      48             :  * value is stashed in `cx`'s pending exception slot or the topmost frame's
      49             :  * return value slot.
      50             :  */
      51             : enum class ResumeMode {
      52             :     /**
      53             :      * The debuggee should continue unchanged.
      54             :      *
      55             :      * This corresponds to a resumption value of `undefined`.
      56             :      */
      57             :     Continue,
      58             : 
      59             :     /**
      60             :      * Throw an exception in the debuggee.
      61             :      *
      62             :      * This corresponds to a resumption value of `{throw: <value>}`.
      63             :      */
      64             :     Throw,
      65             : 
      66             :     /**
      67             :      * Terminate the debuggee, as if it had been cancelled via the "slow
      68             :      * script" ribbon.
      69             :      *
      70             :      * This corresponds to a resumption value of `null`.
      71             :      */
      72             :     Terminate,
      73             : 
      74             :     /**
      75             :      * Force the debuggee to return from the current frame.
      76             :      *
      77             :      * This corresponds to a resumption value of `{return: <value>}`.
      78             :      */
      79             :     Return,
      80             : };
      81             : 
      82             : class Breakpoint;
      83             : class DebuggerMemory;
      84             : class ScriptedOnStepHandler;
      85             : class ScriptedOnPopHandler;
      86             : class WasmInstanceObject;
      87             : 
      88             : typedef HashSet<ReadBarrieredGlobalObject,
      89             :                 MovableCellHasher<ReadBarrieredGlobalObject>,
      90             :                 ZoneAllocPolicy> WeakGlobalObjectSet;
      91             : 
      92             : /*
      93             :  * A weakmap from GC thing keys to JSObject values that supports the keys being
      94             :  * in different compartments to the values. All values must be in the same
      95             :  * compartment.
      96             :  *
      97             :  * The purpose of this is to allow the garbage collector to easily find edges
      98             :  * from debuggee object compartments to debugger compartments when calculating
      99             :  * the compartment groups.  Note that these edges are the inverse of the edges
     100             :  * stored in the cross compartment map.
     101             :  *
     102             :  * The current implementation results in all debuggee object compartments being
     103             :  * swept in the same group as the debugger.  This is a conservative approach,
     104             :  * and compartments may be unnecessarily grouped, however it results in a
     105             :  * simpler and faster implementation.
     106             :  *
     107             :  * If InvisibleKeysOk is true, then the map can have keys in invisible-to-
     108             :  * debugger compartments. If it is false, we assert that such entries are never
     109             :  * created.
     110             :  *
     111             :  * Also note that keys in these weakmaps can be in any compartment, debuggee or
     112             :  * not, because they cannot be deleted when a compartment is no longer a
     113             :  * debuggee: the values need to maintain object identity across add/remove/add
     114             :  * transitions.
     115             :  */
     116             : template <class UnbarrieredKey, bool InvisibleKeysOk=false>
     117           0 : class DebuggerWeakMap : private WeakMap<HeapPtr<UnbarrieredKey>, HeapPtr<JSObject*>,
     118             :                                         MovableCellHasher<HeapPtr<UnbarrieredKey>>>
     119             : {
     120             :   private:
     121             :     typedef HeapPtr<UnbarrieredKey> Key;
     122             :     typedef HeapPtr<JSObject*> Value;
     123             : 
     124             :     typedef HashMap<JS::Zone*,
     125             :                     uintptr_t,
     126             :                     DefaultHasher<JS::Zone*>,
     127             :                     ZoneAllocPolicy> CountMap;
     128             : 
     129             :     CountMap zoneCounts;
     130             :     JS::Compartment* compartment;
     131             : 
     132             :   public:
     133             :     typedef WeakMap<Key, Value, MovableCellHasher<Key>> Base;
     134             : 
     135           0 :     explicit DebuggerWeakMap(JSContext* cx)
     136             :         : Base(cx),
     137             :           zoneCounts(cx->zone()),
     138           0 :           compartment(cx->compartment())
     139           0 :     { }
     140             : 
     141             :   public:
     142             :     /* Expose those parts of HashMap public interface that are used by Debugger methods. */
     143             : 
     144             :     typedef typename Base::Entry Entry;
     145             :     typedef typename Base::Ptr Ptr;
     146             :     typedef typename Base::AddPtr AddPtr;
     147             :     typedef typename Base::Range Range;
     148             :     typedef typename Base::Enum Enum;
     149             :     typedef typename Base::Lookup Lookup;
     150             : 
     151             :     /* Expose WeakMap public interface */
     152             : 
     153             :     using Base::lookupForAdd;
     154             :     using Base::all;
     155             :     using Base::trace;
     156             : 
     157           0 :     MOZ_MUST_USE bool init(uint32_t len = 16) {
     158           0 :         return Base::init(len) && zoneCounts.init();
     159             :     }
     160             : 
     161             :     template<typename KeyInput, typename ValueInput>
     162           0 :     bool relookupOrAdd(AddPtr& p, const KeyInput& k, const ValueInput& v) {
     163           0 :         MOZ_ASSERT(v->compartment() == this->compartment);
     164           0 :         MOZ_ASSERT(!k->realm()->creationOptions().mergeable());
     165           0 :         MOZ_ASSERT_IF(!InvisibleKeysOk,
     166             :                       !k->realm()->creationOptions().invisibleToDebugger());
     167           0 :         MOZ_ASSERT(!Base::has(k));
     168           0 :         if (!incZoneCount(k->zone()))
     169             :             return false;
     170           0 :         bool ok = Base::relookupOrAdd(p, k, v);
     171           0 :         if (!ok)
     172           0 :             decZoneCount(k->zone());
     173             :         return ok;
     174             :     }
     175             : 
     176           0 :     void remove(const Lookup& l) {
     177           0 :         MOZ_ASSERT(Base::has(l));
     178           0 :         Base::remove(l);
     179           0 :         decZoneCount(l->zone());
     180           0 :     }
     181             : 
     182             :   public:
     183             :     template <void (traceValueEdges)(JSTracer*, JSObject*)>
     184           0 :     void traceCrossCompartmentEdges(JSTracer* tracer) {
     185           0 :         for (Enum e(*static_cast<Base*>(this)); !e.empty(); e.popFront()) {
     186           0 :             traceValueEdges(tracer, e.front().value());
     187           0 :             Key key = e.front().key();
     188           0 :             TraceEdge(tracer, &key, "Debugger WeakMap key");
     189           0 :             if (key != e.front().key())
     190             :                 e.rekeyFront(key);
     191           0 :             key.unsafeSet(nullptr);
     192             :         }
     193           0 :     }
     194             : 
     195           0 :     bool hasKeyInZone(JS::Zone* zone) {
     196           0 :         CountMap::Ptr p = zoneCounts.lookup(zone);
     197           0 :         MOZ_ASSERT_IF(p.found(), p->value() > 0);
     198           0 :         return p.found();
     199             :     }
     200             : 
     201             :   private:
     202             :     /* Override sweep method to also update our edge cache. */
     203           0 :     void sweep() override {
     204           0 :         MOZ_ASSERT(CurrentThreadIsPerformingGC());
     205           0 :         for (Enum e(*static_cast<Base*>(this)); !e.empty(); e.popFront()) {
     206           0 :             if (gc::IsAboutToBeFinalized(&e.front().mutableKey())) {
     207           0 :                 decZoneCount(e.front().key()->zoneFromAnyThread());
     208             :                 e.removeFront();
     209             :             }
     210             :         }
     211           0 :         Base::assertEntriesNotAboutToBeFinalized();
     212           0 :     }
     213             : 
     214           0 :     MOZ_MUST_USE bool incZoneCount(JS::Zone* zone) {
     215           0 :         CountMap::Ptr p = zoneCounts.lookupWithDefault(zone, 0);
     216           0 :         if (!p)
     217             :             return false;
     218           0 :         ++p->value();
     219           0 :         return true;
     220             :     }
     221             : 
     222           0 :     void decZoneCount(JS::Zone* zone) {
     223           0 :         CountMap::Ptr p = zoneCounts.lookup(zone);
     224           0 :         MOZ_ASSERT(p);
     225           0 :         MOZ_ASSERT(p->value() > 0);
     226           0 :         --p->value();
     227           0 :         if (p->value() == 0)
     228           0 :             zoneCounts.remove(zone);
     229           0 :     }
     230             : };
     231             : 
     232             : class LeaveDebuggeeNoExecute;
     233             : 
     234             : // Suppresses all debuggee NX checks, i.e., allow all execution. Used to allow
     235             : // certain whitelisted operations to execute code.
     236             : //
     237             : // WARNING
     238             : // WARNING Do not use this unless you know what you are doing!
     239             : // WARNING
     240             : class AutoSuppressDebuggeeNoExecuteChecks
     241             : {
     242             :     EnterDebuggeeNoExecute** stack_;
     243             :     EnterDebuggeeNoExecute* prev_;
     244             : 
     245             :   public:
     246           0 :     explicit AutoSuppressDebuggeeNoExecuteChecks(JSContext* cx) {
     247           0 :         stack_ = &cx->noExecuteDebuggerTop.ref();
     248           0 :         prev_ = *stack_;
     249         644 :         *stack_ = nullptr;
     250             :     }
     251             : 
     252           0 :     ~AutoSuppressDebuggeeNoExecuteChecks() {
     253           0 :         MOZ_ASSERT(!*stack_);
     254           0 :         *stack_ = prev_;
     255         644 :     }
     256             : };
     257             : 
     258             : class MOZ_RAII EvalOptions {
     259             :     JS::UniqueChars filename_;
     260             :     unsigned lineno_ = 1;
     261             : 
     262             :   public:
     263           0 :     EvalOptions() = default;
     264           0 :     ~EvalOptions() = default;
     265           0 :     const char* filename() const { return filename_.get(); }
     266             :     unsigned lineno() const { return lineno_; }
     267             :     MOZ_MUST_USE bool setFilename(JSContext* cx, const char* filename);
     268           0 :     void setLineno(unsigned lineno) { lineno_ = lineno; }
     269             : };
     270             : 
     271             : /*
     272             :  * Env is the type of what ES5 calls "lexical environments" (runtime activations
     273             :  * of lexical scopes). This is currently just JSObject, and is implemented by
     274             :  * CallObject, LexicalEnvironmentObject, and WithEnvironmentObject, among
     275             :  * others--but environments and objects are really two different concepts.
     276             :  */
     277             : typedef JSObject Env;
     278             : 
     279             : // Either a real JSScript or synthesized.
     280             : //
     281             : // If synthesized, the referent is one of the following:
     282             : //
     283             : //   1. A WasmInstanceObject, denoting a synthesized toplevel wasm module
     284             : //      script.
     285             : //   2. A wasm JSFunction, denoting a synthesized wasm function script.
     286             : //      NYI!
     287             : typedef mozilla::Variant<JSScript*, WasmInstanceObject*> DebuggerScriptReferent;
     288             : 
     289             : // Either a ScriptSourceObject, for ordinary JS, or a WasmInstanceObject,
     290             : // denoting the synthesized source of a wasm module.
     291             : typedef mozilla::Variant<ScriptSourceObject*, WasmInstanceObject*> DebuggerSourceReferent;
     292             : 
     293             : class Debugger : private mozilla::LinkedListElement<Debugger>
     294             : {
     295             :     friend class Breakpoint;
     296             :     friend class DebuggerMemory;
     297             :     friend struct JSRuntime::GlobalObjectWatchersLinkAccess<Debugger>;
     298             :     friend class SavedStacks;
     299             :     friend class ScriptedOnStepHandler;
     300             :     friend class ScriptedOnPopHandler;
     301             :     friend class mozilla::LinkedListElement<Debugger>;
     302             :     friend class mozilla::LinkedList<Debugger>;
     303             :     friend bool (::JS_DefineDebuggerObject)(JSContext* cx, JS::HandleObject obj);
     304             :     friend bool (::JS::dbg::IsDebugger)(JSObject&);
     305             :     friend bool (::JS::dbg::GetDebuggeeGlobals)(JSContext*, JSObject&, AutoObjectVector&);
     306             :     friend bool JS::dbg::FireOnGarbageCollectionHookRequired(JSContext* cx);
     307             :     friend bool JS::dbg::FireOnGarbageCollectionHook(JSContext* cx,
     308             :                                                      JS::dbg::GarbageCollectionEvent::Ptr&& data);
     309             : 
     310             :   public:
     311             :     enum Hook {
     312             :         OnDebuggerStatement,
     313             :         OnExceptionUnwind,
     314             :         OnNewScript,
     315             :         OnEnterFrame,
     316             :         OnNewGlobalObject,
     317             :         OnNewPromise,
     318             :         OnPromiseSettled,
     319             :         OnGarbageCollection,
     320             :         HookCount
     321             :     };
     322             :     enum {
     323             :         JSSLOT_DEBUG_PROTO_START,
     324             :         JSSLOT_DEBUG_FRAME_PROTO = JSSLOT_DEBUG_PROTO_START,
     325             :         JSSLOT_DEBUG_ENV_PROTO,
     326             :         JSSLOT_DEBUG_OBJECT_PROTO,
     327             :         JSSLOT_DEBUG_SCRIPT_PROTO,
     328             :         JSSLOT_DEBUG_SOURCE_PROTO,
     329             :         JSSLOT_DEBUG_MEMORY_PROTO,
     330             :         JSSLOT_DEBUG_PROTO_STOP,
     331             :         JSSLOT_DEBUG_HOOK_START = JSSLOT_DEBUG_PROTO_STOP,
     332             :         JSSLOT_DEBUG_HOOK_STOP = JSSLOT_DEBUG_HOOK_START + HookCount,
     333             :         JSSLOT_DEBUG_MEMORY_INSTANCE = JSSLOT_DEBUG_HOOK_STOP,
     334             :         JSSLOT_DEBUG_COUNT
     335             :     };
     336             : 
     337             :     class ExecutionObservableSet
     338             :     {
     339             :       public:
     340             :         typedef HashSet<Zone*>::Range ZoneRange;
     341             : 
     342           0 :         virtual Zone* singleZone() const { return nullptr; }
     343           0 :         virtual JSScript* singleScriptForZoneInvalidation() const { return nullptr; }
     344           0 :         virtual const HashSet<Zone*>* zones() const { return nullptr; }
     345             : 
     346             :         virtual bool shouldRecompileOrInvalidate(JSScript* script) const = 0;
     347             :         virtual bool shouldMarkAsDebuggee(FrameIter& iter) const = 0;
     348             :     };
     349             : 
     350             :     // This enum is converted to and compare with bool values; NotObserving
     351             :     // must be 0 and Observing must be 1.
     352             :     enum IsObserving {
     353             :         NotObserving = 0,
     354             :         Observing = 1
     355             :     };
     356             : 
     357             :     // Return true if the given realm is a debuggee of this debugger,
     358             :     // false otherwise.
     359             :     bool isDebuggeeUnbarriered(const Realm* realm) const;
     360             : 
     361             :     // Return true if this Debugger observed a debuggee that participated in the
     362             :     // GC identified by the given GC number. Return false otherwise.
     363             :     // May return false negatives if we have hit OOM.
     364             :     bool observedGC(uint64_t majorGCNumber) const {
     365           0 :         return observedGCs.has(majorGCNumber);
     366             :     }
     367             : 
     368             :     // Notify this Debugger that one or more of its debuggees is participating
     369             :     // in the GC identified by the given GC number.
     370             :     bool debuggeeIsBeingCollected(uint64_t majorGCNumber) {
     371           0 :         return observedGCs.put(majorGCNumber);
     372             :     }
     373             : 
     374             :     bool isEnabled() const {
     375             :         return enabled;
     376             :     }
     377             : 
     378             :     static SavedFrame* getObjectAllocationSite(JSObject& obj);
     379             : 
     380           0 :     struct AllocationsLogEntry
     381             :     {
     382           0 :         AllocationsLogEntry(HandleObject frame, mozilla::TimeStamp when, const char* className,
     383             :                             HandleAtom ctorName, size_t size, bool inNursery)
     384           0 :             : frame(frame),
     385             :               when(when),
     386             :               className(className),
     387             :               ctorName(ctorName),
     388             :               size(size),
     389           0 :               inNursery(inNursery)
     390             :         {
     391           0 :             MOZ_ASSERT_IF(frame, UncheckedUnwrap(frame)->is<SavedFrame>());
     392           0 :         };
     393             : 
     394             :         HeapPtr<JSObject*> frame;
     395             :         mozilla::TimeStamp when;
     396             :         const char* className;
     397             :         HeapPtr<JSAtom*> ctorName;
     398             :         size_t size;
     399             :         bool inNursery;
     400             : 
     401           0 :         void trace(JSTracer* trc) {
     402           0 :             TraceNullableEdge(trc, &frame, "Debugger::AllocationsLogEntry::frame");
     403           0 :             TraceNullableEdge(trc, &ctorName, "Debugger::AllocationsLogEntry::ctorName");
     404           0 :         }
     405             :     };
     406             : 
     407             :     // Barrier methods so we can have ReadBarriered<Debugger*>.
     408             :     static void readBarrier(Debugger* dbg) {
     409           0 :         InternalBarrierMethods<JSObject*>::readBarrier(dbg->object);
     410             :     }
     411             :     static void writeBarrierPost(Debugger** vp, Debugger* prev, Debugger* next) {}
     412             : #ifdef DEBUG
     413             :     static bool thingIsNotGray(Debugger* dbg) { return true; }
     414             : #endif
     415             : 
     416             :   private:
     417             :     GCPtrNativeObject object; /* The Debugger object. Strong reference. */
     418             :     WeakGlobalObjectSet debuggees; /* Debuggee globals. Cross-compartment weak references. */
     419             :     JS::ZoneSet debuggeeZones; /* Set of zones that we have debuggees in. */
     420             :     js::GCPtrObject uncaughtExceptionHook; /* Strong reference. */
     421             :     bool enabled;
     422             :     bool allowUnobservedAsmJS;
     423             :     bool allowWasmBinarySource;
     424             : 
     425             :     // Whether to enable code coverage on the Debuggee.
     426             :     bool collectCoverageInfo;
     427             : 
     428             :     template <typename T>
     429             :     struct DebuggerLinkAccess {
     430             :       static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) {
     431             :         return aThis->debuggerLink;
     432             :       }
     433             :     };
     434             : 
     435             :     // List of all js::Breakpoints in this debugger.
     436             :     using BreakpointList =
     437             :         mozilla::DoublyLinkedList<js::Breakpoint,
     438             :                                   DebuggerLinkAccess<js::Breakpoint>>;
     439             :     BreakpointList breakpoints;
     440             : 
     441             :     // The set of GC numbers for which one or more of this Debugger's observed
     442             :     // debuggees participated in.
     443             :     using GCNumberSet = HashSet<uint64_t, DefaultHasher<uint64_t>, ZoneAllocPolicy>;
     444             :     GCNumberSet observedGCs;
     445             : 
     446             :     using AllocationsLog = js::TraceableFifo<AllocationsLogEntry>;
     447             : 
     448             :     AllocationsLog allocationsLog;
     449             :     bool trackingAllocationSites;
     450             :     double allocationSamplingProbability;
     451             :     size_t maxAllocationsLogLength;
     452             :     bool allocationsLogOverflowed;
     453             : 
     454             :     static const size_t DEFAULT_MAX_LOG_LENGTH = 5000;
     455             : 
     456             :     MOZ_MUST_USE bool appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
     457             :                                            mozilla::TimeStamp when);
     458             : 
     459             :     /*
     460             :      * Recompute the set of debuggee zones based on the set of debuggee globals.
     461             :      */
     462             :     void recomputeDebuggeeZoneSet();
     463             : 
     464             :     /*
     465             :      * Return true if there is an existing object metadata callback for the
     466             :      * given global's compartment that will prevent our instrumentation of
     467             :      * allocations.
     468             :      */
     469             :     static bool cannotTrackAllocations(const GlobalObject& global);
     470             : 
     471             :     /*
     472             :      * Return true if the given global is being observed by at least one
     473             :      * Debugger that is tracking allocations.
     474             :      */
     475             :     static bool isObservedByDebuggerTrackingAllocations(const GlobalObject& global);
     476             : 
     477             :     /*
     478             :      * Add allocations tracking for objects allocated within the given
     479             :      * debuggee's compartment. The given debuggee global must be observed by at
     480             :      * least one Debugger that is enabled and tracking allocations.
     481             :      */
     482             :     static MOZ_MUST_USE bool addAllocationsTracking(JSContext* cx, Handle<GlobalObject*> debuggee);
     483             : 
     484             :     /*
     485             :      * Remove allocations tracking for objects allocated within the given
     486             :      * global's compartment. This is a no-op if there are still Debuggers
     487             :      * observing this global and who are tracking allocations.
     488             :      */
     489             :     static void removeAllocationsTracking(GlobalObject& global);
     490             : 
     491             :     /*
     492             :      * Add or remove allocations tracking for all debuggees.
     493             :      */
     494             :     MOZ_MUST_USE bool addAllocationsTrackingForAllDebuggees(JSContext* cx);
     495             :     void removeAllocationsTrackingForAllDebuggees();
     496             : 
     497             :     /*
     498             :      * If this Debugger is enabled, and has a onNewGlobalObject handler, then
     499             :      * this link is inserted into the list headed by
     500             :      * JSRuntime::onNewGlobalObjectWatchers.
     501             :      */
     502             :     mozilla::DoublyLinkedListElement<Debugger> onNewGlobalObjectWatchersLink;
     503             : 
     504             :     /*
     505             :      * Map from stack frames that are currently on the stack to Debugger.Frame
     506             :      * instances.
     507             :      *
     508             :      * The keys are always live stack frames. We drop them from this map as
     509             :      * soon as they leave the stack (see slowPathOnLeaveFrame) and in
     510             :      * removeDebuggee.
     511             :      *
     512             :      * We don't trace the keys of this map (the frames are on the stack and
     513             :      * thus necessarily live), but we do trace the values. It's like a WeakMap
     514             :      * that way, but since stack frames are not gc-things, the implementation
     515             :      * has to be different.
     516             :      */
     517             :     typedef HashMap<AbstractFramePtr,
     518             :                     HeapPtr<DebuggerFrame*>,
     519             :                     DefaultHasher<AbstractFramePtr>,
     520             :                     ZoneAllocPolicy> FrameMap;
     521             :     FrameMap frames;
     522             : 
     523             :     /* An ephemeral map from JSScript* to Debugger.Script instances. */
     524             :     typedef DebuggerWeakMap<JSScript*> ScriptWeakMap;
     525             :     ScriptWeakMap scripts;
     526             : 
     527             :     /* The map from debuggee source script objects to their Debugger.Source instances. */
     528             :     typedef DebuggerWeakMap<JSObject*, true> SourceWeakMap;
     529             :     SourceWeakMap sources;
     530             : 
     531             :     /* The map from debuggee objects to their Debugger.Object instances. */
     532             :     typedef DebuggerWeakMap<JSObject*> ObjectWeakMap;
     533             :     ObjectWeakMap objects;
     534             : 
     535             :     /* The map from debuggee Envs to Debugger.Environment instances. */
     536             :     ObjectWeakMap environments;
     537             : 
     538             :     /* The map from WasmInstanceObjects to synthesized Debugger.Script instances. */
     539             :     typedef DebuggerWeakMap<WasmInstanceObject*> WasmInstanceWeakMap;
     540             :     WasmInstanceWeakMap wasmInstanceScripts;
     541             : 
     542             :     /* The map from WasmInstanceObjects to synthesized Debugger.Source instances. */
     543             :     WasmInstanceWeakMap wasmInstanceSources;
     544             : 
     545             :     /*
     546             :      * Keep track of tracelogger last drained identifiers to know if there are
     547             :      * lost events.
     548             :      */
     549             : #ifdef NIGHTLY_BUILD
     550             :     uint32_t traceLoggerLastDrainedSize;
     551             :     uint32_t traceLoggerLastDrainedIteration;
     552             : #endif
     553             :     uint32_t traceLoggerScriptedCallsLastDrainedSize;
     554             :     uint32_t traceLoggerScriptedCallsLastDrainedIteration;
     555             : 
     556             :     class ScriptQuery;
     557             :     class ObjectQuery;
     558             : 
     559             :     MOZ_MUST_USE bool addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> obj);
     560             :     void removeDebuggeeGlobal(FreeOp* fop, GlobalObject* global,
     561             :                               WeakGlobalObjectSet::Enum* debugEnum);
     562             : 
     563             :     /*
     564             :      * Report and clear the pending exception on ar.context, if any, and return
     565             :      * ResumeMode::Terminate.
     566             :      */
     567             :     ResumeMode reportUncaughtException(mozilla::Maybe<AutoRealm>& ar);
     568             : 
     569             :     /*
     570             :      * Cope with an error or exception in a debugger hook.
     571             :      *
     572             :      * If callHook is true, then call the uncaughtExceptionHook, if any. If, in
     573             :      * addition, vp is given, then parse the value returned by
     574             :      * uncaughtExceptionHook as a resumption value.
     575             :      *
     576             :      * If there is no uncaughtExceptionHook, or if it fails, report and clear
     577             :      * the pending exception on ar.context and return ResumeMode::Terminate.
     578             :      *
     579             :      * This always calls ar.leave(); ar is a parameter because this method must
     580             :      * do some things in the debugger realm and some things in the debuggee
     581             :      * realm.
     582             :      */
     583             :     ResumeMode handleUncaughtException(mozilla::Maybe<AutoRealm>& ar);
     584             :     ResumeMode handleUncaughtException(mozilla::Maybe<AutoRealm>& ar,
     585             :                                        MutableHandleValue vp,
     586             :                                        const mozilla::Maybe<HandleValue>& thisVForCheck = mozilla::Nothing(),
     587             :                                        AbstractFramePtr frame = NullFramePtr());
     588             : 
     589             :     ResumeMode handleUncaughtExceptionHelper(mozilla::Maybe<AutoRealm>& ar,
     590             :                                              MutableHandleValue* vp,
     591             :                                              const mozilla::Maybe<HandleValue>& thisVForCheck,
     592             :                                              AbstractFramePtr frame);
     593             : 
     594             :     /*
     595             :      * Handle the result of a hook that is expected to return a resumption
     596             :      * value <https://wiki.mozilla.org/Debugger#Resumption_Values>. This is
     597             :      * called when we return from a debugging hook to debuggee code. The
     598             :      * interpreter wants a (ResumeMode, Value) pair telling it how to proceed.
     599             :      *
     600             :      * Precondition: ar is entered. We are in the debugger compartment.
     601             :      *
     602             :      * Postcondition: This called ar.leave(). See handleUncaughtException.
     603             :      *
     604             :      * If `success` is false, the hook failed. If an exception is pending in
     605             :      * ar.context(), return handleUncaughtException(ar, vp, callhook).
     606             :      * Otherwise just return ResumeMode::Terminate.
     607             :      *
     608             :      * If `success` is true, there must be no exception pending in ar.context().
     609             :      * `rv` may be:
     610             :      *
     611             :      *     undefined - Return `ResumeMode::Continue` to continue execution
     612             :      *         normally.
     613             :      *
     614             :      *     {return: value} or {throw: value} - Call unwrapDebuggeeValue to
     615             :      *         unwrap `value`. Store the result in `*vp` and return
     616             :      *         `ResumeMode::Return` or `ResumeMode::Throw`. The interpreter
     617             :      *         will force the current frame to return or throw an exception.
     618             :      *
     619             :      *     null - Return `ResumeMode::Terminate` to terminate the debuggee with
     620             :      *         an uncatchable error.
     621             :      *
     622             :      *     anything else - Make a new TypeError the pending exception and
     623             :      *         return handleUncaughtException(ar, vp, callHook).
     624             :      */
     625             :     ResumeMode processHandlerResult(mozilla::Maybe<AutoRealm>& ar, bool success, const Value& rv,
     626             :                                     AbstractFramePtr frame, jsbytecode* pc, MutableHandleValue vp);
     627             : 
     628             :     ResumeMode processParsedHandlerResult(mozilla::Maybe<AutoRealm>& ar,
     629             :                                           AbstractFramePtr frame, jsbytecode* pc,
     630             :                                           bool success, ResumeMode resumeMode,
     631             :                                           MutableHandleValue vp);
     632             : 
     633             :     ResumeMode processParsedHandlerResultHelper(mozilla::Maybe<AutoRealm>& ar,
     634             :                                                 AbstractFramePtr frame,
     635             :                                                 const mozilla::Maybe<HandleValue>& maybeThisv,
     636             :                                                 bool success, ResumeMode resumeMode,
     637             :                                                 MutableHandleValue vp);
     638             : 
     639             :     bool processResumptionValue(mozilla::Maybe<AutoRealm>& ar, AbstractFramePtr frame,
     640             :                                 const mozilla::Maybe<HandleValue>& maybeThis, HandleValue rval,
     641             :                                 ResumeMode& resumeMode, MutableHandleValue vp);
     642             : 
     643             :     GlobalObject* unwrapDebuggeeArgument(JSContext* cx, const Value& v);
     644             : 
     645             :     static void traceObject(JSTracer* trc, JSObject* obj);
     646             : 
     647             :     void trace(JSTracer* trc);
     648             :     friend struct js::GCManagedDeletePolicy<Debugger>;
     649             : 
     650             :     void traceForMovingGC(JSTracer* trc);
     651             :     void traceCrossCompartmentEdges(JSTracer* tracer);
     652             : 
     653             :     static const ClassOps classOps_;
     654             : 
     655             :   public:
     656             :     static const Class class_;
     657             : 
     658             :   private:
     659             :     static MOZ_MUST_USE bool getHookImpl(JSContext* cx, CallArgs& args, Debugger& dbg, Hook which);
     660             :     static MOZ_MUST_USE bool setHookImpl(JSContext* cx, CallArgs& args, Debugger& dbg, Hook which);
     661             : 
     662             :     static bool getEnabled(JSContext* cx, unsigned argc, Value* vp);
     663             :     static bool setEnabled(JSContext* cx, unsigned argc, Value* vp);
     664             :     static bool getOnDebuggerStatement(JSContext* cx, unsigned argc, Value* vp);
     665             :     static bool setOnDebuggerStatement(JSContext* cx, unsigned argc, Value* vp);
     666             :     static bool getOnExceptionUnwind(JSContext* cx, unsigned argc, Value* vp);
     667             :     static bool setOnExceptionUnwind(JSContext* cx, unsigned argc, Value* vp);
     668             :     static bool getOnNewScript(JSContext* cx, unsigned argc, Value* vp);
     669             :     static bool setOnNewScript(JSContext* cx, unsigned argc, Value* vp);
     670             :     static bool getOnEnterFrame(JSContext* cx, unsigned argc, Value* vp);
     671             :     static bool setOnEnterFrame(JSContext* cx, unsigned argc, Value* vp);
     672             :     static bool getOnNewGlobalObject(JSContext* cx, unsigned argc, Value* vp);
     673             :     static bool setOnNewGlobalObject(JSContext* cx, unsigned argc, Value* vp);
     674             :     static bool getOnNewPromise(JSContext* cx, unsigned argc, Value* vp);
     675             :     static bool setOnNewPromise(JSContext* cx, unsigned argc, Value* vp);
     676             :     static bool getOnPromiseSettled(JSContext* cx, unsigned argc, Value* vp);
     677             :     static bool setOnPromiseSettled(JSContext* cx, unsigned argc, Value* vp);
     678             :     static bool getUncaughtExceptionHook(JSContext* cx, unsigned argc, Value* vp);
     679             :     static bool setUncaughtExceptionHook(JSContext* cx, unsigned argc, Value* vp);
     680             :     static bool getAllowUnobservedAsmJS(JSContext* cx, unsigned argc, Value* vp);
     681             :     static bool setAllowUnobservedAsmJS(JSContext* cx, unsigned argc, Value* vp);
     682             :     static bool getAllowWasmBinarySource(JSContext* cx, unsigned argc, Value* vp);
     683             :     static bool setAllowWasmBinarySource(JSContext* cx, unsigned argc, Value* vp);
     684             :     static bool getCollectCoverageInfo(JSContext* cx, unsigned argc, Value* vp);
     685             :     static bool setCollectCoverageInfo(JSContext* cx, unsigned argc, Value* vp);
     686             :     static bool getMemory(JSContext* cx, unsigned argc, Value* vp);
     687             :     static bool addDebuggee(JSContext* cx, unsigned argc, Value* vp);
     688             :     static bool addAllGlobalsAsDebuggees(JSContext* cx, unsigned argc, Value* vp);
     689             :     static bool removeDebuggee(JSContext* cx, unsigned argc, Value* vp);
     690             :     static bool removeAllDebuggees(JSContext* cx, unsigned argc, Value* vp);
     691             :     static bool hasDebuggee(JSContext* cx, unsigned argc, Value* vp);
     692             :     static bool getDebuggees(JSContext* cx, unsigned argc, Value* vp);
     693             :     static bool getNewestFrame(JSContext* cx, unsigned argc, Value* vp);
     694             :     static bool clearAllBreakpoints(JSContext* cx, unsigned argc, Value* vp);
     695             :     static bool findScripts(JSContext* cx, unsigned argc, Value* vp);
     696             :     static bool findObjects(JSContext* cx, unsigned argc, Value* vp);
     697             :     static bool findAllGlobals(JSContext* cx, unsigned argc, Value* vp);
     698             :     static bool makeGlobalObjectReference(JSContext* cx, unsigned argc, Value* vp);
     699             :     static bool setupTraceLoggerScriptCalls(JSContext* cx, unsigned argc, Value* vp);
     700             :     static bool drainTraceLoggerScriptCalls(JSContext* cx, unsigned argc, Value* vp);
     701             :     static bool startTraceLogger(JSContext* cx, unsigned argc, Value* vp);
     702             :     static bool endTraceLogger(JSContext* cx, unsigned argc, Value* vp);
     703             :     static bool isCompilableUnit(JSContext* cx, unsigned argc, Value* vp);
     704             : #ifdef NIGHTLY_BUILD
     705             :     static bool setupTraceLogger(JSContext* cx, unsigned argc, Value* vp);
     706             :     static bool drainTraceLogger(JSContext* cx, unsigned argc, Value* vp);
     707             : #endif
     708             :     static bool adoptDebuggeeValue(JSContext* cx, unsigned argc, Value* vp);
     709             :     static bool construct(JSContext* cx, unsigned argc, Value* vp);
     710             :     static const JSPropertySpec properties[];
     711             :     static const JSFunctionSpec methods[];
     712             :     static const JSFunctionSpec static_methods[];
     713             : 
     714             :     static void removeFromFrameMapsAndClearBreakpointsIn(JSContext* cx, AbstractFramePtr frame);
     715             :     static bool updateExecutionObservabilityOfFrames(JSContext* cx, const ExecutionObservableSet& obs,
     716             :                                                      IsObserving observing);
     717             :     static bool updateExecutionObservabilityOfScripts(JSContext* cx, const ExecutionObservableSet& obs,
     718             :                                                       IsObserving observing);
     719             :     static bool updateExecutionObservability(JSContext* cx, ExecutionObservableSet& obs,
     720             :                                              IsObserving observing);
     721             : 
     722             :     template <typename FrameFn /* void (DebuggerFrame*) */>
     723             :     static void forEachDebuggerFrame(AbstractFramePtr frame, FrameFn fn);
     724             : 
     725             :     /*
     726             :      * Return a vector containing all Debugger.Frame instances referring to
     727             :      * |frame|. |global| is |frame|'s global object; if nullptr or omitted, we
     728             :      * compute it ourselves from |frame|.
     729             :      */
     730             :     using DebuggerFrameVector = GCVector<DebuggerFrame*>;
     731             :     static MOZ_MUST_USE bool getDebuggerFrames(AbstractFramePtr frame,
     732             :                                                MutableHandle<DebuggerFrameVector> frames);
     733             : 
     734             :   public:
     735             :     static MOZ_MUST_USE bool ensureExecutionObservabilityOfOsrFrame(JSContext* cx,
     736             :                                                                     InterpreterFrame* frame);
     737             : 
     738             :     // Public for DebuggerScript_setBreakpoint.
     739             :     static MOZ_MUST_USE bool ensureExecutionObservabilityOfScript(JSContext* cx, JSScript* script);
     740             : 
     741             :     // Whether the Debugger instance needs to observe all non-AOT JS
     742             :     // execution of its debugees.
     743             :     IsObserving observesAllExecution() const;
     744             : 
     745             :     // Whether the Debugger instance needs to observe AOT-compiled asm.js
     746             :     // execution of its debuggees.
     747             :     IsObserving observesAsmJS() const;
     748             : 
     749             :     // Whether the Debugger instance needs to observe coverage of any JavaScript
     750             :     // execution.
     751             :     IsObserving observesCoverage() const;
     752             : 
     753             :     IsObserving observesBinarySource() const;
     754             : 
     755             :   private:
     756             :     static MOZ_MUST_USE bool ensureExecutionObservabilityOfFrame(JSContext* cx,
     757             :                                                                  AbstractFramePtr frame);
     758             :     static MOZ_MUST_USE bool ensureExecutionObservabilityOfRealm(JSContext* cx,
     759             :                                                                  JS::Realm* realm);
     760             : 
     761             :     static bool hookObservesAllExecution(Hook which);
     762             : 
     763             :     MOZ_MUST_USE bool updateObservesAllExecutionOnDebuggees(JSContext* cx, IsObserving observing);
     764             :     MOZ_MUST_USE bool updateObservesCoverageOnDebuggees(JSContext* cx, IsObserving observing);
     765             :     void updateObservesAsmJSOnDebuggees(IsObserving observing);
     766             :     void updateObservesBinarySourceDebuggees(IsObserving observing);
     767             : 
     768             :     JSObject* getHook(Hook hook) const;
     769             :     bool hasAnyLiveHooks(JSRuntime* rt) const;
     770             : 
     771             :     static MOZ_MUST_USE bool slowPathCheckNoExecute(JSContext* cx, HandleScript script);
     772             :     static ResumeMode slowPathOnEnterFrame(JSContext* cx, AbstractFramePtr frame);
     773             :     static MOZ_MUST_USE bool slowPathOnLeaveFrame(JSContext* cx, AbstractFramePtr frame,
     774             :                                                   jsbytecode* pc, bool ok);
     775             :     static ResumeMode slowPathOnDebuggerStatement(JSContext* cx, AbstractFramePtr frame);
     776             :     static ResumeMode slowPathOnExceptionUnwind(JSContext* cx, AbstractFramePtr frame);
     777             :     static void slowPathOnNewScript(JSContext* cx, HandleScript script);
     778             :     static void slowPathOnNewWasmInstance(JSContext* cx, Handle<WasmInstanceObject*> wasmInstance);
     779             :     static void slowPathOnNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global);
     780             :     static MOZ_MUST_USE bool slowPathOnLogAllocationSite(JSContext* cx, HandleObject obj,
     781             :                                                          HandleSavedFrame frame,
     782             :                                                          mozilla::TimeStamp when,
     783             :                                                          GlobalObject::DebuggerVector& dbgs);
     784             :     static void slowPathPromiseHook(JSContext* cx, Hook hook, Handle<PromiseObject*> promise);
     785             : 
     786             :     template <typename HookIsEnabledFun /* bool (Debugger*) */,
     787             :               typename FireHookFun /* ResumeMode (Debugger*) */>
     788             :     static ResumeMode dispatchHook(JSContext* cx, HookIsEnabledFun hookIsEnabled,
     789             :                                    FireHookFun fireHook);
     790             : 
     791             :     ResumeMode fireDebuggerStatement(JSContext* cx, MutableHandleValue vp);
     792             :     ResumeMode fireExceptionUnwind(JSContext* cx, MutableHandleValue vp);
     793             :     ResumeMode fireEnterFrame(JSContext* cx, MutableHandleValue vp);
     794             :     ResumeMode fireNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global, MutableHandleValue vp);
     795             :     ResumeMode firePromiseHook(JSContext* cx, Hook hook, HandleObject promise, MutableHandleValue vp);
     796             : 
     797             :     NativeObject* newVariantWrapper(JSContext* cx, Handle<DebuggerScriptReferent> referent) {
     798           0 :         return newDebuggerScript(cx, referent);
     799             :     }
     800             :     NativeObject* newVariantWrapper(JSContext* cx, Handle<DebuggerSourceReferent> referent) {
     801           0 :         return newDebuggerSource(cx, referent);
     802             :     }
     803             : 
     804             :     /*
     805             :      * Helper function to help wrap Debugger objects whose referents may be
     806             :      * variants. Currently Debugger.Script and Debugger.Source referents may
     807             :      * be variants.
     808             :      *
     809             :      * Prefer using wrapScript, wrapWasmScript, wrapSource, and wrapWasmSource
     810             :      * whenever possible.
     811             :      */
     812             :     template <typename ReferentVariant, typename Referent, typename Map>
     813             :     JSObject* wrapVariantReferent(JSContext* cx, Map& map, Handle<CrossCompartmentKey> key,
     814             :                                   Handle<ReferentVariant> referent);
     815             :     JSObject* wrapVariantReferent(JSContext* cx, Handle<DebuggerScriptReferent> referent);
     816             :     JSObject* wrapVariantReferent(JSContext* cx, Handle<DebuggerSourceReferent> referent);
     817             : 
     818             :     /*
     819             :      * Allocate and initialize a Debugger.Script instance whose referent is
     820             :      * |referent|.
     821             :      */
     822             :     NativeObject* newDebuggerScript(JSContext* cx, Handle<DebuggerScriptReferent> referent);
     823             : 
     824             :     /*
     825             :      * Allocate and initialize a Debugger.Source instance whose referent is
     826             :      * |referent|.
     827             :      */
     828             :     NativeObject* newDebuggerSource(JSContext* cx, Handle<DebuggerSourceReferent> referent);
     829             : 
     830             :     /*
     831             :      * Receive a "new script" event from the engine. A new script was compiled
     832             :      * or deserialized.
     833             :      */
     834             :     void fireNewScript(JSContext* cx, Handle<DebuggerScriptReferent> scriptReferent);
     835             : 
     836             :     /*
     837             :      * Receive a "garbage collection" event from the engine. A GC cycle with the
     838             :      * given data was recently completed.
     839             :      */
     840             :     void fireOnGarbageCollectionHook(JSContext* cx,
     841             :                                      const JS::dbg::GarbageCollectionEvent::Ptr& gcData);
     842             : 
     843             :     inline Breakpoint* firstBreakpoint() const;
     844             : 
     845             :     static MOZ_MUST_USE bool replaceFrameGuts(JSContext* cx, AbstractFramePtr from,
     846             :                                               AbstractFramePtr to,
     847             :                                               ScriptFrameIter& iter);
     848             : 
     849             :   public:
     850             :     Debugger(JSContext* cx, NativeObject* dbg);
     851             :     ~Debugger();
     852             : 
     853             :     MOZ_MUST_USE bool init(JSContext* cx);
     854             :     inline const js::GCPtrNativeObject& toJSObject() const;
     855             :     inline js::GCPtrNativeObject& toJSObjectRef();
     856             :     static inline Debugger* fromJSObject(const JSObject* obj);
     857             :     static Debugger* fromChildJSObject(JSObject* obj);
     858             : 
     859             :     Zone* zone() const { return toJSObject()->zone(); }
     860             : 
     861             :     bool hasMemory() const;
     862             :     DebuggerMemory& memory() const;
     863             : 
     864           0 :     WeakGlobalObjectSet::Range allDebuggees() const { return debuggees.all(); }
     865             : 
     866             :     /*********************************** Methods for interaction with the GC. */
     867             : 
     868             :     /*
     869             :      * A Debugger object is live if:
     870             :      *   * the Debugger JSObject is live (Debugger::trace handles this case); OR
     871             :      *   * it is in the middle of dispatching an event (the event dispatching
     872             :      *     code roots it in this case); OR
     873             :      *   * it is enabled, and it is debugging at least one live compartment,
     874             :      *     and at least one of the following is true:
     875             :      *       - it has a debugger hook installed
     876             :      *       - it has a breakpoint set on a live script
     877             :      *       - it has a watchpoint set on a live object.
     878             :      *
     879             :      * Debugger::markIteratively handles the last case. If it finds any Debugger
     880             :      * objects that are definitely live but not yet marked, it marks them and
     881             :      * returns true. If not, it returns false.
     882             :      */
     883             :     static void traceIncomingCrossCompartmentEdges(JSTracer* tracer);
     884             :     static MOZ_MUST_USE bool markIteratively(GCMarker* marker);
     885             :     static void traceAllForMovingGC(JSTracer* trc);
     886             :     static void sweepAll(FreeOp* fop);
     887             :     static void detachAllDebuggersFromGlobal(FreeOp* fop, GlobalObject* global);
     888             :     static void findZoneEdges(JS::Zone* v, gc::ZoneComponentFinder& finder);
     889             : #ifdef DEBUG
     890             :     static bool isDebuggerCrossCompartmentEdge(JSObject* obj, const js::gc::Cell* cell);
     891             : #endif
     892             : 
     893             :     // Checks it the current compartment is allowed to execute code.
     894             :     static inline MOZ_MUST_USE bool checkNoExecute(JSContext* cx, HandleScript script);
     895             : 
     896             :     /*
     897             :      * Announce to the debugger that the context has entered a new JavaScript
     898             :      * frame, |frame|. Call whatever hooks have been registered to observe new
     899             :      * frames.
     900             :      */
     901             :     static inline ResumeMode onEnterFrame(JSContext* cx, AbstractFramePtr frame);
     902             : 
     903             :     /*
     904             :      * Announce to the debugger a |debugger;| statement on has been
     905             :      * encountered on the youngest JS frame on |cx|. Call whatever hooks have
     906             :      * been registered to observe this.
     907             :      *
     908             :      * Note that this method is called for all |debugger;| statements,
     909             :      * regardless of the frame's debuggee-ness.
     910             :      */
     911             :     static inline ResumeMode onDebuggerStatement(JSContext* cx, AbstractFramePtr frame);
     912             : 
     913             :     /*
     914             :      * Announce to the debugger that an exception has been thrown and propagated
     915             :      * to |frame|. Call whatever hooks have been registered to observe this.
     916             :      */
     917             :     static inline ResumeMode onExceptionUnwind(JSContext* cx, AbstractFramePtr frame);
     918             : 
     919             :     /*
     920             :      * Announce to the debugger that the thread has exited a JavaScript frame, |frame|.
     921             :      * If |ok| is true, the frame is returning normally; if |ok| is false, the frame
     922             :      * is throwing an exception or terminating.
     923             :      *
     924             :      * Change cx's current exception and |frame|'s return value to reflect the changes
     925             :      * in behavior the hooks request, if any. Return the new error/success value.
     926             :      *
     927             :      * This function may be called twice for the same outgoing frame; only the
     928             :      * first call has any effect. (Permitting double calls simplifies some
     929             :      * cases where an onPop handler's resumption value changes a return to a
     930             :      * throw, or vice versa: we can redirect to a complete copy of the
     931             :      * alternative path, containing its own call to onLeaveFrame.)
     932             :      */
     933             :     static inline MOZ_MUST_USE bool onLeaveFrame(JSContext* cx, AbstractFramePtr frame,
     934             :                                                  jsbytecode* pc, bool ok);
     935             : 
     936             :     static inline void onNewScript(JSContext* cx, HandleScript script);
     937             :     static inline void onNewWasmInstance(JSContext* cx, Handle<WasmInstanceObject*> wasmInstance);
     938             :     static inline void onNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global);
     939             :     static inline MOZ_MUST_USE bool onLogAllocationSite(JSContext* cx, JSObject* obj,
     940             :                                                         HandleSavedFrame frame, mozilla::TimeStamp when);
     941             :     static ResumeMode onTrap(JSContext* cx, MutableHandleValue vp);
     942             :     static ResumeMode onSingleStep(JSContext* cx, MutableHandleValue vp);
     943             :     static MOZ_MUST_USE bool handleBaselineOsr(JSContext* cx, InterpreterFrame* from,
     944             :                                                jit::BaselineFrame* to);
     945             :     static MOZ_MUST_USE bool handleIonBailout(JSContext* cx, jit::RematerializedFrame* from,
     946             :                                               jit::BaselineFrame* to);
     947             :     static void handleUnrecoverableIonBailoutError(JSContext* cx, jit::RematerializedFrame* frame);
     948             :     static void propagateForcedReturn(JSContext* cx, AbstractFramePtr frame, HandleValue rval);
     949             :     static bool hasLiveHook(GlobalObject* global, Hook which);
     950             :     static bool inFrameMaps(AbstractFramePtr frame);
     951             : 
     952             :     // Notify any Debugger instances observing this promise's global that a new
     953             :     // promise was allocated.
     954             :     static inline void onNewPromise(JSContext* cx, Handle<PromiseObject*> promise);
     955             : 
     956             :     // Notify any Debugger instances observing this promise's global that the
     957             :     // promise has settled (ie, it has either been fulfilled or rejected). Note that
     958             :     // this is *not* equivalent to the promise resolution (ie, the promise's fate
     959             :     // getting locked in) because you can resolve a promise with another pending
     960             :     // promise, in which case neither promise has settled yet.
     961             :     //
     962             :     // This should never be called on the same promise more than once, because a
     963             :     // promise can only make the transition from unsettled to settled once.
     964             :     static inline void onPromiseSettled(JSContext* cx, Handle<PromiseObject*> promise);
     965             : 
     966             :     /************************************* Functions for use by Debugger.cpp. */
     967             : 
     968             :     inline bool observesEnterFrame() const;
     969             :     inline bool observesNewScript() const;
     970             :     inline bool observesNewGlobalObject() const;
     971             :     inline bool observesGlobal(GlobalObject* global) const;
     972             :     bool observesFrame(AbstractFramePtr frame) const;
     973             :     bool observesFrame(const FrameIter& iter) const;
     974             :     bool observesScript(JSScript* script) const;
     975             :     bool observesWasm(wasm::Instance* instance) const;
     976             : 
     977             :     /*
     978             :      * If env is nullptr, call vp->setNull() and return true. Otherwise, find
     979             :      * or create a Debugger.Environment object for the given Env. On success,
     980             :      * store the Environment object in *vp and return true.
     981             :      */
     982             :     MOZ_MUST_USE bool wrapEnvironment(JSContext* cx, Handle<Env*> env, MutableHandleValue vp);
     983             :     MOZ_MUST_USE bool wrapEnvironment(JSContext* cx, Handle<Env*> env,
     984             :                                       MutableHandleDebuggerEnvironment result);
     985             : 
     986             :     /*
     987             :      * Like cx->compartment()->wrap(cx, vp), but for the debugger realm.
     988             :      *
     989             :      * Preconditions: *vp is a value from a debuggee realm; cx is in the
     990             :      * debugger's compartment.
     991             :      *
     992             :      * If *vp is an object, this produces a (new or existing) Debugger.Object
     993             :      * wrapper for it. Otherwise this is the same as Compartment::wrap.
     994             :      *
     995             :      * If *vp is a magic JS_OPTIMIZED_OUT value, this produces a plain object
     996             :      * of the form { optimizedOut: true }.
     997             :      *
     998             :      * If *vp is a magic JS_OPTIMIZED_ARGUMENTS value signifying missing
     999             :      * arguments, this produces a plain object of the form { missingArguments:
    1000             :      * true }.
    1001             :      *
    1002             :      * If *vp is a magic JS_UNINITIALIZED_LEXICAL value signifying an
    1003             :      * unaccessible uninitialized binding, this produces a plain object of the
    1004             :      * form { uninitialized: true }.
    1005             :      */
    1006             :     MOZ_MUST_USE bool wrapDebuggeeValue(JSContext* cx, MutableHandleValue vp);
    1007             :     MOZ_MUST_USE bool wrapDebuggeeObject(JSContext* cx, HandleObject obj,
    1008             :                                          MutableHandleDebuggerObject result);
    1009             : 
    1010             :     /*
    1011             :      * Unwrap a Debug.Object, without rewrapping it for any particular debuggee
    1012             :      * compartment.
    1013             :      *
    1014             :      * Preconditions: cx is in the debugger compartment. *vp is a value in that
    1015             :      * compartment. (*vp should be a "debuggee value", meaning it is the
    1016             :      * debugger's reflection of a value in the debuggee.)
    1017             :      *
    1018             :      * If *vp is a Debugger.Object, store the referent in *vp. Otherwise, if *vp
    1019             :      * is an object, throw a TypeError, because it is not a debuggee
    1020             :      * value. Otherwise *vp is a primitive, so leave it alone.
    1021             :      *
    1022             :      * When passing values from the debuggee to the debugger:
    1023             :      *     enter debugger compartment;
    1024             :      *     call wrapDebuggeeValue;  // compartment- and debugger-wrapping
    1025             :      *
    1026             :      * When passing values from the debugger to the debuggee:
    1027             :      *     call unwrapDebuggeeValue;  // debugger-unwrapping
    1028             :      *     enter debuggee realm;
    1029             :      *     call cx->compartment()->wrap;  // compartment-rewrapping
    1030             :      *
    1031             :      * (Extreme nerd sidebar: Unwrapping happens in two steps because there are
    1032             :      * two different kinds of symmetry at work: regardless of which direction
    1033             :      * we're going, we want any exceptions to be created and thrown in the
    1034             :      * debugger compartment--mirror symmetry. But compartment wrapping always
    1035             :      * happens in the target compartment--rotational symmetry.)
    1036             :      */
    1037             :     MOZ_MUST_USE bool unwrapDebuggeeValue(JSContext* cx, MutableHandleValue vp);
    1038             :     MOZ_MUST_USE bool unwrapDebuggeeObject(JSContext* cx, MutableHandleObject obj);
    1039             :     MOZ_MUST_USE bool unwrapPropertyDescriptor(JSContext* cx, HandleObject obj,
    1040             :                                                MutableHandle<PropertyDescriptor> desc);
    1041             : 
    1042             :     /*
    1043             :      * Store the Debugger.Frame object for iter in *vp/result.
    1044             :      *
    1045             :      * If this Debugger does not already have a Frame object for the frame
    1046             :      * `iter` points to, a new Frame object is created, and `iter`'s private
    1047             :      * data is copied into it.
    1048             :      */
    1049             :     MOZ_MUST_USE bool getFrame(JSContext* cx, const FrameIter& iter,
    1050             :                                MutableHandleValue vp);
    1051             :     MOZ_MUST_USE bool getFrame(JSContext* cx, const FrameIter& iter,
    1052             :                                MutableHandleDebuggerFrame result);
    1053             : 
    1054             :     /*
    1055             :      * Set |*resumeMode| and |*value| to a (ResumeMode, Value) pair reflecting a
    1056             :      * standard SpiderMonkey call state: a boolean success value |ok|, a return
    1057             :      * value |rv|, and a context |cx| that may or may not have an exception set.
    1058             :      * If an exception was pending on |cx|, it is cleared (and |ok| is asserted
    1059             :      * to be false).
    1060             :      */
    1061             :     static void resultToCompletion(JSContext* cx, bool ok, const Value& rv,
    1062             :                                    ResumeMode* resumeMode, MutableHandleValue value);
    1063             : 
    1064             :     /*
    1065             :      * Set |*result| to a JavaScript completion value corresponding to |resumeMode|
    1066             :      * and |value|. |value| should be the return value or exception value, not
    1067             :      * wrapped as a debuggee value. |cx| must be in the debugger compartment.
    1068             :      */
    1069             :     MOZ_MUST_USE bool newCompletionValue(JSContext* cx, ResumeMode resumeMode, const Value& value,
    1070             :                                          MutableHandleValue result);
    1071             : 
    1072             :     /*
    1073             :      * Precondition: we are in the debuggee realm (ar is entered) and ok is true
    1074             :      * if the operation in the debuggee realm succeeded, false on error or
    1075             :      * exception.
    1076             :      *
    1077             :      * Postcondition: we are in the debugger realm, having called ar.leave()
    1078             :      * even if an error occurred.
    1079             :      *
    1080             :      * On success, a completion value is in vp and ar.context does not have a
    1081             :      * pending exception. (This ordinarily returns true even if the ok argument
    1082             :      * is false.)
    1083             :      */
    1084             :     MOZ_MUST_USE bool receiveCompletionValue(mozilla::Maybe<AutoRealm>& ar, bool ok,
    1085             :                                              HandleValue val,
    1086             :                                              MutableHandleValue vp);
    1087             : 
    1088             :     /*
    1089             :      * Return the Debugger.Script object for |script|, or create a new one if
    1090             :      * needed. The context |cx| must be in the debugger realm; |script| must be
    1091             :      * a script in a debuggee realm.
    1092             :      */
    1093             :     JSObject* wrapScript(JSContext* cx, HandleScript script);
    1094             : 
    1095             :     /*
    1096             :      * Return the Debugger.Script object for |wasmInstance| (the toplevel
    1097             :      * script), synthesizing a new one if needed. The context |cx| must be in
    1098             :      * the debugger compartment; |wasmInstance| must be a WasmInstanceObject in
    1099             :      * the debuggee realm.
    1100             :      */
    1101             :     JSObject* wrapWasmScript(JSContext* cx, Handle<WasmInstanceObject*> wasmInstance);
    1102             : 
    1103             :     /*
    1104             :      * Return the Debugger.Source object for |source|, or create a new one if
    1105             :      * needed. The context |cx| must be in the debugger compartment; |source|
    1106             :      * must be a script source object in a debuggee realm.
    1107             :      */
    1108             :     JSObject* wrapSource(JSContext* cx, js::HandleScriptSourceObject source);
    1109             : 
    1110             :     /*
    1111             :      * Return the Debugger.Source object for |wasmInstance| (the entire module),
    1112             :      * synthesizing a new one if needed. The context |cx| must be in the
    1113             :      * debugger compartment; |wasmInstance| must be a WasmInstanceObject in the
    1114             :      * debuggee realm.
    1115             :      */
    1116             :     JSObject* wrapWasmSource(JSContext* cx, Handle<WasmInstanceObject*> wasmInstance);
    1117             : 
    1118             :   private:
    1119             :     Debugger(const Debugger&) = delete;
    1120             :     Debugger & operator=(const Debugger&) = delete;
    1121             : };
    1122             : 
    1123             : enum class DebuggerEnvironmentType {
    1124             :     Declarative,
    1125             :     With,
    1126             :     Object
    1127             : };
    1128             : 
    1129             : class DebuggerEnvironment : public NativeObject
    1130             : {
    1131             :   public:
    1132             :     enum {
    1133             :         OWNER_SLOT
    1134             :     };
    1135             : 
    1136             :     static const unsigned RESERVED_SLOTS = 1;
    1137             : 
    1138             :     static const Class class_;
    1139             : 
    1140             :     static NativeObject* initClass(JSContext* cx, HandleObject dbgCtor,
    1141             :                                    Handle<GlobalObject*> global);
    1142             :     static DebuggerEnvironment* create(JSContext* cx, HandleObject proto, HandleObject referent,
    1143             :                                        HandleNativeObject debugger);
    1144             : 
    1145             :     DebuggerEnvironmentType type() const;
    1146             :     MOZ_MUST_USE bool getParent(JSContext* cx, MutableHandleDebuggerEnvironment result) const;
    1147             :     MOZ_MUST_USE bool getObject(JSContext* cx, MutableHandleDebuggerObject result) const;
    1148             :     MOZ_MUST_USE bool getCallee(JSContext* cx, MutableHandleDebuggerObject result) const;
    1149             :     bool isDebuggee() const;
    1150             :     bool isOptimized() const;
    1151             : 
    1152             :     static MOZ_MUST_USE bool getNames(JSContext* cx, HandleDebuggerEnvironment environment,
    1153             :                                       MutableHandle<IdVector> result);
    1154             :     static MOZ_MUST_USE bool find(JSContext* cx, HandleDebuggerEnvironment environment,
    1155             :                                   HandleId id, MutableHandleDebuggerEnvironment result);
    1156             :     static MOZ_MUST_USE bool getVariable(JSContext* cx, HandleDebuggerEnvironment environment,
    1157             :                                          HandleId id, MutableHandleValue result);
    1158             :     static MOZ_MUST_USE bool setVariable(JSContext* cx, HandleDebuggerEnvironment environment,
    1159             :                                          HandleId id, HandleValue value);
    1160             : 
    1161             :   private:
    1162             :     static const ClassOps classOps_;
    1163             : 
    1164             :     static const JSPropertySpec properties_[];
    1165             :     static const JSFunctionSpec methods_[];
    1166             : 
    1167           0 :     Env* referent() const {
    1168           0 :         Env* env = static_cast<Env*>(getPrivate());
    1169           0 :         MOZ_ASSERT(env);
    1170           0 :         return env;
    1171             :     }
    1172             : 
    1173             :     Debugger* owner() const;
    1174             : 
    1175             :     bool requireDebuggee(JSContext* cx) const;
    1176             : 
    1177             :     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
    1178             : 
    1179             :     static MOZ_MUST_USE bool typeGetter(JSContext* cx, unsigned argc, Value* vp);
    1180             :     static MOZ_MUST_USE bool parentGetter(JSContext* cx, unsigned argc, Value* vp);
    1181             :     static MOZ_MUST_USE bool objectGetter(JSContext* cx, unsigned argc, Value* vp);
    1182             :     static MOZ_MUST_USE bool calleeGetter(JSContext* cx, unsigned argc, Value* vp);
    1183             :     static MOZ_MUST_USE bool inspectableGetter(JSContext* cx, unsigned argc, Value* vp);
    1184             :     static MOZ_MUST_USE bool optimizedOutGetter(JSContext* cx, unsigned argc, Value* vp);
    1185             : 
    1186             :     static MOZ_MUST_USE bool namesMethod(JSContext* cx, unsigned argc, Value* vp);
    1187             :     static MOZ_MUST_USE bool findMethod(JSContext* cx, unsigned argc, Value* vp);
    1188             :     static MOZ_MUST_USE bool getVariableMethod(JSContext* cx, unsigned argc, Value* vp);
    1189             :     static MOZ_MUST_USE bool setVariableMethod(JSContext* cx, unsigned argc, Value* vp);
    1190             : };
    1191             : 
    1192             : enum class DebuggerFrameType {
    1193             :     Eval,
    1194             :     Global,
    1195             :     Call,
    1196             :     Module,
    1197             :     WasmCall
    1198             : };
    1199             : 
    1200             : enum class DebuggerFrameImplementation {
    1201             :     Interpreter,
    1202             :     Baseline,
    1203             :     Ion,
    1204             :     Wasm
    1205             : };
    1206             : 
    1207             : /*
    1208             :  * A Handler represents a reference to a handler function. These handler
    1209             :  * functions are called by the Debugger API to notify the user of certain
    1210             :  * events. For each event type, we define a separate subclass of Handler. This
    1211             :  * allows users to define a single reference to an object that implements
    1212             :  * multiple handlers, by inheriting from the appropriate subclasses.
    1213             :  *
    1214             :  * A Handler can be stored on a reflection object, in which case the reflection
    1215             :  * object becomes responsible for managing the lifetime of the Handler. To aid
    1216             :  * with this, the Handler base class defines several methods, which are to be
    1217             :  * called by the reflection object at the appropriate time (see below).
    1218             :  */
    1219             : struct Handler {
    1220             :     virtual ~Handler() {}
    1221             : 
    1222             :     /*
    1223             :      * If the Handler is a reference to a callable JSObject, this method returns
    1224             :      * the latter. This allows the Handler to be used from JS. Otherwise, this
    1225             :      * method returns nullptr.
    1226             :      */
    1227             :     virtual JSObject* object() const = 0;
    1228             : 
    1229             :     /*
    1230             :      * Drops the reference to the handler. This method will be called by the
    1231             :      * reflection object on which the reference is stored when the former is
    1232             :      * finalized, or the latter replaced.
    1233             :      */
    1234             :     virtual void drop() = 0;
    1235             : 
    1236             :     /*
    1237             :      * Traces the reference to the handler. This method will be called
    1238             :      * by the reflection object on which the reference is stored whenever the
    1239             :      * former is traced.
    1240             :      */
    1241             :     virtual void trace(JSTracer* tracer) = 0;
    1242             : };
    1243             : 
    1244             : class DebuggerArguments : public NativeObject {
    1245             :   public:
    1246             :     static const Class class_;
    1247             : 
    1248             :     static DebuggerArguments* create(JSContext* cx, HandleObject proto, HandleDebuggerFrame frame);
    1249             : 
    1250             :   private:
    1251             :     enum {
    1252             :         FRAME_SLOT
    1253             :     };
    1254             : 
    1255             :     static const unsigned RESERVED_SLOTS = 1;
    1256             : };
    1257             : 
    1258             : /*
    1259             :  * An OnStepHandler represents a handler function that is called when a small
    1260             :  * amount of progress is made in a frame.
    1261             :  */
    1262           0 : struct OnStepHandler : Handler {
    1263             :     /*
    1264             :      * If we have made a small amount of progress in a frame, this method is
    1265             :      * called with the frame as argument. If succesful, this method should
    1266             :      * return true, with `resumeMode` and `vp` set to a resumption value
    1267             :      * specifiying how execution should continue.
    1268             :      */
    1269             :     virtual bool onStep(JSContext* cx, HandleDebuggerFrame frame, ResumeMode& resumeMode,
    1270             :                         MutableHandleValue vp) = 0;
    1271             : };
    1272             : 
    1273           0 : class ScriptedOnStepHandler final : public OnStepHandler {
    1274             :   public:
    1275             :     explicit ScriptedOnStepHandler(JSObject* object);
    1276             :     virtual JSObject* object() const override;
    1277             :     virtual void drop() override;
    1278             :     virtual void trace(JSTracer* tracer) override;
    1279             :     virtual bool onStep(JSContext* cx, HandleDebuggerFrame frame, ResumeMode& resumeMode,
    1280             :                         MutableHandleValue vp) override;
    1281             : 
    1282             :   private:
    1283             :     HeapPtr<JSObject*> object_;
    1284             : };
    1285             : 
    1286             : /*
    1287             :  * An OnPopHandler represents a handler function that is called just before a
    1288             :  * frame is popped.
    1289             :  */
    1290           0 : struct OnPopHandler : Handler {
    1291             :     /*
    1292             :      * If a frame is about the be popped, this method is called with the frame
    1293             :      * as argument, and `resumeMode` and `vp` set to a completion value specifying
    1294             :      * how this frame's execution completed. If successful, this method should
    1295             :      * return true, with `resumeMode` and `vp` set to a resumption value specifying
    1296             :      * how execution should continue.
    1297             :      */
    1298             :     virtual bool onPop(JSContext* cx, HandleDebuggerFrame frame, ResumeMode& resumeMode,
    1299             :                        MutableHandleValue vp) = 0;
    1300             : };
    1301             : 
    1302           0 : class ScriptedOnPopHandler final : public OnPopHandler {
    1303             :   public:
    1304             :     explicit ScriptedOnPopHandler(JSObject* object);
    1305             :     virtual JSObject* object() const override;
    1306             :     virtual void drop() override;
    1307             :     virtual void trace(JSTracer* tracer) override;
    1308             :     virtual bool onPop(JSContext* cx, HandleDebuggerFrame frame, ResumeMode& resumeMode,
    1309             :                        MutableHandleValue vp) override;
    1310             : 
    1311             :   private:
    1312             :     HeapPtr<JSObject*> object_;
    1313             : };
    1314             : 
    1315             : class DebuggerFrame : public NativeObject
    1316             : {
    1317             :     friend class DebuggerArguments;
    1318             :     friend class ScriptedOnStepHandler;
    1319             :     friend class ScriptedOnPopHandler;
    1320             : 
    1321             :   public:
    1322             :     enum {
    1323             :         OWNER_SLOT
    1324             :     };
    1325             : 
    1326             :     static const unsigned RESERVED_SLOTS = 1;
    1327             : 
    1328             :     static const Class class_;
    1329             : 
    1330             :     static NativeObject* initClass(JSContext* cx, HandleObject dbgCtor,
    1331             :                                    Handle<GlobalObject*> global);
    1332             :     static DebuggerFrame* create(JSContext* cx, HandleObject proto, const FrameIter& iter,
    1333             :                                  HandleNativeObject debugger);
    1334             :     void freeFrameIterData(FreeOp* fop);
    1335             : 
    1336             :     static MOZ_MUST_USE bool getArguments(JSContext* cx, HandleDebuggerFrame frame,
    1337             :                                           MutableHandleDebuggerArguments result);
    1338             :     static MOZ_MUST_USE bool getCallee(JSContext* cx, HandleDebuggerFrame frame,
    1339             :                                        MutableHandleDebuggerObject result);
    1340             :     static MOZ_MUST_USE bool getIsConstructing(JSContext* cx, HandleDebuggerFrame frame,
    1341             :                                                bool& result);
    1342             :     static MOZ_MUST_USE bool getEnvironment(JSContext* cx, HandleDebuggerFrame frame,
    1343             :                                             MutableHandleDebuggerEnvironment result);
    1344             :     static bool getIsGenerator(HandleDebuggerFrame frame);
    1345             :     static MOZ_MUST_USE bool getOffset(JSContext* cx, HandleDebuggerFrame frame, size_t& result);
    1346             :     static MOZ_MUST_USE bool getOlder(JSContext* cx, HandleDebuggerFrame frame,
    1347             :                                       MutableHandleDebuggerFrame result);
    1348             :     static MOZ_MUST_USE bool getThis(JSContext* cx, HandleDebuggerFrame frame,
    1349             :                                      MutableHandleValue result);
    1350             :     static DebuggerFrameType getType(HandleDebuggerFrame frame);
    1351             :     static DebuggerFrameImplementation getImplementation(HandleDebuggerFrame frame);
    1352             :     static MOZ_MUST_USE bool setOnStepHandler(JSContext* cx, HandleDebuggerFrame frame,
    1353             :                                               OnStepHandler* handler);
    1354             : 
    1355             :     static MOZ_MUST_USE bool eval(JSContext* cx, HandleDebuggerFrame frame,
    1356             :                                   mozilla::Range<const char16_t> chars, HandleObject bindings,
    1357             :                                   const EvalOptions& options, ResumeMode& resumeMode,
    1358             :                                   MutableHandleValue value);
    1359             : 
    1360             :     bool isLive() const;
    1361             :     OnStepHandler* onStepHandler() const;
    1362             :     OnPopHandler* onPopHandler() const;
    1363             :     void setOnPopHandler(OnPopHandler* handler);
    1364             : 
    1365             :   private:
    1366             :     static const ClassOps classOps_;
    1367             : 
    1368             :     static const JSPropertySpec properties_[];
    1369             :     static const JSFunctionSpec methods_[];
    1370             : 
    1371             :     static AbstractFramePtr getReferent(HandleDebuggerFrame frame);
    1372             :     static MOZ_MUST_USE bool getFrameIter(JSContext* cx, HandleDebuggerFrame frame,
    1373             :                                           mozilla::Maybe<FrameIter>& result);
    1374             :     static MOZ_MUST_USE bool requireScriptReferent(JSContext* cx, HandleDebuggerFrame frame);
    1375             : 
    1376             :     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
    1377             : 
    1378             :     static MOZ_MUST_USE bool argumentsGetter(JSContext* cx, unsigned argc, Value* vp);
    1379             :     static MOZ_MUST_USE bool calleeGetter(JSContext* cx, unsigned argc, Value* vp);
    1380             :     static MOZ_MUST_USE bool constructingGetter(JSContext* cx, unsigned argc, Value* vp);
    1381             :     static MOZ_MUST_USE bool environmentGetter(JSContext* cx, unsigned argc, Value* vp);
    1382             :     static MOZ_MUST_USE bool generatorGetter(JSContext* cx, unsigned argc, Value* vp);
    1383             :     static MOZ_MUST_USE bool liveGetter(JSContext* cx, unsigned argc, Value* vp);
    1384             :     static MOZ_MUST_USE bool offsetGetter(JSContext* cx, unsigned argc, Value* vp);
    1385             :     static MOZ_MUST_USE bool olderGetter(JSContext* cx, unsigned argc, Value* vp);
    1386             :     static MOZ_MUST_USE bool thisGetter(JSContext* cx, unsigned argc, Value* vp);
    1387             :     static MOZ_MUST_USE bool typeGetter(JSContext* cx, unsigned argc, Value* vp);
    1388             :     static MOZ_MUST_USE bool implementationGetter(JSContext* cx, unsigned argc, Value* vp);
    1389             :     static MOZ_MUST_USE bool onStepGetter(JSContext* cx, unsigned argc, Value* vp);
    1390             :     static MOZ_MUST_USE bool onStepSetter(JSContext* cx, unsigned argc, Value* vp);
    1391             :     static MOZ_MUST_USE bool onPopGetter(JSContext* cx, unsigned argc, Value* vp);
    1392             :     static MOZ_MUST_USE bool onPopSetter(JSContext* cx, unsigned argc, Value* vp);
    1393             : 
    1394             :     static MOZ_MUST_USE bool evalMethod(JSContext* cx, unsigned argc, Value* vp);
    1395             :     static MOZ_MUST_USE bool evalWithBindingsMethod(JSContext* cx, unsigned argc, Value* vp);
    1396             : 
    1397             :     Debugger* owner() const;
    1398             :   public:
    1399             :     FrameIter::Data* frameIterData() const;
    1400             : };
    1401             : 
    1402             : class DebuggerObject : public NativeObject
    1403             : {
    1404             :   public:
    1405             :     static const Class class_;
    1406             : 
    1407             :     static NativeObject* initClass(JSContext* cx, Handle<GlobalObject*> global,
    1408             :                                    HandleObject debugCtor);
    1409             :     static DebuggerObject* create(JSContext* cx, HandleObject proto, HandleObject obj,
    1410             :                                   HandleNativeObject debugger);
    1411             : 
    1412             :     // Properties
    1413             :     static MOZ_MUST_USE bool getClassName(JSContext* cx, HandleDebuggerObject object,
    1414             :                                           MutableHandleString result);
    1415             :     static MOZ_MUST_USE bool getGlobal(JSContext* cx, HandleDebuggerObject object,
    1416             :                                        MutableHandleDebuggerObject result);
    1417             :     static MOZ_MUST_USE bool getParameterNames(JSContext* cx, HandleDebuggerObject object,
    1418             :                                                MutableHandle<StringVector> result);
    1419             :     static MOZ_MUST_USE bool getBoundTargetFunction(JSContext* cx, HandleDebuggerObject object,
    1420             :                                                  MutableHandleDebuggerObject result);
    1421             :     static MOZ_MUST_USE bool getBoundThis(JSContext* cx, HandleDebuggerObject object,
    1422             :                                           MutableHandleValue result);
    1423             :     static MOZ_MUST_USE bool getBoundArguments(JSContext* cx, HandleDebuggerObject object,
    1424             :                                                MutableHandle<ValueVector> result);
    1425             :     static MOZ_MUST_USE bool getAllocationSite(JSContext* cx, HandleDebuggerObject object,
    1426             :                                             MutableHandleObject result);
    1427             :     static MOZ_MUST_USE bool getErrorMessageName(JSContext* cx, HandleDebuggerObject object,
    1428             :                                                  MutableHandleString result);
    1429             :     static MOZ_MUST_USE bool getErrorNotes(JSContext* cx, HandleDebuggerObject object,
    1430             :                                            MutableHandleValue result);
    1431             :     static MOZ_MUST_USE bool getErrorLineNumber(JSContext* cx, HandleDebuggerObject object,
    1432             :                                                 MutableHandleValue result);
    1433             :     static MOZ_MUST_USE bool getErrorColumnNumber(JSContext* cx, HandleDebuggerObject object,
    1434             :                                                   MutableHandleValue result);
    1435             :     static MOZ_MUST_USE bool getScriptedProxyTarget(JSContext* cx, HandleDebuggerObject object,
    1436             :                                                     MutableHandleDebuggerObject result);
    1437             :     static MOZ_MUST_USE bool getScriptedProxyHandler(JSContext* cx, HandleDebuggerObject object,
    1438             :                                                      MutableHandleDebuggerObject result);
    1439             :     static MOZ_MUST_USE bool getPromiseValue(JSContext* cx, HandleDebuggerObject object,
    1440             :                                              MutableHandleValue result);
    1441             :     static MOZ_MUST_USE bool getPromiseReason(JSContext* cx, HandleDebuggerObject object,
    1442             :                                               MutableHandleValue result);
    1443             : 
    1444             :     // Methods
    1445             :     static MOZ_MUST_USE bool isExtensible(JSContext* cx, HandleDebuggerObject object,
    1446             :                                           bool& result);
    1447             :     static MOZ_MUST_USE bool isSealed(JSContext* cx, HandleDebuggerObject object, bool& result);
    1448             :     static MOZ_MUST_USE bool isFrozen(JSContext* cx, HandleDebuggerObject object, bool& result);
    1449             :     static MOZ_MUST_USE bool getPrototypeOf(JSContext* cx, HandleDebuggerObject object,
    1450             :                                             MutableHandleDebuggerObject result);
    1451             :     static MOZ_MUST_USE bool getOwnPropertyNames(JSContext* cx, HandleDebuggerObject object,
    1452             :                                                  MutableHandle<IdVector> result);
    1453             :     static MOZ_MUST_USE bool getOwnPropertySymbols(JSContext* cx, HandleDebuggerObject object,
    1454             :                                                    MutableHandle<IdVector> result);
    1455             :     static MOZ_MUST_USE bool getOwnPropertyDescriptor(JSContext* cx, HandleDebuggerObject object,
    1456             :                                                       HandleId id,
    1457             :                                                       MutableHandle<PropertyDescriptor> desc);
    1458             :     static MOZ_MUST_USE bool preventExtensions(JSContext* cx, HandleDebuggerObject object);
    1459             :     static MOZ_MUST_USE bool seal(JSContext* cx, HandleDebuggerObject object);
    1460             :     static MOZ_MUST_USE bool freeze(JSContext* cx, HandleDebuggerObject object);
    1461             :     static MOZ_MUST_USE bool defineProperty(JSContext* cx, HandleDebuggerObject object,
    1462             :                                             HandleId id, Handle<PropertyDescriptor> desc);
    1463             :     static MOZ_MUST_USE bool defineProperties(JSContext* cx, HandleDebuggerObject object,
    1464             :                                               Handle<IdVector> ids,
    1465             :                                               Handle<PropertyDescriptorVector> descs);
    1466             :     static MOZ_MUST_USE bool deleteProperty(JSContext* cx, HandleDebuggerObject object,
    1467             :                                             HandleId id, ObjectOpResult& result);
    1468             :     static MOZ_MUST_USE bool call(JSContext* cx, HandleDebuggerObject object, HandleValue thisv,
    1469             :                                   Handle<ValueVector> args, MutableHandleValue result);
    1470             :     static MOZ_MUST_USE bool forceLexicalInitializationByName(JSContext* cx,
    1471             :                                                               HandleDebuggerObject object,
    1472             :                                                               HandleId id, bool& result);
    1473             :     static MOZ_MUST_USE bool executeInGlobal(JSContext* cx, HandleDebuggerObject object,
    1474             :                                              mozilla::Range<const char16_t> chars,
    1475             :                                              HandleObject bindings, const EvalOptions& options,
    1476             :                                              ResumeMode& resumeMode, MutableHandleValue value);
    1477             :     static MOZ_MUST_USE bool makeDebuggeeValue(JSContext* cx, HandleDebuggerObject object,
    1478             :                                                HandleValue value, MutableHandleValue result);
    1479             :     static MOZ_MUST_USE bool unsafeDereference(JSContext* cx, HandleDebuggerObject object,
    1480             :                                                MutableHandleObject result);
    1481             :     static MOZ_MUST_USE bool unwrap(JSContext* cx, HandleDebuggerObject object,
    1482             :                                     MutableHandleDebuggerObject result);
    1483             : 
    1484             :     // Infallible properties
    1485             :     bool isCallable() const;
    1486             :     bool isFunction() const;
    1487             :     bool isDebuggeeFunction() const;
    1488             :     bool isBoundFunction() const;
    1489             :     bool isArrowFunction() const;
    1490             :     bool isAsyncFunction() const;
    1491             :     bool isGeneratorFunction() const;
    1492             :     bool isGlobal() const;
    1493             :     bool isScriptedProxy() const;
    1494             :     bool isPromise() const;
    1495             :     JSAtom* name(JSContext* cx) const;
    1496             :     JSAtom* displayName(JSContext* cx) const;
    1497             :     JS::PromiseState promiseState() const;
    1498             :     double promiseLifetime() const;
    1499             :     double promiseTimeToResolution() const;
    1500             : 
    1501             :   private:
    1502             :     enum {
    1503             :         OWNER_SLOT
    1504             :     };
    1505             : 
    1506             :     static const unsigned RESERVED_SLOTS = 1;
    1507             : 
    1508             :     static const ClassOps classOps_;
    1509             : 
    1510             :     static const JSPropertySpec properties_[];
    1511             :     static const JSPropertySpec promiseProperties_[];
    1512             :     static const JSFunctionSpec methods_[];
    1513             : 
    1514           0 :     JSObject* referent() const {
    1515           0 :         JSObject* obj = (JSObject*) getPrivate();
    1516           0 :         MOZ_ASSERT(obj);
    1517           0 :         return obj;
    1518             :     }
    1519             : 
    1520             :     Debugger* owner() const;
    1521             :     PromiseObject* promise() const;
    1522             : 
    1523             :     static MOZ_MUST_USE bool requireGlobal(JSContext* cx, HandleDebuggerObject object);
    1524             :     static MOZ_MUST_USE bool requirePromise(JSContext* cx, HandleDebuggerObject object);
    1525             :     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
    1526             : 
    1527             :     // JSNative properties
    1528             :     static MOZ_MUST_USE bool callableGetter(JSContext* cx, unsigned argc, Value* vp);
    1529             :     static MOZ_MUST_USE bool isBoundFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
    1530             :     static MOZ_MUST_USE bool isArrowFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
    1531             :     static MOZ_MUST_USE bool isAsyncFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
    1532             :     static MOZ_MUST_USE bool isGeneratorFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
    1533             :     static MOZ_MUST_USE bool protoGetter(JSContext* cx, unsigned argc, Value* vp);
    1534             :     static MOZ_MUST_USE bool classGetter(JSContext* cx, unsigned argc, Value* vp);
    1535             :     static MOZ_MUST_USE bool nameGetter(JSContext* cx, unsigned argc, Value* vp);
    1536             :     static MOZ_MUST_USE bool displayNameGetter(JSContext* cx, unsigned argc, Value* vp);
    1537             :     static MOZ_MUST_USE bool parameterNamesGetter(JSContext* cx, unsigned argc, Value* vp);
    1538             :     static MOZ_MUST_USE bool scriptGetter(JSContext* cx, unsigned argc, Value* vp);
    1539             :     static MOZ_MUST_USE bool environmentGetter(JSContext* cx, unsigned argc, Value* vp);
    1540             :     static MOZ_MUST_USE bool boundTargetFunctionGetter(JSContext* cx, unsigned argc, Value* vp);
    1541             :     static MOZ_MUST_USE bool boundThisGetter(JSContext* cx, unsigned argc, Value* vp);
    1542             :     static MOZ_MUST_USE bool boundArgumentsGetter(JSContext* cx, unsigned argc, Value* vp);
    1543             :     static MOZ_MUST_USE bool globalGetter(JSContext* cx, unsigned argc, Value* vp);
    1544             :     static MOZ_MUST_USE bool allocationSiteGetter(JSContext* cx, unsigned argc, Value* vp);
    1545             :     static MOZ_MUST_USE bool errorMessageNameGetter(JSContext* cx, unsigned argc, Value* vp);
    1546             :     static MOZ_MUST_USE bool errorNotesGetter(JSContext* cx, unsigned argc, Value* vp);
    1547             :     static MOZ_MUST_USE bool errorLineNumberGetter(JSContext* cx, unsigned argc, Value* vp);
    1548             :     static MOZ_MUST_USE bool errorColumnNumberGetter(JSContext* cx, unsigned argc, Value* vp);
    1549             :     static MOZ_MUST_USE bool isProxyGetter(JSContext* cx, unsigned argc, Value* vp);
    1550             :     static MOZ_MUST_USE bool proxyTargetGetter(JSContext* cx, unsigned argc, Value* vp);
    1551             :     static MOZ_MUST_USE bool proxyHandlerGetter(JSContext* cx, unsigned argc, Value* vp);
    1552             :     static MOZ_MUST_USE bool isPromiseGetter(JSContext* cx, unsigned argc, Value* vp);
    1553             :     static MOZ_MUST_USE bool promiseStateGetter(JSContext* cx, unsigned argc, Value* vp);
    1554             :     static MOZ_MUST_USE bool promiseValueGetter(JSContext* cx, unsigned argc, Value* vp);
    1555             :     static MOZ_MUST_USE bool promiseReasonGetter(JSContext* cx, unsigned argc, Value* vp);
    1556             :     static MOZ_MUST_USE bool promiseLifetimeGetter(JSContext* cx, unsigned argc, Value* vp);
    1557             :     static MOZ_MUST_USE bool promiseTimeToResolutionGetter(JSContext* cx, unsigned argc, Value* vp);
    1558             :     static MOZ_MUST_USE bool promiseAllocationSiteGetter(JSContext* cx, unsigned argc, Value* vp);
    1559             :     static MOZ_MUST_USE bool promiseResolutionSiteGetter(JSContext* cx, unsigned argc, Value* vp);
    1560             :     static MOZ_MUST_USE bool promiseIDGetter(JSContext* cx, unsigned argc, Value* vp);
    1561             :     static MOZ_MUST_USE bool promiseDependentPromisesGetter(JSContext* cx, unsigned argc, Value* vp);
    1562             : 
    1563             :     // JSNative methods
    1564             :     static MOZ_MUST_USE bool isExtensibleMethod(JSContext* cx, unsigned argc, Value* vp);
    1565             :     static MOZ_MUST_USE bool isSealedMethod(JSContext* cx, unsigned argc, Value* vp);
    1566             :     static MOZ_MUST_USE bool isFrozenMethod(JSContext* cx, unsigned argc, Value* vp);
    1567             :     static MOZ_MUST_USE bool getOwnPropertyNamesMethod(JSContext* cx, unsigned argc, Value* vp);
    1568             :     static MOZ_MUST_USE bool getOwnPropertySymbolsMethod(JSContext* cx, unsigned argc, Value* vp);
    1569             :     static MOZ_MUST_USE bool getOwnPropertyDescriptorMethod(JSContext* cx, unsigned argc, Value* vp);
    1570             :     static MOZ_MUST_USE bool preventExtensionsMethod(JSContext* cx, unsigned argc, Value* vp);
    1571             :     static MOZ_MUST_USE bool sealMethod(JSContext* cx, unsigned argc, Value* vp);
    1572             :     static MOZ_MUST_USE bool freezeMethod(JSContext* cx, unsigned argc, Value* vp);
    1573             :     static MOZ_MUST_USE bool definePropertyMethod(JSContext* cx, unsigned argc, Value* vp);
    1574             :     static MOZ_MUST_USE bool definePropertiesMethod(JSContext* cx, unsigned argc, Value* vp);
    1575             :     static MOZ_MUST_USE bool deletePropertyMethod(JSContext* cx, unsigned argc, Value* vp);
    1576             :     static MOZ_MUST_USE bool callMethod(JSContext* cx, unsigned argc, Value* vp);
    1577             :     static MOZ_MUST_USE bool applyMethod(JSContext* cx, unsigned argc, Value* vp);
    1578             :     static MOZ_MUST_USE bool asEnvironmentMethod(JSContext* cx, unsigned argc, Value* vp);
    1579             :     static MOZ_MUST_USE bool forceLexicalInitializationByNameMethod(JSContext* cx, unsigned argc, Value* vp);
    1580             :     static MOZ_MUST_USE bool executeInGlobalMethod(JSContext* cx, unsigned argc, Value* vp);
    1581             :     static MOZ_MUST_USE bool executeInGlobalWithBindingsMethod(JSContext* cx, unsigned argc, Value* vp);
    1582             :     static MOZ_MUST_USE bool makeDebuggeeValueMethod(JSContext* cx, unsigned argc, Value* vp);
    1583             :     static MOZ_MUST_USE bool unsafeDereferenceMethod(JSContext* cx, unsigned argc, Value* vp);
    1584             :     static MOZ_MUST_USE bool unwrapMethod(JSContext* cx, unsigned argc, Value* vp);
    1585             :     static MOZ_MUST_USE bool getErrorReport(JSContext* cx, HandleObject maybeError,
    1586             :                                             JSErrorReport*& report);
    1587             : };
    1588             : 
    1589             : class JSBreakpointSite;
    1590             : class WasmBreakpoint;
    1591             : class WasmBreakpointSite;
    1592             : 
    1593             : class BreakpointSite {
    1594             :     friend class Breakpoint;
    1595             :     friend class ::JSScript;
    1596             :     friend class Debugger;
    1597             : 
    1598             :   public:
    1599             :     enum class Type { JS, Wasm };
    1600             : 
    1601             :   private:
    1602             :     Type type_;
    1603             : 
    1604             :     template <typename T>
    1605             :     struct SiteLinkAccess {
    1606             :       static mozilla::DoublyLinkedListElement<T>& Get(T* aThis) {
    1607             :         return aThis->siteLink;
    1608             :       }
    1609             :     };
    1610             : 
    1611             :     // List of all js::Breakpoints at this instruction.
    1612             :     using BreakpointList =
    1613             :         mozilla::DoublyLinkedList<js::Breakpoint,
    1614             :                                   SiteLinkAccess<js::Breakpoint>>;
    1615             :     BreakpointList breakpoints;
    1616             :     size_t enabledCount;  /* number of breakpoints in the list that are enabled */
    1617             : 
    1618             :   protected:
    1619             :     virtual void recompile(FreeOp* fop) = 0;
    1620             :     bool isEmpty() const;
    1621           0 :     inline bool isEnabled() const { return enabledCount > 0; }
    1622             : 
    1623             :   public:
    1624             :     BreakpointSite(Type type);
    1625             :     Breakpoint* firstBreakpoint() const;
    1626             :     virtual ~BreakpointSite() {}
    1627             :     bool hasBreakpoint(Breakpoint* bp);
    1628             :     inline Type type() const { return type_; }
    1629             : 
    1630             :     void inc(FreeOp* fop);
    1631             :     void dec(FreeOp* fop);
    1632             :     virtual void destroyIfEmpty(FreeOp* fop) = 0;
    1633             : 
    1634             :     inline JSBreakpointSite* asJS();
    1635             :     inline WasmBreakpointSite* asWasm();
    1636             : };
    1637             : 
    1638             : /*
    1639             :  * Each Breakpoint is a member of two linked lists: its debugger's list and its
    1640             :  * site's list.
    1641             :  *
    1642             :  * GC rules:
    1643             :  *   - script is live, breakpoint exists, and debugger is enabled
    1644             :  *      ==> debugger is live
    1645             :  *   - script is live, breakpoint exists, and debugger is live
    1646             :  *      ==> retain the breakpoint and the handler object is live
    1647             :  *
    1648             :  * Debugger::markIteratively implements these two rules. It uses
    1649             :  * Debugger::hasAnyLiveHooks to check for rule 1.
    1650             :  *
    1651             :  * Nothing else causes a breakpoint to be retained, so if its script or
    1652             :  * debugger is collected, the breakpoint is destroyed during GC sweep phase,
    1653             :  * even if the debugger compartment isn't being GC'd. This is implemented in
    1654             :  * Zone::sweepBreakpoints.
    1655             :  */
    1656           0 : class Breakpoint {
    1657             :     friend class Debugger;
    1658             :     friend class BreakpointSite;
    1659             : 
    1660             :   public:
    1661             :     Debugger * const debugger;
    1662             :     BreakpointSite * const site;
    1663             :   private:
    1664             :     /* |handler| is marked unconditionally during minor GC. */
    1665             :     js::PreBarrieredObject handler;
    1666             : 
    1667             :     /**
    1668             :      * Link elements for each list this breakpoint can be in.
    1669             :      */
    1670             :     mozilla::DoublyLinkedListElement<Breakpoint> debuggerLink;
    1671             :     mozilla::DoublyLinkedListElement<Breakpoint> siteLink;
    1672             : 
    1673             :   public:
    1674             :     Breakpoint(Debugger* debugger, BreakpointSite* site, JSObject* handler);
    1675             :     void destroy(FreeOp* fop);
    1676             :     Breakpoint* nextInDebugger();
    1677             :     Breakpoint* nextInSite();
    1678             :     const PreBarrieredObject& getHandler() const { return handler; }
    1679             :     PreBarrieredObject& getHandlerRef() { return handler; }
    1680             : 
    1681             :     inline WasmBreakpoint* asWasm();
    1682             : };
    1683             : 
    1684           0 : class JSBreakpointSite : public BreakpointSite
    1685             : {
    1686             :   public:
    1687             :     JSScript* script;
    1688             :     jsbytecode * const pc;
    1689             : 
    1690             :   protected:
    1691             :     void recompile(FreeOp* fop) override;
    1692             : 
    1693             :   public:
    1694             :     JSBreakpointSite(JSScript* script, jsbytecode* pc);
    1695             : 
    1696             :     void destroyIfEmpty(FreeOp* fop) override;
    1697             : };
    1698             : 
    1699             : inline JSBreakpointSite*
    1700           0 : BreakpointSite::asJS()
    1701             : {
    1702           0 :     MOZ_ASSERT(type() == Type::JS);
    1703           0 :     return static_cast<JSBreakpointSite*>(this);
    1704             : }
    1705             : 
    1706           0 : class WasmBreakpointSite : public BreakpointSite
    1707             : {
    1708             :   public:
    1709             :     wasm::DebugState* debug;
    1710             :     uint32_t offset;
    1711             : 
    1712             :   protected:
    1713             :     void recompile(FreeOp* fop) override;
    1714             : 
    1715             :   public:
    1716             :     WasmBreakpointSite(wasm::DebugState* debug, uint32_t offset);
    1717             : 
    1718             :     void destroyIfEmpty(FreeOp* fop) override;
    1719             : };
    1720             : 
    1721             : inline WasmBreakpointSite*
    1722             : BreakpointSite::asWasm()
    1723             : {
    1724             :     MOZ_ASSERT(type() == Type::Wasm);
    1725             :     return static_cast<WasmBreakpointSite*>(this);
    1726             : }
    1727             : 
    1728             : class WasmBreakpoint : public Breakpoint
    1729             : {
    1730             :   public:
    1731             :     WasmInstanceObject* wasmInstance;
    1732             : 
    1733             :     WasmBreakpoint(Debugger* debugger, WasmBreakpointSite* site, JSObject* handler,
    1734             :                    WasmInstanceObject* wasmInstance_)
    1735           0 :       : Breakpoint(debugger, site, handler),
    1736           0 :         wasmInstance(wasmInstance_)
    1737             :     {}
    1738             : };
    1739             : 
    1740             : inline WasmBreakpoint*
    1741           0 : Breakpoint::asWasm()
    1742             : {
    1743           0 :     MOZ_ASSERT(site && site->type() == BreakpointSite::Type::Wasm);
    1744           0 :     return static_cast<WasmBreakpoint*>(this);
    1745             : }
    1746             : 
    1747             : 
    1748             : Breakpoint*
    1749             : Debugger::firstBreakpoint() const
    1750             : {
    1751           0 :     if (breakpoints.isEmpty())
    1752             :         return nullptr;
    1753           0 :     return &(*breakpoints.begin());
    1754             : }
    1755             : 
    1756             : const js::GCPtrNativeObject&
    1757           0 : Debugger::toJSObject() const
    1758             : {
    1759           0 :     MOZ_ASSERT(object);
    1760           0 :     return object;
    1761             : }
    1762             : 
    1763             : js::GCPtrNativeObject&
    1764           0 : Debugger::toJSObjectRef()
    1765             : {
    1766           0 :     MOZ_ASSERT(object);
    1767           0 :     return object;
    1768             : }
    1769             : 
    1770             : bool
    1771             : Debugger::observesEnterFrame() const
    1772             : {
    1773           0 :     return enabled && getHook(OnEnterFrame);
    1774             : }
    1775             : 
    1776             : bool
    1777             : Debugger::observesNewScript() const
    1778             : {
    1779           0 :     return enabled && getHook(OnNewScript);
    1780             : }
    1781             : 
    1782             : bool
    1783             : Debugger::observesNewGlobalObject() const
    1784             : {
    1785           0 :     return enabled && getHook(OnNewGlobalObject);
    1786             : }
    1787             : 
    1788             : bool
    1789           0 : Debugger::observesGlobal(GlobalObject* global) const
    1790             : {
    1791           0 :     ReadBarriered<GlobalObject*> debuggee(global);
    1792           0 :     return debuggees.has(debuggee);
    1793             : }
    1794             : 
    1795             : /* static */ void
    1796        2230 : Debugger::onNewScript(JSContext* cx, HandleScript script)
    1797             : {
    1798             :     // We early return in slowPathOnNewScript for self-hosted scripts, so we can
    1799             :     // ignore those in our assertion here.
    1800        6368 :     MOZ_ASSERT_IF(!script->realm()->creationOptions().invisibleToDebugger() &&
    1801             :                   !script->selfHosted(),
    1802             :                   script->realm()->firedOnNewGlobalObject);
    1803             : 
    1804             :     // The script may not be ready to be interrogated by the debugger.
    1805        4460 :     if (script->hideScriptFromDebugger())
    1806             :         return;
    1807             : 
    1808        4460 :     if (script->realm()->isDebuggee())
    1809           0 :         slowPathOnNewScript(cx, script);
    1810             : }
    1811             : 
    1812             : /* static */ void
    1813          42 : Debugger::onNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global)
    1814             : {
    1815          84 :     MOZ_ASSERT(!global->realm()->firedOnNewGlobalObject);
    1816             : #ifdef DEBUG
    1817          84 :     global->realm()->firedOnNewGlobalObject = true;
    1818             : #endif
    1819          84 :     if (!cx->runtime()->onNewGlobalObjectWatchers().isEmpty())
    1820           0 :         Debugger::slowPathOnNewGlobalObject(cx, global);
    1821           0 : }
    1822             : 
    1823             : /* static */ bool
    1824           0 : Debugger::onLogAllocationSite(JSContext* cx, JSObject* obj, HandleSavedFrame frame, mozilla::TimeStamp when)
    1825             : {
    1826           0 :     GlobalObject::DebuggerVector* dbgs = cx->global()->getDebuggers();
    1827           0 :     if (!dbgs || dbgs->empty())
    1828             :         return true;
    1829           0 :     RootedObject hobj(cx, obj);
    1830           0 :     return Debugger::slowPathOnLogAllocationSite(cx, hobj, frame, when, *dbgs);
    1831             : }
    1832             : 
    1833             : MOZ_MUST_USE bool ReportObjectRequired(JSContext* cx);
    1834             : 
    1835             : } /* namespace js */
    1836             : 
    1837             : namespace JS {
    1838             : 
    1839             : template <>
    1840             : struct DeletePolicy<js::Debugger> : public js::GCManagedDeletePolicy<js::Debugger>
    1841             : {};
    1842             : 
    1843             : } /* namespace JS */
    1844             : 
    1845             : #endif /* vm_Debugger_h */

Generated by: LCOV version 1.13-14-ga5dd952