Debugger: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
(→‎Property Conventions: More monkey-patching friendliness.)
(Replace with a link to the new MDN page.)
 
(156 intermediate revisions by 3 users not shown)
Line 1: Line 1:
<i>This draft is being discussed in [https://bugzilla.mozilla.org/show_bug.cgi?id=636907 bug 636907]. The interface it describes is not stable.</i>
The documentation for the <code>Debugger</code> API has moved to the Mozilla Developer Network: https://developer.mozilla.org/en-US/docs/Tools/Debugger-API
 
The Debug object provides functions for debugging code running in a separate compartment. You can provide functions for SpiderMonkey to call when events like steps, calls, and breakpoint hits occur in the debuggee, examine the debuggee's stack frames, and inspect and manipulate the debuggee's objects.
 
Debug object event hook functions run in the same thread as the debuggee, on the same stack: when the event occurs, the debuggee pauses while your hook functions run, and resumes (unless you say otherwise) when your functions return.
 
The debugger and debuggee must be in separate compartments. Your hook functions run in the debugger's compartment. SpiderMonkey mediates their access to the debuggee's objects, and prevents the debuggee from accessing the debugger's objects at all.
The Debug object provides objects representing the debuggee's stack frames, scripts, and other internal interpreter structures, for your hook functions to examine and manipulate.
 
== Debuggee Values ==
 
The <code>Debug</code> object follows certain conventions to help debuggers safely inspect and modify the debuggee's objects and values. Primitive values are passed freely between debugger and debuggee; copying or wrapping is handled transparently. Objects received from the debuggee (including host objects like DOM elements) are fronted in the debugger by <code>Debug.Object</code> instances, which provide reflection-oriented methods for inspecting their referents; see <code>Debug.Object</code>, below.
 
Of the debugger's objects, only <code>Debug.Object</code> instances may be passed to the debuggee: when this occurs, the debuggee receives the <code>Debug.Object</code>'s referent, not the Debug.Object instance itself.
 
In the descriptions below, the term "debuggee value" means either a primitive value or a <code>Debug.Object</code> instance; it is a value that might be received from the debuggee, or that could be passed to the debuggee.
 
== Property Conventions ==
 
The <code>Debug</code> interface creates various sorts of objects to present the debuggee's state to the debugger. These objects' properties follow some conventions:
<ul>
<li>Properties described here are configurable. This applies to both "own" and prototype properties, and to both methods and data properties.
<li>Non-method properties are generally non-writable value properties. Since they are configurable, they can be made writable, but assigning to them has no effect on the debuggee unless stated otherwise.
<li>Instances and prototypes are extensible; you can add your own properties and methods to them.
</ul>
 
== Beginning to Debug ==
 
To begin debugging another compartment's code, create a Debug object for the debuggee compartment. You can use this object to install hook functions, set breakpoints, and so on.
 
<dl>
<dt>Debug(<i>object</i>)
<dd>Create a debugger object debugging <i>object</i>'s compartment. <i>Object</i> is typically a global object, but can be any JavaScript object from the debuggee's compartment. This debugger object is initially enabled; see the <code>enabled</code> property, below.
 
The <i>object</i> must be in a different compartment than the calling code, and debugger/debuggee compartments may not form a cycle. <i>Object</i>'s compartment must not be in use by another thread while this call runs.
</dl>
 
=== Properties of Debug instances ===
 
<dl>
<dt>enabled
<dd>A boolean value indicating whether this <code>Debug</code> instance's hooks, breakpoints, and watchpoints are currently enabled. It is an accessor property with a getter and setter: assigning to it enables or disables this <code>Debug</code> instance; reading it produces true if the instance is enabled, or false otherwise.
 
This property gives debugger code a single point of control for disentangling itself from the debuggee, regardless of what sort of events or hooks or "points" we add to the interface.
</dl>
 
=== Properties of the Debug Prototype Object ===
 
The functions described below may only be called with a <code>this</code> value referring to a <code>Debug</code> instance; they may not be used as methods of other kinds of objects.
 
<dl>
<dt>setHooks(<i>hooks</i>)
<dd>Use the functions in <i>hooks</i> to handle events occurring in this debuggee. <i>Hooks</i> should be an object; each property should be named after a debugging event, and its value should be a function SpiderMonkey should call when the named event occurs. See below for descriptions of specific debugging hooks.
 
This removes all previously registered hooks; after the call, only the hooks mentioned in <i>hooks</i> are in force. Thus, a call like <code>setHooks({})</code> removes all debugging hooks.
 
Hook function calls are cross-compartment, same-thread calls. Hook functions run in the thread in which the event occurred, not in the thread that registered the hooks. (It is your responsibility to ensure that two threads don't try to run in the same compartment). Hook functions run in the compartment to which they belong, not in the debuggee's compartment.
 
Rather than keeping a reference to the <i>hooks</i> object and consulting it when each event occurs, this function copies the hook functions present in the <i>hooks</i> object, and stores them internally. Once the call to <code>setHooks</code> has returned, changes to the <i>hooks</i> object have no effect on the debugger hooks in force.
 
Note that if the debugger object is disabled, hook functions are not called; see the <code>enabled</code> property.
 
<dt>getHooks()
<dd>Return an object holding all the event hooks currently in force. The returned object is suitable for use with <code>setHooks</code>.
 
<dt>setBreakpoint(<i>script</i>, <i>offset</i>, <i>handler</i>)
<dd>Set a breakpoint at the bytecode instruction at <i>offset</i> in <i>script</i>, reporting hits to the function <i>handler</i>. This call replaces any existing breakpoint at the given location.
 
When execution reaches the given instruction, SpiderMonkey calls <i>handler</i>, passing a <code>Debug.Frame</code> instance representing the currently executing stack frame. The handler method's return value determines how execution should continue:
<ul>
<li>If it returns true, execution continues normally.
<li>If it returns an object of the form <code>{ throw: <i>value</i> }</code>, then <i>value</i> is thrown as an exception from the current bytecode instruction. <i>value</i> must be a debuggee value.
<li>If it returns null, the calling code is terminated, as if it had been cancelled by the "slow script" dialog box.
</ul>
 
Breakpoint handler calls are cross-compartment, intra-thread calls: <i>handler</i> must be a function in the debugger's compartment (and thus calls to it take place in the debugger's compartment), and the call takes place in the same thread that hit the breakpoint.
 
The new breakpoint belongs to this <code>Debug</code> instance; disabling the <code>Debug</code> instance disables this breakpoint.
 
(While a typical design would have debugger objects that represent breakpoints and handler functions whose behavior is driven by those objects, it seems practical in JavaScript to have the handler function play both roles, since it is itself an object. Other code can access function objects' properties, and the function's own code can find them by referring to the its own name, as in <code>function f() { ... f.x ... }</code>.)
 
<dt>clearBreakpoint(<i>script</i>, <i>offset</i>)
<dd>Remove any breakpoint set at <i>offset</i> in <i>script</i>.
 
<dt>clearAllBreakpoints([<i>script</i>])
<dd>Remove all breakpoints set using this <code>Debug</code> instance. If <i>script</i> is present and refers to a <code>Debug.Script</code> instance, remove all breakpoints set in that script.
 
<dt>setPropertyWatchpoint(<i>object</i>, <i>name</i>, <i>handler</i>) <i>(future plan)</i>
<dd>Set a watchpoint on the own property named <i>name</i> of the referent of the <code>Debug.Object</code> instance <i>object</i>, reporting events by calling <i>handler</i>'s methods. <i>Handler</i> may have the following methods, called under the given circumstances:
 
<dl>
<dt>add(<i>frame</i>, <i>descriptor</i>)
<dd>A property named <i>name</i> has been added to <i>object</i>'s referent. <i>Descriptor</i> is a property descriptor of the sort accepted by <code>Object.defineProperty</code>, giving the newly added property's attributes.
<dt>delete(<i>frame</i>)
<dd>A property named <i>name</i> has been deleted from <i>object</i>'s referent.
<dt>change(<i>frame</i>, <i>oldDescriptor</i>, <i>newDescriptor</i>)
<dd>The existing property named <i>name</i> on <i>object</i>'s referent has had its attributes changed from those given by <i>oldDescriptor</i> to those given by <i>newDescriptor</i>.
<dt>set(<i>frame</i>, <i>value</i>)
<dd>The property named <i>name</i> is about to have <i>value</i> assigned to it. The assignment has not yet taken place, so the debugger can use <i>getOwnPropertyDescriptor</i> to find the property's pre-assignment value (assuming it is not an accessor property). This call takes place whether the property is a data or accessor property, even if the property is not writable or lacks a setter. This call takes place even if the property is a value property and <i>value</i> is identical to its current value.
<dt>get(<i>frame</i>)
<dd>The property named <i>name</i> is about to be read. This call takes place whether the property is a data or accessor property, even if the property lacks a getter.
</dl>
 
In all cases, the method's <i>frame</i> argument is the current stack frame, whose code is about to perform the operation on the object being reported.
 
The handler method's return value determines how execution proceeds, as described below for the <code>interrupt</code> hook function. Furthermore, <code>set</code> may return an object of the form <code>{ value:<i>newValue</i> }</code>, indicating that the property should have <i>newValue</i> assigned to it instead of the <i>value</i> passed to <code>set</code>.
 
If a given method is absent from <i>handler</i>, then events of the given sort are ignored. The watchpoint retains a reference to the <i>handler</i> object itself, and consults its properties each time an event occurs, so adding methods to or removing methods from <i>handler</i> after setting the watchpoint enables or disables reporting of the corresponding events.
 
Values passed to <i>handler</i>'s methods are debuggee values. Descriptors passed to <i>handler</i>'s methods are ordinary objects in the debugger's compartment, except for <code>value</code>, <code>get</code>, and <code>set</code> properties in descriptors, which are debuggee values.
 
Watchpoint handler calls are cross-compartment, intra-thread calls: <i>handler</i> must be a function in the debugger's compartment (and thus calls to it take place in the debugger's compartment), and the call takes place in the same thread that changed the property.
 
The new watchpoint belongs to this <code>Debug</code> instance; disabling the <code>Debug</code> instance disables this watchpoint.
 
<dt>clearPropertyWatchpoint(<i>object</i>, <i>name</i>) <i>(future plan)</i>
<dd>Remove any watchpoint set on the own property named <i>name</i> of the referent of the <code>Debug.Object</code> instance <i>object</i>.
 
<dt>clearAllWatchpoints() <i>(future plan)</i>
<dd>Clear all watchpoints owned by this <code>Debug</code> instance.
 
</dl>
 
=== Debugging hooks ===
 
For each debugging hook, we give the name of the hook and the arguments passed to its handler function, and describe the circumstances under which SpiderMonkey calls it.
 
<dl>
<dt>interrupt(<i>frame</i>)
<dd>A bytecode instruction is about to execute in the stack frame represented by <i>frame</i>, a <code>Debug.Frame</code> instance. Naturally, <i>frame</i> is the youngest debuggee frame.
 
This hook function's return value determines how execution should continue:
<ul>
<li>If it returns true, execution continues normally.
<li>If it returns an object of the form <code>{ throw: <i>value</i> }</code>, then <i>value</i> is thrown as an exception from the current bytecode instruction. <i>value</i> must be a debuggee value.
<li>If it returns an object of the form <code>{ return: <i>value</i> }</code>, then <i>value</i> is immediately returned as the current value of the function. <i>value</i> must be a debuggee value.
<li>If it returns null, the calling code is terminated, as if it had been cancelled by the "slow script" dialog box.
<li>If the hook throws an exception, ... well, we're in trouble. That's an error in the debugger which should be reported somehow, but certainly not handled by the debuggee.
</ul>
 
Some notes about the interrupt hook:
<ul>
<li>If a script object has not had its <code>singleStepMode</code> flag set, SpiderMonkey may not call the <code>interrupt</code> hook function when running the script.
<li>Depending on whether the code has been compiled or is being run by the bytecode interpreter, SpiderMonkey may not call the <code>interrupt</code> on every bytecode instruction. However, it will call the <code>interrupt</code> at least every time the source code line and JavaScript statement associated with the current bytecode changes. (That is, multi-line statements may only receive a single interrupt, not one interrupt for each line the statement occupies.)
</ul>
 
<dt>newScript(<i>script</i>, [<i>function</i>])
<dd>New code, represented by the <code>Debug.Script</code> instance <i>script</i>, has been loaded into the debuggee's compartment. If the new code is part of a function, <i>function</i> is a Debug.Object reference to the function object. (Not all code is part of a function; for example, the code appearing in a <code>&lt;script&gt;</code> tag that is outside of any functions defined in that tag would be passed to <code>newScript</code> without an accompanying <i>function</i> argument.)
 
Note that <i>script</i> may be a temporary script, created for a call to <i>eval</i> and destroyed when its execution is complete.
 
<dt>destroyScript(<i>script</i>)
<dd>SpiderMonkey has determined that <i>script</i> will no longer be needed, and is about to throw it away. The garbage collector may have found that the script is no longer in use, or perhaps <i>eval</i> has finished executing the script, and is about to destroy it. In any case, operations on <i>script</i> after this hook function returns will throw an error.
 
<dt>debuggerHandler(<i>frame</i>)
<dd>The debuggee has executed a <i>debugger</i> statement in <i>frame</i>. This hook function's return value determines how execution proceeds, as for the <i>interrupt</i> hook function.
 
<dt>sourceHandler(<i>ASuffusionOfYellow</i>)
<dd>This hook function is never called. If it is ever called, a contradiction has been proven, and the debugger is free to assume that everything is true.
 
<dt>enterFrame(<i>frame</i>, <i>call</i>)
<dd>The stack frame <i>frame</i> is about to begin executing code. (Naturally, <i>frame</i> is currently the youngest debuggee frame.) If <i>call</i> is true, it is a function call; if <i>call</i> is false, it is global or eval code.
 
If this hook function returns a function <i>f</i>, SpiderMonkey will call <i>f</i> when execution of <i>frame</i> completes, passing one argument indicating how it completed.
<ul>
<li>If the argument is of the form <code>{ return: <i>value</i> }</code>, then the code completed normally, yielding <i>value</i>. <i>Value</i> is a debuggee value.
<li>If the argument is of the form <code>{ throw: <i>value</i> }</code>, then the code threw <i>value</i> as an exception. <i>Value</i> is a debuggee value.
<li>If the argument is <code>null</code>, then the code was terminated, as if by the "slow script" dialog box.
</ul>
 
<dt>throw(<i>frame</i>, <i>value</i>)
<dd>The code running in <i>frame</i> is about to throw <i>value</i> as an exception. The value this hook function returns determines how execution proceeds, as for <i>interrupt</i>.
 
<dt>error(<i>frame</i>, <i>report</i>)
<dd>SpiderMonkey is about to report an error in <i>frame</i>. <i>Report</i> is an object describing the error, with the following properties:
 
<dl>
<dt>message
<dd>The fully formatted error message.
<dt>file
<dd>If present, the source file name, URL, etc. (If this property is present, the <i>line</i> property will be too, and vice versa.)
<dt>line
<dd>If present, the source line number at which the error occurred.
<dt>lineText
<dd>If present, this is the source code of the offending line.
<dt>offset
<dd>The index of the character within lineText at which the error occurred.
<dt>warning
<dd>Present and true if this is a warning; absent otherwise.
<dt>strict
<dd>Present and true if this error or warning is due to the strict option (not to be confused with ES strict mode)
<dt>exception
<dd>Present and true if an exception will be thrown; absent otherwise.
<dt>arguments
<dd>An array of strings, representing the arguments substituted into the error message.
</dl>
</dl>
 
== Debug.Frame ==
 
A <code>Debug.Frame</code> instance represents a debuggee stack frame. Given a <code>Debug.Frame</code> 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.
 
SpiderMonkey creates instances of <code>Debug.Frame</code> as needed in two situations: when it calls a hook function that expects a frame as an argument, and when the debugger reads an existing frame's <code>older</code> property. SpiderMonkey creates only one <code>Debug.Frame</code> instance for a given debuggee frame; every hook function called while the debuggee is running in a given frame receives the same frame object; and 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 <code>==</code> to decide whether two expressions refer to the same frame, and so on.
 
A <code>Debug.Frame</code> instance is a weak reference to the frame; once the debuggee destroys the frame (by returning from the function, completing the <code>eval</code> call, freeing the generator-iterator object, or taking some similar action), the <code>Debug.Frame</code> instance becomes inactive: its <code>live</code> property becomes <code>false</code>, its properties become undefined, and calls to its methods throw exceptions. (Note that this means that debugger code can be affected by the garbage collector, since debugger code can notice when <code>Debug.Frame</code> instances die.)
 
=== Properties of Debug.Frame instances ===
 
A <code>Debug.Frame</code> instance has the following properties:
 
<dl>
<dt>type
<dd>A string describing what sort of frame this is:
<ul>
<li><code>"call"</code>: a frame running a function call.
<li><code>"eval"</code>: a frame running code passed to <code>eval</code>.
<li><code>"global"</code>: a frame running global code (JavaScript that is neither of the above)
<li><code>"host"</code>: a frame for a call to a host function (I'm not sure if we can obtain these)
<li><code>"debugger"</code>: a frame for a call to user code invoked by the debugger (see the <code>eval</code> method below)
<li><code>"dummy"</code>: a frame pushed for stupid people (rather&mdash;I don't know what this is)
</ul>
 
<dt>older
<dd>The next-older frame, in which control will resume when this frame completes.
 
<dt>depth
<dd>The depth of this frame, counting from oldest to youngest; the oldest frame has a depth of zero.
 
<dt>callee
<dd>The function whose application created this frame. Present only on <code>"call"</code> and <code>"host"</code> frames.
 
<dt>generator
<dd>True if this frame is a generator frame, false otherwise. Present only on frames whose type is <code>"call"</code>.
 
<dt>constructing
<dd>True if this frame is for a function called as a constructor, false otherwise. Present on <code>"call"</code> and <code>"host"</code> frames.
 
<dt>script
<dd>The script being executed in this frame (a <code>Debug.Script</code> instance). Present on <code>"call"</code>, <code>"eval"</code>, and <code>"global"</code> frames. On <code>"call"</code> frames, this is equal to <code>callee.script</code>.
 
<dt>offset
<dd>The offset of the bytecode instruction currently being executed in <code>script</code>. Present when <code>script</code> is. This is an accessor property with a getter, but no setter.
 
<dt>environment
<dd>The lexical environment within which evaluation is taking place (a <code>Debug.Object</code> instance). Present on <code>"call"</code>, <code>"eval"</code>, and <code>"global"</code> frames.
 
<dt>this
<dd>The value of <code>this</code> for the current frame (a debuggee value). Present on <code>"call"</code>, <code>"eval"</code>, and <code>"host"</code> frames. This is an accessor property with a getter, but no setter.
 
<dt>arguments
<dd>The arguments passed to the current frame, as an array of debuggee values. (The array itself is an ordinary array in the debugger compartment.) Present on <code>"call"</code>, <code>"eval"</code>, and <code>"host"</code> frames.
 
<dt>live
<dd>True if the frame this <code>Debug.Frame</code> instance refers to still exists in the debuggee; false if it has been destroyed.
</dl>
 
=== Properties of the Debug.Frame Prototype Object ===
 
The functions described below may only be called with a <code>this</code> value referring to a <code>Debug.Frame</code> instance; they may not be used as methods of other kinds of objects.
 
<dl>
<dt>eval(<i>code</i>)
<dd>Begin evaluating <i>code</i> in the scope of this frame. <i>Code</i> is a string. This pushes a <code>"debugger"</code> frame on the debuggee's stack, evaluates <i>code</i> with all extant hook functions active, and returns a value of the sort passed to an <code>enterFrame</code> completion function describing how the code completed.
 
Note that, although this method mixes the debugger's own stack frames with the debuggee's, walking the stack only shows the debuggee's frames; the continuation of the debugger's call to this method, up to the debugging hook function call, is represented by a single <code>"debugger"</code> frame. The next younger frame is an <code>"eval"</code> frame running <i>code</i> itself.
 
<dt>finish(<i>result</i>) <i>(future plan)</i>
<dd>Pop this frame (and any younger frames) from the stack as if this frame had completed. <i>Result</i> is a value of the sort that the <code>interrupt</code> hook might return, indicating how execution should be prepared to continue.
 
Note that this does <i>not</i> resume the debuggee's execution; it merely adjusts the debuggee's state to what it would be if this frame's execution had completed. You must return <code>true</code> from the hook function to resume execution in that state.
 
This cannot remove any <code>"host"</code> frames (calls through C++) from the stack. (We might be able to make this work eventually, but it will take some cleverness.)
 
<dt>restart(<i>function</i>, <i>this</i>, <i>arguments</i>) <i>(future plan)</i>
<dd>Pop any younger frames from the stack, and then change this frame into a frame for a call to <i>function</i>, with the given <i>this</i> value and <i>arguments</i>. <i>This</i> should be a debuggee value, or <code>{ asConstructor: true }</code> to invoke <i>function</i> as a constructor, in which case SpiderMonkey provides an appropriate <code>this</code> value itself. <i>Arguments</i> should be an array of debuggee values. This frame must be a <code>"call"</code> frame.
 
This can be used as a primitive in implementing some forms of a "patch and continue" debugger feature.
 
Note that this does <i>not</i> resume the debuggee's execution; it merely adjusts the debuggee's state to what it would be if this frame were about to make this call. You must return <code>true</code> from the hook function to resume execution in that state.
 
Like <code>finish</code>, this cannot remove <code>"host"</code> frames from the stack.
</dl>
 
=== Generator Frames ===
 
SpiderMonkey supports generator-iterator objects, which produce a series of values by repeatedly suspending the execution of a function or expression. For example, calling a function that uses <code>yield</code> produces a generator-iterator object, as does evaluating a generator expression like <code>(i*i for each (i in [1,2,3]))</code>.
 
A generator-iterator object refers to a stack frame with no fixed continuation frame. While the generator's code is running, its continuation is whatever frame called its <code>next</code> method; while the generator is suspended, it has no particular continuation frame; and when it resumes again, the continuation frame for that resumption could be different from that of the previous resumption.
 
When you use the <code>Debug</code> object to inspect a program that is running a generator frame, that frame appears on the stack like any other call frame, except that its <code>generator</code> property is <code>true</code>. Such a frame will disappear from the stack when it is suspended, and reappear (possibly with a different <code>older</code> frame and <code>depth</code> value) each time it is resumed.
 
== Debug.Script ==
 
A <code>Debug.Script</code> instance refers to a sequence of bytecode in the debuggee; it is the JavaScript-level presentation of a JSAPI <code>JSScript</code> object. Each of the following is represented by single JSScript object:
<ul>
<li>The body of a function&mdash;that is, all the code in the function that is not contained within some nested function.
<li>The code passed to a single call to <code>eval</code>, excluding the bodies of any functions that code defines.
<li>The contents of a <code>&lt;script&gt;</code> element.
<li>A DOM event handler, whether embedded in HTML or attached to the element by other JavaScript code.
<li>Code appearing in a <code>javascript:</code> URL.
</ul>
 
The Debug interface constructs <code>Debug.Script</code> objects as script objects are uncovered by the debugger: via the <code>newScript</code> hook; via <code>Debug.Frame</code>'s <code>script</code> properties; via the <code>functionScript</code> method of <code>Debug.Object</code> instances; and so on. It constructs exactly one <code>Debug.Script</code> instance for each underlying script object; debugger code can add its own properties to a script object and expect to find them later, use <code>==</code> to decide whether two expressions refer to the same script, and so on.
 
A <code>Debug.Script</code> instance is a weak reference to a JSScript object; it does not protect the script it refers to from being freed or garbage collected. When SpiderMonkey decides to free the script, it calls the <code>destroyScript</code> debugger hook function to let the debugger know. Once that call has returned, the <code>Debug.Script</code> object's <code>live</code> property becomes false, its properties become undefined, and calls to its methods throw exceptions. (Note that this means that debugger code can be affected by the garbage collector, since debugger code can notice when <code>Debug.Script</code> instances die.)
 
The lifetime of a script depends on its origin. A function script is shared by all closures produced for that function, and lives as long as there are live closures referring to it. An <code>eval</code> script lives until the call to <code>eval</code> completes. Debuggers should avoid depending on scripts' lifetimes after the stack frames, functions, and so on that own them have been destroyed.
 
=== Properties of Debug.Script instances ===
 
<dl>
<dt>url
<dd>The filename or URL from which this script's code was loaded.
 
<dt>startLine
<dd>The number of the line at which this script's code starts, within the file or document named by <code>url</code>.
 
<dt>length
<dd>The number of lines this script's code occupies, within the file or document named by <code>url</code>.
 
<dt>singleStepMode
<dd>True if executing this script will produce calls to the <code>Debug</code> instance's <code>interrupt</code> hook for each source line. This is an accessor property with a getter and setter; assigning a true value to this property enables single stepping mode for this script. The property reads true if single step mode mode is set, or false otherwise.
 
<dt>live
<dd>True if the script this <code>Debug.Script</code> instance refers to still exists in the debuggee; false if it has been destroyed.
</dl>
 
=== Properties of the Debug.Script Prototype Object ===
 
The functions described below may only be called with a <code>this</code> value referring to a <code>Debug.Script</code> instance; they may not be used as methods of other kinds of objects.
 
<dl>
<dt>decompile([<i>pretty</i>])
<dd>Return a string containing JavaScript source code equivalent to this script in its effect and result. If <i>pretty</i> is present and true, produce indented code with line breaks.
 
<dt>getAllOffsets()
<dd>Return an array <i>L</i> describing the relationship between bytecode instruction offsets and source code positions in this script. <i>L</i> is sparse, and indexed by source line number. If a source line number <i>line</i> has no code, then <i>L</i> has no <i>line</i> property. If there is code for <i>line</i>, then <code><i>L</i>[<i>line</i>]</code> 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:
  a=[]
  for (i=1; i < 10; i++)
    // It's hip to be square.
    a[i] = i*i;
 
Calling <code>getAllOffsets()</code> on that code might yield an array like this:
  [[0], [5, 20], , [10]]
 
This array indicates that:
<ul>
<li>the first line's code starts at offset 0 in the script;
<li>the <code>for</code> 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);
<li>the third line has no code;
<li>and the fourth line begins at offset 10.
</ul>
 
<dt>getLineOffsets(<i>line</i>)
<dd>Return an array of bytecode instruction offsets representing the entry points to source line <i>line</i>. If the script contains no executable code at that line, the array returned is empty.
 
<dt>getOffsetLine(<i>offset</i>)
<dd>Return the source code line responsible for the bytecode at <i>offset</i> in this script.
</dl>
 
== Debug.Object ==
 
A <code>Debug.Object</code> instance represents an object in the debuggee. Debugger code never accesses debuggee objects directly; instead, it operates on <code>Debug.Object</code> instances that refer to the debuggee objects. SpiderMonkey's compartment system ensures that this separation is respected.
 
A <code>Debug.Object</code> instance has reflection-oriented methods to inspect and modify its referent. The referent's properties do not appear directly as properties of the <code>Debug.Object</code> instance; the debugger can access them only through methods like <code>Debug.Object.prototype.getOwnPropertyDescriptor</code> and <code>Debug.Object.prototype.defineProperty</code>, ensuring that the debugger will not inadvertently invoke the referent's getters and setters.
 
SpiderMonkey creates exactly one <code>Debug.Object</code> instance for each debuggee object it presents to the debugger: if the debugger encounters the same object through two different routes (perhaps two functions are called on the same object), SpiderMonkey presents the same <code>Debug.Object</code> instance to the debugger each time. This means that the debugger can use the <code>==</code> operator to recognize when two <code>Debug.Object</code> instances refer to the same debuggee object, and place its own properties on a <code>Debug.Object</code> instance to store metadata about particular debuggee objects.
 
While most <code>Debug.Object</code> instances are created by SpiderMonkey in the process of exposing debuggee's behavior and state to the debugger, the debugger can apply the <code>Debug.Object</code> constructor to its own objects, to copy them into the debuggee; see the description of the <code>Debug.Object</code> constructor below.
 
<code>Debug.Object</code> instances protect their referents from the garbage collector; as long as the <code>Debug.Object</code> instance is live, the referent remains live. Garbage collection has no debugger-visible effect on <code>Debug.Object</code> instances.
 
=== The Debug.Object constructor ===
 
When called via a <code>new</code> expression, the <code>Debug.Object</code> constructor takes one argument, an object in the debugger's compartment, and applies the HTML5 "structured cloning" algorithm to copy the object into the debuggee's compartment. It then returns a <code>Debug.Object</code> instance referring to the copy. It is an error to apply <code>Debug.Object</code> to a primitive value via a <code>new</code> expression.
 
When applied as a function, <code>Debug.Object</code> behaves as above, except that primitive values are returned unchanged (although possibly wrapped, in an ordinary cross-compartment wrapper). This allows the debugger to use <code>Debug.Object</code> as a generic "debugger value to debuggee value" conversion function.
 
=== Properties of the Debug.Object constructor ===
 
<dl>
<dt>create(<i>prototype</i>, [<i>properties</i>])
<dd>Create a new object in the debuggee's compartment, and return a <code>Debug.Object</code> referring to it. The new object's prototype is <i>prototype</i>; <i>prototype</i> must be an object. The new object's properties are as given by <i>properties</i>, as if it were passed to the standard <code>Object.defineProperties</code> function.
</dl>
 
=== Properties of the Debug.Object prototype ===
 
The functions described below may only be called with a <code>this</code> value referring to a <code>Debug.Object</code> instance; they may not be used as methods of other kinds of objects. The descriptions use "referent" to mean "the referent of this <code>Debug.Object</code> instance".
 
<dl>
<dt>getPrototype()
<dd>Return the referent's prototype (as a new <code>Debug.Object</code> instance), or <code>null</code> if it has no prototype.
 
<dt>getClass()
<dd>Return a string naming the ECMAScript <code><nowiki>[[Class]]</nowiki></code> of the referent.
 
<dt>hasOwnProperty(<i>name</i>)
<dd>Return true if the referent has an own property named <i>name</i>.
 
<dt>getOwnPropertyDescriptor(<i>name</i>)
<dd>Return a property descriptor for the property named <i>name</i> of the referent. (This function behaves like the standard <code>Object.getOwnPropertyDescriptor</code> function, except that the object being inspected is implicit; the property descriptor returned is in the debugger's compartment; and its <code>value</code>, <code>get</code>, and <code>set</code> properties, if present, are debuggee values.)
 
<dt>getOwnPropertyNames()
<dd>Return an array of strings naming all the referent's own properties, as if <code>Object.getOwnPropertyNames(<i>referent</i>)</code> had been called in the debuggee, and the result copied to the debugger's compartment.
 
<dt>defineProperty(<i>name</i>, <i>attributes</i>)
<dd>Define a property on the referent named <i>name</i>, as described by the property descriptor <i>descriptor</i>. Any <code>value</code>, <code>get</code>, and <code>set</code> properties of <i>attributes</i> must be debuggee values. (This function behaves like <code>Object.defineProperty</code>, except that the target object is implicit, and in a different compartment from the function and descriptor.)
 
<dt>defineProperties(<i>properties</i>)
<dd>Add the properties given by <i>properties</i> to the referent. (This function behaves like <code>Object.defineProperties</code>, except that the target object is implicit, and in a different compartment from the <i>properties</i> argument.)
 
<dt>deleteProperty(<i>name</i>)
<dd>Remove the referent's property named <i>name</i>. Return true if the property was successfully removed, or if the referent has no such property. Return false if the property is non-configurable.
 
<dt>seal()
<dd>Prevent properties from being added to or deleted from the referent. Return this <code>Debug.Object</code> instance. (This function behaves like the standard <code>Object.seal</code> function, except that the object to be sealed is implicit and in a different compartment from the caller.)
 
<dt>freeze()
<dd>Prevent properties from being added to or deleted from the referent, and mark each property as non-writable. Return this <code>Debug.Object</code> instance. (This function behaves like the standard <code>Object.freeze</code> function, except that the object to be sealed is implicit and in a different compartment from the caller.)
 
<dt>preventExtensions()
<dd>Prevent properties from being added to the referent. (This function behaves like the standard <code>Object.preventExtensions</code> function, except that the object to operate on is implicit and in a different compartment from the caller.)
 
<dt>isSealed()
<dd>Return true if the referent is sealed&mdash;that is, if it is not extensible, and all its properties have been marked as non-configurable. (This function behaves like the standard <code>Object.isSealed</code> function, except that the object inspected is implicit and in a different compartment from the caller.)
 
<dt>isFrozen()
<dd>Return true if the referent is frozen&mdash;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 <code>Object.isFrozen</code> function, except that the object inspected is implicit and in a different compartment from the caller.)
 
<dt>isExtensible()
<dd>Return true if the referent is extensible&mdash;that is, if it can have new properties defined on it. (This function behaves like the standard <code>Object.isExtensible</code> function, except that the object inspected is implicit and in a different compartment from the caller.)
 
<dt>isFunction()
<dd>Return true if the referent has a <code><nowiki>[[Call]]</nowiki></code> internal method.
 
<dt>getFunctionName()
<dd>If the referent is a named function, return its name. If the referent is an anonymous function, return <code>null</code>. If the referent is not a function, throw a <code>TypeError</code>.
 
<dt>getFunctionParameterNames()
<dd>If the referent is a function, return the names of its parameters as an array of strings. If the referent is not a function, throw a <code>TypeError</code>.
 
<dt>getFunctionScript()
<dd>If the referent is a function, return its script, as a <code>Debug.Script</code> instance. If the referent is not a function, throw a <code>TypeError</code>.
 
<dt>getFunctionScope()
<dd>If the referent is a function, return a <code>Debug.Object</code> instance referring to the lexical environment enclosing the function when it was created. If the referent is not a function, throw a <code>TypeError</code>.
 
<dt>decompile([<i>pretty</i>])
<dd>If the referent is a function, return the source code for a JavaScript function definition equivalent to this function in its effect and result, as a string. If the referent is not a function, throw a <code>TypeError</code>. If <i>pretty</i> is present and true, produce indented code with line breaks.
 
<dt>outerEnvironment()
<dd>If the referent is a lexical environment, return a <code>Debug.Object</code> instance referring to its enclosing lexical environment, or <code>null</code> if it is the outermost environment. If the referent is not a lexical environment, throw a <code>TypeError</code>.
 
<dt>referentToString()
<dd>Return a string representing the referent, showing its class and any other useful information, without invoking its <code>toString</code> or <code>toSource</code> methods, or running any other debuggee code. The specific string returned is unspecified. (It is better to add functions to <code>Debug.Object.prototype</code> that retrieve the information you need about the object than to depend on details of <code>safeToString</code>'s behavior.)
 
(Note that simply calling the <code>toString</code> method of a <code>Debug.Object</code> instance applies to instance itself, not its referent, and thus returns something like <code>"[Object Debug.Object]"</code>.)
 
</dl>

Latest revision as of 04:40, 16 April 2014

The documentation for the Debugger API has moved to the Mozilla Developer Network: https://developer.mozilla.org/en-US/docs/Tools/Debugger-API