diff -r 000000000000 -r 6474c204b198 js/src/doc/Debugger/Debugger.Frame.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/src/doc/Debugger/Debugger.Frame.md Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,421 @@ +# Debugger.Frame + +A `Debugger.Frame` instance represents a [visible stack frame][vf]. 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 [`Debugger`][debugger-object] 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 [`Debugger`][debugger-object] instance is debugging the +same code, each [`Debugger`][debugger-object] gets a separate +`Debugger.Frame` instance for a given frame. This allows the code using +each [`Debugger`][debugger-object] 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. + +Stack frames that represent the control state of generator-iterator objects +behave in a special way, described in [Generator Frames][generator] below. + + +## Visible Frames + +When inspecting the call stack, [`Debugger`][debugger-object] 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 [`Debugger`][debugger-object] does reveal +visible frames. + +A frame is a visible frame if any of the following are true: + +* it is running [debuggee code][dbg code]; + +* its immediate caller is a frame running debuggee code; or + +* it is a [`"debugger"` frame][inv fr], + representing the continuation of debuggee code invoked by the debugger. + +The "immediate caller" rule means that, when debuggee code calls a +non-debuggee function, 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.) + + +## 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 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][cv] 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). + + * `"debugger"`: a frame for a call to user code invoked by the debugger + (see the `eval` method below). + +`this` +: The value of `this` for this frame (a debuggee value). + +`older` +: The next-older visible frame, in which control will resume when this + frame completes. If there is no older frame, this is `null`. (On a + suspended generator frame, the value of this property is `null`; see + [Generator Frames][generator].) + +`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 (or, in the case of generator-iterator objects, has not yet + finished its iteration); false if it has completed execution or been + popped in some other way. + +`script` +: The script being executed in this frame (a [`Debugger.Script`][script] + 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`. + +`environment` +: The lexical environment within which evaluation is taking place (a + [`Debugger.Environment`][environment] 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][rv] 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 [`Debugger`][debugger-object] 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][cv] indicating how this frame's execution + completed, and providing this `Debugger.Frame` instance as the `this` + value. The function should return a [resumption value][rv] indicating + how execution should proceed. On newly created frames, this property's + value is `undefined`. + + 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. + + (Not yet implemented.) When a generator frame yields a value, + SpiderMonkey calls its `Debugger.Frame` instance's `onPop` handler + method, if present, passing a `yield` resumption value; however, the + `Debugger.Frame` instance remains live. + + If multiple [`Debugger`][debugger-object] 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 property is ignored on `"debugger"` frames. + +`onResume` +: This property must be either `undefined` or a function. If it is a + function, SpiderMonkey calls it if the current frame is a generator + frame whose execution has just been resumed. The function should return + a [resumption value][rv] indicating how execution should proceed. On + newly created frames, this property's value is `undefined`. + + If the program resumed the generator by calling its `send` method and + passing a value, then value is that value. Otherwise, + value is `undefined`. + + +## 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. + +eval(code, [options]) +: Evaluate code in the execution context of this frame, and return + a [completion value][cv] describing how it completed. Code is a + string. If this frame's `environment` property is `null`, throw a + `TypeError`. All extant handler methods, breakpoints, watchpoints, and + so on remain active during the call. This function follows the + [invocation function conventions][inv fr]. + + 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 + [`Debugger.Frame.prototype.eval`][fr eval], described above. + +pop(completion) (future plan) +: Pop this frame (and any younger frames) from the stack as if this frame + had completed as specified by the completion value completion. + + Note that this does not resume the debuggee's execution; it + merely adjusts the debuggee's state to what it would be if this frame's + execution had completed. The debuggee will only resume execution when + you return from the handler method that brought control to the debugger + originally. + + This cannot remove any `"call"` frames for calls to host functions from + the stack. (We might be able to make this work eventually, but it will + take some cleverness.) + +replaceCall(function, this, arguments) (future plan) +: Pop any younger frames from the stack, and then change this frame into + a frame for a call to function, with the given this value + and arguments. 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 should be an array of debuggee values. This frame must + be a `"call"` frame. + + This can be used as a primitive in implementing some forms of a "patch + and continue" debugger feature. + + Note that this does not 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. The debuggee will only resume execution + when you return from the handler method that brought control to the + debugger originally. + + Like `pop`, this cannot remove `"call"` frames for calls to host + functions from the stack. + + +## Generator Frames + +Not all behavior described in this section has been implemented +yet. + +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 `yield` produces a +generator-iterator object, as does evaluating a generator expression like +`(i*i for each (i in [1,2,3]))`. + +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 `next` 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. + +A `Debugger.Frame` instance representing a generator frame differs from an +ordinary stack frame as follows: + +* A generator frame's `generator` property is true. + +* A generator frame disappears from the stack each time the generator + yields a value and is suspended, and reappears atop the stack when it is + resumed to produce the generator's next value. The same `Debugger.Frame` + instance refers to the generator frame until it returns, throws an + exception, or is terminated. + +* A generator frame's `older` property refers to the frame's continuation + frame while the generator is running, and is `null` while the generator + is suspended. + +* A generator frame's `depth` property reflects the frame's position on + the stack when the generator is resumed, and is `null` while the + generator is suspended. + +* A generator frame's `live` property remains true until the frame + returns, throws an exception, or is terminated. Thus, generator frames + can be live while not present on the stack. + +The other `Debugger.Frame` methods and accessor properties work as +described on generator frames, even when the generator frame is suspended. +You may examine a suspended generator frame's variables, and use its +`script` and `offset` members to see which `yield` it is suspended at. + +A `Debugger.Frame` instance referring to a generator-iterator frame has a +strong reference to the generator-iterator object; the frame (and its +object) will live as long as the `Debugger.Frame` instance does. However, +when the generator function returns, throws an exception, or is terminated, +thus ending the iteration, the `Debugger.Frame` instance becomes inactive +and its `live` property becomes `false`, just as would occur for any other +sort of frame that is popped. A non-live `Debugger.Frame` instance no +longer holds a strong reference to the generator-iterator object.