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<

parameterNames

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

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

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

如果函数使用解构参数,则相应的数组元素为 undefined。例如,如果引用对象以这种方式声明的函数

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

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

["a", undefined, undefined]

script

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

environment

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

isError

如果引用对象是任何可能包装的 Error,则为 true;否则为 false

errorMessageName

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

errorLineNumber

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

errorColumnNumber

如果引用对象是 Error 对象,则为创建引用对象的 1 起始列号(以 UTF-16 代码单元为单位);否则为 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。)

isClassConstructor

如果引用对象是一个被调试的函数,则如果该引用对象是一个类,则返回true,或者如果它是其他类型的函数则返回false。如果引用对象不是被调试的函数,或者根本不是函数,则为undefined。(这始终等于obj.script.isClassConstructor,假设obj.scriptDebugger.Script。)

isPromise

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

boundTargetFunction

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

boundThis

如果引用对象是一个绑定的被调试的函数,则这是它绑定的this值。如果引用对象不是绑定函数,也不是被调试的函数,或者根本不是函数,则为undefined

boundArguments

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

isProxy

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

proxyTarget

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

proxyHandler

如果引用对象是一个未撤销的(脚本化的)代理,则返回一个Debugger.Object实例,该实例引用引用对象的 ECMAScript [[ProxyHandler]]。如果引用对象是一个已撤销的(脚本化的)代理,则返回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 异常。

allocationSite

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

Debugger.Object 原型的函数属性

下面描述的函数只能在 this 值引用 Debugger.Object 实例时调用;它们不能用作其他类型对象的的方法。描述中使用“引用对象”表示“此 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。返回一个 完成值,其中“return”为成功/失败布尔值,或者“throw”为属性赋值期间抛出的异常。在调用期间,所有现有的处理程序方法、断点等都保持活动状态。

getOwnPropertyDescriptor(key)

返回引用对象的名称为 key 的属性的属性描述符。如果引用对象没有这样的属性,则返回 undefined。(此函数的行为类似于标准的 Object.getOwnPropertyDescriptor 函数,除了被检查的对象是隐式的;返回的属性描述符就像调试器的全局对象范围内的代码一样分配(因此在调试器的隔间中);并且它的 valuegetset 属性(如果存在)是调试目标值。)

getOwnPropertyNames()

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

getOwnPropertyNamesLength()

返回引用对象自身属性的数量。

getOwnPropertySymbols()

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

defineProperty(key, attributes)

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

defineProperties(properties)

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

deleteProperty(key)

删除引用对象的名称为 key 的属性。如果属性成功删除或引用对象没有这样的属性,则返回 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 函数,除了被检查的对象是隐式的,并且与调用者位于不同的隔间中。)

makeDebuggeeValue(value)

返回表示调试目标中 value 的调试目标值。如果 value 是一个原始值,我们将其原样返回;如果 value 是一个对象,我们返回表示该对象的 Debugger.Object 实例,并将其适当地包装以供在此 Debugger.Object 的引用对象所在的隔间中使用。

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

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

isSameNative(value)

如果 value 是调试器隔间中的原生函数,则返回引用对象是否为同一 C++ 原生的原生函数。

isSameNativeWithJitInfo(value)

如果 value 是调试器隔间中的原生函数,则返回引用对象是否为具有相同 JSJitInfo 指针值的同一 C++ 原生的原生函数。

这可用于区分具有共享原生函数实现但 JSJitInfo 指针不同的函数,以定义底层功能。

isNativeGetterWithJitInfo()

返回引用对象是否为具有 JSJitInfo 的原生 getter 函数。

decompile([pretty])

如果引用对象是调试目标代码的函数,则返回一个 JavaScript 源代码字符串,该字符串等效于引用函数的效果和结果。如果 pretty 存在且为 true,则生成带缩进和换行的代码。如果引用对象不是调试目标代码的函数,则返回 undefined

call(this, argument, ...)

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

注意:如果此方法在拥有Debugger 对象且该对象具有onNativeCall处理程序的对象上调用,则在评估期间,只有与该调试器关联的对象上的钩子才会被调用。

apply(this, arguments)

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

注意:如果此方法在拥有Debugger 对象且该对象具有onNativeCall处理程序的对象上调用,则在评估期间,只有与该调试器关联的对象上的钩子才会被调用。

executeInGlobal(code, [options])

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

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

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

Options参数与Debugger.Frame.prototype.eval相同。

注意:如果此方法在拥有Debugger 对象且该对象具有onNativeCall处理程序的对象上调用,则在评估期间,只有与该调试器关联的对象上的钩子才会被调用。

executeInGlobalWithBindings(code, bindings, [options])

类似于executeInGlobal,但使用引用对象作为变量对象来评估code,但使用扩展了对象bindings中绑定的词法环境。

使用bindings指定的绑定创建一个额外的环境。该环境包含与bindings的每个自身可枚举属性相对应的绑定,其中属性名称name作为绑定名称,属性值value作为绑定的初始值。

如果未指定options.useInnerBindings或将其指定为false,则它会模拟将绑定环境放置在全局外部的位置,这意味着,如果绑定与code中声明的任何全局变量或任何现有的全局变量冲突,则该绑定将被忽略。

如果将options.useInnerBindings指定为true,则它会直接执行将绑定环境放置在全局内部的操作,并且提供的绑定会隐藏全局变量。

每个value都必须是一个调试目标值。

这不像with语句:code可以访问、分配和删除引入的绑定,而不会对传递的bindings对象产生任何影响,因为属性在每次调用时都会复制到一个新对象中。

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

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

Options参数与Debugger.Frame.prototype.eval相同。

注意:如果此方法在拥有Debugger 对象且该对象具有onNativeCall处理程序的对象上调用,则在评估期间,只有与该调试器关联的对象上的钩子才会被调用。

createSource(options)

如果引用对象是全局对象,则在全局对象的领域中返回一个新的JavaScript源,其属性根据options对象填充。如果引用对象不是全局对象,则抛出TypeError异常。options对象可以具有以下属性

  • text:源中JavaScript的字符串内容。

  • url:结果源应关联的URL。

  • startLine:源的起始行。

  • startColumn:源的起始列。

  • sourceMapURL:可选URL,指定源的源映射URL。如果未指定,则如果源文本指定,则可以填写源映射URL。

  • isScriptElement:可选布尔值,如果指定,则会将源的introductionType设置为"inlineScript"。否则,源的introductionType将为undefined

asEnvironment()

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

unwrap()

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

unsafeDereference()

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

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

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

forceLexicalInitializationByName(binding)

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

getPromiseReactions

如果引用对象是Promise或其跨区室包装器,则它会返回一个对象数组,这些对象描述添加到promise的反应记录。有几种不同类型的反应记录

  • 使用thencatch添加的反应记录的数组条目具有{ resolve: F, reject: F, result: P }的形式,其中每个F都是一个Debugger.Object,引用一个函数对象,而P是将使用调用它们的结果解析的promise。

    在某些情况下,resolvereject属性可能不存在。对then的调用可以省略拒绝处理程序,而对catch的调用会省略解析处理程序。此外,各种promise工具会将类似的记录创建为内部实现细节,创建不可表示为JavaScript函数的处理程序。

  • 当一个promise P1被解析为另一个promise P2(以至于解析P2以相同的方式解析P1)时,这会向P2添加一个反应记录。该反应记录的数组条目只是表示P1Debugger.Object

    请注意,如果P1P2位于不同的区室中,则将P1解析为P2会创建与对thencatch的调用相同的反应记录,其中P1仅存储在resolvereject函数的私有槽中,而不是直接从反应记录中获取。

  • 一个await表达式在其操作数上调用PromiseResolve以获取一个promise P,然后向P添加一个反应记录,以适当地恢复挂起的调用。该反应记录的数组条目是表示挂起调用的Debugger.Frame

    如果await的操作数A是具有标准构造函数的原生promise,则PromiseResolve只会返回不变的A,并且用于恢复挂起调用的反应记录将添加到A的列表中。但是,如果A是某种其他类型的“thenable”,则PromiseResolve会创建一个新的promise并排队一个作业来调用Athen方法;这可能会从awaitees到awaiters产生更多间接链。

  • JS::AddPromiseReactionsJS::AddPromiseReactionsIgnoringUnhandledRejection创建一个反应记录,其promise字段为null