Debugger.Object

Debugger.Object 实例代表调试目标中的一个对象,提供面向反射的方法来检查和修改其引用对象。引用对象的属性不会直接显示为 Debugger.Object 实例的属性;调试器只能通过诸如 Debugger.Object.prototype.getOwnPropertyDescriptorDebugger.Object.prototype.defineProperty 之类的方法访问它们,从而确保调试器不会无意中调用引用对象的 getter 和 setter。

SpiderMonkey 为每个它提供给给定 Debugger 实例的调试目标对象创建恰好一个 Debugger.Object 实例:如果调试器通过两种不同的途径遇到同一个对象(也许两个函数被调用在同一个对象上),SpiderMonkey 会每次都向调试器呈现相同的 Debugger.Object 实例。这意味着调试器可以使用 == 运算符来识别两个 Debugger.Object 实例何时引用同一个调试目标对象,并在 Debugger.Object 实例上放置自己的属性来存储有关特定调试目标对象的元数据。

不同区隔中的 JavaScript 代码可以对同一个对象有不同的视图。例如,在 Firefox 中,特权区隔中的代码会看到内容 DOM 元素对象,而不会重新定义或扩展内容代码对该对象属性所做的更改。(在 Firefox 术语中,特权代码通过“X 光包装器”看到该元素。)为了确保调试器代码像调试目标一样看到每个对象,每个 Debugger.Object 实例都以从特定区隔中看到的形式呈现其引用对象。这个“查看区隔”的选择方式与调试器遇到引用对象的方式相匹配。因此,一个 Debugger 实例实际上可能有多个 Debugger.Object 实例:每个查看引用对象的区隔一个。

如果多个 Debugger 实例正在调试相同的代码,则每个 Debugger 为给定对象获取一个单独的 Debugger.Object 实例。这允许使用每个 Debugger 实例的代码在其自己的 Debugger.Object 实例上放置任何它喜欢的属性,而无需担心干扰其他调试器。

虽然大多数 Debugger.Object 实例是由 SpiderMonkey 在将调试目标的行为和状态暴露给调试器的过程中创建的,但调试器可以使用 Debugger.Object.prototype.makeDebuggeeValue 为给定的调试目标对象创建 Debugger.Object 实例,或者使用 Debugger.Object.prototype.copyDebugger.Object.prototype.create 在调试目标区隔中创建新对象,就像由特定的调试目标全局对象分配一样。

Debugger.Object 实例保护其引用对象免受垃圾回收器的影响;只要 Debugger.Object 实例处于活动状态,引用对象就会保持活动状态。这意味着垃圾回收对 Debugger.Object 实例没有可见的影响。

Debugger.Object 原型的访问器属性

Debugger.Object 实例从其原型继承以下访问器属性

proto

引用对象的原型(作为一个新的 Debugger.Object 实例),或者如果它没有原型则为 null。如果引用对象是脚本代理或其他类型的奇特对象(例如不透明包装器),则此访问器可能会抛出异常。

class

一个字符串,命名引用对象的 ECMAScript [[Class]]

callable

如果引用对象是可调用对象(例如函数或函数代理),则为 true;否则为 false。

name

引用对象的名称,如果它是命名函数。如果引用对象是匿名函数,或者根本不是函数,则为 undefined

此访问器返回源代码中 function 关键字后出现的任何名称,无论该函数是实例化函数声明(将函数绑定到其封闭作用域中的名称)的结果还是评估函数表达式(将函数绑定到其名称仅在函数体内的结果)。

displayName

引用对象的显示名称,如果引用对象是具有显示名称的函数。如果引用对象不是函数,或者没有显示名称,则为 undefined

如果函数具有给定名称,则其显示名称与其给定名称相同。在这种情况下,displayNamename 属性相等。

如果函数没有名称,SpiderMonkey 会尝试根据其上下文推断一个合适的名称。例如

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
};

请注意,显示名称可能不是正确的 JavaScript 标识符,甚至不是正确的表达式:我们尝试找到有用的名称,即使函数没有立即被分配为某个变量或属性的值。因此,我们使用 a/b 来指代在 a 中定义的 b,并使用 a< 来指代出现在分配给 a 的表达式的某个地方的函数。例如

function h() {
  var i = function() {};    // display name: h/i
  f(function () {});        // display name: h/<
}
var s = f(function () {});  // display name: s<``</pre>
parameterNames

如果引用对象是调试目标函数,则其参数的名称,作为字符串数组。如果引用对象不是调试目标函数,或者根本不是函数,则为 undefined

如果引用对象是主机函数,且参数名称不可用,则返回一个数组,其中每个参数一个元素,每个元素都是 undefined

如果引用对象是函数代理,则返回一个空数组。

如果引用对象使用解构参数,则数组的元素反映参数的结构。例如,如果引用对象是这样声明的函数

function f(a, [b, c], {d, e:f}) { ... }

那么此 Debugger.Object 实例的 parameterNames 属性将具有以下值

["a", ["b", "c"], {d:"d", e:"f"}]
script

如果引用对象是调试目标代码的函数,则为该函数的脚本,作为 Debugger.Script 实例。如果引用对象是函数代理或不是调试目标代码,则为 undefined

environment

如果引用对象是调试目标代码的函数,则为 Debugger.Environment 实例,表示创建函数时封闭该函数的词法环境。如果引用对象是函数代理或不是调试目标代码,则为 undefined

errorMessageName

如果引用对象是用引擎内部消息模板创建的错误,则为一个字符串,表示模板的名称;否则为 undefined

errorLineNumber

如果引用对象是 Error 对象,则为创建引用对象的行号;否则为 undefined

errorColumnNumber

如果引用对象是 Error 对象,则为创建引用对象的列号;否则为 undefined

isBoundFunction

如果引用对象是调试目标函数,则如果引用对象是绑定函数,则返回 true;否则返回 false。如果引用对象不是调试目标函数,或者根本不是函数,则改为返回 undefined

isArrowFunction

如果引用对象是调试目标函数,则如果引用对象是箭头函数,则返回 true;否则返回 false。如果引用对象不是调试目标函数,或者根本不是函数,则改为返回 undefined

isGeneratorFunction

如果引用对象是调试目标函数,则如果引用对象是用 function* 表达式或语句创建的,则返回 true,或者如果它是其他类型的函数则返回 false。如果引用对象不是调试目标函数,或者根本不是函数,则为 undefined。(这始终等于 obj.script.isGeneratorFunction,假设 obj.scriptDebugger.Script。)

isAsyncFunction

如果引用对象是调试目标函数,则如果引用对象是用 async function 表达式或语句定义的,则返回 true,或者如果它是其他类型的函数则返回 false。如果引用对象不是调试目标函数,或者根本不是函数,则为 undefined。(这始终等于 obj.script.isAsyncFunction,假设 obj.scriptDebugger.Script。)

isPromise

如果引用对象是 Promise,则为 true;否则为 false

boundTargetFunction

如果引用对象是绑定调试目标函数,则为其目标函数——绑定到特定 this 对象的函数。如果引用对象不是绑定函数,不是调试目标函数,或者根本不是函数,则为 undefined

boundThis

如果引用对象是绑定调试目标函数,则为其绑定的 this 值。如果引用对象不是绑定函数,不是调试目标函数,或者根本不是函数,则为 undefined

boundArguments

如果引用对象是绑定调试目标函数,则为一个数组(在调试器对象的区隔中),其中包含其绑定的 arguments 对象的调试目标值。如果引用对象不是绑定函数,不是调试目标函数,或者根本不是函数,则为 undefined

isProxy

如果引用对象是(脚本)代理,无论是否已撤销,都返回 true。如果引用对象不是(脚本)代理,则返回 false

proxyTarget

如果引用对象是一个未撤销的(脚本化的)代理,则返回一个引用 ECMAScript [[ProxyTarget]]Debugger.Object 实例。如果引用对象是一个已撤销的(脚本化的)代理,则返回 null。如果引用对象不是一个(脚本化的)代理,则返回 undefined

proxyHandler

如果引用对象是一个未撤销的(脚本化的)代理,则返回一个引用 ECMAScript [[ProxyHandler]]Debugger.Object 实例。如果引用对象是一个已撤销的(脚本化的)代理,则返回 null。如果引用对象不是一个(脚本化的)代理,则返回 undefined

promiseState

如果引用对象是一个 Promise,则返回一个字符串,指示该 Promise 是处于挂起状态,还是已完成或已拒绝。此字符串取以下值之一

  • "pending",如果 Promise 处于挂起状态。

  • "fulfilled",如果 Promise 已完成。

  • "rejected",如果 Promise 已拒绝。

如果引用对象不是一个 Promise,则抛出一个 TypeError

promiseValue

返回一个表示 Promise 已完成时的值的调试器值。

如果引用对象不是一个 Promise,或者 Promise 未完成,则抛出一个 TypeError

promiseReason

返回一个表示 Promise 已拒绝时的值的调试器值。

如果引用对象不是一个 Promise,或者 Promise 未拒绝,则抛出一个 TypeError

promiseAllocationSite

如果引用对象是一个 Promise,则这是在 promise 分配时捕获的 JavaScript 执行栈。如果 promise 不是从脚本创建的,则此值可能返回 null。如果引用对象不是一个 Promise,则抛出一个 TypeError 异常。

promiseResolutionSite

如果引用对象是一个 Promise,则这是在 promise 解决时捕获的 JavaScript 执行栈。如果 promise 不是通过从脚本调用其 resolvereject 解决函数来解决的,则此值可能返回 null。如果引用对象不是一个 Promise,则抛出一个 TypeError 异常。

promiseID

如果引用对象是一个 Promise,则这是该 Promise 的进程唯一标识符。使用 e10s,如果这些实例是在不同的进程中创建的,则可能会将相同的 id 分配给多个 Promise 实例。如果引用对象不是一个 Promise,则抛出一个 TypeError 异常。

promiseDependentPromises

如果引用对象是一个 Promise,则这是一个 Array,其中包含 Debugger.Objects,这些对象引用直接依赖于引用 Promise 的 promise。这些是

  1. promise 上 then() 调用的返回值。

  2. 如果引用 Promise 作为参数之一传递到 Promise.all() 中,则返回其返回值。

  3. 如果引用 Promise 作为参数之一传递到 Promise.race() 中,则返回其返回值。

一旦 Promise 已解决,它通常会通知其依赖的 promise 并忘记它们,因此这在挂起的 promise 上最有用。

请注意,该 Array 只包含直接依赖于引用 Promise 的 promise。它不包含依赖于依赖于引用 Promise 的 promise 的 promise。

如果引用对象不是一个 Promise,则抛出一个 TypeError 异常。

promiseLifetime

如果引用对象是一个 Promise,则这是自创建 Promise 以来经过的毫秒数。如果引用对象不是一个 Promise,则抛出一个 TypeError 异常。

promiseTimeToResolution

如果引用对象是一个 Promise,则这是从创建 Promise 到其解决之间经过的毫秒数。如果引用对象尚未解决或不是 Promise,则抛出一个 TypeError 异常。

global

一个引用分配引用对象作用域的全局对象的 Debugger.Object 实例。这不会解包跨隔间包装器:如果引用对象是包装器,则结果将引用包装器的全局对象,而不是被包装对象的全局对象。结果直接引用全局对象,而不是通过包装器。

allocationSite

如果在分配此 Debugger.Object 的引用对象时启用了 对象分配站点跟踪,则返回在分配时捕获的 JavaScript 执行栈。否则,返回 null

Debugger.Object 原型的函数属性

下面描述的函数只能使用引用 Debugger.Object 实例的 this 值来调用;它们不能用作其他类型的对象的函数。这些描述使用“引用对象”来表示“此 Debugger.Object 实例的引用对象”。

除非另有说明,否则这些方法不是 调用函数;如果调用会导致调试器代码运行(例如,因为它获取或设置了其处理程序为调试器代码的访问器属性,或者因为引用对象是一个其陷阱为调试器代码的代理),则调用会抛出一个 Debugger.DebuggeeWouldRun 异常。

如果引用对象不是原生对象,则这些方法可能会抛出异常。即使是像 isExtensible 这样的简单访问器,如果引用对象是代理或某种异域对象(如不透明包装器),也可能会抛出异常。

getProperty(key, [receiver])

返回一个完成值,其中“return”是引用对象的属性(名为 key)的值,如果该属性不存在,则返回 undefinedkey 必须是字符串或符号;receiver 必须是调试器值。如果属性是 getter,则它将使用 receiver 作为接收器进行评估,如果省略,则默认为 Debugger.Object

setProperty(key, value, [receiver])

value 存储为引用对象的属性(名为 key)的值,如果属性不存在则创建该属性。key 必须是字符串或符号;valuereceiver 必须是调试器值。如果属性是 setter,则它将使用 receiver 作为接收器进行评估,如果省略,则默认为 Debugger.Object

getOwnPropertyDescriptor(name)

返回引用对象属性(名为 name)的属性描述符。如果引用对象没有此属性,则返回 undefined。(此函数的行为类似于标准的 Object.getOwnPropertyDescriptor 函数,除了被检查的对象是隐式的;返回的属性描述符是在调试器的全局对象的作用域中分配的(因此在调试器的隔间中);并且它的 valuegetset 属性(如果存在)是调试器值。)

getOwnPropertyNames()

返回一个字符串数组,命名引用对象的所有自身属性,就像在调试器中调用了 Object.getOwnPropertyNames(referent) 一样,并且结果在调试器的全局对象的作用域中复制。

getOwnPropertySymbols()

返回一个字符串数组,命名引用对象的所有自身符号,就像在调试器中调用了 Object.getOwnPropertySymbols(referent) 一样,并且结果在调试器的全局对象的作用域中复制。

defineProperty(name, attributes)

根据属性描述符 descriptor 定义引用对象上名为 name 的属性。attributes 的任何 valuegetset 属性都必须是调试器值。(此函数的行为类似于 Object.defineProperty,除了目标对象是隐式的,并且位于与函数和描述符不同的隔间中。)

defineProperties(properties)

properties 给出的属性添加到引用对象。(此函数的行为类似于 Object.defineProperties,除了目标对象是隐式的,并且位于与 properties 参数不同的隔间中。)

deleteProperty(name)

删除引用对象的属性(名为 name)。如果属性已成功删除,或者引用对象没有此属性,则返回 true。如果属性不可配置,则返回 false。

seal()

防止向引用对象添加或从中删除属性。返回此 Debugger.Object 实例。(此函数的行为类似于标准的 Object.seal 函数,除了要密封的对象是隐式的,并且位于与调用者不同的隔间中。)

freeze()

防止向引用对象添加或从中删除属性,并将每个属性标记为不可写。返回此 Debugger.Object 实例。(此函数的行为类似于标准的 Object.freeze 函数,除了要密封的对象是隐式的,并且位于与调用者不同的隔间中。)

preventExtensions()

防止向引用对象添加属性。(此函数的行为类似于标准的 Object.preventExtensions 函数,除了要操作的对象是隐式的,并且位于与调用者不同的隔间中。)

isSealed()

如果引用对象已密封,则返回 true,即如果它不可扩展,并且所有属性都已标记为不可配置。(此函数的行为类似于标准的 Object.isSealed 函数,除了被检查的对象是隐式的,并且位于与调用者不同的隔间中。)

isFrozen()

如果被引用对象已冻结,则返回 true——也就是说,如果它不可扩展,并且其所有属性都已标记为不可配置且只读。(此函数的行为类似于标准的Object.isFrozen函数,不同之处在于检查的对象是隐式的,并且与调用者位于不同的隔间中。)

isExtensible()

如果被引用对象是可扩展的,则返回 true——也就是说,如果可以在其上定义新的属性。(此函数的行为类似于标准的Object.isExtensible函数,不同之处在于检查的对象是隐式的,并且与调用者位于不同的隔间中。)

copy(value)

应用 HTML5“结构化克隆”算法在被引用对象的全局对象(以及被引用对象的隔间中)中创建value的副本,并返回一个引用该副本的Debugger.Object实例。

请注意,这会将原始值保持不变。这意味着您可以使用Debugger.Object.prototype.copy作为通用的“调试器值到被调试器值”转换函数——在“结构化克隆”算法的限制范围内。

create(prototype, [properties])

在被引用对象的全局对象中(以及被引用对象的隔间中)创建一个新对象,并返回一个引用它的Debugger.Object。新对象的原型是prototype,它必须是一个Debugger.Object实例。新对象的属性由properties给出,就像properties传递给Debugger.Object.prototype.defineProperties一样,其中新的Debugger.Object实例作为this值。

makeDebuggeeValue(value)

返回在被调试器中表示value的被调试器值。如果value是原始值,则我们将其保持不变;如果value是对象,则我们返回表示该对象的Debugger.Object实例,并将其包装为适合在此Debugger.Object的被引用对象的隔间中使用。

请注意,如果value是对象,则它不必是在被调试器全局对象中分配的对象,甚至不必是被调试器隔间中的对象;它可以是调试器希望用作被调试器值的任何对象。

如上所述,每个Debugger.Object实例都以从特定隔间中看到的视角呈现其被引用对象。给定一个Debugger.Object实例d和一个对象o,调用d.makeDebuggeeValue(o)将返回一个Debugger.Object实例,该实例以d的隔间中的代码将看到的视角呈现o

call(this, argument, …)

如果被引用对象是可调用的,则使用给定的this值和argument值调用它,并返回一个完成值,描述调用如何完成。This应该是一个被调试器值,或者{ asConstructor: true }以将被引用对象作为构造函数调用,在这种情况下,SpiderMonkey 本身会提供一个合适的this值。每个argument都必须是一个被调试器值。在调用期间,所有现有的处理程序方法、断点等都保持活动状态。如果被引用对象不可调用,则抛出TypeError。此函数遵循调用函数约定。

apply(this, arguments)

如果被引用对象是可调用的,则使用给定的this值和arguments中的参数值调用它,并返回一个完成值,描述调用如何完成。This应该是一个被调试器值,或者{ asConstructor: true }以将function作为构造函数调用,在这种情况下,SpiderMonkey 本身会提供一个合适的this值。Arguments必须是(在调试器中)被调试器值的数组,或者nullundefined,它们被视为空数组。在调用期间,所有现有的处理程序方法、断点等都保持活动状态。如果被引用对象不可调用,则抛出TypeError。此函数遵循调用函数约定

executeInGlobal(code, [options])

如果被引用对象是全局对象,则在该全局环境中评估code,并返回一个完成值,描述其如何完成。Code是一个字符串。在调用期间,所有现有的处理程序方法、断点等都保持活动状态。此函数遵循调用函数约定。如果被引用对象不是全局对象,则抛出TypeError异常。

Code包含 Use Strict 指令时,它被解释为严格模式代码。

此评估在语义上等效于在全局级别执行语句,而不是间接 eval。无论code是否为严格模式代码,code中的变量声明都会影响被引用全局对象。

options参数与Debugger.Frame.eval的参数相同。

executeInGlobalWithBindings(code, bindings, [options])

类似于executeInGlobal,但使用被引用对象作为变量对象评估code,但使用扩展了对象bindings中的绑定的词法环境。对于bindings的每个自己的可枚举属性(名为name,其值为value),在评估code的词法环境中包含一个名为name的变量,其值为value。每个value都必须是被调试器值。(这不像with语句:code可以访问、赋值和删除引入的绑定,而不会对bindings对象产生任何影响。)

此方法允许调试器代码引入对给定的被调试器代码可见的临时绑定,这些绑定引用调试器持有的被调试器值,并且这样做不会修改任何现有的被调试器环境。

请注意,与executeInGlobal一样,它包含的任何声明都会影响被引用全局对象,即使code在根据bindings扩展的环境中进行评估。(在 ECMAScript 规范中使用的术语中,code的执行上下文的VariableEnvironment是被引用对象,并且bindings出现在一个新的声明性环境中,该环境是 eval 代码的LexicalEnvironment。)

options参数与Debugger.Frame.eval的参数相同。

asEnvironment()

如果被引用对象是全局对象,则返回表示被引用对象的全局词法作用域的Debugger.Environment实例。全局词法作用域的封闭作用域是全局对象。如果被引用对象不是全局对象,则抛出TypeError

unwrap()

如果被引用对象是此Debugger.Object的隔间允许解包的包装器,则返回一个引用包装对象的Debugger.Object实例。如果我们不允许解包被引用对象,则返回null。如果被引用对象不是包装器,则保持此Debugger.Object实例不变。

unsafeDereference()

返回此Debugger.Object实例的被引用对象。

如果被引用对象是内部对象(例如,HTML5Window对象),则返回相应的外部对象(例如,HTML5WindowProxy对象)。这使得unsafeDereference在生成适合被调试器代码直接使用的值的方面更有用,而无需使用调用函数

此方法穿透了旨在保护调试器代码免受被调试器代码影响的Debugger.Object实例的膜,并允许调试器代码通过标准的跨隔间包装器访问被调试器对象,而不是通过Debugger.Object的面向反射的接口。此方法使大型代码库逐渐适应此调试器 API 变得更容易:代码的已适应部分可以使用Debugger.Object实例,但使用此方法将直接对象引用传递给尚未更新的代码。

forceLexicalInitializationByName(binding)

如果binding处于未初始化状态,则将其初始化为 undefined 并返回 true,否则不执行任何操作并返回 false。

源元数据

从文件生成

js/src/doc/Debugger/Debugger.Object.md

水印

sha256:7ae16a834e0883a95b4e0d227193293f6b6e4e4dd812c2570372a39c4c04897b

变更集

5572465c08a9+