Remote Debugging Protocol: Difference between revisions

Jump to navigation Jump to search
Move "Lexical Environments" back down towards the bottom.
(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>.
= 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.
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.


= 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 =
Confirmed users
497

edits

Navigation menu