16 ECMAScript 语言:脚本与模块

16.1 脚本 (Scripts)

语法 (Syntax)

Script : ScriptBodyopt ScriptBody : StatementList[~Yield, ~Await, ~Return]

16.1.1 静态语义:早期错误 (Static Semantics: Early Errors)

Script : ScriptBody
  • ScriptBody 的 LexicallyDeclaredNames 含有任意重复条目,则为语法错误。
  • ScriptBody 的 LexicallyDeclaredNames 中任一元素也出现在 ScriptBody 的 VarDeclaredNames 中,则为语法错误。
ScriptBody : StatementList
  • StatementList Contains supertrue(除非包含 super 的源文本为正通过直接 eval 处理的 eval 代码),则为语法错误。直接 eval 中 super 的额外早期错误规则定义在 19.2.1.1
  • StatementList Contains NewTargettrue(除非包含 NewTarget 的源文本为正通过直接 eval 处理的 eval 代码),则为语法错误。直接 eval 中 NewTarget 的额外早期错误规则定义在 19.2.1.1
  • 若 ContainsDuplicateLabels(StatementList, « ») 为 true,则为语法错误。
  • 若 ContainsUndefinedBreakTarget(StatementList, « ») 为 true,则为语法错误。
  • 若 ContainsUndefinedContinueTarget(StatementList, « », « ») 为 true,则为语法错误。
  • 若 AllPrivateIdentifiersValid(StatementList, « ») 为 false(除非包含 ScriptBody 的源文本为正通过直接 eval 处理的 eval 代码),则为语法错误。

16.1.2 静态语义:ScriptIsStrict

The syntax-directed operation 静态语义:ScriptIsStrict takes no arguments and returns Boolean. It is defined piecewise over the following productions:

Script : ScriptBodyopt
  1. ScriptBody 存在且 ScriptBody 的指令序言包含 Use Strict 指令,返回 true;否则返回 false

16.1.3 运行时语义:求值 (Runtime Semantics: Evaluation)

Script : [empty]
  1. 返回 undefined

16.1.4 脚本记录 (Script Records)

脚本记录封装了正被求值的脚本的信息。每个脚本记录包含 Table 37 中列出的字段。

Table 37: 脚本记录字段
字段名 值类型 含义
[[Realm]] 一个 Realm Record 此脚本被创建时所在的领域。
[[ECMAScriptCode]] 一个 Script 解析节点 解析此脚本源文本的结果。
[[LoadedModules]] LoadedModuleRequest Record 的列表 从此脚本导入的说明符字符串到已解析的 Module Record 的映射。列表不包含两个不同的记录 r1r2 使得 ModuleRequestsEqual(r1, r2) 为 true
[[HostDefined]] 任意类型(默认值为 empty 为需要将额外信息与脚本关联的宿主环境保留的字段。

16.1.5 ParseScript ( sourceText, realm, hostDefined )

The abstract operation ParseScript takes arguments sourceText (ECMAScript 源文本), realm (一个 Realm Record), and hostDefined (任意类型) and returns 一个 Script Record 或非空的 SyntaxError 对象列表. 基于将 sourceText 解析为 Script 的结果创建一个 Script Record。 It performs the following steps when called:

  1. script 为 ParseText(sourceText, Script)。
  2. script 为错误列表,返回 script
  3. 返回 Script Record { [[Realm]]: realm, [[ECMAScriptCode]]: script, [[LoadedModules]]: « », [[HostDefined]]: hostDefined }。
Note

实现可以在对该脚本源文本求值 ParseScript 之前解析脚本源文本并分析早期错误条件。然而,任何错误的报告必须推迟到本规范实际对该源文本执行 ParseScript 的时候。

16.1.6 ScriptEvaluation ( scriptRecord )

The abstract operation ScriptEvaluation takes argument scriptRecord (一个 Script Record) and returns 正常完成(包含一个 ECMAScript 语言值)或突然完成. It performs the following steps when called:

  1. globalEnvscriptRecord.[[Realm]].[[GlobalEnv]]
  2. scriptContext 为一个新的 ECMAScript 代码执行上下文
  3. scriptContext 的 Function 为 null
  4. scriptContextRealmscriptRecord.[[Realm]]
  5. scriptContext 的 ScriptOrModule 为 scriptRecord
  6. scriptContext 的 VariableEnvironment 为 globalEnv
  7. scriptContext 的 LexicalEnvironment 为 globalEnv
  8. scriptContext 的 PrivateEnvironment 为 null
  9. 暂停正在运行的执行上下文。
  10. scriptContext 压入执行上下文栈;scriptContext 现在成为正在运行的执行上下文。
  11. scriptscriptRecord.[[ECMAScriptCode]]
  12. resultCompletion(GlobalDeclarationInstantiation(script, globalEnv))。
  13. result正常完成,则
    1. resultCompletion(Evaluation of script)。
    2. result正常完成result.[[Value]]empty,则
      1. resultNormalCompletion(undefined)。
  14. 暂停 scriptContext 并从执行上下文栈中移除它。
  15. 断言:执行上下文栈非空。
  16. 恢复现在位于执行上下文栈顶的上下文作为正在运行的执行上下文。
  17. 返回 ? result

16.1.7 GlobalDeclarationInstantiation ( script, env )

The abstract operation GlobalDeclarationInstantiation takes arguments script (一个 Script 解析节点) and env (一个 Global Environment Record) and returns 正常完成(包含 unused)或 throw completion. script 是正为其建立执行上下文的 Scriptenv 是要在其中创建绑定的全局环境。

Note 1

当为求值脚本建立执行上下文时,声明在当前全局环境中实例化。代码中声明的每个全局绑定都被实例化。

被调用时执行以下步骤:

  1. lexNamesscript 的 LexicallyDeclaredNames。
  2. varNamesscript 的 VarDeclaredNames。
  3. lexNames 的每个元素 name
    1. HasLexicalDeclaration(env, name) 为 true,抛出 SyntaxError 异常。
    2. hasRestrictedGlobal 为 ? HasRestrictedGlobalProperty(env, name)。
    3. 注:全局 varfunction 绑定(除了由非严格直接 eval 引入的那些)是不可配置的,因此是受限的全局属性。
    4. hasRestrictedGlobaltrue,抛出 SyntaxError 异常。
  4. varNames 的每个元素 name
    1. HasLexicalDeclaration(env, name) 为 true,抛出 SyntaxError 异常。
  5. varDeclarationsscript 的 VarScopedDeclarations。
  6. functionsToInitialize 为新的空列表。
  7. declaredFunctionNames 为新的空列表。
  8. varDeclarations 的每个元素 d,以反向列表顺序:
    1. d 既不是 VariableDeclarationForBinding 也不是 BindingIdentifier,则
      1. 断言:dFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration
      2. 注:若同一名称有多个函数声明,使用最后的声明。
      3. fnd 的 BoundNames 的唯一元素。
      4. declaredFunctionNames 不包含 fn,则
        1. fnDefinable 为 ? CanDeclareGlobalFunction(env, fn)。
        2. fnDefinablefalse,抛出 TypeError 异常。
        3. fn 追加到 declaredFunctionNames
        4. d 插入为 functionsToInitialize 的第一个元素。
  9. declaredVarNames 为新的空列表。
  10. varDeclarations 的每个元素 d
    1. dVariableDeclarationForBindingBindingIdentifier,则
      1. d 的 BoundNames 中每个字符串 vn
        1. declaredFunctionNames 不包含 vn,则
          1. vnDefinable 为 ? CanDeclareGlobalVar(env, vn)。
          2. vnDefinablefalse,抛出 TypeError 异常。
          3. declaredVarNames 不包含 vn,则
            1. vn 追加到 declaredVarNames
  11. 注:若全局对象是普通对象,此算法步骤之后不会发生异常终止。然而,若全局对象是 Proxy 异域对象,它可能表现出在某些后续步骤中导致异常终止的行为。
  12. Normative Optional
    宿主是 Web 浏览器或以其他方式支持 块级函数声明 Web 历史兼容语义,则
    1. strict 为 ScriptIsStrict(script)。
    2. strictfalse,则
      1. declaredFunctionOrVarNamesdeclaredFunctionNamesdeclaredVarNames 的列表连接。
      2. 对直接包含在任意 BlockCaseClauseDefaultClause xStatementList 中的每个 FunctionDeclaration f(使得 script Contains xtrue):
        1. FfBindingIdentifier 的 StringValue。
        2. 若将 FunctionDeclaration f 替换为以 F 作为 BindingIdentifierVariableStatement 不会为 script 产生任何早期错误,则
          1. HasLexicalDeclaration(env, F) 为 false,则
            1. fnDefinable 为 ? CanDeclareGlobalVar(env, F)。
            2. fnDefinabletrue,则
              1. 注:F 的 var 绑定仅在它既不是 VarDeclaredName 也不是另一个 FunctionDeclaration 的名称时才在此实例化。
              2. declaredFunctionOrVarNames 不包含 F,则
                1. 执行 ? CreateGlobalVarBinding(env, F, false)。
                2. F 追加到 declaredFunctionOrVarNames
              3. FunctionDeclaration f 被求值时,执行以下步骤而不是 15.2.6 中提供的 FunctionDeclaration 求值算法:
                1. gEnv 为正在运行的执行上下文的 VariableEnvironment。
                2. bEnv 为正在运行的执行上下文的 LexicalEnvironment。
                3. fObj 为 ! bEnv.GetBindingValue(F, false)。
                4. 执行 ? gEnv.SetMutableBinding(F, fObj, false)。
                5. 返回 unused
  13. lexDeclarationsscript 的 LexicallyScopedDeclarations。
  14. privateEnvnull
  15. lexDeclarations 的每个元素 d
    1. 注:词法声明的名称仅在此实例化但不初始化。
    2. d 的 BoundNames 的每个元素 dn
      1. 若 IsConstantDeclaration(d) 为 true,则
        1. 执行 ? env.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ? env.CreateMutableBinding(dn, false)。
  16. functionsToInitialize 的每个解析节点 f
    1. fnf 的 BoundNames 的唯一元素。
    2. fo 为 InstantiateFunctionObject(f, env, privateEnv)。
    3. 执行 ? CreateGlobalFunctionBinding(env, fn, fo, false)。
  17. declaredVarNames 的每个字符串 vn
    1. 执行 ? CreateGlobalVarBinding(env, vn, false)。
  18. 返回 unused
Note 2

16.1.1 中指定的早期错误防止了 function/var 声明与 let/const/class 声明之间的名称冲突,以及单个 Script 内声明的 let/const/class 绑定的重复声明。然而,跨越多个 Script 的此类冲突和重复声明在 GlobalDeclarationInstantiation 期间被检测为运行时错误。若检测到任何此类错误,不会为脚本实例化绑定。然而,若全局对象使用 Proxy 异域对象定义,则冲突声明的运行时测试可能不可靠,导致突然完成且某些全局声明未被实例化。若发生这种情况,Script 的代码不会被求值。

与显式的 var 或 function 声明不同,直接在全局对象上创建的属性会产生可能被 let/const/class 声明遮蔽的全局绑定。

16.2 模块 (Modules)

语法 (Syntax)

Module : ModuleBodyopt ModuleBody : ModuleItemList ModuleItemList : ModuleItem ModuleItemList ModuleItem ModuleItem : ImportDeclaration ExportDeclaration StatementListItem[~Yield, +Await, ~Return] ModuleExportName : IdentifierName StringLiteral

16.2.1 模块语义 (Module Semantics)

16.2.1.1 静态语义:早期错误 (Static Semantics: Early Errors)

ModuleBody : ModuleItemList
  • ModuleItemList 的 LexicallyDeclaredNames 包含任何重复条目,则为语法错误。
  • ModuleItemList 的 LexicallyDeclaredNames 中的任何元素也出现在 ModuleItemList 的 VarDeclaredNames 中,则为语法错误。
  • ModuleItemList 的 ExportedNames 包含任何重复条目,则为语法错误。
  • ModuleItemList 的 ExportedBindings 中的任何元素也不出现在 ModuleItemList 的 VarDeclaredNames 或 LexicallyDeclaredNames 中,则为语法错误。
  • ModuleItemList Contains super,则为语法错误。
  • ModuleItemList Contains NewTarget,则为语法错误。
  • 若 ContainsDuplicateLabels(ModuleItemList, « ») 为 true,则为语法错误。
  • 若 ContainsUndefinedBreakTarget(ModuleItemList, « ») 为 true,则为语法错误。
  • 若 ContainsUndefinedContinueTarget(ModuleItemList, « », « ») 为 true,则为语法错误。
  • 若 AllPrivateIdentifiersValid(ModuleItemList, « ») 为 false,则为语法错误。
Note

重复 ExportedNames 规则意味着在 ModuleBody 中有多个 export default ExportDeclaration 项是语法错误。与冲突或重复声明相关的额外错误条件在模块链接期间、Module 求值之前检查。如果检测到任何此类错误,Module 不会被求值。

ModuleExportName : StringLiteral
  • 若 IsStringWellFormedUnicode(SV of StringLiteral) 为 false,则为语法错误。

16.2.1.2 静态语义:ImportedLocalNames ( importEntries )

The abstract operation 静态语义:ImportedLocalNames takes argument importEntries (ImportEntry Record 列表) and returns 字符串列表. 创建由 importEntries 定义的所有本地名称绑定的列表。 It performs the following steps when called:

  1. localNames 为新的空列表。
  2. 对于 importEntries 的每个 ImportEntry Record i
    1. i.[[LocalName]] 追加到 localNames
  3. 返回 localNames

16.2.1.3 ModuleRequest 记录 (ModuleRequest Records)

ModuleRequest Record 表示使用给定导入属性导入模块的请求。它由以下字段组成:

Table 38: ModuleRequest Record 字段
字段名 值类型 含义
[[Specifier]] 字符串 模块说明符
[[Attributes]] ImportAttribute Record 列表 导入属性

LoadedModuleRequest Record 表示导入模块的请求以及生成的 Module Record。它由表 Table 38 中定义的相同字段组成,另外添加了 [[Module]]

Table 39: LoadedModuleRequest Record 字段
字段名 值类型 含义
[[Specifier]] 字符串 模块说明符
[[Attributes]] ImportAttribute Record 列表 导入属性
[[Module]] Module Record 对应此模块请求的已加载模块

ImportAttribute Record 由以下字段组成:

Table 40: ImportAttribute Record 字段
字段名 值类型 含义
[[Key]] 字符串 属性键
[[Value]] 字符串 属性值

16.2.1.3.1 ModuleRequestsEqual ( left, right )

The abstract operation ModuleRequestsEqual takes arguments left (ModuleRequest RecordLoadedModuleRequest Record) and right (ModuleRequest RecordLoadedModuleRequest Record) and returns Boolean. It performs the following steps when called:

  1. left.[[Specifier]] 不是 right.[[Specifier]],返回 false
  2. leftAttrsleft.[[Attributes]]
  3. rightAttrsright.[[Attributes]]
  4. leftAttrsCountleftAttrs 中元素的数量。
  5. rightAttrsCountrightAttrs 中元素的数量。
  6. leftAttrsCountrightAttrsCount,返回 false
  7. 对于 leftAttrs 的每个 ImportAttribute Record l
    1. rightAttrs 不包含满足 l.[[Key]]r.[[Key]]l.[[Value]]r.[[Value]]ImportAttribute Record r,返回 false
  8. 返回 true

16.2.1.4 静态语义:ModuleRequests

The syntax-directed operation 静态语义:ModuleRequests takes no arguments and returns ModuleRequest Record 列表. It is defined piecewise over the following productions:

Module : [empty]
  1. 返回新的空列表。
ModuleItemList : ModuleItem
  1. 返回 ModuleItem 的 ModuleRequests。
ModuleItemList : ModuleItemList ModuleItem
  1. requestsModuleItemList 的 ModuleRequests。
  2. additionalRequestsModuleItem 的 ModuleRequests。
  3. 对于 additionalRequests 的每个 ModuleRequest Record mr
    1. requests 不包含满足 ModuleRequestsEqual(mr, mr2) 为 trueModuleRequest Record mr2,则
      1. mr 追加到 requests
  4. 返回 requests
ModuleItem : StatementListItem
  1. 返回新的空列表。
ImportDeclaration : import ImportClause FromClause ;
  1. specifierFromClause 的 SV。
  2. 返回唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » } 的列表。
ImportDeclaration : import ImportClause FromClause WithClause ;
  1. specifierFromClause 的 SV。
  2. attributes 为 WithClauseToAttributes of WithClause
  3. 返回唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes } 的列表。
ImportDeclaration : import ModuleSpecifier ;
  1. specifierModuleSpecifier 的 SV。
  2. 返回唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » } 的列表。
ImportDeclaration : import ModuleSpecifier WithClause ;
  1. specifierModuleSpecifier 的 SV。
  2. attributes 为 WithClauseToAttributes of WithClause
  3. 返回唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes } 的列表。
ExportDeclaration : export ExportFromClause FromClause ;
  1. specifierFromClause 的 SV。
  2. 返回唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » } 的列表。
ExportDeclaration : export ExportFromClause FromClause WithClause ;
  1. specifierFromClause 的 SV。
  2. attributes 为 WithClauseToAttributes of WithClause
  3. 返回唯一元素为 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes } 的列表。
ExportDeclaration : export NamedExports ; export VariableStatement export Declaration export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回新的空列表。

16.2.1.5 抽象模块记录 (Abstract Module Records)

Module Record 封装了关于单个模块导入和导出的结构信息。这些信息用于链接连接模块集合的导入和导出。Module Record 包含四个仅在求值模块时使用的字段。

出于规范目的,Module Record 值是 Record 规范类型的值,可以看作存在于简单的面向对象层次结构中,其中 Module Record 是具有抽象和具体子类的抽象类。本规范定义了名为 Cyclic Module Record 的抽象子类及其名为 Source Text Module Record 的具体子类。其他规范和实现可以定义对应于它们所定义的替代模块定义工具的其他 Module Record 子类。

Module Record 定义了 Table 41 中列出的字段。所有 Module Definition 子类至少包含这些字段。Module Record 还定义了 Table 42 中的抽象方法列表。所有 Module definition 子类必须提供这些抽象方法的具体实现。

Table 41: Module Record 字段
字段名 值类型 含义
[[Realm]] Realm Record 创建此模块的领域。
[[Environment]] Module Environment Recordempty 包含此模块顶级绑定的 Environment Record。此字段在模块链接时设置。
[[Namespace]] Object 或 empty Module Namespace Object(28.3),如果已为此模块创建。
[[HostDefined]] 任意类型(默认值为 undefined 为需要将附加信息与模块关联的宿主环境保留的字段。
Table 42: Module Record 的抽象方法
方法 目的
LoadRequestedModules([hostDefined])

通过递归加载所有依赖项来准备模块以进行链接,并返回一个 promise。

GetExportedNames([exportStarSet])

返回从此模块直接或间接导出的所有名称的列表。

在调用此方法之前,LoadRequestedModules 必须已成功完成。

ResolveExport(exportName [, resolveSet])

返回此模块导出的名称的绑定。绑定由 ResolvedBinding Record 表示,形式为 { [[Module]]: Module Record, [[BindingName]]: String | namespace }。如果导出是没有任何模块中直接绑定的 Module Namespace Object,[[BindingName]] 将设置为 namespace。如果名称无法解析则返回 null,如果找到多个绑定则返回 ambiguous

每次使用特定 exportNameresolveSet 对作为参数调用此操作时,必须返回相同结果。

在调用此方法之前,LoadRequestedModules 必须已成功完成。

Link()

通过传递性地解析所有模块依赖项并创建 Module Environment Record 来准备模块以进行求值。

在调用此方法之前,LoadRequestedModules 必须已成功完成。

Evaluate()

返回此模块及其依赖项求值的 promise,在成功求值或已成功求值时解决,在求值错误或已求值失败时拒绝。如果 promise 被拒绝,期望宿主处理 promise 拒绝并重新抛出求值错误。

在调用此方法之前,Link 必须已成功完成。

16.2.1.5.1 EvaluateModuleSync ( module )

The abstract operation EvaluateModuleSync takes argument module (Module Record) and returns 包含 unused正常完成或 throw completion. 同步求值 module,前提是调用者保证 module 的求值将返回已定已 promise。 It performs the following steps when called:

  1. 断言:module 不是 Cyclic Module Record
  2. promisemodule.Evaluate()。
  3. 断言:promise.[[PromiseState]]fulfilledrejected
  4. promise.[[PromiseState]]rejected,则
    1. promise.[[PromiseIsHandled]]false,执行 HostPromiseRejectionTracker(promise, "handle")。
    2. promise.[[PromiseIsHandled]]true
    3. 返回 ThrowCompletion(promise.[[PromiseResult]])。
  5. 返回 unused

16.2.1.6 循环模块记录 (Cyclic Module Records)

Cyclic Module Record(循环模块记录) 用于表示一个模块与其它同属 Cyclic Module Record 类型子类的模块之间可以形成依赖环的信息。不是 Cyclic Module Record 类型子类的 Module Record 不得与 Source Text Module Record 形成依赖环。

Table 41 中定义的字段外,循环模块记录还具有 Table 43 中列出的附加字段。

Table 43: 循环模块记录的附加字段 (Additional Fields of Cyclic Module Records)
字段名 (Field Name) 值类型 (Value Type) 含义 (Meaning)
[[Status]] new, unlinked, linking, linked, evaluating, evaluating-async, 或 evaluated 初始为 new。在模块生命周期推进过程中按顺序转变为 unlinked, linking, linked, evaluating, 可能的 evaluating-async, 最终 evaluatedevaluating-async 表示该模块已排队等待其异步依赖完成后执行,或其 [[HasTLA]]true 且已开始执行,正在等待顶层完成。
[[EvaluationError]] throw completion 或 empty 表示求值期间发生的异常的 throw completion。若无异常或 [[Status]] 不是 evaluated,则为 undefined
[[DFSAncestorIndex]] 整数或 empty 仅在 Link 与 Evaluate 过程中使用的辅助字段。若 [[Status]]linkingevaluating,此值为该模块的深度优先遍历索引或其所在强连通分量中“更早”模块的索引。
[[RequestedModules]] ModuleRequest Record 列表 与该模块中的 import 相关联的 ModuleRequest Record 列表,按源码出现顺序排列。
[[LoadedModules]] LoadedModuleRequest Record 列表 将此记录所代表模块使用的说明符字符串(及相对导入属性)映射到解析得到的 Module Record。该列表不包含两个不同记录 r1r2 使得 ModuleRequestsEqual(r1, r2) 为 true
[[CycleRoot]] Cyclic Module Recordempty 环的首个访问模块,即强连通分量(SCC)的深度优先根祖先。对不在环中的模块,该字段为其自身。Evaluate 完成后,模块的 [[DFSAncestorIndex]] 等于其 [[CycleRoot]] 的深度优先遍历索引。
[[HasTLA]] Boolean 该模块自身是否为异步(例如包含顶层 await 的 Source Text Module Record)。拥有异步依赖不意味着此字段为 true。解析后不得再改变。
[[AsyncEvaluationOrder]] unset、整数或 done 初始为 unset,同步模块保持 unset。对自身异步或拥有异步依赖的模块,设为一个整数,用于决定 16.2.1.6.1.3.4 排队执行的顺序。待执行完毕后设为 done
[[TopLevelCapability]] PromiseCapability Recordempty 若此模块是某个环的 [[CycleRoot]] 且对该环中某模块调用了 Evaluate(),此字段保存该整体求值的 PromiseCapability,用于完成 Evaluate() 返回的 Promise。除非对依赖发起顶层 Evaluate(),否则依赖的该字段为 empty
[[AsyncParentModules]] Cyclic Module Record 列表 若此模块或其依赖具有 [[HasTLA]] true 且执行中,记录在顶层执行作业中依赖它的父导入者。在其完成之前这些父模块不会开始执行。
[[PendingAsyncDependencies]] 整数或 empty 若该模块有异步依赖,此值跟踪剩余尚未执行完成的异步依赖模块数量。计数降至 0 且无执行错误时,该模块执行。

Table 42 中的方法外,循环模块记录还具有 Table 44 中列出的附加抽象方法。

Table 44: 循环模块记录的附加抽象方法 (Additional Abstract Methods of Cyclic Module Records)
方法 (Method) 目的 (Purpose)
InitializeEnvironment() 初始化模块的 Environment Record(包括解析全部导入绑定)并创建模块的执行上下文。
ExecuteModule([promiseCapability]) 在其执行上下文内求值模块代码。若模块 [[HasTLA]]true,则传入 PromiseCapability Record,方法应 resolve 或 reject 该能力;此时不得抛出异常,需通过 reject 处理。

GraphLoadingState Record(图加载状态记录) 是包含模块图加载流程信息的记录,用于在 HostLoadImportedModule 调用后继续加载。每个记录包含 Table 45 中的字段:

Table 45: 图加载状态记录字段 (GraphLoadingState Record Fields)
字段名 (Field Name) 值类型 (Value Type) 含义 (Meaning)
[[PromiseCapability]] PromiseCapability Record 加载流程完成时要 resolve 的 promise。
[[IsLoading]] Boolean 若加载流程尚未成功或失败完成则为 true
[[PendingModulesCount]] 非负整数 跟踪未完成 HostLoadImportedModule 调用的数量。
[[Visited]] Cyclic Module Record 列表 已在本次加载过程中加载的循环模块集合,用于避免循环依赖无限循环。
[[HostDefined]] 任意(默认 empty 宿主传入、供 LoadRequestedModules 到 HostLoadImportedModule 传递的宿主定义数据。

16.2.1.6.1 模块记录抽象方法的具体实现 (Implementation of Module Record Abstract Methods)

以下为循环模块记录对 Table 42 中相应模块记录抽象方法的具体实现。

16.2.1.6.1.1 LoadRequestedModules ( [ hostDefined ] )

The LoadRequestedModules concrete method of Cyclic Module Record module takes optional argument hostDefined (anything) and returns Promise. 填充 module 依赖图中所有 Module Record[[LoadedModules]](主要工作由辅助函数 InnerModuleLoading 完成)。可选参数 hostDefined 将传递给 HostLoadImportedModule 钩子。 It performs the following steps when called:

  1. hostDefined 未传入,令 hostDefinedempty
  2. pc 为 ! NewPromiseCapability(%Promise%)。
  3. state 为 GraphLoadingState Record { [[IsLoading]]: true, [[PendingModulesCount]]: 1, [[Visited]]: « », [[PromiseCapability]]: pc, [[HostDefined]]: hostDefined }。
  4. 执行 InnerModuleLoading(state, module)。
  5. 返回 pc.[[Promise]]
Note
参数 hostDefined 可传递获取导入模块所需的额外信息。例如 HTML 用它为 <link rel="preload" as="..."> 设置正确的 fetch destination。import() 表达式不会设置该参数。

16.2.1.6.1.1.1 InnerModuleLoading ( state, module )

The abstract operation InnerModuleLoading takes arguments state (GraphLoadingState Record) and module (Module Record) and returns unused. 被 LoadRequestedModules 使用,递归执行 module 依赖图的实际加载过程。 It performs the following steps when called:

  1. 断言:state.[[IsLoading]]true
  2. module 是 Cyclic Module Recordmodule.[[Status]]newstate.[[Visited]] 不含 module,则
    1. module 追加至 state.[[Visited]]
    2. requestedModulesCountmodule.[[RequestedModules]] 的元素数。
    3. state.[[PendingModulesCount]] = state.[[PendingModulesCount]] + requestedModulesCount
    4. module.[[RequestedModules]] 每个 ModuleRequest Record request
      1. AllImportAttributesSupported(request.[[Attributes]]) 为 false,则
        1. errorThrowCompletion(新建的 SyntaxError 对象)。
        2. 执行 ContinueModuleLoading(state, error)。
      2. 否则若 module.[[LoadedModules]]LoadedModuleRequest Record record 使 ModuleRequestsEqual(record, request) 为 true,则
        1. 执行 InnerModuleLoading(state, record.[[Module]])。
      3. 否则,
        1. 执行 HostLoadImportedModule(module, request, state.[[HostDefined]], state)。
        2. 注:HostLoadImportedModule 将调用 FinishLoadingImportedModule,经由 ContinueModuleLoading 重新进入图加载流程。
      4. state.[[IsLoading]]false,返回 unused
  3. 断言:state.[[PendingModulesCount]] ≥ 1。
  4. state.[[PendingModulesCount]] = state.[[PendingModulesCount]] - 1。
  5. state.[[PendingModulesCount]] = 0,则
    1. state.[[IsLoading]] = false
    2. state.[[Visited]] 中每个 Cyclic Module Record loaded
      1. loaded.[[Status]]new,设其为 unlinked
    3. 执行 ! Call(state.[[PromiseCapability]].[[Resolve]], undefined, « undefined »)。
  6. 返回 unused

16.2.1.6.1.1.2 ContinueModuleLoading ( state, moduleCompletion )

The abstract operation ContinueModuleLoading takes arguments state (GraphLoadingState Record) and moduleCompletion (正常完成(含 Module Record)或 throw completion) and returns unused. 在 HostLoadImportedModule 返回后重新进入加载流程。 It performs the following steps when called:

  1. state.[[IsLoading]]false,返回 unused
  2. moduleCompletion正常完成,则
    1. 执行 InnerModuleLoading(state, moduleCompletion.[[Value]])。
  3. 否则,
    1. state.[[IsLoading]] = false
    2. 执行 ! Call(state.[[PromiseCapability]].[[Reject]], undefined, « moduleCompletion.[[Value]] »)。
  4. 返回 unused

16.2.1.6.1.2 Link ( )

The Link concrete method of Cyclic Module Record module takes no arguments and returns 正常完成(含 unused)或 throw completion. 成功时将 [[Status]]unlinked 过渡到 linked。失败时抛出异常且保持 unlinked。(主要工作由辅助函数 InnerModuleLinking 完成。) It performs the following steps when called:

  1. 断言:module.[[Status]] 属于 unlinked, linked, evaluating-async, evaluated 之一。
  2. stack 为新空列表。
  3. resultCompletion(InnerModuleLinking(module, stack, 0))。
  4. result 为突然完成,则
    1. stack 中每个 Cyclic Module Record m
      1. 断言:m.[[Status]]linking
      2. m.[[Status]] = unlinked
    2. 断言:module.[[Status]]unlinked
    3. 返回 ? result
  5. 断言:module.[[Status]] 属于 linked, evaluating-async, evaluated
  6. 断言:stack 为空。
  7. 返回 unused

16.2.1.6.1.2.1 InnerModuleLinking ( module, stack, index )

The abstract operation InnerModuleLinking takes arguments module (Module Record), stack (Cyclic Module Record 列表), and index (非负整数) and returns 正常完成(含非负整数)或 throw completion. Link 使用它执行 module 的实际链接,并递归链接其依赖图的其它模块。参数 stackindex 以及模块的 [[DFSAncestorIndex]] 用于跟踪深度优先遍历(DFS),借此发现强连通分量(SCC),确保同一 SCC 内模块一起转为 linked。 It performs the following steps when called:

  1. module 不是 Cyclic Module Record,则
    1. 执行 ? module.Link()。
    2. 返回 index
  2. module.[[Status]] 属于 linking, linked, evaluating-async, evaluated,则
    1. 返回 index
  3. 断言:module.[[Status]]unlinked
  4. module.[[Status]] = linking
  5. moduleIndex = index
  6. module.[[DFSAncestorIndex]] = index
  7. index = index + 1。
  8. module 追加到 stack
  9. module.[[RequestedModules]] 每个 ModuleRequest Record request
    1. requiredModule = GetImportedModule(module, request)。
    2. index = ? InnerModuleLinking(requiredModule, stack, index)。
    3. requiredModule 是 Cyclic Module Record,则
      1. 断言:其 [[Status]] 属于 linking, linked, evaluating-async, evaluated
      2. 断言:requiredModule.[[Status]]linking 当且仅当 stack 含有它。
      3. 若为 linking,则
        1. module.[[DFSAncestorIndex]] = min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])。
  10. 执行 ? module.InitializeEnvironment()。
  11. 断言:modulestack 中仅出现一次。
  12. 断言:module.[[DFSAncestorIndex]]moduleIndex
  13. module.[[DFSAncestorIndex]] = moduleIndex,则
    1. done = false
    2. donefalse 循环:
      1. requiredModulestack 最末元素。
      2. 移除该末元素。
      3. 断言:requiredModule 为 Cyclic Module Record
      4. requiredModule.[[Status]] = linked
      5. requiredModulemodule 相同,设 done = true
  14. 返回 index

16.2.1.6.1.3 Evaluate ( )

The Evaluate concrete method of Cyclic Module Record module takes no arguments and returns Promise. Evaluate 将 [[Status]]linked 过渡为 evaluating-asyncevaluated。在给定强连通分量中第一次对任一模块调用时创建并返回 Promise,直至模块求值完成。该 Promise 存入该分量 [[CycleRoot]][[TopLevelCapability]]。随后对分量中任何模块的调用返回同一 Promise。(主要工作由 InnerModuleEvaluation 完成。) It performs the following steps when called:

  1. 断言:本次 Evaluate 调用未与同代理内另一 Evaluate 并发。
  2. 断言:module.[[Status]] 属于 linked, evaluating-async, evaluated
  3. [[Status]]evaluating-asyncevaluated,令 module = module.[[CycleRoot]]
  4. module.[[TopLevelCapability]]empty,返回其 [[Promise]]
  5. stack 为新空列表。
  6. capability = ! NewPromiseCapability(%Promise%)。
  7. module.[[TopLevelCapability]] = capability
  8. result = Completion(InnerModuleEvaluation(module, stack, 0))。
  9. result 为突然完成,则
    1. stack 中每个 Cyclic Module Record m
      1. 断言:m.[[Status]]evaluating
      2. 断言:m.[[AsyncEvaluationOrder]]unset
      3. m.[[Status]] = evaluated
      4. m.[[EvaluationError]] = result
    2. 断言:module.[[Status]]evaluated
    3. 断言:module.[[EvaluationError]]result 为同一 Completion Record
    4. 执行 ! Call(capability.[[Reject]], undefined, « result.[[Value]] »)。
  10. 否则,
    1. 断言:module.[[Status]]evaluating-asyncevaluated
    2. 断言:module.[[EvaluationError]]empty
    3. module.[[Status]]evaluated,则
      1. 注:表示同步完成求值。
      2. 断言:module.[[AsyncEvaluationOrder]]unset
      3. 执行 ! Call(capability.[[Resolve]], undefined, « undefined »)。
    4. 断言:stack 为空。
  11. 返回 capability.[[Promise]]

16.2.1.6.1.3.1 InnerModuleEvaluation ( module, stack, index )

The abstract operation InnerModuleEvaluation takes arguments module (Module Record), stack (Cyclic Module Record 列表), and index (非负整数) and returns 正常完成(含非负整数)或 throw completion. Evaluate 使用它执行 module 的实际求值,并递归应用于依赖图的其它模块。stack / index[[DFSAncestorIndex]] 用法与 InnerModuleLinking 相同。 It performs the following steps when called:

  1. module 非 Cyclic Module Record,则
    1. 执行 ? EvaluateModuleSync(module)。
    2. 返回 index
  2. module.[[Status]]evaluating-asyncevaluated,则
    1. [[EvaluationError]]empty,返回 index
    2. 否则返回 ? module.[[EvaluationError]]
  3. module.[[Status]]evaluating,返回 index
  4. 断言:module.[[Status]]linked
  5. module.[[Status]] = evaluating
  6. moduleIndex = index
  7. module.[[DFSAncestorIndex]] = index
  8. module.[[PendingAsyncDependencies]] = 0。
  9. index = index + 1。
  10. module 追加至 stack
  11. module.[[RequestedModules]] 每个 ModuleRequest Record request
    1. requiredModule = GetImportedModule(module, request)。
    2. index = ? InnerModuleEvaluation(requiredModule, stack, index)。
    3. requiredModule 为 Cyclic Module Record,则
      1. 断言:其 [[Status]] 属于 evaluating, evaluating-async, evaluated
      2. 断言:当且仅当 stack 含其时状态为 evaluating
      3. 若为 evaluating,设 module.[[DFSAncestorIndex]] = min(两者索引)。
      4. 否则,
        1. requiredModule = requiredModule.[[CycleRoot]]
        2. 断言:其 [[Status]]evaluating-asyncevaluated
        3. 若其 [[EvaluationError]]empty,返回 ? 该错误。
      5. requiredModule.[[AsyncEvaluationOrder]] 为整数,则
        1. module.[[PendingAsyncDependencies]] += 1。
        2. module 追加至 requiredModule.[[AsyncParentModules]]
  12. module.[[PendingAsyncDependencies]] > 0 或 [[HasTLA]]true,则
    1. 断言:module.[[AsyncEvaluationOrder]]unset
    2. module.[[AsyncEvaluationOrder]] = IncrementModuleAsyncEvaluationCount()。
    3. module.[[PendingAsyncDependencies]] = 0,执行 ExecuteAsyncModule(module)。
  13. 否则,
    1. 执行 ? module.ExecuteModule()
  14. 断言:modulestack 中仅出现一次。
  15. 断言:module.[[DFSAncestorIndex]]moduleIndex
  16. module.[[DFSAncestorIndex]] = moduleIndex,则
    1. done = false
    2. donefalse
      1. requiredModulestack 最末元素并移除。
      2. 断言:其为 Cyclic Module Record
      3. 断言:其 [[AsyncEvaluationOrder]] 为整数或 unset
      4. 若为 unset,设其 [[Status]] = evaluated;否则设为 evaluating-async
      5. 若与 module 相同,设 done = true
      6. requiredModule.[[CycleRoot]] = module
  17. 返回 index
Note 1

模块在 InnerModuleEvaluation 遍历时为 evaluating;若执行完成则为 evaluated,若执行期间自身 [[HasTLA]]true 或有异步依赖则为 evaluating-async

Note 2

依赖某异步环的模块在该环不处于 evaluating 时,通过 [[CycleRoot]] 依赖环根的执行,确保环作为单个强连通分量对待。

16.2.1.6.1.3.2 ExecuteAsyncModule ( module )

The abstract operation ExecuteAsyncModule takes argument module (Cyclic Module Record) and returns unused. It performs the following steps when called:

  1. 断言:module.[[Status]]evaluatingevaluating-async
  2. 断言:module.[[HasTLA]]true
  3. capability = ! NewPromiseCapability(%Promise%)。
  4. fulfilledClosure 为捕获 module 的无参抽象闭包,调用时:
    1. 执行 AsyncModuleExecutionFulfilled(module)。
    2. 返回 NormalCompletion(undefined)。
  5. onFulfilled = CreateBuiltinFunction(fulfilledClosure, 0, "", « »)。
  6. rejectedClosure 为捕获 module 的抽象闭包(参数 error):
    1. 执行 AsyncModuleExecutionRejected(module, error)。
    2. 返回 NormalCompletion(undefined)。
  7. onRejected = CreateBuiltinFunction(rejectedClosure, 0, "", « »)。
  8. 执行 PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected)。
  9. 执行 ! module.ExecuteModule(capability)。
  10. 返回 unused

16.2.1.6.1.3.3 GatherAvailableAncestors ( module, execList )

The abstract operation GatherAvailableAncestors takes arguments module (Cyclic Module Record) and execList (Cyclic Module Record 列表) and returns unused. It performs the following steps when called:

  1. module.[[AsyncParentModules]] 中每个 Cyclic Module Record m
    1. execList 不含 mm.[[CycleRoot]].[[EvaluationError]]empty,则
      1. 断言:m.[[Status]]evaluating-async
      2. 断言:m.[[EvaluationError]]empty
      3. 断言:m.[[AsyncEvaluationOrder]] 为整数。
      4. 断言:m.[[PendingAsyncDependencies]] > 0。
      5. m.[[PendingAsyncDependencies]] = m.[[PendingAsyncDependencies]] - 1。
      6. 若其为 0,则
        1. m 追加至 execList
        2. m.[[HasTLA]]false,执行 GatherAvailableAncestors(m, execList)。
  2. 返回 unused
Note

当根 module 的异步执行 fulfilled 时,此函数确定可同步继续执行的模块集合,填入 execList

16.2.1.6.1.3.4 AsyncModuleExecutionFulfilled ( module )

The abstract operation AsyncModuleExecutionFulfilled takes argument module (Cyclic Module Record) and returns unused. It performs the following steps when called:

  1. module.[[Status]]evaluated,则
    1. 断言:module.[[EvaluationError]]empty
    2. 返回 unused
  2. 断言:module.[[Status]]evaluating-async
  3. 断言:module.[[AsyncEvaluationOrder]] 为整数。
  4. 断言:module.[[EvaluationError]]empty
  5. module.[[AsyncEvaluationOrder]] = done
  6. module.[[Status]] = evaluated
  7. module.[[TopLevelCapability]]empty,则
    1. 断言:module.[[CycleRoot]]module 为同一记录。
    2. 执行 ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)。
  8. execList 为新空列表。
  9. 执行 GatherAvailableAncestors(module, execList)。
  10. 断言:execList 各元素之 [[AsyncEvaluationOrder]] 为整数、[[PendingAsyncDependencies]] 为 0、[[EvaluationError]]empty
  11. sortedExecList 为按 [[AsyncEvaluationOrder]] 升序排序的 execList 拷贝。
  12. sortedExecList 每个 Cyclic Module Record m
    1. m.[[Status]]evaluated,断言其 [[EvaluationError]]empty
    2. 否则若 m.[[HasTLA]]true,执行 ExecuteAsyncModule(m)。
    3. 否则,
      1. result = m.ExecuteModule()
      2. result 为突然完成,执行 AsyncModuleExecutionRejected(m, result.[[Value]])。
      3. 否则,
        1. m.[[AsyncEvaluationOrder]] = done
        2. m.[[Status]] = evaluated
        3. m.[[TopLevelCapability]]empty
          1. 断言:m.[[CycleRoot]]m 相同。
          2. 执行 ! Call(m.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)。
  13. 返回 unused

16.2.1.6.1.3.5 AsyncModuleExecutionRejected ( module, error )

The abstract operation AsyncModuleExecutionRejected takes arguments module (Cyclic Module Record) and error (ECMAScript 语言值) and returns unused. It performs the following steps when called:

  1. module.[[Status]]evaluated,则
    1. 断言:module.[[EvaluationError]]empty
    2. 返回 unused
  2. 断言:module.[[Status]]evaluating-async
  3. 断言:module.[[AsyncEvaluationOrder]] 为整数。
  4. 断言:module.[[EvaluationError]]empty
  5. module.[[EvaluationError]] = ThrowCompletion(error)。
  6. module.[[Status]] = evaluated
  7. module.[[AsyncEvaluationOrder]] = done
  8. 注:出于与 AsyncModuleExecutionFulfilled 对称,在出现错误时也设为 done;当 [[EvaluationError]]empty 时,其 [[AsyncEvaluationOrder]] 不再使用。
  9. module.[[AsyncParentModules]] 中每个 Cyclic Module Record m
    1. 执行 AsyncModuleExecutionRejected(m, error)。
  10. module.[[TopLevelCapability]]empty,则
    1. 断言:module.[[CycleRoot]]module 相同。
    2. 执行 ! Call(module.[[TopLevelCapability]].[[Reject]], undefined, « error »)。
  11. 返回 unused

16.2.1.6.2 循环模块记录图示例 (Example Cyclic Module Record Graphs)

本非规范性章节展示若干常见模块图的链接与求值示例,重点说明错误如何出现。

先看一个简单模块图:

Figure 2: 简单模块图 (A simple module graph)
模块 A 依赖模块 B,模块 B 依赖模块 C 的模块图

假设无错误:宿主首先调用 A.LoadRequestedModules()(递归加载 BC 的依赖),然后将 ABC[[Status]] 设为 unlinked。接着调用 A.Link(),三者转为 linked。稍后宿主在需要触发副作用时调用 A.Evaluate(),按顺序先求值 CB,最终三者 [[Status]]evaluated,Promise resolve 为 undefined

若在成功的 A.LoadRequestedModules() 之后出现链接错误:例如 InnerModuleLinking 处理 C 成功但随后 B 失败(导入不存在的内容),则 A.Link() 失败,AB 保持 unlinkedClinked

若在成功 Link() 后出现求值错误:例如 C 求值成功但 B 中代码抛出异常,则 A.Evaluate() 返回被拒绝的 Promise;异常记录在 AB[[EvaluationError]],二者变为 evaluatedC 也为 evaluated 但无错误。记录异常保证后续再次 Evaluate() 遇到相同错误。

接着看一个无法解析模块的情形:

Figure 3: 含缺失模块的模块图 (A module graph with an unresolvable module)
模块 A 依赖一个缺失模块 ??? 的模块图

此时 A 依赖的模块不存在(HostLoadImportedModule 最终以异常完成 FinishLoadingImportedModule)。可能原因包括资源不存在或解析返回错误。宿主可选择暴露失败原因。该异常导致加载失败,A.[[Status]] 保持 new

加载、链接与求值错误的差异:

  • 求值只应执行一次(可能有副作用),需记住是否已求值及其结果(包含异常)。
  • 链接无副作用,可失败后重试。
  • 加载与宿主交互紧密,宿主可能允许在临时网络错误后重试。

现在看一个包含环的模块图:

Figure 4: 循环模块图 (A cyclic module graph)
模块 A 依赖 B 和 C,且 B 依赖 A 的模块图

A 为入口,LoadRequestedModules 触发对 BC 的加载;因循环再次访问 A 时不再重复。成功后所有模块状态同时从 new 转为 unlinked

随后 Link 通过 DFS 对环进行 InnerModuleLinking,遇回返时不重复,最终在回溯根时同时把 SCC 中的 AB 设为 linkedC 已先行)。求值阶段的成功路径类同。

A 存在链接错误(如从 C 导入不存在的绑定),第二次回到 A 时提前返回,但最终在 InitializeEnvironment(调用 C.ResolveExport 后)抛出 SyntaxError。异常向上使当前栈中仍 linkingAB 重置为 unlinkedC 保持 linked

A 存在求值错误(源码抛异常),则求值阶段对应逻辑使 A 与仍 evaluatingB 记录错误并转为 evaluatedC 成功为 evaluated 且无错误。包含顶层 await 的路径通过 [[AsyncParentModules]] 传播。

最后看一个所有模块异步完成的循环图:

Figure 5: 异步循环模块图 (An asynchronous cyclic module graph)
模块 A 依赖 B 与 C,B 依赖 D,C 依赖 D 与 E,D 依赖 A 的模块图

加载与链接后全部为 linked

调用 A.Evaluate():ABD 设为 evaluatingD 无待依赖触发 ExecuteAsyncModule(D);回溯时 B 记录等待;继续处理 C 及其 D(无操作)与 E(执行异步)。最终整个环出栈,转为 evaluating-async,其字段如 Table 46

Table 46: 初次 Evaluate() 后的模块字段 (Module fields after the initial Evaluate() call)
字段 / 模块
Module
A B C D E
[[DFSAncestorIndex]] 0 0 0 0 4
[[Status]] evaluating-async evaluating-async evaluating-async evaluating-async evaluating-async
[[AsyncEvaluationOrder]] 4 1 3 0 2
[[AsyncParentModules]] « » « A » « A » « B, C » « C »
[[PendingAsyncDependencies]] 2 (B, C) 1 (D) 2 (D, E) 0 0

假设 E 先完成,调用 AsyncModuleExecutionFulfilledEevaluatedC.[[PendingAsyncDependencies]] 减至 1;字段见 Table 47

Table 47: 模块 E 完成后的字段 (Module fields after module E finishes executing)
字段
Module
C E
[[DFSAncestorIndex]] 0 4
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 3 done
[[AsyncParentModules]] « A » « C »
[[PendingAsyncDependencies]] 1 (D) 0

接着 D 完成:D 设为 evaluated,其可激活祖先为 B(顺序 1)与 C(顺序 3),因此先处理 B:其 Pending 变为 0,执行 ExecuteAsyncModule(B);随后 C 也开始执行;字段见 Table 48

Table 48: 模块 D 完成后的字段 (Module fields after module D finishes executing)
字段
Module
B C D
[[DFSAncestorIndex]]000
[[Status]]evaluating-asyncevaluating-asyncevaluated
[[AsyncEvaluationOrder]]13done
[[AsyncParentModules]]« A »« A »« B, C »
[[PendingAsyncDependencies]]000

然后 C 完成:设为 evaluatedA.Pending 减为 1;见 Table 49

Table 49: 模块 C 完成后的字段 (Module fields after module C finishes executing)
字段
Module
A C
[[DFSAncestorIndex]]00
[[Status]]evaluating-asyncevaluated
[[AsyncEvaluationOrder]]4done
[[AsyncParentModules]]« »« A »
[[PendingAsyncDependencies]]1 (B)0

随后 B 完成:设为 evaluatedA.Pending 减为 0,执行 ExecuteAsyncModule(A);见 Table 50

Table 50: 模块 B 完成后的字段 (Module fields after module B finishes executing)
字段
Module
A B
[[DFSAncestorIndex]]00
[[Status]]evaluating-asyncevaluated
[[AsyncEvaluationOrder]]4done
[[AsyncParentModules]]« »« A »
[[PendingAsyncDependencies]]00

最终 A 完成:A 设为 evaluated,其 [[TopLevelCapability]] 的 Promise resolve,图处理结束;见 Table 51

Table 51: 模块 A 完成后的字段 (Module fields after module A finishes executing)
字段
Module
A
[[DFSAncestorIndex]]0
[[Status]]evaluated
[[AsyncEvaluationOrder]]done
[[AsyncParentModules]]« »
[[PendingAsyncDependencies]]0

若失败:假设 C 先执行出错,在 AsyncModuleExecutionRejectedC 设为 evaluated 且记录错误,并沿 AsyncParentModules 传播;见 Table 52

Table 52: 模块 C 错误后的字段 (Module fields after module C finishes with an error)
字段
Module
A C
[[DFSAncestorIndex]]00
[[Status]]evaluatedevaluated
[[AsyncEvaluationOrder]]donedone
[[AsyncParentModules]]« »« A »
[[PendingAsyncDependencies]]1 (B)0
[[EvaluationError]]emptyC 的求值错误

A 也被拒绝并记录相同错误;见 Table 53

Table 53: 模块 A 被拒绝后的字段 (Module fields after module A is rejected)
字段
Module
A
[[DFSAncestorIndex]]0
[[Status]]evaluated
[[AsyncEvaluationOrder]]done
[[AsyncParentModules]]« »
[[PendingAsyncDependencies]]0
[[EvaluationError]]C 的 Evaluation Error

若随后 B 正常完成AsyncModuleExecutionFulfilled 运行但因 A(环根)已有错误,不再继续执行;未来导入 B 的模块通过 B.[[CycleRoot]].[[EvaluationError]] 看到同一错误;见 Table 54

Table 54: 错误图中 B 完成后的字段 (Module fields after module B finishes executing in an erroring graph)
字段
Module
A B
[[DFSAncestorIndex]]00
[[Status]]evaluatedevaluated
[[AsyncEvaluationOrder]]41
[[AsyncParentModules]]« »« A »
[[PendingAsyncDependencies]]00
[[EvaluationError]]C 的 Evaluation Errorempty

16.2.1.7 源码文本模块记录 (Source Text Module Records)

Source Text Module Record(源码文本模块记录) 表示由 ECMAScript 源文本(11,以 Module目标符号)解析出的模块信息。其字段包含模块导入与导出的摘要,具体方法利用这些摘要进行链接与求值。

该记录可与其它 Module Record 子类共存于模块图,并可与其它 Cyclic Module Record 子类构成环。

Table 43 字段外,还拥有 Table 55 中列出的附加字段,均在 ParseModule 中初始化。

Table 55: 源码文本模块记录附加字段 (Additional Fields of Source Text Module Records)
字段名 值类型 含义
[[ECMAScriptCode]] Parse Node Module目标符号解析该模块源文本的结果。
[[Context]] ECMAScript 代码执行上下文empty 与模块关联的执行上下文;在环境初始化前为 empty
[[ImportMeta]] Object 或 empty 通过 import.meta 暴露的对象;首次访问前为 empty
[[ImportEntries]] ImportEntry Record 列表 源码导入语句解析出的 ImportEntry 列表。
[[LocalExportEntries]] ExportEntry Record 列表 对应模块内部声明的导出。
[[IndirectExportEntries]] ExportEntry Record 列表 对应重导出的导入或 export * as namespace 的导出。
[[StarExportEntries]] ExportEntry Record 列表 对应 export *(不含 export * as namespace)的导出。

ImportEntry Record(导入项记录) 汇总单个声明式导入的信息,其字段见 Table 56

Table 56: ImportEntry 记录字段 (ImportEntry Record Fields)
字段名 值类型 含义
[[ModuleRequest]] ModuleRequest Record 表示 ImportDeclarationModuleSpecifier 与导入属性。
[[ImportName]] String 或 namespace-object 目标模块中导出的绑定名称。namespace-object 表示请求模块命名空间对象。
[[LocalName]] String 在本模块中访问该导入值的局部名字。
Note 1

Table 57 展示不同导入语法与 ImportEntry 字段的映射:

Table 57 (Informative): 导入语法到 ImportEntry 映射 (Import Forms Mappings to ImportEntry Records)
导入语句形式 [[ModuleRequest]] [[ImportName]] [[LocalName]]
import v from "mod"; "mod" "default" "v"
import * as ns from "mod"; "mod" namespace-object "ns"
import {x} from "mod"; "mod" "x" "x"
import {x as v} from "mod"; "mod" "x" "v"
import "mod"; 不创建 ImportEntry Record

ExportEntry Record(导出项记录) 汇总单个声明式导出信息,字段见 Table 58

Table 58: ExportEntry 记录字段 (ExportEntry Record Fields)
字段名 值类型 含义
[[ExportName]] String 或 null 对外导出的名称。
[[ModuleRequest]] ModuleRequest Recordnull 表示 ExportDeclarationModuleSpecifier 与导入属性;无则为 null
[[ImportName]] String、nullallall-but-default [[ModuleRequest]] 指定模块导出的绑定名;export * as nsallexport *all-but-default。无则 null
[[LocalName]] String 或 null 在本模块内部访问该导出值的名字;若非本地可访问则为 null
Note 2

Table 59 展示导出语法与 ExportEntry 字段映射:

Table 59 (Informative): 导出语法到 ExportEntry 映射 (Export Forms Mappings to ExportEntry Records)
导出语句形式 [[ExportName]] [[ModuleRequest]] [[ImportName]] [[LocalName]]
export var v; "v" null null "v"
export default function f() {} "default" null null "f"
export default function () {} "default" null null "default*"*
export default 42; "default" null null "default*"*
export {x}; "x" null null "x"
export {v as x}; "x" null null "v"
export {x} from "mod"; "x" "mod" "x" null
export {v as x} from "mod"; "x" "mod" "v" null
export * from "mod"; null "mod" all-but-default null
export * as ns from "mod"; "ns" "mod" all null

以下定义 Source Text Module Record 所需的具体方法与相关抽象操作

16.2.1.7.1 ParseModule ( sourceText, realm, hostDefined )

The abstract operation ParseModule takes arguments sourceText (ECMAScript 源文本), realm (Realm Record), and hostDefined (任意) and returns Source Text Module Record 或非空 SyntaxError 对象列表. 将 sourceTextModule 解析并创建 Source Text Module Record。 It performs the following steps when called:

  1. body = ParseText(sourceText, Module)。
  2. body 为错误列表,返回之。
  3. requestedModules = ModuleRequests(body)。
  4. importEntries = ImportEntries(body)。
  5. importedBoundNames = ImportedLocalNames(importEntries)。
  6. indirectExportEntrieslocalExportEntriesstarExportEntries 各为新空列表。
  7. exportEntries = ExportEntries(body)。
  8. exportEntries 每个 ExportEntry Record ee
    1. ee.[[ModuleRequest]]null,则
      1. importedBoundNames 不含 ee.[[LocalName]],追加 eelocalExportEntries
      2. 否则,
        1. ieimportEntries[[LocalName]] 等于该名的元素。
        2. ie.[[ImportName]]namespace-object
          1. 注:重导出模块命名空间对象。
          2. 追加 eelocalExportEntries
        3. 否则:
          1. 注:重导出单一名称。
          2. 追加 ExportEntry { [[ModuleRequest]]: ie.[[ModuleRequest]], [[ImportName]]: ie.[[ImportName]], [[LocalName]]: null, [[ExportName]]: ee.[[ExportName]] } 至 indirectExportEntries
    2. 否则若 ee.[[ImportName]]all-but-default
      1. 断言:ee.[[ExportName]]null
      2. 追加 eestarExportEntries
    3. 否则追加 eeindirectExportEntries
  9. async = body Contains await
  10. 返回 Source Text Module Record { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[CycleRoot]]: empty, [[HasTLA]]: async, [[AsyncEvaluationOrder]]: unset, [[TopLevelCapability]]: empty, [[AsyncParentModules]]: « », [[PendingAsyncDependencies]]: empty, [[Status]]: new, [[EvaluationError]]: empty, [[HostDefined]]: hostDefined, [[ECMAScriptCode]]: body, [[Context]]: empty, [[ImportMeta]]: empty, [[RequestedModules]]: requestedModules, [[LoadedModules]]: « », [[ImportEntries]]: importEntries, [[LocalExportEntries]]: localExportEntries, [[IndirectExportEntries]]: indirectExportEntries, [[StarExportEntries]]: starExportEntries, [[DFSAncestorIndex]]: empty }。
Note

实现可提前解析并检查早期错误,但错误报告需延迟到实际调用 ParseModule 时。

16.2.1.7.2 模块记录抽象方法实现 (Implementation of Module Record Abstract Methods)

以下为 Source Text Module RecordTable 42 中模块记录抽象方法的具体实现。

16.2.1.7.2.1 GetExportedNames ( [ exportStarSet ] )

The GetExportedNames concrete method of Source Text Module Record module takes optional argument exportStarSet (Source Text Module Record 列表) and returns String 列表. It performs the following steps when called:

  1. 断言:module.[[Status]]new
  2. exportStarSet 未传入,设为新空列表。
  3. exportStarSetmodule
    1. 断言:达到 export * 循环起点。
    2. 返回新空列表。
  4. 追加 moduleexportStarSet
  5. exportedNames 为新空列表。
  6. module.[[LocalExportEntries]] 每个 e
    1. 断言:存在直接绑定。
    2. 断言:e.[[ExportName]]null
    3. 追加该名称。
  7. module.[[IndirectExportEntries]] 每个 e
    1. 断言:导入特定绑定。
    2. 追加 e.[[ExportName]]
  8. module.[[StarExportEntries]] 每个 e
    1. 断言:e.[[ModuleRequest]]null
    2. requestedModule = GetImportedModule(module, e.[[ModuleRequest]])。
    3. starNames = requestedModule.GetExportedNames(exportStarSet)。
    4. starNames 每个 n
      1. n"default"exportedNames 不含 n,则追加。
  9. 返回 exportedNames
Note

GetExportedNames 不过滤或抛出模糊的星号再导出绑定。

16.2.1.7.2.2 ResolveExport ( exportName [ , resolveSet ] )

The ResolveExport concrete method of Source Text Module Record module takes argument exportName (String) and optional argument resolveSet (记录列表(字段 [[Module]] Module Record[[ExportName]] String)) and returns ResolvedBinding Recordnullambiguous.

尝试解析导出名称到定义的模块与局部绑定名。若是命名空间导出且无本地绑定,则 [[BindingName]]namespaceresolveSet 用于检测循环路径;若对同一 (module, exportName) 再次出现则返回 null。找到单一定义返回 ResolvedBinding;无定义或循环返回 null;多重模糊返回 ambiguous

It performs the following steps when called:

  1. 断言:module.[[Status]]new
  2. resolveSet 未传入,设为新空列表。
  3. resolveSet 中存在记录与 (module, exportName) 相同:
    1. 断言:循环导出请求。
    2. 返回 null
  4. 追加 { [[Module]]: module, [[ExportName]]: exportName } 至 resolveSet
  5. 遍历 [[LocalExportEntries]]
    1. 若匹配 exportName,返回 { [[Module]]: module, [[BindingName]]: e.[[LocalName]] }。
  6. 遍历 [[IndirectExportEntries]]
    1. 若匹配:
      1. 断言有 [[ModuleRequest]]
      2. importedModule = GetImportedModule(module, e.[[ModuleRequest]])。
      3. e.[[ImportName]]all
        1. 返回 { [[Module]]: importedModule, [[BindingName]]: namespace }。
      4. 否则返回 importedModule.ResolveExport(e.[[ImportName]], resolveSet)。
  7. exportName"default"
    1. 返回 null。(默认导出不会由 export * from 提供)
  8. starResolution = null
  9. 遍历 [[StarExportEntries]]
    1. importedModule = GetImportedModule(... )。
    2. resolution = importedModule.ResolveExport(exportName, resolveSet)。
    3. ambiguous 返回 ambiguous
    4. 若非 null
      1. starResolutionnull,设之。
      2. 否则若模块不同或 BindingName 不兼容(含命名空间冲突)返回 ambiguous
  10. 返回 starResolution

16.2.1.7.3 循环模块记录抽象方法的实现 (Implementation of Cyclic Module Record Abstract Methods)

以下为 Source Text Module RecordTable 44 中循环模块记录抽象方法的实现。

16.2.1.7.3.1 InitializeEnvironment ( )

The InitializeEnvironment concrete method of Source Text Module Record module takes no arguments and returns 正常完成(含 unused)或 throw completion. It performs the following steps when called:

  1. module.[[IndirectExportEntries]] 每个 e
    1. 断言 e.[[ExportName]]null
    2. resolution = module.ResolveExport(e.[[ExportName]])。
    3. 若为 nullambiguousSyntaxError
  2. 断言所有命名导出可解析。
  3. realm = module.[[Realm]]
  4. 断言非 undefined
  5. env = NewModuleEnvironment(realm.[[GlobalEnv]])。
  6. module.[[Environment]] = env
  7. module.[[ImportEntries]] 每个 in
    1. importedModule = GetImportedModule(... )。
    2. in.[[ImportName]]namespace-object
      1. namespace = GetModuleNamespace(importedModule)。
      2. ! CreateImmutableBinding + InitializeBinding。
    3. 否则:
      1. resolution = importedModule.ResolveExport(in.[[ImportName]])。
      2. nullambiguousSyntaxError
      3. resolution.[[BindingName]]namespace
        1. 获取命名空间并绑定。
      4. 否则 CreateImportBinding
  8. 创建执行上下文 moduleContext 并关联环境。
  9. 推入执行上下文栈并获取 code
  10. 处理 VarScopedDeclarations:为每个唯一变量创建并初始化 undefined
  11. 处理 LexicallyScopedDeclarations:创建(可变或不可变)绑定;若是函数类声明,实例化函数对象并初始化绑定。
  12. 弹出执行上下文。
  13. 返回 unused

16.2.1.7.3.2 ExecuteModule ( [ capability ] )

The ExecuteModule concrete method of Source Text Module Record module takes optional argument capability (PromiseCapability Record) and returns 正常完成(含 unused)或 throw completion. It performs the following steps when called:

  1. 创建新执行上下文 moduleContext 并关联 module.[[Environment]]
  2. 暂停当前执行上下文。
  3. module.[[HasTLA]]false
    1. 断言 capability 未提供。
    2. 推入 moduleContext
    3. result = Completion(Evaluation of module.[[ECMAScriptCode]])。
    4. 弹出并恢复上层上下文。
    5. result 为突然完成,返回 ? result
  4. 否则:
    1. 断言 capability 存在。
    2. 执行 AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext)。
  5. 返回 unused

16.2.1.8 合成模块记录 (Synthetic Module Records)

Synthetic Module Record(合成模块记录) 表示由规范定义的模块,其导出名称在创建时静态确定,但值可通过 SetSyntheticModuleExport 动态更新;无导入或依赖。

Note
可用于定义多种模块类型,如 JSON 模块或 CSS 模块。

Table 41 字段外,还具有 Table 60 中附加字段。

Table 60: 合成模块记录附加字段 (Additional Fields of Synthetic Module Records)
字段名 值类型 含义
[[ExportNames]] 字符串列表 模块的导出名称;无重复。
[[EvaluationSteps]] 抽象闭包 求值期间的初始化逻辑,以模块自身为唯一参数;不得修改 [[ExportNames]];可返回突然完成。

16.2.1.8.1 CreateDefaultExportSyntheticModule ( defaultExport )

The abstract operation CreateDefaultExportSyntheticModule takes argument defaultExport (ECMAScript 语言值) and returns Synthetic Module Record. 创建一个默认导出为 defaultExport 的合成模块记录。 It performs the following steps when called:

  1. realm当前 Realm Record
  2. setDefaultExport 为捕获 defaultExport 的抽象闭包(module):
    1. 执行 SetSyntheticModuleExport(module, "default", defaultExport)。
    2. 返回 NormalCompletion(unused)。
  3. 返回 { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[HostDefined]]: undefined, [[ExportNames]]: « "default" », [[EvaluationSteps]]: setDefaultExport } 的 Synthetic Module Record

16.2.1.8.2 ParseJSONModule ( source )

The abstract operation ParseJSONModule takes argument source (String) and returns 正常完成(含 Synthetic Module Record)或 throw completion. It performs the following steps when called:

  1. json = ? ParseJSON(source)。
  2. 返回 CreateDefaultExportSyntheticModule(json)。

16.2.1.8.3 SetSyntheticModuleExport ( module, exportName, exportValue )

The abstract operation SetSyntheticModuleExport takes arguments module (Synthetic Module Record), exportName (String), and exportValue (ECMAScript 语言值) and returns unused. 设置或更新合成模块已存在导出的值。 It performs the following steps when called:

  1. 断言:module.[[ExportNames]]exportName
  2. envRec = module.[[Environment]]
  3. 断言:envRecempty
  4. 执行 envRec.SetMutableBinding(exportName, exportValue, true)。
  5. 返回 unused

16.2.1.8.4 模块记录抽象方法实现 (Implementation of Module Record Abstract Methods)

以下为合成模块记录对 Table 42 抽象方法的实现。

16.2.1.8.4.1 LoadRequestedModules ( )

The LoadRequestedModules concrete method of Synthetic Module Record module takes no arguments and returns Promise. It performs the following steps when called:

  1. 返回 ! PromiseResolve(%Promise%, undefined)。
Note
合成模块记录无依赖。

16.2.1.8.4.2 GetExportedNames ( )

The GetExportedNames concrete method of Synthetic Module Record module takes no arguments and returns 字符串列表. It performs the following steps when called:

  1. 返回 module.[[ExportNames]]

16.2.1.8.4.3 ResolveExport ( exportName )

The ResolveExport concrete method of Synthetic Module Record module takes argument exportName (String) and returns ResolvedBinding Recordnull. It performs the following steps when called:

  1. 若不含 exportName,返回 null
  2. 返回 { [[Module]]: module, [[BindingName]]: exportName }。

16.2.1.8.4.4 Link ( )

The Link concrete method of Synthetic Module Record module takes no arguments and returns 正常完成(含 unused). It performs the following steps when called:

  1. realm = module.[[Realm]]
  2. env = NewModuleEnvironment(realm.[[GlobalEnv]])。
  3. module.[[Environment]] = env
  4. module.[[ExportNames]] 每个 exportName
    1. ! CreateMutableBinding + InitializeBinding(exportName, undefined)。
  5. 返回 NormalCompletion(unused)。

16.2.1.8.4.5 Evaluate ( )

The Evaluate concrete method of Synthetic Module Record module takes no arguments and returns Promise. It performs the following steps when called:

  1. 创建执行上下文 moduleContext 并关联环境。
  2. 暂停当前执行上下文并推入 moduleContext
  3. steps = module.[[EvaluationSteps]]
  4. result = Completion(steps(module))。
  5. 弹出 moduleContext 并恢复。
  6. pc = ! NewPromiseCapability(%Promise%)。
  7. IfAbruptRejectPromise(result, pc)。
  8. 执行 ! Call(pc.[[Resolve]], undefined, « undefined »)。
  9. 返回 pc.[[Promise]]

16.2.1.9 GetImportedModule ( referrer, request )

The abstract operation GetImportedModule takes arguments referrer (Cyclic Module Record) and request (ModuleRequest Record) and returns Module Record. It performs the following steps when called:

  1. recordsreferrer.[[LoadedModules]] 中满足 ModuleRequestsEqual(r, request) 为 trueLoadedModuleRequest Record 列表。
  2. 断言:records 恰有一个元素。
  3. record 为其唯一元素。
  4. 返回 record.[[Module]]

16.2.1.10 HostLoadImportedModule ( referrer, moduleRequest, hostDefined, payload )

The host-defined abstract operation HostLoadImportedModule takes arguments referrer (Script Record、Cyclic Module RecordRealm Record), moduleRequest (ModuleRequest Record), hostDefined (任意), and payload (GraphLoadingState RecordPromiseCapability Record) and returns unused.

Note 1

在浏览器中,用户点击:

<button type="button" onclick="import('./foo.mjs')">Click me</button>

执行 import() 时可能没有活动脚本或模块(执行上下文栈顶 ScriptOrModule 为 null),因此 referrer 可能是 Realm Record

HostLoadImportedModule 的实现需满足:

实际过程由宿主定义,通常包括执行所需 I/O 以加载 Module Record。不同 (referrer, 说明符, 属性) 组合可映射到同一模块实例,说明符标准化过程由宿主定义(如解析相对与简写路径)。

Note 2

上述要求宿主type: "json" 时支持 JSON 模块(且正常完成),但不禁止在缺省类型下支持 JSON。

16.2.1.11 FinishLoadingImportedModule ( referrer, moduleRequest, payload, result )

The abstract operation FinishLoadingImportedModule takes arguments referrer (一个 Script Record、Cyclic Module RecordRealm Record), moduleRequest (一个 ModuleRequest Record), payload (一个 GraphLoadingState RecordPromiseCapability Record), and result (正常完成(包含一个 Module Record)或 throw completion) and returns unused. It performs the following steps when called:

  1. 如果 result正常完成,则
    1. 如果 referrer.[[LoadedModules]] 包含某个 LoadedModuleRequest Record recordModuleRequestsEqual(record, moduleRequest) 为 true,则
      1. 断言:record.[[Module]]result.[[Value]] 是同一个 Module Record
    2. 否则,
      1. LoadedModuleRequest Record { [[Specifier]]: moduleRequest.[[Specifier]], [[Attributes]]: moduleRequest.[[Attributes]], [[Module]]: result.[[Value]] } 追加到 referrer.[[LoadedModules]]
  2. 如果 payload 是 GraphLoadingState Record,则
    1. 执行 ContinueModuleLoading(payload, result)。
  3. 否则,
    1. 执行 ContinueDynamicImport(payload, result)。
  4. 返回 unused

16.2.1.12 AllImportAttributesSupported ( attributes )

The abstract operation AllImportAttributesSupported takes argument attributes (ImportAttribute Records 的列表) and returns Boolean. It performs the following steps when called:

  1. supportedHostGetSupportedImportAttributes()。
  2. attributes 的每个 ImportAttribute Record attribute
    1. 如果 supported 不包含 attribute.[[Key]],返回 false
  3. 返回 true

16.2.1.12.1 HostGetSupportedImportAttributes ( )

The host-defined abstract operation HostGetSupportedImportAttributes takes no arguments and returns 字符串列表. 允许宿主环境指明其支持的 import 属性。只有具有受支持键的属性才会提供给宿主

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

  • 必须返回一个字符串列表,每个字符串表示一个受支持的属性。
  • 每次调用都必须返回同一个包含相同内容且顺序相同的列表。

默认实现返回一个新的空列表。

Note
要求宿主声明支持的导入属性,而不是将全部属性传给宿主再筛选,旨在确保不同宿主对不支持属性的处理一致。

16.2.1.13 GetModuleNamespace ( module )

The abstract operation GetModuleNamespace takes argument module (Module Record 具体子类的一个实例) and returns Module Namespace Object. 获取表示 module 导出的 Module Namespace Object,第一次请求时惰性创建并存入 module.[[Namespace]] 以供后续复用。 It performs the following steps when called:

  1. 断言:若 module 是 Cyclic Module Record,则 module.[[Status]] 不为 newunlinked
  2. namespacemodule.[[Namespace]]
  3. 如果 namespaceempty,则
    1. exportedNamesmodule.GetExportedNames()。
    2. unambiguousNames 为新的空列表。
    3. exportedNames 的每个元素 name
      1. resolutionmodule.ResolveExport(name)。
      2. 如果 resolutionResolvedBinding Record,将 name 追加到 unambiguousNames
    4. namespaceModuleNamespaceCreate(module, unambiguousNames)。
  4. 返回 namespace
Note

GetModuleNamespace 不会抛出异常。不可解析的名称此时直接排除;除非它们全是未被显式请求的歧义星号导出,否则稍后会导致真实的链接错误。

16.2.1.14 运行时语义:求值 (Runtime Semantics: Evaluation)

Module : [empty]
  1. 返回 undefined
ModuleBody : ModuleItemList
  1. resultCompletion(Evaluation of ModuleItemList)。
  2. 如果 result正常完成result.[[Value]]empty,则
    1. 返回 undefined
  3. 返回 ? result
ModuleItemList : ModuleItemList ModuleItem
  1. sl 为 ? Evaluation of ModuleItemList
  2. sCompletion(Evaluation of ModuleItem)。
  3. 返回 ? UpdateEmpty(s, sl)。
Note

ModuleItemList 的值是其中最后一个产生值的条目的值。

ModuleItem : ImportDeclaration
  1. 返回 empty

16.2.2 导入 (Imports)

语法 (Syntax)

ImportDeclaration : import ImportClause FromClause WithClauseopt ; import ModuleSpecifier WithClauseopt ; ImportClause : ImportedDefaultBinding NameSpaceImport NamedImports ImportedDefaultBinding , NameSpaceImport ImportedDefaultBinding , NamedImports ImportedDefaultBinding : ImportedBinding NameSpaceImport : * as ImportedBinding NamedImports : { } { ImportsList } { ImportsList , } FromClause : from ModuleSpecifier ImportsList : ImportSpecifier ImportsList , ImportSpecifier ImportSpecifier : ImportedBinding ModuleExportName as ImportedBinding ModuleSpecifier : StringLiteral ImportedBinding : BindingIdentifier[~Yield, +Await] WithClause : with { } with { WithEntries ,opt } WithEntries : AttributeKey : StringLiteral AttributeKey : StringLiteral , WithEntries AttributeKey : IdentifierName StringLiteral

16.2.2.1 静态语义:早期错误 (Static Semantics: Early Errors)

ModuleItem : ImportDeclaration
  • ImportDeclaration 的 BoundNames 含有任意重复条目,则为语法错误。
WithClause : with { WithEntries ,opt }
  • WithClause 的 WithClauseToAttributes 具有两个不同条目 aba.[[Key]]b.[[Key]],则为语法错误。

16.2.2.2 静态语义:ImportEntries

The syntax-directed operation 静态语义:ImportEntries takes no arguments and returns ImportEntry Record 列表. It is defined piecewise over the following productions:

Module : [empty]
  1. 返回新的空列表。
ModuleItemList : ModuleItemList ModuleItem
  1. entries1ModuleItemList 的 ImportEntries。
  2. entries2ModuleItem 的 ImportEntries。
  3. 返回 entries1entries2 的列表连接。
ModuleItem : ExportDeclaration StatementListItem
  1. 返回新的空列表。
ImportDeclaration : import ImportClause FromClause WithClauseopt ;
  1. moduleImportDeclaration 的 ModuleRequests 的唯一元素。
  2. 返回 ImportClause 的 ImportEntriesForModule,参数 module
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  1. 返回新的空列表。

16.2.2.3 静态语义:ImportEntriesForModule

The syntax-directed operation 静态语义:ImportEntriesForModule takes argument module (ModuleRequest Record) and returns ImportEntry Record 列表. It is defined piecewise over the following productions:

ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. entries1ImportedDefaultBinding 的 ImportEntriesForModule,参数 module
  2. entries2NameSpaceImport 的 ImportEntriesForModule,参数 module
  3. 返回 entries1entries2 的列表连接。
ImportClause : ImportedDefaultBinding , NamedImports
  1. entries1ImportedDefaultBinding 的 ImportEntriesForModule,参数 module
  2. entries2NamedImports 的 ImportEntriesForModule,参数 module
  3. 返回 entries1entries2 的列表连接。
ImportedDefaultBinding : ImportedBinding
  1. localNameImportedBinding 的 BoundNames 的唯一元素。
  2. defaultEntry 为 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: "default", [[LocalName]]: localName }。
  3. 返回 « defaultEntry »。
NameSpaceImport : * as ImportedBinding
  1. localNameImportedBinding 的 StringValue。
  2. entry 为 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: namespace-object, [[LocalName]]: localName }。
  3. 返回 « entry »。
NamedImports : { }
  1. 返回新的空列表。
ImportsList : ImportsList , ImportSpecifier
  1. specs1ImportsList 的 ImportEntriesForModule,参数 module
  2. specs2ImportSpecifier 的 ImportEntriesForModule,参数 module
  3. 返回 specs1specs2 的列表连接。
ImportSpecifier : ImportedBinding
  1. localNameImportedBinding 的 BoundNames 的唯一元素。
  2. entry 为 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: localName, [[LocalName]]: localName }。
  3. 返回 « entry »。
ImportSpecifier : ModuleExportName as ImportedBinding
  1. importNameModuleExportName 的 StringValue。
  2. localNameImportedBinding 的 StringValue。
  3. entry 为 ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName }。
  4. 返回 « entry »。

16.2.2.4 静态语义:WithClauseToAttributes

The syntax-directed operation 静态语义:WithClauseToAttributes takes no arguments and returns ImportAttribute Record 列表. It is defined piecewise over the following productions:

WithClause : with { }
  1. 返回新的空列表。
WithClause : with { WithEntries ,opt }
  1. attributesWithEntries 的 WithClauseToAttributes。
  2. 按其 [[Key]] 字段的字典序(视各字段值为 UTF-16 代码单元序列)对 attributes 排序。注:该排序的可观察性仅体现在宿主被禁止基于枚举顺序改变行为。
  3. 返回 attributes
WithEntries : AttributeKey : StringLiteral
  1. keyAttributeKey 的 PropName。
  2. entryImportAttribute Record { [[Key]]: key, [[Value]]: StringLiteral 的 SV }。
  3. 返回 « entry »。
WithEntries : AttributeKey : StringLiteral , WithEntries
  1. keyAttributeKey 的 PropName。
  2. entryImportAttribute Record { [[Key]]: key, [[Value]]: StringLiteral 的 SV }。
  3. restWithEntries 的 WithClauseToAttributes。
  4. 返回 « entry » 与 rest 的列表连接。

16.2.3 导出 (Exports)

语法 (Syntax)

ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement[~Yield, +Await] export Declaration[~Yield, +Await] export default HoistableDeclaration[~Yield, +Await, +Default] export default ClassDeclaration[~Yield, +Await, +Default] export default [lookahead ∉ { function, async [no LineTerminator here] function, class }] AssignmentExpression[+In, ~Yield, +Await] ; ExportFromClause : * * as ModuleExportName NamedExports NamedExports : { } { ExportsList } { ExportsList , } ExportsList : ExportSpecifier ExportsList , ExportSpecifier ExportSpecifier : ModuleExportName ModuleExportName as ModuleExportName

16.2.3.1 静态语义:早期错误 (Static Semantics: Early Errors)

ExportDeclaration : export NamedExports ;
  • NamedExports 的 ReferencedBindings 包含任意 StringLiteral,则为语法错误。
  • 对于 NamedExports 的 ReferencedBindings 中每个 IdentifierName n:若 n 的 StringValue 是 ReservedWord,或其值是 "implements""interface""let""package""private""protected""public""static" 之一,则为语法错误。
Note

上述规则意味着 NamedExports 的每个 ReferencedBindings 被视作一个 IdentifierReference

16.2.3.2 静态语义:ExportedBindings

The syntax-directed operation 静态语义:ExportedBindings takes no arguments and returns 字符串列表.

Note

ExportedBindings 是一个 Module 的 ExportedNames 显式映射到的本地绑定名称集合。

It is defined piecewise over the following productions:

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemList 的 ExportedBindings。
  2. names2ModuleItem 的 ExportedBindings。
  3. 返回 names1names2 的列表连接。
ModuleItem : ImportDeclaration StatementListItem
  1. 返回新的空列表。
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回新的空列表。
ExportDeclaration : export NamedExports ;
  1. 返回 NamedExports 的 ExportedBindings。
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatement 的 BoundNames。
ExportDeclaration : export Declaration
  1. 返回 Declaration 的 BoundNames。
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回此 ExportDeclaration 的 BoundNames。
NamedExports : { }
  1. 返回新的空列表。
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsList 的 ExportedBindings。
  2. names2ExportSpecifier 的 ExportedBindings。
  3. 返回 names1names2 的列表连接。
ExportSpecifier : ModuleExportName
  1. 返回仅含 ModuleExportName 的 StringValue 的列表。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回仅含第一个 ModuleExportName 的 StringValue 的列表。

16.2.3.3 静态语义:ExportedNames

The syntax-directed operation 静态语义:ExportedNames takes no arguments and returns 字符串列表.

Note

ExportedNames 是 Module 显式映射到其本地绑定的对外可见名称集合。

It is defined piecewise over the following productions:

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemList 的 ExportedNames。
  2. names2ModuleItem 的 ExportedNames。
  3. 返回 names1names2 的列表连接。
ModuleItem : ExportDeclaration
  1. 返回 ExportDeclaration 的 ExportedNames。
ModuleItem : ImportDeclaration StatementListItem
  1. 返回新的空列表。
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回 ExportFromClause 的 ExportedNames。
ExportFromClause : *
  1. 返回新的空列表。
ExportFromClause : * as ModuleExportName
  1. 返回仅含 ModuleExportName 的 StringValue 的列表。
ExportFromClause : NamedExports
  1. 返回 NamedExports 的 ExportedNames。
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatement 的 BoundNames。
ExportDeclaration : export Declaration
  1. 返回 Declaration 的 BoundNames。
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回 « "default" »。
NamedExports : { }
  1. 返回新的空列表。
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsList 的 ExportedNames。
  2. names2ExportSpecifier 的 ExportedNames。
  3. 返回 names1names2 的列表连接。
ExportSpecifier : ModuleExportName
  1. 返回仅含 ModuleExportName 的 StringValue 的列表。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回仅含第二个 ModuleExportName 的 StringValue 的列表。

16.2.3.4 静态语义:ExportEntries

The syntax-directed operation 静态语义:ExportEntries takes no arguments and returns ExportEntry Record 列表. It is defined piecewise over the following productions:

Module : [empty]
  1. 返回新的空列表。
ModuleItemList : ModuleItemList ModuleItem
  1. entries1ModuleItemList 的 ExportEntries。
  2. entries2ModuleItem 的 ExportEntries。
  3. 返回 entries1entries2 的列表连接。
ModuleItem : ImportDeclaration StatementListItem
  1. 返回新的空列表。
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. moduleExportDeclaration 的 ModuleRequests 的唯一元素。
  2. 返回 ExportFromClause 的 ExportEntriesForModule,参数 module
ExportDeclaration : export NamedExports ;
  1. 返回 NamedExports 的 ExportEntriesForModule,参数 null
ExportDeclaration : export VariableStatement
  1. entries 为新的空列表。
  2. namesVariableStatement 的 BoundNames。
  3. names 中每个 name
    1. 将 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } 追加至 entries
  4. 返回 entries
ExportDeclaration : export Declaration
  1. entries 为新的空列表。
  2. namesDeclaration 的 BoundNames。
  3. names 中每个 name
    1. 将 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } 追加至 entries
  4. 返回 entries
ExportDeclaration : export default HoistableDeclaration
  1. namesHoistableDeclaration 的 BoundNames。
  2. localNamenames 的唯一元素。
  3. 返回唯一元素为新 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" } 的列表。
ExportDeclaration : export default ClassDeclaration
  1. namesClassDeclaration 的 BoundNames。
  2. localNamenames 的唯一元素。
  3. 返回唯一元素为新 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" } 的列表。
ExportDeclaration : export default AssignmentExpression ;
  1. entry 为 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: "*default*", [[ExportName]]: "default" }。
  2. 返回 « entry »。
Note

"*default*" 在本规范中用作匿名默认导出值的合成名称。详见 该注释

16.2.3.5 静态语义:ExportEntriesForModule

The syntax-directed operation 静态语义:ExportEntriesForModule takes argument module (ModuleRequest Recordnull) and returns ExportEntry Record 列表. It is defined piecewise over the following productions:

ExportFromClause : *
  1. entry 为 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: all-but-default, [[LocalName]]: null, [[ExportName]]: null }。
  2. 返回 « entry »。
ExportFromClause : * as ModuleExportName
  1. exportNameModuleExportName 的 StringValue。
  2. entry 为 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: all, [[LocalName]]: null, [[ExportName]]: exportName }。
  3. 返回 « entry »。
NamedExports : { }
  1. 返回新的空列表。
ExportsList : ExportsList , ExportSpecifier
  1. specs1ExportsList 的 ExportEntriesForModule,参数 module
  2. specs2ExportSpecifier 的 ExportEntriesForModule,参数 module
  3. 返回 specs1specs2 的列表连接。
ExportSpecifier : ModuleExportName
  1. sourceNameModuleExportName 的 StringValue。
  2. modulenull,则
    1. localNamesourceName
    2. importNamenull
  3. 否则,
    1. localNamenull
    2. importNamesourceName
  4. 返回仅含新 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: sourceName } 的列表。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. sourceName 为第一个 ModuleExportName 的 StringValue。
  2. exportName 为第二个 ModuleExportName 的 StringValue。
  3. modulenull,则
    1. localNamesourceName
    2. importNamenull
  4. 否则,
    1. localNamenull
    2. importNamesourceName
  5. 返回仅含新 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: exportName } 的列表。

16.2.3.6 静态语义:ReferencedBindings

The syntax-directed operation 静态语义:ReferencedBindings takes no arguments and returns 解析节点列表. It is defined piecewise over the following productions:

NamedExports : { }
  1. 返回新的空列表。
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsList 的 ReferencedBindings。
  2. names2ExportSpecifier 的 ReferencedBindings。
  3. 返回 names1names2 的列表连接。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回第一个 ModuleExportName 的 ReferencedBindings。
ModuleExportName : IdentifierName
  1. 返回仅含该 IdentifierName 的列表。
ModuleExportName : StringLiteral
  1. 返回仅含该 StringLiteral 的列表。

16.2.3.7 运行时语义:求值 (Runtime Semantics: Evaluation)

ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ;
  1. 返回 empty
ExportDeclaration : export VariableStatement
  1. 返回 ? 对 VariableStatement 的 Evaluation。
ExportDeclaration : export Declaration
  1. 返回 ? 对 Declaration 的 Evaluation。
ExportDeclaration : export default HoistableDeclaration
  1. 返回 ? 对 HoistableDeclaration 的 Evaluation。
ExportDeclaration : export default ClassDeclaration
  1. value 为 ? 对 ClassDeclaration 的 BindingClassDeclarationEvaluation。
  2. classNameClassDeclaration 的 BoundNames 的唯一元素。
  3. className"*default*",则
    1. env 为正在运行的执行上下文的 LexicalEnvironment。
    2. 执行 ? InitializeBoundName("*default*", value, env)。
  4. 返回 empty
ExportDeclaration : export default AssignmentExpression ;
  1. 若 IsAnonymousFunctionDefinition(AssignmentExpression) 为 true,则
    1. value 为 ? NamedEvaluation(AssignmentExpression, "default")。
  2. 否则,
    1. rhs 为 ? Evaluation(AssignmentExpression)。
    2. value 为 ? GetValue(rhs)。
  3. env 为正在运行的执行上下文的 LexicalEnvironment。
  4. 执行 ? InitializeBoundName("*default*", value, env)。
  5. 返回 empty