Confirmed users
497
edits
(Add example of lexical environment.) |
(Move "Lexical Environments" back down towards the bottom.) |
||
| Line 222: | Line 222: | ||
<i>TODO: find function's source position</i> | <i>TODO: find function's source position</i> | ||
<i>TODO: get function's named arguments, in order</i> | |||
<i>TODO: descriptors for Harmony proxies</i> | <i>TODO: descriptors for Harmony proxies</i> | ||
| Line 269: | Line 271: | ||
= Source Locations = | = Source Locations = | ||
Descriptions of source locations (written as <i>location</i> in packet descriptions) can take one of the following forms: | Many packets refer to particular locations in source code: breakpoint requests specify where the breakpoint should be set; stack frames show the current point of execution; and so on. | ||
Descriptions of source code locations (written as <i>location</i> in packet descriptions) can take one of the following forms: | |||
{ "url":<i>url</i>, "line":<i>line</i>, "column":<i>column</i> } | { "url":<i>url</i>, "line":<i>line</i>, "column":<i>column</i> } | ||
| Line 290: | Line 294: | ||
refers to line 40 of the code passed to the call to eval occurring on line 30 of the code passed to the call to eval on line 20 of <tt>file:///home/example/sample.js</tt>. | refers to line 40 of the code passed to the call to eval occurring on line 30 of the code passed to the call to eval on line 20 of <tt>file:///home/example/sample.js</tt>. | ||
= The Root Actor = | = The Root Actor = | ||
| Line 764: | Line 672: | ||
<i>TODO: evaluate with given grips bound to given identifiers</i> | <i>TODO: evaluate with given grips bound to given identifiers</i> | ||
= Lexical Environments = | |||
A lexical environment (written as <i>environment</i> in packet descriptions) records the identifier bindings visible at a particular point in the program. An environment has one of the following forms: | |||
{ "type":"object", "actor":<i>actor</i>, "object":<i>object</i>, "parent":<i>parent-environment</i> } | |||
This represents a scope chain element whose identifier bindings reflect the properties of <i>object</i> (a grip). This could be the global object (<tt>window</tt> in a browser), or a DOM element (for event handler content attributes, which have the input element, form, and document on their scope chain along with the <tt>window</tt>). | |||
<i>Actor</i> is the name of an actor representing this lexical environment. The requests it can answer are described below. | |||
<i>Parent-environment</i> describes the next enclosing lexical environment; the <tt>parent</tt> property is omitted on the outermost environment. | |||
{ "type":"function", "actor":<i>actor</i>, "function":<i>function</i>, "function-name":<i>function-name</i>, | |||
"bindings":<i>bindings</i>, "parent":<i>parent-environment</i> } | |||
This represents the variable environment created by a call to <i>function</i> (a grip), whose name is <i>function-name</i> (a string). <i>Bindings</i> describes the bindings in scope, including the function's arguments, the <tt>arguments</tt> object, and local <tt>var</tt> and function bindings; its form is described in detail below. The <tt>function-name</tt> property is omitted if the function is anonymous. The other properties are as described above. | |||
{ "type":"with", "actor":<i>actor</i>, "object":<i>object</i>, "parent":<i>parent-environment</i> } | |||
This represents bindings introduced by a <tt>with</tt> statement whose operand is <i>object</i> (a grip). The other properties are as described above. | |||
{ "type":"block", "actor":<i>actor</i>, "bindings":<i>bindings</i>, "parent":<i>parent-environment</i> } | |||
This represents bindings introduced by a <tt>let</tt> block, <tt>for-in</tt> statement, <tt>catch</tt> block, or the like. The properties are as described above. | |||
A <i>bindings</i> value has the form: | |||
{ "mutable":{ <i>name</i>:<i>value</i>, ... }, | |||
"immutable":{ <i>name</i>:<i>value</i>, ... } } | |||
where each <i>name</i> is the name of a bound identifier, and each <i>value</i> is a grip on that identifier's value. Mutable bindings appear in the <tt>mutable</tt> object, and immutable bindings appear in the <tt>immutable</tt> object. If either category has no bindings, the property may be omitted entirely. | |||
<i>TODO: Should we segregate function arguments in bindings values, in case clients want to display them separately? They should appear in order...</i> | |||
Note that language implementations may omit some environment records from a function's scope if it can determine that the function would not use them. This means that it may be impossible for a debugger to find all the variables that ought to be in scope. | |||
To fully enumerate the bindings introduced by any lexical environment, the client can send a request of the following form to the environment's actor: | |||
{ "to":<i>env-actor</i>, "type":"bindings" } | |||
The actor will reply as follows: | |||
{ "from":<i>env-actor</i>, "bindings":<i>bindings</i> } | |||
To change the value of a variable bound in a particular lexical environment, the client can send a request to the environment's actor: | |||
{ "to":<i>env-actor</i>, "type":"assign", "name":<i>name</i>, "value":<i>value</i> } | |||
This changes the value of the identifier whose name is <i>name</i> (a string) to that represented by <i>value</i> (a grip). The actor will reply as follows, simply: | |||
{ "from":<i>env-actor</i> } | |||
If the named identifier is immutable, the actor will send an error reply of the form: | |||
{ "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. | |||
= Breakpoints = | = Breakpoints = | ||