9 可执行代码与执行上下文

9.1 环境记录

Environment Record 是一种规范类型,用于根据 ECMAScript 代码的词法嵌套结构,定义 Identifier 与特定变量和函数之间的关联。通常,一个 Environment Record 会与 ECMAScript 代码中的某个特定语法结构相关联,例如 FunctionDeclarationBlockStatement,或 TryStatement 的某个 Catch 子句。每次对此类代码求值时,都会创建一个新的 Environment Record,用来记录由该代码创建的标识符绑定。

每个 Environment Record 都有一个 [[OuterEnv]] 字段,其值要么是 null,要么是对外层 Environment Record 的引用。它用于表示 Environment Record 值之间的逻辑嵌套关系。某个(内层)Environment Record 的外层引用,是对在逻辑上包围该内层 Environment Record 的那个 Environment Record 的引用。外层 Environment Record 当然也可以有它自己的外层 Environment Record。一个 Environment Record 可以作为多个内层 Environment Record 的外部环境。例如,如果一个 FunctionDeclaration 包含两个嵌套的 FunctionDeclaration,那么这两个嵌套函数各自的 Environment Record,其外层 Environment Record 都将是当前对外围函数进行求值时的那个 Environment Record。

Environment Record 纯粹是规范机制,不需要对应于任何 ECMAScript 实现中的特定构件。ECMAScript 程序不可能直接访问或操作这类值。

9.1.1 Environment Record 类型层级

可以将 Environment Record 视为存在于一个简单的面向对象层级中,其中 Environment Record 是一个抽象类,具有三个具体子类:Declarative Environment RecordObject Environment RecordGlobal Environment RecordFunction Environment RecordModule Environment Record 则是 Declarative Environment Record 的子类。

Environment Record 抽象类包含 Table 14 中定义的抽象规范方法。这些抽象方法在每个具体子类中都有各自不同的具体算法。

Table 14: Abstract Methods of Environment Records
方法 目的 定义
HasBinding ( name )

The abstract method HasBinding takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成.

它用于判定一个 Environment Record 是否具有 name 的绑定。
它在以下类型中有具体定义:
CreateMutableBinding ( name, deletable )

The abstract method CreateMutableBinding takes arguments name (一个 String,) and deletable (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成.

它在 Environment Record 中创建一个新的、但尚未初始化的可变绑定。name 是被绑定名称的文本。如果 deletabletrue,则该绑定之后可以被删除。
它在以下类型中有具体定义:
CreateImmutableBinding ( name, strict )

The abstract method CreateImmutableBinding takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成.

它在 Environment Record 中创建一个新的、但尚未初始化的不可变绑定。name 是被绑定名称的文本。如果 stricttrue,那么在其被初始化之后再尝试设置它时,无论引用该绑定的操作是否处于严格模式,都会始终抛出异常。
它在以下类型中有具体定义:
InitializeBinding ( name, value )

The abstract method InitializeBinding takes arguments name (一个 String,) and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成.

它为 Environment Record 中一个已存在但尚未初始化的绑定设定值。name 是被绑定名称的文本。value 是该绑定的值。
它在以下类型中有具体定义:
SetMutableBinding ( name, value, strict )

The abstract method SetMutableBinding takes arguments name (一个 String,), value (一个 ECMAScript 语言值,), and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成.

它为 Environment Record 中一个已存在的可变绑定设定值。name 是被绑定名称的文本。value 是该绑定的值。如果 stricttrue 且该绑定无法被设置,则会抛出一个 TypeError 异常。
它在以下类型中有具体定义:
GetBindingValue ( name, strict )

The abstract method GetBindingValue takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成.

它从 Environment Record 中返回一个已存在绑定的值。name 是被绑定名称的文本。strict 用于标识那些源自严格模式代码,或因其他原因需要严格模式引用语义的引用。如果 stricttrue 且绑定不存在,则会抛出一个 ReferenceError 异常。如果绑定存在但尚未初始化,则无论 strict 的值为何,都会抛出 ReferenceError
它在以下类型中有具体定义:
DeleteBinding ( name )

The abstract method DeleteBinding takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成.

它从 Environment Record 中删除一个绑定。name 是被绑定名称的文本。如果 name 的绑定存在,则移除该绑定并返回 true。如果绑定存在但不能移除,则返回 false。如果绑定不存在,则返回 true
它在以下类型中有具体定义:
HasThisBinding ( )

The abstract method HasThisBinding takes no arguments and returns 一个 Boolean.

它用于判定一个 Environment Record 是否建立了 this 绑定。如果有则返回 true,否则返回 false
它在以下类型中有具体定义:
GetThisBinding ( )

The abstract method GetThisBinding takes no arguments and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成.

它返回该 Environment Recordthis 绑定值。如果 this 绑定尚未初始化,则抛出 ReferenceError
它在以下类型中有具体定义:
HasSuperBinding ( )

The abstract method HasSuperBinding takes no arguments and returns 一个 Boolean.

它用于判定一个 Environment Record 是否建立了 super 方法绑定。如果有则返回 true,否则返回 false。如果它返回 true,则意味着该 Environment Record 是一个 Function Environment Record,但反过来并不成立。
它在以下类型中有具体定义:
WithBaseObject ( )

The abstract method WithBaseObject takes no arguments and returns 一个 Object 或 undefined.

如果此 Environment Recordwith 语句相关联,则返回该 with 对象。否则返回 undefined
它在以下类型中有具体定义:

9.1.1.1 Declarative Environment Record

每个 Declarative Environment Record 都与一个 ECMAScript 程序作用域相关联,该作用域中包含变量、常量、let、class、module、import 和/或函数声明。Declarative Environment Record 绑定了其作用域内声明所定义的一组标识符。

9.1.1.1.1 HasBinding ( name )

The HasBinding concrete method of a Declarative Environment Record envRec takes argument name (一个 String,) and returns 一个包含 Boolean 的正常完成. 它用于判定参数标识符是否是该记录所绑定的标识符之一。 It performs the following steps when called:

  1. 如果 envRec 具有 name 的绑定,返回 true
  2. 返回 false

9.1.1.1.2 CreateMutableBinding ( name, deletable )

The CreateMutableBinding concrete method of a Declarative Environment Record envRec takes arguments name (一个 String,) and deletable (一个 Boolean,) and returns 一个包含 unused正常完成. 它为名称 name 创建一个新的可变绑定,并且该绑定未初始化。在这个 Environment Record 中,name 的绑定必须尚不存在。如果 deletabletrue,则新绑定会被标记为可删除。 It performs the following steps when called:

  1. 断言:envRec 尚不存在 name 的绑定。
  2. envRec 中为 name 创建一个可变绑定,并记录其尚未初始化。如果 deletabletrue,则记录新创建的绑定可被后续的 DeleteBinding 调用删除。
  3. 返回 unused

9.1.1.1.3 CreateImmutableBinding ( name, strict )

The CreateImmutableBinding concrete method of a Declarative Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 一个包含 unused正常完成. 它为名称 name 创建一个新的不可变绑定,并且该绑定未初始化。在这个 Environment Record 中,name 的绑定必须尚不存在。如果 stricttrue,则新绑定会被标记为严格绑定。 It performs the following steps when called:

  1. 断言:envRec 尚不存在 name 的绑定。
  2. envRec 中为 name 创建一个不可变绑定,并记录其尚未初始化。如果 stricttrue,则记录新创建的绑定是严格绑定。
  3. 返回 unused

9.1.1.1.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of a Declarative Environment Record envRec takes arguments name (一个 String,) and value (一个 ECMAScript 语言值,) and returns 一个包含 unused正常完成. 它用于将当前名称为 name 的标识符绑定的绑定值设为 value。必须已经存在一个未初始化的 name 绑定。 It performs the following steps when called:

  1. 断言:envRec 中必须存在一个未初始化的 name 绑定。
  2. envRecname 的绑定值设为 value
  3. 记录 envRecname 的绑定已经完成初始化。
  4. 返回 unused

9.1.1.1.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of a Declarative Environment Record envRec takes arguments name (一个 String,), value (一个 ECMAScript 语言值,), and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它尝试将当前名称为 name 的标识符绑定的绑定值更改为 value。通常 name 的绑定已经存在,但在极少数情况下可能不存在。如果该绑定是不可变绑定,则当 stricttrue 时会抛出 TypeError。 It performs the following steps when called:

  1. 如果 envRec 没有 name 的绑定,那么
    1. 如果 stricttrue,抛出一个 ReferenceError 异常。
    2. 执行 ! envRec.CreateMutableBinding(name, true)。
    3. 执行 ! envRec.InitializeBinding(name, value)。
    4. 返回 unused
  2. 如果 envRecname 的绑定是一个严格绑定,则将 strict 设为 true
  3. 如果 envRecname 的绑定尚未初始化,那么
    1. 抛出一个 ReferenceError 异常。
  4. 否则如果 envRecname 的绑定是一个可变绑定,那么
    1. 将其绑定值改为 value
  5. 否则,
    1. 断言:这是一次试图更改不可变绑定值的操作。
    2. 如果 stricttrue,抛出一个 TypeError 异常。
  6. 返回 unused
Note

会在步骤 1 处产生缺失绑定的 ECMAScript 代码示例如下:

function f() { eval("var x; x = (delete x, 0);"); }

9.1.1.1.6 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Declarative Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它返回其所绑定的、名称为 name 的标识符的值。如果该绑定存在但尚未初始化,则无论 strict 的值为何,都会抛出 ReferenceError。 It performs the following steps when called:

  1. 断言:envRec 具有 name 的绑定。
  2. 如果 envRecname 的绑定是未初始化绑定,抛出一个 ReferenceError 异常。
  3. 返回 envRec 中当前绑定到 name 的值。

9.1.1.1.7 DeleteBinding ( name )

The DeleteBinding concrete method of a Declarative Environment Record envRec takes argument name (一个 String,) and returns 一个包含 Boolean 的正常完成. 它只能删除那些被显式指定为可删除的绑定。 It performs the following steps when called:

  1. 断言:envRec 具有 name 的绑定。
  2. 如果 envRecname 的绑定不能被删除,返回 false
  3. envRec 中移除 name 的绑定。
  4. 返回 true

9.1.1.1.8 HasThisBinding ( )

The HasThisBinding concrete method of a Declarative Environment Record envRec takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

普通的 Declarative Environment Record(即既不是 Function Environment Record 也不是 Module Environment Record 的那种)不提供 this 绑定。

9.1.1.1.9 GetThisBinding ( )

本规范中从不使用 Declarative Environment RecordGetThisBinding 具体方法。

9.1.1.1.10 HasSuperBinding ( )

The HasSuperBinding concrete method of a Declarative Environment Record envRec takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

普通的 Declarative Environment Record(即既不是 Function Environment Record 也不是 Module Environment Record 的那种)不提供 super 绑定。

9.1.1.1.11 WithBaseObject ( )

The WithBaseObject concrete method of a Declarative Environment Record envRec takes no arguments and returns undefined. It performs the following steps when called:

  1. 返回 undefined

9.1.1.2 Object Environment Record

每个 Object Environment Record 都与一个称为其绑定对象的对象相关联。Object Environment Record 绑定了一组字符串标识符名称,这些名称直接对应于其绑定对象的属性名属性键中那些不是 IdentifierName 形式的字符串的,不包含在绑定标识符集合中。无论是自有属性还是继承属性,都包含在此集合中,而不管它们的 [[Enumerable]] 特性的设置如何。由于对象的属性可以被动态添加和删除,因此 Object Environment Record 所绑定的标识符集合,可能会作为任何添加或删除属性操作的副作用而发生变化。由于这类副作用而创建的任何绑定,即使相应属性的 Writable 特性为 false,也会被视为可变绑定。Object Environment Record 不存在不可变绑定。

with 语句(14.11)创建的 Object Environment Record,可以将其绑定对象作为函数调用中的隐式 this 值提供。该能力由一个 Boolean 类型[[IsWithEnvironment]] 字段控制。

Object Environment Record 具有 Table 15 中列出的附加状态字段。

Table 15: Object Environment Record 的附加字段
字段名称 含义
[[BindingObject]] 一个 Object Environment Record 的绑定对象。
[[IsWithEnvironment]] 一个 Boolean 表示此 Environment Record 是否是为 with 语句创建的。

9.1.1.2.1 HasBinding ( name )

The HasBinding concrete method of a Object Environment Record envRec takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定其关联的绑定对象是否具有名称为 name 的属性。 It performs the following steps when called:

  1. bindingObjectenvRec.[[BindingObject]]
  2. foundBinding 为 ? HasProperty(bindingObject, name)。
  3. 如果 foundBindingfalse,返回 false
  4. 如果 envRec.[[IsWithEnvironment]]false,返回 true
  5. unscopables 为 ? Get(bindingObject, %Symbol.unscopables%)。
  6. 如果 unscopables 是一个 Object,那么
    1. blockedToBoolean(? Get(unscopables, name))。
    2. 如果 blockedtrue,返回 false
  7. 返回 true

9.1.1.2.2 CreateMutableBinding ( name, deletable )

The CreateMutableBinding concrete method of a Object Environment Record envRec takes arguments name (一个 String,) and deletable (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它会在 Environment Record 关联的绑定对象中创建一个名为 name 的属性,并将其初始化为值 undefined。如果 deletabletrue,则该新属性的 [[Configurable]] 特性设为 true;否则设为 false。 It performs the following steps when called:

  1. bindingObjectenvRec.[[BindingObject]]
  2. 执行 ? DefinePropertyOrThrow(bindingObject, name, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: deletable })。
  3. 返回 unused
Note

通常 envRec 不会已有 name 的绑定,但如果已有,则 DefinePropertyOrThrow 的语义可能导致现有绑定被替换、被遮蔽,或导致返回突兀完成

9.1.1.2.3 CreateImmutableBinding ( name, strict )

本规范中从不使用 Object Environment RecordCreateImmutableBinding 具体方法。

9.1.1.2.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of a Object Environment Record envRec takes arguments name (一个 String,) and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它用于将当前名称为 name 的标识符绑定的绑定值设为 value。 It performs the following steps when called:

  1. 执行 ? envRec.SetMutableBinding(name, value, false)
  2. 返回 unused
Note

在本规范中,Object Environment Record 上所有对 CreateMutableBinding 的使用,都会立即紧跟着对同一名称调用 InitializeBinding。因此,本规范不会显式跟踪 Object Environment Record 中绑定的初始化状态。

9.1.1.2.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of a Object Environment Record envRec takes arguments name (一个 String,), value (一个 ECMAScript 语言值,), and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它尝试将该 Environment Record 关联的绑定对象中名称为 name 的属性值设为 value。通常名称为 name 的属性已存在,但如果不存在,或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

  1. bindingObjectenvRec.[[BindingObject]]
  2. stillExists 为 ? HasProperty(bindingObject, name)。
  3. 如果 stillExistsfalsestricttrue,抛出一个 ReferenceError 异常。
  4. 执行 ? Set(bindingObject, name, value, strict)。
  5. 返回 unused

9.1.1.2.6 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Object Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它返回其关联的绑定对象中名称为 name 的属性值。该属性应当已经存在,但如果不存在,则结果取决于 strict。 It performs the following steps when called:

  1. bindingObjectenvRec.[[BindingObject]]
  2. value 为 ? HasProperty(bindingObject, name)。
  3. 如果 valuefalse,那么
    1. 如果 strictfalse,返回 undefined
    2. 抛出一个 ReferenceError 异常。
  4. 返回 ? Get(bindingObject, name)。

9.1.1.2.7 DeleteBinding ( name )

The DeleteBinding concrete method of a Object Environment Record envRec takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它只能删除那些对应于环境对象属性、且其 [[Configurable]] 特性值为 true 的绑定。 It performs the following steps when called:

  1. bindingObjectenvRec.[[BindingObject]]
  2. 返回 ? bindingObject.[[Delete]](name)

9.1.1.2.8 HasThisBinding ( )

The HasThisBinding concrete method of a Object Environment Record envRec takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

Object Environment Record 不提供 this 绑定。

9.1.1.2.9 GetThisBinding ( )

本规范中从不使用 Object Environment RecordGetThisBinding 具体方法。

9.1.1.2.10 HasSuperBinding ( )

The HasSuperBinding concrete method of a Object Environment Record envRec takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

Object Environment Record 不提供 super 绑定。

9.1.1.2.11 WithBaseObject ( )

The WithBaseObject concrete method of a Object Environment Record envRec takes no arguments and returns 一个 Object 或 undefined. It performs the following steps when called:

  1. 如果 envRec.[[IsWithEnvironment]]true,返回 envRec.[[BindingObject]]
  2. 返回 undefined

9.1.1.3 Function Environment Record

Function Environment Record 是一种 Declarative Environment Record,用于表示函数的顶层作用域,并且如果该函数不是 ArrowFunction,则提供 this 绑定。如果函数不是 ArrowFunction 且引用了 super,那么它的 Function Environment Record 还会包含从该函数内部执行 super 方法调用所需的状态。

Function Environment Record 具有 Table 16 中列出的附加状态字段。

Table 16: Function Environment Record 的附加字段
字段名称 含义
[[ThisValue]] 一个 ECMAScript 语言值 这是本次函数调用所使用的 this 值。
[[ThisBindingStatus]] lexicalinitializeduninitialized 如果该值为 lexical,则表示这是一个 ArrowFunction,并且没有局部 this 值。
[[FunctionObject]] 一个 ECMAScript 函数对象 导致创建本 Environment Record 的那个函数对象调用本身。
[[NewTarget]] 一个构造器undefined 如果该 Environment Record 是由 [[Construct]] 内部方法创建的,则 [[NewTarget]] 的值是 [[Construct]]newTarget 参数值。否则,其值为 undefined

Function Environment Record 支持 Table 14 中列出的所有 Declarative Environment Record 方法,并且除 HasThisBindingGetThisBindingHasSuperBinding 之外,其余这些方法的规范都与 Declarative Environment Record 相同。

9.1.1.3.1 BindThisValue ( envRec, value )

The abstract operation BindThisValue takes arguments envRec (一个 Function Environment Record,) and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它设置 envRec.[[ThisValue]] 并记录其已经初始化。 It performs the following steps when called:

  1. 断言:envRec.[[ThisBindingStatus]] 不是 lexical
  2. 如果 envRec.[[ThisBindingStatus]]initialized,抛出一个 ReferenceError 异常。
  3. envRec.[[ThisValue]] 设为 value
  4. envRec.[[ThisBindingStatus]] 设为 initialized
  5. 返回 unused

9.1.1.3.2 HasThisBinding ( )

The HasThisBinding concrete method of a Function Environment Record envRec takes no arguments and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 envRec.[[ThisBindingStatus]]lexical,返回 false
  2. 返回 true

9.1.1.3.3 GetThisBinding ( )

The GetThisBinding concrete method of a Function Environment Record envRec takes no arguments and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. It performs the following steps when called:

  1. 断言:envRec.[[ThisBindingStatus]] 不是 lexical
  2. 如果 envRec.[[ThisBindingStatus]]uninitialized,抛出一个 ReferenceError 异常。
  3. 返回 envRec.[[ThisValue]]

9.1.1.3.4 HasSuperBinding ( )

The HasSuperBinding concrete method of a Function Environment Record envRec takes no arguments and returns 一个 Boolean. It performs the following steps when called:

  1. 如果 envRec.[[ThisBindingStatus]]lexical,返回 false
  2. 如果 envRec.[[FunctionObject]].[[HomeObject]]undefined,返回 false
  3. 返回 true

9.1.1.3.5 GetSuperBase ( envRec )

The abstract operation GetSuperBase takes argument envRec (一个 Function Environment Record,) and returns 一个 Object、nullundefined. 它返回作为 envRec 中绑定的 super 属性访问基础对象的那个对象。值 undefined 表示这类访问将产生运行时错误。 It performs the following steps when called:

  1. homeenvRec.[[FunctionObject]].[[HomeObject]]
  2. 如果 homeundefined,返回 undefined
  3. 断言:home 是一个普通对象
  4. 返回 ! home.[[GetPrototypeOf]]()。

9.1.1.4 Global Environment Record

Global Environment Record 用于表示在某个共享 realm 中,由所有被处理的 ECMAScript Script 元素共同共享的最外层作用域。Global Environment Record 为内建全局对象(条款 19)、全局对象的属性,以及 Script 中出现的所有顶层声明(8.2.98.2.11)提供绑定。

从逻辑上说,Global Environment Record 是一个单一记录,但规范中将其描述为一个封装了 Object Environment RecordDeclarative Environment Record 的复合体。其 Object Environment Record 的基础对象是关联 Realm Record全局对象。这个全局对象也是 Global Environment Record 的 GetThisBinding 具体方法返回的值。Global Environment Record 的 Object Environment Record 组件,包含所有内建全局对象(条款 19)的绑定,以及全局代码中由 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableStatement 引入的所有绑定。全局代码中所有其他 ECMAScript 声明的绑定,则包含在 Global Environment Record 的 Declarative Environment Record 组件中。

属性可以被直接创建在全局对象上。因此,Global Environment Record 的 Object Environment Record 组件,既可能包含由 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableDeclaration 显式创建的绑定,也可能包含作为全局对象属性而隐式创建的绑定。

Global Environment Record 具有 Table 17 中列出的附加字段。

Table 17: Global Environment Record 的附加字段
字段名称 含义
[[ObjectRecord]] 一个 Object Environment Record 其绑定对象是全局对象。它包含关联 realm 的全局内建绑定,以及全局代码中的 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableDeclaration 绑定。
[[GlobalThisValue]] 一个 Object 全局作用域中 this 返回的值。宿主可以提供任意 ECMAScript Object 值。
[[DeclarativeRecord]] 一个 Declarative Environment Record 包含关联 realm 代码的全局代码中所有声明的绑定,但不包括 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableDeclaration 绑定。

9.1.1.4.1 HasBinding ( name )

The HasBinding concrete method of a Global Environment Record envRec takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定参数标识符是否是该记录所绑定的标识符之一。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,返回 true
  3. objectRecordenvRec.[[ObjectRecord]]
  4. 返回 ? objectRecord.HasBinding(name)

9.1.1.4.2 CreateMutableBinding ( name, deletable )

The CreateMutableBinding concrete method of a Global Environment Record envRec takes arguments name (一个 String,) and deletable (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它为名称 name 创建一个新的未初始化可变绑定。该绑定创建于关联的 DeclarativeRecord 中。DeclarativeRecord 中必须还不存在 name 的绑定。如果 deletabletrue,则新绑定会被标记为可删除。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,抛出一个 TypeError 异常。
  3. 返回 ! declarativeRecord.CreateMutableBinding(name, deletable)。

9.1.1.4.3 CreateImmutableBinding ( name, strict )

The CreateImmutableBinding concrete method of a Global Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它为名称 name 创建一个新的未初始化不可变绑定。在这个 Environment Record 中,name 的绑定必须尚不存在。如果 stricttrue,则新绑定会被标记为严格绑定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,抛出一个 TypeError 异常。
  3. 返回 ! declarativeRecord.CreateImmutableBinding(name, strict)。

9.1.1.4.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of a Global Environment Record envRec takes arguments name (一个 String,) and value (一个 ECMAScript 语言值,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它用于将当前名称为 name 的标识符绑定的绑定值设为 value。必须已经存在一个未初始化的 name 绑定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,那么
    1. 返回 ! declarativeRecord.InitializeBinding(name, value)。
  3. 断言:如果绑定存在,那么它一定在 Object Environment Record 中。
  4. objectRecordenvRec.[[ObjectRecord]]
  5. 返回 ? objectRecord.InitializeBinding(name, value)

9.1.1.4.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of a Global Environment Record envRec takes arguments name (一个 String,), value (一个 ECMAScript 语言值,), and strict (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它尝试将当前名称为 name 的标识符绑定的绑定值更改为 value。如果该绑定是不可变绑定且 stricttrue,则会抛出一个 TypeError。通常名称为 name 的绑定已经存在,但如果不存在,或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,那么
    1. 返回 ? declarativeRecord.SetMutableBinding(name, value, strict)。
  3. objectRecordenvRec.[[ObjectRecord]]
  4. 返回 ? objectRecord.SetMutableBinding(name, value, strict)

9.1.1.4.6 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Global Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它返回其绑定的、名称为 name 的标识符的值。如果绑定是未初始化绑定,则会抛出一个 ReferenceError 异常。通常名称为 name 的绑定已经存在,但如果不存在,或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,那么
    1. 返回 ? declarativeRecord.GetBindingValue(name, strict)。
  3. objectRecordenvRec.[[ObjectRecord]]
  4. 返回 ? objectRecord.GetBindingValue(name, strict)

9.1.1.4.7 DeleteBinding ( name )

The DeleteBinding concrete method of a Global Environment Record envRec takes argument name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它只能删除那些被显式指定为可删除的绑定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 如果 ! declarativeRecord.HasBinding(name) 是 true,那么
    1. 返回 ! declarativeRecord.DeleteBinding(name)。
  3. objectRecordenvRec.[[ObjectRecord]]
  4. globalObjectobjectRecord.[[BindingObject]]
  5. existingProp 为 ? HasOwnProperty(globalObject, name)。
  6. 如果 existingProptrue,那么
    1. 返回 ? objectRecord.DeleteBinding(name)
  7. 返回 true

9.1.1.4.8 HasThisBinding ( )

The HasThisBinding concrete method of a Global Environment Record envRec takes no arguments and returns true. It performs the following steps when called:

  1. 返回 true
Note

Global Environment Record 总是提供 this 绑定。

9.1.1.4.9 GetThisBinding ( )

The GetThisBinding concrete method of a Global Environment Record envRec takes no arguments and returns 一个包含 Object 的正常完成. It performs the following steps when called:

  1. 返回 envRec.[[GlobalThisValue]]

9.1.1.4.10 HasSuperBinding ( )

The HasSuperBinding concrete method of a Global Environment Record envRec takes no arguments and returns false. It performs the following steps when called:

  1. 返回 false
Note

Global Environment Record 不提供 super 绑定。

9.1.1.4.11 WithBaseObject ( )

The WithBaseObject concrete method of a Global Environment Record envRec takes no arguments and returns undefined. It performs the following steps when called:

  1. 返回 undefined

9.1.1.4.12 HasLexicalDeclaration ( envRec, name )

The abstract operation HasLexicalDeclaration takes arguments envRec (一个 Global Environment Record,) and name (一个 String,) and returns 一个 Boolean. 它用于判定参数标识符在 envRec 中是否具有一个由词法声明(例如 LexicalDeclarationClassDeclaration)创建的绑定。 It performs the following steps when called:

  1. declarativeRecordenvRec.[[DeclarativeRecord]]
  2. 返回 ! declarativeRecord.HasBinding(name)。

9.1.1.4.13 HasRestrictedGlobalProperty ( envRec, name )

The abstract operation HasRestrictedGlobalProperty takes arguments envRec (一个 Global Environment Record,) and name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定参数标识符是否是全局对象上某个属性的名称,并且该属性不能被全局词法绑定遮蔽。 It performs the following steps when called:

  1. objectRecordenvRec.[[ObjectRecord]]
  2. globalObjectobjectRecord.[[BindingObject]]
  3. existingProp 为 ? globalObject.[[GetOwnProperty]](name)
  4. 如果 existingPropundefined,返回 false
  5. 如果 existingProp.[[Configurable]]true,返回 false
  6. 返回 true
Note

全局对象上可能存在某些直接创建出来的属性,而不是通过 var 或 function 声明来声明的。不能创建一个与全局对象的不可配置属性同名的全局词法绑定。全局属性 "undefined" 就是这样一个属性的例子。

9.1.1.4.14 CanDeclareGlobalVar ( envRec, name )

The abstract operation CanDeclareGlobalVar takes arguments envRec (一个 Global Environment Record,) and name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定:如果对同一个参数 name 调用对应的 CreateGlobalVarBinding,是否会成功。冗余的 var 声明,以及为已有全局对象属性进行的 var 声明,都是允许的。 It performs the following steps when called:

  1. objectRecordenvRec.[[ObjectRecord]]
  2. globalObjectobjectRecord.[[BindingObject]]
  3. hasProperty 为 ? HasOwnProperty(globalObject, name)。
  4. 如果 hasPropertytrue,返回 true
  5. 返回 ? IsExtensible(globalObject)。

9.1.1.4.15 CanDeclareGlobalFunction ( envRec, name )

The abstract operation CanDeclareGlobalFunction takes arguments envRec (一个 Global Environment Record,) and name (一个 String,) and returns 要么是包含 Boolean 的正常完成,要么是抛出完成. 它用于判定:如果对同一个参数 name 调用对应的 CreateGlobalFunctionBinding,是否会成功。 It performs the following steps when called:

  1. objectRecordenvRec.[[ObjectRecord]]
  2. globalObjectobjectRecord.[[BindingObject]]
  3. existingProp 为 ? globalObject.[[GetOwnProperty]](name)
  4. 如果 existingPropundefined,返回 ? IsExtensible(globalObject)。
  5. 如果 existingProp.[[Configurable]]true,返回 true
  6. 如果 IsDataDescriptor(existingProp) 是 true,并且 existingProp 具有特性值 { [[Writable]]: true, [[Enumerable]]: true },返回 true
  7. 返回 false

9.1.1.4.16 CreateGlobalVarBinding ( envRec, name, deletable )

The abstract operation CreateGlobalVarBinding takes arguments envRec (一个 Global Environment Record,), name (一个 String,), and deletable (一个 Boolean,) and returns 要么是包含 unused正常完成,要么是抛出完成. 它在关联的 Object Environment Record 中创建并初始化一个可变绑定。如果绑定已经存在,则重用它,并假定其已经初始化。 It performs the following steps when called:

  1. objectRecordenvRec.[[ObjectRecord]]
  2. globalObjectobjectRecord.[[BindingObject]]
  3. hasProperty 为 ? HasOwnProperty(globalObject, name)。
  4. extensible 为 ? IsExtensible(globalObject)。
  5. 如果 hasPropertyfalseextensibletrue,那么
    1. 执行 ? objectRecord.CreateMutableBinding(name, deletable)
    2. 执行 ? objectRecord.InitializeBinding(name, undefined)
  6. 返回 unused

9.1.1.4.17 CreateGlobalFunctionBinding ( envRec, name, value, deletable )

The abstract operation CreateGlobalFunctionBinding takes arguments envRec (a Global Environment Record), name (a String), value (an ECMAScript function object), and deletable (a Boolean) and returns 要么是包含 unused正常完成,要么是抛出完成. 它在关联的 Object Environment Record 中创建并初始化一个可变绑定。如果绑定已经存在,则会被替换。 It performs the following steps when called:

  1. objectRecordenvRec.[[ObjectRecord]]
  2. globalObjectobjectRecord.[[BindingObject]]
  3. existingProp 为 ? globalObject.[[GetOwnProperty]](name)
  4. 如果 existingPropundefinedexistingProp.[[Configurable]]true,那么
    1. desc 为 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: deletable }。
  5. 否则,
    1. desc 为 PropertyDescriptor { [[Value]]: value }。
  6. 执行 ? DefinePropertyOrThrow(globalObject, name, desc)。
  7. 执行 ? Set(globalObject, name, value, false)。
  8. 返回 unused
Note

全局函数声明始终表示为全局对象的自有属性。如果可能,会重新配置已有的自有属性,使其具有一组标准特性值。步骤 7 等价于调用 InitializeBinding 具体方法将执行的操作;如果 globalObject 是一个 Proxy,则会产生相同顺序的 Proxy trap 调用。

9.1.1.5 Module Environment Record

Module Environment Record 是一种 Declarative Environment Record,用于表示 ECMAScript Module 的外层作用域。除了普通的可变绑定和不可变绑定之外,Module Environment Record 还提供不可变的 import 绑定,这类绑定会间接访问存在于另一个 Environment Record 中的目标绑定。

Module Environment Record 支持 Table 14 中列出的所有 Declarative Environment Record 方法,并且除 GetBindingValueDeleteBindingHasThisBindingGetThisBinding 之外,其余这些方法的规范都与 Declarative Environment Record 相同。

9.1.1.5.1 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Module Environment Record envRec takes arguments name (一个 String,) and strict (一个 Boolean,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它返回其绑定的、名称为 name 的标识符的值。不过,如果该绑定是一个间接绑定,则返回目标绑定的值。如果绑定存在但未初始化,则抛出 ReferenceError。 It performs the following steps when called:

  1. 断言:stricttrue
  2. 断言:envRec 具有 name 的绑定。
  3. 如果 name 的绑定是一个间接绑定,那么
    1. moduletargetName 为创建这个 name 绑定时提供的间接引用值。
    2. targetEnvmodule.[[Environment]]
    3. 如果 targetEnvempty,抛出一个 ReferenceError 异常。
    4. 返回 ? targetEnv.GetBindingValue(targetName, true)
  4. 如果 envRecname 的绑定是未初始化绑定,抛出一个 ReferenceError 异常。
  5. 返回 envRec 中当前绑定到 name 的值。
Note

strict 总是 true,因为 Module 始终是严格模式代码

9.1.1.5.2 DeleteBinding ( name )

本规范中从不使用 Module Environment RecordDeleteBinding 具体方法。

Note

Module Environment Record 只会在严格代码中使用,而早期错误规则会阻止在严格代码中将 delete 运算符应用到一个最终会解析为 Module Environment Record 绑定的 Reference Record 上。见 13.5.1.1

9.1.1.5.3 HasThisBinding ( )

The HasThisBinding concrete method of a Module Environment Record envRec takes no arguments and returns true. It performs the following steps when called:

  1. 返回 true
Note

Module Environment Record 总是提供 this 绑定。

9.1.1.5.4 GetThisBinding ( )

The GetThisBinding concrete method of a Module Environment Record envRec takes no arguments and returns 一个包含 undefined正常完成. It performs the following steps when called:

  1. 返回 undefined

9.1.1.5.5 CreateImportBinding ( envRec, name, targetModule, targetName )

The abstract operation CreateImportBinding takes arguments envRec (一个 Module Environment Record,), name (一个 String,), targetModule (一个 Module Record,), and targetName (一个 String,) and returns unused. 它为名称 name 创建一个新的、已初始化的不可变间接绑定。在 envRec 中,name 的绑定必须尚不存在。targetName 是存在于 targetModuleModule Environment Record 中的某个绑定名称。对这个新绑定值的访问将会间接访问目标绑定所绑定的值。 It performs the following steps when called:

  1. 断言:envRec 尚不存在 name 的绑定。
  2. 断言:当 targetModule.[[Environment]] 被实例化时,它将具有 targetName 的直接绑定。
  3. envRec 中为 name 创建一个不可变间接绑定,该绑定引用 targetModuletargetName 作为其目标绑定,并记录该绑定已初始化。
  4. 返回 unused

9.1.2 Environment Record 操作

本规范使用以下抽象操作来操作 Environment Record

9.1.2.1 GetIdentifierReference ( env, name, strict )

The abstract operation GetIdentifierReference takes arguments env (一个 Environment Recordnull,), name (一个 String,), and strict (一个 Boolean,) and returns 要么是包含 Reference Record正常完成,要么是抛出完成. It performs the following steps when called:

  1. 如果 envnull,那么
    1. 返回 Reference Record { [[Base]]: unresolvable, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  2. exists 为 ? env.HasBinding(name)
  3. 如果 existstrue,那么
    1. 返回 Reference Record { [[Base]]: env, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  4. outerenv.[[OuterEnv]]
  5. 返回 ? GetIdentifierReference(outer, name, strict)。

9.1.2.2 NewDeclarativeEnvironment ( outerEnv )

The abstract operation NewDeclarativeEnvironment takes argument outerEnv (一个 Environment Recordnull,) and returns 一个 Declarative Environment Record. It performs the following steps when called:

  1. env 为一个新的 Declarative Environment Record,不含任何绑定。
  2. env.[[OuterEnv]] 设为 outerEnv
  3. 返回 env

9.1.2.3 NewObjectEnvironment ( obj, isWithEnvironment, outerEnv )

The abstract operation NewObjectEnvironment takes arguments obj (一个 Object,), isWithEnvironment (一个 Boolean,), and outerEnv (一个 Environment Recordnull,) and returns 一个 Object Environment Record. It performs the following steps when called:

  1. env 为一个新的 Object Environment Record
  2. env.[[BindingObject]] 设为 obj
  3. env.[[IsWithEnvironment]] 设为 isWithEnvironment
  4. env.[[OuterEnv]] 设为 outerEnv
  5. 返回 env

9.1.2.4 NewFunctionEnvironment ( func, newTarget )

The abstract operation NewFunctionEnvironment takes arguments func (一个 ECMAScript 函数对象,) and newTarget (一个 Object 或 undefined,) and returns 一个 Function Environment Record. It performs the following steps when called:

  1. env 为一个新的 Function Environment Record,不含任何绑定。
  2. env.[[FunctionObject]] 设为 func
  3. 如果 func.[[ThisMode]]lexical,将 env.[[ThisBindingStatus]] 设为 lexical
  4. 否则,将 env.[[ThisBindingStatus]] 设为 uninitialized
  5. env.[[NewTarget]] 设为 newTarget
  6. env.[[OuterEnv]] 设为 func.[[Environment]]
  7. 返回 env

9.1.2.5 NewGlobalEnvironment ( obj, thisValue )

The abstract operation NewGlobalEnvironment takes arguments obj (一个 Object,) and thisValue (一个 Object,) and returns 一个 Global Environment Record. It performs the following steps when called:

  1. objRecNewObjectEnvironment(obj, false, null)。
  2. dclRecNewDeclarativeEnvironment(null)。
  3. env 为一个新的 Global Environment Record
  4. env.[[ObjectRecord]] 设为 objRec
  5. env.[[GlobalThisValue]] 设为 thisValue
  6. env.[[DeclarativeRecord]] 设为 dclRec
  7. env.[[OuterEnv]] 设为 null
  8. 返回 env

9.1.2.6 NewModuleEnvironment ( outerEnv )

The abstract operation NewModuleEnvironment takes argument outerEnv (a Global Environment Record) and returns a Module Environment Record. It performs the following steps when called:

  1. env 为一个新的 Module Environment Record,不含任何绑定。
  2. env.[[OuterEnv]] 设为 outerEnv
  3. 返回 env

9.2 PrivateEnvironment Record

PrivateEnvironment Record 是一种规范机制,用于根据 ECMAScript 代码中 ClassDeclarationClassExpression 的词法嵌套结构来追踪 Private Name。它们与 Environment Record 类似,但彼此不同。每个 PrivateEnvironment Record 都与一个 ClassDeclarationClassExpression 相关联。每次对此类类进行求值时,都会创建一个新的 PrivateEnvironment Record,用来记录该类声明的 Private Name

每个 PrivateEnvironment Record 都具有 Table 18 中定义的字段。

Table 18: PrivateEnvironment Record 字段
字段名称 值类型 含义
[[OuterPrivateEnvironment]] 一个 PrivateEnvironment Recordnull 最近的包含类的 PrivateEnvironment Record。如果与此 PrivateEnvironment Record 相关联的类未包含在任何其他类中,则为 null
[[Names]] 一个 Private NameList 由该类声明的 Private Name

9.2.1 PrivateEnvironment Record 操作

本规范使用以下抽象操作来操作 PrivateEnvironment Record

9.2.1.1 NewPrivateEnvironment ( outerPrivateEnv )

The abstract operation NewPrivateEnvironment takes argument outerPrivateEnv (一个 PrivateEnvironment Recordnull,) and returns 一个 PrivateEnvironment Record. It performs the following steps when called:

  1. names 为一个新的空 List
  2. 返回 PrivateEnvironment Record { [[OuterPrivateEnvironment]]: outerPrivateEnv, [[Names]]: names }。

9.2.1.2 ResolvePrivateIdentifier ( privateEnv, identifier )

The abstract operation ResolvePrivateIdentifier takes arguments privateEnv (一个 PrivateEnvironment Record,) and identifier (一个 String,) and returns 一个 Private Name. It performs the following steps when called:

  1. namesprivateEnv.[[Names]]
  2. names 中的每个 Private Name pn,执行
    1. 如果 pn.[[Description]]identifier,那么
      1. 返回 pn
  3. outerPrivateEnvprivateEnv.[[OuterPrivateEnvironment]]
  4. 断言:outerPrivateEnv 不是 null
  5. 返回 ResolvePrivateIdentifier(outerPrivateEnv, identifier)。

9.3 Realm

在求值之前,所有 ECMAScript 代码都必须与一个 realm 相关联。从概念上说,一个 realm 由一组内在对象、一个 ECMAScript 全局环境、在该全局环境作用域内加载的所有 ECMAScript 代码,以及其他相关状态和资源组成。

在本规范中,realm 表示为一个 Realm Record,其字段规定在 Table 19 中:

Table 19: Realm Record 字段
字段名称 含义
[[AgentSignifier]] 一个 agent 标识符 拥有该 realmagent
[[Intrinsics]] 一个 Record,其字段名为内在键,字段值为对象 与该 realm 关联的代码所使用的内在值
[[GlobalObject]] 一个 Object realm全局对象
[[GlobalEnv]] 一个 Global Environment Record realm 的全局环境
[[TemplateMap]] 一个 RecordList,这些 Record 具有 [[Site]](一个 TemplateLiteral Parse Node)和 [[Array]](一个 Array)字段

模板对象会针对每个 realm 分别使用其 Realm Record[[TemplateMap]] 进行规范化。每个 [[Site]] 值都是一个 Parse Node,并且是一个 TemplateLiteral。关联的 [[Array]] 值是传递给标签函数的对应模板对象。

Note 1
一旦某个 Parse Node 变得不可达,则相应的 [[Array]] 也变得不可达,并且如果某实现将该对从 [[TemplateMap]] 列表中移除,这种行为将不可观察。
[[LoadedModules]] 一个 LoadedModuleRequest RecordList

从该 realm 导入的说明符字符串到已解析 Module Record 的映射。该列表中不会包含两个不同的 Record r1r2,使得 ModuleRequestsEqual(r1, r2) 是 true

Note 2
HostLoadImportedModule16.2.1.10 Note 1)中所述,Realm Record 中的 [[LoadedModules]] 仅在没有活动 script 或 module 的上下文中运行 import() 表达式时使用。
[[HostDefined]] 任意值(默认值为 undefined 为需要将附加信息与 Realm Record 关联起来的宿主保留的字段。

9.3.1 InitializeHostDefinedRealm ( )

The abstract operation InitializeHostDefinedRealm takes no arguments and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

  1. realm 为一个新的 Realm Record
  2. 执行 CreateIntrinsics(realm)。
  3. realm.[[AgentSignifier]] 设为 AgentSignifier()。
  4. realm.[[TemplateMap]] 设为一个新的空 List
  5. newContext 为一个新的执行上下文
  6. newContext 的 Function 设为 null
  7. newContextRealm 设为 realm
  8. newContext 的 ScriptOrModule 设为 null
  9. newContext 压入执行上下文栈newContext 现在是正在运行的执行上下文
  10. 如果宿主要求使用某个特定对象作为 realm全局对象,那么
    1. global 为以宿主定义方式创建的该对象。
  11. 否则,
    1. globalOrdinaryObjectCreate(realm.[[Intrinsics]].[[%Object.prototype%]])。
  12. 如果宿主要求 realm 的全局作用域中的 this 绑定返回的对象不同于全局对象,那么
    1. thisValue 为以宿主定义方式创建的该对象。
  13. 否则,
    1. thisValueglobal
  14. realm.[[GlobalObject]] 设为 global
  15. realm.[[GlobalEnv]] 设为 NewGlobalEnvironment(global, thisValue)。
  16. 执行 ? SetDefaultGlobalBindings(realm)。
  17. global 上创建任何宿主定义全局对象属性。
  18. 返回 unused

9.3.2 CreateIntrinsics ( realmRec )

The abstract operation CreateIntrinsics takes argument realmRec (一个 Realm Record,) and returns unused. It performs the following steps when called:

  1. realmRec.[[Intrinsics]] 设为一个新的 Record
  2. Table 6 中列出的值设为 realmRec.[[Intrinsics]] 的字段。字段名是表中“Intrinsic Name”列列出的名称。每个字段的值都是一个全新的对象值,并且根据条款 1928 中对每个对象的规范,完整且递归地填充其属性值。所有对象属性值都是新创建的对象值。所有内建函数对象的值都通过执行 CreateBuiltinFunction(steps, length, name, slots, realmRec, prototype, async) 来创建,其中 steps 是本规范提供的该函数定义,name 是函数 "name" 属性的初始值,length 是函数 "length" 属性的初始值,slots 是该函数规定的内部名称列表(如果有),prototype 是该函数 [[Prototype]] 内部槽规定的值,而 async 则在该函数被描述为“async”时为 true,否则为 false。内在对象及其属性的创建顺序必须避免依赖于尚未创建的对象。
  3. 执行 AddRestrictedFunctionProperties(realmRec.[[Intrinsics]].[[%Function.prototype%]], realmRec)。
  4. 返回 unused

9.3.3 SetDefaultGlobalBindings ( realmRec )

The abstract operation SetDefaultGlobalBindings takes argument realmRec (一个 Realm Record,) and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

  1. globalrealmRec.[[GlobalObject]]
  2. 对条款 19 中规定的 Global Object 的每个属性,执行
    1. name 为该属性名的 String 值。
    2. desc 为该属性的完整填充数据 Property Descriptor,包含该属性规定的特性值。对于列在 19.219.319.4 中的属性,其 [[Value]] 特性的值为来自 realmRec 的相应内在对象。
    3. 执行 ? DefinePropertyOrThrow(global, name, desc)。
  3. 返回 unused

9.4 执行上下文

执行上下文是一种规范装置,用于跟踪 ECMAScript 实现对代码的运行时求值。在任意时刻,每个 agent 最多只有一个实际正在执行代码的执行上下文。这称为该 agent正在运行的执行上下文。本规范中所有对正在运行的执行上下文的引用,都表示外围 agent 的正在运行执行上下文。

执行上下文栈用于跟踪执行上下文。正在运行的执行上下文总是该栈的顶部元素。每当控制从当前正在运行执行上下文关联的可执行代码转移到不与该执行上下文关联的可执行代码时,就会创建一个新的执行上下文。新创建的执行上下文会被压入栈中,并成为正在运行的执行上下文

一个执行上下文包含跟踪其关联代码执行进度所需的任何实现特定状态。每个执行上下文至少具有 Table 20 中列出的状态组成部分。

Table 20: 所有执行上下文的状态组成部分
组成部分 目的
代码求值状态 执行、挂起和恢复与该执行上下文关联代码的求值所需的任何状态。
Function 如果该执行上下文正在求值某个函数对象的代码,则该组成部分的值为该函数对象。如果该上下文正在求值 ScriptModule 的代码,则该值为 null
Realm 与该代码访问 ECMAScript 资源相关联的 Realm Record
ScriptOrModule 与该代码来源相关联的 Module RecordScript Record。如果不存在来源脚本或模块(如在 InitializeHostDefinedRealm 中创建的原始执行上下文的情况),则该值为 null

正在运行的执行上下文对代码的求值,可能会在本规范定义的多个点上被挂起。一旦正在运行的执行上下文被挂起,另一个执行上下文就可能成为正在运行的执行上下文并开始求值其代码。在稍后的某个时间点,一个已挂起的执行上下文可能再次成为正在运行的执行上下文,并从先前挂起的位置继续求值其代码。执行上下文之间正在运行状态的切换,通常以栈式后进先出的方式发生。然而,某些 ECMAScript 特性要求执行上下文的正在运行状态发生非 LIFO 切换。

正在运行的执行上下文Realm 组成部分的值,也称为当前 Realm Record正在运行的执行上下文的 Function 组成部分的值,也称为活动函数对象

ECMAScript 代码执行上下文具有 Table 21 中列出的附加状态组成部分。

Table 21: ECMAScript 代码执行上下文的附加状态组成部分
组成部分 目的
LexicalEnvironment 标识用于解析在该执行上下文中的代码所产生的标识符引用的 Environment Record
VariableEnvironment 标识保存该执行上下文VariableStatement 所创建绑定的 Environment Record
PrivateEnvironment 标识保存最近外围类中由 ClassElement 创建的 Private NamePrivateEnvironment Record。如果不存在外围类,则为 null

执行上下文的 LexicalEnvironment 和 VariableEnvironment 组成部分始终都是 Environment Record

表示 Generator 求值的执行上下文具有 Table 22 中列出的附加状态组成部分。

Table 22: Generator 执行上下文的附加状态组成部分
组成部分 目的
Generator 执行上下文正在求值的 Generator。

在大多数情况下,本规范中的算法只会直接操作正在运行的执行上下文(即执行上下文栈顶)。因此,当术语“LexicalEnvironment”和“VariableEnvironment”在未加限定的情况下使用时,它们指的都是正在运行执行上下文中的相应组成部分。

执行上下文纯粹是一种规范机制,不需要对应于任何 ECMAScript 实现中的特定构件。ECMAScript 代码不可能直接访问或观察执行上下文。

9.4.1 GetActiveScriptOrModule ( )

The abstract operation GetActiveScriptOrModule takes no arguments and returns 一个 Script Record、一个 Module Recordnull. 它用于根据正在运行的执行上下文,确定当前正在运行的脚本或模块。 It performs the following steps when called:

  1. 如果执行上下文栈为空,返回 null
  2. ec执行上下文栈中最顶部的那个执行上下文,且其 ScriptOrModule 组成部分不为 null
  3. 如果不存在这样的执行上下文,返回 null
  4. 返回 ec 的 ScriptOrModule。

9.4.2 ResolveBinding ( name [ , env ] )

The abstract operation ResolveBinding takes argument name (一个 String,) and optional argument env (一个 Environment Recordundefined,) and returns 要么是包含 Reference Record正常完成,要么是抛出完成. 它用于确定 name 的绑定。env 可用于显式提供应当被搜索该绑定的 Environment Record。 It performs the following steps when called:

  1. 如果 env 不存在,或 envundefined,那么
    1. env 设为正在运行执行上下文的 LexicalEnvironment。
  2. 断言:env 是一个 Environment Record
  3. strictIsStrict(当前正在求值的语法产生式)。
  4. 返回 ? GetIdentifierReference(env, name, strict)。
Note

ResolveBinding 的结果始终是一个 Reference Record,其 [[ReferencedName]] 字段为 name

9.4.3 GetThisEnvironment ( )

The abstract operation GetThisEnvironment takes no arguments and returns 一个 Environment Record. 它查找当前提供关键字 this 绑定的那个 Environment Record。 It performs the following steps when called:

  1. env 为正在运行执行上下文的 LexicalEnvironment。
  2. 重复,
    1. existsenv.HasThisBinding()。
    2. 如果 existstrue,返回 env
    3. outerenv.[[OuterEnv]]
    4. 断言:outer 不是 null
    5. env 设为 outer
Note

步骤 2 中的循环总会终止,因为环境列表最终总是以具有 this 绑定的全局环境结束。

9.4.4 ResolveThisBinding ( )

The abstract operation ResolveThisBinding takes no arguments and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成. 它使用正在运行执行上下文的 LexicalEnvironment 来确定关键字 this 的绑定。 It performs the following steps when called:

  1. envRecGetThisEnvironment()。
  2. 返回 ? envRec.GetThisBinding()。

9.4.5 GetNewTarget ( )

The abstract operation GetNewTarget takes no arguments and returns 一个 Object 或 undefined. 它使用正在运行执行上下文的 LexicalEnvironment 来确定 NewTarget 值。 It performs the following steps when called:

  1. envRecGetThisEnvironment()。
  2. 断言:envRec 具有 [[NewTarget]] 字段。
  3. 返回 envRec.[[NewTarget]]

9.4.6 GetGlobalObject ( )

The abstract operation GetGlobalObject takes no arguments and returns 一个 Object. 它返回当前正在运行执行上下文所使用的全局对象。 It performs the following steps when called:

  1. currentRealm当前 Realm Record
  2. 返回 currentRealm.[[GlobalObject]]

9.4.7 RunSuspendedContext ( context, completionRecord )

The abstract operation RunSuspendedContext takes arguments context (一个执行上下文) and completionRecord (一个完成记录) and returns 要么是一个包含 ECMAScript 语言值unused正常完成,要么是一个突然完成. 它恢复 context(将 completionRecord 作为恢复值发送给它),并等待结果。 It performs the following steps when called:

  1. callerContext正在运行的执行上下文
  2. 挂起 callerContext
  3. context 压入执行上下文栈context 现在是正在运行的执行上下文
  4. 恢复 context 的已挂起求值,使用 completionRecord 作为挂起它的操作的结果。令 result 为恢复的计算返回的完成记录。
  5. 断言:当到达此步骤时,context 已经从执行上下文栈中移除,并且 callerContext 再次成为正在运行的执行上下文
  6. 返回 Completion(result)。

9.5 Job 以及将 Job 入队的宿主操作

Job 是一个不带参数的 Abstract Closure,当当前没有其他 ECMAScript 计算正在进行时,它会启动一段 ECMAScript 计算。

Job 由 ECMAScript 宿主环境安排到某个特定 agent 中执行。本规范描述了宿主钩子 HostEnqueueGenericJobHostEnqueueFinalizationRegistryCleanupJobHostEnqueuePromiseJobHostEnqueueTimeoutJob,用于调度 Job。本规范中的宿主钩子是按 Job 调度时施加的附加约束来组织的。宿主还可以定义额外的抽象操作来调度 Job。这类操作接受一个 Job Abstract Closure 和一个 realm(一个 Realm Recordnull)作为参数。如果提供的是一个 Realm Record,那么这些操作会将该 Job 调度到将来某个时间、在提供的 realm 中、由拥有该 realmagent 来执行。如果提供的是 null 而不是 realm,那么该 Job 不会求值 ECMAScript 代码。它们的实现必须符合以下要求:

Note 1
宿主环境不要求在调度上对所有 Job 一视同仁。例如,Web 浏览器和 Node.js 会将 Promise 处理 Job 视为比其他工作更高优先级;未来的特性也可能引入一些不会被赋予如此高优先级的 Job

在任意特定时刻,如果 scriptOrModule(一个 Script Record、一个 Module Recordnull)满足以下所有条件,则它是活动脚本或模块

在任意特定时刻,如果满足以下所有条件,则某次执行是已准备好求值 ECMAScript 代码的:

Note 2

宿主环境可以通过向执行上下文栈压入执行上下文,使某次执行准备好求值代码。具体步骤由实现定义

Realm 的具体选择由宿主环境决定。这个初始执行上下文Realm 只会在任何回调函数被调用之前使用。当与某个 Job 相关的回调函数(例如 Promise 处理器)被调用时,该调用会压入它自己的执行上下文Realm

某些特定种类的 Job 还具有额外的一致性要求。

9.5.1 JobCallback Record

JobCallback Record 是一种 Record 值,用于存储一个函数对象和一个宿主定义值。通过宿主入队的 Job 来调用的函数对象,可能具有额外的宿主定义上下文。为了传播该状态,Job Abstract Closure 不应直接捕获并调用函数对象。相反,应使用 HostMakeJobCallbackHostCallJobCallback

Note

例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)使用该宿主定义值来传播 Promise 回调的 incumbent settings object。

JobCallback Record 具有 Table 23 中列出的字段。

Table 23: JobCallback Record 字段
字段名称 含义
[[Callback]] 一个函数对象 Job 被调用时要调用的函数。
[[HostDefined]] 任意值(默认值为 empty 宿主保留的字段。

9.5.2 HostMakeJobCallback ( callback )

The host-defined abstract operation HostMakeJobCallback takes argument callback (一个函数对象,) and returns 一个 JobCallback Record.

HostMakeJobCallback 的实现必须符合以下要求:

HostMakeJobCallback 的默认实现会在被调用时执行以下步骤:

  1. 返回 JobCallback Record { [[Callback]]: callback, [[HostDefined]]: empty }。

不是 Web 浏览器的 ECMAScript 宿主必须使用 HostMakeJobCallback 的默认实现。

Note

这是在回调被传给负责最终调度并运行它的函数时调用的。例如,promise.then(thenAction) 会在调用 Promise.prototype.then 时对 thenAction 调用 MakeJobCallback,而不是在调度 reaction Job 时才调用。

9.5.3 HostCallJobCallback ( jobCallback, value, argumentsList )

The host-defined abstract operation HostCallJobCallback takes arguments jobCallback (一个 JobCallback Record,), value (一个 ECMAScript 语言值,), and argumentsList (一个 ECMAScript 语言值List,) and returns 要么是包含 ECMAScript 语言值正常完成,要么是抛出完成.

HostCallJobCallback 的实现必须符合以下要求:

  • 它必须执行并返回 Call(jobCallback.[[Callback]], value, argumentsList) 的结果。
Note

这一要求意味着宿主不能改变本规范中定义的函数对象[[Call]] 行为。

HostCallJobCallback 的默认实现会在被调用时执行以下步骤:

  1. 断言:IsCallable(jobCallback.[[Callback]]) 是 true
  2. 返回 ? Call(jobCallback.[[Callback]], value, argumentsList)。

不是 Web 浏览器的 ECMAScript 宿主必须使用 HostCallJobCallback 的默认实现。

9.5.4 HostEnqueueGenericJob ( job, realm )

The host-defined abstract operation HostEnqueueGenericJob takes arguments job (一个 Job Abstract Closure,) and realm (一个 Realm Record,) and returns unused. 它会将 job 安排到由 realm.[[AgentSignifier]] 所标识的 agent 中、在 realm realm 内,于将来的某个时间执行。与该算法一起使用的 Abstract Closure 旨在不受诸如优先级与顺序等额外约束地被调度。

HostEnqueueGenericJob 的实现必须符合 9.5 中的要求。

9.5.5 HostEnqueuePromiseJob ( job, realm )

The host-defined abstract operation HostEnqueuePromiseJob takes arguments job (一个 Job Abstract Closure,) and realm (一个 Realm Recordnull,) and returns unused. 它会安排 job 在将来的某个时间执行。与该算法一起使用的 Abstract Closure 旨在与 Promise 的处理相关,或者以与 Promise 处理操作同等优先级的方式进行调度。

HostEnqueuePromiseJob 的实现除了必须符合 9.5 中的要求之外,还必须符合以下要求:

Note

对于由 NewPromiseResolveThenableJob 返回的 Job,其 realm 通常是对 then 函数对象调用 GetFunctionRealm 的结果。对于由 NewPromiseReactionJob 返回的 Job,如果 handler 不是 undefined,则其 realm 通常是对该 handler 调用 GetFunctionRealm 的结果;如果 handler 是 undefined,则 realmnull。对于这两类 Job,当 GetFunctionRealm 异常完成时(即在一个已撤销的 Proxy 上调用),realm 为调用 GetFunctionRealm 时的当前 Realm Record。当 realmnull 时,不会求值任何用户 ECMAScript 代码,也不会创建任何新的 ECMAScript 对象(例如 Error 对象)。例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)会使用 realm 来检查是否有能力运行脚本以及 entry 概念。

9.5.6 HostEnqueueTimeoutJob ( timeoutJob, realm, milliseconds )

The host-defined abstract operation HostEnqueueTimeoutJob takes arguments timeoutJob (一个 Job Abstract Closure,), realm (一个 Realm Record,), and milliseconds (一个非负有限 Number,) and returns unused. 它会将 timeoutJob 安排到由 realm.[[AgentSignifier]] 所标识的 agent 中、在 realm realm 内,至少在 milliseconds 毫秒之后执行。

HostEnqueueTimeoutJob 的实现必须符合 9.5 中的要求。

9.6 Agent

agent 由一组 ECMAScript 执行上下文、一个执行上下文栈、一个正在运行的执行上下文、一个 Agent Record,以及一个执行线程组成。除执行线程外,agent 的这些组成部分都专属于该 agent

一个 agent执行线程会独立于其他 agent,在该 agent执行上下文上执行算法步骤;但一个执行线程也可以同时被多个 agent 作为执行线程使用,只要这些共享该线程的 agent 中,没有任何一个 agentAgent Record[[CanBlock]] 字段为 true

Note 1

例如,一些 Web 浏览器会在一个浏览器窗口中的多个互不相关的标签页之间共享同一个执行线程

当一个 agent执行线程正在执行算法步骤时,该 agent 就是这些步骤的外围 agent。这些步骤通过外围 agent 来访问 agent 内部持有的规范层级执行对象:正在运行的执行上下文执行上下文栈,以及 Agent Record 的字段。

agent 标识符是一个全局唯一的不透明值,用于标识一个 Agent

Table 24: Agent Record 字段
字段名称 含义
[[LittleEndian]] 一个 Boolean 在算法 GetValueFromBufferSetValueInBuffer 需要 isLittleEndian 参数时,作为默认值使用。其选择由实现定义,并且应采用对实现最有效的方案。
[[CanBlock]] 一个 Boolean 决定该 agent 是否可以阻塞。
[[Signifier]] 一个 agent 标识符 在其 agent cluster 内唯一标识该 agent
[[IsLockFree1]] 一个 Boolean 如果对 1 字节值的原子操作是无锁的,则为 true,否则为 false
[[IsLockFree2]] 一个 Boolean 如果对 2 字节值的原子操作是无锁的,则为 true,否则为 false
[[IsLockFree8]] 一个 Boolean 如果对 8 字节值的原子操作是无锁的,则为 true,否则为 false
[[CandidateExecution]] 一个 candidate execution Record 参见内存模型
[[KeptAlive]] 一个由 Object 或 Symbol 组成的 List 初始为一个新的空 List,表示在当前 Job 结束前需要保持存活的对象和/或 symbol 列表
[[ModuleAsyncEvaluationCount]] 一个整数 初始值为 0,用于为异步模块或具有异步依赖的模块的 [[AsyncEvaluationOrder]] 字段分配唯一递增值。

[[LittleEndian]][[Signifier]][[IsLockFree1]][[IsLockFree2]][[IsLockFree8]] 的值都不能改变。

Note 2

[[IsLockFree1]][[IsLockFree2]][[IsLockFree8]] 的值不一定完全由硬件决定,也可能反映实现选择,而这些选择可能随时间变化,并且在不同 ECMAScript 实现之间也可能不同。

不存在 [[IsLockFree4]] 字段:4 字节原子操作始终是无锁的。

在实践中,如果一个原子操作是通过任何类型的锁实现的,那么该操作就不是无锁的。无锁并不意味着无等待:完成一个无锁原子操作所需的机器步骤数没有上界。

大小为 n 的原子访问是无锁的,并不意味着大小为 n 的非原子访问在(感知到的)原子性方面有什么保证;具体来说,非原子访问仍然可能作为多个独立内存访问的序列来执行。详见 ReadSharedMemory 和 WriteSharedMemory。

Note 3

agent 是一种规范机制,不需要对应于任何 ECMAScript 实现中的特定构件。

9.6.1 AgentSignifier ( )

The abstract operation AgentSignifier takes no arguments and returns 一个 agent 标识符. It performs the following steps when called:

  1. agentRecord外围 agentAgent Record
  2. 返回 agentRecord.[[Signifier]]

9.6.2 AgentCanSuspend ( )

The abstract operation AgentCanSuspend takes no arguments and returns 一个 Boolean. It performs the following steps when called:

  1. agentRecord外围 agentAgent Record
  2. 返回 agentRecord.[[CanBlock]]
Note

在某些环境中,允许某个给定 agent 挂起可能并不合理。例如,在 Web 浏览器环境中,禁止挂起文档的主事件处理线程可能是合理的,而仍然允许 worker 的事件处理线程挂起。

9.6.3 IncrementModuleAsyncEvaluationCount ( )

The abstract operation IncrementModuleAsyncEvaluationCount takes no arguments and returns a non-negative integer. It performs the following steps when called:

  1. agentRecord外围 agentAgent Record
  2. countagentRecord.[[ModuleAsyncEvaluationCount]]
  3. agentRecord.[[ModuleAsyncEvaluationCount]] 设为 count + 1。
  4. 返回 count
Note

该值仅用于跟踪待定模块之间的相对求值顺序。当不存在待定模块时,实现可以以不可观察的方式将 [[ModuleAsyncEvaluationCount]] 重置为 0。

9.7 Agent 集群

agent 集群是一个极大 agent 集合,这些 agent 能够通过操作共享内存进行通信。

Note 1

不同 agent 中的程序可以通过未指定的手段共享内存。至少,SharedArrayBuffer 的后备内存可以在该集群中的 agent 之间共享。

可能存在一些 agent,它们可以通过消息传递进行通信,但不能共享内存;它们绝不会处于同一个 agent 集群中。

每个 agent 都且仅属于一个 agent 集群。

Note 2

一个集群中的 agent 不必在某个特定时间点都存活。如果 agent A 创建了另一个 agent B,随后 A 终止,而 B 又创建了 agent C,那么如果 A 能与 B 共享某些内存,且 B 能与 C 共享某些内存,则这三个 agent 处于同一个集群中。

一个集群中的所有 agent,其各自 Agent Record 中的 [[LittleEndian]] 字段必须具有相同的值。

Note 3

如果一个 agent 集群中的不同 agent 具有不同的 [[LittleEndian]] 值,那么在共享内存中使用多字节数据就会变得困难。

一个集群中的所有 agent,其各自 Agent Record 中的 [[IsLockFree1]] 字段必须具有相同的值;[[IsLockFree2]][[IsLockFree8]] 字段也同样如此。

一个集群中的所有 agent,其各自 Agent Record 中的 [[Signifier]] 字段必须具有不同的值。

嵌入环境可以在 agent 不知情或不配合的情况下停用(停止前进进展)或激活(恢复前进进展)一个 agent。如果嵌入环境这样做,它就不得让集群中的某些 agent 保持活动状态,而其他 agent 被无限期停用。

Note 4

上述限制的目的是避免这样一种情况:某个 agent 因为另一个 agent 已被停用而发生死锁或饥饿。例如,如果某个 HTML 共享 worker 的生命周期独立于任何窗口中的文档,并且它被允许与这样一个独立文档的专用 worker 共享内存;而当该专用 worker 持有某个锁时(比如,该文档被推入其窗口历史记录中),该文档及其专用 worker 被停用;然后该共享 worker 又尝试获取这个锁,那么该共享 worker 将一直被阻塞,直到该专用 worker 再次被激活(如果有的话)。与此同时,来自其他窗口、试图通过该共享 worker 进行访问的其他 worker 就会发生饥饿。

这一限制的含义是:不可能在不属于嵌入环境中同一个挂起/唤醒集合的 agent 之间共享内存。

嵌入环境可以在该 agent 集群中的其他 agent 都事先不知情或不配合的情况下终止一个 agent。如果一个 agent 的终止不是由它自己或集群中另一个 agent 的程序动作引起,而是由集群外部的力量导致的,那么嵌入环境必须在两种策略中选择其一:要么终止该集群中的所有 agent,要么提供可靠的 API,使集群中的 agent 能够协调,以便至少有一个剩余成员能够检测到该终止,并且该终止数据中包含足够的信息来识别被终止的那个 agent

Note 5

这种终止的例子包括:操作系统或用户终止运行在独立进程中的 agent;或者当按 agent 的资源记账表明某个 agent 已经失控时,嵌入环境自身终止那个与其他 agent 共同在进程内运行的 agent

以下每一个规范值,以及从它们可传递到达的值,都且仅属于一个 agent 集群。

在一个集群中的任意 agent 开始对任何 ECMAScript 代码求值之前,该集群中所有 agentAgent Record[[CandidateExecution]] 字段都被设为初始 candidate execution。初始 candidate execution 是一个空的 candidate execution,其 [[EventsRecords]] 字段是一个 List;对于每个 agent,其中包含一个 Agent Events Record,该 Record[[AgentSignifier]] 字段为该 agentagent 标识符,而其 [[EventList]][[AgentSynchronizesWith]] 字段均为空 List

Note 6

一个 agent 集群中的所有 agent 在其 Agent Record[[CandidateExecution]] 字段中共享同一个 candidate execution。candidate execution 是内存模型所使用的一种规范机制。

Note 7

agent 集群是一种规范机制,不需要对应于任何 ECMAScript 实现中的特定构件。

9.8 前进进展

一个 agent 取得前进进展,是指它按照本规范执行了一步求值步骤。

当一个 agent 的正在运行执行上下文同步且无限期地等待某个外部事件时,该 agent 就变为阻塞状态。只有其 Agent Record[[CanBlock]] 字段为 trueagent,才能以这种意义进入阻塞状态。未阻塞agent 是指未处于阻塞状态的 agent

实现必须确保:

  • 每个拥有专用执行线程的未阻塞 agent 最终都会取得前进进展
  • 在一组共享同一执行线程agent 中,最终会有一个 agent 取得前进进展
  • 一个 agent 不会使另一个 agent 进入阻塞状态,除非是通过嵌入环境提供阻塞能力的 API。
Note

这一点,加上内存模型中的活性保证,可确保所有 seq-cst 写入最终都会对所有 agent 变得可观察。

9.9 WeakRef 和 FinalizationRegistry 目标的处理模型

9.9.1 目标

本规范不保证任何对象或 symbol 一定会被垃圾回收。那些不再存活的对象或 symbol,可能会在很长时间后才被释放,甚至永远不被释放。出于这个原因,本规范在描述由垃圾回收触发的行为时使用术语“may”。

WeakRefFinalizationRegistry 的语义建立在两个会在特定时间点发生的操作之上:

这两种动作(ClearKeptObjectsCleanupFinalizationRegistry)都不得中断同步 ECMAScript 执行。由于宿主可能会组织出更长的同步 ECMAScript 执行序列,因此本规范将 ClearKeptObjectsCleanupFinalizationRegistry 的调度推迟给宿主环境

某些 ECMAScript 实现包含后台运行的垃圾回收器实现,包括在 ECMAScript 空闲时运行。让宿主环境调度 CleanupFinalizationRegistry,使其能够恢复 ECMAScript 执行以运行终结器工作,而这可能释放 held value,从而减少整体内存使用。

9.9.2 活性

对于某个对象和/或 symbol 的集合 objectSet,相对于 objectSet 的一次假想的 WeakRef-oblivious执行,是指这样一种执行:其中某个 WeakRef 的 abstract operation WeakRefDeref,只要其 referent 是 objectSet 的元素,就总是返回 undefined

Note 1
WeakRef-obliviousness 与活性一起,捕捉了两个概念。其一,WeakRef 本身不会让其 referent 保持存活。其二,活性中的循环并不意味着某个值就是活的。具体来说,如果判定 v 的活性依赖于判定某个 WeakRef referent r 的活性,那么 r 的活性就不能反过来假定 v 的活性,否则会形成循环论证。
Note 2
WeakRef-obliviousness 是对对象或 symbol 的集合而不是单个值定义的,这是为了处理循环。如果它是对单个值定义的,那么处于循环中的某个 WeakRef referent 即使其身份仅通过该循环中的其他 WeakRef referent 才能被观察到,也会被认为是活的。
Note 3
通俗地说,如果每个包含某个单独对象或 symbol 的集合都是活的,那么我们就说这个对象或 symbol 是活的。

在求值期间的任意时刻,一个对象和/或 symbol 的集合 objectSet 被认为是活的,当且仅当满足以下任一条件:

  • objectSet 中的任一元素包含在任意 agent[[KeptAlive]] List 中。
  • 存在一个相对于 objectSet 的有效未来假想 WeakRef-oblivious 执行,并且该执行会观察到 objectSet 中某个值的身份。
Note 4
上述第二个条件意在表达这样一种直觉:如果某个值的身份可以通过非 WeakRef 的方式被观察到,那么该值就是活的。一个值的身份可以通过观察严格相等比较,或者观察该值被用作 Map 的键来观察到。
Note 5

对象或 symbol 出现在某个字段、内部槽或属性中,并不意味着该值就是活的。例如,如果相关值从未被返回给程序,那么它就无法被观察到。

WeakMap 中的键、WeakSet 的成员,以及 FinalizationRegistry Cell record 的 [[WeakRefTarget]][[UnregisterToken]] 字段,就属于这种情况。

上述定义意味着,如果 WeakMap 中的某个键不是活的,那么与之对应的值也不一定是活的。

Note 6
活性是保证哪些 WeakRef 引擎不得清空的下界。这里定义的活性是不可判定的。在实践中,引擎会使用诸如可达性之类的保守近似。预计实现会拥有相当大的自由度。

9.9.3 执行

在任意时刻,如果某个对象和/或 symbol 的集合 objectSet 不是活的,那么 ECMAScript 实现可以原子地执行以下步骤:

  1. objectSet 中的每个元素 value,执行
    1. 对于每个满足 ref.[[WeakRefTarget]]valueWeakRef ref,执行
      1. ref.[[WeakRefTarget]] 设为 empty
    2. 对于每个满足 fg.[[Cells]] 包含某个 Record cellcell.[[WeakRefTarget]]valueFinalizationRegistry fg,执行
      1. cell.[[WeakRefTarget]] 设为 empty
      2. 可选地,执行 HostEnqueueFinalizationRegistryCleanupJob(fg)。
    3. 对于每个满足 map.[[WeakMapData]] 包含某个 Record rr.[[Key]]value 的 WeakMap map,执行
      1. r.[[Key]] 设为 empty
      2. r.[[Value]] 设为 empty
    4. 对于每个满足 set.[[WeakSetData]] 包含 value 的 WeakSet set,执行
      1. set.[[WeakSetData]] 中值为 value 的那个元素替换为值为 empty 的元素。
Note 1

结合活性的定义,本条款规定了实现针对 WeakRef 可以应用的优化。

可以在不观察对象身份的情况下访问对象。诸如死变量消除,以及对那些身份未被观察到的、未逃逸对象属性进行标量替换之类的优化,都是允许的。因此,这些优化允许以可观察的方式清空指向这类对象的 WeakRef

另一方面,如果某个对象的身份是可观察的,并且该对象位于某个 WeakRef[[WeakRefTarget]] 内部槽中,那么像重新实化(rematerialization)这样会以可观察方式清空该 WeakRef 的优化就是被禁止的。

由于调用 HostEnqueueFinalizationRegistryCleanupJob 是可选的,因此注册在某个 FinalizationRegistry 中的对象不一定会使该 FinalizationRegistry 保持活性。实现可以出于任何原因省略 FinalizationRegistry 回调,例如,如果 FinalizationRegistry 本身已经死亡,或者应用程序正在关闭。

Note 2

实现没有义务为极大的非活对象或 symbol 集合清空 WeakRef

如果某个实现选择了一个非活集合 objectSet 来清空 WeakRef,那么本定义要求它同时为 objectSet 中所有值清空 WeakRef。换句话说,如果某实现清空了一个指向值 vWeakRef,却没有同时清空其他那些 WeakRef,而这些未清空的 WeakRef 可能导致某次执行观察到 v 的值,那么这种实现就是不符合规范的。

9.9.4 宿主钩子

9.9.4.1 HostEnqueueFinalizationRegistryCleanupJob ( finalizationRegistry )

The host-defined abstract operation HostEnqueueFinalizationRegistryCleanupJob takes argument finalizationRegistry (一个 FinalizationRegistry,) and returns unused.

cleanupJob 为一个新的无参数 Job Abstract Closure,它捕获 finalizationRegistry,并在被调用时执行以下步骤:

  1. cleanupResultCompletion(CleanupFinalizationRegistry(finalizationRegistry))。
  2. 如果 cleanupResult 是一个突兀完成,执行任何宿主定义的用于报告错误的步骤。
  3. 返回 unused

HostEnqueueFinalizationRegistryCleanupJob 的实现会在将来某个时间(如果可能)安排执行 cleanupJob。它还必须符合 9.5 中的要求。

9.10 ClearKeptObjects ( )

The abstract operation ClearKeptObjects takes no arguments and returns unused. 当一段同步的 ECMAScript 执行序列完成时,ECMAScript 实现预期会调用 ClearKeptObjects。 It performs the following steps when called:

  1. agentRecord外围 agentAgent Record
  2. agentRecord.[[KeptAlive]] 设为一个新的空 List
  3. 返回 unused

9.11 AddToKeptObjects ( value )

The abstract operation AddToKeptObjects takes argument value (一个 Object 或一个 Symbol,) and returns unused. It performs the following steps when called:

  1. agentRecord外围 agentAgent Record
  2. value 追加到 agentRecord.[[KeptAlive]]
  3. 返回 unused
Note
当以某个目标对象或 symbol 调用抽象操作 AddToKeptObjects 时,它会将该目标加入到一个列表中,在调用 ClearKeptObjects 之前,该列表会一直对该目标保持强引用。

9.12 CleanupFinalizationRegistry ( finalizationRegistry )

The abstract operation CleanupFinalizationRegistry takes argument finalizationRegistry (一个 FinalizationRegistry,) and returns 要么是包含 unused正常完成,要么是抛出完成. It performs the following steps when called:

  1. 断言:finalizationRegistry 具有 [[Cells]][[CleanupCallback]] 内部槽。
  2. callbackfinalizationRegistry.[[CleanupCallback]]
  3. finalizationRegistry.[[Cells]] 包含某个 Record cellcell.[[WeakRefTarget]]empty 时,实现可以执行以下步骤:
    1. 任选一个这样的 cell
    2. finalizationRegistry.[[Cells]] 中移除 cell
    3. 执行 ? HostCallJobCallback(callback, undefined, « cell.[[HeldValue]] »)。
  4. 返回 unused

9.13 CanBeHeldWeakly ( v )

The abstract operation CanBeHeldWeakly takes argument v (一个 ECMAScript 语言值,) and returns 一个 Boolean. 当且仅当 v 适合用作弱引用时,它返回 true。只有适合用作弱引用的值,才能作为 WeakMap 的键、WeakSet 的元素、WeakRef 的目标,或 FinalizationRegistry 的某个目标。 It performs the following steps when called:

  1. 如果 v 是一个 Object,返回 true
  2. 如果 v 是一个 Symbol,且 KeyForSymbol(v) 是 undefined,返回 true
  3. 返回 false
Note

没有语言身份的语言值可以在没有先前引用的情况下被显现,因此不适合作为弱引用。由 Symbol.for 产生的 Symbol 值,与其他 Symbol 值不同,它没有语言身份,因此不适合作为弱引用。众所周知的 symbol 很可能永远不会被回收,但它们仍被视为适合作为弱引用,因为它们数量有限,因此可由多种实现方式来管理。然而,在某个存活的 WeakMap 中,与一个众所周知的 symbol 关联的任何值都不太可能被回收,并且在实现中可能会“泄漏”内存资源。