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

Generated by: LCOV version 1.13