diff options
Diffstat (limited to '')
15 files changed, 2009 insertions, 0 deletions
diff --git a/devtools/docs/user/debugger-api/debugger.environment/index.rst b/devtools/docs/user/debugger-api/debugger.environment/index.rst new file mode 100644 index 0000000000..43baa06f25 --- /dev/null +++ b/devtools/docs/user/debugger-api/debugger.environment/index.rst @@ -0,0 +1,98 @@ +==================== +Debugger.Environment +==================== + +A ``Debugger.Environment`` instance represents a lexical environment, associating names with variables. Each :doc:`Debugger.Frame <../debugger.frame/index>` instance representing a debuggee frame has an associated environment object describing the variables in scope in that frame; and each :doc:`Debugger.Object <../debugger.object/index>` instance representing a debuggee function has an environment object representing the environment the function has closed over. + +ECMAScript environments form a tree, in which each local environment is parented by its enclosing environment (in ECMAScript terms, its ‘outer’ environment). We say an environment *binds* an identifier if that environment itself associates the identifier with a variable, independently of its outer environments. We say an identifier is *in scope* in an environment if the identifier is bound in that environment or any enclosing environment. + +SpiderMonkey creates ``Debugger.Environment`` instances as needed as the debugger inspects stack frames and function objects; calling ``Debugger.Environment`` as a function or constructor raises a ``TypeError`` exception. + +SpiderMonkey creates exactly one ``Debugger.Environment`` instance for each environment it presents via a given :doc:`Debugger <../debugger/index>` instance: if the debugger encounters the same environment through two different routes (perhaps two functions have closed over the same environment), SpiderMonkey presents the same ``Debugger.Environment`` instance to the debugger each time. This means that the debugger can use the ``==`` operator to recognize when two ``Debugger.Environment`` instances refer to the same environment in the debuggee, and place its own properties on a ``Debugger.Environment`` instance to store metadata about particular environments. + +(If more than one :doc:`Debugger <../debugger/index>` instance is debugging the same code, each :doc:`Debugger <../debugger/index>` gets a separate ``Debugger.Environment`` instance for a given environment. This allows the code using each :doc:`Debugger <../debugger/index>` instance to place whatever properties it likes on its own :doc:`Debugger.Object <../debugger.object/index>` instances, without worrying about interfering with other debuggers.) + +If a ``Debugger.Environment`` instance’s referent is not a debuggee environment, then attempting to access its properties (other than ``inspectable``) or call any its methods throws an instance of ``Error``. + +``Debugger.Environment`` instances protect their referents from the garbage collector; as long as the ``Debugger.Environment`` instance is live, the referent remains live. Garbage collection has no visible effect on ``Debugger.Environment`` instances. + + +Accessor Properties of the Debugger.Environment Prototype Object +**************************************************************** + +A ``Debugger.Environment`` instance inherits the following accessor properties from its prototype: + + +``inspectable`` + + True if this environment is a debuggee environment, and can therefore be inspected. False otherwise. All other properties and methods of ``Debugger.Environment`` instances throw if applied to a non-inspectable environment. + +``type`` + + The type of this environment object, one of the following values: + + - “declarative”, indicating that the environment is a declarative environment record. Function calls, calls to ``eval``, ``let`` blocks, ``catch`` blocks, and the like create declarative environment records. + + - “object”, indicating that the environment’s bindings are the properties of an object. The global object and DOM elements appear in the chain of environments via object environments. (Note that ``with`` statements have their own environment type.) + + - “with”, indicating that the environment was introduced by a ``with`` statement. + +``parent`` + + The environment that encloses this one (the “outer” environment, in ECMAScript terminology), or ``null`` if this is the outermost environment. + +``object`` + + A :doc:`Debugger.Object <../debugger.object/index>` instance referring to the object whose properties this environment reflects. If this is a declarative environment record, this accessor throws a ``TypeError`` (since declarative environment records have no such object). Both ``"object"`` and ``"with"`` environments have ``object`` properties that provide the object whose properties they reflect as variable bindings. + +``callee`` + + If this environment represents the variable environment (the top-level environment within the function, which receives ``var`` definitions) for a call to a function *f*, then this property’s value is a :doc:`Debugger.Object <../debugger.object/index>` instance referring to *f*. Otherwise, this property’s value is ``null``. + +``optimizedOut`` + + True if this environment is optimized out. False otherwise. For example, functions whose locals are never aliased may present optimized-out environments. When true, ``getVariable`` returns an ordinary JavaScript object whose ``optimizedOut`` property is true on all bindings, and ``setVariable`` throws a ``ReferenceError``. + + +Function Properties of the Debugger.Environment Prototype Object +**************************************************************** + +The methods described below may only be called with a ``this`` value referring to a ``Debugger.Environment`` instance; they may not be used as methods of other kinds of objects. + + +``names()`` + + Return an array of strings giving the names of the identifiers bound by this environment. The result does not include the names of identifiers bound by enclosing environments. + +``getVariable(*name*)`` + + Return the value of the variable bound to *name* in this environment, or ``undefined`` if this environment does not bind *name*. *Name* must be a string that is a valid ECMAScript identifier name. The result is a debuggee value. + + JavaScript engines often omit variables from environments, to save space and reduce execution time. If the given variable should be in scope, but ``getVariable`` is unable to produce its value, it returns an ordinary JavaScript object (not a :doc:`Debugger.Object <../debugger.object/index>` instance) whose ``optimizedOut`` property is ``true``. + + This is not an :ref:`invocation function <debugger-api-debugger-frame-invf>`; if this call would cause debuggee code to run (say, because the environment is a ``"with"`` environment, and *name* refers to an accessor property of the ``with`` statement’s operand), this call throws a ``Debugger.DebuggeeWouldRun`` exception. + +``setVariable(*name*,*value*)`` + + Store *value* as the value of the variable bound to *name* in this environment. *Name* must be a string that is a valid ECMAScript identifier name; *value* must be a debuggee value. + + If this environment binds no variable named *name*, throw a ``ReferenceError``. + + This is not an :ref:`invocation function <debugger-api-debugger-frame-invf>`; if this call would cause debuggee code to run, this call throws a ``Debugger.DebuggeeWouldRun`` exception. + +``find(*name*)`` + + Return a reference to the innermost environment, starting with this environment, that binds *name*. If *name* is not in scope in this environment, return ``null``. *Name* must be a string whose value is a valid ECMAScript identifier name. + + +Source Metadata +--------------- + +Generated from file: + js/src/doc/Debugger/Debugger.Environment.md + +Watermark: + sha256:3d6f67939e351803d5d7fe201ed38c4aaf766caf032f255e168df1f1c6fe73cb + +Changeset: + `7ae377917236 <https://hg.mozilla.org/mozilla-central/rev/7ae377917236>`_ diff --git a/devtools/docs/user/debugger-api/debugger.frame/index.rst b/devtools/docs/user/debugger-api/debugger.frame/index.rst new file mode 100644 index 0000000000..b1c53f19e4 --- /dev/null +++ b/devtools/docs/user/debugger-api/debugger.frame/index.rst @@ -0,0 +1,202 @@ +============== +Debugger.Frame +============== + +A ``Debugger.Frame`` instance represents a :ref:`visible stack frame <debugger-api-debugger-frame-visible-frames>`. Given a ``Debugger.Frame`` instance, you can find the script the frame is executing, walk the stack to older frames, find the lexical environment in which the execution is taking place, and so on. + +For a given :doc:`Debugger <../debugger/index>` instance, SpiderMonkey creates only one ``Debugger.Frame`` instance for a given visible frame. Every handler method called while the debuggee is running in a given frame is given the same frame object. Similarly, walking the stack back to a previously accessed frame yields the same frame object as before. Debugger code can add its own properties to a frame object and expect to find them later, use ``==`` to decide whether two expressions refer to the same frame, and so on. + +(If more than one :doc:`Debugger <../debugger/index>` instance is debugging the same code, each :doc:`Debugger <../debugger/index>` gets a separate ``Debugger.Frame`` instance for a given frame. This allows the code using each :doc:`Debugger <../debugger/index>` instance to place whatever properties it likes on its ``Debugger.Frame`` instances, without worrying about interfering with other debuggers.) + +When the debuggee pops a stack frame (say, because a function call has returned or an exception has been thrown from it), the ``Debugger.Frame`` instance referring to that frame becomes inactive: its ``live`` property becomes ``false``, and accessing its other properties or calling its methods throws an exception. Note that frames only become inactive at times that are predictable for the debugger: when the debuggee runs, or when the debugger removes frames from the stack itself. + + +.. _debugger-api-debugger-frame-visible-frames: + +Visible frames +************** + +When inspecting the call stack, :doc:`Debugger <../debugger/index>` does not reveal all the frames that are actually present on the stack: while it does reveal all frames running debuggee code, it omits frames running the debugger’s own code, and omits most frames running non-debuggee code. We call those stack frames a :doc:`Debugger <../debugger/index>` does reveal *visible frames*. + +A frame is a visible frame if any of the following are true: + + +- it is running debuggee code; + +- its immediate caller is a frame running debuggee code; or + +- it is a :ref:`"debugger" <debugger-api-debugger-frame-invf>`, representing the continuation of debuggee code invoked by the debugger. + + +The “immediate caller” rule means that, when debuggee code calls a non-debuggee funct`on, it looks like a call to a primitive: you see a frame for the non-debuggee function that was accessible to the debuggee, but any further calls that function makes are treated as internal details, and omitted from the stack trace. If the non-debuggee function eventually calls back into debuggee code, then those frames are visible. + +(Note that the debuggee is not considered an “immediate caller” of handler methods it triggers. Even though the debuggee and debugger share the same JavaScript stack, frames pushed for SpiderMonkey’s calls to handler methods to report events in the debuggee are never considered visible frames.) + + +.. _debugger-api-debugger-frame-invf: + +Invocation functions and Debugger frames +**************************************** + +An *invocation function* is any function in this interface that allows the debugger to invoke code in the debuggee: ``Debugger.Object.prototype.call``, ``Debugger.Frame.prototype.eval``, and so on. + +While invocation functions differ in the code to be run and how to pass values to it, they all follow this general procedure: + +1. Let *older* be the youngest visible frame on the stack, or ``null`` if there is no such frame. (This is never one of the debugger’s own frames; those never appear as ``Debugger.Frame`` instances.) + +2. Push a ``"debugger"`` frame on the stack, with *older* as its ``older`` property. + +3. Invoke the debuggee code as appropriate for the given invocation function, with the ``"debugger"`` frame as its continuation. For example, ``Debugger.Frame.prototype.eval`` pushes an ``"eval"`` frame for code it runs, whereas ``Debugger.Object.prototype.call`` pushes a ``"call"`` frame. + +4. When the debuggee code completes, whether by returning, throwing an exception or being terminated, pop the ``"debugger"`` frame, and return an appropriate completion value from the invocation function to the debugger. + + +When a debugger calls an invocation function to run debuggee code, that code’s continuation is the debugger, not the next debuggee code frame. Pushing a ``"debugger"`` frame makes this continuation explicit, and makes it easier to find the extent of the stack created for the invocation. + + +Accessor properties of the Debugger.Frame prototype object +********************************************************** + +A ``Debugger.Frame`` instance inherits the following accessor properties from its prototype: + + +``type`` + + A string describing what sort of frame this is: + + - ``"call"``: a frame running a function call. (We may not be able to obtain frames for calls to host functions.) + + - ``"eval"``: a frame running code passed to ``eval``. + - ``"global"``: a frame running global code (JavaScript that is neither of the above). + - ``"module"``: a frame running code at the top level of a module. + - ``"wasmcall"``: a frame running a WebAssembly function call. + - ``"debugger"``: a frame for a call to user code invoked by the debugger (see the ``eval`` method below). + +``implementation`` + + A string describing which tier of the JavaScript engine this frame is executing in: + + - ``"interpreter"``: a frame running in the interpreter. + - ``"baseline"``: a frame running in the unoptimizing, baseline JIT. + - ``"ion"``: a frame running in the optimizing JIT. + - ``"wasm"``: a frame running in WebAssembly baseline JIT. + +``this`` + + The value of ``this`` for this frame (a debuggee value). For a ``wasmcall`` frame, this property throws a ``TypeError``. + +``older`` + + The next-older visible frame, in which control will resume when this frame completes. If there is no older frame, this is ``null``. + +``depth`` + The depth of this frame, counting from oldest to youngest; the oldest frame has a depth of zero. + +``live`` + True if the frame this ``Debugger.Frame`` instance refers to is still on the stack; false if it has completed execution or been popped in some other way. + +``script`` + The script being executed in this frame (a :doc:`Debugger.Script <../debugger.script/index>` instance), or ``null`` on frames that do not represent calls to debuggee code. On frames whose ``callee`` property is not null, this is equal to ``callee.script``. + +``offset`` + The offset of the bytecode instruction currently being executed in ``script``, or ``undefined`` if the frame’s ``script`` property is ``null``. For a ``wasmcall`` frame, this property throws a ``TypeError``. + +``environment`` + The lexical environment within which evaluation is taking place (a :doc:`Debugger.Environment <../debugger.environment/index>` instance), or ``null`` on frames that do not represent the evaluation of debuggee code, like calls non-debuggee functions, host functions or ``"debugger"`` frames. + +``callee`` + The function whose application created this frame, as a debuggee value, or ``null`` if this is not a ``"call"`` frame. + +``generator`` + True if this frame is a generator frame, false otherwise. + +``constructing`` + True if this frame is for a function called as a constructor, false otherwise. + +``arguments`` + The arguments passed to the current frame, or ``null`` if this is not a ``"call"`` frame. When non-``null``, this is an object, allocated in the same global as the debugger, with ``Array.prototype`` on its prototype chain, a non-writable ``length`` property, and properties whose names are array indices. Each property is a read-only accessor property whose getter returns the current value of the corresponding parameter. When the referent frame is popped, the argument value’s properties’ getters throw an error. + + +Handler methods of Debugger.Frame instances +******************************************* + +Each ``Debugger.Frame`` instance inherits accessor properties holding handler functions for SpiderMonkey to call when given events occur in the frame. + +Calls to frames’ handler methods are cross-compartment, intra-thread calls: the call takes place in the thread to which the frame belongs, and runs in the compartment to which the handler method belongs. + +``Debugger.Frame`` instances inherit the following handler method properties: + + +``onStep`` + + This property must be either ``undefined`` or a function. If it is a function, SpiderMonkey calls it when execution in this frame makes a small amount of progress, passing no arguments and providing this ``Debugger.Frame`` instance as the ``this`` value. The function should return a resumption value specifying how the debuggee’s execution should proceed. + + What constitutes “a small amount of progress” varies depending on the implementation, but it is fine-grained enough to implement useful “step” and “next” behavior. + + If multiple :doc:`Debugger <../debugger/index>` instances each have ``Debugger.Frame`` instances for a given stack frame with ``onStep`` handlers set, their handlers are run in an unspecified order. If any ``onStep`` handler forces the frame to return early (by returning a resumption value other than ``undefined``), any remaining debuggers’ ``onStep`` handlers do not run. + + This property is ignored on frames that are not executing debuggee code, like ``"call"`` frames for calls to host functions and ``"debugger"`` frames. + +``onPop`` + + This property must be either ``undefined`` or a function. If it is a function, SpiderMonkey calls it just before this frame is popped, passing a completion value indicating how this frame’s execution completed, and providing this ``Debugger.Frame`` instance as the ``this`` value. The function should return a resumption value indicating how execution should proceed. On newly created frames, this property’s value is ``undefined``. + + When this handler is called, this frame’s current execution location, as reflected in its ``offset`` and ``environment`` properties, is the operation which caused it to be unwound. In frames returning or throwing an exception, the location is often a return or a throw statement. In frames propagating exceptions, the location is a call. + + When an ``onPop`` call reports the completion of a construction call (that is, a function called via the ``new`` operator), the completion value passed to the handler describes the value returned by the function body. If this value is not an object, it may be different from the value produced by the ``new`` expression, which will be the value of the frame’s ``this`` property. (In ECMAScript terms, the ``onPop`` handler receives the value returned by the ``[[Call]]`` method, not the value returned by the ``[[Construct]]`` method.) + + When a debugger handler function forces a frame to complete early, by returning a ``{ return:... }``, ``{ throw:... }``, or ``null`` resumption value, SpiderMonkey calls the frame’s ``onPop`` handler, if any. The completion value passed in this case reflects the resumption value that caused the frame to complete. + + When SpiderMonkey calls an ``onPop`` handler for a frame that is throwing an exception or being terminated, and the handler returns ``undefined``, then SpiderMonkey proceeds with the exception or termination. That is, an ``undefined`` resumption value leaves the frame’s throwing and termination process undisturbed. + + If multiple :doc:`Debugger <../debugger/index>` instances each have ``Debugger.Frame`` instances for a given stack frame with ``onPop`` handlers set, their handlers are run in an unspecified order. The resumption value each handler returns establishes the completion value reported to the next handler. + + This handler is not called on ``"debugger"`` frames. It is also not called when unwinding a frame due to an over-recursion or out-of-memory exception. + + +Function properties of the Debugger.Frame prototype object +********************************************************** + +The functions described below may only be called with a ``this`` value referring to a ``Debugger.Frame`` instance; they may not be used as methods of other kinds of objects. + +.. _debugger-api-debugger-frame-eval: + +``eval(code, [options])`` + + Evaluate *code* in the execution context of this frame, and return a completion value describing how it completed. *Code* is a string. If this frame’s ``environment`` property is ``null`` or ``type`` property is ``wasmcall``, throw a ``TypeError``. All extant handler methods, breakpoints, and so on remain active during the call. This function follows the :ref:`invocation function convention <debugger-api-debugger-frame-invf>`. + + *Code* is interpreted as strict mode code when it contains a Use Strict Directive, or the code executing in this frame is strict mode code. + + If *code* is not strict mode code, then variable declarations in *code* affect the environment of this frame. (In the terms used by the ECMAScript specification, the ``VariableEnvironment`` of the execution context for the eval code is the ``VariableEnvironment`` of the execution context that this frame represents.) If implementation restrictions prevent SpiderMonkey from extending this frame’s environment as requested, this call throws an Error exception. + + If given, *options* should be an object whose properties specify details of how the evaluation should occur. The ``eval`` method recognizes the following properties: + + + ``url`` + The filename or URL to which we should attribute *code*. If this property is omitted, the URL defaults to ``"debugger eval code"``. + ``lineNumber`` + The line number at which the evaluated code should be claimed to begin within *url*. + + +``evalWithBindings(*code*,*bindings*, [*options*])`` + + Like ``eval``, but evaluate *code* in the environment of this frame, extended with bindings from the object *bindings*. For each own enumerable property of *bindings* named *name* whose value is *value*, include a variable in the environment in which *code* is evaluated named *name*, whose value is *value*. Each *value* must be a debuggee value. (This is not like a ``with`` statement: *code* may access, assign to, and delete the introduced bindings without having any effect on the *bindings* object.) + + This method allows debugger code to introduce temporary bindings that are visible to the given debuggee code and which refer to debugger-held debuggee values, and do so without mutating any existing debuggee environment. + + Note that, like ``eval``, declarations in the *code* passed to ``evalWithBindings`` affect the environment of this frame, even as that environment is extended by bindings visible within *code*. (In the terms used by the ECMAScript specification, the ``VariableEnvironment`` of the execution context for the eval code is the ``VariableEnvironment`` of the execution context that this frame represents, and the *bindings* appear in a new declarative environment, which is the eval code’s ``LexicalEnvironment``.) If implementation restrictions prevent SpiderMonkey from extending this frame’s environment as requested, this call throws an ``Error`` exception. + + The *options* argument is as for :ref:`Debugger.Frame.prototype.eval <debugger-api-debugger-frame-eval>`, described above. Also like ``eval``, if this frame’s ``environment`` property is ``null`` or ``type`` property is ``wasmcall``, throw a ``TypeError``. + + +Source Metadata +--------------- + +Generated from file: + js/src/doc/Debugger/Debugger.Frame.md + +Watermark: + sha256:b1894f88b76b7afd661f3044a05690d76d1498c54c596ca729c6ee0d150d2da1 + +Changeset: + `e91b2c85aacd <https://hg.mozilla.org/mozilla-central/rev/e91b2c85aacd>`_ diff --git a/devtools/docs/user/debugger-api/debugger.memory/index.rst b/devtools/docs/user/debugger-api/debugger.memory/index.rst new file mode 100644 index 0000000000..17f659bba8 --- /dev/null +++ b/devtools/docs/user/debugger-api/debugger.memory/index.rst @@ -0,0 +1,240 @@ +=============== +Debugger.Memory +=============== + +The :doc:`Debugger API <../index>` can help tools observe the debuggee’s memory use in various ways: + + +- It can mark each new object with the JavaScript call stack at which it was allocated. + +- It can log all object allocations, yielding a stream of JavaScript call stacks at which allocations have occurred. + +- It can compute a *census* of items belonging to the debuggee, categorizing items in various ways, and yielding item counts. + + +If *dbg* is a :doc:`Debugger <../debugger/index>` instance, then the methods and accessor properties of ``dbg.memory`` control how *dbg* observes its debuggees’ memory use. The ``dbg.memory`` object is an instance of ``Debugger.Memory``; its inherited accessors and methods are described below. + + +Allocation Site Tracking +************************ + +The JavaScript engine marks each new object with the call stack at which it was allocated, if: + + +- the object is allocated in the scope of a global object that is a debuggee of some :doc:`Debugger <../debugger/index>` instance *dbg*; and + +- :ref:`dbg.memory.trackingAllocationSites <debugger-api-debugger-memory-tracking-allocation-sites>` is set to ``true``. + +- A `Bernoulli trial <https://en.wikipedia.org/wiki/Bernoulli_trial>`_ succeeds, with probability equal to the maximum of :ref:`d.memory.allocationSamplingProbability <debugger-api-debugger-memory-alloc-sampling-probability>` of all ``Debugger`` instances ``d`` that are observing the global that this object is allocated within the scope of. + + +Given a :doc:`Debugger.Object <../debugger.object/index>` instance *dobj* referring to some object, :ref:`dobj.allocationSite <debugger-api-debugger-object-allocation-site>` returns a saved call stack indicating where *dobj*’s referent was allocated. + + +Allocation Logging +****************** + +If *dbg* is a :doc:`Debugger <../debugger/index>` instance, and :ref:`dbg.memory.trackingAllocationSites <debugger-api-debugger-memory-tracking-allocation-sites>` is set to ``true``, then the JavaScript engine logs each object allocated by *dbg*’s debuggee code. You can retrieve the current log by calling *dbg.memory.drainAllocationsLog*. You can control the limit on the log’s size by setting :ref:`dbg.memory.maxAllocationsLogLength <debugger-api-debugger-memory-max-alloc-log>`. + + +Censuses +******** + +A *census* is a complete traversal of the graph of all reachable memory items belonging to a particular ``Debugger``‘s debuggees. It produces a count of those items, broken down by various criteria. If *dbg* is a :doc:`Debugger <../debugger/index>` instance, you can call *dbg.memory.takeCensus* to conduct a census of its debuggees’ possessions. + + +Accessor Properties of the ``Debugger.Memory.prototype`` Object +*************************************************************** + +If *dbg* is a :doc:`Debugger <../debugger/index>` instance, then ``dbg.memory`` is a ``Debugger.Memory`` instance, which inherits the following accessor properties from its prototype: + + +.. _debugger-api-debugger-memory-tracking-allocation-sites: + +``trackingAllocationSites`` + + A boolean value indicating whether this ``Debugger.Memory`` instance is capturing the JavaScript execution stack when each Object is allocated. This accessor property has both a getter and setter: assigning to it enables or disables the allocation site tracking. Reading the accessor produces ``true`` if the Debugger is capturing stacks for Object allocations, and ``false`` otherwise. Allocation site tracking is initially disabled in a new Debugger. + + Assignment is fallible: if the Debugger cannot track allocation sites, it throws an ``Error`` instance. + + You can retrieve the allocation site for a given object with the :ref:`Debugger.Object.prototype.allocationSite <debugger-api-debugger-object-allocation-site>` accessor property. + + +.. _debugger-api-debugger-memory-alloc-sampling-probability: + +``allocationSamplingProbability`` + + A number between 0 and 1 that indicates the probability with which each new allocation should be entered into the allocations log. 0 is equivalent to “never”, 1 is “always”, and .05 would be “one out of twenty”. + + The default is 1, or logging every allocation. + + Note that in the presence of multiple ``Debugger`` instances observing the same allocations within a global’s scope, the maximum ``allocationSamplingProbability`` of all the ``Debugger`` is used. + + +.. _debugger-api-debugger-memory-max-alloc-log: + +``maxAllocationsLogLength`` + + The maximum number of allocation sites to accumulate in the allocations log at a time. This accessor can be both fetched and stored to. Its default value is ``5000``. + + +.. _debugger-api-debugger-memory-alloc-log-overflowed: + +``allocationsLogOverflowed`` + + Returns ``true`` if there have been more than [``maxAllocationsLogLength``][#max-alloc-log] allocations since the last time [``drainAllocationsLog``][#drain-alloc-log] was called and some data has been lost. Returns ``false`` otherwise. + + +Debugger.Memory Handler Functions +********************************* + +Similar to :doc:`Debugger's handler functions <../index>`, ``Debugger.Memory`` inherits accessor properties that store handler functions for SpiderMonkey to call when given events occur in debuggee code. + +Unlike ``Debugger``‘s hooks, ``Debugger.Memory``’s handlers’ return values are not significant, and are ignored. The handler functions receive the ``Debugger.Memory``’s owning ``Debugger`` instance as their ``this`` value. The owning ``Debugger``’s ``uncaughtExceptionHandler`` is still fired for errors thrown in ``Debugger.Memory`` hooks. + +On a new ``Debugger.Memory`` instance, each of these properties is initially ``undefined``. Any value assigned to a debugging handler must be either a function or ``undefined``; otherwise a ``TypeError`` is thrown. + +Handler functions run in the same thread in which the event occurred. They run in the compartment to which they belong, not in a debuggee compartment. + + +``onGarbageCollection(statistics)`` + + A garbage collection cycle spanning one or more debuggees has just been completed. + + The *statistics* parameter is an object containing information about the GC cycle. It has the following properties: + + +``collections`` + + The ``collections`` property’s value is an array. Because SpiderMonkey’s collector is incremental, a full collection cycle may consist of multiple discrete collection slices with the JS mutator running interleaved. For each collection slice that occurred, there is an entry in the ``collections`` array with the following form: + + .. code-block:: javascript + + { + "startTimestamp": timestamp, + "endTimestamp": timestamp, + } + + Here the *timestamp* values are timestamps of the GC slice’s start and end events. + +``reason`` + + A very short string describing the reason why the collection was triggered. Known values include the following: + + - “API” + - “EAGER_ALLOC_TRIGGER” + - “DESTROY_RUNTIME” + - “LAST_DITCH” + - “TOO_MUCH_MALLOC” + - “ALLOC_TRIGGER” + - “DEBUG_GC” + - “COMPARTMENT_REVIVED” + - “RESET” + - “OUT_OF_NURSERY” + - “EVICT_NURSERY” + - “FULL_STORE_BUFFER” + - “SHARED_MEMORY_LIMIT” + - “PERIODIC_FULL_GC” + - “INCREMENTAL_TOO_SLOW” + - “DOM_WINDOW_UTILS” + - “COMPONENT_UTILS” + - “MEM_PRESSURE” + - “CC_WAITING” + - “CC_FORCED” + - “LOAD_END” + - “PAGE_HIDE” + - “NSJSCONTEXT_DESTROY” + - “SET_NEW_DOCUMENT” + - “SET_DOC_SHELL” + - “DOM_UTILS” + - “DOM_IPC” + - “DOM_WORKER” + - “INTER_SLICE_GC” + - “REFRESH_FRAME” + - “FULL_GC_TIMER” + - “SHUTDOWN_CC” + - “USER_INACTIVE” + + +``nonincrementalReason`` + + If SpiderMonkey’s collector determined it could not incrementally collect garbage, and had to do a full GC all at once, this is a short string describing the reason it determined the full GC was necessary. Otherwise, ``null`` is returned. Known values include the following: + + - “GC mode” + - “malloc bytes trigger” + - “allocation trigger” + - “requested” + + +``gcCycleNumber`` + + The GC cycle’s “number”. Does not correspond to the number of GC cycles that have run, but is guaranteed to be monotonically increasing. + + + +Function Properties of the ``Debugger.Memory.prototype`` Object +*************************************************************** + +Memory Use Analysis Exposes Implementation Details + +Memory analysis may yield surprising results, because browser implementation details that are transparent to content JavaScript often have visible effects on memory consumption. Web developers need to know their pages’ actual memory consumption on real browsers, so it is correct for the tool to expose these behaviors, as long as it is done in a way that helps developers make decisions about their own code. + +This section covers some areas where Firefox’s actual behavior deviates from what one might expect from the specified behavior of the web platform. + +Objects +------- + +SpiderMonkey objects usually use less memory than the naïve “table of properties with attributes” model would suggest. For example, it is typical for many objects to have identical sets of properties, with only the properties’ values varying from one object to the next. To take advantage of this regularity, SpiderMonkey objects with identical sets of properties may share their property metadata; only property values are stored directly in the object. + +Array objects may also be optimized, if the set of live indices is dense. + + +Strings +------- + +SpiderMonkey has three representations of strings: + + +- Normal: the string’s text is counted in its size. + +- Substring: the string is a substring of some other string, and points to that string for its storage. This representation may result in a small string retaining a very large string. However, the memory consumed by the string itself is a small constant independent of its size, since it is a reference to the larger string, a start position, and a length. + +- Concatenations: When asked to concatenate two strings, SpiderMonkey may elect to delay copying the strings’ data, and represent the result as a pointer to the two original strings. Again, such a string retains other strings, but the memory consumed by the string itself is a small constant independent of its size, since it is a pair of pointers. + + +SpiderMonkey converts strings from the more complex representations to the simpler ones when it pleases. Such conversions usually increase memory consumption. + +SpiderMonkey shares some strings amongst all web pages and browser JS. These shared strings, called *atoms*, are not included in censuses’ string counts. + + +Scripts +------- + +SpiderMonkey has a complex, hybrid representation of JavaScript code. There are four representations kept in memory: + + +- *Source code*. SpiderMonkey retains a copy of most JavaScript source code. + +- *Compressed source code*. SpiderMonkey compresses JavaScript source code, and de-compresses it on demand. Heuristics determine how long to retain the uncompressed code. + +- *Bytecode*. This is SpiderMonkey’s parsed representation of JavaScript. Bytecode can be interpreted directly, or used as input to a just-in-time compiler. Source is parsed into bytecode on demand; functions that are never called are never parsed. + +- *Machine code*. SpiderMonkey includes several just-in-time compilers, each of which translates JavaScript source or bytecode to machine code. Heuristics determine which code to compile, and which compiler to use. Machine code may be dropped in response to memory pressure, and regenerated as needed. + + +Furthermore, SpiderMonkey tracks which types of values have appeared in variables and object properties. This type information can be large. + +In a census, all the various forms of JavaScript code are placed in the ``"script"`` category. Type information is accounted to the ``"types"`` category. + + +Source Metadata +--------------- + +Generated from file: + js/src/doc/Debugger/Debugger.Memory.md + +Watermark: + sha256:2c1529d6932efec8c624a6f1f366b09cb7fce625a6468657fab81788240bc7ae + +Changeset: + `e91b2c85aacd <https://hg.mozilla.org/mozilla-central/rev/e91b2c85aacd>`_ diff --git a/devtools/docs/user/debugger-api/debugger.object/index.rst b/devtools/docs/user/debugger-api/debugger.object/index.rst new file mode 100644 index 0000000000..e989195b25 --- /dev/null +++ b/devtools/docs/user/debugger-api/debugger.object/index.rst @@ -0,0 +1,310 @@ +=============== +Debugger.Object +=============== + +A ``Debugger.Object`` instance represents an object in the debuggee, providing reflection-oriented methods to inspect and modify its referent. The referent’s properties do not appear directly as properties of the ``Debugger.Object`` instance; the debugger can access them only through methods like ``Debugger.Object.prototype.getOwnPropertyDescriptor`` and ``Debugger.Object.prototype.defineProperty``, ensuring that the debugger will not inadvertently invoke the referent’s getters and setters. + +SpiderMonkey creates exactly one ``Debugger.Object`` instance for each debuggee object it presents to a given :doc:`Debugger <../debugger/index>` instance: if the debugger encounters the same object through two different routes (perhaps two functions are called on the same object), SpiderMonkey presents the same ``Debugger.Object`` instance to the debugger each time. This means that the debugger can use the ``==`` operator to recognize when two ``Debugger.Object`` instances refer to the same debuggee object, and place its own properties on a ``Debugger.Object`` instance to store metadata about particular debuggee objects. + +JavaScript code in different compartments can have different views of the same object. For example, in Firefox, code in privileged compartments sees content DOM element objects without redefinitions or extensions made to that object’s properties by content code. (In Firefox terminology, privileged code sees the element through an “xray wrapper”.) To ensure that debugger code sees each object just as the debuggee would, each ``Debugger.Object`` instance presents its referent as it would be seen from a particular compartment. This “viewing compartment” is chosen to match the way the debugger came across the referent. As a consequence, a single :doc:`Debugger <../debugger/index>` instance may actually have several ``Debugger.Object`` instances: one for each compartment from which the referent is viewed. + +If more than one :doc:`Debugger <../debugger/index>` instance is debugging the same code, each :doc:`Debugger <../debugger/index>` gets a separate ``Debugger.Object`` instance for a given object. This allows the code using each :doc:`Debugger <../debugger/index>` instance to place whatever properties it likes on its own ``Debugger.Object`` instances, without worrying about interfering with other debuggers. + +While most ``Debugger.Object`` instances are created by SpiderMonkey in the process of exposing debuggee’s behavior and state to the debugger, the debugger can use ``Debugger.Object.prototype.makeDebuggeeValue`` to create ``Debugger.Object`` instances for given debuggee objects, or use ``Debugger.Object.prototype.copy`` and ``Debugger.Object.prototype.create`` to create new objects in debuggee compartments, allocated as if by particular debuggee globals. + +``Debugger.Object`` instances protect their referents from the garbage collector; as long as the ``Debugger.Object`` instance is live, the referent remains live. This means that garbage collection has no visible effect on ``Debugger.Object`` instances. + + +Accessor Properties of the Debugger.Object prototype +**************************************************** + +A ``Debugger.Object`` instance inherits the following accessor properties from its prototype: + + +``proto`` + The referent’s prototype (as a new ``Debugger.Object`` instance), or ``null`` if it has no prototype. This accessor may throw if the referent is a scripted proxy or some other sort of exotic object (an opaque wrapper, for example). + +``class`` + A string naming the ECMAScript ``[[Class]]`` of the referent. + +``callable`` + ``true`` if the referent is a callable object (such as a function or a function proxy); false otherwise. + +``name`` + The name of the referent, if it is a named function. If the referent is an anonymous function, or not a function at all, this is ``undefined``. + + This accessor returns whatever name appeared after the ``function`` keyword in the source code, regardless of whether the function is the result of instantiating a function declaration (which binds the function to its name in the enclosing scope) or evaluating a function expression (which binds the function to its name only within the function’s body). + +``displayName`` + + The referent’s display name, if the referent is a function with a display name. If the referent is not a function, or if it has no display name, this is ``undefined``. + + If a function has a given name, its display name is the same as its given name. In this case, the ``displayName`` and ``name`` properties are equal. + + If a function has no name, SpiderMonkey attempts to infer an appropriate name for it given its context. For example: + + .. code-block:: javascript + + function f() {} // display name: f (the given name) + var g = function () {}; // display name: g + o.p = function () {}; // display name: o.p + var q = { + r: function () {} // display name: q.r + }; + + Note that the display name may not be a proper JavaScript identifier, or even a proper expression: we attempt to find helpful names even when the function is not immediately assigned as the value of some variable or property. Thus, we use ``a/b`` to refer to the *b* defined within *a*, and ``a<`` to refer to a function that occurs somewhere within an expression that is assigned to *a*. For example: + + .. code-block:: javascript + + function h() { + var i = function() {}; // display name: h/i + f(function () {}); // display name: h/< + } + var s = f(function () {}); // display name: s<``</pre> + +``parameterNames`` + If the referent is a debuggee function, the names of the its parameters, as an array of strings. If the referent is not a debuggee function, or not a function at all, this is ``undefined``. + + If the referent is a host function for which parameter names are not available, return an array with one element per parameter, each of which is ``undefined``. + + If the referent is a function proxy, return an empty array. + + If the referent uses destructuring parameters, then the array’s elements reflect the structure of the parameters. For example, if the referent is a function declared in this way: + + .. code-block:: javascript + + function f(a, [b, c], {d, e:f}) { ... } + + then this ``Debugger.Object`` instance’s ``parameterNames`` property would have the value: + + .. code-block:: javascript + + ["a", ["b", "c"], {d:"d", e:"f"}] + +``script`` + If the referent is a function that is debuggee code, this is that function’s script, as a :doc:`Debugger.Script <../debugger.script/index>` instance. If the referent is a function proxy or not debuggee code, this is ``undefined``. + +``environment`` + If the referent is a function that is debuggee code, a :doc:`Debugger.Environment <../debugger.environment/index>` instance representing the lexical environment enclosing the function when it was created. If the referent is a function proxy or not debuggee code, this is ``undefined``. + +``errorMessageName`` + If the referent is an error created with an engine internal message template this is a string which is the name of the template; ``undefined`` otherwise. + +``errorLineNumber`` + If the referent is an Error object, this is the line number at which the referent was created; ``undefined`` otherwise. + +``errorColumnNumber`` + If the referent is an Error object, this is the column number at which the referent was created; ``undefined`` otherwise. + +``isBoundFunction`` + If the referent is a debuggee function, returns ``true`` if the referent is a bound function; ``false`` otherwise. If the referent is not a debuggee function, or not a function at all, returns ``undefined`` instead. + +``isArrowFunction`` + If the referent is a debuggee function, returns ``true`` if the referent is an arrow function; ``false`` otherwise. If the referent is not a debuggee function, or not a function at all, returns ``undefined`` instead. + +``isGeneratorFunction`` + If the referent is a debuggee function, returns ``true`` if the referent was created with a ``function*`` expression or statement, or false if it is some other sort of function. If the referent is not a debuggee function, or not a function at all, this is ``undefined``. (This is always equal to ``obj.script.isGeneratorFunction``, assuming ``obj.script`` is a ``Debugger.Script``.) + +``isAsyncFunction`` + If the referent is a debuggee function, returns ``true`` if the referent is an async function, defined with an ``async function`` expression or statement, or false if it is some other sort of function. If the referent is not a debuggee function, or not a function at all, this is ``undefined``. (This is always equal to ``obj.script.isAsyncFunction``, assuming ``obj.script`` is a ``Debugger.Script``.) + +``isPromise`` + ``true`` if the referent is a Promise; ``false`` otherwise. + +``boundTargetFunction`` + If the referent is a bound debuggee function, this is its target function— the function that was bound to a particular ``this`` object. If the referent is either not a bound function, not a debuggee function, or not a function at all, this is ``undefined``. + +``boundThis`` + If the referent is a bound debuggee function, this is the ``this`` value it was bound to. If the referent is either not a bound function, not a debuggee function, or not a function at all, this is ``undefined``. + +``boundArguments`` + If the referent is a bound debuggee function, this is an array (in the Debugger object’s compartment) that contains the debuggee values of the ``arguments`` object it was bound to. If the referent is either not a bound function, not a debuggee function, or not a function at all, this is ``undefined``. + +``isProxy`` + If the referent is a (scripted) proxy, either revoked or not, return ``true``. If the referent is not a (scripted) proxy, return ``false``. + +``proxyTarget`` + If the referent is a non-revoked (scripted) proxy, return a ``Debugger.Object`` instance referring to the ECMAScript ``[[ProxyTarget]]`` of the referent. If the referent is a revoked (scripted) proxy, return ``null``. If the referent is not a (scripted) proxy, return ``undefined``. + +``proxyHandler`` + If the referent is a non-revoked (scripted) proxy, return a ``Debugger.Object`` instance referring to the ECMAScript ``[[ProxyHandler]]`` of the referent. If the referent is a revoked (scripted) proxy, return ``null``. If the referent is not a (scripted) proxy, return ``undefined``. + +``promiseState`` + If the referent is a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, return a string indicating whether the `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ is pending, or has been fulfilled or rejected. This string takes one of the following values: + + - ``"pending"``, if the `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ is pending. + - ``"fulfilled"``, if the `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ has been fulfilled. + - ``"rejected"``, if the `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ has been rejected. + + + If the referent is not a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, throw a ``TypeError``. + +``promiseValue`` + Return a debuggee value representing the value the `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ has been fulfilled with. + + If the referent is not a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, or the `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ has not been fulfilled, throw a ``TypeError``. + +``promiseReason`` + Return a debuggee value representing the value the `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ has been rejected with. + + If the referent is not a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, or the `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ has not been rejected, throw a ``TypeError``. + +``promiseAllocationSite`` + If the referent is a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, this is the JavaScript execution stack captured at the time of the promise’s allocation. This can return null if the promise was not created from script. If the referent is not a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, throw a ``TypeError`` exception. + +``promiseResolutionSite`` + If the referent is a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, this is the JavaScript execution stack captured at the time of the promise’s resolution. This can return null if the promise was not resolved by calling its ``resolve`` or ``reject`` resolving functions from script. If the referent is not a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, throw a ``TypeError`` exception. + +``promiseID`` + If the referent is a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, this is a process-unique identifier for the `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_. With e10s, the same id can potentially be assigned to multiple `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ instances, if those instances were created in different processes. If the referent is not a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, throw a ``TypeError`` exception. + +``promiseDependentPromises`` + If the referent is a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, this is an ``Array`` of ``Debugger.Objects`` referring to the promises directly depending on the referent `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_. These are: + + + 1. Return values of ``then()`` calls on the promise. + 2. Return values of ``Promise.all()`` if the referent `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ was passed in as one of the arguments. + 3. Return values of ``Promise.race()`` if the referent `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ was passed in as one of the arguments. + + + Once a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ is settled, it will generally notify its dependent promises and forget about them, so this is most useful on *pending* promises. + + Note that the ``Array`` only contains the promises that directly depend on the referent `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_. It does not contain promises that depend on promises that depend on the referent `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_. + + If the referent is not a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, throw a ``TypeError`` exception. + + +``promiseLifetime`` + If the referent is a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, this is the number of milliseconds elapsed since the `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ was created. If the referent is not a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, throw a ``TypeError`` exception. + +``promiseTimeToResolution`` + If the referent is a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, this is the number of milliseconds elapsed between when the `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_ was created and when it was resolved. If the referent hasn’t been resolved or is not a `Promise <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise>`_, throw a ``TypeError`` exception. + +``global`` + A ``Debugger.Object`` instance referring to the global object in whose scope the referent was allocated. This does not unwrap cross-compartment wrappers: if the referent is a wrapper, the result refers to the wrapper’s global, not the wrapped object’s global. The result refers to the global directly, not via a wrapper. + +.. _debugger-api-debugger-object-allocation-site: + +``allocationSite`` + If :ref:`object allocation site tracking <debugger-api-debugger-memory-tracking-allocation-sites>` was enabled when this ``Debugger.Object``’s referent was allocated, return the JavaScript execution stack captured at the time of the allocation. Otherwise, return ``null``. + + +Function Properties of the Debugger.Object prototype +**************************************************** + +The functions described below may only be called with a ``this`` value referring to a ``Debugger.Object`` instance; they may not be used as methods of other kinds of objects. The descriptions use “referent” to mean “the referent of this ``Debugger.Object`` instance”. + +Unless otherwise specified, these methods are not :ref:`invocation functions <debugger-api-debugger-frame-invf>`; if a call would cause debuggee code to run (say, because it gets or sets an accessor property whose handler is debuggee code, or because the referent is a proxy whose traps are debuggee code), the call throws a ``Debugger.DebuggeeWouldRun`` exception. + +These methods may throw if the referent is not a native object. Even simple accessors like ``isExtensible`` may throw if the referent is a proxy or some sort of exotic object like an opaque wrapper. + + +``getProperty(key, [receiver])`` + Return a completion value with "return" being the value of the referent's property named *key*, or ``undefined`` if it has no such property. *key* must be a string or symbol; *receiver* must be a debuggee value. If the property is a getter, it will be evaluated with *receiver* as the receiver, defaulting to the ``Debugger.Object`` if omitted. + +``setProperty(key, value, [receiver])`` + Store *value* as the value of the referent’s property named *key*, creating the property if it does not exist. *key* must be a string or symbol; *value* and *receiver* must be debuggee values. If the property is a setter, it will be evaluated with *receiver* as the receiver, defaulting to the ``Debugger.Object`` if omitted. + +``getOwnPropertyDescriptor(name)`` + Return a property descriptor for the property named *name* of the referent. If the referent has no such property, return ``undefined``. (This function behaves like the standard ``Object.getOwnPropertyDescriptor`` function, except that the object being inspected is implicit; the property descriptor returned is allocated as if by code scoped to the debugger’s global object (and is thus in the debugger’s compartment); and its ``value``, ``get``, and ``set`` properties, if present, are debuggee values.) + +``getOwnPropertyNames()`` + Return an array of strings naming all the referent’s own properties, as if ``Object.getOwnPropertyNames(referent)`` had been called in the debuggee, and the result copied in the scope of the debugger’s global object. + +``getOwnPropertySymbols()`` + Return an array of strings naming all the referent’s own symbols, as if ``Object.getOwnPropertySymbols(referent)`` had been called in the debuggee, and the result copied in the scope of the debugger’s global object. + +``defineProperty(name, attributes)`` + Define a property on the referent named *name*, as described by the property descriptor *descriptor*. Any ``value``, ``get``, and ``set`` properties of *attributes* must be debuggee values. (This function behaves like ``Object.defineProperty``, except that the target object is implicit, and in a different compartment from the function and descriptor.) + +``defineProperties(properties)`` + Add the properties given by *properties* to the referent. (This function behaves like ``Object.defineProperties``, except that the target object is implicit, and in a different compartment from the *properties* argument.) + +``deleteProperty(name)`` + Remove the referent’s property named *name*. Return true if the property was successfully removed, or if the referent has no such property. Return false if the property is non-configurable. + +``seal()`` + Prevent properties from being added to or deleted from the referent. Return this ``Debugger.Object`` instance. (This function behaves like the standard ``Object.seal`` function, except that the object to be sealed is implicit and in a different compartment from the caller.) + +``freeze()`` + Prevent properties from being added to or deleted from the referent, and mark each property as non-writable. Return this ``Debugger.Object`` instance. (This function behaves like the standard ``Object.freeze`` function, except that the object to be sealed is implicit and in a different compartment from the caller.) + +``preventExtensions()`` + Prevent properties from being added to the referent. (This function behaves like the standard ``Object.preventExtensions`` function, except that the object to operate on is implicit and in a different compartment from the caller.) + +``isSealed()`` + Return true if the referent is sealed—that is, if it is not extensible, and all its properties have been marked as non-configurable. (This function behaves like the standard ``Object.isSealed`` function, except that the object inspected is implicit and in a different compartment from the caller.) + +``isFrozen()`` + Return true if the referent is frozen—that is, if it is not extensible, and all its properties have been marked as non-configurable and read-only. (This function behaves like the standard ``Object.isFrozen`` function, except that the object inspected is implicit and in a different compartment from the caller.) + +``isExtensible()`` + Return true if the referent is extensible—that is, if it can have new properties defined on it. (This function behaves like the standard ``Object.isExtensible`` function, except that the object inspected is implicit and in a different compartment from the caller.) + +``copy(value)`` + Apply the HTML5 “structured cloning” algorithm to create a copy of *value* in the referent’s global object (and thus in the referent’s compartment), and return a ``Debugger.Object`` instance referring to the copy. + + Note that this returns primitive values unchanged. This means you can use ``Debugger.Object.prototype.copy`` as a generic “debugger value to debuggee value” conversion function—within the limitations of the “structured cloning” algorithm. + +``create(prototype, [properties])`` + Create a new object in the referent’s global (and thus in the referent’s compartment), and return a ``Debugger.Object`` referring to it. The new object’s prototype is *prototype*, which must be an ``Debugger.Object`` instance. The new object’s properties are as given by *properties*, as if *properties* were passed to ``Debugger.Object.prototype.defineProperties``, with the new ``Debugger.Object`` instance as the ``this`` value. + +``makeDebuggeeValue(value)`` + Return the debuggee value that represents *value* in the debuggee. If *value* is a primitive, we return it unchanged; if *value* is an object, we return the ``Debugger.Object`` instance representing that object, wrapped appropriately for use in this ``Debugger.Object``’s referent’s compartment. + + Note that, if *value* is an object, it need not be one allocated in a debuggee global, nor even a debuggee compartment; it can be any object the debugger wishes to use as a debuggee value. + + As described above, each ``Debugger.Object`` instance presents its referent as viewed from a particular compartment. Given a ``Debugger.Object`` instance *d* and an object *o*, the call ``d.makeDebuggeeValue(o)`` returns a ``Debugger.Object`` instance that presents *o* as it would be seen by code in *d*’s compartment. + +``call(this, argument, …)`` + If the referent is callable, call it with the given *this* value and *argument* values, and return a completion value describing how the call completed. *This* should be a debuggee value, or ``{ asConstructor: true }`` to invoke the referent as a constructor, in which case SpiderMonkey provides an appropriate ``this`` value itself. Each *argument* must be a debuggee value. All extant handler methods, breakpoints, and so on remain active during the call. If the referent is not callable, throw a ``TypeError``. This function follows the invocation function conventions. + +``apply(this, arguments)`` + If the referent is callable, call it with the given *this* value and the argument values in *arguments*, and return a completion value describing how the call completed. *This* should be a debuggee value, or ``{ asConstructor: true }`` to invoke *function* as a constructor, in which case SpiderMonkey provides an appropriate ``this`` value itself. *Arguments* must either be an array (in the debugger) of debuggee values, or ``null`` or ``undefined``, which are treated as an empty array. All extant handler methods, breakpoints, and so on remain active during the call. If the referent is not callable, throw a ``TypeError``. This function follows the :ref:`invocation function conventions <debugger-api-debugger-frame-invf>`. + +``executeInGlobal(code, [options])`` + If the referent is a global object, evaluate *code* in that global environment, and return a completion value describing how it completed. *Code* is a string. All extant handler methods, breakpoints, and so on remain active during the call. This function follows the :ref:`invocation function conventions <debugger-api-debugger-frame-invf>`. If the referent is not a global object, throw a ``TypeError`` exception. + + *Code* is interpreted as strict mode code when it contains a Use Strict Directive. + + This evaluation is semantically equivalent to executing statements at the global level, not an indirect eval. Regardless of *code* being strict mode code, variable declarations in *code* affect the referent global object. + + The *options* argument is as for :ref:`Debugger.Frame.eval <debugger-api-debugger-frame-eval>`. + +``executeInGlobalWithBindings(code, bindings, [options])`` + + Like ``executeInGlobal``, but evaluate *code* using the referent as the variable object, but with a lexical environment extended with bindings from the object *bindings*. For each own enumerable property of *bindings* named *name* whose value is value, include a variable in the lexical environment in which *code* is evaluated named *name*, whose value is *value*. Each *value* must be a debuggee value. (This is not like a ``with`` statement: *code* may access, assign to, and delete the introduced bindings without having any effect on the *bindings* object.) + + This method allows debugger code to introduce temporary bindings that are visible to the given debuggee code and which refer to debugger-held debuggee values, and do so without mutating any existing debuggee environment. + + Note that, like ``executeInGlobal``, any declarations it contains affect the referent global object, even as *code* is evaluated in an environment extended according to *bindings*. (In the terms used by the ECMAScript specification, the ``VariableEnvironment`` of the execution context for *code* is the referent, and the *bindings* appear in a new declarative environment, which is the eval code’s ``LexicalEnvironment``.) + + The *options* argument is as for :ref:`Debugger.Frame.eval <debugger-api-debugger-frame-eval>`. + +``asEnvironment()`` + If the referent is a global object, return the :doc:`Debugger.Environment <../debugger.environment/index>` instance representing the referent’s global lexical scope. The global lexical scope’s enclosing scope is the global object. If the referent is not a global object, throw a ``TypeError``. + +``unwrap()`` + If the referent is a wrapper that this ``Debugger.Object``’s compartment is permitted to unwrap, return a ``Debugger.Object`` instance referring to the wrapped object. If we are not permitted to unwrap the referent, return ``null``. If the referent is not a wrapper, return this ``Debugger.Object`` instance unchanged. + +``unsafeDereference()`` + Return the referent of this ``Debugger.Object`` instance. + + If the referent is an inner object (say, an HTML5 ``Window`` object), return the corresponding outer object (say, the HTML5 ``WindowProxy`` object). This makes ``unsafeDereference`` more useful in producing values appropriate for direct use by debuggee code, without using :ref:`invocation functions <debugger-api-debugger-frame-invf>`. + + This method pierces the membrane of ``Debugger.Object`` instances meant to protect debugger code from debuggee code, and allows debugger code to access debuggee objects through the standard cross-compartment wrappers, rather than via ``Debugger.Object``’s reflection-oriented interfaces. This method makes it easier to gradually adapt large code bases to this Debugger API: adapted portions of the code can use ``Debugger.Object`` instances, but use this method to pass direct object references to code that has not yet been updated. + +``forceLexicalInitializationByName(binding)`` + If *binding* is in an uninitialized state initialize it to undefined and return true, otherwise do nothing and return false. + + +Source Metadata +*************** + +Generated from file: + js/src/doc/Debugger/Debugger.Object.md + +Watermark: + sha256:7ae16a834e0883a95b4e0d227193293f6b6e4e4dd812c2570372a39c4c04897b +Changeset: + `5572465c08a9+ <https://hg.mozilla.org/mozilla-central/rev/5572465c08a9>`_ diff --git a/devtools/docs/user/debugger-api/debugger.script/index.rst b/devtools/docs/user/debugger-api/debugger.script/index.rst new file mode 100644 index 0000000000..7df26208af --- /dev/null +++ b/devtools/docs/user/debugger-api/debugger.script/index.rst @@ -0,0 +1,272 @@ +=============== +Debugger.Script +=============== + +A ``Debugger.Script`` instance may refer to a sequence of bytecode in the debuggee or to a block of WebAssembly code. For the former, it is the :doc:`Debugger <../debugger/index>` API’s presentation of a JSAPI ``JSScript`` object. The two cases are distinguished by their ``format`` property being ``"js"`` or ``"wasm"``. + + +Debugger.Script for JSScripts +***************************** + +For ``Debugger.Script`` instances referring to a ``JSScript``, they are distinguished by their ``format`` property being ``"js"``. + +Each of the following is represented by a single ``JSScript`` object: + + +- The body of a function—that is, all the code in the function that is not contained within some nested function. + +- The code passed to a single call to ``eval``, excluding the bodies of any functions that code defines. + +- The contents of a ``<script>`` element. + +- A DOM event handler, whether embedded in HTML or attached to the element by other JavaScript code. + +- Code appearing in a ``javascript:`` URL. + + +The :doc:`Debugger <../debugger/index>` interface constructs ``Debugger.Script`` objects as scripts of debuggee code are uncovered by the debugger: via the ``onNewScript`` handler method; via :doc:`Debugger.Frame <../debugger.frame/index>`’s ``script`` properties; via the ``functionScript`` method of :doc:`Debugger.Object <../debugger.object/index>` instances; and so on. For a given :doc:`Debugger <../debugger/index>` instance, SpiderMonkey constructs exactly one ``Debugger.Script`` instance for each underlying script object; debugger code can add its own properties to a script object and expect to find them later, use ``==`` to decide whether two expressions refer to the same script, and so on. + +(If more than one :doc:`Debugger <../debugger/index>` instance is debugging the same code, each :doc:`Debugger <../debugger/index>` gets a separate ``Debugger.Script`` instance for a given script. This allows the code using each :doc:`Debugger <../debugger/index>` instance to place whatever properties it likes on its ``Debugger.Script`` instances, without worrying about interfering with other debuggers.) + +A ``Debugger.Script`` instance is a strong reference to a JSScript object; it protects the script it refers to from being garbage collected. + +Note that SpiderMonkey may use the same ``Debugger.Script`` instances for equivalent functions or evaluated code—that is, scripts representing the same source code, at the same position in the same source file, evaluated in the same lexical environment. + + +Debugger.Script for WebAssembly +******************************* + +For ``Debugger.Script`` instances referring to a block of WebAssembly code, they are distinguished by their ``format`` property being ``"wasm"``. + +Currently only entire modules evaluated via ``new WebAssembly.Module`` are represented. + +``Debugger.Script`` objects for WebAssembly are uncovered via ``onNewScript`` when a new WebAssembly module is instantiated and via the ``findScripts`` method on :doc:`Debugger <../debugger/index>` instances. SpiderMonkey constructs exactly one ``Debugger.Script`` for each underlying WebAssembly module per :doc:`Debugger <../debugger/index>` instance. + +A ``Debugger.Script`` instance is a strong reference to the underlying WebAssembly module; it protects the module it refers to from being garbage collected. + +Please note at the time of this writing, support for WebAssembly is very preliminary. Many properties and methods below throw. + + +Convention +********** + +For descriptions of properties and methods below, if the behavior of the property or method differs between the instance referring to a ``JSScript`` or to a block of WebAssembly code, the text will be split into two sections, headed by “**if the instance refers to a JSScript**” and “**if the instance refers to WebAssembly code**”, respectively. If the behavior does not differ, no such emphasized headings will appear. + + +Accessor Properties of the Debugger.Script Prototype Object +*********************************************************** + +A ``Debugger.Script`` instance inherits the following accessor properties from its prototype: + + +``isGeneratorFunction`` + True if this instance refers to a ``JSScript`` for a function defined with a ``function*`` expression or statement. False otherwise. + +``isAsyncFunction`` + True if this instance refers to a ``JSScript`` for an async function, defined with an ``async function`` expression or statement. False otherwise. + +``displayName`` + **If the instance refers to a JSScript**, this is the script’s display name, if it has one. If the script has no display name — for example, if it is a top-level ``eval`` script — this is ``undefined``. + + If the script’s function has a given name, its display name is the same as its function’s given name. + + If the script’s function has no name, SpiderMonkey attempts to infer an appropriate name for it given its context. For example: + + .. code-block:: javascript + + function f() {} // display name: f (the given name) + var g = function () {}; // display name: g + o.p = function () {}; // display name: o.p + var q = { + r: function () {} // display name: q.r + }; + + + Note that the display name may not be a proper JavaScript identifier, or even a proper expression: we attempt to find helpful names even when the function is not immediately assigned as the value of some variable or property. Thus, we use ``a/b`` to refer to the *b* defined within *a*, and ``a<`` to refer to a function that occurs somewhere within an expression that is assigned to *a*. For example: + + .. code-block:: javascript + + function h() { + var i = function() {}; // display name: h/i + f(function () {}); // display name: h/< + } + var s = f(function () {}); // display name: s<``</pre> + + **If the instance refers to WebAssembly code**, throw a ``TypeError``. + +``url`` + + **If the instance refers to a JSScript**, the filename or URL from which this script’s code was loaded. For scripts created by ``eval`` or the ``Function`` constructor, this may be a synthesized filename, starting with a valid URL and followed by information tracking how the code was introduced into the system; the entire string is not a valid URL. For ``Function.prototype``’s script, this is ``null``. If this ``Debugger.Script``’s ``source`` property is non-``null``, then this is equal to ``source.url``. + + **If the instance refers to WebAssembly code**, throw a ``TypeError``. + +``startLine`` + **If the instance refers to a JSScript**, the number of the line at which this script’s code starts, within the file or document named by ``url``. + +``lineCount`` + **If the instance refers to a JSScript**, the number of lines this script’s code occupies, within the file or document named by ``url``. + +``source`` + **If the instance refers to a JSScript**, the :doc:`Debugger.Source <../debugger.source/index>` instance representing the source code from which this script was produced. This is ``null`` if the source code was not retained. + + **If the instance refers to WebAssembly code**, the :doc:`Debugger.Source <../debugger.source/index>` instance representing the serialized text format of the WebAssembly code. + +``sourceStart`` + **If the instance refers to a JSScript**, the character within the :doc:`Debugger.Source <../debugger.source/index>` instance given by ``source`` at which this script’s code starts; zero-based. If this is a function’s script, this is the index of the start of the ``function`` token in the source code. + + **If the instance refers to WebAssembly code**, throw a ``TypeError``. + +``sourceLength`` + **If the instance refers to a JSScript**, the length, in characters, of this script’s code within the :doc:`Debugger.Source <../debugger.source/index>` instance given by ``source``. + + **If the instance refers to WebAssembly code**, throw a ``TypeError``. + +``global`` + + **If the instance refers to a JSScript**, a :doc:`Debugger.Object <../debugger.object/index>` instance referring to the global object in whose scope this script runs. The result refers to the global directly, not via a wrapper or a ``WindowProxy`` (“outer window”, in Firefox). + + **If the instance refers to WebAssembly code**, throw a ``TypeError``. + +``format`` + **If the instance refers to a JSScript**, ``"js"``. + + **If the instance refers to WebAssembly code**, ``"wasm"``. + + + +Function Properties of the Debugger.Script Prototype Object +*********************************************************** + +The functions described below may only be called with a ``this`` value referring to a ``Debugger.Script`` instance; they may not be used as methods of other kinds of objects. + + +``getAllOffsets()`` + **If the instance refers to a JSScript**, return an array *L* describing the relationship between bytecode instruction offsets and source code positions in this script. *L* is sparse, and indexed by source line number. If a source line number *line* has no code, then *L* has no *line* property. If there is code for *line*, then ``L[line]`` is an array of offsets of byte code instructions that are entry points to that line. + + For example, suppose we have a script for the following source code: + + .. code-block:: javascript + + a=[] + for (i=1; i < 10; i++) + // It's hip to be square. + a[i] = i*i; + + Calling ``getAllOffsets()`` on that code might yield an array like this: + + .. code-block:: javascript + + [[0], [5, 20], , [10]] + + This array indicates that: + + - the first line’s code starts at offset 0 in the script; + - the ``for`` statement head has two entry points at offsets 5 and 20 (for the initialization, which is performed only once, and the loop test, which is performed at the start of each iteration); + - the third line has no code; + - and the fourth line begins at offset 10. + + **If the instance refers to WebAssembly code**, throw a ``TypeError``. + + +``getAllColumnOffsets()``: + **If the instance refers to a JSScript**, return an array describing the relationship between bytecode instruction offsets and source code positions in this script. Unlike getAllOffsets(), which returns all offsets that are entry points for each line, getAllColumnOffsets() returns all offsets that are entry points for each (line, column) pair. + + The elements of the array are objects, each of which describes a single entry point, and contains the following properties: + + - lineNumber: the line number for which offset is an entry point + - columnNumber: the column number for which offset is an entry point + - offset: the bytecode instruction offset of the entry point + + + For example, suppose we have a script for the following source code: + + .. code-block:: javascript + + a=[] + for (i=1; i < 10; i++) + // It's hip to be square. + a[i] = i*i; + + Calling ``getAllColumnOffsets()`` on that code might yield an array like this: + + .. code-block:: javascript + + [{ lineNumber: 0, columnNumber: 0, offset: 0 }, + { lineNumber: 1, columnNumber: 5, offset: 5 }, + { lineNumber: 1, columnNumber: 10, offset: 20 }, + { lineNumber: 3, columnNumber: 4, offset: 10 }] + + **If the instance refers to WebAssembly code**, throw a ``TypeError``. + +``getLineOffsets(line)`` + **If the instance refers to a JSScript**, return an array of bytecode instruction offsets representing the entry points to source line *line*. If the script contains no executable code at that line, the array returned is empty. + +``getOffsetLocation(offset)`` + **If the instance refers to a JSScript**, return an object describing the source code location responsible for the bytecode at *offset* in this script. The object has the following properties: + + - lineNumber: the line number for which offset is an entry point + - columnNumber: the column number for which offset is an entry point + - isEntryPoint: true if the offset is a column entry point, as would be reported by getAllColumnOffsets(); otherwise false. + + +``getOffsetsCoverage()``: + **If the instance refers to a JSScript**, return ``null`` or an array which contains information about the coverage of all opcodes. The elements of the array are objects, each of which describes a single opcode, and contains the following properties: + + - lineNumber: the line number of the current opcode. + - columnNumber: the column number of the current opcode. + - offset: the bytecode instruction offset of the current opcode. + - count: the number of times the current opcode got executed. + + + If this script has no coverage, or if it is not instrumented, then this function will return ``null``. To ensure that the debuggee is instrumented, the flag ``Debugger.collectCoverageInfo`` should be set to ``true``. + + **If the instance refers to WebAssembly code**, throw a ``TypeError``. + +``getChildScripts()`` + **If the instance refers to a JSScript**, return a new array whose elements are Debugger.Script objects for each function in this script. Only direct children are included; nested children can be reached by walking the tree. + + **If the instance refers to WebAssembly code**, throw a ``TypeError``. + +``setBreakpoint(offset, handler)`` + **If the instance refers to a JSScript**, set a breakpoint at the bytecode instruction at *offset* in this script, reporting hits to the ``hit`` method of *handler*. If *offset* is not a valid offset in this script, throw an error. + + When execution reaches the given instruction, SpiderMonkey calls the ``hit`` method of *handler*, passing a :doc:`Debugger.Frame <../debugger.frame/index>` instance representing the currently executing stack frame. The ``hit`` method’s return value should be a resumption value, determining how execution should continue. + + Any number of breakpoints may be set at a single location; when control reaches that point, SpiderMonkey calls their handlers in an unspecified order. + + Any number of breakpoints may use the same *handler* object. + + Breakpoint handler method calls are cross-compartment, intra-thread calls: the call takes place in the same thread that hit the breakpoint, and in the compartment containing the handler function (typically the debugger’s compartment). + + The new breakpoint belongs to the :doc:`Debugger <../debugger/index>` instance to which this script belongs. Disabling the :doc:`Debugger <../debugger/index>` instance disables this breakpoint; and removing a global from the :doc:`Debugger <../debugger/index>` instance’s set of debuggees clears all the breakpoints belonging to that :doc:`Debugger <../debugger/index>` instance in that global’s scripts. + +``getBreakpoints([offset])`` + **If the instance refers to a JSScript**, return an array containing the handler objects for all the breakpoints set at *offset* in this script. If *offset* is omitted, return the handlers of all breakpoints set anywhere in this script. If *offset* is present, but not a valid offset in this script, throw an error. + + **If the instance refers to WebAssembly code**, throw a ``TypeError``. + +``clearBreakpoint(handler, [offset])`` + **If the instance refers to a JSScript**, remove all breakpoints set in this :doc:`Debugger <../debugger/index>` instance that use *handler* as their handler. If *offset* is given, remove only those breakpoints set at *offset* that use *handler*; if *offset* is not a valid offset in this script, throw an error. + + Note that, if breakpoints using other handler objects are set at the same location(s) as *handler*, they remain in place. + +``clearAllBreakpoints([offset])`` + **If the instance refers to a JSScript**, remove all breakpoints set in this script. If *offset* is present, remove all breakpoints set at that offset in this script; if *offset* is not a valid bytecode offset in this script, throw an error. + +``isInCatchScope([offset])`` + **If the instance refers to a JSScript**, this is ``true`` if this offset falls within the scope of a try block, and ``false`` otherwise. + + **If the instance refers to WebAssembly code**, throw a ``TypeError``. + + +Source Metadata +*************** + +Generated from file: + js/src/doc/Debugger/Debugger.Script.md + +Watermark: + sha256:8816a4e8617be32c4ce7f3ae54970fe9c8a7d248175d215a8990ccff23e6efa9 + +Changeset: + `5572465c08a9+ <https://hg.mozilla.org/mozilla-central/rev/5572465c08a9>`_ diff --git a/devtools/docs/user/debugger-api/debugger.source/index.rst b/devtools/docs/user/debugger-api/debugger.source/index.rst new file mode 100644 index 0000000000..3e4e73c1ee --- /dev/null +++ b/devtools/docs/user/debugger-api/debugger.source/index.rst @@ -0,0 +1,130 @@ +=============== +Debugger.Source +=============== + +A ``Debugger.Source`` instance represents either a piece of JavaScript source code or the serialized text of a block of WebAssembly code. The two cases are distinguished by the latter having its ``introductionType`` property always being ``"wasm"`` and the former having its ``introductionType`` property never being ``"wasm"``. + +Each :doc:`Debugger <../debugger/index>` instance has a separate collection of ``Debugger.Source`` instances representing the source code that has been presented to the system. + +A debugger may place its own properties on ``Debugger.Source`` instances, to store metadata about particular pieces of source code. + + +Debugger.Source for JavaScript +****************************** + +For a ``Debugger.Source`` instance representing a piece of JavaScript source code, its properties provide the source code itself as a string, and describe where it came from. Each :doc:`Debugger.Script <../debugger.script/index>` instance refers to the ``Debugger.Source`` instance holding the source code from which it was produced. + +If a single piece of source code contains both top-level code and function definitions, perhaps with nested functions, then the :doc:`Debugger.Script <../debugger.script/index>` instances for those all refer to the same ``Debugger.Source`` instance. Each script indicates the substring of the overall source to which it corresponds. + +A ``Debugger.Source`` instance may represent only a portion of a larger source document. For example, an HTML document can contain JavaScript in multiple ``<script>`` elements and event handler content attributes. In this case, there may be either a single ``Debugger.Source`` instance for the entire HTML document, with each :doc:`Debugger.Script <../debugger.script/index>` referring to its substring of the document; or there may be a separate ``Debugger.Source`` instance for each ``<script>`` element and attribute. The choice is left up to the implementation. + +If a given piece of source code is presented to the JavaScript implementation more than once, with the same origin metadata, the JavaScript implementation may generate a fresh ``Debugger.Source`` instance to represent each presentation, or it may use a single ``Debugger.Source`` instance to represent them all. + + +Debugger.Source for WebAssembly +******************************* + +For a ``Debugger.Source`` instance representing the serialized text of a block of WebAssembly code, its properties provide the serialized text as a string. + +Currently only entire modules evaluated via ``new WebAssembly.Module`` are represented. SpiderMonkey constructs exactly one ``Debugger.Source`` for each underlying WebAssembly module per :doc:`Debugger <../debugger/index>` instance. + +Please note at the time of this writing, support for WebAssembly is very preliminary. Many properties below return placeholder values. + + +Convention +********** + +For descriptions of properties and methods below, if the behavior of the property or method differs between the instance referring to JavaScript source or to a block of WebAssembly code, the text will be split into two sections, headed by “**if the instance refers to JavaScript source**” and “**if the instance refers to WebAssembly code**”, respectively. If the behavior does not differ, no such emphasized headings will appear. + + +Accessor Properties of the Debugger.Source Prototype Object +*********************************************************** + +A ``Debugger.Source`` instance inherits the following accessor properties from its prototype: + + +``text`` + **If the instance refers to JavaScript source**, the JavaScript source code, as a string. The value satisfies the ``Program``, ``FunctionDeclaration``, or ``FunctionExpression`` productions in the ECMAScript standard. + + **If the instance refers to WebAssembly code**, the serialized text representation. The format is yet to be specified in the WebAssembly standard. Currently, the text is an s-expression based syntax. The text generation is disabled if the Debugger has the ``allowWasmBinarySource`` property set, the ``"[wasm]"`` value will be returned in this case. + +``binary`` + **If the instance refers to WebAssembly code** and the Debugger has the ``allowWasmBinarySource`` property set, a Uint8Array that contains the WebAssembly bytecode. + +``url`` + **If the instance refers to JavaScript source**, the filename or URL from which this script’s code was loaded. For scripts created by ``eval`` or the ``Function`` constructor, this may be a synthesized filename, starting with a valid URL and followed by information tracking how the code was introduced into the system; the entire string is not a valid URL. For ``Function.prototype``’s script, this is ``null``. Source may be loaded from a URL in the following ways: + + - The URL may appear as the ``src`` attribute of a ``<script>`` element in markup text. + - The URL may be passed to the ``Worker`` web worker constructor, or the web worker ``importScripts`` function. + - The URL may be the name of a XPCOM JavaScript module or subscript. + + + (Note that code passed to ``eval``, the ``Function`` constructor, or a similar function is*not* considered to be loaded from a URL; the ``url`` accessor on ``Debugger.Source`` instances for such sources should return ``undefined``.) + + **If the instance refers to WebAssembly code**, the URL of the script that called ``new WebAssembly.Module`` with the string ``"> wasm"`` appended. + +``sourceMapURL`` + **If the instance refers to JavaScript source**, if this source was produced by a minimizer or translated from some other language, and we know the URL of a **source map** document relating the source positions in this source to the corresponding source positions in the original source, then this property’s value is that URL. Otherwise, this is ``null``. + + (On the web, the translator may provide the source map URL in a specially formatted comment in the JavaScript source code, or via a header in the HTTP reply that carried the generated JavaScript.) + + This property is writable, so you can change the source map URL by setting it. All Debugger.Source objects referencing the same source will see the change. Setting an empty string has no effect and will not change existing value. + + **If the instance refers to WebAssembly code**, ``null``. Attempts to write to this property throw a ``TypeError``. + +``displayURL`` + If the script had a special ``//# sourceURL`` comment, as described in the source maps specification, then this property’s value holds the string that was given. Otherwise, this is ``null``. + +``element`` + The <a href="Debugger.Object">``Debugger.Object``</a> instance referring to the DOM element to which this source code belongs, if any, or ``undefined`` if it belongs to no DOM element. Source belongs to a DOM element in the following cases: + + - Source belongs to a ``<script>`` element if it is the element’s text content (that is, it is written out as the body of the ``<script>`` element in the markup text), or is the source document referenced by its ``src`` attribute. + - Source belongs to a DOM element if it is an event handler content attribute (that is, if it is written out in the markup text as an attribute value). + - Source belongs to a DOM element if it was assigned to one of the element’s event handler IDL attributes as a string. (Note that one may assign both strings and functions to DOM elements’ event handler IDL attributes. If one assigns a function, that function’s script’s source does*not* belong to the DOM element; the function’s definition must appear elsewhere.) + + (If the sources attached to a DOM element change, the ``Debugger.Source`` instances representing superseded code still refer to the DOM element; this accessor only reflects origins, not current relationships.) + +``elementAttributeName`` + If this source belongs to a DOM element because it is an event handler content attribute or an event handler IDL attribute, this is the name of that attribute, a string. Otherwise, this is ``undefined``. + +``introductionType`` + **If the instance refers to JavaScript source**, a string indicating how this source code was introduced into the system. This accessor returns one of the following values: + + - ``"eval"``, for code passed to ``eval``. + - ``"Function"``, for code passed to the ``Function`` constructor. + - ``"Function.prototype"``, for ``Function.prototype`` internally generated code. + - ``"Worker"``, for code loaded by calling the Web worker constructor—the worker’s main script. + - ``"importScripts"``, for code by calling ``importScripts`` in a web worker. + - ``"eventHandler"``, for code assigned to DOM elements’ event handler IDL attributes as a string. + - ``"scriptElement"``, for code belonging to ``<script>`` elements. + - ``"javascriptURL"``, for code presented in ``javascript:`` URLs. + - ``"setTimeout"``, for code passed to ``setTimeout`` as a string. + - ``"setInterval"``, for code passed to ``setInterval`` as a string. + - ``undefined``, if the implementation doesn’t know how the code was introduced. + + + **If the instance refers to WebAssembly code**, ``"wasm"``. + +``introductionScript``, ``introductionOffset`` + **If the instance refers to JavaScript source**, and if this source was introduced by calling a function from debuggee code, then ``introductionScript`` is the <a href="Debugger.Script">``Debugger.Script``</a> instance referring to the script containing that call, and ``introductionOffset`` is the call’s bytecode offset within that script. Otherwise, these are both ``undefined``. Taken together, these properties indicate the location of the introducing call. + + For the purposes of these accessors, assignments to accessor properties are treated as function calls. Thus, setting a DOM element’s event handler IDL attribute by assigning to the corresponding JavaScript property creates a source whose ``introductionScript`` and ``introductionOffset`` refer to the property assignment. + + Since a ``<script>`` element parsed from a web page’s original HTML was not introduced by any scripted call, its source’s ``introductionScript`` and ``introductionOffset`` accessors both return ``undefined``. + + If a ``<script>`` element was dynamically inserted into a document, then these accessors refer to the call that actually caused the script to run—usually the call that made the element part of the document. Thus, they do*not* refer to the call that created the element; stored the source as the element’s text child; made the element a child of some uninserted parent node that was later inserted; or the like. + + Although the main script of a worker thread is introduced by a call to ``Worker`` or ``SharedWorker``, these accessors always return ``undefined`` on such script’s sources. A worker’s main script source and the call that created the worker are always in separate threads, but <a href="Debugger" title="The Debugger object">``Debugger``</a> is an inherently single-threaded facility: its debuggees must all run in the same thread. Since the global that created the worker is in a different thread, it is guaranteed not to be a debuggee of the <a href="Debugger" title="The Debugger object">``Debugger``</a> instance that owns this source; and thus the creating call is never “in debuggee code”. Relating a worker to its creator, and other multi-threaded debugging concerns, are out of scope for <a href="Debugger" title="The Debugger object">``Debugger``</a>. + + **If the instance refers to WebAssembly code**, ``introductionScript`` is the <a href="Debugger.Script">``Debugger.Script``</a> instance referring to the same underlying WebAssembly module. ``introductionOffset`` is ``undefined``. + + +Source Metadata +--------------- + +Generated from file: + js/src/doc/Debugger/Debugger.Source.md +Watermark: + sha256:5ca245813db96628aab1c78b803355eb2aa8c575839c67eb7d7bde177898df88 +Changeset: + `e91b2c85aacd <https://hg.mozilla.org/mozilla-central/rev/e91b2c85aacd>`_ diff --git a/devtools/docs/user/debugger-api/debugger/index.rst b/devtools/docs/user/debugger-api/debugger/index.rst new file mode 100644 index 0000000000..b26716a78a --- /dev/null +++ b/devtools/docs/user/debugger-api/debugger/index.rst @@ -0,0 +1,314 @@ +======== +Debugger +======== + +The Debugger Object +******************* + +When called as a constructor, the ``Debugger`` object creates a new ``Debugger`` instance. + + +``new Debugger([global, …])`` + Create a debugger object, and apply its :ref:`addDebuggee <debugger-api-debugger-add-debuggee>` method to each of the given *global* objects to add them as the initial debuggees. + + +Accessor Properties of the Debugger Prototype Object +---------------------------------------------------- + +A ``Debugger`` instance inherits the following accessor properties from its prototype: + + +``enabled`` + + A boolean value indicating whether this ``Debugger`` instance’s handlers, breakpoints, and the like are currently enabled. It is an accessor property with a getter and setter: assigning to it enables or disables this ``Debugger`` instance; reading it produces true if the instance is enabled, or false otherwise. This property is initially ``true`` in a freshly created ``Debugger`` instance. + + This property gives debugger code a single point of control for disentangling itself from the debuggee, regardless of what sort of events or handlers or “points” we add to the interface. + +``allowUnobservedAsmJS`` + + A boolean value indicating whether asm.js code running inside this ``Debugger`` instance’s debuggee globals is invisible to Debugger API handlers and breakpoints. Setting this to ``false`` inhibits the ahead-of-time asm.js compiler and forces asm.js code to run as normal JavaScript. This is an accessor property with a getter and setter. It is initially ``false`` in a freshly created ``Debugger`` instance. + + Setting this flag to ``true`` is intended for uses of subsystems of the Debugger API (e.g, :doc:`Debugger.Source <../debugger.source/index>`) for purposes other than step debugging a target JavaScript program. + +``allowWasmBinarySource`` + + A boolean value indicating whether WebAssembly sources will be available in binary form. The WebAssembly text generation will be disabled. + +``collectCoverageInfo`` + + A boolean value indicating whether code coverage should be enabled inside each debuggee of this ``Debugger`` instance. Changing this flag value will recompile all JIT code to add or remove code coverage instrumentation. Changing this flag when any frame of the debuggee is currently active on the stack will produce an exception. + + Setting this to ``true`` enables code coverage instrumentation, which can be accessed via the :doc:`Debugger.Script <../debugger.script/index>` ``getOffsetsCoverage`` function. In some cases, the code coverage might expose information which pre-date the modification of this flag. Code coverage reports are monotone, thus one can take a snapshot when the Debugger is enabled, and output the difference. + + Setting this to ``false`` prevents this ``Debugger`` instance from requiring any code coverage instrumentation, but it does not guarantee that the instrumentation is not present. + +``uncaughtExceptionHook`` + + Either ``null`` or a function that SpiderMonkey calls when a call to a debug event handler, breakpoint handler, or similar function throws some exception, which we refer to as *debugger-exception* here. Exceptions thrown in the debugger are not propagated to debuggee code; instead, SpiderMonkey calls this function, passing *debugger-exception* as its sole argument and the ``Debugger`` instance as the ``this`` value. This function should return a resumption value, which determines how the debuggee should continue. + + If the uncaught exception hook itself throws an exception, *uncaught-hook-exception*, SpiderMonkey throws a new error object, *confess-to-debuggee-exception*, to the debuggee whose message blames the debugger, and includes textual descriptions of *uncaught-hook-exception* and the original *debugger-exception*. + + If ``uncaughtExceptionHook``’s value is ``null``, SpiderMonkey throws an exception to the debuggee whose message blames the debugger, and includes a textual description of *debugger-exception*. + + Assigning anything other than a callable value or ``null`` to this property throws a ``TypeError`` exception. + + (This is not an ideal way to handle debugger bugs, but the hope here is that some sort of backstop, even if imperfect, will make life easier for debugger developers. For example, an uncaught exception hook may have access to browser-level features like the ``alert`` function, which this API’s implementation does not, making it possible to present debugger errors to the developer in a way suited to the context.) + + +Debugger Handler Functions +************************** + +Each ``Debugger`` instance inherits accessor properties with which you can store handler functions for SpiderMonkey to call when given events occur in debuggee code. + +When one of the events described below occurs in debuggee code, the engine pauses the debuggee and calls the corresponding debugging handler on each ``Debugger`` instance that is observing the debuggee. The handler functions receive the ``Debugger`` instance as their ``this`` value. Most handler functions can return a resumption value indicating how the debuggee’s execution should proceed. + +On a new ``Debugger`` instance, each of these properties is initially ``undefined``. Any value assigned to a debugging handler must be either a function or ``undefined``; otherwise a ``TypeError`` is thrown. + +Handler functions run in the same thread in which the event occurred. They run in the compartment to which they belong, not in a debuggee compartment. + + +``onNewScript(script, global)`` + + New code, represented by the :doc:`Debugger.Script <../debugger.script/index>` instance *script*, has been loaded in the scope of the debuggees. + + This method’s return value is ignored. + +``onNewPromise(promise)`` + + A new Promise object, referenced by the :doc:`Debugger.Object <../debugger.object/index>` instance *promise*, has been allocated in the scope of the debuggees. The Promise’s allocation stack can be obtained using the *promiseAllocationStack* accessor property of the :doc:`Debugger.Object <../debugger.object/index>` instance *promise*. + + This handler method should return a resumption value specifying how the debuggee’s execution should proceed. However, note that a ``{ return: value }`` resumption value is treated like ``undefined`` (“continue normally”); *value* is ignored. + +``onPromiseSettled(promise)`` + + A Promise object, referenced by the :doc:`Debugger.Object <../debugger.object/index>` instance *promise* that was allocated within a debuggee scope, has settled (either fulfilled or rejected). The Promise’s state, fulfillment or rejection value, and the allocation and resolution stacks can be obtained using the Promise-related accessor properties of the :doc:`Debugger.Object <../debugger.object/index>` instance *promise*. + + This handler method should return a resumption value specifying how the debuggee’s execution should proceed. However, note that a ``{ return: value }`` resumption value is treated like ``undefined`` (“continue normally”); *value* is ignored. + +``onDebuggerStatement(frame)`` + + Debuggee code has executed a *debugger* statement in *frame*. This method should return a resumption value specifying how the debuggee’s execution should proceed. + +``onEnterFrame(frame)`` + + The stack *frame* is about to begin executing code. (Naturally, *frame* is currently the youngest :doc:`visible frame <../debugger.frame/index>`.) This method should return a resumption value specifying how the debuggee’s execution should proceed. + + SpiderMonkey only calls ``onEnterFrame`` to report :ref:`visible <debugger-api-debugger-frame-visible-frames>`, non-``"debugger"`` frames. + +``onExceptionUnwind(frame, value)`` + + The exception *value* has been thrown, and has propagated to *frame*; *frame* is the youngest remaining stack frame, and is a debuggee frame. This method should return a resumption value specifying how the debuggee’s execution should proceed. If it returns ``undefined``, the exception continues to propagate as normal: if control in ``frame`` is in a ``try`` block, control jumps to the corresponding ``catch`` or ``finally`` block; otherwise, *frame* is popped, and the exception propagates to *frame* caller. + + When an exception’s propagation causes control to enter a ``finally`` block, the exception is temporarily set aside. If the ``finally`` block finishes normally, the exception resumes propagation, and the debugger’s ``onExceptionUnwind`` handler is called again, in the same frame. (The other possibility is for the ``finally`` block to exit due to a ``return``, ``continue``, or ``break`` statement, or a new exception. In those cases the old exception does not continue to propagate; it is discarded.) + + This handler is not called when unwinding a frame due to an over-recursion or out-of-memory exception. + +``sourceHandler(ASuffusionOfYellow)`` + + This method is never called. If it is ever called, a contradiction has been proven, and the debugger is free to assume that everything is true. + +``onError(frame, report)`` + + SpiderMonkey is about to report an error in *frame*. *Report* is an object describing the error, with the following properties: + + + ``message`` + The fully formatted error message. + ``file`` + If present, the source file name, URL, etc. (If this property is present, the *line* property will be too, and vice versa.) + ``line`` + If present, the source line number at which the error occurred. + ``lineText`` + If present, this is the source code of the offending line. + ``offset`` + The index of the character within lineText at which the error occurred. + ``warning`` + Present and true if this is a warning; absent otherwise. + ``strict`` + Present and true if this error or warning is due to the strict option (not to be confused with ES strict mode) + ``exception`` + Present and true if an exception will be thrown; absent otherwise. + ``arguments`` + An array of strings, representing the arguments substituted into the error message. + + + This method’s return value is ignored. + +``onNewGlobalObject(global)`` + + A new global object, *global*, has been created. + + This handler method should return a resumption value specifying how the debuggee’s execution should proceed. However, note that a ``{ return: value }`` resumption value is treated like ``undefined`` (“continue normally”); *value* is ignored. (Allowing the handler to substitute its own value for the new global object doesn’t seem useful.) + + This handler method is only available to debuggers running in privileged code (“chrome”, in Firefox). Most functions provided by this ``Debugger`` API observe activity in only those globals that are reachable by the API’s user, thus imposing capability-based restrictions on a ``Debugger``’s reach. However, the ``onNewGlobalObject`` method allows the API user to monitor all global object creation that occurs anywhere within the JavaScript system (the “JSRuntime”, in SpiderMonkey terms), thereby escaping the capability-based limits. For this reason, ``onNewGlobalObject`` is only available to privileged code. + + +Function Properties of the Debugger Prototype Object +**************************************************** + +The functions described below may only be called with a ``this`` value referring to a ``Debugger`` instance; they may not be used as methods of other kinds of objects. + +.. _debugger-api-debugger-add-debuggee: + +``addDebuggee(global)`` + + Add the global object designated by *global* to the set of global objects this ``Debugger`` instance is debugging. If the designated global is already a debuggee, this has no effect. Return this ``Debugger`` :doc:`Debugger.Object <../debugger.object/index>` instance referring to the designated global. + + The value *global* may be any of the following: + + - A global object. + + - An HTML5 ``WindowProxy`` object (an “outer window”, in Firefox terminology), which is treated as if the ``Window`` object of the browsing context’s active document (the “inner window”) were passed. + + - A cross-compartment wrapper of an object; we apply the prior rules to the wrapped object. + + - A :doc:`Debugger.Object <../debugger.object/index>` instance belonging to this ``Debugger`` instance; we apply the prior rules to the referent. + + - Any other sort of value is treated as a ``TypeError``. (Note that each rule is only applied once in the process of resolving a given *global* argument. Thus, for example, a :doc:`Debugger.Object <../debugger.object/index>` referring to a second :doc:`Debugger.Object <../debugger.object/index>` which refers to a global does not designate that global for the purposes of this function.) + + + The global designated by *global* must be in a different compartment than this ``Debugger`` instance itself. If adding the designated global’s compartment would create a cycle of debugger and debuggee compartments, this method throws an error. + + This method returns the :doc:`Debugger.Object <../debugger.object/index>` instance whose referent is the designated global object. + + The ``Debugger`` instance does not hold a strong reference to its debuggee globals: if a debuggee global is not otherwise reachable, then it is dropped from the ``Debugger`` set of debuggees. (Naturally, the :doc:`Debugger.Object <../debugger.object/index>` instance this method returns does hold a strong reference to the added global.) + + If this debugger is :ref:`tracking allocation sites <debugger-api-debugger-memory-tracking-allocation-sites>` and cannot track allocation sites for *global*, this method throws an ``Error``. + +``addAllGlobalsAsDebuggees()`` + + This method is like :ref:`addDebuggee <debugger-api-debugger-add-debuggee>`, but adds all the global objects from all compartments to this ``Debugger`` instance’s set of debuggees. Note that it skips this debugger’s compartment. + + If this debugger is :ref:`tracking allocation sites <debugger-api-debugger-memory-tracking-allocation-sites>` and cannot track allocation sites for some global, this method throws an ``Error``. Otherwise this method returns ``undefined``. + + This method is only available to debuggers running in privileged code (“chrome”, in Firefox). Most functions provided by this ``Debugger`` API observe activity in only those globals that are reachable by the API’s user, thus imposing capability-based restrictions on a ``Debugger``’s reach. However, the ``addAllGlobalsAsDebuggees`` method allows the API user to monitor all global object creation that occurs anywhere within the JavaScript system (the “JSRuntime”, in SpiderMonkey terms), thereby escaping the capability-based limits. For this reason, ``addAllGlobalsAsDebuggees`` is only available to privileged code. + +``removeDebuggee(global)`` + + Remove the global object designated by *global* from this ``Debugger`` instance’s set of debuggees. Return ``undefined``. + + This method interprets *global* using the same rules that :ref:`addDebuggee <debugger-api-debugger-add-debuggee>` does. + + Removing a global as a debuggee from this ``Debugger`` clears all breakpoints that belong to that ``Debugger`` in that global. + +``removeAllDebuggees()`` + + Remove all the global objects from this ``Debugger`` instance’s set of debuggees. Return ``undefined``. + +``hasDebuggee(global)`` + + Return ``true`` if the global object designated by *global* is a debuggee of this ``Debugger`` instance. + + This method interprets *global* using the same rules that :ref:`addDebuggee <debugger-api-debugger-add-debuggee>` does. + +``getDebuggees()`` + + Return an array of distinct :doc:`Debugger.Object <../debugger.object/index>` instances whose referents are all the global objects this ``Debugger`` instance is debugging. + + Since ``Debugger`` instances don’t hold strong references to their debuggee globals, if a debuggee global is otherwise unreachable, it may be dropped at any moment from the array this method returns. + +``getNewestFrame()`` + + Return a :doc:`Debugger.Frame <../debugger.frame/index>` instance referring to the youngest :doc:`visible frame <../debugger.frame/index>` currently on the calling thread’s stack, or ``null`` if there are no visible frames on the stack. + +``findSources([query]) (not yet implemented)`` + + Return an array of all :doc:`Debugger.Source <../debugger.source/index>` instances matching *query*. Each source appears only once in the array. *Query* is an object whose properties restrict which sources are returned; a source must meet all the criteria given by *query* to be returned. If *query* is omitted, we return all sources of all debuggee scripts. + + *Query* may have the following properties: + + ``url`` + The source’s ``url`` property must be equal to this value. + + ``global`` + The source must have been evaluated in the scope of the given global object. If this property’s value is a :doc:`Debugger.Object <../debugger.object/index>` instance belonging to this ``Debugger`` instance, then its referent is used. If the object is not a global object, then the global in whose scope it was allocated is used. + + Note that the result may include sources that can no longer ever be used by the debuggee: say, eval code that has finished running, or source for unreachable functions. Whether such sources appear can be affected by the garbage collector’s behavior, so this function’s result is not entirely deterministic. + +``findScripts([query])`` + + Return an array of :doc:`Debugger.Script <../debugger.script/index>` instances for all debuggee scripts matching *query*. Each instance appears only once in the array. *Query* is an object whose properties restrict which scripts are returned; a script must meet all the criteria given by *query* to be returned. If *query* is omitted, we return the :doc:`Debugger.Script <../debugger.script/index>` instances for all debuggee scripts. + + *Query* may have the following properties: + + + ``url`` + The script’s ``url`` property must be equal to this value. + ``source`` + The script’s ``source`` property must be equal to this value. + ``line`` + The script must at least partially cover the given source line. If this property is present, the ``url`` property must be present as well. + ``column`` + The script must include given column on the line given by the ``line`` property. If this property is present, the ``url`` and ``line`` properties must both be present as well. + ``innermost`` + If this property is present and true, the script must be the innermost script covering the given source location; scripts of enclosing code are omitted. + ``global`` + The script must be in the scope of the given global object. If this property’s value is a :doc:`Debugger.Object <../debugger.object/index>` instance belonging to this ``Debugger`` instance, then its referent is used. If the object is not a global object, then the global in whose scope it was allocated is used. + + + All properties of *query* are optional. Passing an empty object returns all debuggee code scripts. + + Note that the result may include :doc:`Debugger.Script <../debugger.script/index>` instances for scripts that can no longer ever be used by the debuggee, say, those for eval code that has finished running, or unreachable functions. Whether such scripts appear can be affected by the garbage collector’s behavior, so this function’s behavior is not entirely deterministic. + +``findObjects([query])`` + + Return an array of :doc:`Debugger.Object <../debugger.object/index>` instances referring to each live object allocated in the scope of the debuggee globals that matches *query*. Each instance appears only once in the array. *Query* is an object whose properties restrict which objects are returned; an object must meet all the criteria given by *query* to be returned. If *query* is omitted, we return the :doc:`Debugger.Object <../debugger.object/index>` instances for all objects allocated in the scope of debuggee globals. + + The *query* object may have the following properties: + + + ``class`` + If present, only return objects whose internal ``[[Class]]``’s name matches the given string. Note that in some cases, the prototype object for a given constructor has the same ``[[Class]]`` as the instances that refer to it, but cannot itself be used as a valid instance of the class. Code gathering objects by class name may need to examine them further before trying to use them. + + + All properties of *query* are optional. Passing an empty object returns all objects in debuggee globals. + + Unlike ``findScripts``, this function is deterministic and will never return <a href="Debugger.Object">``Debugger.Object``s</a> referring to previously unreachable objects that had not been collected yet. + +``clearBreakpoint(handler)`` + + Remove all breakpoints set in this ``Debugger`` instance that use *handler* as their handler. Note that, if breakpoints using other handler objects are set at the same location(s) as *handler*, they remain in place. + +``clearAllBreakpoints()`` + + Remove all breakpoints set using this ``Debugger`` instance. + +``findAllGlobals()`` + + Return an array of :doc:`Debugger.Object <../debugger.object/index>` instances referring to all the global objects present in this JavaScript instance. + + The results of this call can be affected in non-deterministic ways by the details of the JavaScript implementation. The array may include :doc:`Debugger.Object <../debugger.object/index>` instances referring to global objects that are not actually reachable by the debuggee or any other code in the system. (Naturally, once the function has returned, the array’s :doc:`Debugger.Object <../debugger.object/index>` instances strongly reference the globals they refer to.) + + This handler method is only available to debuggers running in privileged code (“chrome”, in Firefox). Most functions provided by this ``Debugger`` API observe activity in only those globals that are reachable by the API’s user, thus imposing capability-based restrictions on a ``Debugger``’s reach. However, ``findAllGlobals`` allows the API user to find all global objects anywhere within the JavaScript system (the “JSRuntime”, in SpiderMonkey terms), thereby escaping the capability-based limits. For this reason, ``findAllGlobals`` is only available to privileged code. + +``makeGlobalObjectReference(global)`` + + Return the :doc:`Debugger.Object <../debugger.object/index>` whose referent is the global object designated by *global*, without adding the designated global as a debuggee. If *global* does not designate a global object, throw a ``TypeError``. Determine which global is designated by *global* using the same rules as <a href="Debugger#addDebuggee" title="The Debugger object: addDebuggee">``Debugger.prototype.addDebuggee``</a>. + +``adoptDebuggeeValue(value)`` + + Given a debuggee value ``value`` owned by an arbitrary ``Debugger``, return an equivalent debuggee value owned by this ``Debugger``. + + If ``value`` is a primitive value, return it unchanged. If ``value`` is a ``Debugger.Object`` owned by an arbitrary ``Debugger``, return an equivalent ``Debugger.Object`` owned by this ``Debugger``. Otherwise, if ``value`` is some other kind of object, and hence not a proper debuggee value, throw a TypeError instead. + + +Static methods of the Debugger Object +************************************* + +The functions described below are not called with a ``this`` value. + +``isCompilableUnit(source)`` + Given a string of source code, designated by *source*, return false if the string might become a valid JavaScript statement with the addition of more lines. Otherwise return true. The intent is to support interactive compilation - accumulate lines in a buffer until isCompilableUnit is true, then pass it to the compiler. + + +Source Metadata +--------------- + +Generated from file: + js/src/doc/Debugger/Debugger.md + +Watermark: + sha256:03b36132885e046a5f213130ba22b1139b473770f7324b842483c09ab7665f7c + +Changeset: + `e91b2c85aacd <https://hg.mozilla.org/mozilla-central/rev/e91b2c85aacd>`_ diff --git a/devtools/docs/user/debugger-api/index.rst b/devtools/docs/user/debugger-api/index.rst new file mode 100644 index 0000000000..158b70213a --- /dev/null +++ b/devtools/docs/user/debugger-api/index.rst @@ -0,0 +1,92 @@ +============ +Debugger-API +============ + +The ``Debugger`` Interface +************************** + +Mozilla’s JavaScript engine, SpiderMonkey, provides a debugging interface named ``Debugger`` which lets JavaScript code observe and manipulate the execution of other JavaScript code. Both Firefox’s built-in developer tools and the Firebug add-on use ``Debugger`` to implement their JavaScript debuggers. However, ``Debugger`` is quite general, and can be used to implement other kinds of tools like tracers, coverage analysis, patch-and-continue, and so on. + +``Debugger`` has three essential qualities: + + +- It is a *source level* interface: it operates in terms of the JavaScript language, not machine language. It operates on JavaScript objects, stack frames, environments, and code, and presents a consistent interface regardless of whether the debuggee is interpreted, compiled, or optimized. If you have a strong command of the JavaScript language, you should have all the background you need to use ``Debugger`` successfully, even if you have never looked into the language’s implementation. + +- It is for use *by JavaScript code*. JavaScript is both the debuggee language and the tool implementation language, so the qualities that make JavaScript effective on the web can be brought to bear in crafting tools for developers. As is expected of JavaScript APIs, ``Debugger`` is a *sound* interface: using (or even misusing) ``Debugger`` should never cause Gecko to crash. Errors throw proper JavaScript exceptions. + +- It is an *intra-thread* debugging API. Both the debuggee and the code using ``Debugger`` to observe it must run in the same thread. Cross-thread, cross-process, and cross-device tools must use ``Debugger`` to observe the debuggee from within the same thread, and then handle any needed communication themselves. (Firefox’s builtin tools have a `protocol <https://wiki.mozilla.org/Remote_Debugging_Protocol>`_ defined for this purpose.) + + +In Gecko, the ``Debugger`` API is available to chrome code only. By design, it ought not to introduce security holes, so in principle it could be made available to content as well; but it is hard to justify the security risks of the additional attack surface. + +The ``Debugger`` API cannot currently observe self-hosted JavaScript. This is not inherent in the API’s design, but that the self-hosting infrastructure isn’t prepared for the kind of invasions the ``Debugger`` API can perform. + + +Debugger Instances and Shadow Objects +************************************* + +``Debugger`` reflects every aspect of the debuggee’s state as a JavaScript value—not just actual JavaScript values like objects and primitives, but also stack frames, environments, scripts, and compilation units, which are not normally accessible as objects in their own right. + +Here is a JavaScript program in the process of running a timer callback function: + +.. image:: shadows.svg + :alt: A running JavaScript program and its Debugger shadows + :class: center + +A running JavaScript program and its Debugger shadows + +This diagram shows the various types of shadow objects that make up the Debugger API (which all follow some general conventions): + + +- A :doc:`Debugger.Object <debugger.object/index>` represents a debuggee object, offering a reflection-oriented API that protects the debugger from accidentally invoking getters, setters, proxy traps, and so on. + +- A :doc:`Debugger.Script <debugger.script/index>` represents a block of JavaScript code—either a function body or a top-level script. Given a ``Debugger.Script``, one can set breakpoints, translate between source positions and bytecode offsets (a deviation from the “source level” design principle), and find other static characteristics of the code. + +- A :doc:`Debugger.Frame <debugger.frame/index>` represents a running stack frame. You can use these to walk the stack and find each frame’s script and environment. You can also set ``onStep`` and ``onPop`` handlers on frames. + +- A :doc:`Debugger.Environment <debugger.environment/index>` represents an environment, associating variable names with storage locations. Environments may belong to a running stack frame, captured by a function closure, or reflect some global object’s properties as variables. + + +The :doc:`Debugger <debugger/index>` instance itself is not really a shadow of anything in the debuggee; rather, it maintains the set of global objects which are to be considered debuggees. A ``Debugger`` observes only execution taking place in the scope of these global objects. You can set functions to be called when new stack frames are pushed; when new code is loaded; and so on. + +Omitted from this picture are :doc:`Debugger.Source <debugger.source/index.>` instances, which represent JavaScript compilation units. A ``Debugger.Source`` can furnish a full copy of its source code, and explain how the code entered the system, whether via a call to ``eval``, a ``<script>`` element, or otherwise. A ``Debugger.Script`` points to the ``Debugger.Source`` from which it is derived. + +Also omitted is the ``Debugger``’s :doc:`Debugger.Memory <debugger.memory/index>` instance, which holds methods and accessors for observing the debuggee’s memory use. + +All these types follow some general conventions, which you should look through before drilling down into any particular type’s specification. + +All shadow objects are unique per ``Debugger`` and per referent. For a given ``Debugger``, there is exactly one ``Debugger.Object`` that refers to a particular debuggee object; exactly one ``Debugger.Frame`` for a particular stack frame; and so on. Thus, a tool can store metadata about a shadow’s referent as a property on the shadow itself, and count on finding that metadata again if it comes across the same referent. And since shadows are per-``Debugger``, tools can do so without worrying about interfering with other tools that use their own ``Debugger`` instances. + + +Examples +******** + +Here are some things you can try out yourself that show off some of ``Debugger``’s features: + + +- :doc:`Setting a breakpoint <tutorial-breakpoint/index>` in a page, running a handler function when it is hit that evaluates an expression in the page’s context. + +- :doc:`Showing how many objects different call paths allocate. <tutorial-allocation-log-tree/index>` + + +Gecko-specific features +*********************** + +While the ``Debugger`` core API deals only with concepts common to any JavaScript implementation, it also includes some Gecko-specific features: + + +- [Global tracking][global] supports debugging all the code running in a Gecko instance at once—the ‘chrome debugging’ model. +- [Object wrapper][wrapper] functions help manipulate object references that cross privilege boundaries. + + +Source Metadata +--------------- + +Generated from file: + js/src/doc/Debugger/Debugger-API.md + +Watermark: + sha256:6ee2381145a0d2e53d2f798f3f682e82dd7ab0caa0ac4dd5e56601c2e49913a7 + +Changeset: + `ffa775dd5bd4 <https://hg.mozilla.org/mozilla-central/rev/ffa775dd5bd4>`_ diff --git a/devtools/docs/user/debugger-api/shadows.svg b/devtools/docs/user/debugger-api/shadows.svg new file mode 100644 index 0000000000..03db057223 --- /dev/null +++ b/devtools/docs/user/debugger-api/shadows.svg @@ -0,0 +1,4 @@ +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> +<svg xmlns="http://www.w3.org/2000/svg" width="650" height="400"><defs><marker orient="auto" refY="0" refX="0" id="c" overflow="visible"><path d="M.98 0a1 1 0 11-2 0 1 1 0 012 0z" fill-rule="evenodd" stroke="#000" stroke-width=".2pt"/></marker><marker orient="auto" refY="0" refX="0" id="d" overflow="visible"><path d="M-1.2 0l-1 1 3.5-1-3.5-1 1 1z" fill-rule="evenodd" stroke="#000" stroke-width=".2pt"/></marker><marker orient="auto" refY="0" refX="0" id="a" overflow="visible"><path d="M.98 0a1 1 0 11-2 0 1 1 0 012 0z" fill-rule="evenodd" stroke="#000" stroke-width=".2pt"/></marker><marker orient="auto" refY="0" refX="0" id="b" overflow="visible"><path d="M-1.2 0l-1 1 3.5-1-3.5-1 1 1z" fill-rule="evenodd" stroke="#000" stroke-width=".2pt"/></marker></defs><g class="flip"><rect width="171.317" height="150.685" x=".11" y="248.55" ry="4.814" rx="4.035" fill="#c8c0c0" stroke="#000" stroke-width="2.182" stroke-dasharray="4.36452564,4.36452564"/><text style="line-height:125%" x="9.875" y="268.844" font-size="14.12" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="9.875" y="268.844">Debugger</tspan></text></g><g class="flip"><rect width="119.421" height="42.398" x="25.236" y="160.02" ry="11.065" rx="11.065" fill="#969696"/><rect width="177.655" height="46.615" x="209.361" y="336.42" ry="4.039" rx="4.039" fill="#969696"/><rect width="149.122" height="46.615" x="237.894" y="287.164" ry="4.039" rx="4.039" fill="#969696"/><rect width="119.421" height="42.398" x="192.177" y="161.099" ry="11.065" rx="11.065" fill="#969696"/><rect width="136.405" height="46.615" x="26.006" y="336.42" ry="11.065" rx="11.065" fill="#969696"/><rect width="242.772" height="75.739" x="183.318" y="47.055" ry="6.125" rx="6.125" fill="#969696"/><rect width="186.276" height="18.675" x="285.598" y="66.984" ry="6.125" rx="6.125" fill="#969696" stroke="#fff" stroke-width="2.929"/><rect width="194.03" height="46.615" x="413.202" y="336.42" ry="4.039" rx="4.039" fill="#969696"/><rect width="90.035" height="46.615" x="296.98" y="237.91" ry="4.039" rx="4.039" fill="#969696"/><text style="line-height:125%" x="33.258" y="378.201" font-size="12.935" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="33.258" y="378.201">Debugger.Object</tspan></text><text style="line-height:125%" x="218.723" y="377.522" font-size="12.935" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="218.723" y="377.522">Debugger.Environment</tspan></text><text style="line-height:125%" x="421.849" y="377.522" font-size="12.935" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="421.849" y="377.522">Debugger.Frame</tspan></text><text style="line-height:125%" x="29.181" y="196.813" font-size="12.935" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="29.181" y="196.813">Debugger.Object</tspan></text><text style="line-height:125%" x="199.222" y="197.892" font-size="12.935" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="199.222" y="197.892">Debugger.Object</tspan></text><text style="line-height:125%" x="190.189" y="118.008" font-size="12.935" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="190.189" y="118.008">Debugger.Script</tspan></text><rect width="194.03" height="46.615" x="413.202" y="287.164" ry="4.039" rx="4.039" fill="#969696"/></g><g transform="translate(0 -344.094)" class="flip"><rect width="177.927" height="46.615" x="201.82" y="664.159" ry="4.039" rx="4.039" class="nonvalue" fill="#ffd257"/><text style="line-height:125%" x="210.634" y="691.887" transform="scale(1.00076 .99924)" font-size="14.122" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="210.634" y="691.887">global environment</tspan></text><rect width="136.614" height="46.615" x="18.811" y="664.159" ry="11.065" rx="11.065" fill="#83d4ff"/><path d="M204.053 687.466h-46.267" fill="none" stroke="#000" stroke-width="3" marker-start="url(#a)" marker-end="url(#b)"/><text style="line-height:125%" x="3.02" y="659.444" transform="scale(1.00076 .99924)" font-size="14.122" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="3.02" y="659.444">global object:</tspan></text><text style="text-align:center;line-height:125%" x="87.051" y="698.414" transform="scale(1.00076 .99924)" font-size="14.122" font-weight="400" letter-spacing="0" word-spacing="0" text-anchor="middle" font-family="Sans"><tspan x="87.051" y="698.414">Date; Math; ...</tspan></text></g><g class="flip"><rect transform="translate(0 -652.362)" width="243.144" height="75.74" x="176.363" y="683.061" ry="6.125" rx="6.125" class="nonvalue" fill="#83ff9a"/><rect transform="translate(0 -652.362)" width="186.561" height="18.675" x="278.799" y="702.99" ry="6.125" rx="6.125" class="nonvalue" fill="#83ff9a" stroke="#e6e4dd" stroke-width="2.929"/></g><text style="line-height:125%" x="183" y="699.527" transform="matrix(1.00076 0 0 .99924 0 -652.362)" font-size="14.122" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="183" y="699.527">function alertLater(msg, delay) {</tspan><tspan x="183" y="717.179"> setTimeout( function () { alert(msg); },</tspan><tspan x="183" y="734.832"> delay);</tspan><tspan x="183" y="752.485">}</tspan></text><g class="flip"><rect transform="translate(0 -652.362)" width="119.604" height="42.398" x="18.04" y="796.026" ry="11.065" rx="11.065" fill="#83d4ff"/><text style="text-align:end;line-height:125%" x="98.428" y="811.158" transform="matrix(1.00076 0 0 .99924 0 -652.362)" font-size="13.919" font-weight="400" letter-spacing="0" word-spacing="0" text-anchor="end" font-family="Sans"><tspan x="98.428" y="811.158">[[Code]]:</tspan></text><text style="text-align:end;line-height:125%" x="98.428" y="831.649" transform="matrix(1.00076 0 0 .99924 0 -652.362)" font-size="13.919" font-weight="400" letter-spacing="0" word-spacing="0" text-anchor="end" font-family="Sans"><tspan x="98.428" y="831.649">[[Scope]]:</tspan></text><path d="M18.04 165.532h119.602" fill="none" stroke="#e6e4dd" stroke-width="2.957"/><text style="line-height:125%" x="2.407" y="791.508" transform="matrix(1.00076 0 0 .99924 0 -652.362)" font-size="14.122" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="2.407" y="791.508">alertLater:</tspan></text><path transform="translate(0 -652.362)" d="M113.607 806.633c0-45.024 23.466-83.543 59.207-83.543m-59.207 104.131c51.733 0 90.506 99.848 90.506 141.325" fill="none" stroke="#000" stroke-width="3" marker-start="url(#c)" marker-end="url(#d)"/><text style="text-align:center;line-height:125%" x="87.051" y="991.618" transform="matrix(1.00076 0 0 .99924 0 -652.362)" font-size="14.122" font-weight="400" letter-spacing="0" word-spacing="0" text-anchor="middle" font-family="Sans"><tspan x="89.299" y="991.618">alertLater;</tspan></text></g><g class="flip"><rect width="149.35" height="46.615" x="229.789" y="270.808" ry="4.039" rx="4.039" class="nonvalue" fill="#ffd257"/><g font-size="22" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><text transform="matrix(.58945 0 0 .58739 4.526 -176.544)" y="795.716" x="499.133" style="text-align:end;line-height:125%" text-anchor="end"><tspan y="795.716" x="499.133">msg:</tspan><tspan y="823.216" x="499.133">delay:</tspan></text><text y="794.926" x="507" style="line-height:125%" transform="matrix(.58887 0 0 .58797 4.526 -176.544)"><tspan y="794.926" x="507">'xlerb'</tspan><tspan y="822.426" x="507">1000</tspan></text></g></g><g class="flip"><rect width="119.604" height="42.398" x="185.843" y="143.664" ry="11.065" rx="11.065" fill="#83d4ff"/><text style="text-align:end;line-height:125%" x="266.103" y="158.298" transform="scale(1.00076 .99924)" font-size="13.919" font-weight="400" letter-spacing="0" word-spacing="0" text-anchor="end" font-family="Sans"><tspan x="266.103" y="158.298">[[Code]]:</tspan></text><text style="text-align:end;line-height:125%" x="266.103" y="178.789" transform="scale(1.00076 .99924)" font-size="13.919" font-weight="400" letter-spacing="0" word-spacing="0" text-anchor="end" font-family="Sans"><tspan x="266.103" y="178.789">[[Scope]]:</tspan></text><path d="M185.843 165.532h119.602" fill="none" stroke="#e6e4dd" stroke-width="2.957"/><path d="M285.445 176.59c0 31.26-38.089 59.767-38.089 91.053m38.594-113.165c165.685 0 170.772-32.93 158.206-82.184" fill="none" stroke="#000" stroke-width="3" marker-start="url(#c)" marker-end="url(#d)"/></g><g class="flip"><rect width="194.03" height="46.615" x="406.385" y="320.064" ry="4.039" rx="4.039" class="nonvalue" fill="#ff9457"/><text style="line-height:125%" x="434.11" y="346.934" font-size="12.935" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="434.11" y="346.934"><tspan style="-inkscape-font-specification:Sans Italic" font-style="italic">anonymous</tspan>()</tspan></text><rect width="90.035" height="46.615" x="289.103" y="221.555" ry="4.039" rx="4.039" class="nonvalue" fill="#ffd257"/><text style="line-height:125%;-inkscape-font-specification:Sans Italic" x="312.997" y="248.058" font-size="12.935" font-style="italic" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="312.997" y="248.058">empty</tspan></text><path d="M415.86 342.35c-51.097 0 11.106-95.595-39.03-95.595m211.854 96.578c66.197 0 27.6-283.142-117.224-283.142" fill="none" stroke="#000" stroke-width="3" marker-start="url(#a)" marker-end="url(#b)"/></g><g class="flip"><rect width="194.03" height="46.615" x="406.385" y="270.808" ry="4.039" rx="4.039" class="nonvalue" fill="#ff9457"/><text style="line-height:125%" x="433.863" y="298.871" font-size="12.935" font-weight="400" letter-spacing="0" word-spacing="0" font-family="Sans"><tspan x="433.863" y="298.871">alert('xlerb')</tspan></text></g></svg>
\ No newline at end of file diff --git a/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/alloc-plot-console.png b/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/alloc-plot-console.png Binary files differnew file mode 100644 index 0000000000..e41a5449b7 --- /dev/null +++ b/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/alloc-plot-console.png diff --git a/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/enable-chrome-devtools.png b/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/enable-chrome-devtools.png Binary files differnew file mode 100644 index 0000000000..17e3b30aa6 --- /dev/null +++ b/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/enable-chrome-devtools.png diff --git a/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/index.rst b/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/index.rst new file mode 100644 index 0000000000..711e6f245b --- /dev/null +++ b/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/index.rst @@ -0,0 +1,235 @@ +======================================== +Tutorial: Show Allocations Per Call Path +======================================== + +.. |br| raw:: html + + <br/> + +This page shows how to use the :doc:`Debugger API <../index>` to show how many objects a web page allocates, sorted by the function call path that allocated them. + +1. Visit the URL ``about:config``, and set the ``devtools.chrome.enabled`` preference to ``true``: + + .. image:: enable-chrome-devtools.png + :alt: Setting the devtools.chrome.enabled preference + :class: center + + Setting the ``devtools.chrome.enabled`` preference + +|br| + +2. Open a developer Scratchpad (Menu button > Developer > Scratchpad), and select "Browser" from the "Environment" menu. (This menu will not be present unless you have changed the preference as explained above.) + + .. image:: scratchpad-browser-environment.png + :alt: Selecting the browser context in the Scratchpad + :class: center + + Selecting the 'browser' context in the Scratchpad + +|br| + +3. Enter the following code in the Scratchpad: + + .. code-block:: javascript + + // This defines the 'Debugger' constructor in this + // Scratchpad; it doesn't actually start debugging anything. + const { addDebuggerToGlobal } = ChromeUtils.importESModule( + 'resource://gre/modules/jsdebugger.sys.mjs' + ); + addDebuggerToGlobal(window); + + (function () { + // The debugger we'll use to observe a tab's allocation. + var dbg; + + // Start measuring the selected tab's main window's memory + // consumption. This function is available in the browser + // console. + window.demoTrackAllocations = function() { + dbg = new Debugger; + + // This makes hacking on the demo *much* more + // pleasant. + dbg.uncaughtExceptionHook = handleUncaughtException; + + // Find the current tab's main content window. + var w = gBrowser.selectedBrowser.contentWindow; + console.log("Tracking allocations in page: " + + w.location.href); + + // Make that window a debuggee of our Debugger. + dbg.addDebuggee(w.wrappedJSObject); + + // Enable allocation tracking in dbg's debuggees. + dbg.memory.trackingAllocationSites = true; + } + + window.demoPlotAllocations = function() { + // Grab the allocation log. + var log = dbg.memory.drainAllocationsLog(); + + // Neutralize the Debugger, and drop it on the floor + // for the GC to collect. + console.log("Stopping allocation tracking."); + dbg.removeAllDebuggees(); + dbg = undefined; + + // Analyze and display the allocation log. + plot(log); + } + + function handleUncaughtException(ex) { + console.log('Debugger hook threw:'); + console.log(ex.toString()); + console.log('Stack:'); + console.log(ex.stack); + }; + + function plot(log) { + // Given the log, compute a map from allocation sites to + // allocation counts. Note that stack entries are '===' if + // they represent the same site with the same callers. + var counts = new Map; + for (let site of log) { + // This is a kludge, necessary for now. The saved stacks + // are new, and Firefox doesn't yet understand that they + // are safe for chrome code to use, so we must tell it + // so explicitly. + site = Components.utils.waiveXrays(site.frame); + + if (!counts.has(site)) + counts.set(site, 0); + counts.set(site, counts.get(site) + 1); + } + + // Walk from each site that allocated something up to the + // root, computing allocation totals that include + // children. Remember that 'null' is a valid site, + // representing the root. + var totals = new Map; + for (let [site, count] of counts) { + for(;;) { + if (!totals.has(site)) + totals.set(site, 0); + totals.set(site, totals.get(site) + count); + if (!site) + break; + site = site.parent; + } + } + + // Compute parent-to-child links, since saved stack frames + // have only parent links. + var rootChildren = new Map; + function childMapFor(site) { + if (!site) + return rootChildren; + + let parentMap = childMapFor(site.parent); + if (parentMap.has(site)) + return parentMap.get(site); + + var m = new Map; + parentMap.set(site, m); + return m; + } + for (let [site, total] of totals) { + childMapFor(site); + } + + // Print the allocation count for |site|. Print + // |children|'s entries as |site|'s child nodes. Indent + // the whole thing by |indent|. + function walk(site, children, indent) { + var name, place; + if (site) { + name = site.functionDisplayName; + place = ' ' + site.source + ':' + site.line + ':' + site.column; + } else { + name = '(root)'; + place = ''; + } + console.log(indent + totals.get(site) + ': ' + name + place); + for (let [child, grandchildren] of children) + walk(child, grandchildren, indent + ' '); + } + walk(null, rootChildren, ''); + } + })(); + +|br| + +4. In the Scratchpad, ensure that no text is selected, and press the "Run" button. (If you get an error complaining that ``Components.utils`` is not defined, be sure you've selected ``Browser`` from the scratchpad's ``Environment`` menu, as described in step 2.) + +|br| + +5. Save the following HTML text to a file, and visit the file in your browser. Make sure the current browser tab is displaying this page. + +.. code-block:: html + + <div onclick="doDivsAndSpans()"> + Click here to make the page do some allocations. + </div> + + <script> + function makeFactory(type) { + return function factory(content) { + var elt = document.createElement(type); + elt.textContent = content; + return elt; + }; + } + + var divFactory = makeFactory('div'); + var spanFactory = makeFactory('span'); + + function divsAndSpans() { + for (i = 0; i < 10; i++) { + var div = divFactory('div #' + i); + div.appendChild(spanFactory('span #' + i)); + document.body.appendChild(div); + } + } + + function doDivsAndSpans() { divsAndSpans(); } + </script> + +|br| + +6. Open the browser console (Menu Button > Developer > Browser Console), and then evaluate the expression ``demoTrackAllocations()`` in the browser console. This begins logging allocations in the current browser tab. + +|br| + +7. In the browser tab, click on the text that says "Click here…". The event handler should add some text to the end of the page. + +|br| + +8. Back in the browser console, evaluate the expression ``demoPlotAllocations()``. This stops logging allocations, and displays a tree of allocations: + + .. image:: alloc-plot-console.png + :alt: An allocation plot, displayed in the console + :class: center + + An allocation plot, displayed in the console + + The numbers at the left edge of each line show the total number of objects allocated at that site or at sites called from there. After the count, we see the function name, and the source code location of the call site or allocation. + + The ``(root)`` node's count includes objects allocated in the content page by the web browser, like DOM events. Indeed, this display shows that ``popup.xml`` and ``content.js``, which are internal components of Firefox, allocated more objects in the page's compartment than the page itself. (We will probably revise the allocation log to present such allocations in a way that is more informative, and that exposes less of Firefox's internal structure.) + + As expected, the ``onclick`` handler is responsible for all allocation done by the page's own code. (The line number for the onclick handler is ``1``, indicating that the allocating call is located on line one of the handler text itself. We will probably change this to be the line number within ``page.html``, not the line number within the handler code.) + + The ``onclick`` handler calls ``doDivsAndSpans``, which calls ``divsAndSpans``, which invokes closures of ``factory`` to do all the actual allocation. (It is unclear why ``spanFactory`` allocated thirteen objects, despite being called only ten times.) + + + +Source Metadata +--------------- + +Generated from file: + js/src/doc/Debugger/Tutorial-Alloc-Log-Tree.md + +Watermark: + sha256:b56f6df61c39dbe19ca1f49752aea42207c804355513f4fea8249bdeb4cb056d +Changeset: + `251fccc1f62b <https://hg.mozilla.org/mozilla-central/rev/251fccc1f62b>`_ diff --git a/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/scratchpad-browser-environment.png b/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/scratchpad-browser-environment.png Binary files differnew file mode 100644 index 0000000000..1e2e6cc51e --- /dev/null +++ b/devtools/docs/user/debugger-api/tutorial-allocation-log-tree/scratchpad-browser-environment.png diff --git a/devtools/docs/user/debugger-api/tutorial-breakpoint/console.png b/devtools/docs/user/debugger-api/tutorial-breakpoint/console.png Binary files differnew file mode 100644 index 0000000000..5016838502 --- /dev/null +++ b/devtools/docs/user/debugger-api/tutorial-breakpoint/console.png diff --git a/devtools/docs/user/debugger-api/tutorial-breakpoint/index.rst b/devtools/docs/user/debugger-api/tutorial-breakpoint/index.rst new file mode 100644 index 0000000000..918fecb00a --- /dev/null +++ b/devtools/docs/user/debugger-api/tutorial-breakpoint/index.rst @@ -0,0 +1,112 @@ +========================== +Tutorial: Set a breakpoint +========================== + +.. |br| raw:: html + + <br/> + +This page shows how you can try out the :doc:`Debugger API <../index>` yourself using Firefox’s Scratchpad. We use ``Debugger`` to set a breakpoint in a function, and then evaluate an expression whenever it is hit. + +This tutorial was tested against Firefox 58 Beta and Nightly. It does not work in Firefox 57. + +1. Since the ``Debugger`` API is only available to privileged JavaScript code, you’ll need to use the Browser Content Toolbox to try it out. To do this, open the Firefox developer tools, click on the options gear at the upper right of the toolbox, and make sure that both “Enable browser chrome and add-on debugging toolboxes” and “Enable remote debugging” are checked. These are located at the bottom right of the options panel; you may need to scroll to see them. Once they’re checked, you can close the developer tools. + +|br| + +2. Save the following text to an HTML file: + + .. code-block:: html + + <div onclick="report('the best div');">Click me!</div> + <div onclick="report('another great div');">Or me!</div> + <script> + function report(what) { + console.log('clicked: ' + what); + } + </script> + +|br| + +3. Visit the HTML file in your browser, and open the Browser Content Toolbox by opening the Firefox menu, choosing “Browser Tools”, and then “Browser Content Toolbox”. If that item doesn’t appear in the “Web Developer” menu, make sure you checked both boxes to enable the Browser Content Toolbox as explained in Step 1. + +|br| + +4. Our example code is long enough that the best way to run it is to use the Scratchpad panel, which is not enabled by default. To enable it, click on the options gear at the upper right of the Browser Content Toolbox, and make sure the “Scratchpad” box in the “Default Developer Tools” section the left is checked. The Scratchpad panel should appear at the top of the Toolbox alongside the Console, Debugger, and Memory panels. + +|br| + +5. Click on the Scratchpad panel and enter the following code: + + .. code-block:: javascript + + const { addDebuggerToGlobal } = ChromeUtils.importESModule( + "resource://gre/modules/jsdebugger.sys.mjs" + ); + const { console } = ChromeUtils.importESModule( + "resource://gre/modules/Console.sys.mjs" + ); + + // This defines 'Debugger' in this Scratchpad; + // it doesn't actually start debugging anything. + addDebuggerToGlobal(globalThis); + + // Create a 'Debugger' instance. + var dbg = new Debugger; + + // Make the tab's top window a debuggee, and get a + // Debugger.Object referring to the window. + var windowDO = dbg.addDebuggee(tabs[0].content); + + // Get a Debugger.Object referring to the window's `report` + // function. + var reportDO = windowDO.getOwnPropertyDescriptor('report').value; + + // Set a breakpoint at the entry point of `report`. + reportDO.script.setBreakpoint(0, { + hit: function (frame) { + console.log('hit breakpoint in ' + frame.callee.name); + console.log('what = ' + frame.eval('what').return); + } + }); + + console.log('Finished setting breakpoint!'); + +|br| + +6. In the Scratchpad, ensure that no text is selected, and press the “Run” button. + + Now, click on the text that says “Click me!” in the web page. This runs the ``div`` element’s ``onclick`` handler. When control reaches the start of the ``report`` function, ``Debugger`` calls the breakpoint handler’s ``hit`` method, passing a ``Debugger.Frame`` instance. The ``hit`` method logs the breakpoint hit to the browser content toolbox’s console. Then it evaluates the expression ``what`` in the given stack frame, and logs its result. The toolbox’s console now looks like this: + + .. image:: console.png + :alt: The breakpoint handler’s console output + :class: center + + You can also click on the text that says “Or me!”, to see ``report`` called from a different handler. + + If ``Debugger`` is unable to find the ``report`` function, or the console output does not appear, evaluate the expression ``tabs[0].content.document.location`` in the console to make sure that ``tabs[0]`` indeed refers to the HTML file you visited. If you have more than one tab visiting a ``file:`` URL, they all share a single content process, so you may need to use a different element of the array as the debuggee. + +|br| + +7. Press “Run” in the Scratchpad again. Now, clicking on “Click me!” causes the breakpoint hit to be logged twice—one for each ``Debugger`` instance. + + Multiple ``Debugger`` instances can observe the same debuggee. Re-running the code in the Scratchpad creates a fresh ``Debugger`` instance, adds the same web page as its debuggee, and then sets a new breakpoint. When you click on the ``div`` element, both ``Debugger's`` breakpoints are hit, and both handlers run. + + This shows how any number of ``Debugger``-based tools can observe a single web page simultaneously. In fact, you can use the Browser Content Toolbox’s Debugger panel to set its own breakpoint in ``report``, and it will trigger along with the first two. Keep in mind, however, that when multiple Debuggers share a debuggee, the order in which their handlers run is not specified. If more than one tool tries to influence the debuggee’s behavior, their combined behavior could be unpredictable. + +|br| + +8. Close the web page and the Browser Content Toolbox. + + Since both the Scratchpad’s global object and the debuggee window are now gone, the ``Debugger`` instances will be garbage collected, since they can no longer have any visible effect on Firefox’s behavior. The ``Debugger`` API tries to interact with garbage collection as transparently as possible; for example, if both a ``Debugger.Object`` instance and its referent are not reachable, they will both be collected, even while the ``Debugger`` instance to which the shadow belonged continues to exist. + + +Source Metadata +--------------- + +Generated from file: + js/src/doc/Debugger/Tutorial-Breakpoint.md +Watermark: + sha256:c8dd4bb69972b58e59fcbe6870499206463a5e330fda25f1214893595a1c01d0 +Changeset: + `ffa775dd5bd4 <https://hg.mozilla.org/mozilla-central/rev/ffa775dd5bd4>`_ |