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
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
instance may actually have several Debugger.Object
instances: one for each compartment from which the referent is viewed.
If more than one Debugger
instance is debugging the same code, each Debugger
gets a separate Debugger.Object
instance for a given object. This allows the code using each Debugger
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), ornull
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
andname
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: go.p = function () {}; // display name: o.pvar 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, anda<
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'sparameterNames
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
instance. If the referent is a function proxy or not debuggee code, this isundefined
.environment
If the referent is a function that is debuggee code, a
Debugger.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 isundefined
.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 isnull
.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 thisDebugger.Object
instance. The same metadata object is returned each time for a givenDebugger.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; 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
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 standardObject.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 itsvalue
,get
, andset
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
, andset
properties of attributes must be debuggee values. (This function behaves likeObject.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 standardObject.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 standardObject.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 anDebugger.Object
instance. The new object's properties are as given by properties, as if properties were passed toDebugger.Object.prototype.defineProperties
, with the newDebugger.Object
instance as thethis
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 thisDebugger.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 aDebugger.Object
instance d and an object o, the calld.makeDebuggeeValue(o)
returns aDebugger.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 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 appropriatethis
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 aTypeError
. This function follows the invocation function conventions.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 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 appropriatethis
value itself. Arguments must either be an array (in the debugger) of debuggee values, ornull
orundefined
, 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 aTypeError
. This function follows the invocation function conventions.evalInGlobal(code, [options])
If the referent is a global object, evaluate code in that global environment, and return a completion value 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. 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
.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 awith
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 toevalInGlobalWithBindings
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, theVariableEnvironment
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'sLexicalEnvironment
.)The options argument is as for
Debugger.Frame.prototype.eval
.asEnvironment()
If the referent is a global object, return the
Debugger.Environment
instance representing the referent as a variable environment for evaluating code. If the referent is not a global object, throw aTypeError
.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, 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
, andset
properties in descriptors, which are debuggee values; they are the sort of value expected byDebugger.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
instance to which thisDebugger.Object
instance belongs; disabling theDebugger
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 forDebugger.Object.prototype.setObjectWatchpoint
, except that it does not receiveextensionsPrevented
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 aDebugger.Object
instance referring to the wrapped object. If we are not permitted to unwrap the referent, returnnull
. If the referent is not a wrapper, return thisDebugger.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 HTML5WindowProxy
object). This makesunsafeDereference
more useful in producing values appropriate for direct use by debuggee code, without using invocation functions.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 viaDebugger.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 useDebugger.Object
instances, but use this method to pass direct object references to code that has not yet been updated.