js/src/doc/Debugger/Debugger-API.md

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/doc/Debugger/Debugger-API.md	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,186 @@
     1.4 +# The `Debugger` Interface
     1.5 +
     1.6 +Mozilla's JavaScript engine, SpiderMonkey, provides a debugging interface
     1.7 +named `Debugger` which lets JavaScript code observe and manipulate the
     1.8 +execution of other JavaScript code. Both Firefox's built-in developer tools
     1.9 +and the Firebug add-on use `Debugger` to implement their JavaScript
    1.10 +debuggers. However, `Debugger` is quite general, and can be used to
    1.11 +implement other kinds of tools like tracers, coverage analysis,
    1.12 +patch-and-continue, and so on.
    1.13 +
    1.14 +`Debugger` has three essential qualities:
    1.15 +
    1.16 +- It is a *source level* interface: it operates in terms of the JavaScript
    1.17 +  language, not machine language. It operates on JavaScript objects, stack
    1.18 +  frames, environments, and code, and presents a consistent interface
    1.19 +  regardless of whether the debuggee is interpreted, compiled, or
    1.20 +  optimized. If you have a strong command of the JavaScript language, you
    1.21 +  should have all the background you need to use `Debugger` successfully,
    1.22 +  even if you have never looked into the language's implementation.
    1.23 +
    1.24 +- It is for use *by JavaScript code*. JavaScript is both the debuggee
    1.25 +  language and the tool implementation language, so the qualities that make
    1.26 +  JavaScript effective on the web can be brought to bear in crafting tools
    1.27 +  for developers. As is expected of JavaScript APIs, `Debugger` is a
    1.28 +  *sound* interface: using (or even misusing) `Debugger` should never cause
    1.29 +  Gecko to crash. Errors throw proper JavaScript exceptions.
    1.30 +
    1.31 +- It is an *intra-thread* debugging API. Both the debuggee and the code
    1.32 +  using `Debugger` to observe it must run in the same thread. Cross-thread,
    1.33 +  cross-process, and cross-device tools must use `Debugger` to observe the
    1.34 +  debuggee from within the same thread, and then handle any needed
    1.35 +  communication themselves. (Firefox's builtin tools have a
    1.36 +  [protocol][protocol] defined for this purpose.)
    1.37 +
    1.38 +In Gecko, the `Debugger` API is available to chrome code only. By design,
    1.39 +it ought not to introduce security holes, so in principle it could be made
    1.40 +available to content as well; but it is hard to justify the security risks
    1.41 +of the additional attack surface.
    1.42 +
    1.43 +
    1.44 +## Debugger Instances and Shadow Objects
    1.45 +
    1.46 +`Debugger` reflects every aspect of the debuggee's state as a JavaScript
    1.47 +value—not just actual JavaScript values like objects and primitives,
    1.48 +but also stack frames, environments, scripts, and compilation units, which
    1.49 +are not normally accessible as objects in their own right.
    1.50 +
    1.51 +Here is a JavaScript program in the process of running a timer callback function:
    1.52 +
    1.53 +![A running JavaScript program and its Debugger shadows][img-shadows]
    1.54 +
    1.55 +This diagram shows the various types of shadow objects that make up the
    1.56 +Debugger API (which all follow some [general conventions][conventions]):
    1.57 +
    1.58 +- A [`Debugger.Object`][object] represents a debuggee object, offering a
    1.59 +  reflection-oriented API that protects the debugger from accidentally
    1.60 +  invoking getters, setters, proxy traps, and so on.
    1.61 +
    1.62 +- A [`Debugger.Script`][script] represents a block of JavaScript
    1.63 +  code—either a function body or a top-level script. Given a
    1.64 +  `Debugger.Script`, one can set breakpoints, translate between source
    1.65 +  positions and bytecode offsets (a deviation from the "source level"
    1.66 +  design principle), and find other static characteristics of the code.
    1.67 +
    1.68 +- A [`Debugger.Frame`][frame] represents a running stack frame. You can use
    1.69 +  these to walk the stack and find each frame's script and environment. You
    1.70 +  can also set `onStep` and `onPop` handlers on frames.
    1.71 +
    1.72 +- A [`Debugger.Environment`][environment] represents an environment,
    1.73 +  associating variable names with storage locations. Environments may
    1.74 +  belong to a running stack frame, captured by a function closure, or
    1.75 +  reflect some global object's properties as variables.
    1.76 +
    1.77 +The [`Debugger`][debugger-object] instance itself is not really a shadow of
    1.78 +anything in the debuggee; rather, it maintains the set of global objects
    1.79 +which are to be considered debuggees. A `Debugger` observes only execution
    1.80 +taking place in the scope of these global objects. You can set functions to
    1.81 +be called when new stack frames are pushed; when new code is loaded; and so
    1.82 +on.
    1.83 +
    1.84 +Omitted from this picture are [`Debugger.Source`][source] instances, which
    1.85 +represent JavaScript compilation units. A `Debugger.Source` can furnish a
    1.86 +full copy of its source code, and explain how the code entered the system,
    1.87 +whether via a call to `eval`, a `<script>` element, or otherwise. A
    1.88 +`Debugger.Script` points to the `Debugger.Source` from which it is derived.
    1.89 +
    1.90 +All these types follow some [general conventions][conventions], which you
    1.91 +should look through before drilling down into any particular type's
    1.92 +specification.
    1.93 +
    1.94 +All shadow objects are unique per `Debugger` and per referent. For a given
    1.95 +`Debugger`, there is exactly one `Debugger.Object` that refers to a
    1.96 +particular debuggee object; exactly one `Debugger.Frame` for a particular
    1.97 +stack frame; and so on. Thus, a tool can store metadata about a shadow's
    1.98 +referent as a property on the shadow itself, and count on finding that
    1.99 +metadata again if it comes across the same referent. And since shadows are
   1.100 +per-`Debugger`, tools can do so without worrying about interfering with
   1.101 +other tools that use their own `Debugger` instances.
   1.102 +
   1.103 +
   1.104 +## Example
   1.105 +
   1.106 +You can try out `Debugger` yourself in Firefox's Scratchpad.
   1.107 +
   1.108 +1)  Visit the URL `about:config`, and set the `devtools.chrome.enabled`
   1.109 +    preference to `true`:
   1.110 +
   1.111 +    ![Setting the 'devtools.chrome.enabled' preference][img-chrome-pref]
   1.112 +
   1.113 +2)  Save the following HTML text to a file, and visit the file in your
   1.114 +    browser:
   1.115 +
   1.116 +        <div onclick="var x = 'snoo'; debugger;">Click me!</div>
   1.117 +
   1.118 +3)  Open a developer Scratchpad (Menu button > Developer > Scratchpad), and
   1.119 +    select "Browser" from the "Environment" menu. (This menu will not be
   1.120 +    present unless you have changed the preference as explained above.)
   1.121 +
   1.122 +    ![Selecting the 'browser' context in the Scratchpad][img-scratchpad-browser]
   1.123 +
   1.124 +4)  Enter the following code in the Scratchpad:
   1.125 +
   1.126 +        // This simply defines 'Debugger' in this Scratchpad;
   1.127 +        // it doesn't actually start debugging anything.
   1.128 +        Cu.import("resource://gre/modules/jsdebugger.jsm");
   1.129 +        addDebuggerToGlobal(window);
   1.130 +
   1.131 +        // Create a 'Debugger' instance.
   1.132 +        var dbg = new Debugger;
   1.133 +
   1.134 +        // Get the current tab's content window, and make it a debuggee.
   1.135 +        var w = gBrowser.selectedBrowser.contentWindow.wrappedJSObject;
   1.136 +        dbg.addDebuggee(w);
   1.137 +
   1.138 +        // When the debuggee executes a 'debugger' statement, evaluate
   1.139 +        // the expression 'x' in that stack frame, and show its value.
   1.140 +        dbg.onDebuggerStatement = function (frame) {
   1.141 +            alert('hit debugger statement; x = ' + frame.eval('x').return);
   1.142 +        }
   1.143 +
   1.144 +5)  In the Scratchpad, ensure that no text is selected, and press the "Run"
   1.145 +    button.
   1.146 +
   1.147 +6)  Now, click on the text that says "Click me!" in the web page. This runs
   1.148 +    the `div` element's `onclick` handler. When control reaches the
   1.149 +    `debugger;` statement, `Debugger` calls your callback function, passing
   1.150 +    a `Debugger.Frame` instance. Your callback function evaluates the
   1.151 +    expression `x` in the given stack frame, and displays the alert:
   1.152 +
   1.153 +    ![The Debugger callback displaying an alert][img-example-alert]
   1.154 +
   1.155 +7)  Press "Run" in the Scratchpad again. Now, clicking on the "Click me!"
   1.156 +    text causes *two* alerts to show&mdash;one for each `Debugger`
   1.157 +    instance.
   1.158 +
   1.159 +    Multiple `Debugger` instances can observe the same debuggee. Re-running
   1.160 +    the code in the Scratchpad created a fresh `Debugger` instance, added
   1.161 +    the same web page as its debuggee, and then registered a fresh
   1.162 +    `debugger;` statement handler with the new instance. When you clicked
   1.163 +    on the `div` element, both of them ran. This shows how any number of
   1.164 +    `Debugger`-based tools can observe a single web page
   1.165 +    simultaneously&mdash;although, since the order in which their handlers
   1.166 +    run is not specified, such tools should probably only observe, and not
   1.167 +    influence, the debuggee's behavior.
   1.168 +
   1.169 +8)  Close the web page and the Scratchpad.
   1.170 +
   1.171 +    Since both the Scratchpad's global object and the debuggee window are
   1.172 +    now gone, the `Debugger` instances will be garbage collected, since
   1.173 +    they can no longer have any visible effect on Firefox's behavior. The
   1.174 +    `Debugger` API tries to interact with garbage collection as
   1.175 +    transparently as possible; for example, if both a `Debugger.Object`
   1.176 +    instance and its referent are not reachable, they will both be
   1.177 +    collected, even while the `Debugger` instance to which the shadow
   1.178 +    belonged continues to exist.
   1.179 +
   1.180 +
   1.181 +## Gecko-specific features
   1.182 +
   1.183 +While the `Debugger` core API deals only with concepts common to any
   1.184 +JavaScript implementation, it also includes some Gecko-specific features:
   1.185 +
   1.186 +- [Global tracking][global] supports debugging all the code running in a
   1.187 +  Gecko instance at once&mdash;the 'chrome debugging' model.
   1.188 +- [Object wrapper][wrapper] functions help manipulate object references
   1.189 +  that cross privilege boundaries.

mercurial