diff -r 000000000000 -r 6474c204b198 js/src/doc/Debugger/Debugger.Object.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/src/doc/Debugger/Debugger.Object.md Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,534 @@ +# Debugger.Object + +A `Debugger.Object` instance represents an object in the debuggee, +providing reflection-oriented methods to inspect and modify its referent. +The referent's properties do not appear directly as properties of the +`Debugger.Object` instance; the debugger can access them only through +methods like `Debugger.Object.prototype.getOwnPropertyDescriptor` and +`Debugger.Object.prototype.defineProperty`, ensuring that the debugger will +not inadvertently invoke the referent's getters and setters. + +SpiderMonkey creates exactly one `Debugger.Object` instance for each +debuggee object it presents to a given [`Debugger`][debugger-object] +instance: if the debugger encounters the same object through two different +routes (perhaps two functions are called on the same object), SpiderMonkey +presents the same `Debugger.Object` instance to the debugger each time. +This means that the debugger can use the `==` operator to recognize when +two `Debugger.Object` instances refer to the same debuggee object, and +place its own properties on a `Debugger.Object` instance to store metadata +about particular debuggee objects. + +JavaScript code in different compartments can have different views of the +same object. For example, in Firefox, code in privileged compartments sees +content DOM element objects without redefinitions or extensions made to +that object's properties by content code. (In Firefox terminology, +privileged code sees the element through an "xray wrapper".) To ensure that +debugger code sees each object just as the debuggee would, each +`Debugger.Object` instance presents its referent as it would be seen from a +particular compartment. This "viewing compartment" is chosen to match the +way the debugger came across the referent. As a consequence, a single +[`Debugger`][debugger-object] instance may actually have several +`Debugger.Object` instances: one for each compartment from which the +referent is viewed. + +If more than one [`Debugger`][debugger-object] instance is debugging the +same code, each [`Debugger`][debugger-object] gets a separate +`Debugger.Object` instance for a given object. This allows the code using +each [`Debugger`][debugger-object] instance to place whatever properties it +likes on its own `Debugger.Object` instances, without worrying about +interfering with other debuggers. + +While most `Debugger.Object` instances are created by SpiderMonkey in the +process of exposing debuggee's behavior and state to the debugger, the +debugger can use `Debugger.Object.prototype.makeDebuggeeValue` to create +`Debugger.Object` instances for given debuggee objects, or use +`Debugger.Object.prototype.copy` and `Debugger.Object.prototype.create` to +create new objects in debuggee compartments, allocated as if by particular +debuggee globals. + +`Debugger.Object` instances protect their referents from the garbage +collector; as long as the `Debugger.Object` instance is live, the referent +remains live. This means that garbage collection has no visible effect on +`Debugger.Object` instances. + + +## Accessor Properties of the Debugger.Object prototype + +A `Debugger.Object` instance inherits the following accessor properties +from its prototype: + +`proto` +: The referent's prototype (as a new `Debugger.Object` instance), or + `null` if it has no prototype. + +`class` +: A string naming the ECMAScript `[[Class]]` of the referent. + +`callable` +: `true` if the referent is a callable object (such as a function or a + function proxy); false otherwise. + +`name` +: The name of the referent, if it is a named function. If the referent is + an anonymous function, or not a function at all, this is `undefined`. + + This accessor returns whatever name appeared after the `function` + keyword in the source code, regardless of whether the function is the + result of instantiating a function declaration (which binds the + function to its name in the enclosing scope) or evaluating a function + expression (which binds the function to its name only within the + function's body). + +`displayName` +: The referent's display name, if the referent is a function with a + display name. If the referent is not a function, or if it has no display + name, this is `undefined`. + + If a function has a given name, its display name is the same as its + given name. In this case, the `displayName` and `name` properties are + equal. + + If a function has no name, SpiderMonkey attempts to infer an appropriate + name for it given its context. For example: + + function f() {} // display name: f (the given name) + var g = function () {}; // display name: g + o.p = function () {}; // display name: o.p + var q = { + r: function () {} // display name: q.r + }; + + Note that the display name may not be a proper JavaScript identifier, + or even a proper expression: we attempt to find helpful names even when + the function is not immediately assigned as the value of some variable + or property. Thus, we use a/b to refer to + the b defined within a, and a< to + refer to a function that occurs somewhere within an expression that is + assigned to a. For example: + + function h() { + var i = function() {}; // display name: h/i + f(function () {}); // display name: h/< + } + var s = f(function () {}); // display name: s< + +`parameterNames` +: If the referent is a debuggee function, the names of the its parameters, + as an array of strings. If the referent is not a debuggee function, or + not a function at all, this is `undefined`. + + If the referent is a host function for which parameter names are not + available, return an array with one element per parameter, each of which + is `undefined`. + + If the referent is a function proxy, return an empty array. + + If the referent uses destructuring parameters, then the array's elements + reflect the structure of the parameters. For example, if the referent is + a function declared in this way: + + function f(a, [b, c], {d, e:f}) { ... } + + then this `Debugger.Object` instance's `parameterNames` property would + have the value: + + ["a", ["b", "c"], {d:"d", e:"f"}] + +`script` +: If the referent is a function that is debuggee code, this is that + function's script, as a [`Debugger.Script`][script] instance. If the + referent is a function proxy or not debuggee code, this is `undefined`. + +`environment` +: If the referent is a function that is debuggee code, a + [`Debugger.Environment`][environment] instance representing the lexical + environment enclosing the function when it was created. If the referent + is a function proxy or not debuggee code, this is `undefined`. + +`proxyHandler` +: If the referent is a proxy whose handler object was allocated by + debuggee code, this is its handler object—the object whose methods are + invoked to implement accesses of the proxy's properties. If the referent + is not a proxy whose handler object was allocated by debuggee code, this + is `null`. + +`proxyCallTrap` +: If the referent is a function proxy whose handler object was allocated + by debuggee code, this is its call trap function—the function called + when the function proxy is called. If the referent is not a function + proxy whose handler object was allocated by debuggee code, this is + `null`. + +`proxyConstructTrap` +: If the referent is a function proxy whose handler object was allocated + by debuggee code, its construction trap function—the function called + when the function proxy is called via a `new` expression. If the + referent is not a function proxy whose handler object was allocated by + debuggee code, this is `null`. + +`global` +: A `Debugger.Object` instance referring to the global object in whose + scope the referent was allocated. This does not unwrap cross-compartment + wrappers: if the referent is a wrapper, the result refers to the + wrapper's global, not the wrapped object's global. The result refers to + the global directly, not via a wrapper. + +`hostAnnotations` +: A JavaScript object providing further metadata about the referent, or + `null` if none is available. The metadata object is in the same + compartment as this `Debugger.Object` instance. The same metadata + object is returned each time for a given `Debugger.Object` instance. + + A typical JavaScript embedding provides "host objects" to expose + application-specific functionality to scripts. The `hostAnnotations` + accessor consults the embedding for additional information about the + referent that might be of interest to the debugger. The returned + object's properties' meanings are up to the embedding. For example, a + web browser might provide host annotations for global objects to + distinguish top-level windows, iframes, and internal JavaScript scopes. + + By convention, host annotation objects have a string-valued `"type"` + property that, taken together with the object's class, indicate what + sort of thing the referent is. The host annotation object's other + properties provide further details, as appropriate for the type. For + example, in Firefox, a metadata object for a JavaScript Module's global + object might look like this: + + { "type":"jsm", "uri":"resource:://gre/modules/XPCOMUtils.jsm" } + + Firefox provides [DebuggerHostAnnotationsForFirefox annotations] for its + host objects. + + + +## Function Properties of the Debugger.Object prototype + +The functions described below may only be called with a `this` value +referring to a `Debugger.Object` instance; they may not be used as methods +of other kinds of objects. The descriptions use "referent" to mean "the +referent of this `Debugger.Object` instance". + +Unless otherwise specified, these methods are not +[invocation functions][inv fr]; if a call would cause debuggee code to run +(say, because it gets or sets an accessor property whose handler is +debuggee code, or because the referent is a proxy whose traps are debuggee +code), the call throws a [`Debugger.DebuggeeWouldRun`][wouldrun] exception. + +getProperty(name) +: Return the value of the referent's property named name, or + `undefined` if it has no such property. Name must be a string. + The result is a debuggee value. + +setProperty(name, value) +: Store value as the value of the referent's property named + name, creating the property if it does not exist. Name + must be a string; value must be a debuggee value. + +getOwnPropertyDescriptor(name) +: Return a property descriptor for the property named name of the + referent. If the referent has no such property, return `undefined`. + (This function behaves like the standard + `Object.getOwnPropertyDescriptor` function, except that the object being + inspected is implicit; the property descriptor returned is allocated as + if by code scoped to the debugger's global object (and is thus in the + debugger's compartment); and its `value`, `get`, and `set` properties, + if present, are debuggee values.) + +`getOwnPropertyNames()` +: Return an array of strings naming all the referent's own properties, as + if Object.getOwnPropertyNames(referent) had been + called in the debuggee, and the result copied in the scope of the + debugger's global object. + +defineProperty(name, attributes) +: Define a property on the referent named name, as described by + the property descriptor descriptor. Any `value`, `get`, and + `set` properties of attributes must be debuggee values. (This + function behaves like `Object.defineProperty`, except that the target + object is implicit, and in a different compartment from the function + and descriptor.) + +defineProperties(properties) +: Add the properties given by properties to the referent. (This + function behaves like `Object.defineProperties`, except that the target + object is implicit, and in a different compartment from the + properties argument.) + +deleteProperty(name) +: Remove the referent's property named name. Return true if the + property was successfully removed, or if the referent has no such + property. Return false if the property is non-configurable. + +`seal()` +: Prevent properties from being added to or deleted from the referent. + Return this `Debugger.Object` instance. (This function behaves like the + standard `Object.seal` function, except that the object to be sealed is + implicit and in a different compartment from the caller.) + +`freeze()` +: Prevent properties from being added to or deleted from the referent, and + mark each property as non-writable. Return this `Debugger.Object` + instance. (This function behaves like the standard `Object.freeze` + function, except that the object to be sealed is implicit and in a + different compartment from the caller.) + +`preventExtensions()` +: Prevent properties from being added to the referent. (This function + behaves like the standard `Object.preventExtensions` function, except + that the object to operate on is implicit and in a different compartment + from the caller.) + +`isSealed()` +: Return true if the referent is sealed—that is, if it is not extensible, + and all its properties have been marked as non-configurable. (This + function behaves like the standard `Object.isSealed` function, except + that the object inspected is implicit and in a different compartment + from the caller.) + +`isFrozen()` +: Return true if the referent is frozen—that is, if it is not extensible, + and all its properties have been marked as non-configurable and + read-only. (This function behaves like the standard `Object.isFrozen` + function, except that the object inspected is implicit and in a + different compartment from the caller.) + +`isExtensible()` +: Return true if the referent is extensible—that is, if it can have new + properties defined on it. (This function behaves like the standard + `Object.isExtensible` function, except that the object inspected is + implicit and in a different compartment from the caller.) + +copy(value) +: Apply the HTML5 "structured cloning" algorithm to create a copy of + value in the referent's global object (and thus in the referent's + compartment), and return a `Debugger.Object` instance referring to the + copy. + + Note that this returns primitive values unchanged. This means you can + use `Debugger.Object.prototype.copy` as a generic "debugger value to + debuggee value" conversion function—within the limitations of the + "structured cloning" algorithm. + +create(prototype, [properties]) +: Create a new object in the referent's global (and thus in the + referent's compartment), and return a `Debugger.Object` referring to + it. The new object's prototype is prototype, which must be an + `Debugger.Object` instance. The new object's properties are as given by + properties, as if properties were passed to + `Debugger.Object.prototype.defineProperties`, with the new + `Debugger.Object` instance as the `this` value. + +makeDebuggeeValue(value) +: Return the debuggee value that represents value in the debuggee. + If value is a primitive, we return it unchanged; if value + is an object, we return the `Debugger.Object` instance representing + that object, wrapped appropriately for use in this `Debugger.Object`'s + referent's compartment. + + Note that, if value is an object, it need not be one allocated + in a debuggee global, nor even a debuggee compartment; it can be any + object the debugger wishes to use as a debuggee value. + + As described above, each `Debugger.Object` instance presents its + referent as viewed from a particular compartment. Given a + `Debugger.Object` instance d and an object o, the call + d.makeDebuggeeValue(o) returns a + `Debugger.Object` instance that presents o as it would be seen + by code in d's compartment. + +decompile([pretty]) +: If the referent is a function that is debuggee code, return the + JavaScript source code for a function definition equivalent to the + referent function in its effect and result, as a string. If + pretty is present and true, produce indented code with line + breaks. If the referent is not a function that is debuggee code, return + `undefined`. + +call(this, argument, ...) +: If the referent is callable, call it with the given this value + and argument values, and return a [completion value][cv] + describing how the call completed. This should be a debuggee + value, or `{ asConstructor: true }` to invoke the referent as a + constructor, in which case SpiderMonkey provides an appropriate `this` + value itself. Each argument must be a debuggee value. All extant + handler methods, breakpoints, watchpoints, and so on remain active + during the call. If the referent is not callable, throw a `TypeError`. + This function follows the [invocation function conventions][inv fr]. + +apply(this, arguments) +: If the referent is callable, call it with the given this value + and the argument values in arguments, and return a + [completion value][cv] describing how the call completed. This + should be a debuggee value, or `{ asConstructor: true }` to invoke + function as a constructor, in which case SpiderMonkey provides + an appropriate `this` value itself. Arguments must either be an + array (in the debugger) of debuggee values, or `null` or `undefined`, + which are treated as an empty array. All extant handler methods, + breakpoints, watchpoints, and so on remain active during the call. If + the referent is not callable, throw a `TypeError`. This function + follows the [invocation function conventions][inv fr]. + +evalInGlobal(code, [options]) +: If the referent is a global object, evaluate code in that global + environment, and return a [completion value][cv] describing how it completed. + Code is a string. All extant handler methods, breakpoints, + watchpoints, and so on remain active during the call. This function + follows the [invocation function conventions][inv fr]. + If the referent is not a global object, throw a `TypeError` exception. + + Code is interpreted as strict mode code when it contains a Use + Strict Directive. + + If code is not strict mode code, then variable declarations in + code affect the referent global object. (In the terms used by the + ECMAScript specification, the `VariableEnvironment` of the execution + context for the eval code is the referent.) + + The options argument is as for [`Debugger.Frame.prototype.eval`][fr eval]. + +evalInGlobalWithBindings(code, bindings, [options]) +: Like `evalInGlobal`, but evaluate code using the referent as the + variable object, but with a lexical environment extended with bindings + from the object bindings. For each own enumerable property of + bindings named name whose value is value, include a + variable in the lexical environment in which code is evaluated + named name, whose value is value. Each value must + be a debuggee value. (This is not like a `with` statement: code + may access, assign to, and delete the introduced bindings without having + any effect on the bindings object.) + + This method allows debugger code to introduce temporary bindings that + are visible to the given debuggee code and which refer to debugger-held + debuggee values, and do so without mutating any existing debuggee + environment. + + Note that, like `evalInGlobal`, if the code passed to + `evalInGlobalWithBindings` is not strict mode code, then any + declarations it contains affect the referent global object, even as + code is evaluated in an environment extended according to + bindings. (In the terms used by the ECMAScript specification, the + `VariableEnvironment` of the execution context for non-strict eval code + is the referent, and the bindings appear in a new declarative + environment, which is the eval code's `LexicalEnvironment`.) + + The options argument is as for [`Debugger.Frame.prototype.eval`][fr eval]. + +`asEnvironment()` +: If the referent is a global object, return the [`Debugger.Environment`][environment] + instance representing the referent as a variable environment for + evaluating code. If the referent is not a global object, throw a + `TypeError`. + +setObjectWatchpoint(handler) (future plan) +: Set a watchpoint on all the referent's own properties, reporting events + by calling handler's methods. Any previous watchpoint handler on + this `Debugger.Object` instance is replaced. If handler is null, + the referent is no longer watched. Handler may have the following + methods, called under the given circumstances: + + add(frame, name, descriptor) + : A property named name has been added to the referent. + Descriptor is a property descriptor of the sort accepted by + `Debugger.Object.prototype.defineProperty`, giving the newly added + property's attributes. + + delete(frame, name) + : The property named name is about to be deleted from the referent. + + change(frame, name, oldDescriptor, newDescriptor) + : The existing property named name on the referent is being changed + from those given by oldDescriptor to those given by + newDescriptor. This handler method is only called when attributes + of the property other than its value are being changed; if only the + value is changing, SpiderMonkey calls the handler's `set` method. + + set(frame, oldValue, newValue) + : The data property named name of the referent is about to have its + value changed from oldValue to newValue. + + SpiderMonkey only calls this method on assignments to data properties + that will succeed; assignments to un-writable data properties fail + without notifying the debugger. + + extensionsPrevented(frame) + : The referent has been made non-extensible, as if by a call to + `Object.preventExtensions`. + + For all watchpoint handler methods: + + * Handler calls receive the handler object itself as the `this` value. + + * The frame argument is the current stack frame, whose code is + about to perform the operation on the object being reported. + + * If the method returns `undefined`, then SpiderMonkey makes the announced + change to the object, and continues execution normally. If the method + returns an object: + + * If the object has a `superseded` property whose value is a true value, + then SpiderMonkey does not make the announced change. + + * If the object has a `resume` property, its value is taken as a + [resumption value][rv], indicating how + execution should proceed. (However, `return` resumption values are not + supported.) + + * If a given method is absent from handler, then events of that + sort are ignored. The watchpoint consults handler's properties + each time an event occurs, so adding methods to or removing methods from + handler after setting the watchpoint enables or disables + reporting of the corresponding events. + + * Values passed to handler's methods are debuggee values. + Descriptors passed to handler's methods are ordinary objects in + the debugger's compartment, except for `value`, `get`, and `set` + properties in descriptors, which are debuggee values; they are the sort + of value expected by `Debugger.Object.prototype.defineProperty`. + + * Watchpoint handler calls are cross-compartment, intra-thread calls: the + call takes place in the same thread that changed the property, and in + handler's method's compartment (typically the same as the + debugger's compartment). + + The new watchpoint belongs to the [`Debugger`][debugger-object] instance to which this + `Debugger.Object` instance belongs; disabling the [`Debugger`][debugger-object] instance + disables this watchpoint. + +`clearObjectWatchpoint()` (future plan) +: Remove any object watchpoint set on the referent. + +setPropertyWatchpoint(name, handler) (future plan) +: Set a watchpoint on the referent's property named name, reporting + events by calling handler's methods. Any previous watchpoint + handler on this property for this `Debugger.Object` instance is + replaced. If handler is null, the property is no longer watched. + Handler is as described for + `Debugger.Object.prototype.setObjectWatchpoint`, except that it does not + receive `extensionsPrevented` events. + +clearPropertyWatchpoint(name) (future plan) +: Remove any watchpoint set on the referent's property named name. + +`unwrap()` +: If the referent is a wrapper that this `Debugger.Object`'s compartment + is permitted to unwrap, return a `Debugger.Object` instance referring to + the wrapped object. If we are not permitted to unwrap the referent, + return `null`. If the referent is not a wrapper, return this + `Debugger.Object` instance unchanged. + +`unsafeDereference()` +: Return the referent of this `Debugger.Object` instance. + + If the referent is an inner object (say, an HTML5 `Window` object), + return the corresponding outer object (say, the HTML5 `WindowProxy` + object). This makes `unsafeDereference` more useful in producing values + appropriate for direct use by debuggee code, without using [invocation functions][inv fr]. + + This method pierces the membrane of `Debugger.Object` instances meant to + protect debugger code from debuggee code, and allows debugger code to + access debuggee objects through the standard cross-compartment wrappers, + rather than via `Debugger.Object`'s reflection-oriented interfaces. This + method makes it easier to gradually adapt large code bases to this + Debugger API: adapted portions of the code can use `Debugger.Object` + instances, but use this method to pass direct object references to code + that has not yet been updated.