Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | # General Conventions |
michael@0 | 2 | |
michael@0 | 3 | This page describes general conventions used in the [`Debugger`][debugger] API, |
michael@0 | 4 | and defines some terminology used throughout the specification. |
michael@0 | 5 | |
michael@0 | 6 | |
michael@0 | 7 | ## Properties |
michael@0 | 8 | |
michael@0 | 9 | Properties of objects that comprise the `Debugger` interface, and those |
michael@0 | 10 | that the interface creates, follow some general conventions: |
michael@0 | 11 | |
michael@0 | 12 | - Instances and prototypes are extensible; you can add your own properties |
michael@0 | 13 | and methods to them. |
michael@0 | 14 | |
michael@0 | 15 | - Properties are configurable. This applies to both "own" and prototype |
michael@0 | 16 | properties, and to both methods and data properties. (Leaving these |
michael@0 | 17 | properties open to redefinition will hopefully make it easier for |
michael@0 | 18 | JavaScript debugger code to cope with bugs, bug fixes, and changes in the |
michael@0 | 19 | interface over time.) |
michael@0 | 20 | |
michael@0 | 21 | - Method properties are writable. |
michael@0 | 22 | |
michael@0 | 23 | - We prefer inherited accessor properties to own data properties. Both are |
michael@0 | 24 | read using the same syntax, but inherited accessors seem like a more |
michael@0 | 25 | accurate reflection of what's going on. Unless otherwise noted, these |
michael@0 | 26 | properties have getters but no setters, as they cannot meaningfully be |
michael@0 | 27 | assigned to. |
michael@0 | 28 | |
michael@0 | 29 | |
michael@0 | 30 | ## Debuggee Values |
michael@0 | 31 | |
michael@0 | 32 | The `Debugger` interface follows some conventions to help debuggers safely |
michael@0 | 33 | inspect and modify the debuggee's objects and values. Primitive values are |
michael@0 | 34 | passed freely between debugger and debuggee; copying or wrapping is handled |
michael@0 | 35 | transparently. Objects received from the debuggee (including host objects |
michael@0 | 36 | like DOM elements) are fronted in the debugger by `Debugger.Object` |
michael@0 | 37 | instances, which provide reflection-oriented methods for inspecting their |
michael@0 | 38 | referents; see `Debugger.Object`, below. |
michael@0 | 39 | |
michael@0 | 40 | Of the debugger's objects, only `Debugger.Object` instances may be passed |
michael@0 | 41 | to the debuggee: when this occurs, the debuggee receives the |
michael@0 | 42 | `Debugger.Object`'s referent, not the `Debugger.Object` instance itself. |
michael@0 | 43 | |
michael@0 | 44 | In the descriptions below, the term "debuggee value" means either a |
michael@0 | 45 | primitive value or a `Debugger.Object` instance; it is a value that might |
michael@0 | 46 | be received from the debuggee, or that could be passed to the debuggee. |
michael@0 | 47 | |
michael@0 | 48 | |
michael@0 | 49 | ## Debuggee Code |
michael@0 | 50 | |
michael@0 | 51 | Each `Debugger` instance maintains a set of global objects that, taken |
michael@0 | 52 | together, comprise the debuggee. Code evaluated in the scope of a debuggee |
michael@0 | 53 | global object, directly or indirectly, is considered *debuggee code*. |
michael@0 | 54 | Similarly: |
michael@0 | 55 | |
michael@0 | 56 | - a *debuggee frame* is a frame running debuggee code; |
michael@0 | 57 | |
michael@0 | 58 | - a *debuggee function* is a function that closes over a debuggee |
michael@0 | 59 | global object (and thus the function's code is debuggee code); |
michael@0 | 60 | |
michael@0 | 61 | - a *debuggee environment* is an environment whose outermost |
michael@0 | 62 | enclosing environment is a debuggee global object; and |
michael@0 | 63 | |
michael@0 | 64 | - a *debuggee script* is a script containing debuggee code. |
michael@0 | 65 | |
michael@0 | 66 | |
michael@0 | 67 | ## Completion Values |
michael@0 | 68 | |
michael@0 | 69 | When a debuggee stack frame completes its execution, or when some sort |
michael@0 | 70 | of debuggee call initiated by the debugger finishes, the `Debugger` |
michael@0 | 71 | interface provides a value describing how the code completed; these are |
michael@0 | 72 | called *completion values*. A completion value has one of the |
michael@0 | 73 | following forms: |
michael@0 | 74 | |
michael@0 | 75 | <code>{ return: <i>value</i> }</code> |
michael@0 | 76 | : The code completed normally, returning <i>value</i>. <i>Value</i> is a |
michael@0 | 77 | debuggee value. |
michael@0 | 78 | |
michael@0 | 79 | <code>{ yield: <i>value</i> }</code> |
michael@0 | 80 | : <i>(Not yet implemented.)</i> The running code is a generator frame |
michael@0 | 81 | which has yielded <i>value</i>. <i>Value</i> is a debuggee value. |
michael@0 | 82 | |
michael@0 | 83 | <code>{ throw: <i>value</i> }</code> |
michael@0 | 84 | : The code threw <i>value</i> as an exception. <i>Value</i> is a debuggee |
michael@0 | 85 | value. |
michael@0 | 86 | |
michael@0 | 87 | `null` |
michael@0 | 88 | : The code was terminated, as if by the "slow script" dialog box. |
michael@0 | 89 | |
michael@0 | 90 | If control reaches the end of a generator frame, the completion value is |
michael@0 | 91 | <code>{ throw: <i>stop</i> }</code> where <i>stop</i> is a |
michael@0 | 92 | `Debugger.Object` object representing the `StopIteration` object being |
michael@0 | 93 | thrown. |
michael@0 | 94 | |
michael@0 | 95 | |
michael@0 | 96 | ## Resumption Values |
michael@0 | 97 | |
michael@0 | 98 | As the debuggee runs, the `Debugger` interface calls various |
michael@0 | 99 | debugger-provided handler functions to report the debuggee's behavior. |
michael@0 | 100 | Some of these calls can return a value indicating how the debuggee's |
michael@0 | 101 | execution should continue; these are called *resumption values*. A |
michael@0 | 102 | resumption value has one of the following forms: |
michael@0 | 103 | |
michael@0 | 104 | `undefined` |
michael@0 | 105 | : The debuggee should continue execution normally. |
michael@0 | 106 | |
michael@0 | 107 | <code>{ return: <i>value</i> }</code> |
michael@0 | 108 | : Return <i>value</i> immediately as the current value of the function. |
michael@0 | 109 | <i>Value</i> must be a debuggee value. (Most handler functions support |
michael@0 | 110 | this, except those whose descriptions say otherwise.) If the function |
michael@0 | 111 | was called as a constructor (that is, via a `new` expression), then |
michael@0 | 112 | <i>value</i> serves as the value returned by the function's body, not |
michael@0 | 113 | that produced by the `new` expression: if the value is not an object, |
michael@0 | 114 | the `new` expression returns the frame's `this` value. |
michael@0 | 115 | |
michael@0 | 116 | <code>{ yield: <i>value</i> }</code> |
michael@0 | 117 | : <i>(Not yet implemented.)</i> Yield <i>value</i> immediately as the |
michael@0 | 118 | next value of the current frame, which must be a generator frame. |
michael@0 | 119 | <i>Value</i> is a debuggee value. The current frame must be a generator |
michael@0 | 120 | frame that has not yet completed in some other way. You may use `yield` |
michael@0 | 121 | resumption values to substitute a new value or one already yielded by a |
michael@0 | 122 | generator, or to make a generator yield additional values. |
michael@0 | 123 | |
michael@0 | 124 | <code>{ throw: <i>value</i> }</code> |
michael@0 | 125 | : Throw <i>value</i> as an exception from the current bytecode |
michael@0 | 126 | instruction. <i>Value</i> must be a debuggee value. |
michael@0 | 127 | |
michael@0 | 128 | `null` |
michael@0 | 129 | : Terminate the debuggee, as if it had been cancelled by the "slow script" |
michael@0 | 130 | dialog box. |
michael@0 | 131 | |
michael@0 | 132 | If a function that would normally return a resumption value to indicate |
michael@0 | 133 | how the debuggee should continue instead throws an exception, we never |
michael@0 | 134 | propagate such an exception to the debuggee; instead, we call the |
michael@0 | 135 | associated `Debugger` instance's `uncaughtExceptionHook` property, as |
michael@0 | 136 | described below. |
michael@0 | 137 | |
michael@0 | 138 | |
michael@0 | 139 | ## The `Debugger.DebuggeeWouldRun` Exception |
michael@0 | 140 | |
michael@0 | 141 | Some debugger operations that appear to simply inspect the debuggee's state |
michael@0 | 142 | may actually cause debuggee code to run. For example, reading a variable |
michael@0 | 143 | might run a getter function on the global or on a `with` expression's |
michael@0 | 144 | operand; and getting an object's property descriptor will run a handler |
michael@0 | 145 | trap if the object is a proxy. To protect the debugger's integrity, only |
michael@0 | 146 | methods whose stated purpose is to run debuggee code can do so. These |
michael@0 | 147 | methods are called [invocation functions][inv fr], and they follow certain |
michael@0 | 148 | common conventions to report the debuggee's behavior safely. For other |
michael@0 | 149 | methods, if their normal operation would cause debuggee code to run, they |
michael@0 | 150 | throw an instance of the `Debugger.DebuggeeWouldRun` exception. |
michael@0 | 151 | |
michael@0 | 152 | A `Debugger.DebuggeeWouldRun` exception may have a `cause` property, |
michael@0 | 153 | providing more detailed information on why the debuggee would have run. The |
michael@0 | 154 | `cause` property's value is one of the following strings: |
michael@0 | 155 | |
michael@0 | 156 | <i>cause</i> value meaning |
michael@0 | 157 | -------------------- -------------------------------------------------------------------------------- |
michael@0 | 158 | "proxy" Carrying out the operation would have caused a proxy handler to run. |
michael@0 | 159 | "getter" Carrying out the operation would have caused an object property getter to run. |
michael@0 | 160 | "setter" Carrying out the operation would have caused an object property setter to run. |
michael@0 | 161 | |
michael@0 | 162 | If the system can't determine why control attempted to enter the debuggee, |
michael@0 | 163 | it will leave the exception's `cause` property undefined. |