michael@0: # Debugger.Environment
michael@0:
michael@0: A `Debugger.Environment` instance represents a lexical environment,
michael@0: associating names with variables. Each [`Debugger.Frame`][frame] instance
michael@0: representing a debuggee frame has an associated environment object
michael@0: describing the variables in scope in that frame; and each
michael@0: [`Debugger.Object`][object] instance representing a debuggee function has an
michael@0: environment object representing the environment the function has closed
michael@0: over.
michael@0:
michael@0: ECMAScript environments form a tree, in which each local environment is
michael@0: parented by its enclosing environment (in ECMAScript terms, its 'outer'
michael@0: environment). We say an environment binds an identifier if that
michael@0: environment itself associates the identifier with a variable, independently
michael@0: of its outer environments. We say an identifier is in scope in an
michael@0: environment if the identifier is bound in that environment or any enclosing
michael@0: environment.
michael@0:
michael@0: SpiderMonkey creates `Debugger.Environment` instances as needed as the
michael@0: debugger inspects stack frames and function objects; calling
michael@0: `Debugger.Environment` as a function or constructor raises a `TypeError`
michael@0: exception.
michael@0:
michael@0: SpiderMonkey creates exactly one `Debugger.Environment` instance for each
michael@0: environment it presents via a given [`Debugger`][debugger-object] instance:
michael@0: if the debugger encounters the same environment through two different
michael@0: routes (perhaps two functions have closed over the same environment),
michael@0: SpiderMonkey presents the same `Debugger.Environment` instance to the
michael@0: debugger each time. This means that the debugger can use the `==` operator
michael@0: to recognize when two `Debugger.Environment` instances refer to the same
michael@0: environment in the debuggee, and place its own properties on a
michael@0: `Debugger.Environment` instance to store metadata about particular
michael@0: environments.
michael@0:
michael@0: (If more than one [`Debugger`][debugger-object] instance is debugging the
michael@0: same code, each [`Debugger`][debugger-object] gets a separate
michael@0: `Debugger.Environment` instance for a given environment. This allows the
michael@0: code using each [`Debugger`][debugger-object] instance to place whatever
michael@0: properties it likes on its own [`Debugger.Object`][object] instances,
michael@0: without worrying about interfering with other debuggers.)
michael@0:
michael@0: If a `Debugger.Environment` instance's referent is not a debuggee
michael@0: environment, then attempting to access its properties (other than
michael@0: `inspectable`) or call any its methods throws an instance of `Error`.
michael@0:
michael@0: `Debugger.Environment` instances protect their referents from the
michael@0: garbage collector; as long as the `Debugger.Environment` instance is
michael@0: live, the referent remains live. Garbage collection has no visible
michael@0: effect on `Debugger.Environment` instances.
michael@0:
michael@0:
michael@0: ## Accessor Properties of the Debugger.Environment Prototype Object
michael@0:
michael@0: A `Debugger.Environment` instance inherits the following accessor
michael@0: properties from its prototype:
michael@0:
michael@0: `inspectable`
michael@0: : True if this environment is a debuggee environment, and can therefore
michael@0: be inspected. False otherwise. All other properties and methods of
michael@0: `Debugger.Environment` instances throw if applied to a non-inspectable
michael@0: environment.
michael@0:
michael@0: `type`
michael@0: : The type of this environment object, one of the following values:
michael@0:
michael@0: * "declarative", indicating that the environment is a declarative
michael@0: environment record. Function calls, calls to `eval`, `let` blocks,
michael@0: `catch` blocks, and the like create declarative environment records.
michael@0:
michael@0: * "object", indicating that the environment's bindings are the
michael@0: properties of an object. The global object and DOM elements appear in
michael@0: the chain of environments via object environments. (Note that `with`
michael@0: statements have their own environment type.)
michael@0:
michael@0: * "with", indicating that the environment was introduced by a `with`
michael@0: statement.
michael@0:
michael@0: `parent`
michael@0: : The environment that encloses this one (the "outer" environment, in
michael@0: ECMAScript terminology), or `null` if this is the outermost environment.
michael@0:
michael@0: `object`
michael@0: : A [`Debugger.Object`][object] instance referring to the object whose
michael@0: properties this environment reflects. If this is a declarative
michael@0: environment record, this accessor throws a `TypeError` (since
michael@0: declarative environment records have no such object). Both `"object"`
michael@0: and `"with"` environments have `object` properties that provide the
michael@0: object whose properties they reflect as variable bindings.
michael@0:
michael@0: `callee`
michael@0: : If this environment represents the variable environment (the top-level
michael@0: environment within the function, which receives `var` definitions) for
michael@0: a call to a function f, then this property's value is a
michael@0: [`Debugger.Object`][object] instance referring to f. Otherwise,
michael@0: this property's value is `null`.
michael@0:
michael@0:
michael@0:
michael@0: ## Function Properties of the Debugger.Environment Prototype Object
michael@0:
michael@0: The methods described below may only be called with a `this` value
michael@0: referring to a `Debugger.Environment` instance; they may not be used as
michael@0: methods of other kinds of objects.
michael@0:
michael@0: `names()`
michael@0: : Return an array of strings giving the names of the identifiers bound by
michael@0: this environment. The result does not include the names of identifiers
michael@0: bound by enclosing environments.
michael@0:
michael@0: getVariable(name)
michael@0: : Return the value of the variable bound to name in this
michael@0: environment, or `undefined` if this environment does not bind
michael@0: name. Name must be a string that is a valid ECMAScript
michael@0: identifier name. The result is a debuggee value.
michael@0:
michael@0: JavaScript engines often omit variables from environments, to save space
michael@0: and reduce execution time. If the given variable should be in scope, but
michael@0: `getVariable` is unable to produce its value, it returns an ordinary
michael@0: JavaScript object (not a [`Debugger.Object`][object] instance) whose
michael@0: `optimizedOut` property is `true`.
michael@0:
michael@0: This is not an [invocation function][inv fr];
michael@0: if this call would cause debuggee code to run (say, because the
michael@0: environment is a `"with"` environment, and name refers to an
michael@0: accessor property of the `with` statement's operand), this call throws a
michael@0: [`Debugger.DebuggeeWouldRun`][wouldrun]
michael@0: exception.
michael@0:
michael@0: setVariable(name, value)
michael@0: : Store value as the value of the variable bound to name in
michael@0: this environment. Name must be a string that is a valid
michael@0: ECMAScript identifier name; value must be a debuggee value.
michael@0:
michael@0: If this environment binds no variable named name, throw a
michael@0: `ReferenceError`.
michael@0:
michael@0: This is not an [invocation function][inv fr];
michael@0: if this call would cause debuggee code to run, this call throws a
michael@0: [`Debugger.DebuggeeWouldRun`][wouldrun]
michael@0: exception.
michael@0:
michael@0: getVariableDescriptor(name)
michael@0: : Return an property descriptor describing the variable bound to
michael@0: name in this environment, of the sort returned by
michael@0: `Debugger.Object.prototype.getOwnPropertyDescriptor`. Name must
michael@0: be a string whose value is a valid ECMAScript identifier name.
michael@0:
michael@0: If this is an `"object"` or `"with"` environment record, this simply
michael@0: returns the descriptor for the given property of the environment's
michael@0: object. If this is a declarative environment record, this returns a
michael@0: descriptor reflecting the binding's mutability as the descriptor's
michael@0: `writable` property, and its deletability as the descriptor's
michael@0: `configurable` property. All declarative environment record bindings are
michael@0: marked as `enumerable`. (This isn't great; the semantics of variables
michael@0: in declarative enviroments don't really match those of properties, so
michael@0: writing code that operates properly on descriptors for either kind may
michael@0: be difficult.)
michael@0:
michael@0: If this environment binds no variable named name, throw a
michael@0: `ReferenceError`.
michael@0:
michael@0: defineVariable(name, descriptor)
michael@0: : Create or reconfigure the variable bound to name in this
michael@0: environment according to descriptor. Descriptor is the
michael@0: sort of value returned by `getVariableDescriptor`. On success, return
michael@0: `undefined`; on failure, throw an appropriate exception. Name
michael@0: must be a string whose value is a valid ECMAScript identifier name.
michael@0:
michael@0: If implementation restrictions prevent SpiderMonkey from creating or
michael@0: reconfiguring the variable as requested, this call throws an `Error`
michael@0: exception.
michael@0:
michael@0: deleteVariable(name)
michael@0: : Delete this environment's binding for name.
michael@0:
michael@0: If this environment binds no variable named name, throw a
michael@0: `ReferenceError`.
michael@0:
michael@0: If implementation restrictions prevent SpiderMonkey from deleting the
michael@0: variable as requested, this call throws an `Error` exception.
michael@0:
michael@0: find(name)
michael@0: : Return a reference to the innermost environment, starting with this
michael@0: environment, that binds name. If name is not in scope in
michael@0: this environment, return `null`. Name must be a string whose
michael@0: value is a valid ECMAScript identifier name.
michael@0:
michael@0: eval(code)
(future plan)
michael@0: : Evaluate code in this environment, and return a
michael@0: [completion value][cv] describing how it completed. Code is a
michael@0: string. All extant handler methods, breakpoints, watchpoints, and so on
michael@0: remain active during the call. This function follows the
michael@0: [invocation function conventions][inv fr].
michael@0:
michael@0: Code is interpreted as strict mode code when it contains a Use
michael@0: Strict Directive.
michael@0:
michael@0: If code is not strict mode code, then variable declarations in
michael@0: code affect this environment. (In the terms used by the
michael@0: ECMAScript specification, the `VariableEnvironment` of the execution
michael@0: context for the eval code is the `VariableEnvironment` this
michael@0: `Debugger.Environment` instance represents.) If implementation
michael@0: restrictions prevent SpiderMonkey from extending this environment as
michael@0: requested, this call throws an `Error` exception.
michael@0:
michael@0: evalWithBindings(code, bindings)
(future plan)
michael@0: : Like `eval`, but evaluate code in this environment, extended with
michael@0: bindings from the object bindings. For each own enumerable
michael@0: property of bindings named name whose value is
michael@0: value, include a variable in the environment in which code
michael@0: is evaluated named name, whose value is value. Each
michael@0: value must be a debuggee value. (This is not like a `with`
michael@0: statement: code may access, assign to, and delete the introduced
michael@0: bindings without having any effect on the bindings object.)
michael@0:
michael@0: This method allows debugger code to introduce temporary bindings that
michael@0: are visible to the given debuggee code and which refer to debugger-held
michael@0: debuggee values, and do so without mutating any existing debuggee
michael@0: environment.
michael@0:
michael@0: Note that, like `eval`, declarations in the code passed to
michael@0: `evalWithBindings` affect this environment, even as code is
michael@0: evaluated with bindings visible. (In the terms used by the
michael@0: ECMAScript specification, the `VariableEnvironment` of the execution
michael@0: context for the eval code is the `VariableEnvironment` this environment
michael@0: represents, and the bindings appear in a new declarative
michael@0: environment, which is the eval code's `LexicalEnvironment`.) If
michael@0: implementation restrictions prevent SpiderMonkey from extending this
michael@0: environment as requested, this call throws an `Error` exception.
michael@0:
michael@0: