From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- js/src/doc/Debugger/Conventions.md | 168 ++++ js/src/doc/Debugger/Debugger-API.md | 126 +++ js/src/doc/Debugger/Debugger.Environment.md | 153 ++++ js/src/doc/Debugger/Debugger.Frame.md | 328 +++++++ js/src/doc/Debugger/Debugger.Memory.md | 549 ++++++++++++ js/src/doc/Debugger/Debugger.Object.md | 559 ++++++++++++ js/src/doc/Debugger/Debugger.Script.md | 379 ++++++++ js/src/doc/Debugger/Debugger.Source.md | 220 +++++ js/src/doc/Debugger/Debugger.md | 496 ++++++++++ js/src/doc/Debugger/Tutorial-Alloc-Log-Tree.md | 222 +++++ js/src/doc/Debugger/Tutorial-Debugger-Statement.md | 82 ++ js/src/doc/Debugger/alloc-plot-console.png | Bin 0 -> 82359 bytes js/src/doc/Debugger/config.sh | 66 ++ js/src/doc/Debugger/debugger-alert.png | Bin 0 -> 27770 bytes js/src/doc/Debugger/enable-chrome-devtools.png | Bin 0 -> 28465 bytes .../Debugger/scratchpad-browser-environment.png | Bin 0 -> 30443 bytes js/src/doc/Debugger/shadows.svg | 997 +++++++++++++++++++++ 17 files changed, 4345 insertions(+) create mode 100644 js/src/doc/Debugger/Conventions.md create mode 100644 js/src/doc/Debugger/Debugger-API.md create mode 100644 js/src/doc/Debugger/Debugger.Environment.md create mode 100644 js/src/doc/Debugger/Debugger.Frame.md create mode 100644 js/src/doc/Debugger/Debugger.Memory.md create mode 100644 js/src/doc/Debugger/Debugger.Object.md create mode 100644 js/src/doc/Debugger/Debugger.Script.md create mode 100644 js/src/doc/Debugger/Debugger.Source.md create mode 100644 js/src/doc/Debugger/Debugger.md create mode 100644 js/src/doc/Debugger/Tutorial-Alloc-Log-Tree.md create mode 100644 js/src/doc/Debugger/Tutorial-Debugger-Statement.md create mode 100644 js/src/doc/Debugger/alloc-plot-console.png create mode 100644 js/src/doc/Debugger/config.sh create mode 100644 js/src/doc/Debugger/debugger-alert.png create mode 100644 js/src/doc/Debugger/enable-chrome-devtools.png create mode 100644 js/src/doc/Debugger/scratchpad-browser-environment.png create mode 100644 js/src/doc/Debugger/shadows.svg (limited to 'js/src/doc/Debugger') diff --git a/js/src/doc/Debugger/Conventions.md b/js/src/doc/Debugger/Conventions.md new file mode 100644 index 000000000..e8bd3ee43 --- /dev/null +++ b/js/src/doc/Debugger/Conventions.md @@ -0,0 +1,168 @@ +# General Conventions + +This page describes general conventions used in the [`Debugger`][debugger] API, +and defines some terminology used throughout the specification. + + +## Properties + +Properties of objects that comprise the `Debugger` interface, and those +that the interface creates, follow some general conventions: + +- Instances and prototypes are extensible; you can add your own properties + and methods to them. + +- Properties are configurable. This applies to both "own" and prototype + properties, and to both methods and data properties. (Leaving these + properties open to redefinition will hopefully make it easier for + JavaScript debugger code to cope with bugs, bug fixes, and changes in the + interface over time.) + +- Method properties are writable. + +- We prefer inherited accessor properties to own data properties. Both are + read using the same syntax, but inherited accessors seem like a more + accurate reflection of what's going on. Unless otherwise noted, these + properties have getters but no setters, as they cannot meaningfully be + assigned to. + + +## Debuggee Values + +The `Debugger` interface follows some conventions to help debuggers safely +inspect and modify the debuggee's objects and values. Primitive values are +passed freely between debugger and debuggee; copying or wrapping is handled +transparently. Objects received from the debuggee (including host objects +like DOM elements) are fronted in the debugger by `Debugger.Object` +instances, which provide reflection-oriented methods for inspecting their +referents; see `Debugger.Object`, below. + +Of the debugger's objects, only `Debugger.Object` instances may be passed +to the debuggee: when this occurs, the debuggee receives the +`Debugger.Object`'s referent, not the `Debugger.Object` instance itself. + +In the descriptions below, the term "debuggee value" means either a +primitive value or a `Debugger.Object` instance; it is a value that might +be received from the debuggee, or that could be passed to the debuggee. + + +## Debuggee Code + +Each `Debugger` instance maintains a set of global objects that, taken +together, comprise the debuggee. Code evaluated in the scope of a debuggee +global object, directly or indirectly, is considered *debuggee code*. +Similarly: + +- a *debuggee frame* is a frame running debuggee code; + +- a *debuggee function* is a function that closes over a debuggee + global object (and thus the function's code is debuggee code); + +- a *debuggee environment* is an environment whose outermost + enclosing environment is a debuggee global object; and + +- a *debuggee script* is a script containing debuggee code. + + +## Completion Values + +When a debuggee stack frame completes its execution, or when some sort +of debuggee call initiated by the debugger finishes, the `Debugger` +interface provides a value describing how the code completed; these are +called *completion values*. A completion value has one of the +following forms: + +{ return: value } +: The code completed normally, returning value. Value is a + debuggee value. + +{ throw: value } +: The code threw value as an exception. Value is a debuggee + value. + +`null` +: The code was terminated, as if by the "slow script" dialog box. + +If control reaches the end of a generator frame, the completion value is +{ throw: stop } where stop is a +`Debugger.Object` object representing the `StopIteration` object being +thrown. + + +## Resumption Values + +As the debuggee runs, the `Debugger` interface calls various +debugger-provided handler functions to report the debuggee's behavior. +Some of these calls can return a value indicating how the debuggee's +execution should continue; these are called *resumption values*. A +resumption value has one of the following forms: + +`undefined` +: The debuggee should continue execution normally. + +{ return: value } +: Return value immediately as the current value of the function. + Value must be a debuggee value. (Most handler functions support + this, except those whose descriptions say otherwise.) If the function + was called as a constructor (that is, via a `new` expression), then + value serves as the value returned by the function's body, not + that produced by the `new` expression: if the value is not an object, + the `new` expression returns the frame's `this` value. Similarly, if + the function is the constructor for a subclass, then a non-object + value may result in a TypeError. + If the frame is a generator or async function, then value must + conform to the iterator protocol: it must be a non-proxy object of the form + { done: boolean, value: v }, where + both `done` and `value` are ordinary properties. + +{ throw: value } +: Throw value as an exception from the current bytecode + instruction. Value must be a debuggee value. + +`null` +: Terminate the debuggee, as if it had been cancelled by the "slow script" + dialog box. + +If a function that would normally return a resumption value to indicate +how the debuggee should continue instead throws an exception, we never +propagate such an exception to the debuggee; instead, we call the +associated `Debugger` instance's `uncaughtExceptionHook` property, as +described below. + + +## Timestamps + +Timestamps are expressed in units of milliseconds since an arbitrary, +but fixed, epoch. The resolution of timestamps is generally greater +than milliseconds, though no specific resolution is guaranteed. + + +## The `Debugger.DebuggeeWouldRun` Exception + +Some debugger operations that appear to simply inspect the debuggee's state +may actually cause debuggee code to run. For example, reading a variable +might run a getter function on the global or on a `with` expression's +operand; and getting an object's property descriptor will run a handler +trap if the object is a proxy. To protect the debugger's integrity, only +methods whose stated purpose is to run debuggee code can do so. These +methods are called [invocation functions][inv fr], and they follow certain +common conventions to report the debuggee's behavior safely. For other +methods, if their normal operation would cause debuggee code to run, they +throw an instance of the `Debugger.DebuggeeWouldRun` exception. + +If there are debugger frames on stack from multiple Debugger instances, the +thrown exception is an instance of the topmost locking debugger's global's +`Debugger.DebuggeeWouldRun`. + +A `Debugger.DebuggeeWouldRun` exception may have a `cause` property, +providing more detailed information on why the debuggee would have run. The +`cause` property's value is one of the following strings: + + cause value meaning + -------------------- -------------------------------------------------------------------------------- + "proxy" Carrying out the operation would have caused a proxy handler to run. + "getter" Carrying out the operation would have caused an object property getter to run. + "setter" Carrying out the operation would have caused an object property setter to run. + +If the system can't determine why control attempted to enter the debuggee, +it will leave the exception's `cause` property undefined. diff --git a/js/src/doc/Debugger/Debugger-API.md b/js/src/doc/Debugger/Debugger-API.md new file mode 100644 index 000000000..10f6ebf89 --- /dev/null +++ b/js/src/doc/Debugger/Debugger-API.md @@ -0,0 +1,126 @@ +# The `Debugger` Interface + +Mozilla's JavaScript engine, SpiderMonkey, provides a debugging interface +named `Debugger` which lets JavaScript code observe and manipulate the +execution of other JavaScript code. Both Firefox's built-in developer tools +and the Firebug add-on use `Debugger` to implement their JavaScript +debuggers. However, `Debugger` is quite general, and can be used to +implement other kinds of tools like tracers, coverage analysis, +patch-and-continue, and so on. + +`Debugger` has three essential qualities: + +- It is a *source level* interface: it operates in terms of the JavaScript + language, not machine language. It operates on JavaScript objects, stack + frames, environments, and code, and presents a consistent interface + regardless of whether the debuggee is interpreted, compiled, or + optimized. If you have a strong command of the JavaScript language, you + should have all the background you need to use `Debugger` successfully, + even if you have never looked into the language's implementation. + +- It is for use *by JavaScript code*. JavaScript is both the debuggee + language and the tool implementation language, so the qualities that make + JavaScript effective on the web can be brought to bear in crafting tools + for developers. As is expected of JavaScript APIs, `Debugger` is a + *sound* interface: using (or even misusing) `Debugger` should never cause + Gecko to crash. Errors throw proper JavaScript exceptions. + +- It is an *intra-thread* debugging API. Both the debuggee and the code + using `Debugger` to observe it must run in the same thread. Cross-thread, + cross-process, and cross-device tools must use `Debugger` to observe the + debuggee from within the same thread, and then handle any needed + communication themselves. (Firefox's builtin tools have a + [protocol][protocol] defined for this purpose.) + +In Gecko, the `Debugger` API is available to chrome code only. By design, +it ought not to introduce security holes, so in principle it could be made +available to content as well; but it is hard to justify the security risks +of the additional attack surface. + +The `Debugger` API cannot currently observe self-hosted JavaScript. This is not +inherent in the API's design, but simply that the self-hosting infrastructure +isn't prepared for the kind of invasions the `Debugger` API can perform. + + +## Debugger Instances and Shadow Objects + +`Debugger` reflects every aspect of the debuggee's state as a JavaScript +value---not just actual JavaScript values like objects and primitives, +but also stack frames, environments, scripts, and compilation units, which +are not normally accessible as objects in their own right. + +Here is a JavaScript program in the process of running a timer callback function: + +![A running JavaScript program and its Debugger shadows][img-shadows] + +This diagram shows the various types of shadow objects that make up the +Debugger API (which all follow some [general conventions][conventions]): + +- A [`Debugger.Object`][object] represents a debuggee object, offering a + reflection-oriented API that protects the debugger from accidentally + invoking getters, setters, proxy traps, and so on. + +- A [`Debugger.Script`][script] represents a block of JavaScript + code---either a function body or a top-level script. Given a + `Debugger.Script`, one can set breakpoints, translate between source + positions and bytecode offsets (a deviation from the "source level" + design principle), and find other static characteristics of the code. + +- A [`Debugger.Frame`][frame] represents a running stack frame. You can use + these to walk the stack and find each frame's script and environment. You + can also set `onStep` and `onPop` handlers on frames. + +- A [`Debugger.Environment`][environment] represents an environment, + associating variable names with storage locations. Environments may + belong to a running stack frame, captured by a function closure, or + reflect some global object's properties as variables. + +The [`Debugger`][debugger-object] instance itself is not really a shadow of +anything in the debuggee; rather, it maintains the set of global objects +which are to be considered debuggees. A `Debugger` observes only execution +taking place in the scope of these global objects. You can set functions to +be called when new stack frames are pushed; when new code is loaded; and so +on. + +Omitted from this picture are [`Debugger.Source`][source] instances, which +represent JavaScript compilation units. A `Debugger.Source` can furnish a +full copy of its source code, and explain how the code entered the system, +whether via a call to `eval`, a ` + ``` + +6) Open the browser console (Menu Button > Developer > Browser Console), and + then evaluate the expression `demoTrackAllocations()` in the browser + console. This begins logging allocations in the current browser tab. + +7) In the browser tab, click on the text that says "Click here...". The event + handler should add some text to the end of the page. + +8) Back in the browser console, evaluate the expression + `demoPlotAllocations()`. This stops logging allocations, and displays a tree + of allocations: + + ![An allocation plot, displayed in the console][img-alloc-plot] + + The numbers at the left edge of each line show the total number of objects + allocated at that site or at sites called from there. After the count, we + see the function name, and the source code location of the call site or + allocation. + + The `(root)` node's count includes objects allocated in the content page by + the web browser, like DOM events. Indeed, this display shows that + `popup.xml` and `content.js`, which are internal components of Firefox, + allocated more objects in the page's compartment than the page itself. (We + will probably revise the allocation log to present such allocations in a way + that is more informative, and that exposes less of Firefox's internal + structure.) + + As expected, the `onclick` handler is responsible for all allocation done by + the page's own code. (The line number for the onclick handler is `1`, + indicating that the allocating call is located on line one of the handler + text itself. We will probably change this to be the line number within + `page.html`, not the line number within the handler code.) + + The `onclick` handler calls `doDivsAndSpans`, which calls `divsAndSpans`, + which invokes closures of `factory` to do all the actual allocation. (It is + unclear why `spanFactory` allocated thirteen objects, despite being called + only ten times.) + diff --git a/js/src/doc/Debugger/Tutorial-Debugger-Statement.md b/js/src/doc/Debugger/Tutorial-Debugger-Statement.md new file mode 100644 index 000000000..58360ff6f --- /dev/null +++ b/js/src/doc/Debugger/Tutorial-Debugger-Statement.md @@ -0,0 +1,82 @@ +Tutorial: Evaluate an Expression When a debugger; Statement Is Executed +======================================================================= + +This page shows how you can try out the [`Debugger` API][debugger] yourself +using Firefox's Scratchpad. We use the API to evaluate an expression in the web +page whenever it executes a JavaScript `debugger;` statement. + +1) Visit the URL `about:config`, and set the `devtools.chrome.enabled` + preference to `true`: + + ![Setting the 'devtools.chrome.enabled' preference][img-chrome-pref] + +2) Save the following HTML text to a file, and visit the file in your + browser: + + ```language-html +
Click me!
+ ``` + +3) Open a developer Scratchpad (Menu button > Developer > Scratchpad), and + select "Browser" from the "Environment" menu. (This menu will not be + present unless you have changed the preference as explained above.) + + ![Selecting the 'browser' context in the Scratchpad][img-scratchpad-browser] + +4) Enter the following code in the Scratchpad: + + ```language-js + // This simply defines 'Debugger' in this Scratchpad; + // it doesn't actually start debugging anything. + Components.utils.import("resource://gre/modules/jsdebugger.jsm"); + addDebuggerToGlobal(window); + + // Create a 'Debugger' instance. + var dbg = new Debugger; + + // Get the current tab's content window, and make it a debuggee. + var w = gBrowser.selectedBrowser.contentWindow.wrappedJSObject; + dbg.addDebuggee(w); + + // When the debuggee executes a 'debugger' statement, evaluate + // the expression 'x' in that stack frame, and show its value. + dbg.onDebuggerStatement = function (frame) { + alert('hit debugger statement; x = ' + frame.eval('x').return); + } + ``` + +5) In the Scratchpad, ensure that no text is selected, and press the "Run" + button. + +6) Now, click on the text that says "Click me!" in the web page. This runs + the `div` element's `onclick` handler. When control reaches the + `debugger;` statement, `Debugger` calls your callback function, passing + a `Debugger.Frame` instance. Your callback function evaluates the + expression `x` in the given stack frame, and displays the alert: + + ![The Debugger callback displaying an alert][img-example-alert] + +7) Press "Run" in the Scratchpad again. Now, clicking on the "Click me!" + text causes *two* alerts to show---one for each `Debugger` + instance. + + Multiple `Debugger` instances can observe the same debuggee. Re-running + the code in the Scratchpad created a fresh `Debugger` instance, added + the same web page as its debuggee, and then registered a fresh + `debugger;` statement handler with the new instance. When you clicked + on the `div` element, both of them ran. This shows how any number of + `Debugger`-based tools can observe a single web page + simultaneously---although, since the order in which their handlers + run is not specified, such tools should probably only observe, and not + influence, the debuggee's behavior. + +8) Close the web page and the Scratchpad. + + Since both the Scratchpad's global object and the debuggee window are + now gone, the `Debugger` instances will be garbage collected, since + they can no longer have any visible effect on Firefox's behavior. The + `Debugger` API tries to interact with garbage collection as + transparently as possible; for example, if both a `Debugger.Object` + instance and its referent are not reachable, they will both be + collected, even while the `Debugger` instance to which the shadow + belonged continues to exist. diff --git a/js/src/doc/Debugger/alloc-plot-console.png b/js/src/doc/Debugger/alloc-plot-console.png new file mode 100644 index 000000000..541172472 Binary files /dev/null and b/js/src/doc/Debugger/alloc-plot-console.png differ diff --git a/js/src/doc/Debugger/config.sh b/js/src/doc/Debugger/config.sh new file mode 100644 index 000000000..eda4ed8d7 --- /dev/null +++ b/js/src/doc/Debugger/config.sh @@ -0,0 +1,66 @@ +### Description of Debugger docs: how to format, where to install. +### See js/src/doc/README.md for a description. + +base-url https://developer.mozilla.org/en-US/docs/Tools/ + +markdown Debugger-API.md Debugger-API + label 'debugger' "The Debugger API" + +markdown Conventions.md Debugger-API/Conventions + label 'conventions' "Debugger API: General Conventions" + label 'dbg code' '#debuggee-code' "Debugger API: General Conventions: Debuggee Code" + label 'cv' '#completion-values' "Debugger API: General Conventions: Completion Values" + label 'rv' '#resumption-values' "Debugger API: General Conventions: Resumption Values" + label 'timestamps' '#timestamps' "Debugger API: General Conventions: Timestamps" + label 'wouldrun' '#the-debugger.debuggeewouldrun-exception' "Debugger API: DebuggeeWouldRun" + +markdown Debugger.md Debugger-API/Debugger + label 'debugger-object' "The Debugger object" + label 'add' '#addDebuggee' "The Debugger object: addDebuggee" + +markdown Debugger.Environment.md Debugger-API/Debugger.Environment + label 'environment' "Debugger.Environment" + +markdown Debugger.Frame.md Debugger-API/Debugger.Frame + label 'frame' "Debugger.Frame" + label 'vf' '#visible-frames' "Debugger.Frame: Visible Frames" + label 'inv fr' '#invf' "Debugger.Frame: Invocation Frames" + label 'fr eval' '#eval' "Debugger.Frame: Eval" + +markdown Debugger.Object.md Debugger-API/Debugger.Object + label 'object' "Debugger.Object" + label 'allocation-site' '#allocationsite' "Debugger.Object: allocationSite" + +markdown Debugger.Script.md Debugger-API/Debugger.Script + label 'script' "Debugger.Script" + +markdown Debugger.Source.md Debugger-API/Debugger.Source + label 'source' "Debugger.Source" + +markdown Debugger.Memory.md Debugger-API/Debugger.Memory + label 'memory' "Debugger.Memory" + label 'tracking-allocs' '#trackingallocationsites' "Debugger.Memory: trackingAllocationSites" + label 'drain-alloc-log' '#drain-alloc-log' "Debugger.Memory: drainAllocationsLog" + label 'max-alloc-log' '#max-alloc-log' "Debugger.Memory: maxAllocationsLogLength" + label 'alloc-sampling-probability' '#alloc-sampling-probability' "Debugger.Memory: allocationSamplingProbability" + label 'take-census' '#take-census' "Debugger.Memory: takeCensus" + +markdown Tutorial-Debugger-Statement.md Debugger-API/Tutorial-Debugger-Statement + label 'tut debugger' "Tutorial: the debugger; statement" + +markdown Tutorial-Alloc-Log-Tree.md Debugger-API/Tutorial-Allocation-Log-Tree + label 'tut alloc log' "Tutorial: the allocation log" + +# Images: +RBASE=https://mdn.mozillademos.org/files +resource 'img-shadows' shadows.svg $RBASE/7225/shadows.svg +resource 'img-chrome-pref' enable-chrome-devtools.png $RBASE/7233/enable-chrome-devtools.png +resource 'img-scratchpad-browser' scratchpad-browser-environment.png $RBASE/7229/scratchpad-browser-environment.png +resource 'img-example-alert' debugger-alert.png $RBASE/7231/debugger-alert.png +resource 'img-alloc-plot' alloc-plot-console.png $RBASE/8461/alloc-plot-console.png + +# External links: +absolute-label 'protocol' https://wiki.mozilla.org/Remote_Debugging_Protocol "Remote Debugging Protocol" +absolute-label 'saved-frame' https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/SavedFrame "SavedFrame" +absolute-label 'bernoulli-trial' https://en.wikipedia.org/wiki/Bernoulli_trial "Bernoulli Trial" +absolute-label 'promise' https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise "Promise" diff --git a/js/src/doc/Debugger/debugger-alert.png b/js/src/doc/Debugger/debugger-alert.png new file mode 100644 index 000000000..2bf936224 Binary files /dev/null and b/js/src/doc/Debugger/debugger-alert.png differ diff --git a/js/src/doc/Debugger/enable-chrome-devtools.png b/js/src/doc/Debugger/enable-chrome-devtools.png new file mode 100644 index 000000000..033468991 Binary files /dev/null and b/js/src/doc/Debugger/enable-chrome-devtools.png differ diff --git a/js/src/doc/Debugger/scratchpad-browser-environment.png b/js/src/doc/Debugger/scratchpad-browser-environment.png new file mode 100644 index 000000000..534d0f950 Binary files /dev/null and b/js/src/doc/Debugger/scratchpad-browser-environment.png differ diff --git a/js/src/doc/Debugger/shadows.svg b/js/src/doc/Debugger/shadows.svg new file mode 100644 index 000000000..5774fc78f --- /dev/null +++ b/js/src/doc/Debugger/shadows.svg @@ -0,0 +1,997 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + Debugger + + + + + + + + + + + + Debugger.Object + Debugger.Environment + Debugger.Frame + Debugger.Object + Debugger.Object + Debugger.Script + + + + + global environment + + + global object: + Date; Math; ... + + + + + + + function alertLater(msg, delay) { setTimeout( function () { alert(msg); }, delay);} + + + + [[Code]]: + [[Scope]]: + + alertLater: + + + alertLater; + + + + + msg:delay: + 'xlerb'1000 + + + + + [[Code]]: + [[Scope]]: + + + + + + + anonymous() + + empty + + + + + + alert('xlerb') + + -- cgit v1.2.3