# 16 ECMAScript Language: Scripts and Modules

# 16.1 Scripts

## Syntax

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

# 16.1.1 Static Semantics: Early Errors

Script : ScriptBody

- It is a Syntax Error if the LexicallyDeclaredNames of ScriptBody contains any duplicate entries.
- It is a Syntax Error if any element of the LexicallyDeclaredNames of ScriptBody also occurs in the VarDeclaredNames of ScriptBody.

ScriptBody : StatementList

- It is a Syntax Error if StatementList Contains `super` unless the source text containing `super` is eval code that is being processed by a direct eval. Additional early error rules for `super` within direct eval are defined in 19.2.1.1.
- It is a Syntax Error if StatementList Contains NewTarget unless the source text containing NewTarget is eval code that is being processed by a direct eval. Additional early error rules for NewTarget in direct eval are defined in 19.2.1.1.
- It is a Syntax Error if ContainsDuplicateLabels of StatementList with argument « » is true.
- It is a Syntax Error if ContainsUndefinedBreakTarget of StatementList with argument « » is true.
- It is a Syntax Error if ContainsUndefinedContinueTarget of StatementList with arguments « » and « » is true.
- It is a Syntax Error if AllPrivateIdentifiersValid of StatementList with argument « » is false unless the source text containing ScriptBody is eval code that is being processed by a direct eval.

# 16.1.2 Static Semantics: ScriptIsStrict

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

Script : ScriptBody opt

1. If ScriptBody is present and the Directive Prologue of ScriptBody contains a Use Strict Directive, return true.
2. Return false.

# 16.1.3 Runtime Semantics: Evaluation

Script : [empty]

1. Return undefined.

# 16.1.4 Script Records

A Script Record encapsulates information about a script being evaluated. Each script record contains the fields listed in Table 34.

Table 34: Script Record Fields

Field Name | Value Type | Meaning
--- | --- | ---
[[Realm]] | a Realm Record | The realm within which this script was created.
[[ECMAScriptCode]] | a Script Parse Node | The result of parsing the source text of this script.
[[LoadedModules]] | a List of LoadedModuleRequest Records | A map from the specifier strings imported by this script to the resolved Module Record. The list does not contain two different Records r1 and r2 such that ModuleRequestsEqual(r1, r2) is true.
[[HostDefined]] | anything (default value is empty) | Field reserved for use by host environments that need to associate additional information with a script.

# 16.1.5 ParseScript ( sourceText, realm, hostDefined )

The abstract operation ParseScript takes arguments sourceText (ECMAScript source text), realm (a Realm Record), and hostDefined (anything) and returns a Script Record or a non-empty List of SyntaxError objects. It creates a Script Record based upon the result of parsing sourceText as a Script. It performs the following steps when called:

1. Let script be ParseText(sourceText, Script).
2. If script is a List of errors, return script.
3. Return Script Record { [[Realm]]: realm, [[ECMAScriptCode]]: script, [[LoadedModules]]: « », [[HostDefined]]: hostDefined }.

Note

An implementation may parse script source text and analyse it for Early Error conditions prior to evaluation of ParseScript for that script source text. However, the reporting of any errors must be deferred until the point where this specification actually performs ParseScript upon that source text.

# 16.1.6 ScriptEvaluation ( scriptRecord )

The abstract operation ScriptEvaluation takes argument scriptRecord (a Script Record) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

1. Let globalEnv be scriptRecord.[[Realm]].[[GlobalEnv]].
2. Let scriptContext be a new ECMAScript code execution context.
3. Set the Function of scriptContext to null.
4. Set the Realm of scriptContext to scriptRecord.[[Realm]].
5. Set the ScriptOrModule of scriptContext to scriptRecord.
6. Set the VariableEnvironment of scriptContext to globalEnv.
7. Set the LexicalEnvironment of scriptContext to globalEnv.
8. Set the PrivateEnvironment of scriptContext to null.
9. Suspend the running execution context.
10. Push scriptContext onto the execution context stack; scriptContext is now the running execution context.
11. Let script be scriptRecord.[[ECMAScriptCode]].
12. Let result be Completion(GlobalDeclarationInstantiation(script, globalEnv)).
13. If result is a normal completion, then
    1. Set result to Completion(Evaluation of script).
    2. If result is a normal completion and result.[[Value]] is empty, then
       1. Set result to NormalCompletion(undefined).
14. Suspend scriptContext and remove it from the execution context stack.
15. Assert: The execution context stack is not empty.
16. Resume the context that is now on the top of the execution context stack as the running execution context.
17. Return ? result.

# 16.1.7 GlobalDeclarationInstantiation ( script, env )

The abstract operation GlobalDeclarationInstantiation takes arguments script (a Script Parse Node) and env (a Global Environment Record) and returns either a normal completion containing unused or a throw completion. script is the Script for which the execution context is being established. env is the global environment in which bindings are to be created.

Note 1

When an execution context is established for evaluating scripts, declarations are instantiated in the current global environment. Each global binding declared in the code is instantiated.

It performs the following steps when called:

1. Let lexNames be the LexicallyDeclaredNames of script.
2. Let varNames be the VarDeclaredNames of script.
3. For each element name of lexNames, do
   1. If HasLexicalDeclaration(env, name) is true, throw a SyntaxError exception.
   2. Let hasRestrictedGlobal be ? HasRestrictedGlobalProperty(env, name).
   3. NOTE: Global `var` and `function` bindings (except those that are introduced by non-strict direct eval) are non-configurable and are therefore restricted global properties.
   4. If hasRestrictedGlobal is true, throw a SyntaxError exception.
4. For each element name of varNames, do
   1. If HasLexicalDeclaration(env, name) is true, throw a SyntaxError exception.
5. Let varDeclarations be the VarScopedDeclarations of script.
6. Let functionsToInitialize be a new empty List.
7. Let declaredFunctionNames be a new empty List.
8. For each element d of varDeclarations, in reverse List order, do
   1. If d is not either a VariableDeclaration, a ForBinding, or a BindingIdentifier, then
      1. Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration.
      2. NOTE: If there are multiple function declarations for the same name, the last declaration is used.
      3. Let fn be the sole element of the BoundNames of d.
      4. If declaredFunctionNames does not contain fn, then
         1. Let fnDefinable be ? CanDeclareGlobalFunction(env, fn).
         2. If fnDefinable is false, throw a TypeError exception.
         3. Append fn to declaredFunctionNames.
         4. Insert d as the first element of functionsToInitialize.
9. Let declaredVarNames be a new empty List.
10. For each element d of varDeclarations, do
    1. If d is either a VariableDeclaration, a ForBinding, or a BindingIdentifier, then
       1. For each String vn of the BoundNames of d, do
          1. If declaredFunctionNames does not contain vn, then
             1. Let vnDefinable be ? CanDeclareGlobalVar(env, vn).
             2. If vnDefinable is false, throw a TypeError exception.
             3. If declaredVarNames does not contain vn, then
                1. Append vn to declaredVarNames.
11. NOTE: No abnormal terminations occur after this algorithm step if the global object is an ordinary object. However, if the global object is a Proxy exotic object it may exhibit behaviours that cause abnormal terminations in some of the following steps.
12. Normative Optional
    If the host is a web browser or otherwise supports Block-Level Function Declarations Web Legacy Compatibility Semantics, then
    1. Let strict be ScriptIsStrict of script.
    2. If strict is false, then
       1. Let declaredFunctionOrVarNames be the list-concatenation of declaredFunctionNames and declaredVarNames.
       2. For each FunctionDeclaration f that is directly contained in the StatementList of any Block, CaseClause, or DefaultClause x such that script Contains x is true, do
          1. Let F be the StringValue of the BindingIdentifier of f.
          2. If replacing the FunctionDeclaration f with a VariableStatement that has F as a BindingIdentifier would not produce any Early Errors for script, then
             1. If HasLexicalDeclaration(env, F) is false, then
                1. Let fnDefinable be ? CanDeclareGlobalVar(env, F).
                2. If fnDefinable is true, then
                   1. NOTE: A var binding for F is only instantiated here if it is neither a VarDeclaredName nor the name of another FunctionDeclaration.
                   2. If declaredFunctionOrVarNames does not contain F, then
                      1. Perform ? CreateGlobalVarBinding(env, F, false).
                      2. Append F to declaredFunctionOrVarNames.
                   3. When the FunctionDeclaration f is evaluated, perform the following steps in place of the FunctionDeclaration Evaluation algorithm provided in 15.2.6:
                      1. Let gEnv be the running execution context's VariableEnvironment.
                      2. Let bEnv be the running execution context's LexicalEnvironment.
                      3. Let fObj be ! bEnv.GetBindingValue(F, false).
                      4. Perform ? gEnv.SetMutableBinding(F, fObj, false).
                      5. Return unused.
13. Let lexDeclarations be the LexicallyScopedDeclarations of script.
14. Let privateEnv be null.
15. For each element d of lexDeclarations, do
    1. NOTE: Lexically declared names are only instantiated here but not initialized.
    2. For each element dn of the BoundNames of d, do
       1. If IsConstantDeclaration of d is true, then
          1. Perform ? env.CreateImmutableBinding(dn, true).
       2. Else,
          1. Perform ? env.CreateMutableBinding(dn, false).
16. For each Parse Node f of functionsToInitialize, do
    1. Let fn be the sole element of the BoundNames of f.
    2. Let fo be InstantiateFunctionObject of f with arguments env and privateEnv.
    3. Perform ? CreateGlobalFunctionBinding(env, fn, fo, false).
17. For each String vn of declaredVarNames, do
    1. Perform ? CreateGlobalVarBinding(env, vn, false).
18. Return unused.

Note 2

Early errors specified in 16.1.1 prevent name conflicts between function/var declarations and let/const/class declarations as well as redeclaration of let/const/class bindings for declaration contained within a single Script. However, such conflicts and redeclarations that span more than one Script are detected as runtime errors during GlobalDeclarationInstantiation. If any such errors are detected, no bindings are instantiated for the script. However, if the global object is defined using Proxy exotic objects then the runtime tests for conflicting declarations may be unreliable resulting in an abrupt completion and some global declarations not being instantiated. If this occurs, the code for the Script is not evaluated.

Unlike explicit var or function declarations, properties that are directly created on the global object result in global bindings that may be shadowed by let/const/class declarations.

# 16.2 Modules

## Syntax

Module : ModuleBody opt 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

- It is a Syntax Error if the LexicallyDeclaredNames of ModuleItemList contains any duplicate entries.
- It is a Syntax Error if any element of the LexicallyDeclaredNames of ModuleItemList also occurs in the VarDeclaredNames of ModuleItemList.
- It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries.
- It is a Syntax Error if any element of the ExportedBindings of ModuleItemList does not also occur in either the VarDeclaredNames of ModuleItemList, or the LexicallyDeclaredNames of ModuleItemList.
- It is a Syntax Error if ModuleItemList Contains `super`.
- It is a Syntax Error if ModuleItemList Contains NewTarget.
- It is a Syntax Error if ContainsDuplicateLabels of ModuleItemList with argument « » is true.
- It is a Syntax Error if ContainsUndefinedBreakTarget of ModuleItemList with argument « » is true.
- It is a Syntax Error if ContainsUndefinedContinueTarget of ModuleItemList with arguments « » and « » is true.
- It is a Syntax Error if AllPrivateIdentifiersValid of ModuleItemList with argument « » is false.

Note

The duplicate ExportedNames rule implies that multiple `export default` ExportDeclaration items within a ModuleBody is a Syntax Error. Additional error conditions relating to conflicting or duplicate declarations are checked during module linking prior to evaluation of a Module. If any such errors are detected the Module is not evaluated.

ModuleExportName : StringLiteral

- It is a Syntax Error if IsStringWellFormedUnicode(SV of StringLiteral) is false.

# 16.2.1.2 Static Semantics: ImportedLocalNames ( importEntries )

The abstract operation ImportedLocalNames takes argument importEntries (a List of ImportEntry Records) and returns a List of Strings. It creates a List of all of the local name bindings defined by importEntries. It performs the following steps when called:

1. Let localNames be a new empty List.
2. For each ImportEntry Record i of importEntries, do
   1. Append i.[[LocalName]] to localNames.
3. Return localNames.

# 16.2.1.3 ModuleRequest Records

A ModuleRequest Record represents the request to import a module with given import attributes. It consists of the following fields:

Table 35: ModuleRequest Record Fields

Field Name | Value Type | Meaning
--- | --- | ---
[[Specifier]] | a String | The module specifier
[[Attributes]] | a List of ImportAttribute Records | The import attributes

A LoadedModuleRequest Record represents the request to import a module together with the resulting Module Record. It consists of the same fields defined in table Table 35, with the addition of [[Module]]:

Table 36: LoadedModuleRequest Record Fields

Field Name | Value Type | Meaning
--- | --- | ---
[[Specifier]] | a String | The module specifier
[[Attributes]] | a List of ImportAttribute Records | The import attributes
[[Module]] | a Module Record | The loaded module corresponding to this module request

An ImportAttribute Record consists of the following fields:

Table 37: ImportAttribute Record Fields

Field Name | Value Type | Meaning
--- | --- | ---
[[Key]] | a String | The attribute key
[[Value]] | a String | The attribute value

# 16.2.1.3.1 ModuleRequestsEqual ( left, right )

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

1. If left.[[Specifier]] is not right.[[Specifier]], return false.
2. Let leftAttrs be left.[[Attributes]].
3. Let rightAttrs be right.[[Attributes]].
4. Let leftAttrsCount be the number of elements in leftAttrs.
5. Let rightAttrsCount be the number of elements in rightAttrs.
6. If leftAttrsCount ≠ rightAttrsCount, return false.
7. For each ImportAttribute Record l of leftAttrs, do
   1. If rightAttrs does not contain an ImportAttribute Record r such that l.[[Key]] is r.[[Key]] and l.[[Value]] is r.[[Value]], return false.
8. Return true.

# 16.2.1.4 Static Semantics: ModuleRequests

The syntax-directed operation ModuleRequests takes no arguments and returns a List of ModuleRequest Records. It is defined piecewise over the following productions:

Module : [empty]

1. Return a new empty List.

ModuleItemList : ModuleItem

1. Return the ModuleRequests of ModuleItem.

ModuleItemList : ModuleItemList ModuleItem

1. Let requests be the ModuleRequests of ModuleItemList.
2. Let additionalRequests be the ModuleRequests of ModuleItem.
3. For each ModuleRequest Record mr of additionalRequests, do
   1. If requests does not contain a ModuleRequest Record mr2 such that ModuleRequestsEqual(mr, mr2) is true, then
      1. Append mr to requests.
4. Return requests.

ModuleItem : StatementListItem

1. Return a new empty List.

ImportDeclaration : import ImportClause FromClause ;

1. Let specifier be the SV of FromClause.
2. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }.

ImportDeclaration : import ImportClause FromClause WithClause ;

1. Let specifier be the SV of FromClause.
2. Let attributes be WithClauseToAttributes of WithClause.
3. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }.

ImportDeclaration : import ModuleSpecifier ;

1. Let specifier be the SV of ModuleSpecifier.
2. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }.

ImportDeclaration : import ModuleSpecifier WithClause ;

1. Let specifier be the SV of ModuleSpecifier.
2. Let attributes be WithClauseToAttributes of WithClause.
3. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }.

ExportDeclaration : export ExportFromClause FromClause ;

1. Let specifier be the SV of FromClause.
2. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }.

ExportDeclaration : export ExportFromClause FromClause WithClause ;

1. Let specifier be the SV of FromClause.
2. Let attributes be WithClauseToAttributes of WithClause.
3. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }.

ExportDeclaration : export NamedExports ; export VariableStatement export Declaration export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;

1. Return a new empty List.

# 16.2.1.5 Abstract Module Records

A Module Record encapsulates structural information about the imports and exports of a single module. This information is used to link the imports and exports of sets of connected modules. A Module Record includes four fields that are only used when evaluating a module.

For specification purposes Module Record values are values of the Record specification type and can be thought of as existing in a simple object-oriented hierarchy where Module Record is an abstract class with both abstract and concrete subclasses. This specification defines the abstract subclass named Cyclic Module Record and its concrete subclass named Source Text Module Record. Other specifications and implementations may define additional Module Record subclasses corresponding to alternative module definition facilities that they defined.

Module Record defines the fields listed in Table 38. All Module Definition subclasses include at least those fields. Module Record also defines the abstract method list in Table 39. All Module definition subclasses must provide concrete implementations of these abstract methods.

Table 38: Module Record Fields

Field Name | Value Type | Meaning
--- | --- | ---
[[Realm]] | a Realm Record | The Realm within which this module was created.
[[Environment]] | a Module Environment Record or empty | The Environment Record containing the top level bindings for this module. This field is set when the module is linked.
[[Namespace]] | an Object or empty | The Module Namespace Object (28.3) if one has been created for this module.
[[HostDefined]] | anything (default value is undefined) | Field reserved for use by host environments that need to associate additional information with a module.

Table 39: Abstract Methods of Module Records

Method | Purpose | Definitions
--- | --- | ---
LoadRequestedModules ( [ hostDefined ] ) | The abstract method LoadRequestedModules takes optional argument hostDefined (anything) and returns a Promise. It prepares the module for linking by recursively loading all its dependencies. | Within this specification it has definitions in the following types; hosts may provide additional types with their own definitions: 16.2.1.6.1.1 Cyclic Module Record 16.2.1.8.4.1 Synthetic Module Record
GetExportedNames ( [ exportStarSet ] ) | The abstract method GetExportedNames takes optional argument exportStarSet (a List of Source Text Module Records) and returns a List of Strings. It returns a list of all names that are either directly or indirectly exported from this module. LoadRequestedModules must have completed successfully prior to invoking this method. | Within this specification it has definitions in the following types; hosts may provide additional types with their own definitions: 16.2.1.7.2.1 Source Text Module Record 16.2.1.8.4.2 Synthetic Module Record
ResolveExport ( exportName [ , resolveSet ] ) | The abstract method ResolveExport takes argument exportName (a String) and optional argument resolveSet (a List of Records with fields [[Module]] (a Module Record) and [[ExportName]] (a String)) and returns a ResolvedBinding Record, null, or ambiguous. It returns the binding of a name exported by this module. Bindings are represented by a ResolvedBinding Record, of the form { [[Module]]: Module Record, [[BindingName]]: String | namespace }. If the export is a Module Namespace Object without a direct binding in any module, [[BindingName]] will be set to namespace. It returns null if the name cannot be resolved, or ambiguous if multiple bindings were found. Each time this operation is called with a specific exportName, resolveSet pair as arguments it must return the same result. LoadRequestedModules must have completed successfully prior to invoking this method. | Within this specification it has definitions in the following types; hosts may provide additional types with their own definitions: 16.2.1.7.2.2 Source Text Module Record 16.2.1.8.4.3 Synthetic Module Record
Link ( ) | The abstract method Link takes no arguments and returns either a normal completion containing unused or a throw completion. It prepares the module for evaluation by transitively resolving all module dependencies and creating a Module Environment Record. LoadRequestedModules must have completed successfully prior to invoking this method. | Within this specification it has definitions in the following types; hosts may provide additional types with their own definitions: 16.2.1.6.1.2 Cyclic Module Record 16.2.1.8.4.4 Synthetic Module Record
Evaluate ( ) | The abstract method Evaluate takes no arguments and returns a Promise. It returns a promise for the evaluation of this module and its dependencies, resolving on successful evaluation or if it has already been evaluated successfully, and rejecting for an evaluation error or if it has already been evaluated unsuccessfully. If the promise is rejected, hosts are expected to handle the promise rejection and rethrow the evaluation error. Unless this module is a Cyclic Module Record, the returned promise must be already settled. Link must have completed successfully prior to invoking this method. | Within this specification it has definitions in the following types; hosts may provide additional types with their own definitions: 16.2.1.6.1.3 Cyclic Module Record 16.2.1.8.4.5 Synthetic Module Record

# 16.2.1.5.1 EvaluateModuleSync ( module )

The abstract operation EvaluateModuleSync takes argument module (a Module Record) and returns either a normal completion containing unused or a throw completion. It synchronously evaluates module, provided that the caller guarantees that module's evaluation will return an already settled promise. It performs the following steps when called:

1. Assert: module is not a Cyclic Module Record.
2. Let promise be module.Evaluate().
3. Assert: promise.[[PromiseState]] is either fulfilled or rejected.
4. If promise.[[PromiseState]] is rejected, then
   1. If promise.[[PromiseIsHandled]] is false, perform HostPromiseRejectionTracker(promise, "handle").
   2. Set promise.[[PromiseIsHandled]] to true.
   3. Return ThrowCompletion(promise.[[PromiseResult]]).
5. Return unused.

# 16.2.1.6 Cyclic Module Records

A Cyclic Module Record is used to represent information about a module that can participate in dependency cycles with other modules that are subclasses of the Cyclic Module Record type. Module Records that are not subclasses of the Cyclic Module Record type must not participate in dependency cycles with Source Text Module Records.

In addition to the fields defined in Table 38 Cyclic Module Records have the additional fields listed in Table 40

Table 40: Additional Fields of Cyclic Module Records

Field Name | Value Type | Meaning
--- | --- | ---
[[Status]] | new, unlinked, linking, linked, evaluating, evaluating-async, or evaluated | Initially new. Transitions to unlinked, linking, linked, evaluating, possibly evaluating-async, evaluated (in that order) as the module progresses throughout its lifecycle. evaluating-async indicates this module is queued to execute on completion of its asynchronous dependencies or it is a module whose [[HasTLA]] field is true that has been executed and is pending top-level completion.
[[EvaluationError]] | a throw completion or empty | A throw completion representing the exception that occurred during evaluation. undefined if no exception occurred or if [[Status]] is not evaluated.
[[DFSAncestorIndex]] | an integer or empty | Auxiliary field used during Link and Evaluate only. If [[Status]] is either linking or evaluating, this is either the module's depth-first traversal index or that of an "earlier" module in the same strongly connected component.
[[RequestedModules]] | a List of ModuleRequest Records | A List of the ModuleRequest Records associated with the imports in this module. The List is in source text occurrence order of the imports.
[[LoadedModules]] | a List of LoadedModuleRequest Records | A map from the specifier strings used by the module represented by this record to request the importation of a module with the relative import attributes to the resolved Module Record. The list does not contain two different Records r1 and r2 such that ModuleRequestsEqual(r1, r2) is true.
[[CycleRoot]] | a Cyclic Module Record or empty | The first visited module of the cycle, the root DFS ancestor of the strongly connected component. For a module not in a cycle, this would be the module itself. Once Evaluate has completed, a module's [[DFSAncestorIndex]] is the depth-first traversal index of its [[CycleRoot]].
[[HasTLA]] | a Boolean | Whether this module is individually asynchronous (for example, if it's a Source Text Module Record containing a top-level await). Having an asynchronous dependency does not mean this field is true. This field must not change after the module is parsed.
[[AsyncEvaluationOrder]] | unset, an integer, or done | This field is initially set to unset, and remains unset for fully synchronous modules. For modules that are either themselves asynchronous or have an asynchronous dependency, it is set to an integer that determines the order in which execution of pending modules is queued by 16.2.1.6.1.3.4. Once the pending module is executed, the field is set to done.
[[TopLevelCapability]] | a PromiseCapability Record or empty | If this module is the [[CycleRoot]] of some cycle, and Evaluate() was called on some module in that cycle, this field contains the PromiseCapability Record for that entire evaluation. It is used to settle the Promise object that is returned from the Evaluate() abstract method. This field will be empty for any dependencies of that module, unless a top-level Evaluate() has been initiated for some of those dependencies.
[[AsyncParentModules]] | a List of Cyclic Module Records | If this module or a dependency has [[HasTLA]] true, and execution is in progress, this tracks the parent importers of this module for the top-level execution job. These parent modules will not start executing before this module has successfully completed execution.
[[PendingAsyncDependencies]] | an integer or empty | If this module has any asynchronous dependencies, this tracks the number of asynchronous dependency modules remaining to execute for this module. A module with asynchronous dependencies will be executed when this field reaches 0 and there are no execution errors.

In addition to the methods defined in Table 39 Cyclic Module Records have the additional methods listed in Table 41:

Table 41: Additional Abstract Methods of Cyclic Module Records

Method | Purpose | Definitions
--- | --- | ---
InitializeEnvironment ( ) | The abstract method InitializeEnvironment takes no arguments and returns either a normal completion containing unused or a throw completion. It initializes the Environment Record of the module, including resolving all imported bindings, and creates the module's execution context. | Within this specification it has definitions in the following types; hosts may provide additional types with their own definitions: 16.2.1.7.3.1 Source Text Module Record
ExecuteModule ( [ capability ] ) | The abstract method ExecuteModule takes optional argument capability (a PromiseCapability Record) and returns either a normal completion containing unused or a throw completion. It evaluates the module's code within its execution context. If this module has true in [[HasTLA]], then a PromiseCapability Record is passed as an argument, and the method is expected to resolve or reject the given capability. In this case, the method must not throw an exception, but instead reject the PromiseCapability Record if necessary. | Within this specification it has definitions in the following types; hosts may provide additional types with their own definitions: 16.2.1.7.3.2 Source Text Module Record

A GraphLoadingState Record is a Record that contains information about the loading process of a module graph. It's used to continue loading after a call to HostLoadImportedModule. Each GraphLoadingState Record has the fields defined in Table 42:

Table 42: GraphLoadingState Record Fields

Field Name | Value Type | Meaning
--- | --- | ---
[[PromiseCapability]] | a PromiseCapability Record | The promise to resolve when the loading process finishes.
[[IsLoading]] | a Boolean | It is true if the loading process has not finished yet, neither successfully nor with an error.
[[PendingModulesCount]] | a non-negative integer | It tracks the number of pending HostLoadImportedModule calls.
[[Visited]] | a List of Cyclic Module Records | It is a list of the Cyclic Module Records that have been already loaded by the current loading process, to avoid infinite loops with circular dependencies.
[[HostDefined]] | anything (default value is empty) | It contains host-defined data to pass from the LoadRequestedModules caller to HostLoadImportedModule.

# 16.2.1.6.1 Implementation of Module Record Abstract Methods

The following are the concrete methods for Cyclic Module Record that implement the corresponding Module Record abstract methods defined in Table 39.

# 16.2.1.6.1.1 LoadRequestedModules ( [ hostDefined ] )

The LoadRequestedModules concrete method of a Cyclic Module Record module takes optional argument hostDefined (anything) and returns a Promise. It populates the [[LoadedModules]] of all the Module Records in the dependency graph of module (most of the work is done by the auxiliary function InnerModuleLoading). It takes an optional hostDefined parameter that is passed to the HostLoadImportedModule hook. It performs the following steps when called:

1. If hostDefined is not present, set hostDefined to empty.
2. Let pc be ! NewPromiseCapability(%Promise%).
3. Let state be the GraphLoadingState Record { [[IsLoading]]: true, [[PendingModulesCount]]: 1, [[Visited]]: « », [[PromiseCapability]]: pc, [[HostDefined]]: hostDefined }.
4. Perform InnerModuleLoading(state, module).
5. Return pc.[[Promise]].

Note
The hostDefined parameter can be used to pass additional information necessary to fetch the imported modules. It is used, for example, by HTML to set the correct fetch destination for `<link rel="preload" as="...">` tags. `import()` expressions never set the hostDefined parameter.

# 16.2.1.6.1.1.1 InnerModuleLoading ( state, module )

The abstract operation InnerModuleLoading takes arguments state (a GraphLoadingState Record) and module (a Module Record) and returns unused. It is used by LoadRequestedModules to recursively perform the actual loading process for module's dependency graph. It performs the following steps when called:

1. Assert: state.[[IsLoading]] is true.
2. If module is a Cyclic Module Record, module.[[Status]] is new, and state.[[Visited]] does not contain module, then
   1. Append module to state.[[Visited]].
   2. Let requestedModulesCount be the number of elements in module.[[RequestedModules]].
   3. Set state.[[PendingModulesCount]] to state.[[PendingModulesCount]] + requestedModulesCount.
   4. For each ModuleRequest Record request of module.[[RequestedModules]], do
      1. If AllImportAttributesSupported(request.[[Attributes]]) is false, then
         1. Let error be ThrowCompletion(a newly created SyntaxError object).
         2. Perform ContinueModuleLoading(state, error).
      2. Else if module.[[LoadedModules]] contains a LoadedModuleRequest Record record such that ModuleRequestsEqual(record, request) is true, then
         1. Perform InnerModuleLoading(state, record.[[Module]]).
      3. Else,
         1. Perform HostLoadImportedModule(module, request, state.[[HostDefined]], state).
         2. NOTE: HostLoadImportedModule will call FinishLoadingImportedModule, which re-enters the graph loading process through ContinueModuleLoading.
      4. If state.[[IsLoading]] is false, return unused.
3. Assert: state.[[PendingModulesCount]] ≥ 1.
4. Set state.[[PendingModulesCount]] to state.[[PendingModulesCount]] - 1.
5. If state.[[PendingModulesCount]] = 0, then
   1. Set state.[[IsLoading]] to false.
   2. For each Cyclic Module Record loaded of state.[[Visited]], do
      1. If loaded.[[Status]] is new, set loaded.[[Status]] to unlinked.
   3. Perform ! Call(state.[[PromiseCapability]].[[Resolve]], undefined, « undefined »).
6. Return unused.

# 16.2.1.6.1.1.2 ContinueModuleLoading ( state, moduleCompletion )

The abstract operation ContinueModuleLoading takes arguments state (a GraphLoadingState Record) and moduleCompletion (either a normal completion containing a Module Record or a throw completion) and returns unused. It is used to re-enter the loading process after a call to HostLoadImportedModule. It performs the following steps when called:

1. If state.[[IsLoading]] is false, return unused.
2. If moduleCompletion is a normal completion, then
   1. Perform InnerModuleLoading(state, moduleCompletion.[[Value]]).
3. Else,
   1. Set state.[[IsLoading]] to false.
   2. Perform ! Call(state.[[PromiseCapability]].[[Reject]], undefined, « moduleCompletion.[[Value]] »).
4. Return unused.

# 16.2.1.6.1.2 Link ( )

The Link concrete method of a Cyclic Module Record module takes no arguments and returns either a normal completion containing unused or a throw completion. On success, Link transitions this module's [[Status]] from unlinked to linked. On failure, an exception is thrown and this module's [[Status]] remains unlinked. (Most of the work is done by the auxiliary function InnerModuleLinking.) It performs the following steps when called:

1. Assert: module.[[Status]] is one of unlinked, linked, evaluating-async, or evaluated.
2. Let stack be a new empty List.
3. Let result be Completion(InnerModuleLinking(module, stack, 0)).
4. If result is an abrupt completion, then
   1. For each Cyclic Module Record m of stack, do
      1. Assert: m.[[Status]] is linking.
      2. Set m.[[Status]] to unlinked.
   2. Assert: module.[[Status]] is unlinked.
   3. Return ? result.
5. Assert: module.[[Status]] is one of linked, evaluating-async, or evaluated.
6. Assert: stack is empty.
7. Return unused.

# 16.2.1.6.1.2.1 InnerModuleLinking ( module, stack, index )

The abstract operation InnerModuleLinking takes arguments module (a Module Record), stack (a List of Cyclic Module Records), and index (a non-negative integer) and returns either a normal completion containing a non-negative integer or a throw completion. It is used by Link to perform the actual linking process for module, as well as recursively on all other modules in the dependency graph. The stack and index parameters, as well as a module's [[DFSAncestorIndex]] field, keep track of the depth-first search (DFS) traversal. In particular, [[DFSAncestorIndex]] is used to discover strongly connected components (SCCs), such that all modules in an SCC transition to linked together. It performs the following steps when called:

1. If module is not a Cyclic Module Record, then
   1. Perform ? module.Link().
   2. Return index.
2. If module.[[Status]] is one of linking, linked, evaluating-async, or evaluated, then
   1. Return index.
3. Assert: module.[[Status]] is unlinked.
4. Set module.[[Status]] to linking.
5. Let moduleIndex be index.
6. Set module.[[DFSAncestorIndex]] to index.
7. Set index to index + 1.
8. Append module to stack.
9. For each ModuleRequest Record request of module.[[RequestedModules]], do
   1. Let requiredModule be GetImportedModule(module, request).
   2. Set index to ? InnerModuleLinking(requiredModule, stack, index).
   3. If requiredModule is a Cyclic Module Record, then
      1. Assert: requiredModule.[[Status]] is one of linking, linked, evaluating-async, or evaluated.
      2. Assert: requiredModule.[[Status]] is linking if and only if stack contains requiredModule.
      3. If requiredModule.[[Status]] is linking, then
         1. Set module.[[DFSAncestorIndex]] to min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]]).
10. Perform ? module.InitializeEnvironment().
11. Assert: module occurs exactly once in stack.
12. Assert: module.[[DFSAncestorIndex]] ≤ moduleIndex.
13. If module.[[DFSAncestorIndex]] = moduleIndex, then
    1. Let done be false.
    2. Repeat, while done is false,
       1. Let requiredModule be the last element of stack.
       2. Remove the last element of stack.
       3. Assert: requiredModule is a Cyclic Module Record.
       4. Set requiredModule.[[Status]] to linked.
       5. If requiredModule and module are the same Module Record, set done to true.
14. Return index.

# 16.2.1.6.1.3 Evaluate ( )

The Evaluate concrete method of a Cyclic Module Record module takes no arguments and returns a Promise. Evaluate transitions this module's [[Status]] from linked to either evaluating-async or evaluated. The first time it is called on a module in a given strongly connected component, Evaluate creates and returns a Promise which resolves when the module has finished evaluating. This Promise is stored in the [[TopLevelCapability]] field of the [[CycleRoot]] for the component. Future invocations of Evaluate on any module in the component return the same Promise. (Most of the work is done by the auxiliary function InnerModuleEvaluation.) It performs the following steps when called:

1. Assert: This call to Evaluate is not happening at the same time as another call to Evaluate within the surrounding agent.
2. Assert: module.[[Status]] is one of linked, evaluating-async, or evaluated.
3. If module.[[Status]] is either evaluating-async or evaluated, then
   1. If module.[[CycleRoot]] is not empty, then
      1. Set module to module.[[CycleRoot]].
   2. Else,
      1. Assert: module.[[Status]] is evaluated and module.[[EvaluationError]] is a throw completion.
4. If module.[[TopLevelCapability]] is not empty, then
   1. Return module.[[TopLevelCapability]].[[Promise]].
5. Let stack be a new empty List.
6. Let capability be ! NewPromiseCapability(%Promise%).
7. Set module.[[TopLevelCapability]] to capability.
8. Let result be Completion(InnerModuleEvaluation(module, stack, 0)).
9. If result is an abrupt completion, then
   1. For each Cyclic Module Record m of stack, do
      1. Assert: m.[[Status]] is evaluating.
      2. Assert: m.[[AsyncEvaluationOrder]] is unset.
      3. Set m.[[Status]] to evaluated.
      4. Set m.[[EvaluationError]] to result.
   2. Assert: module.[[Status]] is evaluated.
   3. Assert: module.[[EvaluationError]] and result are the same Completion Record.
   4. Perform ! Call(capability.[[Reject]], undefined, « result.[[Value]] »).
10. Else,
    1. Assert: module.[[Status]] is either evaluating-async or evaluated.
    2. Assert: module.[[EvaluationError]] is empty.
    3. If module.[[Status]] is evaluated, then
       1. Assert: module.[[AsyncEvaluationOrder]] is either unset or done.
       2. NOTE: module.[[AsyncEvaluationOrder]] is done if and only if module had already been evaluated and that evaluation was asynchronous.
       3. Perform ! Call(capability.[[Resolve]], undefined, « undefined »).
    4. Assert: stack is empty.
11. Return capability.[[Promise]].

# 16.2.1.6.1.3.1 InnerModuleEvaluation ( module, stack, index )

The abstract operation InnerModuleEvaluation takes arguments module (a Module Record), stack (a List of Cyclic Module Records), and index (a non-negative integer) and returns either a normal completion containing a non-negative integer or a throw completion. It is used by Evaluate to perform the actual evaluation process for module, as well as recursively on all other modules in the dependency graph. The stack and index parameters, as well as module's [[DFSAncestorIndex]] field, are used the same way as in InnerModuleLinking. It performs the following steps when called:

1. If module is not a Cyclic Module Record, then
   1. Perform ? EvaluateModuleSync(module).
   2. Return index.
2. If module.[[Status]] is either evaluating-async or evaluated, then
   1. If module.[[EvaluationError]] is empty, return index.
   2. Return ? module.[[EvaluationError]].
3. If module.[[Status]] is evaluating, return index.
4. Assert: module.[[Status]] is linked.
5. Set module.[[Status]] to evaluating.
6. Let moduleIndex be index.
7. Set module.[[DFSAncestorIndex]] to index.
8. Set module.[[PendingAsyncDependencies]] to 0.
9. Set index to index + 1.
10. Append module to stack.
11. For each ModuleRequest Record request of module.[[RequestedModules]], do
    1. Let requiredModule be GetImportedModule(module, request).
    2. Set index to ? InnerModuleEvaluation(requiredModule, stack, index).
    3. If requiredModule is a Cyclic Module Record, then
       1. Assert: requiredModule.[[Status]] is one of evaluating, evaluating-async, or evaluated.
       2. Assert: requiredModule.[[Status]] is evaluating if and only if stack contains requiredModule.
       3. If requiredModule.[[Status]] is evaluating, then
          1. Set module.[[DFSAncestorIndex]] to min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]]).
       4. Else,
          1. Set requiredModule to requiredModule.[[CycleRoot]].
          2. Assert: requiredModule.[[Status]] is either evaluating-async or evaluated.
          3. If requiredModule.[[EvaluationError]] is not empty, return ? requiredModule.[[EvaluationError]].
       5. If requiredModule.[[AsyncEvaluationOrder]] is an integer, then
          1. Set module.[[PendingAsyncDependencies]] to module.[[PendingAsyncDependencies]] + 1.
          2. Append module to requiredModule.[[AsyncParentModules]].
12. If module.[[PendingAsyncDependencies]] > 0 or module.[[HasTLA]] is true, then
    1. Assert: module.[[AsyncEvaluationOrder]] is unset.
    2. Set module.[[AsyncEvaluationOrder]] to IncrementModuleAsyncEvaluationCount().
    3. If module.[[PendingAsyncDependencies]] = 0, perform ExecuteAsyncModule(module).
13. Else,
    1. Perform ? module.ExecuteModule().
14. Assert: module occurs exactly once in stack.
15. Assert: module.[[DFSAncestorIndex]] ≤ moduleIndex.
16. If module.[[DFSAncestorIndex]] = moduleIndex, then
    1. Let done be false.
    2. Repeat, while done is false,
       1. Let requiredModule be the last element of stack.
       2. Remove the last element of stack.
       3. Assert: requiredModule is a Cyclic Module Record.
       4. Assert: requiredModule.[[AsyncEvaluationOrder]] is either an integer or unset.
       5. If requiredModule.[[AsyncEvaluationOrder]] is unset, set requiredModule.[[Status]] to evaluated.
       6. Else, set requiredModule.[[Status]] to evaluating-async.
       7. If requiredModule and module are the same Module Record, set done to true.
       8. Set requiredModule.[[CycleRoot]] to module.
17. Return index.

Note 1

A module is evaluating while it is being traversed by InnerModuleEvaluation. A module is evaluated on execution completion or evaluating-async during execution if its [[HasTLA]] field is true or if it has asynchronous dependencies.

Note 2

Any modules depending on a module of an asynchronous cycle when that cycle is not evaluating will instead depend on the execution of the root of the cycle via [[CycleRoot]]. This ensures that the cycle state can be treated as a single strongly connected component through its root module state.

# 16.2.1.6.1.3.2 ExecuteAsyncModule ( module )

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

1. Assert: module.[[Status]] is either evaluating or evaluating-async.
2. Assert: module.[[HasTLA]] is true.
3. Let capability be ! NewPromiseCapability(%Promise%).
4. Let fulfilledClosure be a new Abstract Closure with no parameters that captures module and performs the following steps when called:
   1. Perform AsyncModuleExecutionFulfilled(module).
   2. Return NormalCompletion(undefined).
5. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 0, "", « »).
6. Let rejectedClosure be a new Abstract Closure with parameters (error) that captures module and performs the following steps when called:
   1. Perform AsyncModuleExecutionRejected(module, error).
   2. Return NormalCompletion(undefined).
7. Let onRejected be CreateBuiltinFunction(rejectedClosure, 0, "", « »).
8. Perform PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected).
9. Perform ! module.ExecuteModule(capability).
10. Return unused.

# 16.2.1.6.1.3.3 GatherAvailableAncestors ( module, execList )

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

1. For each Cyclic Module Record m of module.[[AsyncParentModules]], do
   1. If execList does not contain m and m.[[CycleRoot]].[[EvaluationError]] is empty, then
      1. Assert: m.[[Status]] is evaluating-async.
      2. Assert: m.[[EvaluationError]] is empty.
      3. Assert: m.[[AsyncEvaluationOrder]] is an integer.
      4. Assert: m.[[PendingAsyncDependencies]] > 0.
      5. Set m.[[PendingAsyncDependencies]] to m.[[PendingAsyncDependencies]] - 1.
      6. If m.[[PendingAsyncDependencies]] = 0, then
         1. Append m to execList.
         2. If m.[[HasTLA]] is false, perform GatherAvailableAncestors(m, execList).
2. Return unused.

Note

When an asynchronous execution for a root module is fulfilled, this function determines the list of modules which are able to synchronously execute together on this completion, populating them in execList.

# 16.2.1.6.1.3.4 AsyncModuleExecutionFulfilled ( module )

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

1. If module.[[Status]] is evaluated, then
   1. Assert: module.[[EvaluationError]] is not empty.
   2. Return unused.
2. Assert: module.[[Status]] is evaluating-async.
3. Assert: module.[[AsyncEvaluationOrder]] is an integer.
4. Assert: module.[[EvaluationError]] is empty.
5. Set module.[[AsyncEvaluationOrder]] to done.
6. Set module.[[Status]] to evaluated.
7. If module.[[TopLevelCapability]] is not empty, then
   1. Assert: module.[[CycleRoot]] and module are the same Module Record.
   2. Perform ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »).
8. Let execList be a new empty List.
9. Perform GatherAvailableAncestors(module, execList).
10. Assert: All elements of execList have their [[AsyncEvaluationOrder]] field set to an integer, [[PendingAsyncDependencies]] field set to 0, and [[EvaluationError]] field set to empty.
11. Let sortedExecList be a List whose elements are the elements of execList, sorted by their [[AsyncEvaluationOrder]] field in ascending order.
12. For each Cyclic Module Record m of sortedExecList, do
    1. If m.[[Status]] is evaluated, then
       1. Assert: m.[[EvaluationError]] is not empty.
    2. Else if m.[[HasTLA]] is true, then
       1. Perform ExecuteAsyncModule(m).
    3. Else,
       1. Let result be Completion(m.ExecuteModule()).
       2. If result is an abrupt completion, then
          1. Perform AsyncModuleExecutionRejected(m, result.[[Value]]).
       3. Else,
          1. Set m.[[AsyncEvaluationOrder]] to done.
          2. Set m.[[Status]] to evaluated.
          3. If m.[[TopLevelCapability]] is not empty, then
             1. Assert: m.[[CycleRoot]] and m are the same Module Record.
             2. Perform ! Call(m.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »).
13. Return unused.

# 16.2.1.6.1.3.5 AsyncModuleExecutionRejected ( module, error )

The abstract operation AsyncModuleExecutionRejected takes arguments module (a Cyclic Module Record) and error (an ECMAScript language value) and returns unused. It performs the following steps when called:

1. If module.[[Status]] is evaluated, then
   1. Assert: module.[[EvaluationError]] is not empty.
   2. Return unused.
2. Assert: module.[[Status]] is evaluating-async.
3. Assert: module.[[AsyncEvaluationOrder]] is an integer.
4. Assert: module.[[EvaluationError]] is empty.
5. Set module.[[EvaluationError]] to ThrowCompletion(error).
6. Set module.[[Status]] to evaluated.
7. Set module.[[AsyncEvaluationOrder]] to done.
8. NOTE: module.[[AsyncEvaluationOrder]] is set to done for symmetry with AsyncModuleExecutionFulfilled. In InnerModuleEvaluation, the value of a module's [[AsyncEvaluationOrder]] internal slot is unused when its [[EvaluationError]] internal slot is not empty.
9. If module.[[TopLevelCapability]] is not empty, then
   1. Assert: module.[[CycleRoot]] and module are the same Module Record.
   2. Perform ! Call(module.[[TopLevelCapability]].[[Reject]], undefined, « error »).
10. For each Cyclic Module Record m of module.[[AsyncParentModules]], do
    1. Perform AsyncModuleExecutionRejected(m, error).
11. Return unused.

# 16.2.1.6.2 Example Cyclic Module Record Graphs

This non-normative section gives a series of examples of the linking and evaluation of a few common module graphs, with a specific focus on how errors can occur.

First consider the following simple module graph:

Figure 2: A simple module graph

Let's first assume that there are no error conditions. When a host first calls A.LoadRequestedModules(), this will complete successfully by assumption, and recursively load the dependencies of B and C as well (respectively, C and none), and then set A.[[Status]] = B.[[Status]] = C.[[Status]] = unlinked. Then, when the host calls A.Link(), it will complete successfully (again by assumption) such that A.[[Status]] = B.[[Status]] = C.[[Status]] = linked. These preparatory steps can be performed at any time. Later, when the host is ready to incur any possible side effects of the modules, it can call A.Evaluate(), which will complete successfully, returning a Promise resolving to undefined (again by assumption), recursively having evaluated first C and then B. Each module's [[Status]] at this point will be evaluated.

Consider then cases involving linking errors, after a successful call to A.LoadRequestedModules(). If InnerModuleLinking of C succeeds but, thereafter, fails for B, for example because it imports something that C does not provide, then the original A.Link() will fail, and both A and B's [[Status]] remain unlinked. C's [[Status]] has become linked, though.

Finally, consider a case involving evaluation errors after a successful call to Link(). If InnerModuleEvaluation of C succeeds but, thereafter, fails for B, for example because B contains code that throws an exception, then the original A.Evaluate() will fail, returning a rejected Promise. The resulting exception will be recorded in both A and B's [[EvaluationError]] fields, and their [[Status]] will become evaluated. C will also become evaluated but, in contrast to A and B, will remain without an [[EvaluationError]], as it successfully completed evaluation. Storing the exception ensures that any time a host tries to reuse A or B by calling their Evaluate() method, it will encounter the same exception. (Hosts are not required to reuse Cyclic Module Records; similarly, hosts are not required to expose the exception objects thrown by these methods. However, the specification enables such uses.)

Now consider a different type of error condition:

Figure 3: A module graph with an unresolvable module

In this scenario, module A declares a dependency on some other module, but no Module Record exists for that module, i.e. HostLoadImportedModule calls FinishLoadingImportedModule with an exception when asked for it. This could occur for a variety of reasons, such as the corresponding resource not existing, or the resource existing but ParseModule returning some errors when trying to parse the resulting source text. Hosts can choose to expose the cause of failure via the completion they pass to FinishLoadingImportedModule. In any case, this exception causes a loading failure, which results in A's [[Status]] remaining new.

The difference here between loading, linking and evaluation errors is due to the following characteristic:

- Evaluation must be only performed once, as it can cause side effects; it is thus important to remember whether evaluation has already been performed, even if unsuccessfully. (In the error case, it makes sense to also remember the exception because otherwise subsequent Evaluate() calls would have to synthesize a new one.)
- Linking, on the other hand, is side-effect-free, and thus even if it fails, it can be retried at a later time with no issues.
- Loading closely interacts with the host, and it may be desirable for some of them to allow users to retry failed loads (for example, if the failure is caused by temporarily bad network conditions).

Now, consider a module graph with a cycle:

Figure 4: A cyclic module graph

Here we assume that the entry point is module A, so that the host proceeds by calling A.LoadRequestedModules(), which performs InnerModuleLoading on A. This in turn calls InnerModuleLoading on B and C. Because of the cycle, this again triggers InnerModuleLoading on A, but at this point it is a no-op since A's dependencies loading has already been triggered during this LoadRequestedModules process. When all the modules in the graph have been successfully loaded, their [[Status]] transitions from new to unlinked at the same time.

Then the host proceeds by calling A.Link(), which performs InnerModuleLinking on A. This in turn calls InnerModuleLinking on B. Because of the cycle, this again triggers InnerModuleLinking on A, but at this point it is a no-op since A.[[Status]] is already linking. B.[[Status]] itself remains linking when control gets back to A and InnerModuleLinking is triggered on C. After this returns with C.[[Status]] being linked, both A and B transition from linking to linked together; this is by design, since they form a strongly connected component. It's possible to transition the status of modules in the same SCC at the same time because during this phase the module graph is traversed with a depth-first search.

An analogous story occurs for the evaluation phase of a cyclic module graph, in the success case.

Now consider a case where A has a linking error; for example, it tries to import a binding from C that does not exist. In that case, the above steps still occur, including the early return from the second call to InnerModuleLinking on A. However, once we unwind back to the original InnerModuleLinking on A, it fails during InitializeEnvironment, namely right after C.ResolveExport(). The thrown SyntaxError exception propagates up to A.Link, which resets all modules that are currently on its stack (these are always exactly the modules that are still linking). Hence both A and B become unlinked. Note that C is left as linked.

Alternatively, consider a case where A has an evaluation error; for example, its source code throws an exception. In that case, the evaluation-time analogue of the above steps still occurs, including the early return from the second call to InnerModuleEvaluation on A. However, once we unwind back to the original InnerModuleEvaluation on A, it fails by assumption. The exception thrown propagates up to A.Evaluate(), which records the error in all modules that are currently on its stack (i.e., the modules that are still evaluating) as well as via [[AsyncParentModules]], which form a chain for modules which contain or depend on top-level `await` through the whole dependency graph through the AsyncModuleExecutionRejected algorithm. Hence both A and B become evaluated and the exception is recorded in both A and B's [[EvaluationError]] fields, while C is left as evaluated with no [[EvaluationError]].

Lastly, consider a module graph with a cycle, where all modules complete asynchronously:

Figure 5: An asynchronous cyclic module graph

Loading and linking happen as before, and all modules end up with [[Status]] set to linked.

Calling A.Evaluate() calls InnerModuleEvaluation on A, B, and D, which all transition to evaluating. Then InnerModuleEvaluation is called on A again, which is a no-op because it is already evaluating. At this point, D.[[PendingAsyncDependencies]] is 0, so ExecuteAsyncModule(D) is called and we call D.ExecuteModule with a new PromiseCapability tracking the asynchronous execution of D. We unwind back to the InnerModuleEvaluation on B, setting B.[[PendingAsyncDependencies]] to 1 and B.[[AsyncEvaluationOrder]] to 1. We unwind back to the original InnerModuleEvaluation on A, setting A.[[PendingAsyncDependencies]] to 1. In the next iteration of the loop over A's dependencies, we call InnerModuleEvaluation on C and thus on D (again a no-op) and E. As E has no dependencies and is not part of a cycle, we call ExecuteAsyncModule(E) in the same manner as D and E is immediately removed from the stack. We unwind once more to the InnerModuleEvaluation on C, setting C.[[AsyncEvaluationOrder]] to 3. Now we finish the loop over A's dependencies, set A.[[AsyncEvaluationOrder]] to 4, and remove the entire strongly connected component from the stack, transitioning all of the modules to evaluating-async at once. At this point, the fields of the modules are as given in Table 43.

Table 43: Module fields after the initial Evaluate() call

Field 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 and C) | 1 (D) | 2 (D and E) | 0 | 0

Let us assume that E finishes executing first. When that happens, AsyncModuleExecutionFulfilled is called, E.[[Status]] is set to evaluated and C.[[PendingAsyncDependencies]] is decremented to become 1. The fields of the updated modules are as given in Table 44.

Table 44: Module fields after module E finishes executing

Field Module | C | E
--- | --- | ---
[[DFSAncestorIndex]] | 0 | 4
[[Status]] | evaluating-async | evaluated
[[AsyncEvaluationOrder]] | 3 | done
[[AsyncParentModules]] | « A » | « C »
[[PendingAsyncDependencies]] | 1 (D) | 0

D is next to finish (as it was the only module that was still executing). When that happens, AsyncModuleExecutionFulfilled is called again and D.[[Status]] is set to evaluated. Its ancestors available for execution are B (whose [[AsyncEvaluationOrder]] is 1) and C (whose [[AsyncEvaluationOrder]] is 3), thus B will be handled first: B.[[PendingAsyncDependencies]] is decremented to become 0, ExecuteAsyncModule is called on B, and it starts executing. C.[[PendingAsyncDependencies]] is also decremented to become 0, and C starts executing (potentially in parallel to B if B contains an `await`). The fields of the updated modules are as given in Table 45.

Table 45: Module fields after module D finishes executing

Field Module | B | C | D
--- | --- | --- | ---
[[DFSAncestorIndex]] | 0 | 0 | 0
[[Status]] | evaluating-async | evaluating-async | evaluated
[[AsyncEvaluationOrder]] | 1 | 3 | done
[[AsyncParentModules]] | « A » | « A » | « B, C »
[[PendingAsyncDependencies]] | 0 | 0 | 0

Let us assume that C finishes executing next. When that happens, AsyncModuleExecutionFulfilled is called again, C.[[Status]] is set to evaluated and A.[[PendingAsyncDependencies]] is decremented to become 1. The fields of the updated modules are as given in Table 46.

Table 46: Module fields after module C finishes executing

Field Module | A | C
--- | --- | ---
[[DFSAncestorIndex]] | 0 | 0
[[Status]] | evaluating-async | evaluated
[[AsyncEvaluationOrder]] | 4 | done
[[AsyncParentModules]] | « » | « A »
[[PendingAsyncDependencies]] | 1 (B) | 0

Then, B finishes executing. When that happens, AsyncModuleExecutionFulfilled is called again and B.[[Status]] is set to evaluated. A.[[PendingAsyncDependencies]] is decremented to become 0, so ExecuteAsyncModule is called and it starts executing. The fields of the updated modules are as given in Table 47.

Table 47: Module fields after module B finishes executing

Field Module | A | B
--- | --- | ---
[[DFSAncestorIndex]] | 0 | 0
[[Status]] | evaluating-async | evaluated
[[AsyncEvaluationOrder]] | 4 | done
[[AsyncParentModules]] | « » | « A »
[[PendingAsyncDependencies]] | 0 | 0

Finally, A finishes executing. When that happens, AsyncModuleExecutionFulfilled is called again and A.[[Status]] is set to evaluated. At this point, the Promise in A.[[TopLevelCapability]] (which was returned from A.Evaluate()) is resolved, and this concludes the handling of this module graph. The fields of the updated module are as given in Table 48.

Table 48: Module fields after module A finishes executing

Field Module | A
--- | ---
[[DFSAncestorIndex]] | 0
[[Status]] | evaluated
[[AsyncEvaluationOrder]] | done
[[AsyncParentModules]] | « »
[[PendingAsyncDependencies]] | 0

Alternatively, consider a failure case where C fails execution and returns an error before B has finished executing. When that happens, AsyncModuleExecutionRejected is called, which sets C.[[Status]] to evaluated and C.[[EvaluationError]] to the error. It then propagates this error to all of the AsyncParentModules by performing AsyncModuleExecutionRejected on each of them. The fields of the updated modules are as given in Table 49.

Table 49: Module fields after module C finishes with an error

Field Module | A | C
--- | --- | ---
[[DFSAncestorIndex]] | 0 | 0
[[Status]] | evaluated | evaluated
[[AsyncEvaluationOrder]] | done | done
[[AsyncParentModules]] | « » | « A »
[[PendingAsyncDependencies]] | 1 (B) | 0
[[EvaluationError]] | empty | C's evaluation error

A will be rejected with the same error as C since C will call AsyncModuleExecutionRejected on A with C's error. A.[[Status]] is set to evaluated. At this point the Promise in A.[[TopLevelCapability]] (which was returned from A.Evaluate()) is rejected. The fields of the updated module are as given in Table 50.

Table 50: Module fields after module A is rejected

Field Module | A
--- | ---
[[DFSAncestorIndex]] | 0
[[Status]] | evaluated
[[AsyncEvaluationOrder]] | done
[[AsyncParentModules]] | « »
[[PendingAsyncDependencies]] | 0
[[EvaluationError]] | C's Evaluation Error

Then, B finishes executing without an error. When that happens, AsyncModuleExecutionFulfilled is called again and B.[[Status]] is set to evaluated. GatherAvailableAncestors is called on B. However, A.[[CycleRoot]] is A which has an evaluation error, so it will not be added to the returned sortedExecList and AsyncModuleExecutionFulfilled will return without further processing. Any future importer of B will resolve the rejection of B.[[CycleRoot]].[[EvaluationError]] from the evaluation error from C that was set on the cycle root A. The fields of the updated modules are as given in Table 51.

Table 51: Module fields after module B finishes executing in an erroring graph

Field Module | A | B
--- | --- | ---
[[DFSAncestorIndex]] | 0 | 0
[[Status]] | evaluated | evaluated
[[AsyncEvaluationOrder]] | 4 | 1
[[AsyncParentModules]] | « » | « A »
[[PendingAsyncDependencies]] | 0 | 0
[[EvaluationError]] | C's Evaluation Error | empty

# 16.2.1.7 Source Text Module Records

A Source Text Module Record is used to represent information about a module that was defined from ECMAScript source text (11) that was parsed using the goal symbol Module. Its fields contain digested information about the names that are imported and exported by the module, and its concrete methods use these digests to link and evaluate the module.

A Source Text Module Record can exist in a module graph with other subclasses of the abstract Module Record type, and can participate in cycles with other subclasses of the Cyclic Module Record type.

In addition to the fields defined in Table 40, Source Text Module Records have the additional fields listed in Table 52. Each of these fields is initially set in ParseModule.

Table 52: Additional Fields of Source Text Module Records

Field Name | Value Type | Meaning
--- | --- | ---
[[ECMAScriptCode]] | a Parse Node | The result of parsing the source text of this module using Module as the goal symbol.
[[Context]] | an ECMAScript code execution context or empty | The execution context associated with this module. It is empty until the module's environment has been initialized.
[[ImportMeta]] | an Object or empty | An object exposed through the `import.meta` meta property. It is empty until it is accessed by ECMAScript code.
[[ImportEntries]] | a List of ImportEntry Records | A List of ImportEntry records derived from the code of this module.
[[LocalExportEntries]] | a List of ExportEntry Records | A List of ExportEntry records derived from the code of this module that correspond to declarations that occur within the module.
[[IndirectExportEntries]] | a List of ExportEntry Records | A List of ExportEntry records derived from the code of this module that correspond to reexported imports that occur within the module or exports from `export * as namespace` declarations.
[[StarExportEntries]] | a List of ExportEntry Records | A List of ExportEntry records derived from the code of this module that correspond to `export *` declarations that occur within the module, not including `export * as namespace` declarations.

An ImportEntry Record is a Record that digests information about a single declarative import. Each ImportEntry Record has the fields defined in Table 53:

Table 53: ImportEntry Record Fields

Field Name | Value Type | Meaning
--- | --- | ---
[[ModuleRequest]] | a ModuleRequest Record | ModuleRequest Record representing the ModuleSpecifier and import attributes of the ImportDeclaration.
[[ImportName]] | a String or namespace-object | The name under which the desired binding is exported by the module identified by [[ModuleRequest]]. The value namespace-object indicates that the import request is for the target module's namespace object.
[[LocalName]] | a String | The name that is used to locally access the imported value from within the importing module.

Note 1

Table 54 gives examples of ImportEntry records fields used to represent the syntactic import forms:

Table 54 (Informative): Import Forms Mappings to ImportEntry Records

Import Statement Form | [[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";` | An ImportEntry Record is not created.

An ExportEntry Record is a Record that digests information about a single declarative export. Each ExportEntry Record has the fields defined in Table 55:

Table 55: ExportEntry Record Fields

Field Name | Value Type | Meaning
--- | --- | ---
[[ExportName]] | a String or null | The name used to export this binding by this module.
[[ModuleRequest]] | a ModuleRequest Record or null | The ModuleRequest Record representing the ModuleSpecifier and import attributes of the ExportDeclaration. null if the ExportDeclaration does not have a ModuleSpecifier.
[[ImportName]] | a String, null, all, or all-but-default | The name under which the desired binding is exported by the module identified by [[ModuleRequest]]. null if the ExportDeclaration does not have a ModuleSpecifier. all is used for `export * as ns from "mod"` declarations. all-but-default is used for `export * from "mod"` declarations.
[[LocalName]] | a String or null | The name that is used to locally access the exported value from within the importing module. null if the exported value is not locally accessible from within the module.

Note 2

Table 56 gives examples of the ExportEntry record fields used to represent the syntactic export forms:

Table 56 (Informative): Export Forms Mappings to ExportEntry Records

Export Statement Form | [[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

The following definitions specify the required concrete methods and other abstract operations for Source Text Module Records

# 16.2.1.7.1 ParseModule ( sourceText, realm, hostDefined )

The abstract operation ParseModule takes arguments sourceText (ECMAScript source text), realm (a Realm Record), and hostDefined (anything) and returns a Source Text Module Record or a non-empty List of SyntaxError objects. It creates a Source Text Module Record based upon the result of parsing sourceText as a Module. It performs the following steps when called:

1. Let body be ParseText(sourceText, Module).
2. If body is a List of errors, return body.
3. Let requestedModules be the ModuleRequests of body.
4. Let importEntries be the ImportEntries of body.
5. Let importedBoundNames be ImportedLocalNames(importEntries).
6. Let indirectExportEntries be a new empty List.
7. Let localExportEntries be a new empty List.
8. Let starExportEntries be a new empty List.
9. Let exportEntries be the ExportEntries of body.
10. For each ExportEntry Record ee of exportEntries, do
    1. If ee.[[ModuleRequest]] is null, then
       1. If importedBoundNames does not contain ee.[[LocalName]], then
          1. Append ee to localExportEntries.
       2. Else,
          1. NOTE: When exporting a binding or namespace object which was originally imported from another module, the ExportEntry Record is rewritten to match the form it would have if the binding or namespace object had been re-exported directly from the original module rather than imported then exported. This allows conflicts which arise from exporting the same binding or namespace twice under the same name through `export * from` to be ignored rather than being treated as ambiguous in step 9.e.iii of the ResolveExport concrete method of Source Text Module Records.
          2. Let ie be the element of importEntries whose [[LocalName]] is ee.[[LocalName]].
          3. If ie.[[ImportName]] is namespace-object, then
             1. NOTE: This is a re-export of an imported module namespace object.
             2. Append the ExportEntry Record { [[ModuleRequest]]: ie.[[ModuleRequest]], [[ImportName]]: all, [[LocalName]]: null, [[ExportName]]: ee.[[ExportName]] } to indirectExportEntries.
          4. Else,
             1. NOTE: This is a re-export of a single name.
             2. Append the ExportEntry Record { [[ModuleRequest]]: ie.[[ModuleRequest]], [[ImportName]]: ie.[[ImportName]], [[LocalName]]: null, [[ExportName]]: ee.[[ExportName]] } to indirectExportEntries.
    2. Else if ee.[[ImportName]] is all-but-default, then
       1. Assert: ee.[[ExportName]] is null.
       2. Append ee to starExportEntries.
    3. Else,
       1. Append ee to indirectExportEntries.
11. Let async be body Contains `await`.
12. Return 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

An implementation may parse module source text and analyse it for Early Error conditions prior to the evaluation of ParseModule for that module source text. However, the reporting of any errors must be deferred until the point where this specification actually performs ParseModule upon that source text.

# 16.2.1.7.2 Implementation of Module Record Abstract Methods

The following are the concrete methods for Source Text Module Record that implement the corresponding Module Record abstract methods defined in Table 39.

# 16.2.1.7.2.1 GetExportedNames ( [ exportStarSet ] )

The GetExportedNames concrete method of a Source Text Module Record module takes optional argument exportStarSet (a List of Source Text Module Records) and returns a List of Strings. It performs the following steps when called:

1. Assert: module.[[Status]] is not new.
2. If exportStarSet is not present, set exportStarSet to a new empty List.
3. If exportStarSet contains module, then
   1. Assert: We've reached the starting point of an `export *` circularity.
   2. Return a new empty List.
4. Append module to exportStarSet.
5. Let exportedNames be a new empty List.
6. For each ExportEntry Record e of module.[[LocalExportEntries]], do
   1. Assert: module provides the direct binding for this export.
   2. Assert: e.[[ExportName]] is not null.
   3. Append e.[[ExportName]] to exportedNames.
7. For each ExportEntry Record e of module.[[IndirectExportEntries]], do
   1. Assert: module imports a specific binding for this export.
   2. Assert: e.[[ExportName]] is not null.
   3. Append e.[[ExportName]] to exportedNames.
8. For each ExportEntry Record e of module.[[StarExportEntries]], do
   1. Assert: e.[[ModuleRequest]] is not null.
   2. Let requestedModule be GetImportedModule(module, e.[[ModuleRequest]]).
   3. Let starNames be requestedModule.GetExportedNames(exportStarSet).
   4. For each element n of starNames, do
      1. If n is not "default", then
         1. If exportedNames does not contain n, then
            1. Append n to exportedNames.
9. Return exportedNames.

Note

GetExportedNames does not filter out or throw an exception for names that have ambiguous star export bindings.

# 16.2.1.7.2.2 ResolveExport ( exportName [ , resolveSet ] )

The ResolveExport concrete method of a Source Text Module Record module takes argument exportName (a String) and optional argument resolveSet (a List of Records with fields [[Module]] (a Module Record) and [[ExportName]] (a String)) and returns a ResolvedBinding Record, null, or ambiguous.

ResolveExport attempts to resolve an imported binding to the actual defining module and local binding name. The defining module may be the module represented by the Module Record this method was invoked on or some other module that is imported by that module. The parameter resolveSet is used to detect unresolved circular import/export paths. If a pair consisting of specific Module Record and exportName is reached that is already in resolveSet, an import circularity has been encountered. Before recursively calling ResolveExport, a pair consisting of module and exportName is added to resolveSet.

If a defining module is found, a ResolvedBinding Record { [[Module]], [[BindingName]] } is returned. This record identifies the resolved binding of the originally requested export, unless this is the export of a namespace with no local binding. In this case, [[BindingName]] will be set to namespace. If no definition was found or the request is found to be circular, null is returned. If the request is found to be ambiguous, ambiguous is returned.

It performs the following steps when called:

1. Assert: module.[[Status]] is not new.
2. If resolveSet is not present, set resolveSet to a new empty List.
3. For each Record { [[Module]], [[ExportName]] } r of resolveSet, do
   1. If module and r.[[Module]] are the same Module Record and exportName is r.[[ExportName]], then
      1. Assert: This is a circular import request.
      2. Return null.
4. Append the Record { [[Module]]: module, [[ExportName]]: exportName } to resolveSet.
5. For each ExportEntry Record e of module.[[LocalExportEntries]], do
   1. If e.[[ExportName]] is exportName, then
      1. Assert: module provides the direct binding for this export.
      2. Return ResolvedBinding Record { [[Module]]: module, [[BindingName]]: e.[[LocalName]] }.
6. For each ExportEntry Record e of module.[[IndirectExportEntries]], do
   1. If e.[[ExportName]] is exportName, then
      1. Assert: e.[[ModuleRequest]] is not null.
      2. Let importedModule be GetImportedModule(module, e.[[ModuleRequest]]).
      3. If e.[[ImportName]] is all, then
         1. Assert: module does not provide the direct binding for this export.
         2. Return ResolvedBinding Record { [[Module]]: importedModule, [[BindingName]]: namespace }.
      4. Assert: module imports a specific binding for this export.
      5. Assert: e.[[ImportName]] is a String.
      6. Return importedModule.ResolveExport(e.[[ImportName]], resolveSet).
7. If exportName is "default", then
   1. Assert: A `default` export was not explicitly defined by this module.
   2. Return null.
   3. NOTE: A `default` export cannot be provided by an `export * from "mod"` declaration.
8. Let starResolution be null.
9. For each ExportEntry Record e of module.[[StarExportEntries]], do
   1. Assert: e.[[ModuleRequest]] is not null.
   2. Let importedModule be GetImportedModule(module, e.[[ModuleRequest]]).
   3. Let resolution be importedModule.ResolveExport(exportName, resolveSet).
   4. If resolution is ambiguous, return ambiguous.
   5. If resolution is not null, then
      1. Assert: resolution is a ResolvedBinding Record.
      2. If starResolution is null, then
         1. Set starResolution to resolution.
      3. Else,
         1. Assert: There is more than one `*` export that includes the requested name.
         2. If resolution.[[Module]] and starResolution.[[Module]] are not the same Module Record, return ambiguous.
         3. If resolution.[[BindingName]] is not starResolution.[[BindingName]], return ambiguous.
10. Return starResolution.

# 16.2.1.7.3 Implementation of Cyclic Module Record Abstract Methods

The following are the concrete methods for Source Text Module Record that implement the corresponding Cyclic Module Record abstract methods defined in Table 41.

# 16.2.1.7.3.1 InitializeEnvironment ( )

The InitializeEnvironment concrete method of a Source Text Module Record module takes no arguments and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

1. For each ExportEntry Record e of module.[[IndirectExportEntries]], do
   1. Assert: e.[[ExportName]] is not null.
   2. Let resolution be module.ResolveExport(e.[[ExportName]]).
   3. If resolution is either null or ambiguous, throw a SyntaxError exception.
   4. Assert: resolution is a ResolvedBinding Record.
2. Assert: All named exports from module are resolvable.
3. Let realm be module.[[Realm]].
4. Assert: realm is not undefined.
5. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]).
6. Set module.[[Environment]] to env.
7. For each ImportEntry Record in of module.[[ImportEntries]], do
   1. Let importedModule be GetImportedModule(module, in.[[ModuleRequest]]).
   2. If in.[[ImportName]] is namespace-object, then
      1. Let namespace be GetModuleNamespace(importedModule).
      2. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
      3. Perform ! env.InitializeBinding(in.[[LocalName]], namespace).
   3. Else,
      1. Let resolution be importedModule.ResolveExport(in.[[ImportName]]).
      2. If resolution is either null or ambiguous, throw a SyntaxError exception.
      3. If resolution.[[BindingName]] is namespace, then
         1. Let namespace be GetModuleNamespace(resolution.[[Module]]).
         2. Perform ! env.CreateImmutableBinding(in.[[LocalName]], true).
         3. Perform ! env.InitializeBinding(in.[[LocalName]], namespace).
      4. Else,
         1. Perform CreateImportBinding(env, in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
8. Let moduleContext be a new ECMAScript code execution context.
9. Set the Function of moduleContext to null.
10. Assert: module.[[Realm]] is not undefined.
11. Set the Realm of moduleContext to module.[[Realm]].
12. Set the ScriptOrModule of moduleContext to module.
13. Set the VariableEnvironment of moduleContext to module.[[Environment]].
14. Set the LexicalEnvironment of moduleContext to module.[[Environment]].
15. Set the PrivateEnvironment of moduleContext to null.
16. Set module.[[Context]] to moduleContext.
17. Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
18. Let code be module.[[ECMAScriptCode]].
19. Let varDeclarations be the VarScopedDeclarations of code.
20. Let declaredVarNames be a new empty List.
21. For each element d of varDeclarations, do
    1. For each element dn of the BoundNames of d, do
       1. If declaredVarNames does not contain dn, then
          1. Perform ! env.CreateMutableBinding(dn, false).
          2. Perform ! env.InitializeBinding(dn, undefined).
          3. Append dn to declaredVarNames.
22. Let lexDeclarations be the LexicallyScopedDeclarations of code.
23. Let privateEnv be null.
24. For each element d of lexDeclarations, do
    1. For each element dn of the BoundNames of d, do
       1. If IsConstantDeclaration of d is true, then
          1. Perform ! env.CreateImmutableBinding(dn, true).
       2. Else,
          1. Perform ! env.CreateMutableBinding(dn, false).
       3. If d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then
          1. Let fo be InstantiateFunctionObject of d with arguments env and privateEnv.
          2. Perform ! env.InitializeBinding(dn, fo).
25. Remove moduleContext from the execution context stack.
26. Return unused.

# 16.2.1.7.3.2 ExecuteModule ( [ capability ] )

The ExecuteModule concrete method of a Source Text Module Record module takes optional argument capability (a PromiseCapability Record) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

1. Let moduleContext be a new ECMAScript code execution context.
2. Set the Function of moduleContext to null.
3. Set the Realm of moduleContext to module.[[Realm]].
4. Set the ScriptOrModule of moduleContext to module.
5. Assert: module has been linked and declarations in its module environment have been instantiated.
6. Set the VariableEnvironment of moduleContext to module.[[Environment]].
7. Set the LexicalEnvironment of moduleContext to module.[[Environment]].
8. Suspend the running execution context.
9. If module.[[HasTLA]] is false, then
   1. Assert: capability is not present.
   2. Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
   3. Let result be Completion(Evaluation of module.[[ECMAScriptCode]]).
   4. Suspend moduleContext and remove it from the execution context stack.
   5. Resume the context that is now on the top of the execution context stack as the running execution context.
   6. If result is an abrupt completion, then
      1. Return ? result.
10. Else,
    1. Assert: capability is a PromiseCapability Record.
    2. Perform AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext).
11. Return unused.

# 16.2.1.8 Synthetic Module Records

A Synthetic Module Record is used to represent information about a module that is defined by specifications. Its exported names are statically defined at creation, while their corresponding values can change over time using SetSyntheticModuleExport. It has no imports or dependencies.

Note
A Synthetic Module Record could be used for defining a variety of module types: for example, JSON modules or CSS modules.

In addition to the fields defined in Table 38 Synthetic Module Records have the additional fields listed in Table 57.

Table 57: Additional Fields of Synthetic Module Records

Field Name | Value Type | Meaning
--- | --- | ---
[[ExportNames]] | a List of Strings | The names of the exports of the module. This list does not contain duplicates.
[[EvaluationSteps]] | an Abstract Closure | The initialization logic to perform upon evaluation of the module, taking the Synthetic Module Record as its sole argument. It must not modify [[ExportNames]]. It may return an abrupt completion.

# 16.2.1.8.1 CreateDefaultExportSyntheticModule ( defaultExport )

The abstract operation CreateDefaultExportSyntheticModule takes argument defaultExport (an ECMAScript language value) and returns a Synthetic Module Record. It creates a Synthetic Module Record whose default export is defaultExport. It performs the following steps when called:

1. Let realm be the current Realm Record.
2. Let setDefaultExport be a new Abstract Closure with parameters (module) that captures defaultExport and performs the following steps when called:
   1. Perform SetSyntheticModuleExport(module, "default", defaultExport).
   2. Return NormalCompletion(unused).
3. Return the Synthetic Module Record { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[HostDefined]]: undefined, [[ExportNames]]: « "default" », [[EvaluationSteps]]: setDefaultExport }.

# 16.2.1.8.2 ParseJSONModule ( source )

The abstract operation ParseJSONModule takes argument source (a String) and returns either a normal completion containing a Synthetic Module Record, or a throw completion. It performs the following steps when called:

1. Let json be ? ParseJSON(source).
2. Return CreateDefaultExportSyntheticModule(json).

# 16.2.1.8.3 SetSyntheticModuleExport ( module, exportName, exportValue )

The abstract operation SetSyntheticModuleExport takes arguments module (a Synthetic Module Record), exportName (a String), and exportValue (an ECMAScript language value) and returns unused. It can be used to set or change the exported value for an existing export of a Synthetic Module Record. It performs the following steps when called:

1. Assert: module.[[ExportNames]] contains exportName.
2. Let envRec be module.[[Environment]].
3. Assert: envRec is not empty.
4. Perform ! envRec.SetMutableBinding(exportName, exportValue, true).
5. Return unused.

# 16.2.1.8.4 Implementation of Module Record Abstract Methods

The following are the concrete methods for Synthetic Module Record that implement the corresponding Module Record abstract methods defined in Table 39.

# 16.2.1.8.4.1 LoadRequestedModules ( [ hostDefined ] )

The LoadRequestedModules concrete method of a Synthetic Module Record module takes optional argument hostDefined (anything) and returns a Promise. It performs the following steps when called:

1. NOTE: This implementation of LoadRequestedModules does not use hostDefined.
2. Return ! PromiseResolve(%Promise%, undefined).

Note
Synthetic Module Records have no dependencies.

# 16.2.1.8.4.2 GetExportedNames ( [ exportStarSet ] )

The GetExportedNames concrete method of a Synthetic Module Record module takes optional argument exportStarSet (a List of Source Text Module Records) and returns a List of Strings. It performs the following steps when called:

1. NOTE: This implementation of GetExportedNames does not use exportStarSet.
2. Return module.[[ExportNames]].

# 16.2.1.8.4.3 ResolveExport ( exportName [ , resolveSet ] )

The ResolveExport concrete method of a Synthetic Module Record module takes argument exportName (a String) and optional argument resolveSet (a List of Records with fields [[Module]] (a Module Record) and [[ExportName]] (a String)) and returns a ResolvedBinding Record, null, or ambiguous. It performs the following steps when called:

1. NOTE: This implementation of ResolveExport does not use resolveSet.
2. If module.[[ExportNames]] does not contain exportName, return null.
3. Return ResolvedBinding Record { [[Module]]: module, [[BindingName]]: exportName }.

# 16.2.1.8.4.4 Link ( )

The Link concrete method of a Synthetic Module Record module takes no arguments and returns a normal completion containing unused. It performs the following steps when called:

1. Let realm be module.[[Realm]].
2. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]).
3. Set module.[[Environment]] to env.
4. For each String exportName of module.[[ExportNames]], do
   1. Perform ! env.CreateMutableBinding(exportName, false).
   2. Perform ! env.InitializeBinding(exportName, undefined).
5. Return NormalCompletion(unused).

# 16.2.1.8.4.5 Evaluate ( )

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

1. Let moduleContext be a new ECMAScript code execution context.
2. Set the Function of moduleContext to null.
3. Set the Realm of moduleContext to module.[[Realm]].
4. Set the ScriptOrModule of moduleContext to module.
5. Set the VariableEnvironment of moduleContext to module.[[Environment]].
6. Set the LexicalEnvironment of moduleContext to module.[[Environment]].
7. Suspend the running execution context.
8. Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
9. Let steps be module.[[EvaluationSteps]].
10. Let result be Completion(steps(module)).
11. Suspend moduleContext and remove it from the execution context stack.
12. Resume the context that is now on the top of the execution context stack as the running execution context.
13. Let pc be ! NewPromiseCapability(%Promise%).
14. IfAbruptRejectPromise(result, pc).
15. Perform ! Call(pc.[[Resolve]], undefined, « undefined »).
16. Return pc.[[Promise]].

# 16.2.1.9 GetImportedModule ( referrer, request )

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

1. Let records be a List consisting of each LoadedModuleRequest Record r of referrer.[[LoadedModules]] such that ModuleRequestsEqual(r, request) is true.
2. Assert: records has exactly one element, since LoadRequestedModules has completed successfully on referrer prior to invoking this abstract operation.
3. Let record be the sole element of records.
4. Return record.[[Module]].

# 16.2.1.10 HostLoadImportedModule ( referrer, moduleRequest, hostDefined, payload )

The host-defined abstract operation HostLoadImportedModule takes arguments referrer (a Script Record, a Cyclic Module Record, or a Realm Record), moduleRequest (a ModuleRequest Record), hostDefined (anything), and payload (a GraphLoadingState Record or a PromiseCapability Record) and returns unused.

Note 1

An example of when referrer can be a Realm Record is in a web browser host. There, if a user clicks on a control given by

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

there will be no active script or module at the time the `import()` expression runs. More generally, this can happen in any situation where the host pushes execution contexts with null ScriptOrModule components onto the execution context stack.

An implementation of HostLoadImportedModule must conform to the following requirements:

- The host environment must perform FinishLoadingImportedModule(referrer, moduleRequest, payload, result), where result is either a normal completion containing the loaded Module Record or a throw completion, either synchronously or asynchronously.

- If this operation is called multiple times with two (referrer, moduleRequest) pairs such that:

  - the first referrer is the same as the second referrer;
  - ModuleRequestsEqual(the first moduleRequest, the second moduleRequest) is true;

  and it performs FinishLoadingImportedModule(referrer, moduleRequest, payload, result) where result is a normal completion, then it must perform FinishLoadingImportedModule(referrer, moduleRequest, payload, result) with the same result each time.

- If moduleRequest.[[Attributes]] has an entry entry such that entry.[[Key]] is "type" and entry.[[Value]] is "json", when the host environment performs FinishLoadingImportedModule(referrer, moduleRequest, payload, result), result must either be the Completion Record returned by an invocation of ParseJSONModule or a throw completion.

- The operation must treat payload as an opaque value to be passed through to FinishLoadingImportedModule.

The actual process performed is host-defined, but typically consists of performing whatever I/O operations are necessary to load the appropriate Module Record. Multiple different (referrer, moduleRequest.[[Specifier]], moduleRequest.[[Attributes]]) triples may map to the same Module Record instance. The actual mapping semantics is host-defined but typically a normalization process is applied to specifier as part of the mapping process. A typical normalization process would include actions such as expansion of relative and abbreviated path specifiers.

Note 2

The above text requires that hosts support JSON modules when imported with `type: "json"` (and HostLoadImportedModule completes normally), but it does not prohibit hosts from supporting JSON modules when imported without `type: "json"`.

# 16.2.1.11 FinishLoadingImportedModule ( referrer, moduleRequest, payload, result )

The abstract operation FinishLoadingImportedModule takes arguments referrer (a Script Record, a Cyclic Module Record, or a Realm Record), moduleRequest (a ModuleRequest Record), payload (a GraphLoadingState Record or a PromiseCapability Record), and result (either a normal completion containing a Module Record or a throw completion) and returns unused. It performs the following steps when called:

1. If result is a normal completion, then
   1. If referrer.[[LoadedModules]] contains a LoadedModuleRequest Record record such that ModuleRequestsEqual(record, moduleRequest) is true, then
      1. Assert: record.[[Module]] and result.[[Value]] are the same Module Record.
   2. Else,
      1. Append the LoadedModuleRequest Record { [[Specifier]]: moduleRequest.[[Specifier]], [[Attributes]]: moduleRequest.[[Attributes]], [[Module]]: result.[[Value]] } to referrer.[[LoadedModules]].
2. If payload is a GraphLoadingState Record, then
   1. Perform ContinueModuleLoading(payload, result).
3. Else,
   1. Perform ContinueDynamicImport(payload, result).
4. Return unused.

# 16.2.1.12 AllImportAttributesSupported ( attributes )

The abstract operation AllImportAttributesSupported takes argument attributes (a List of ImportAttribute Records) and returns a Boolean. It performs the following steps when called:

1. Let supported be HostGetSupportedImportAttributes().
2. For each ImportAttribute Record attribute of attributes, do
   1. If supported does not contain attribute.[[Key]], return false.
3. Return true.

# 16.2.1.12.1 HostGetSupportedImportAttributes ( )

The host-defined abstract operation HostGetSupportedImportAttributes takes no arguments and returns a List of Strings. It allows host environments to specify which import attributes they support. Only attributes with supported keys will be provided to the host.

An implementation of HostGetSupportedImportAttributes must conform to the following requirements:

- It must return a List of Strings, each indicating a supported attribute.
- Each time this operation is called, it must return the same List with the same contents in the same order.

The default implementation of HostGetSupportedImportAttributes is to return a new empty List.

Note
The purpose of requiring the host to specify its supported import attributes, rather than passing all attributes to the host and letting it then choose which ones it wants to handle, is to ensure that unsupported attributes are handled in a consistent way across different hosts.

# 16.2.1.13 GetModuleNamespace ( module )

The abstract operation GetModuleNamespace takes argument module (an instance of a concrete subclass of Module Record) and returns a Module Namespace Object. It retrieves the Module Namespace Object representing module's exports, lazily creating it the first time it was requested, and storing it in module.[[Namespace]] for future retrieval. It performs the following steps when called:

1. Assert: If module is a Cyclic Module Record, then module.[[Status]] is not new or unlinked.
2. Let namespace be module.[[Namespace]].
3. If namespace is empty, then
   1. Let exportedNames be module.GetExportedNames().
   2. Let unambiguousNames be a new empty List.
   3. For each element name of exportedNames, do
      1. Let resolution be module.ResolveExport(name).
      2. If resolution is a ResolvedBinding Record, append name to unambiguousNames.
   4. Set namespace to ModuleNamespaceCreate(module, unambiguousNames).
4. Return namespace.

Note

GetModuleNamespace never throws. Instead, unresolvable names are simply excluded from the namespace at this point. They will lead to a real linking error later unless they are all ambiguous star exports that are not explicitly requested anywhere.

# 16.2.1.14 Runtime Semantics: Evaluation

Module : [empty]

1. Return undefined.

ModuleBody : ModuleItemList

1. Let result be Completion(Evaluation of ModuleItemList).
2. If result is a normal completion and result.[[Value]] is empty, then
   1. Return undefined.
3. Return ? result.

ModuleItemList : ModuleItemList ModuleItem

1. Let sl be ? Evaluation of ModuleItemList.
2. Let s be Completion(Evaluation of ModuleItem).
3. Return ? UpdateEmpty(s, sl).

Note

The value of a ModuleItemList is the value of the last value-producing item in the ModuleItemList.

ModuleItem : ImportDeclaration

1. Return empty.

# 16.2.2 Imports

## Syntax

ImportDeclaration : import ImportClause FromClause WithClause opt ; import ModuleSpecifier WithClause opt ; 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

- It is a Syntax Error if the BoundNames of ImportDeclaration contains any duplicate entries.

WithClause : with { WithEntries ,opt }

- It is a Syntax Error if WithClauseToAttributes of WithClause has two different entries a and b such that a.[[Key]] is b.[[Key]].

# 16.2.2.2 Static Semantics: ImportEntries

The syntax-directed operation ImportEntries takes no arguments and returns a List of ImportEntry Records. It is defined piecewise over the following productions:

Module : [empty]

1. Return a new empty List.

ModuleItemList : ModuleItemList ModuleItem

1. Let entries1 be the ImportEntries of ModuleItemList.
2. Let entries2 be the ImportEntries of ModuleItem.
3. Return the list-concatenation of entries1 and entries2.

ModuleItem : ExportDeclaration StatementListItem

1. Return a new empty List.

ImportDeclaration : import ImportClause FromClause WithClause opt ;

1. Let module be the sole element of the ModuleRequests of ImportDeclaration.
2. Return the ImportEntriesForModule of ImportClause with argument module.

ImportDeclaration : import ModuleSpecifier WithClause opt ;

1. Return a new empty List.

# 16.2.2.3 Static Semantics: ImportEntriesForModule

The syntax-directed operation ImportEntriesForModule takes argument module (a ModuleRequest Record) and returns a List of ImportEntry Records. It is defined piecewise over the following productions:

ImportClause : ImportedDefaultBinding , NameSpaceImport

1. Let entries1 be the ImportEntriesForModule of ImportedDefaultBinding with argument module.
2. Let entries2 be the ImportEntriesForModule of NameSpaceImport with argument module.
3. Return the list-concatenation of entries1 and entries2.

ImportClause : ImportedDefaultBinding , NamedImports

1. Let entries1 be the ImportEntriesForModule of ImportedDefaultBinding with argument module.
2. Let entries2 be the ImportEntriesForModule of NamedImports with argument module.
3. Return the list-concatenation of entries1 and entries2.

ImportedDefaultBinding : ImportedBinding

1. Let localName be the sole element of the BoundNames of ImportedBinding.
2. Let defaultEntry be the ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: "default", [[LocalName]]: localName }.
3. Return « defaultEntry ».

NameSpaceImport : * as ImportedBinding

1. Let localName be the StringValue of ImportedBinding.
2. Let entry be the ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: namespace-object, [[LocalName]]: localName }.
3. Return « entry ».

NamedImports : { }

1. Return a new empty List.

ImportsList : ImportsList , ImportSpecifier

1. Let specs1 be the ImportEntriesForModule of ImportsList with argument module.
2. Let specs2 be the ImportEntriesForModule of ImportSpecifier with argument module.
3. Return the list-concatenation of specs1 and specs2.

ImportSpecifier : ImportedBinding

1. Let localName be the sole element of the BoundNames of ImportedBinding.
2. Let entry be the ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: localName, [[LocalName]]: localName }.
3. Return « entry ».

ImportSpecifier : ModuleExportName as ImportedBinding

1. Let importName be the StringValue of ModuleExportName.
2. Let localName be the StringValue of ImportedBinding.
3. Let entry be the ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName }.
4. Return « entry ».

# 16.2.2.4 Static Semantics: WithClauseToAttributes

The syntax-directed operation WithClauseToAttributes takes no arguments and returns a List of ImportAttribute Records. It is defined piecewise over the following productions:

WithClause : with { }

1. Return a new empty List.

WithClause : with { WithEntries ,opt }

1. Let attributes be WithClauseToAttributes of WithEntries.
2. Sort attributes according to the lexicographic order of their [[Key]] field, treating the value of each such field as a sequence of UTF-16 code unit values. NOTE: This sorting is observable only in that hosts are prohibited from changing behaviour based on the order in which attributes are enumerated.
3. Return attributes.

WithEntries : AttributeKey : StringLiteral

1. Let key be the PropName of AttributeKey.
2. Let entry be the ImportAttribute Record { [[Key]]: key, [[Value]]: the SV of StringLiteral }.
3. Return « entry ».

WithEntries : AttributeKey : StringLiteral , WithEntries

1. Let key be the PropName of AttributeKey.
2. Let entry be the ImportAttribute Record { [[Key]]: key, [[Value]]: the SV of StringLiteral }.
3. Let rest be WithClauseToAttributes of WithEntries.
4. Return the list-concatenation of « entry » and rest.

# 16.2.3 Exports

## Syntax

ExportDeclaration : export ExportFromClause FromClause WithClause opt ; 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 ;

- It is a Syntax Error if the ReferencedBindings of NamedExports contains any StringLiterals.
- For each IdentifierName n in the ReferencedBindings of NamedExports: It is a Syntax Error if the StringValue of n is a ReservedWord or the StringValue of n is one of "implements", "interface", "let", "package", "private", "protected", "public", or "static".

Note

The above rule means that each ReferencedBindings of NamedExports is treated as an IdentifierReference.

# 16.2.3.2 Static Semantics: ExportedBindings

The syntax-directed operation ExportedBindings takes no arguments and returns a List of Strings.

Note

ExportedBindings are the locally bound names that are explicitly associated with a Module's ExportedNames.

It is defined piecewise over the following productions:

ModuleItemList : ModuleItemList ModuleItem

1. Let names1 be the ExportedBindings of ModuleItemList.
2. Let names2 be the ExportedBindings of ModuleItem.
3. Return the list-concatenation of names1 and names2.

ModuleItem : ImportDeclaration StatementListItem

1. Return a new empty List.

ExportDeclaration : export ExportFromClause FromClause WithClause opt ;

1. Return a new empty List.

ExportDeclaration : export NamedExports ;

1. Return the ExportedBindings of NamedExports.

ExportDeclaration : export VariableStatement

1. Return the BoundNames of VariableStatement.

ExportDeclaration : export Declaration

1. Return the BoundNames of Declaration.

ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;

1. Return the BoundNames of this ExportDeclaration.

NamedExports : { }

1. Return a new empty List.

ExportsList : ExportsList , ExportSpecifier

1. Let names1 be the ExportedBindings of ExportsList.
2. Let names2 be the ExportedBindings of ExportSpecifier.
3. Return the list-concatenation of names1 and names2.

ExportSpecifier : ModuleExportName

1. Return a List whose sole element is the StringValue of ModuleExportName.

ExportSpecifier : ModuleExportName as ModuleExportName

1. Return a List whose sole element is the StringValue of the first ModuleExportName.

# 16.2.3.3 Static Semantics: ExportedNames

The syntax-directed operation ExportedNames takes no arguments and returns a List of Strings.

Note

ExportedNames are the externally visible names that a Module explicitly maps to one of its local name bindings.

It is defined piecewise over the following productions:

ModuleItemList : ModuleItemList ModuleItem

1. Let names1 be the ExportedNames of ModuleItemList.
2. Let names2 be the ExportedNames of ModuleItem.
3. Return the list-concatenation of names1 and names2.

ModuleItem : ExportDeclaration

1. Return the ExportedNames of ExportDeclaration.

ModuleItem : ImportDeclaration StatementListItem

1. Return a new empty List.

ExportDeclaration : export ExportFromClause FromClause WithClause opt ;

1. Return the ExportedNames of ExportFromClause.

ExportFromClause : *

1. Return a new empty List.

ExportFromClause : * as ModuleExportName

1. Return a List whose sole element is the StringValue of ModuleExportName.

ExportFromClause : NamedExports

1. Return the ExportedNames of NamedExports.

ExportDeclaration : export VariableStatement

1. Return the BoundNames of VariableStatement.

ExportDeclaration : export Declaration

1. Return the BoundNames of Declaration.

ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;

1. Return « "default" ».

NamedExports : { }

1. Return a new empty List.

ExportsList : ExportsList , ExportSpecifier

1. Let names1 be the ExportedNames of ExportsList.
2. Let names2 be the ExportedNames of ExportSpecifier.
3. Return the list-concatenation of names1 and names2.

ExportSpecifier : ModuleExportName

1. Return a List whose sole element is the StringValue of ModuleExportName.

ExportSpecifier : ModuleExportName as ModuleExportName

1. Return a List whose sole element is the StringValue of the second ModuleExportName.

# 16.2.3.4 Static Semantics: ExportEntries

The syntax-directed operation ExportEntries takes no arguments and returns a List of ExportEntry Records. It is defined piecewise over the following productions:

Module : [empty]

1. Return a new empty List.

ModuleItemList : ModuleItemList ModuleItem

1. Let entries1 be the ExportEntries of ModuleItemList.
2. Let entries2 be the ExportEntries of ModuleItem.
3. Return the list-concatenation of entries1 and entries2.

ModuleItem : ImportDeclaration StatementListItem

1. Return a new empty List.

ExportDeclaration : export ExportFromClause FromClause WithClause opt ;

1. Let module be the sole element of the ModuleRequests of ExportDeclaration.
2. Return the ExportEntriesForModule of ExportFromClause with argument module.

ExportDeclaration : export NamedExports ;

1. Return the ExportEntriesForModule of NamedExports with argument null.

ExportDeclaration : export VariableStatement

1. Let entries be a new empty List.
2. Let names be the BoundNames of VariableStatement.
3. For each element name of names, do
   1. Append the ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } to entries.
4. Return entries.

ExportDeclaration : export Declaration

1. Let entries be a new empty List.
2. Let names be the BoundNames of Declaration.
3. For each element name of names, do
   1. Append the ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } to entries.
4. Return entries.

ExportDeclaration : export default HoistableDeclaration

1. Let names be the BoundNames of HoistableDeclaration.
2. Let localName be the sole element of names.
3. Return a List whose sole element is a new ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }.

ExportDeclaration : export default ClassDeclaration

1. Let names be the BoundNames of ClassDeclaration.
2. Let localName be the sole element of names.
3. Return a List whose sole element is a new ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }.

ExportDeclaration : export default AssignmentExpression ;

1. Let entry be the ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: "*default*", [[ExportName]]: "default" }.
2. Return « entry ».

Note

"*default*" is used within this specification as a synthetic name for anonymous default export values. See this note for more details.

# 16.2.3.5 Static Semantics: ExportEntriesForModule

The syntax-directed operation ExportEntriesForModule takes argument module (a ModuleRequest Record or null) and returns a List of ExportEntry Records. It is defined piecewise over the following productions:

ExportFromClause : *

1. Let entry be the ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: all-but-default, [[LocalName]]: null, [[ExportName]]: null }.
2. Return « entry ».

ExportFromClause : * as ModuleExportName

1. Let exportName be the StringValue of ModuleExportName.
2. Let entry be the ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: all, [[LocalName]]: null, [[ExportName]]: exportName }.
3. Return « entry ».

NamedExports : { }

1. Return a new empty List.

ExportsList : ExportsList , ExportSpecifier

1. Let specs1 be the ExportEntriesForModule of ExportsList with argument module.
2. Let specs2 be the ExportEntriesForModule of ExportSpecifier with argument module.
3. Return the list-concatenation of specs1 and specs2.

ExportSpecifier : ModuleExportName

1. Let sourceName be the StringValue of ModuleExportName.
2. If module is null, then
   1. Let localName be sourceName.
   2. Let importName be null.
3. Else,
   1. Let localName be null.
   2. Let importName be sourceName.
4. Return a List whose sole element is a new ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: sourceName }.

ExportSpecifier : ModuleExportName as ModuleExportName

1. Let sourceName be the StringValue of the first ModuleExportName.
2. Let exportName be the StringValue of the second ModuleExportName.
3. If module is null, then
   1. Let localName be sourceName.
   2. Let importName be null.
4. Else,
   1. Let localName be null.
   2. Let importName be sourceName.
5. Return a List whose sole element is a new ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: exportName }.

# 16.2.3.6 Static Semantics: ReferencedBindings

The syntax-directed operation ReferencedBindings takes no arguments and returns a List of Parse Nodes. It is defined piecewise over the following productions:

NamedExports : { }

1. Return a new empty List.

ExportsList : ExportsList , ExportSpecifier

1. Let names1 be the ReferencedBindings of ExportsList.
2. Let names2 be the ReferencedBindings of ExportSpecifier.
3. Return the list-concatenation of names1 and names2.

ExportSpecifier : ModuleExportName as ModuleExportName

1. Return the ReferencedBindings of the first ModuleExportName.

ModuleExportName : IdentifierName

1. Return a List whose sole element is the IdentifierName.

ModuleExportName : StringLiteral

1. Return a List whose sole element is the StringLiteral.

# 16.2.3.7 Runtime Semantics: Evaluation

ExportDeclaration : export ExportFromClause FromClause WithClause opt ; export NamedExports ;

1. Return empty.

ExportDeclaration : export VariableStatement

1. Return ? Evaluation of VariableStatement.

ExportDeclaration : export Declaration

1. Return ? Evaluation of Declaration.

ExportDeclaration : export default HoistableDeclaration

1. Return ? Evaluation of HoistableDeclaration.

ExportDeclaration : export default ClassDeclaration

1. Let value be ? BindingClassDeclarationEvaluation of ClassDeclaration.
2. Let className be the sole element of the BoundNames of ClassDeclaration.
3. If className is "*default*", then
   1. Let env be the running execution context's LexicalEnvironment.
   2. Perform ? InitializeBoundName("*default*", value, env).
4. Return empty.

ExportDeclaration : export default AssignmentExpression ;

1. If IsAnonymousFunctionDefinition(AssignmentExpression) is true, then
   1. Let value be ? NamedEvaluation of AssignmentExpression with argument "default".
2. Else,
   1. Let rhs be ? Evaluation of AssignmentExpression.
   2. Let value be ? GetValue(rhs).
3. Let env be the running execution context's LexicalEnvironment.
4. Perform ? InitializeBoundName("*default*", value, env).
5. Return empty.