Remote Debugging Protocol: Difference between revisions

Jump to navigation Jump to search
Revisions based on Panos's implementation notes. https://github.com/jimblandy/DebuggerDocs/commit/f2344f17e4f3aa2a99b6ab0702d782e09398e45d
(Add link to GitHub repo.)
(Revisions based on Panos's implementation notes. https://github.com/jimblandy/DebuggerDocs/commit/f2344f17e4f3aa2a99b6ab0702d782e09398e45d)
Line 70: Line 70:


where <i>message</i> provides details to help debugger developers understand what went wrong: what kind of actor <i>actor</i> is; the packet received; and so on.
where <i>message</i> provides details to help debugger developers understand what went wrong: what kind of actor <i>actor</i> is; the packet received; and so on.
If an actor recieves a packet which is missing needed parameters (say, a <tt>"releaseMany"</tt> packet with no <tt>"actors"</tt> parameter), it sends an error reply of the form:
  { "from":<i>actor</i>, "error":"missingParameter", "message":<i>message</i> }
where <i>message</i> provides details to help debugger developers fix the problem.
If an actor recieves a packet with a parameter whose value is inappropriate for the operation, it sends an error reply of the form:
  { "from":<i>actor</i>, "error":"badParameterType", "message":<i>message</i> }
where <i>message</i> provides details to help debugger developers fix the problem. (Some packets' descriptions specify more specific errors for particular circumstances.)


= Grips =
= Grips =
Line 275: Line 287:
   { "from":<i>functionGripActor</i>, "scope":<i>environment</i> }
   { "from":<i>functionGripActor</i>, "scope":<i>environment</i> }


where <i>environment</i> is a [[#Lexical_Environments|lexical environment]].
where <i>environment</i> is a [[#Lexical_Environments|lexical environment]]. Note that the server only returns environments of functions in a context being debugged; if the function's global scope is not the browsing context to which we are attached, the function grip actor sends an error reply of the form:
 
  { "from":<i>functionGripActor</i>, "error":"notDebuggee", "message":<i>message</i> }
 
where <i>message</i> is text explaining the problem.


   { "to":<i>functionGripActor</i>, "type":"decompile", "pretty":<i>pretty</i> }
   { "to":<i>functionGripActor</i>, "type":"decompile", "pretty":<i>pretty</i> }
Line 284: Line 300:


where <i>code</i> is a string.
where <i>code</i> is a string.
If <i>functionGripActor</i>'s referent is not a function, or is a function proxy, the actor responds to these requests with an error reply of the form:
  { "from":<i>functionGripActor</i>, "error":"objectNotFunction", message:<i>message</i> }
where <i>message</i> is a string containing any additional information that would be helpful to debugger developers.


== Long Strings ==
== Long Strings ==
Line 325: Line 347:
   { "from":<i>gripActor</i> }
   { "from":<i>gripActor</i> }


This closes the grip actor.
This closes the grip actor. The <tt>"release"</tt> packet may only be sent to thread-lifetime grip actors; if a pause-lifetime grip actor receives a <tt>"release"</tt> packet, it sends an error reply of the form:
 
  { "from":<i>gripActor</i>, "error":"notReleasable", "message":<i>message</i> }
 
where <i>message</i> includes whatever further information would be useful to the debugger developers.


The client can release many thread-lifetime grips in a single operation by sending the thread actor a request of the form:
The client can release many thread-lifetime grips in a single operation by sending the thread actor a request of the form:
Line 336: Line 362:


Regardless of the lifetime of a grip, the client may only send messages to grip actors while the thread to which they belong is paused; the client's interaction with values cannot take place concurrently with the thread.
Regardless of the lifetime of a grip, the client may only send messages to grip actors while the thread to which they belong is paused; the client's interaction with values cannot take place concurrently with the thread.
= Completion Values =
Some packets describe the way a stack frame's execution completed using a <b>completion value</b>, which takes one of the following forms:
  { "return":<i>grip</i> }
This indicates that the frame completed normally, returning the value given by <i>grip</i>.
  { "throw":<i>grip</i> }
This indicates that the frame threw an exception; <i>grip</i> is the exception value thrown.
  { "terminated":true }
This indicates that the frame's execution was terminated, as by a "slow script" dialog box or running out of memory.


= Source Locations =
= Source Locations =
Line 526: Line 568:
   { "type":"resumeLimit" }
   { "type":"resumeLimit" }


The client resumed the thread with a "resume" packet that included a <tt>resumeLimit</tt> property, and the thread paused because the given <i>limit</i> was met.
The client resumed the thread with a <tt>"resume"</tt> packet that included a <tt>resumeLimit</tt> property, and the thread paused because the given <i>limit</i> was met. Execution remains in the frame the thread was resumed in, and that frame is not about to be popped.
 
  { "type":"resumeLimit", "frameFinished":<i>completion</i> }
 
The client resumed the thread with a <tt>"resume"</tt> packet that included a <tt>resumeLimit</tt> property, and the thread paused because the frame is about to be popped. <i>Completion</i> is a [[#Completion_Values|completion value]] describing how the frame's execution ended. The frame being popped is still the top frame on the stack, but subsequent <code>"resume"</code> operations will run in the calling frame.


   { "type":"debuggerStatement" }
   { "type":"debuggerStatement" }
Line 542: Line 588:
<i>TODO: This should provide more details about the watchpoint in the packet, instead of incurring another round-trip before we can display anything helpful.</i>
<i>TODO: This should provide more details about the watchpoint in the packet, instead of incurring another round-trip before we can display anything helpful.</i>


   { "type":"clientEvaluated", "value":<i>grip</i> }
   { "type":"clientEvaluated", "frameFinished":<i>completion</i> }


The client's prior <tt>clientEvaluate</tt> command has completed normally; <i>grip</i> is a grip on the expression's value. See [[#Evaluating_Source-Language_Expressions|Evaluating Source-Language Expressions]] for details.
The expression given in the client's prior <tt>clientEvaluate</tt> command has completed execution; <i>completion</i> is a [[#Completion_Values|completion value]] describing how it completed. The frame created for the <tt>clientEvaluate</tt> resumption has been popped from the stack. See [[#Evaluating_Source-Language_Expressions|Evaluating Source-Language Expressions]] for details.
 
  { "type":"clientEvaluated", "exception":<i>grip</i> }
 
The client's prior <tt>clientEvaluate</tt> command has completed abruptly; <i>grip</i> is the uncaught exception value. See [[#Evaluating_Source-Language_Expressions|Evaluating Source-Language Expressions]] for details.


== Resuming a Thread ==
== Resuming a Thread ==
Line 554: Line 596:
If a thread is in the <b>Paused</b> state, the client can resume it by sending a packet of the following form:
If a thread is in the <b>Paused</b> state, the client can resume it by sending a packet of the following form:


   { "to":<i>thread</i>, "type":"resume", "resumeLimit":<i>limit</i> }
   { "to":<i>thread</i>, "type":"resume" }


This puts the thread in the <b>Running</b> state. The thread will pause again for breakpoint hits, watchpoint hits, throw watches, frame pop watches, and other standing pause requests.
This puts the thread in the <b>Running</b> state. The thread will pause again for breakpoint hits, watchpoint hits, throw watches, frame pop watches, and other standing pause requests.


In addition, if the optional <tt>resumeLimit</tt> property is present, then the thread should also pause when <i>limit</i> is reached. <i>Limit</i> must have one of the following forms:
To step a thread's execution, the client can send a packet of the form:
 
  { "to":<i>thread</i>, "type":"resume", "resumeLimit":<i>limit</i> }
 
<i>Limit</i> must have one of the following forms:


   { "type":"next" }
   { "type":"next" }
Line 580: Line 626:
This is the same as <tt>"next"</tt>, except that it steps into calls.
This is the same as <tt>"next"</tt>, except that it steps into calls.


  { "type":"finish" }
To resume the thread but have it stop when the current frame is about to be popped, the client can send a packet of the form:


The thread should pause just before the current frame is popped, whether by throwing an exception or returning a value.
  { "to":<i>thread</i>, "type":"resume", "resumeLimit":{ "type":"finish" } }
 
Here, the thread should pause just before the current frame is popped, whether by throwing an exception, returning a value, or being terminated.


When a thread pauses because a limit was reached, the "paused" packet's <i>reason</i> will have a type of <tt>"resumeLimit"</tt>.
When a thread pauses because a limit was reached, the "paused" packet's <i>reason</i> will have a type of <tt>"resumeLimit"</tt>.
Line 588: Line 636:
A resume limit applies only to the current resumption; once the thread pauses, whether because the limit was reached or some other event occurred&mdash;a breakpoint hit, for example&mdash;the resume limit is no longer in effect.
A resume limit applies only to the current resumption; once the thread pauses, whether because the limit was reached or some other event occurred&mdash;a breakpoint hit, for example&mdash;the resume limit is no longer in effect.


If no <tt>"resumeLimit"</tt> property appears in the "resume" packet, then the thread should run until some standing pause condition is met (a breakpoint is hit; a watchpoint triggers; or the like).
If no <tt>"resumeLimit"</tt> property appears in the <tt>"resume"</tt> packet, then the thread should run until some standing pause condition is met (a breakpoint is hit; a watchpoint triggers; or the like).
 
To force the current frame to end execution immediately, the client can send a packet of the form:
 
  { "to":<i>thread</i>, "type":"resume", "forceCompletion":<i>completion</i> }
 
where <i>completion</i> is a [[#Completion_Values|completion value]] indicating whether the frame should return a value, throw an exception, or be terminated.
 
A <tt>"resume"</tt> packet may not include both a <tt>"resumeLimit"</tt> property and a <tt>"forceCompletion"</tt> property.


A "resume" packet closes the pause actor the client provided in the "paused" packet that began the pause.
A <tt>"resume"</tt> packet closes the pause actor the client provided in the "paused" packet that began the pause.


If the client sends a <code>"resume"</code> packet to a thread that is not in the <b>Paused</b> state, the actor sends an error reply of the form:
If the client sends a <code>"resume"</code> packet to a thread that is not in the <b>Paused</b> state, the actor sends an error reply of the form:
Line 693: Line 749:
and other properties are as above.
and other properties are as above.


For calls to host functions, the <tt>"where"</tt> and <tt>"environment"</tt> properties may be absent.
If the callee is a host function, or a function scoped to some global other than the one to which we are attached, the <tt>"where"</tt> and <tt>"environment"</tt> properties are absent.


The argument list may be incomplete or inaccurate, for various reasons. If the program has assigned to its formal parameters, the original values passed may have been lost, and compiler optimizations may drop some argument values.
The argument list may be incomplete or inaccurate, for various reasons. If the program has assigned to its formal parameters, the original values passed may have been lost, and compiler optimizations may drop some argument values.
Line 731: Line 787:
== Evaluating Source-Language Expressions ==
== Evaluating Source-Language Expressions ==


To evaluate a source-language expression in a thread, the client sends a specialized <tt>resume</tt> packet of the form:
To evaluate a source-language expression in a thread, the client sends a specialized <tt>"resume"</tt> packet of the form:


   { "to":<i>thread</i>, "type":"clientEvaluate", "expression":<i>expr</i>, "frame":<i>frame</i> }
   { "to":<i>thread</i>, "type":"clientEvaluate", "expression":<i>expr</i>, "frame":<i>frame</i> }


This resumes the thread just as an ordinary <tt>resume</tt> packet does, but rather than continuing execution where the pause took place, has the thread begin evaluation of the source-language expression given by <i>expr</i>, a string. The evaluation takes place in a new [[#Client_Evaluation_Frames|Client Evaluation Frame]], pushed on the stack. When evaluation of <i>expr</i> completes, the client will report a <tt>clientEvaluate</tt> pause containing the expression's value.
This resumes the thread just as an ordinary <tt>"resume"</tt> packet does, but, rather than continuing execution where the pause took place, has the thread begin evaluation of the source-language expression given by <i>expr</i>, a string. The evaluation takes place in a new [[#Client_Evaluation_Frames|Client Evaluation Frame]], pushed on top of <i>thread</i>'s current stack, using the environment of <i>frame</i>. <i>Frame</i> must be a live actor for one of <i>thread</i>'s frames, and the given frame must be one from which we can retrieve a lexical environment; that is, it must not be the frame for a call to a non-debuggee function. When evaluation of <i>expr</i> completes, the client will report a <tt>clientEvaluate</tt> pause containing the expression's value.


If evaluating <i>expr</i> completes abruptly, this outcome is still reported via an <tt>clientEvaluated</tt> pause, so it is not necessary for the client to take explicit steps to catch exceptions thrown by the expression.
If evaluating <i>expr</i> completes abruptly, this outcome is still reported via an <tt>clientEvaluated</tt> pause, so it is not necessary for the client to take explicit steps to catch exceptions thrown by the expression.
If <i>frame</i> is not the name of an actor for a frame currently on <i>thread</i>'s stack, the thread actor sends a reply of the form:
{ "from":<i>thread</i>, "error":"unknownFrame", "message":<i>message</i> }
where <i>message</i> provides any details that would be helpful to the debugger developers. In this case, the thread's state is unaffected.
If <i>frame</i> is not a frame whose environment we can access, the thread actor sends an error reply of the form:
  { "from":<i>thread</i>, "error":"notDebuggee", "message":<i>message</i> }
where <i>message</i> provides further appropriate details.
If the client sends a <code>"clientEvaluate"</code> packet to a thread that is not in the <b>Paused</b> state, the actor sends an error reply of the form:
  { "from":<i>thread</i>, "error":"wrongState", "message":<i>message</i> }
where <i>message</i> details which state the thread was in instead (to make debugging debuggers easier). In this case, the thread's state is unaffected.


<i>TODO: evaluate with given grips bound to given identifiers</i>
<i>TODO: evaluate with given grips bound to given identifiers</i>
Confirmed users
497

edits

Navigation menu