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

9.1 环境记录

Environment Record 是一种规范类型,用于基于 ECMAScript 代码的词法嵌套结构,定义 Identifier 与特定变量和函数之间的关联。通常,一个 Environment Record 与 ECMAScript 代码的某个特定句法结构相关联,例如 FunctionDeclarationBlockStatementTryStatementCatch 子句。每当这类代码被求值时,都会创建一个新的 Environment Record,用于记录由该代码创建的标识符绑定。

每个 Environment Record 都有一个 [[OuterEnv]] 字段,它要么是 null,要么是对外层 Environment Record 的引用。这用于建模 Environment Record 值的逻辑嵌套。某个(内层)Environment Record 的外层引用,是对在逻辑上包围该内层 Environment Record 的 Environment Record 的引用。当然,一个外层 Environment Record 可以有自己的外层 Environment Record。一个 Environment Record 可以作为多个内层 Environment Records 的外层环境。例如,如果一个 FunctionDeclaration 包含两个嵌套的 FunctionDeclaration,则每个嵌套函数的 Environment Record 都会将包围函数当前求值的 Environment Record 作为其外层 Environment Record。

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

9.1.1 Environment Record 类型层级结构

Environment Records 可以被看作存在于一个简单的面向对象层级结构中,其中 Environment Record 是一个抽象类,具有三个具体子类:Declarative Environment RecordObject Environment RecordGlobal Environment RecordFunction Environment RecordsModule Environment RecordsDeclarative Environment Record 的子类。

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

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

The abstract method HasBinding takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion.

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

The abstract method CreateMutableBinding takes arguments name (a String) and deletable (a Boolean) and returns either a normal completion containing unused or a throw completion.

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

The abstract method CreateImmutableBinding takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing unused or a throw completion.

它在 Environment Record 中创建一个新的、但未初始化的不可变绑定。name 是被绑定名称的文本。如果 stricttrue,则在它已被初始化之后尝试设置它时,总是会抛出异常,而不管引用该绑定的操作的严格模式设置如何。
它在以下类型中有具体定义:
InitializeBinding ( name, value )

The abstract method InitializeBinding takes arguments name (a String) and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion.

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

The abstract method SetMutableBinding takes arguments name (a String), value (an ECMAScript language value), and strict (a Boolean) and returns either a normal completion containing unused or a throw completion.

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

The abstract method GetBindingValue takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion.

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

The abstract method DeleteBinding takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion.

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

The abstract method HasThisBinding takes no arguments and returns a Boolean.

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

The abstract method GetThisBinding takes no arguments and returns either a normal completion containing an ECMAScript language value or a throw completion.

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

The abstract method HasSuperBinding takes no arguments and returns a Boolean.

它确定 Environment Record 是否建立 super 方法绑定。如果它建立了则返回 true,否则返回 false。如果它返回 true,则意味着该 Environment RecordFunction Environment Record,尽管反向蕴含并不成立。
它在以下类型中有具体定义:
WithBaseObject ( )

The abstract method WithBaseObject takes no arguments and returns an Object or undefined.

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

9.1.1.1 声明式环境记录

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

每个声明式环境记录也都有一个 [[DisposableResourceStack]] 字段,其中包含一个 DisposableResource 记录的列表。此列表中的元素由 using 声明和 await using 声明跟踪,并且必须在构造该环境记录的求值步骤完成时被处置。

9.1.1.1.1 HasBinding ( name )

The HasBinding concrete method of a Declarative Environment Record envRecord takes argument name (a String) and returns a normal completion containing a Boolean. 它确定实参标识符是否为该记录所绑定的标识符之一。 It performs the following steps when called:

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

9.1.1.1.2 CreateMutableBinding ( name, deletable )

The CreateMutableBinding concrete method of a Declarative Environment Record envRecord takes arguments name (a String) and deletable (a Boolean) and returns a normal completion containing unused. 它为名称 name 创建一个新的、未初始化的可变绑定。此 Environment Record 中必须尚不存在 name 的绑定。如果 deletabletrue,则新绑定会被标记为可被删除。 It performs the following steps when called:

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

9.1.1.1.3 CreateImmutableBinding ( name, strict )

The CreateImmutableBinding concrete method of a Declarative Environment Record envRecord takes arguments name (a String) and strict (a Boolean) and returns a normal completion containing unused. 它为名称 name 创建一个新的、未初始化的不可变绑定。此 Environment Record 中必须尚不存在 name 的绑定。如果 stricttrue,则新绑定会被标记为严格绑定。 It performs the following steps when called:

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

9.1.1.1.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of a Declarative Environment Record envRecord takes arguments name (a String) and value (an ECMAScript language value) and returns a normal completion containing unused. 它用于将名称为 name 的标识符的当前绑定的绑定值设置为值 valuename 的未初始化绑定必须已经存在。 It performs the following steps when called:

  1. 断言:envRecord 必须具有 name 的未初始化绑定。
  2. envRecordname 的绑定值设置为 value
  3. 记录 envRecordname 的绑定已经被初始化。
  4. 返回 unused

9.1.1.1.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of a Declarative Environment Record envRecord takes arguments name (a String), value (an ECMAScript language value), and strict (a Boolean) and returns either a normal completion containing unused or a throw completion. 它尝试将名称为 name 的标识符的当前绑定的绑定值更改为值 valuename 的绑定通常已经存在,但在少数情况下可能不存在。如果该绑定是不可变绑定,且 stricttrue,则会抛出 TypeError。 It performs the following steps when called:

  1. 如果 envRecord 不具有 name 的绑定,则
    1. 如果 stricttrue,则抛出 ReferenceError 异常。
    2. 执行 ! envRecord.CreateMutableBinding(name, true)。
    3. 执行 ! envRecord.InitializeBinding(name, value)。
    4. 返回 unused
  2. 如果 envRecordname 的绑定是严格绑定,则将 strict 设置为 true
  3. 如果 envRecordname 的绑定尚未被初始化,则
    1. 抛出 ReferenceError 异常。
  4. 否则如果 envRecordname 的绑定是可变绑定,则
    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 envRecord takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它返回其名称为 name 的已绑定标识符的值。如果该绑定存在但未初始化,则会抛出 ReferenceError,而不管 strict 的值如何。 It performs the following steps when called:

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

9.1.1.1.7 DeleteBinding ( name )

The DeleteBinding concrete method of a Declarative Environment Record envRecord takes argument name (a String) and returns a normal completion containing a Boolean. 它只能删除那些已被显式指定为可被删除的绑定。 It performs the following steps when called:

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

9.1.1.1.8 HasThisBinding ( )

The HasThisBinding concrete method of a Declarative Environment Record envRecord 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 envRecord 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 envRecord 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 绑定一组字符串标识符名称,这些名称直接对应于其绑定对象的属性名称。不是 IdentifierName 形式字符串的属性键包含在被绑定标识符集合中。自有属性和继承属性都包含在该集合中,而不管其 [[Enumerable]] 特性的设置如何。由于属性可以动态地添加到对象并从对象中删除,因此 Object Environment Record 所绑定的标识符集合可能会作为添加或删除属性的任何操作的副作用而发生改变。作为这类副作用结果创建的任何绑定都被认为是可变绑定,即使对应属性的 Writable 特性是 false。Object Environment Records 不存在不可变绑定。

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

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

Table 16: Object Environment Records 的附加字段
字段名 含义
[[BindingObject]] an Object Environment Record 的绑定对象。
[[IsWithEnvironment]] a Boolean 指示此 Environment Record 是否为 with 语句创建。

9.1.1.2.1 HasBinding ( name )

The HasBinding concrete method of an Object Environment Record envRecord takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它确定其关联的绑定对象是否具有名称为 name 的属性。 It performs the following steps when called:

  1. bindingObjenvRecord.[[BindingObject]]
  2. foundBinding 为 ? HasProperty(bindingObj, name)。
  3. 如果 foundBindingfalse,则返回 false
  4. 如果 envRecord.[[IsWithEnvironment]]false,则返回 true
  5. unscopables 为 ? Get(bindingObj, %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 an Object Environment Record envRecord takes arguments name (a String) and deletable (a Boolean) and returns either a normal completion containing unused or a throw completion. 它在 Environment Record 的关联绑定对象中创建一个名称为 name 的属性,并将其初始化为值 undefined。如果 deletabletrue,则新属性的 [[Configurable]] 特性被设置为 true;否则被设置为 false。 It performs the following steps when called:

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

通常 envRecord 不会具有 name 的绑定,但如果它确实具有,则 DefinePropertyOrThrow 的语义可能导致现有绑定被替换或遮蔽,或导致返回一个 abrupt completion。

9.1.1.2.3 CreateImmutableBinding ( name, strict )

Object Environment RecordCreateImmutableBinding 具体方法在本规范中从未被使用。

9.1.1.2.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of an Object Environment Record envRecord takes arguments name (a String) and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. 它用于将名称为 name 的标识符的当前绑定的绑定值设置为值 value。 It performs the following steps when called:

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

在本规范中,Object Environment RecordsCreateMutableBinding 的所有使用后面都会立即跟随对相同名称调用 InitializeBinding。因此,本规范不会显式跟踪 Object Environment Records 中绑定的初始化状态。

9.1.1.2.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of an Object Environment Record envRecord takes arguments name (a String), value (an ECMAScript language value), and strict (a Boolean) and returns either a normal completion containing unused or a throw completion. 它尝试将该 Environment Record 的关联绑定对象中名称为 name 的属性的值设置为值 value。名为 name 的属性通常已经存在,但如果它不存在或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

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

9.1.1.2.6 GetBindingValue ( name, strict )

The GetBindingValue concrete method of an Object Environment Record envRecord takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它返回其关联绑定对象中名称为 name 的属性的值。该属性应当已经存在,但如果它不存在,结果取决于 strict。 It performs the following steps when called:

  1. bindingObjenvRecord.[[BindingObject]]
  2. value 为 ? HasProperty(bindingObj, name)。
  3. 如果 valuefalse,则
    1. 如果 strictfalse,则返回 undefined
    2. 抛出 ReferenceError 异常。
  4. 返回 ? Get(bindingObj, name)。

9.1.1.2.7 DeleteBinding ( name )

The DeleteBinding concrete method of an Object Environment Record envRecord takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它只能删除对应于环境对象属性且其 [[Configurable]] 特性值为 true 的绑定。 It performs the following steps when called:

  1. bindingObjenvRecord.[[BindingObject]]
  2. 返回 ? bindingObj.[[Delete]](name)

9.1.1.2.8 HasThisBinding ( )

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

  1. 返回 false
Note

Object Environment Records 不提供 this 绑定。

9.1.1.2.9 GetThisBinding ( )

Object Environment RecordGetThisBinding 具体方法在本规范中从未被使用。

9.1.1.2.10 HasSuperBinding ( )

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

  1. 返回 false
Note

Object Environment Records 不提供 super 绑定。

9.1.1.2.11 WithBaseObject ( )

The WithBaseObject concrete method of an Object Environment Record envRecord takes no arguments and returns an Object or undefined. It performs the following steps when called:

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

9.1.1.3 函数环境记录

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

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

Table 17: Function Environment Records 的附加字段
字段名 含义
[[ThisValue]] an ECMAScript language value 这是此函数调用所使用的 this 值。
[[ThisBindingStatus]] lexical, initialized, or uninitialized 如果值是 lexical,则这是一个 ArrowFunctionAsyncArrowFunction,并且没有本地 this 值。
[[FunctionObject]] an ECMAScript function object 其调用导致此 Environment Record 被创建的函数对象
[[NewTarget]] a constructor or undefined 如果此 Environment Record[[Construct]] 内部方法创建,则 [[NewTarget]][[Construct]]newTarget 形参的值。否则,其值为 undefined

Function Environment Records 支持 Table 15 中列出的所有 Declarative Environment Record 方法,并且除 HasThisBindingGetThisBindingHasSuperBinding 之外,所有这些方法都共享相同的规范。

9.1.1.3.1 BindThisValue ( envRecord, value )

The abstract operation BindThisValue takes arguments envRecord (a Function Environment Record) and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. 它设置 envRecord.[[ThisValue]],并记录其已被初始化。 It performs the following steps when called:

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

9.1.1.3.2 HasThisBinding ( )

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

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

9.1.1.3.3 GetThisBinding ( )

The GetThisBinding concrete method of a Function Environment Record envRecord takes no arguments and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

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

9.1.1.3.4 HasSuperBinding ( )

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

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

9.1.1.3.5 GetSuperBase ( envRecord )

The abstract operation GetSuperBase takes argument envRecord (a Function Environment Record) and returns an Object, null, or undefined. 它返回在 envRecord 中绑定的 super 属性访问的基对象。值 undefined 表示这类访问会产生运行时错误。 It performs the following steps when called:

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

9.1.1.4 全局环境记录

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

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 Records 具有 Table 18 中列出的附加字段。

Table 18: Global Environment Records 的附加字段
字段名 含义
[[ObjectRecord]] an Object Environment Record 绑定对象是全局对象。它包含内置全局绑定,以及关联 realm 的全局代码中的 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableDeclaration 绑定。
[[GlobalThisValue]] an Object 在全局作用域中由 this 返回的值。宿主可以提供任何 ECMAScript Object 值。
[[DeclarativeRecord]] a Declarative Environment Record 包含关联 realm 代码的全局代码中所有声明的绑定,但 FunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclarationVariableDeclaration 绑定除外。

9.1.1.4.1 HasBinding ( name )

The HasBinding concrete method of a Global Environment Record envRecord takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它确定实参标识符是否为该记录所绑定的标识符之一。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则返回 true
  3. objRecordenvRecord.[[ObjectRecord]]
  4. 返回 ? objRecord.HasBinding(name)

9.1.1.4.2 CreateMutableBinding ( name, deletable )

The CreateMutableBinding concrete method of a Global Environment Record envRecord takes arguments name (a String) and deletable (a Boolean) and returns either a normal completion containing unused or a throw completion. 它为名称 name 创建一个新的、未初始化的可变绑定。该绑定创建于关联的 DeclarativeRecord 中。DeclarativeRecord 中必须尚不存在 name 的绑定。如果 deletabletrue,则新绑定会被标记为可被删除。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则抛出 TypeError 异常。
  3. 返回 ! declRecord.CreateMutableBinding(name, deletable)。

9.1.1.4.3 CreateImmutableBinding ( name, strict )

The CreateImmutableBinding concrete method of a Global Environment Record envRecord takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing unused or a throw completion. 它为名称 name 创建一个新的、未初始化的不可变绑定。此 Environment Record 中必须尚不存在 name 的绑定。如果 stricttrue,则新绑定会被标记为严格绑定。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则抛出 TypeError 异常。
  3. 返回 ! declRecord.CreateImmutableBinding(name, strict)。

9.1.1.4.4 InitializeBinding ( name, value )

The InitializeBinding concrete method of a Global Environment Record envRecord takes arguments name (a String) and value (an ECMAScript language value) and returns either a normal completion containing unused or a throw completion. 它用于将名称为 name 的标识符的当前绑定的绑定值设置为值 valuename 的未初始化绑定必须已经存在。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ! declRecord.InitializeBinding(name, value)。
  3. 断言:如果绑定存在,它必须在 Object Environment Record 中。
  4. objRecordenvRecord.[[ObjectRecord]]
  5. 返回 ? objRecord.InitializeBinding(name, value)

9.1.1.4.5 SetMutableBinding ( name, value, strict )

The SetMutableBinding concrete method of a Global Environment Record envRecord takes arguments name (a String), value (an ECMAScript language value), and strict (a Boolean) and returns either a normal completion containing unused or a throw completion. 它尝试将名称为 name 的标识符的当前绑定的绑定值更改为值 value。如果该绑定是不可变绑定且 stricttrue,则会抛出 TypeError。名为 name 的绑定通常已经存在,但如果它不存在或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ? declRecord.SetMutableBinding(name, value, strict)。
  3. objRecordenvRecord.[[ObjectRecord]]
  4. 返回 ? objRecord.SetMutableBinding(name, value, strict)

9.1.1.4.6 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Global Environment Record envRecord takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它返回其名称为 name 的已绑定标识符的值。如果该绑定是未初始化绑定,则会抛出 ReferenceError 异常。名为 name 的绑定通常已经存在,但如果它不存在或当前不可写,则错误处理由 strict 决定。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ? declRecord.GetBindingValue(name, strict)。
  3. objRecordenvRecord.[[ObjectRecord]]
  4. 返回 ? objRecord.GetBindingValue(name, strict)

9.1.1.4.7 DeleteBinding ( name )

The DeleteBinding concrete method of a Global Environment Record envRecord takes argument name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它只能删除那些已被显式指定为可被删除的绑定。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 如果 ! declRecord.HasBinding(name) 是 true,则
    1. 返回 ! declRecord.DeleteBinding(name)。
  3. objRecordenvRecord.[[ObjectRecord]]
  4. globalObjobjRecord.[[BindingObject]]
  5. existingProperty 为 ? HasOwnProperty(globalObj, name)。
  6. 如果 existingPropertytrue,则
    1. 返回 ? objRecord.DeleteBinding(name)
  7. 返回 true

9.1.1.4.8 HasThisBinding ( )

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

  1. 返回 true
Note

Global Environment Records 总是提供 this 绑定。

9.1.1.4.9 GetThisBinding ( )

The GetThisBinding concrete method of a Global Environment Record envRecord takes no arguments and returns a normal completion containing an Object. It performs the following steps when called:

  1. 返回 envRecord.[[GlobalThisValue]]

9.1.1.4.10 HasSuperBinding ( )

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

  1. 返回 false
Note

Global Environment Records 不提供 super 绑定。

9.1.1.4.11 WithBaseObject ( )

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

  1. 返回 undefined

9.1.1.4.12 HasLexicalDeclaration ( envRecord, name )

The abstract operation HasLexicalDeclaration takes arguments envRecord (a Global Environment Record) and name (a String) and returns a Boolean. 它确定实参标识符是否在 envRecord 中具有通过词法声明(例如 LexicalDeclarationClassDeclaration)创建的绑定。 It performs the following steps when called:

  1. declRecordenvRecord.[[DeclarativeRecord]]
  2. 返回 ! declRecord.HasBinding(name)。

9.1.1.4.13 HasRestrictedGlobalProperty ( envRecord, name )

The abstract operation HasRestrictedGlobalProperty takes arguments envRecord (a Global Environment Record) and name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它确定实参标识符是否为全局对象的某个属性的名称,而该属性不得被全局词法绑定遮蔽。 It performs the following steps when called:

  1. objRecordenvRecord.[[ObjectRecord]]
  2. globalObjobjRecord.[[BindingObject]]
  3. existingProperty 为 ? globalObj.[[GetOwnProperty]](name)
  4. 如果 existingPropertyundefined,则返回 false
  5. 如果 existingProperty.[[Configurable]]true,则返回 false
  6. 返回 true
Note

全局对象上可能存在直接创建而不是使用 var 或 function 声明声明的属性。不得创建与全局对象的不可配置属性具有相同名称的全局词法绑定。全局属性 "undefined" 是这类属性的一个例子。

9.1.1.4.14 CanDeclareGlobalVar ( envRecord, name )

The abstract operation CanDeclareGlobalVar takes arguments envRecord (a Global Environment Record) and name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它确定如果使用相同实参 name 调用对应的 CreateGlobalVarBinding 调用是否会成功。允许冗余的 var 声明和针对预先存在的全局对象属性的 var 声明。 It performs the following steps when called:

  1. objRecordenvRecord.[[ObjectRecord]]
  2. globalObjobjRecord.[[BindingObject]]
  3. hasProperty 为 ? HasOwnProperty(globalObj, name)。
  4. 如果 hasPropertytrue,则返回 true
  5. 返回 ? IsExtensible(globalObj)。

9.1.1.4.15 CanDeclareGlobalFunction ( envRecord, name )

The abstract operation CanDeclareGlobalFunction takes arguments envRecord (a Global Environment Record) and name (a String) and returns either a normal completion containing a Boolean or a throw completion. 它确定如果使用相同实参 name 调用对应的 CreateGlobalFunctionBinding 调用是否会成功。 It performs the following steps when called:

  1. objRecordenvRecord.[[ObjectRecord]]
  2. globalObjobjRecord.[[BindingObject]]
  3. existingProperty 为 ? globalObj.[[GetOwnProperty]](name)
  4. 如果 existingPropertyundefined,则返回 ? IsExtensible(globalObj)。
  5. 如果 existingProperty.[[Configurable]]true,则返回 true
  6. 如果 IsDataDescriptor(existingProperty) 是 trueexistingProperty 具有特性值 { [[Writable]]: true, [[Enumerable]]: true },则返回 true
  7. 返回 false

9.1.1.4.16 CreateGlobalVarBinding ( envRecord, name, deletable )

The abstract operation CreateGlobalVarBinding takes arguments envRecord (a Global Environment Record), name (a String), and deletable (a Boolean) and returns either a normal completion containing unused or a throw completion. 它在关联的 Object Environment Record 中创建并初始化一个可变绑定。如果绑定已经存在,则重用它,并假定它已被初始化。 It performs the following steps when called:

  1. objRecordenvRecord.[[ObjectRecord]]
  2. globalObjobjRecord.[[BindingObject]]
  3. hasProperty 为 ? HasOwnProperty(globalObj, name)。
  4. extensible 为 ? IsExtensible(globalObj)。
  5. 如果 hasPropertyfalseextensibletrue,则
    1. 执行 ? objRecord.CreateMutableBinding(name, deletable)
    2. 执行 ? objRecord.InitializeBinding(name, undefined)
  6. 返回 unused

9.1.1.4.17 CreateGlobalFunctionBinding ( envRecord, name, value, deletable )

The abstract operation CreateGlobalFunctionBinding takes arguments envRecord (a Global Environment Record), name (a String), value (an ECMAScript function object), and deletable (a Boolean) and returns either a normal completion containing unused or a throw completion. 它在关联的 Object Environment Record 中创建并初始化一个可变绑定。如果绑定已经存在,则替换它。 It performs the following steps when called:

  1. objRecordenvRecord.[[ObjectRecord]]
  2. globalObjobjRecord.[[BindingObject]]
  3. existingProperty 为 ? globalObj.[[GetOwnProperty]](name)
  4. 如果 existingPropertyundefinedexistingProperty.[[Configurable]]true,则
    1. propertyDesc 为 PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: deletable }。
  5. 否则,
    1. propertyDesc 为 PropertyDescriptor { [[Value]]: value }。
  6. 执行 ? DefinePropertyOrThrow(globalObj, name, propertyDesc)。
  7. 执行 ? Set(globalObj, name, value, false)。
  8. 返回 unused
Note

全局函数声明总是表示为全局对象的自有属性。如果可能,现有自有属性会被重新配置为具有一组标准特性值。步骤 7 等价于调用 InitializeBinding 具体方法所做的事情,并且如果 globalObj 是 Proxy,将产生相同的 Proxy 陷阱调用序列。

9.1.1.5 模块环境记录

Module Environment Record 是一种 Declarative Environment Record,用于表示 ECMAScript Module 的外层作用域。除了正常的可变绑定和不可变绑定之外,Module Environment Records 还提供不可变导入绑定,即提供对存在于另一个 Environment Record 中的目标绑定的间接访问的绑定。

Module Environment Records 支持 Table 15 中列出的所有 Declarative Environment Record 方法,并且除 GetBindingValueDeleteBindingHasThisBindingGetThisBinding 之外,所有这些方法都共享相同的规范。

9.1.1.5.1 GetBindingValue ( name, strict )

The GetBindingValue concrete method of a Module Environment Record envRecord takes arguments name (a String) and strict (a Boolean) and returns either a normal completion containing an ECMAScript language value or a throw completion. 它返回其名称为 name 的已绑定标识符的值。不过,如果该绑定是间接绑定,则返回目标绑定的值。如果该绑定存在但未初始化,则会抛出 ReferenceError。 It performs the following steps when called:

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

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

9.1.1.5.2 DeleteBinding ( name )

Module Environment RecordDeleteBinding 具体方法在本规范中从未被使用。

Note

Module Environment Records 仅在严格代码中使用,并且早期错误规则会阻止在严格代码中将 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 envRecord takes no arguments and returns true. It performs the following steps when called:

  1. 返回 true
Note

Module Environment Records 总是提供 this 绑定。

9.1.1.5.4 GetThisBinding ( )

The GetThisBinding concrete method of a Module Environment Record envRecord takes no arguments and returns a normal completion containing undefined. It performs the following steps when called:

  1. 返回 undefined

9.1.1.5.5 CreateImportBinding ( envRecord, name, targetModule, targetName )

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

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

9.1.2 Environment Record 操作

以下抽象操作在本规范中用于对 Environment Records 进行操作:

9.1.2.1 GetIdentifierReference ( envRecord, name, strict )

The abstract operation GetIdentifierReference takes arguments envRecord (an Environment Record or null), name (a String), and strict (a Boolean) and returns either a normal completion containing a Reference Record or a throw completion. It performs the following steps when called:

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

9.1.2.2 NewDeclarativeEnvironment ( outerEnv )

The abstract operation NewDeclarativeEnvironment takes argument outerEnv (an Environment Record or null) and returns a Declarative Environment Record. It performs the following steps when called:

  1. envRecord 为一个不包含任何绑定的新声明式环境记录。
  2. envRecord.[[OuterEnv]] 设置为 outerEnv
  3. envRecord.[[DisposableResourceStack]] 设置为一个新的空列表。
  4. 返回 envRecord

9.1.2.3 NewObjectEnvironment ( obj, isWithEnv, outerEnv )

The abstract operation NewObjectEnvironment takes arguments obj (an Object), isWithEnv (a Boolean), and outerEnv (an Environment Record or null) and returns an Object Environment Record. It performs the following steps when called:

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

9.1.2.4 NewFunctionEnvironment ( func, newTarget )

The abstract operation NewFunctionEnvironment takes arguments func (an ECMAScript function object) and newTarget (an Object or undefined) and returns a Function Environment Record. It performs the following steps when called:

  1. envRecord 为一个不包含任何绑定的新函数环境记录。
  2. envRecord.[[FunctionObject]] 设置为 func
  3. 如果 func.[[ThisMode]]lexical,则将 envRecord.[[ThisBindingStatus]] 设置为 lexical
  4. 否则,将 envRecord.[[ThisBindingStatus]] 设置为 uninitialized
  5. envRecord.[[NewTarget]] 设置为 newTarget
  6. envRecord.[[OuterEnv]] 设置为 func.[[Environment]]
  7. envRecord.[[DisposableResourceStack]] 设置为一个新的空列表。
  8. 返回 envRecord

9.1.2.5 NewGlobalEnvironment ( obj, thisValue )

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

  1. objRecordNewObjectEnvironment(obj, false, null)。
  2. declRecordNewDeclarativeEnvironment(null)。
  3. envRecord 为一个新的 Global Environment Record
  4. envRecord.[[ObjectRecord]] 设置为 objRecord
  5. envRecord.[[GlobalThisValue]] 设置为 thisValue
  6. envRecord.[[DeclarativeRecord]] 设置为 declRecord
  7. envRecord.[[OuterEnv]] 设置为 null
  8. 返回 envRecord

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. envRecord 为一个不包含任何绑定的新模块环境记录。
  2. envRecord.[[OuterEnv]] 设置为 outerEnv
  3. envRecord.[[DisposableResourceStack]] 设置为一个新的空列表。
  4. 返回 envRecord

9.2 PrivateEnvironment Records

PrivateEnvironment Record 是一种规范机制,用于基于 ECMAScript 代码中 ClassDeclarationClassExpression 的词法嵌套结构来跟踪 Private Names。它们类似于 Environment Records,但又与其不同。每个 PrivateEnvironment Record 都与一个 ClassDeclarationClassExpression 相关联。每当这样的类被求值时,都会创建一个新的 PrivateEnvironment Record,用于记录由该类声明的 Private Names

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

Table 19: PrivateEnvironment Record 字段
字段名 值类型 含义
[[OuterPrivateEnvironment]] a PrivateEnvironment Record or null 最近的包含类的 PrivateEnvironment Record。如果与此 PrivateEnvironment Record 关联的类不包含在任何其他类中,则为 null
[[Names]] a List of Private Names 此类声明的 Private Names

9.2.1 PrivateEnvironment Record 操作

以下抽象操作在本规范中用于对 PrivateEnvironment Records 进行操作:

9.2.1.1 NewPrivateEnvironment ( outerPrivateEnv )

The abstract operation NewPrivateEnvironment takes argument outerPrivateEnv (a PrivateEnvironment Record or null) and returns a 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 (a PrivateEnvironment Record) and identifier (a String) and returns a Private Name. It performs the following steps when called:

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

9.3 Realms

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

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

Table 20: Realm Record 字段
字段名 含义
[[AgentSignifier]] an agent signifier 拥有此 realmagent
[[Intrinsics]] a Record whose field names are intrinsic keys and whose values are objects 与此 realm 关联的代码所使用的固有值
[[GlobalObject]] an Object realm全局对象
[[GlobalEnv]] a Global Environment Record realm 的全局环境
[[TemplateMap]] a List of Records with fields [[Site]] (a TemplateLiteral Parse Node) and [[Array]] (an Array)

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

Note 1
一旦某个 Parse Node 变得不可达,对应的 [[Array]] 也不可达,并且如果实现从 [[TemplateMap]] 列表中移除这一对,将是不可观察的。
[[LoadedModules]] a List of LoadedModuleRequest Records

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

Note 2
HostLoadImportedModule16.2.1.10 Note 1)中所述,Realm Records 中的 [[LoadedModules]] 仅在没有活动脚本或模块的上下文中运行 import() 表达式时使用。
[[HostDefined]] anything (default value is undefined) 保留给需要将额外信息与 Realm Record 关联的宿主使用的字段。

9.3.1 InitializeHostDefinedRealm ( )

The abstract operation InitializeHostDefinedRealm takes no arguments and returns either a normal completion containing unused or a throw completion. 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 ( realmRecord )

The abstract operation CreateIntrinsics takes argument realmRecord (a Realm Record) and returns unused. It performs the following steps when called:

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

9.3.3 SetDefaultGlobalBindings ( realmRecord )

The abstract operation SetDefaultGlobalBindings takes argument realmRecord (a Realm Record) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. globalrealmRecord.[[GlobalObject]]
  2. 对条款 19 中指定的 Global Object 的每个属性,执行:
    1. name 为该属性名的 String 值。
    2. propertyDesc 为该属性的完全填充的数据 Property Descriptor,其中包含该属性的指定特性。对于 19.219.319.4 中列出的属性,[[Value]] 特性的值是来自 realmRecord 的对应固有对象。
    3. 执行 ? DefinePropertyOrThrow(global, name, propertyDesc)。
  3. 返回 unused

9.4 执行上下文

execution context 是一种规范装置,ECMAScript 实现使用它跟踪代码的运行时求值。在任意时刻,每个 agent 至多有一个实际正在执行代码的执行上下文。这被称为该 agentrunning execution context。本规范中对运行中执行上下文的所有引用,都指周围 agent 的运行中执行上下文。

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

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

Table 21: 所有执行上下文的状态组件
组件 目的
code evaluation state 执行、暂停和恢复与此执行上下文关联的代码求值所需的任何状态。
Function 如果此执行上下文正在求值一个函数对象的代码,则此组件的值就是该函数对象。如果该上下文正在求值 ScriptModule 的代码,则该值为 null
Realm 关联代码访问 ECMAScript 资源所来自的 Realm Record
ScriptOrModule 关联代码所源自的 Module RecordScript Record。如果没有起源脚本或模块,例如在 InitializeHostDefinedRealm 中创建的原始执行上下文的情形,则该值为 null

运行中执行上下文对代码的求值,可以在本规范中定义的各个点被暂停。一旦运行中执行上下文被暂停,另一个不同的执行上下文就可以成为运行中执行上下文并开始求值其代码。在之后的某个时间,被暂停的执行上下文可以再次成为运行中执行上下文,并在它此前被暂停的位置继续求值其代码。运行中执行上下文状态在执行上下文之间的转移通常以类似栈的后进先出方式发生。然而,某些 ECMAScript 特性需要运行中执行上下文的非 LIFO 转移。

运行中执行上下文的 Realm 组件的值也称为 当前 Realm Record。运行中执行上下文的 Function 组件的值也称为 活动函数对象

ECMAScript 代码执行上下文具有 Table 22 中列出的附加状态组件。

Table 22: ECMAScript 代码执行上下文的附加状态组件
组件 目的
LexicalEnvironment 标识用于解析此执行上下文内代码所产生的标识符引用的 Environment Record
VariableEnvironment 标识保存此执行上下文内由 VariableStatement 创建的绑定的 Environment Record
PrivateEnvironment 标识保存最近包含类中的 ClassElement 创建的 Private NamesPrivateEnvironment Record。如果没有包含类,则为 null

执行上下文的 LexicalEnvironment 和 VariableEnvironment 组件始终是 Environment Records

表示 Generators 求值的执行上下文具有 Table 23 中列出的附加状态组件。

Table 23: Generator 执行上下文的附加状态组件
组件 目的
Generator 此执行上下文正在求值的 Generator。

在大多数情况下,本规范中的算法只直接操纵运行中执行上下文(执行上下文栈的顶端)。因此,当术语 “LexicalEnvironment” 和 “VariableEnvironment” 未加限定地使用时,它们指的是运行中执行上下文的这些组件。

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

9.4.1 GetActiveScriptOrModule ( )

The abstract operation GetActiveScriptOrModule takes no arguments and returns a Script Record, a Module Record, or null. 它用于基于运行中执行上下文来确定运行中的脚本或模块。 It performs the following steps when called:

  1. 如果执行上下文栈为空,则返回 null
  2. executionContext 为执行上下文栈中 ScriptOrModule 组件不是 null 的最顶层执行上下文。
  3. 如果不存在这样的执行上下文,则返回 null
  4. 返回 executionContext 的 ScriptOrModule。

9.4.2 ResolveBinding ( name [ , envRecord ] )

The abstract operation ResolveBinding takes argument name (a String) and optional argument envRecord (an Environment Record or undefined) and returns either a normal completion containing a Reference Record or a throw completion. 它用于确定 name 的绑定。envRecord 可用于显式提供要搜索该绑定的 Environment Record。 It performs the following steps when called:

  1. 如果 envRecord 不存在或 envRecordundefined,则
    1. envRecord 设置为运行中执行上下文的 LexicalEnvironment。
  2. 断言:envRecordEnvironment Record
  3. strictIsStrict(正在求值的句法产生式)。
  4. 返回 ? GetIdentifierReference(envRecord, name, strict)。
Note

ResolveBinding 的结果始终是 [[ReferencedName]] 字段为 nameReference Record

9.4.3 GetThisEnvironment ( )

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

  1. envRecord 为运行中执行上下文的 LexicalEnvironment。
  2. 重复,
    1. existsenvRecord.HasThisBinding()。
    2. 如果 existstrue,则返回 envRecord
    3. outerenvRecord.[[OuterEnv]]
    4. 断言:outer 不是 null
    5. envRecord 设置为 outer
Note

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

9.4.4 ResolveThisBinding ( )

The abstract operation ResolveThisBinding takes no arguments and returns either a normal completion containing an ECMAScript language value or a throw completion. 它使用运行中执行上下文的 LexicalEnvironment 确定关键字 this 的绑定。 It performs the following steps when called:

  1. envRecordGetThisEnvironment()。
  2. 返回 ? envRecord.GetThisBinding()。

9.4.5 GetNewTarget ( )

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

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

9.4.6 GetGlobalObject ( )

The abstract operation GetGlobalObject takes no arguments and returns an 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 (an execution context) and completionRecord (a Completion Record) and returns either a normal completion containing either an ECMAScript language value or unused, or an abrupt completion. 它恢复 context(将 completionRecord 作为恢复值发送给它),并等待结果。 It performs the following steps when called:

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

9.4.8 RunCallerContext ( value )

The abstract operation RunCallerContext takes argument value (一个 ECMAScript 语言值empty) and returns 一个完成记录. 它恢复调用方上下文(将 value 作为恢复值发送给它),并等待结果(如果有)。 It performs the following steps when called:

  1. genContext 为运行中的执行上下文。
  2. 从执行上下文栈中移除 genContext,并将位于执行上下文栈顶部的执行上下文恢复为运行中的执行上下文。
  3. callerContext 为运行中的执行上下文。
  4. 恢复 callerContext,传入 NormalCompletion(value)。
  5. 注:上述步骤将控制转移给 callerContext 并暂停。使其解除暂停并让控制继续到此算法后续步骤的唯一方式,是再次恢复 genContext,而这可能永远不会发生。
  6. 断言:genContext 是运行中的执行上下文。
  7. resultgenContext 刚刚被恢复时所用的完成记录。
  8. 返回 Completion(result)。

9.5 作业和用于将作业入队的宿主操作

Job 是一个不带形参的 Abstract Closure,它在当前没有其他 ECMAScript 计算正在进行时发起一个 ECMAScript 计算。

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

  • 在将来的某个时间点,当为该 job 调度的 agent 中没有运行中上下文且该 agent 的执行上下文栈为空时,实现必须:
    1. 执行任何宿主定义的准备步骤。
    2. 调用Job Abstract Closure
    3. 执行任何宿主定义的清理步骤,之后执行上下文栈必须为空。
  • 在任意时间点,一个 agent 中只能有一个 Job 正在主动经历求值。
  • 一旦某个 Job 的求值开始,它必须运行至完成,然后一个 agent 中的任何其他 Job 才能开始求值。
  • Abstract Closure 必须返回 normal completion,并实现其自身的错误处理。
Note 1
宿主环境不要求在调度方面统一对待 Jobs。例如,Web 浏览器和 Node.js 将处理 Promise 的 Jobs 视为比其他工作具有更高优先级;未来特性可能添加不按如此高优先级处理的 Jobs

在任意特定时间,如果以下所有条件均为真,则 scriptOrModuleScript RecordModule Recordnull)是活动脚本或模块

  • GetActiveScriptOrModule() 是 scriptOrModule
  • 如果 scriptOrModuleScript RecordModule Record,则令 executionContext 为执行上下文栈中 ScriptOrModule 组件为 scriptOrModule 的最顶层执行上下文。executionContextRealm 组件是 scriptOrModule.[[Realm]]

在任意特定时间,如果以下所有条件均为真,则某次执行已准备好求值 ECMAScript 代码

  • 执行上下文栈不为空。
  • 执行上下文栈最顶层执行上下文的 Realm 组件是 Realm Record
Note 2

宿主环境可以通过将执行上下文压入执行上下文栈来准备一次执行以求值代码。具体步骤是实现定义的

Realm 的具体选择取决于宿主环境。此初始执行上下文和 Realm 仅在调用任何回调函数之前使用。当调用与 Job 相关的回调函数(例如 Promise handler)时,该调用会压入其自己的执行上下文和 Realm

特定种类的 Jobs 具有附加的一致性要求。

9.5.1 JobCallback Records

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

Note

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

JobCallback Records 具有 Table 24 中列出的字段。

Table 24: JobCallback Record 字段
字段名 含义
[[Callback]] a function object Job 被调用时要调用的函数。
[[HostDefined]] anything (default value is empty) 保留给宿主使用的字段。

9.5.2 HostMakeJobCallback ( callback )

The host-defined abstract operation HostMakeJobCallback takes argument callback (a function object) and returns a 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, thisValue, argList )

The host-defined abstract operation HostCallJobCallback takes arguments jobCallback (a JobCallback Record), thisValue (an ECMAScript language value), and argList (a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value or a throw completion.

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

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

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

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

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

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

9.5.4 HostEnqueueGenericJob ( job, realm )

The host-defined abstract operation HostEnqueueGenericJob takes arguments job (a Job Abstract Closure) and realm (a Realm Record) and returns unused. 它在 realm realm 中、在由 realm.[[AgentSignifier]] 表示的 agent 中,调度 job 在将来某个时间执行。与此算法一起使用的 Abstract Closures 旨在无附加约束(例如优先级和顺序)地被调度。

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

9.5.5 HostEnqueuePromiseJob ( job, realm )

The host-defined abstract operation HostEnqueuePromiseJob takes arguments job (a Job Abstract Closure) and realm (a Realm Record or null) and returns unused. 它调度 job 在将来某个时间执行。与此算法一起使用的 Abstract Closures 旨在与 Promises 的处理有关,或者以其他方式按与 Promise 处理操作相同的优先级调度。

HostEnqueuePromiseJob 的实现必须符合 9.5 中的要求,以及以下要求:

Note

NewPromiseResolveThenableJob 返回的 Jobsrealm 通常是对 then 函数对象调用 GetFunctionRealm 的结果。NewPromiseReactionJob 返回的 Jobsrealm 通常是在 handler 不是 undefined 时对该 handler 调用 GetFunctionRealm 的结果。如果 handler 是 undefined,则 realmnull。对于这两种 Jobs,当 GetFunctionRealm 异常完成(即在已撤销 Proxy 上调用)时,realmGetFunctionRealm 调用时的当前 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 (a Job Abstract Closure), realm (a Realm Record), and milliseconds (a non-negative finite Number) and returns unused. 它在 realm realm 中、在由 realm.[[AgentSignifier]] 表示的 agent 中,调度 timeoutJob 至少在 milliseconds 毫秒之后执行。

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

9.6 Agents

agent 包含一组 ECMAScript 执行上下文、一个执行上下文栈、一个运行中执行上下文、一个 Agent Record,以及一个 执行线程。除执行线程外,agent 的组成部分专属于该 agent

agent执行线程在该 agent 的执行上下文上执行算法步骤,并独立于其他 agents;但一个执行线程可以被多个 agents 用作执行线程,前提是共享该线程的 agents 中没有任何 agent 具有 [[CanBlock]] 字段为 trueAgent Record

Note 1

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

agent执行线程正在执行算法步骤时,该 agent 是这些步骤的周围 agent。这些步骤使用周围 agent 访问该 agent 内持有的规范级执行对象:运行中执行上下文、执行上下文栈,以及 Agent Record 的字段。

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

Table 25: 代理记录字段
字段名称 含义
[[LittleEndian]] 一个布尔值 当算法 GetValueFromBufferSetValueInBuffer 需要 isLittleEndian 参数时,为该参数计算出的默认值。该选择由实现定义,并且应当是对该实现而言最高效的选项。
[[CanBlock]] 一个布尔值 确定该代理是否可以阻塞。
[[Signifier]] 一个代理标识符 在其代理集群中唯一标识该代理。
[[IsLockFree1]] 一个布尔值 如果对一字节值的原子操作是无锁的,则为 true;否则为 false
[[IsLockFree2]] 一个布尔值 如果对两字节值的原子操作是无锁的,则为 true;否则为 false
[[IsLockFree8]] 一个布尔值 如果对八字节值的原子操作是无锁的,则为 true;否则为 false
[[CandidateExecution]] 一个候选执行记录 内存模型
[[KeptAlive]] 一个由对象或 Symbol 组成的列表 最初是一个新的空列表,表示要保持活动直到当前 Job 结束的对象和/或 Symbol 的列表
[[ModuleAsyncEvaluationCount]] 一个整数 最初为 0,用于为异步模块或具有异步依赖项的模块的 [[AsyncEvaluationOrder]] 字段分配唯一的递增值。
[[GlobalSymbolRegistry]] 一个 GlobalSymbolRegistry 记录列表 最初是一个新的空列表,表示由 Symbol.for 产生的 Symbol 值的列表。

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

[[GlobalSymbolRegistry]] 列表只能追加,且绝不会被重新赋值。

Note 2

[[IsLockFree1]][[IsLockFree2]][[IsLockFree8]] 的值不一定由硬件决定,也可以反映会随时间以及 ECMAScript 实现而变化的实现选择。

没有 [[IsLockFree4]] 字段:4 字节原子操作始终是免锁的。

在实践中,如果某个原子操作使用任何类型的锁来实现,则该操作不是免锁的。免锁并不意味着无等待:完成一个免锁原子操作可能需要多少机器步骤没有上界。

大小为 n 的原子访问是免锁的,并不意味着大小为 n 的非原子访问的(感知)原子性有任何保证;具体而言,非原子访问仍可能作为若干独立内存访问的序列执行。详情参见 ReadSharedMemoryWriteSharedMemory

Note 3

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

9.6.1 AgentSignifier ( )

The abstract operation AgentSignifier takes no arguments and returns an agent signifier. 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 a Boolean. It performs the following steps when called:

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

在某些环境中,允许给定 agent 暂停可能并不合理。例如,在 Web 浏览器环境中,禁止挂起 document 的主事件处理线程可能是合理的,同时仍允许 workers 的事件处理线程暂停。

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 Clusters

agent cluster 是可以通过对共享内存进行操作来通信的最大 agent 集合。

Note 1

不同 agents 中的程序可以通过未指定的方式共享内存。至少,SharedArrayBuffers 的后备内存可以在 cluster 中的 agents 之间共享。

可能存在可以通过消息传递通信但不能共享内存的 agents;它们永远不会位于同一个 agent cluster 中。

每个 agent 都恰好属于一个 agent cluster。

Note 2

cluster 中的 agents 不需要在某个特定时间点全部存活。如果 agent A 创建另一个 agent B,之后 A 终止并且 B 创建 agent C,只要 A 能够与 B 共享某些内存,且 B 能够与 C 共享某些内存,则这三个 agents 位于同一个 cluster 中。

cluster 内的所有 agents 在各自 Agent Records 中的 [[LittleEndian]] 字段必须具有相同的值。

Note 3

如果一个 agent cluster 内不同 agents[[LittleEndian]] 值不同,则难以将共享内存用于多字节数据。

cluster 内的所有 agents 在各自 Agent Records 中的 [[IsLockFree1]] 字段必须具有相同值;[[IsLockFree2]][[IsLockFree8]] 字段同理。

cluster 内的所有 agents 在各自 Agent Records 中的 [[Signifier]] 字段必须具有不同值。

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

Note 4

前述限制的目的,是避免 agent 因另一个 agent 被停用而死锁或饥饿的情况。例如,如果允许一个生命周期独立于任何窗口中文档的 HTML shared worker 与这样一个独立文档的 dedicated worker 共享内存,而该文档及其 dedicated worker 在该 dedicated worker 持有锁时被停用(例如,该文档被推入其窗口的历史记录中),随后 shared worker 试图获取该锁,则 shared worker 将被阻塞,直到 dedicated worker 再次被激活,如果它还有机会被激活的话。与此同时,其他窗口中试图访问该 shared worker 的其他 workers 将会饥饿。

该限制的含义是,在嵌入环境中,不属于同一暂停/唤醒集体的 agents 之间将无法共享内存。

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

Note 5

这类终止的例子包括:操作系统或用户终止运行在独立进程中的 agents;当按 agent 资源核算表明某个 agent 失控时,嵌入环境自身终止与其他 agents 运行在进程内的该 agent

以下每个规范值,以及从它们传递可达的值,都恰好属于一个 agent cluster。

在一个 cluster 中任何 agent 对任何 ECMAScript 代码进行任何求值之前,cluster 中所有 agentsAgent Record[[CandidateExecution]] 字段都被设置为初始 candidate execution。初始 candidate execution 是一个空 candidate execution,其 [[EventsRecords]] 字段是一个 List,其中对每个 agent 包含一个 Agent Events Record,该记录的 [[AgentSignifier]] 字段为该 agentagent signifier,且其 [[EventList]][[AgentSynchronizesWith]] 字段为空 Lists

Note 6

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

Note 7

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

9.8 前向进展

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

agent 的运行中执行上下文同步且无限期地等待外部事件时,该 agent 变为阻塞。只有 Agent Record[[CanBlock]] 字段为 trueagents 才能以这种意义变为阻塞。未阻塞agent 是指未被阻塞的 agent

实现必须确保:

  • 每个具有专用执行线程的未阻塞 agent 最终取得前向进展
  • 在共享执行线程的一组 agents 中,某个 agent 最终取得前向进展
  • 一个 agent 不会导致另一个 agent 变为阻塞,除非通过提供阻塞的显式 API。
Note

这与内存模型中的活性保证一起,确保所有 seq-cst 写入最终都变得对所有 agents 可观察。

9.9 WeakRef 和 FinalizationRegistry 目标的处理模型

9.9.1 目标

本规范不保证任何对象或符号会被垃圾回收。不存活的对象或符号可能在很长时间之后被释放,或者永远不会被释放。因此,本规范在描述由垃圾回收触发的行为时使用术语“may”。

WeakRefsFinalizationRegistrys 的语义基于两个发生在特定时间点的操作:

这两个动作(ClearKeptObjectsCleanupFinalizationRegistry)都不得中断同步 ECMAScript 执行。由于宿主可能组装更长的同步 ECMAScript 执行运行,本规范将 ClearKeptObjectsCleanupFinalizationRegistry 的调度推迟给宿主环境

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

9.9.2 活性

对于某组对象和/或符号 objSet,相对于 objSet 的一次假想的 WeakRef-oblivious 执行,是这样一种执行:WeakRef抽象操作 WeakRefDeref 在该 WeakRef 的所指对象是 objSet 的元素时始终返回 undefined

Note 1
WeakRef-obliviousness 与 liveness 一起捕获两个概念。其一,WeakRef 本身不会保持其所指对象存活。其二,liveness 中的循环并不意味着某个值是存活的。具体而言,如果确定 v 的 liveness 依赖于确定某个 WeakRef 所指对象 r 的 liveness,则 r 的 liveness 不能假定 v 的 liveness,因为这将构成循环推理。
Note 2
WeakRef-obliviousness 定义在对象或符号集合上,而不是单个值上,以说明循环。如果它定义在单个值上,则循环中的 WeakRef 所指对象即使其身份仅通过该循环中的其他 WeakRef 所指对象被观察到,也会被认为是存活的。
Note 3
通俗地说,如果包含某个个体对象或符号的每个集合都是 live,我们就说该个体对象或符号是 live。

在求值期间的任何时刻,如果满足以下任一条件,则一组对象和/或符号 objSet 被认为是 live

  • objSet 中的任何元素包含在任何 agent[[KeptAlive]] List 中。
  • 存在一次相对于 objSet 的有效未来假想 WeakRef-oblivious 执行,该执行观察到 objSet 中任何值的身份。
Note 4
上述第二个条件旨在捕获这样的直觉:如果某个值的身份可通过非 WeakRef 手段观察到,则该值是 live。值的身份可以通过观察严格相等比较,或观察该值被用作 Map 中的键来观察。
Note 5

对象或符号出现在某个字段、内部槽或属性中,并不意味着该值是 live。例如,如果所讨论的值永远不会被传回程序,则它不能被观察到。

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

上述定义意味着,如果 WeakMap 中的某个键不是 live,则其对应值也不一定是 live。

Note 6
Liveness 是保证引擎不得清空哪些 WeakRefs 的下界。这里定义的 liveness 是不可判定的。在实践中,引擎使用诸如可达性之类的保守近似。预计会有显著的实现余地。

9.9.3 执行

在任意时间,如果一组对象和/或符号 objSet 不是 live,则 ECMAScript 实现可以原子地执行以下步骤:

  1. objSet 的每个元素 value,执行:
    1. 对每个 WeakRef ref,如果 ref.[[WeakRefTarget]]value,则执行:
      1. ref.[[WeakRefTarget]] 设置为 empty
    2. 对每个 FinalizationRegistry finalizationRegistry,如果 finalizationRegistry.[[Cells]] 包含一个 Record cell,使得 cell.[[WeakRefTarget]]value,则执行:
      1. cell.[[WeakRefTarget]] 设置为 empty
      2. enqueueCleanup 为一个实现定义的选择,其值为 truefalse
      3. 如果 enqueueCleanuptrue,则执行 HostEnqueueFinalizationRegistryCleanupJob(finalizationRegistry)。
    3. 对每个 WeakMap map,如果 map.[[WeakMapData]] 包含一个 Record entry,使得 entry.[[Key]]value,则执行:
      1. entry.[[Key]] 设置为 empty
      2. entry.[[Value]] 设置为 empty
    4. 对每个 WeakSet set,如果 set.[[WeakSetData]] 包含 value,则执行:
      1. set.[[WeakSetData]] 中值为 value 的元素替换为一个值为 empty 的元素。
Note 1

本条款与 liveness 的定义一起,规定了实现可以对 WeakRefs 应用的优化。

可以访问对象而不观察其身份。允许对身份未被观察的非逃逸对象的属性进行诸如死变量消除和标量替换之类的优化。因此,这些优化被允许以可观察方式清空指向这类对象的 WeakRefs

另一方面,如果某个对象的身份是可观察的,并且该对象位于 WeakRef[[WeakRefTarget]] 内部槽中,则禁止诸如 rematerialization 之类会以可观察方式清空 WeakRef 的优化。

由于调用 HostEnqueueFinalizationRegistryCleanupJob 是可选的,FinalizationRegistry 中已注册的对象不一定使该 FinalizationRegistry 保持 live。实现可以出于任何原因省略 FinalizationRegistry 回调,例如,如果 FinalizationRegistry 本身变为 dead,或者应用程序正在关闭。

Note 2

实现没有义务为最大非 live 对象或符号集合清空 WeakRefs

如果实现选择一个非 live 集合 objSet 来清空 WeakRefs,则此定义要求它同时清空 objSet 中所有值的 WeakRefs。换言之,实现如果清空指向值 vWeakRef,而不清空其他 WeakRefs(若不清空则可能导致一次观察到 v 值的执行),则不符合规范。

9.9.4 宿主钩子

9.9.4.1 HostEnqueueFinalizationRegistryCleanupJob ( finalizationRegistry )

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

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

  1. cleanupResultCompletion(CleanupFinalizationRegistry(finalizationRegistry))。
  2. 如果 cleanupResult 是 abrupt completion,则执行任何宿主定义的步骤来报告错误。
  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 (an Object or a Symbol) and returns unused. It performs the following steps when called:

  1. agentRecord周围 agentAgent Record
  2. value 追加到 agentRecord.[[KeptAlive]]
  3. 返回 unused
Note
抽象操作 AddToKeptObjects 以目标对象或符号调用时,它会将该目标添加到一个列表中,该列表会强引用该目标,直到调用 ClearKeptObjects

9.12 CleanupFinalizationRegistry ( finalizationRegistry )

The abstract operation CleanupFinalizationRegistry takes argument finalizationRegistry (a FinalizationRegistry) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

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

9.13 CanBeHeldWeakly ( arg )

The abstract operation CanBeHeldWeakly takes argument arg (an ECMAScript language value) and returns a Boolean. 当且仅当 arg 适合用作弱引用时,它返回 true。只有适合用作弱引用的值,才可以作为 WeakMap 的键、WeakSet 的元素、WeakRef 的目标,或 FinalizationRegistry 的目标之一。 It performs the following steps when called:

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

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