Confirmed users
497
edits
(Move "Source Locations" and "Lexical Environments" into their own top-level sections at the top.) |
(Add example of lexical environment.) |
||
Line 344: | Line 344: | ||
{ "from":<i>env-actor</i>, "error":"immutable-binding", "message":<i>message</i> } | { "from":<i>env-actor</i>, "error":"immutable-binding", "message":<i>message</i> } | ||
== Lexical Environment Examples == | |||
For example, if we have the following JavaScript code: | |||
function f(x) { | |||
function g(y) { | |||
alert(x + y); | |||
} | |||
} | |||
we set a breakpoint on the line containing the call to <tt>alert</tt>, and then evaluate the expression: | |||
f("argument to f")("argument to g") | |||
then we would hit that breakpoint, eliciting a packet like the following: | |||
{ "from":<i>thread</i>, "type":"paused": "actor":<i>pause-actor</i>, | |||
"why":{ "type":"breakpoint", "actors":[<i>breakpoint-actor</i>] }, | |||
"frame":{ "actor":<i>frame-actor</i>, "depth":1, "id":1, | |||
"type":"call", "where": { "url":"sample.js", "line":3 }, | |||
"environment": { "type":"function", "actor":<i>g-frame-actor</i>, | |||
"function":{ "type":"object", "class":"Function", "actor":<i>g-actor</i> }, | |||
"function-name":"g", | |||
"bindings":{ "mutable": { "y":"argument to g" } }, | |||
"parent": { "type":"function", "actor":<i>f-frame-actor</i>, | |||
"function":{ "type":"object", "class":"Function", "actor":<i>f-actor</i> }, | |||
"function-name":"f", | |||
"bindings":{ "mutable": { "x":"argument to f" } }, | |||
"parent": { "type":"object", "actor":<i>global-code-actor</i>, | |||
"object":{ "type":"object", "class":"Global", | |||
"actor":<i>global-object-actor</i> } | |||
} | |||
} | |||
}, | |||
"callee":<i>g-actor</i>, "callee-name":"g", | |||
"this":{ "type":"object", "class":"Function", "actor":<i>g-actor</i> }, | |||
"arguments":["argument to g"] | |||
} | |||
} | |||
You can see here the three nested environment forms, starting with the <tt>environment</tt> property of the top stack frame, reported in the pause. | |||
= The Root Actor = | = The Root Actor = | ||
Line 409: | Line 451: | ||
* At no point may either client or server send an unbounded number of packets without receiving a packet from its counterpart. This avoids deadlock without requiring either side to buffer an arbitrary number of packets per actor. | * At no point may either client or server send an unbounded number of packets without receiving a packet from its counterpart. This avoids deadlock without requiring either side to buffer an arbitrary number of packets per actor. | ||
* In states where a transition can be initiated by either the debugger or the thread, it is always clear to the debugger which state the thread actually entered, and for what reason.<p>For example, if the debugger interrupts a running thread, it cannot be sure whether the thread stopped because of the interruption, paused of its own accord (to report a watchpoint hit, say), or exited. However, the next packet the debugger receives will either be "interrupted", "paused", or "exited", resolving the ambiguity.</p><p>Similarly, when the debugger attaches to a thread, it cannot be sure whether it has succeeded in attaching to the thread, or whether the thread exited before the "attach" packet arrived. However, in either case the debugger can expect a disambiguating response: if the attach suceeded, it receives an "attached" packet; and in the second case, it receives an "exit" packet.</p><p>To support this property, the thread ignores certain debugger packets in some states (the "interrupt" packet in the <b>Paused</b> and <b>Exited</b> states, for | * In states where a transition can be initiated by either the debugger or the thread, it is always clear to the debugger which state the thread actually entered, and for what reason.<p>For example, if the debugger interrupts a running thread, it cannot be sure whether the thread stopped because of the interruption, paused of its own accord (to report a watchpoint hit, say), or exited. However, the next packet the debugger receives will either be "interrupted", "paused", or "exited", resolving the ambiguity.</p><p>Similarly, when the debugger attaches to a thread, it cannot be sure whether it has succeeded in attaching to the thread, or whether the thread exited before the "attach" packet arrived. However, in either case the debugger can expect a disambiguating response: if the attach suceeded, it receives an "attached" packet; and in the second case, it receives an "exit" packet.</p><p>To support this property, the thread ignores certain debugger packets in some states (the "interrupt" packet in the <b>Paused</b> and <b>Exited</b> states, for example). These cases all handle situations where the ignored packet was preempted by some thread action.</p> | ||
Note that the rules here apply to the client's interactions with each thread actor separately. A client may send an "interrupt" to one thread actor while awaiting a reply to a request sent to a different thread actor. | Note that the rules here apply to the client's interactions with each thread actor separately. A client may send an "interrupt" to one thread actor while awaiting a reply to a request sent to a different thread actor. | ||
Line 511: | Line 553: | ||
The client stepped the thread from a "pre-throw" pause, and a catch clause has been found for the exception referred to by <i>grip</i>; control is stopped at the head of the catch clause, with catch variable bindings made. If the catch is conditional, control is at the beginning of the condition. | The client stepped the thread from a "pre-throw" pause, and a catch clause has been found for the exception referred to by <i>grip</i>; control is stopped at the head of the catch clause, with catch variable bindings made. If the catch is conditional, control is at the beginning of the condition. | ||
{ "type":uncaught", "exception":<i>grip</i> } | { "type":"uncaught", "exception":<i>grip</i> } | ||
The client stepped the thread from a "pre-throw" pause, and no catch clause was found for the exception. <i>Grip</i> is as above. <i>(I'm not sure which code the thread is executing at this point; we might as well reveal SpiderMonkey's natural behavior.)</i> | The client stepped the thread from a "pre-throw" pause, and no catch clause was found for the exception. <i>Grip</i> is as above. <i>(I'm not sure which code the thread is executing at this point; we might as well reveal SpiderMonkey's natural behavior.)</i> | ||
Line 637: | Line 679: | ||
{ "actor":<i>actor</i>, "depth":<i>depth</i>, "id":<i>id</i>, | { "actor":<i>actor</i>, "depth":<i>depth</i>, "id":<i>id</i>, | ||
"type":"global", "where":<i>location</i>, "environment" | "type":"global", "where":<i>location</i>, "environment":<i>environment</i> } | ||
where: | where: | ||
Line 654: | Line 696: | ||
"where":<i>location</i>, "environment",<i>environment</i>, | "where":<i>location</i>, "environment",<i>environment</i>, | ||
"callee":<i>callee</i>, "callee-name":<i>callee-name</i>, | "callee":<i>callee</i>, "callee-name":<i>callee-name</i>, | ||
"this" | "this":<i>this</i>, "arguments":<i>arguments</i> } | ||
where: | where: | ||
Line 675: | Line 717: | ||
"type":"host-call", | "type":"host-call", | ||
"callee":<i>callee</i>, "callee-name":<i>callee-name</i>, | "callee":<i>callee</i>, "callee-name":<i>callee-name</i>, | ||
"this" | "this":<i>this</i>, "arguments":<i>arguments</i> } | ||
where the properties are as defined above. (Compared to an ordinary call, the <tt>where</tt> and <tt>environment</tt> properties are missing.) | where the properties are as defined above. (Compared to an ordinary call, the <tt>where</tt> and <tt>environment</tt> properties are missing.) |