Debugger: Difference between revisions

Jump to navigation Jump to search
4,813 bytes added ,  29 March 2011
Split out scope chain objects into their own reflection type, Debug.Environment. Other changes.
(→‎Properties: Make method properties writable.)
(Split out scope chain objects into their own reflection type, Debug.Environment. Other changes.)
Line 7: Line 7:
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 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.
The Debug object provides various sorts of objects representing the debuggee's state, which the debugger code can examine and manipulate:
<ul>
<li><code>Debug.Object</code> instances represent objects in the debuggee.
<li><code>Debug.Frame</code> instances represent debuggee stack frames.
<li><code>Debug.Script</code> instances represent the debuggee's code, whether it is a function body, code passed to <code>eval</code>, or a top-level script.
<li><code>Debug.Environment</code> instances represent the variable scopes in effect at different points in the debuggee's code.
</ul>


== General Conventions ==
== General Conventions ==
Line 45: Line 51:
As the debuggee runs, the <code>Debug</code> interface calls various debugger-provided handler functions to report the debuggee's behavior. Some of these calls can return a value indicating how the debuggee's execution should continue; these are called <i>resumption values</i>. A resumption value has one of the following forms:
As the debuggee runs, the <code>Debug</code> interface calls various debugger-provided handler functions to report the debuggee's behavior. Some of these calls can return a value indicating how the debuggee's execution should continue; these are called <i>resumption values</i>. A resumption value has one of the following forms:
<dl>
<dl>
<dt>true
<dt>undefined
<dd>The debuggee should continue execution normally.
<dd>The debuggee should continue execution normally.
<dt>{ return: <i>value</i> }
<dt>{ return: <i>value</i> }
Line 232: Line 238:
<li><code>"call"</code>: a frame running a function call.
<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>"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>"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>"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>"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>
</ul>


Line 260: Line 265:


<dt>environment
<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.
<dd>The lexical environment within which evaluation is taking place (a <code>Debug.Environment</code> instance). Present on <code>"call"</code>, <code>"eval"</code>, and <code>"global"</code> frames.


<dt>this
<dt>this
Line 280: Line 285:
<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>, and returns a [[#Completion Values|completion value]]. All extant hook functions, breakpoints, watchpoints, and so on remain active during the call.
<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>, and returns a [[#Completion Values|completion value]]. All extant hook functions, breakpoints, watchpoints, and so on remain active during the call.


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.
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; the next older frame is the frame that invoked the debugging hook.


<dt>evalWithBindings(<i>code</i>, <i>bindings</i>)
<dt>evalWithBindings(<i>code</i>, <i>bindings</i>)
Line 468: Line 473:


<dt>getFunctionScope()
<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>.
<dd>If the referent is a function, return a <code>Debug.Environment</code> instance representing 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>])
<dt>decompile([<i>pretty</i>])
Line 492: Line 497:
</ul>
</ul>
<i>This</i> must be a debuggee value, and <i>arguments</i> must be an array (in the debugger) of debuggee values. All extant hook functions, breakpoints, watchpoints, and so on remain active during the call. If the referent is not a function, throw a <code>TypeError</code>.
<i>This</i> must be a debuggee value, and <i>arguments</i> must be an array (in the debugger) of debuggee values. All extant hook functions, breakpoints, watchpoints, and so on remain active during the call. If the referent is not a function, throw a <code>TypeError</code>.
<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()
<dt>referentToString()
Line 501: Line 503:
(Note that simply calling the <code>toString</code> method of a <code>Debug.Object</code> instance applies to the instance itself, not its referent, and thus returns something like <code>"[object Debug.Object]"</code>.)
(Note that simply calling the <code>toString</code> method of a <code>Debug.Object</code> instance applies to the instance itself, not its referent, and thus returns something like <code>"[object Debug.Object]"</code>.)


</dl>
== Debug.Environment ==
A <code>Debug.Environment</code> instance represents a lexical environment, associating names with variables. "Call", "eval", and "global" stack frames have an associated environment object describing the variables in scope in that frame, and each function defined in JavaScript has an environment representing the scope the function has closed over.
SpiderMonkey <code>Debug.Environment</code> instances as needed as the debugger inspects stack frames and function objects; calling <code>Debug.Environment</code> as a function or constructor yields a <code>TypeError</code>.
SpiderMonkey creates exactly one <code>Debug.Environment</code> instance for each environment it presents to the debugger: if the debugger encounters the same environment through two different routes (perhaps two functions have closed over the same scope), SpiderMonkey presents the same <code>Debug.Environment</code> instance to the debugger each time. This means that the debugger can use the <code>==</code> operator to recognize when two <code>Debug.Environment</code> instances refer to the same scope in the debuggee, and place its own properties on a <code>Debug.Environment</code> instance to store metadata about particular scopes.
<code>Debug.Environment</code> instances protect their referents from the garbage collector; as long as the <code>Debug.Environment</code> instance is live, the referent remains live. Garbage collection has no debugger-visible effect on <code>Debug.Environment</code> instances.
=== Accessors for Debug.Environment Instances ===
The following are accessor properties on the <code>Debug.Environment</code> prototype object, and thus are visible on each <code>Debug.Environment</code> instance. Except where noted otherwise, each property has a getter, but no setter.
<dl>
<dt>type
<dd>The type of this environment object, one of the following values:
<ul>
<li>"declarative", indicating that the environment is a declarative environment record. Function calls, calls to <code>eval</code>, <code>let</code> blocks, <code>catch</code> blocks, and the like create declarative environment records.
<li>"object", indicating that the environment's bindings are the properties of an object. <code>With</code> statements create object environments; the global object and DOM elements appear in the scope chain via object environments.
</ul>
<dt>outerEnvironment
<dd>The environment that encloses this one, or <code>null</code> if this is the outermost environment. This is a accessor property with a getter, and no setter, inherited by instances.
<dt>object
<dd>A <code>Debug.Object</code> instance referring to the object whose properties this environment record reflects. If this is a declarative environment record, this accessor throws a <code>TypeError</code>.
</dl>
=== Properties of the Debug.Environment Prototype Object ===
The methods described below may only be called with a <code>this</code> value referring to a <code>Debug.Environment</code> instance; they may not be used as methods of other kinds of objects.
<dl>
<dt>boundIdentifiers()
<dd>Return an array of strings giving the names of the identifiers bound by this environment.
<dt>getVariableDescriptor(<i>name</i>)
<dd>Return an property descriptor describing the variable bound to <i>name</i> in this environment, of the sort returned by <code>getOwnPropertyDescriptor</code>.
If this is an object environment record, this simply returns the descriptor for the given property of the environment's object. If this is a declarative environment record, this returns a descriptor reflecting the binding's mutability as the descriptor's <code>writable</code> property, and its deletability as the descriptor's <code>configurable</code> property. All declarative environment record bindings are marked as <code>enumerable</code>. <i>(This isn't great; the semantics of variables in declarative enviroments don't really match those of properties, so returning descriptors that suggest that they do may be unhelpful.)</i>
If there is no variable named <i>name</i> in this environment, throw a <code>ReferenceError</code>.
This method does not search this environment's enclosing environments for bindings for <i>name</i>.
<dt>defineVariable(<i>name</i>, <i>descriptor</i>)
<dd>Create or reconfigure the variable named <i>name</i> bound in this environment according to <i>descriptor</i>. On success, return <code>undefined</code>; on failure, throw an appropriate exception.
<dt>findBinding(<i>name</i>)
<dd>Return a reference to the innermost environment, starting with this environment, that binds <i>name</i>, a string. If <i>name</i> is unbound in this environment, return <code>null</code>.
</dl>
</dl>
Confirmed users
497

edits

Navigation menu