Multipage preference

Stage 2 Draft / September 29, 2026

Deferred re-exports

NOTE: The diff markers are on top of https://tc39.es/proposal-defer-import-eval/.

8 Syntax-Directed Operations

8.2 Scope Analysis

8.2.1 Static Semantics: BoundNames

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

ImportSpecifier : ModuleExportName as ImportedBinding AliasedImportSpecifier : ModuleExportName as ImportedBinding
  1. Return the BoundNames of ImportedBinding.
ImportSpecifier : ModuleExportName
  1. Return a List whose sole element is the StringValue of ModuleExportName.
NameSpaceImport : NamedImports as ImportedBinding
  1. Return the BoundNames of ImportedBinding.
ExportDeclaration : export defer ExplicitExportFromClause FromClause WithClauseopt ;
  1. Return a new empty List.

8.2.3 Static Semantics: IsConstantDeclaration

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

ExportDeclaration : export defer ExplicitExportFromClause FromClause WithClauseopt ;
  1. Return false.

8.2.7 Static Semantics: LexicallyScopedDeclarations

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

ExportDeclaration : export defer ExplicitExportFromClause FromClause WithClauseopt ;
  1. Return a new empty List.

10 Ordinary and Exotic Objects Behaviours

10.4 Built-in Exotic Object Internal Methods and Slots

This specification defines several kinds of built-in exotic objects. These objects generally behave similar to ordinary objects except for a few specific situations. The following exotic objects use the ordinary object internal methods except where it is explicitly specified otherwise below:

10.4.6 Module Namespace Exotic Objects

A module namespace exotic object is an exotic object that exposes the bindings exported from an ECMAScript Module (See 16.2.3). There is a one-to-one correspondence between the String-keyed own properties of a module namespace exotic object and the binding names exported by the Module. The exported bindings include any bindings that are indirectly exported using export * export items. Each String-valued own property key is the StringValue of the corresponding exported binding name. These are the only String-keyed properties of a module namespace exotic object. Each such property has the attributes { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: false }. Module namespace exotic objects are not extensible.

An object is a module namespace exotic object if its [[GetPrototypeOf]], [[SetPrototypeOf]], [[IsExtensible]], [[PreventExtensions]], [[GetOwnProperty]], [[DefineOwnProperty]], [[HasProperty]], [[Get]], [[Set]], [[Delete]], and [[OwnPropertyKeys]] internal methods use the definitions in this section, and its other essential internal methods use the definitions found in 10.1. These methods are installed by ModuleNamespaceCreate.

Module namespace exotic objects have the internal slots defined in Table 1.

10.4.6.8 [[Get]] ( propertyKey, receiver )

The [[Get]] internal method of a module namespace exotic object obj takes arguments propertyKey (a property key) and receiver (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. If IsSymbolLikeNamespaceKey(propertyKey, obj), return ! OrdinaryGet(obj, propertyKey, receiver).
  2. Let exports be ? GetModuleExportsList(obj).
  3. If exports does not contain propertyKey, return undefined.
  4. Let module be obj.[[Module]].
  5. If module is a Cyclic Module Record, perform ? EnsureDeferredExportEvaluated(module, propertyKey, « »).
  6. Let binding be module.ResolveExport(propertyKey).
  7. Assert: binding is a ResolvedBinding Record.
  8. Let targetModule be binding.[[Module]].
  9. Assert: targetModule is not undefined.
  10. If binding.[[BindingName]] is namespace, then
    1. Return GetModuleNamespace(targetModule, evaluation, all).
  11. If binding.[[BindingName]] is deferred-namespace, then
    1. Return GetModuleNamespace(targetModule, defer, all).
  12. Let targetEnv be targetModule.[[Environment]].
  13. If targetEnv is empty, throw a ReferenceError exception.
  14. Return ? targetEnv.GetBindingValue(binding.[[BindingName]], true).
Note

ResolveExport is side-effect free has no observable side effects. Each time this operation is called with a specific exportName, resolveSet pair as arguments it must return the same result. An implementation might choose to pre-compute or cache the ResolveExport results for the [[Exports]] of each module namespace exotic object.

10.4.6.8.1 EnsureDeferredExportEvaluated ( module, exportName, seen )

The abstract operation EnsureDeferredExportEvaluated takes arguments module (a Cyclic Module Record), exportName (a String), and seen (a List of Module Records) and returns either a normal completion containing unused or a throw completion. It evaluates the deferred export named exportName on the module namespace exotic object for module. It performs the following steps when called:

  1. If seen contains module, return unused.
  2. Append module to seen.
  3. Let optional be module.GetOptionalIndirectExportsModuleRequests(« exportName »).
  4. For each OptionalModuleRequest Record request of optional, do
    1. If request.[[Phase]] is evaluation, then
      1. Let requestedModule be GetImportedModule(module, request).
      2. If request.[[IsStarExport]] is true, then
        1. If requestedModule is a Cyclic Module Record, perform ? EnsureDeferredExportEvaluated(requestedModule, exportName, seen).
      3. Else,
        1. Perform ? EvaluateModuleSync(requestedModule, request.[[ImportedNames]]).
  5. Return unused.

10.4.6.9 ModuleNamespaceCreate ( module, exports, phase )

The abstract operation ModuleNamespaceCreate takes arguments module (a Module Record), exports (a List of Strings), and phase (defer or evaluation) and returns a module namespace exotic object. It is used to specify the creation of new module namespace exotic objects. It performs the following steps when called:

  1. Let internalSlotsList be the internal slots listed in Table 1.
  2. Let namespace be MakeBasicObject(internalSlotsList).
  3. Set namespace's essential internal methods to the definitions specified in 10.4.6.
  4. Set namespace.[[Module]] to module.
  5. Let sortedExports be a List whose elements are the elements of exports, sorted according to lexicographic code unit order.
  6. Set namespace.[[Exports]] to sortedExports.
  7. If phase is defer, then
    1. Assert: module.[[DeferredNamespace]] is empty.
    2. Set module.[[DeferredNamespace]] to namespace.
    3. Set namespace.[[Deferred]] to true.
    4. Let toStringTag be "Deferred Module".
  8. Else,
    1. Assert: module.[[Namespace]] is empty.
    2. Set module.[[Namespace]] to namespace.
    3. Set namespace.[[Deferred]] to false.
    4. Let toStringTag be "Module".
  9. Create an own data property of namespace named %Symbol.toStringTag% whose [[Value]] is toStringTag and whose [[Writable]], [[Enumerable]], and [[Configurable]] attributes are false.
  10. Return namespace.

13 ECMAScript Language: Expressions

13.3 Left-Hand-Side Expressions

13.3.10 Import Calls

13.3.10.1 EvaluateImportCall ( arguments, phase )

The abstract operation EvaluateImportCall takes arguments arguments (a Parse Node) and phase (defer or evaluation) and returns either a normal completion containing a Promise or an abrupt completion. It performs the following steps when called:

  1. Let referrer be GetActiveScriptOrModule().
  2. If referrer is null, set referrer to the current Realm Record.
  3. Let specifier be ? EvaluateImportCallSpecifier of arguments.
  4. Let options be ? EvaluateImportCallOptions of arguments.
  5. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  6. Let specifierString be Completion(ToString(specifier)).
  7. IfAbruptRejectPromise(specifierString, promiseCapability).
  8. Let attrs be a new empty List.
  9. Let importedNames be all.
  10. If options is not undefined, then
    1. If options is not an Object, then
      1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
      2. Return promiseCapability.[[Promise]].
    2. Let attrsObj be Completion(Get(options, "with")).
    3. IfAbruptRejectPromise(attrsObj, promiseCapability).
    4. If attrsObj is not undefined, then
      1. If attrsObj is not an Object, then
        1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
        2. Return promiseCapability.[[Promise]].
      2. Let entries be Completion(EnumerableOwnProperties(attrsObj, key+value)).
      3. IfAbruptRejectPromise(entries, promiseCapability).
      4. For each element entry of entries, do
        1. Let key be ! Get(entry, "0").
        2. Let value be ! Get(entry, "1").
        3. If key is a String, then
          1. If value is not a String, then
            1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
            2. Return promiseCapability.[[Promise]].
          2. Append the ImportAttribute Record { [[Key]]: key, [[Value]]: value } to attrs.
    5. If AllImportAttributesSupported(attrs) is false, then
      1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
      2. Return promiseCapability.[[Promise]].
    6. Sort attrs 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.
    7. Let exports be Completion(Get(options, "exports")).
    8. IfAbruptRejectPromise(exports, promiseCapability).
    9. If exports is not undefined, then
      1. If exports is not an Object, then
        1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
        2. Return promiseCapability.[[Promise]].
      2. Let iteratorRecord be Completion(GetIterator(exports, sync)).
      3. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
      4. Let names be a new empty List.
      5. Let done be false.
      6. Repeat, while done is false,
        1. Let next be Completion(IteratorStepValue(iteratorRecord)).
        2. IfAbruptRejectPromise(next, promiseCapability).
        3. If next is done, then
          1. Set done to true.
        4. Else if next is not a String, then
          1. Let error be ThrowCompletion(a newly created TypeError object).
          2. Let closeResult be Completion(IteratorClose(iteratorRecord, error)).
          3. Assert: closeResult and error are the same Completion Record.
          4. Perform ! Call(promiseCapability.[[Reject]], undefined, « error.[[Value]] »).
          5. Return promiseCapability.[[Promise]].
        5. Else if names does not contain next, then
          1. Append next to names.
      7. Set importedNames to names.
  11. Let moduleRequest be a new ModuleRequest Record { [[Specifier]]: specifierString, [[Attributes]]: attrs, [[Phase]]: phase, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: « », [[Namespace]]: importedNames } }.
  12. Perform HostLoadImportedModule(referrer, moduleRequest, empty, promiseCapability).
  13. Return promiseCapability.[[Promise]].

13.3.10.1.1 ContinueDynamicImport ( promiseCapability, moduleCompletion, phase, importedNames )

The abstract operation ContinueDynamicImport takes arguments promiseCapability (a PromiseCapability Record), moduleCompletion (either a normal completion containing a Module Record or a throw completion), phase (defer or evaluation), and importedNames (all or a List of Strings) and returns unused. It completes the process of a dynamic import originally started by an import() call, resolving or rejecting the promise returned by that call as appropriate. It performs the following steps when called:

  1. If moduleCompletion is an abrupt completion, then
    1. Perform ! Call(promiseCapability.[[Reject]], undefined, « moduleCompletion.[[Value]] »).
    2. Return unused.
  2. Let module be moduleCompletion.[[Value]].
  3. Let loadPromise be module.LoadRequestedModules(importedNames).
  4. Let rejectedClosure be a new Abstract Closure with parameters (reason) that captures promiseCapability and performs the following steps when called:
    1. Perform ! Call(promiseCapability.[[Reject]], undefined, « reason »).
    2. Return unused.
  5. Let onRejected be CreateBuiltinFunction(rejectedClosure, 1, "", « »).
  6. Let linkAndEvaluateClosure be a new Abstract Closure with no parameters that captures module, promiseCapability, phase, importedNames and onRejected and performs the following steps when called:
    1. Let link be Completion(module.Link(importedNames)).
    2. If link is an abrupt completion, then
      1. Perform ! Call(promiseCapability.[[Reject]], undefined, « link.[[Value]] »).
      2. Return unused.
    3. If importedNames is a List of Strings, then
      1. For each String name of importedNames, do
        1. Let resolvable be Completion(EnsureResolvableBinding(module, name, disallow-ambiguous)).
        2. If resolvable is an abrupt completion, then
          1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created ReferenceError object »).
          2. Return unused.
    4. Let fulfilledClosure be a new Abstract Closure with no parameters that captures module, phase, importedNames, and promiseCapability and performs the following steps when called:
      1. Let namespace be GetModuleNamespace(module, phase, importedNames).
      2. Perform ! Call(promiseCapability.[[Resolve]], undefined, « namespace »).
      3. Return unused.
    5. If phase is defer, then
      1. Let evaluationList be GatherAsynchronousTransitiveDependencies(module).
      2. If evaluationList is empty, then
        1. Perform fulfilledClosure().
        2. Return unused.
      3. Let asyncDepsEvaluationPromises be a new empty List.
      4. For each Module Record dep of evaluationList, append dep.Evaluate() to asyncDepsEvaluationPromises.
      5. Let evaluatePromise be SafePerformPromiseAll(asyncDepsEvaluationPromises).
    6. Else,
      1. Assert: phase is evaluation.
      2. Let evaluatePromise be module.Evaluate().
    7. If phase is defer, let evaluationList be GatherAsynchronousTransitiveDependencies(module).
    8. Else, let evaluationList be « module ».
    9. If module is a Cyclic Module Record, then
      1. Let optionalIndirectRequests be module.GetOptionalIndirectExportsModuleRequests(importedNames).
      2. Perform ListAppendUnique(evaluationList, GatherAsynchronousTransitiveDependenciesForRequests(module, optionalIndirectRequests, « », « »)).
    10. If evaluationList is empty, then
      1. Assert: phase is defer.
      2. Perform fulfilledClosure().
      3. Return unused.
    11. If the length of evaluationList = 1, then
      1. Let evaluatePromise be evaluationList[0].Evaluate().
    12. Else,
      1. Let evaluationPromises be a new empty List.
      2. For each Module Record dep of evaluationList, append dep.Evaluate() to evaluationPromises.
      3. Let evaluatePromise be SafePerformPromiseAll(evaluationPromises).
    13. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 0, "", « »).
    14. Perform PerformPromiseThen(evaluatePromise, onFulfilled, onRejected).
    15. Return unused.
  7. Let linkAndEvaluate be CreateBuiltinFunction(linkAndEvaluateClosure, 0, "", « »).
  8. Perform PerformPromiseThen(loadPromise, linkAndEvaluate, onRejected).
  9. Return unused.

16 ECMAScript Language: Scripts and Modules

16.2 Modules

Syntax

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

16.2.1 Module Semantics

16.2.1.1 ModuleRequest Records

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

Table 1: ModuleRequest Record Fields
Field Name Value Type Meaning
[[Specifier]] a String The module specifier
[[Attributes]] a List of ImportAttribute Records The import attributes
[[Phase]] defer or evaluation The target import phase
[[ImportedNames]] an ImportedNames Record The names imported from the requested module, used for filtering export defer declarations.

An ImportedNames Record represents the names imported from a module through a ModuleRequest Record. It has the fields listed in Table 2.

Table 2: ImportedNames Record Fields
Field Name Value Type Meaning
[[Direct]] all or a List of Strings The list of non-namespace names imported from the requested module.
[[Namespace]] all or a List of Strings The list of names imported from the requested module through a namespace object.

An OptionalModuleRequest Record represents the request to import a module due to an optional indirect export (see GetOptionalIndirectExportsModuleRequests ( importedNames )) being imported. It is a ModuleRequest Record with the following additional fields:

Table 3: OptionalModuleRequest Record Fields
Field Name Value Type Meaning
[[IsStarExport]] a Boolean Indicates whether the request is not due to an own optional export, but due to the module re-exposing the requested module's optional exports. In Source Text Module Records this is done by export * from declarations.

16.2.1.1.1 AllImportedNames ( moduleRequest )

The abstract operation AllImportedNames takes argument moduleRequest (a ModuleRequest Record) and returns all or a List of Strings. It performs the following steps when called:

  1. Return MergeImportedNames(moduleRequest.[[ImportedNames]].[[Direct]], moduleRequest.[[ImportedNames]].[[Namespace]]).

16.2.1.3 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 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 moduleRequest of additionalRequests, do
    1. If requests does not contain a ModuleRequest Record otherModuleRequest such that ModuleRequestsKeyEqual(moduleRequest, otherModuleRequest) is true and moduleRequest.[[Phase]] is otherModuleRequest.[[Phase]], then
    2. Let existingRequest be empty.
    3. For each ModuleRequest Record otherModuleRequest of requests, do
      1. If ModuleRequestsKeyEqual(moduleRequest, otherModuleRequest) is true and moduleRequest.[[Phase]] is otherModuleRequest.[[Phase]], then
        1. Assert: existingRequest is empty.
        2. Set existingRequest to otherModuleRequest.
    4. If existingRequest is empty, then
      1. Append moduleRequest to requests.
    5. Else,
      1. Set existingRequest.[[ImportedNames]].[[Direct]] to MergeImportedNames(existingRequest.[[ImportedNames]].[[Direct]], moduleRequest.[[ImportedNames]].[[Direct]]).
      2. Set existingRequest.[[ImportedNames]].[[Namespace]] to MergeImportedNames(existingRequest.[[ImportedNames]].[[Namespace]], moduleRequest.[[ImportedNames]].[[Namespace]]).
  4. Return requests.
ModuleItem : StatementListItem
  1. Return a new empty List.
ImportDeclaration : import ImportClause FromClause ;
  1. Let specifier be the SV of FromClause.
  2. Let directImportedNames be DirectImportedNames of ImportClause.
  3. Let filteredNamespaceImportedNames be FilteredNamespaceImportedNames of ImportClause.
  4. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « », [[Phase]]: evaluation, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: directImportedNames, [[Namespace]]: filteredNamespaceImportedNames } }.
ImportDeclaration : import ImportClause FromClause WithClause ;
  1. Let specifier be the SV of FromClause.
  2. Let attrs be WithClauseToAttributes of WithClause.
  3. Let directImportedNames be DirectImportedNames of ImportClause.
  4. Let filteredNamespaceImportedNames be FilteredNamespaceImportedNames of ImportClause.
  5. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs, [[Phase]]: evaluation, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: directImportedNames, [[Namespace]]: filteredNamespaceImportedNames } }.
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]]: « », [[Phase]]: evaluation, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: « », [[Namespace]]: « » } }.
ImportDeclaration : import ModuleSpecifier WithClause ;
  1. Let specifier be the SV of ModuleSpecifier.
  2. Let attrs be WithClauseToAttributes of WithClause.
  3. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs, [[Phase]]: evaluation, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: « », [[Namespace]]: « » } }.
ImportDeclaration : import defer NameSpaceImport FromClause ;
  1. Let specifier be SV of FromClause.
  2. Let directImportedNames be DirectImportedNames of NameSpaceImport.
  3. Let filteredNamespaceImportedNames be FilteredNamespaceImportedNames of NameSpaceImport.
  4. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « », [[Phase]]: defer, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: directImportedNames, [[Namespace]]: filteredNamespaceImportedNames } }.
ImportDeclaration : import defer NameSpaceImport FromClause WithClause ;
  1. Let specifier be SV of FromClause.
  2. Let attrs be WithClauseToAttributes of WithClause.
  3. Let directImportedNames be DirectImportedNames of NameSpaceImport.
  4. Let namespaceImportedNames be FilteredNamespaceImportedNames of NameSpaceImport.
  5. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs, [[Phase]]: defer, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: directImportedNames, [[Namespace]]: namespaceImportedNames } }.
ExportDeclaration : export ExportFromClause FromClause ;
  1. Let specifier be SV of FromClause.
  2. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « », [[Phase]]: evaluation }.
  3. Return a List whose sole element is ExportFromDeclarationModuleRequest(ExportFromClause, FromClause, evaluation).
ExportDeclaration : export ExportFromClause FromClause WithClause ;
  1. Let specifier be the SV of FromClause.
  2. Let attrs be WithClauseToAttributes of WithClause.
  3. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attrs, [[Phase]]: evaluation }.
  4. Return a List whose sole element is ExportFromDeclarationModuleRequest(ExportFromClause, FromClause, evaluation, WithClause).
ExportDeclaration : export defer ExplicitExportFromClause FromClause WithClauseopt ;
  1. Return a new empty List.
ExportDeclaration : export NamedExports ; export VariableStatement export Declaration export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. Return a new empty List.
Editor's Note

TODO: when integrating with import source, assert that [[ImportedNames]].[[Direct]] is an empty List.

16.2.1.3.1 ExportFromDeclarationModuleRequest ( exportFromClause, fromClause, phase [ , withClause ] )

The abstract operation ExportFromDeclarationModuleRequest takes arguments exportFromClause (an ExportFromClause or ExplicitExportFromClause Parse Node), fromClause (a FromClause Parse Node), and phase (defer or evaluation) and optional argument withClause (a WithClause Parse Node) and returns a ModuleRequest Record. It performs the following steps when called:

  1. Let directImportedNames be DirectImportedNames of exportFromClause.
  2. Let filteredNamespaceImportedNames be FilteredNamespaceImportedNames of exportFromClause.
  3. Let specifier be the SV of fromClause.
  4. If withClause is present, let attributes be WithClauseToAttributes of withClause.
  5. Else, let attributes be « ».
  6. Return the ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes, [[Phase]]: phase, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: directImportedNames, [[Namespace]]: filteredNamespaceImportedNames }}.

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 4. All Module Definition subclasses include at least those fields. Module Record also defines the abstract method list in Table 5. All Module definition subclasses must provide concrete implementations of these abstract methods.

Table 4: 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) whose [[Deferred]] slot is false, if one has been created for this module.
[[DeferredNamespace]] an Object or empty The Module Namespace Object (28.3) whose [[Deferred]] slot is true, 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 5: Abstract Methods of Module Records
Method Purpose Definitions
LoadRequestedModules ( [ importedNames [ , hostDefined ] ] )

The abstract method LoadRequestedModules takes optional arguments importedNames (all or a List of Strings) and hostDefined (anything) and returns a Promise.

It prepares the module for linking by recursively loading all its dependencies.

When this module is a Cyclic Module Record, importedNames is the list of binding names whose additional modules need to be loaded, for usage with GetOptionalIndirectExportsModuleRequests(). By default, all modules re-exported by this module through GetOptionalIndirectExportsModuleRequests() are loaded.

Within this specification it has definitions in the following types; hosts may provide additional types with their own definitions:
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:
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 ResolvedBinding Records a ResolvedBinding Record, of the form { [[Module]]: Module Record, [[BindingName]]: String | namespace| ~deferred-namespace~ }. If the export is a Module Namespace Object without a direct binding in any module, [[BindingName]] will be set to ~namespace~ or ~deferred-namespace~ (depending on whether the binding comes from a deferred import or not). 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:
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:

A ResolvedBinding Record has the following fields:

Table 6: ResolvedBinding Record Fields
Field Name Value Type Meaning
[[Module]] a Module Record The module that provides the binding
[[BindingName]] a String, namespace, or deferred-namespace The name of the binding within that module, or namespace or deferred-namespace if the export is the module's (deferred) namespace object.

16.2.1.5.1 EvaluateModuleSync ( module [ , importedNames ] )

The abstract operation EvaluateModuleSync takes argument module (a Module Record) and optional argument importedNames (an ImportedNames Record) and returns either a normal completion containing unused or a throw completion. It synchronously evaluates module, throwing before evaluating if module's evaluation would not return an already settled promise. It performs the following steps when called:

  1. If importedNames is not present, set importedNames to the ImportedNames Record { [[Direct]]: « », [[Namespace]]: « » }.
  2. Let allImportedNames be MergeImportedNames(importedNames.[[Direct]], importedNames.[[Namespace]]).
  3. If ReadyForSyncExecution(module, allImportedNames, ignore-deferred-namespace) is false, throw a TypeError exception.
  4. Let evaluationList be « module ».
  5. If module is a Cyclic Module Record, then
    1. Let previouslyImportedNames be « the Record { [[Module]]: module, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: « », [[Namespace]]: « » } } ».
    2. Let optionalIndirectRequests be GetNewOptionalIndirectExportsModuleRequests(module, the ImportedNames Record { [[Direct]]: importedNames.[[Direct]], [[Namespace]]: « » }, previouslyImportedNames).
    3. Perform BuildEvaluationList(evaluationList, module, optionalIndirectRequests, previouslyImportedNames, ignore-deferred-namespace).
  6. For each Module Record moduleToEvaluate of evaluationList, do
    1. Let promise be modulemoduleToEvaluate.Evaluate().
    2. Assert: promise.[[PromiseState]] is either fulfilled or rejected.
    3. If promise.[[PromiseState]] is rejected, then
      1. If promise.[[PromiseIsHandled]] is false, perform HostPromiseRejectionTracker(promise, "handle").
      2. Set promise.[[PromiseIsHandled]] to true.
      3. Throw promise.[[PromiseResult]].
  7. Return unused.

16.2.1.5.1.1 ReadyForSyncExecution ( module, importedNames, onDeferredNamespace [ , seen ] )

The abstract operation ReadyForSyncExecution takes arguments module (a Module Record), importedNames (all or a List of Strings), and onDeferredNamespace (ignore-deferred-namespace or gather-async-deps) and optional argument seen (a List of Module RecordsRecords with fields [[Module]] (a Cyclic Module Record) and [[ImportedNames]] (an ImportedNames Record)) and returns a Boolean. ‍It tests whether a given (module, importedNames) pair can be safely evaluated through EvaluateModuleSync. onDeferredNamespace has the same meaning as for BuildEvaluationList: this operation checks the modules that BuildEvaluationList collects when called with the same onDeferredNamespace. It performs the following steps when called:

  1. If module is not a Cyclic Module Record, return true.
  2. If seen is not present, set seen to a new empty List.
  3. If seen contains module, return true.
  4. Append module to seen.
  5. If IsModuleSCCEvaluated(module), return true.
  6. If seen does not contain a Record whose [[Module]] field is module, then
    1. Append the Record { [[Module]]: module, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: « », [[Namespace]]: « » } } to seen.
    2. If IsModuleSCCEvaluated(module) is false, then
      1. If module.[[Status]] is evaluating or evaluating-async, return false.
      2. Assert: module.[[Status]] is linked or evaluated.
      3. If module.[[HasTLA]] is true, return false.
      4. If onDeferredNamespace is gather-async-deps, let seenForAsyncDeps be seen; otherwise, let seenForAsyncDeps be a new empty List.
      5. For each ModuleRequest Record request of module.[[RequestedModules]], do
        1. Let requiredModule be GetImportedModule(module, request).
        2. If ReadyForSyncExecution(requiredModule, AllImportedNames(request), gather-async-deps, seenseenForAsyncDeps) is false, then
          1. Return false.
  7. For each ModuleRequest Record request of GetNewOptionalIndirectExportsModuleRequests(module, the ImportedNames Record { [[Direct]]: importedNames, [[Namespace]]: « » }, seen), do
    1. If request.[[Phase]] is evaluation, then
      1. Let requiredModule be GetImportedModule(module, request).
      2. If ReadyForSyncExecution(requiredModule, AllImportedNames(request), onDeferredNamespace, seen) is false, return false.
    2. Else,
      1. Assert: request.[[Phase]] is defer.
      2. If onDeferredNamespace is gather-async-deps, then
        1. If GatherAsynchronousTransitiveDependenciesForRequests(module, « request », « », CopyPreviouslyImportedNames(seen)) is not empty, return false.
      3. Else,
        1. If GatherAsynchronousTransitiveDependencies(GetImportedModule(module, request)) is not empty, return false.
  8. Return true.
Note

When onDeferredNamespace is gather-async-deps, this operation checks the asynchronous dependencies of a request with the defer phase the same way as BuildEvaluationList, including those reachable through the export defer declarations of the requested module. The requests in [[RequestedModules]] are always checked with gather-async-deps, because Evaluate always gathers the asynchronous dependencies of a module's import defer declarations, regardless of which importedNames are requested.

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 4 Cyclic Module Records have the additional fields listed in Table 7

Table 7: 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 ModuleRequestsKeyEqual(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 5 Cyclic Module Records have the additional methods listed in Table 8

Table 8: 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:
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:
GetOptionalIndirectExportsModuleRequests ( importedNames )

The abstract method GetOptionalIndirectExportsModuleRequests takes argument importedNames (all or a List of Strings) and returns a List of OptionalModuleRequest Records.

It computes the Module Requests for the optional dependencies needed to be able to import importedNames from this module, which are only loaded, linked, and evaluated when some of the names they provide are imported. In case of a Source Text Module Record, these are the dependencies specified through export defer, and the dependencies specified through export * from that may re-export export defer bindings of other modules.

This abstract method has the following default implementation:

  1. Return a new empty List.
Within this specification it has definitions in the following types; hosts may provide additional types with their own definitions:

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 9:

Table 9: 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 a List of Records with fields [[Module]] (a Cyclic Module Record) and [[ImportedNames]] (an ImportedNames Record) It is a list of the Cyclic Module Records that have been already loaded by the current loading process, together with the list of bindings that have already been imported from them, 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 LoadRequestedModules ( [ importedNames [ , hostDefined ] ] )

The LoadRequestedModules concrete method of a Cyclic Module Record module takes optional arguments importedNames (all or a List of Strings) and 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 importedNames is not present, set importedNames to all.
  2. If hostDefined is not present, set hostDefined to empty.
  3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  4. Let state be the GraphLoadingState Record { [[IsLoading]]: true, [[PendingModulesCount]]: 1, [[Visited]]: « », [[PromiseCapability]]: promiseCapability, [[HostDefined]]: hostDefined }.
  5. Perform InnerModuleLoading(state, module, importedNames).
  6. Return promiseCapability.[[Promise]].
Note 1
When the exports of the module are not observed, such as in <script type="module" src="./file.js"> tags, the host should set the importedNames parameter to « ».
Note 2
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 InnerModuleLoading ( state, module, importedNames )

The abstract operation InnerModuleLoading takes arguments state (a GraphLoadingState Record), module (a Module Record), and importedNames (all or a List of Strings) 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
  3. If module is a Cyclic Module Record, then
    1. Let requestsToLoad be a new empty List.
    2. If state.[[Visited]] does not contain a Record whose [[Module]] field is module, then
      1. If module.[[Status]] is new, set requestsToLoad to module.[[RequestedModules]].
      2. Append module to state.[[Visited]].
      3. Append the Record { [[Module]]: module, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: « », [[Namespace]]: « » } } to state.[[Visited]].
    3. Let optionalIndirectRequests be GetNewOptionalIndirectExportsModuleRequests(module, the ImportedNames Record { [[Direct]]: importedNames, [[Namespace]]: « » }, state.[[Visited]]).
    4. Set requestsToLoad to the list-concatenation of requestsToLoad and optionalIndirectRequests.
    5. Let requestedModulesCount be the number of elements in module.[[RequestedModules]]requestsToLoad.
    6. Set state.[[PendingModulesCount]] to state.[[PendingModulesCount]] + requestedModulesCount.
    7. For each ModuleRequest Record request of module.[[RequestedModules]]requestsToLoad, do
      1. If AllImportAttributesSupported(request.[[Attributes]]) is false, then
        1. Let error be ThrowCompletion(a newly created SyntaxError object).
        2. Perform ContinueModuleLoading(state, error, AllImportedNames(request)).
      2. Else if module.[[LoadedModules]] contains a LoadedModuleRequest Record record such that ModuleRequestsKeyEqual(record, request) is true, then
        1. Perform InnerModuleLoading(state, record.[[Module]], AllImportedNames(request)).
      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.
  4. Assert: state.[[PendingModulesCount]] ≥ 1.
  5. Set state.[[PendingModulesCount]] to state.[[PendingModulesCount]] - 1.
  6. If state.[[PendingModulesCount]] = 0, then
    1. Set state.[[IsLoading]] to false.
    2. For each Cyclic Module Record loaded of state.[[Visited]], do
    3. For each Record loaded of state.[[Visited]], do
      1. If loaded.[[Module]].[[Status]] is new, set loaded.[[Module]].[[Status]] to unlinked.
    4. Perform ! Call(state.[[PromiseCapability]].[[Resolve]], undefined, « undefined »).
  7. Return unused.

16.2.1.6.1.2 ContinueModuleLoading ( state, moduleCompletion, importedNames )

The abstract operation ContinueModuleLoading takes arguments state (a GraphLoadingState Record), moduleCompletion (either a normal completion containing a Module Record or a throw completion), and importedNames (all or a List of Strings) 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]], importedNames).
  3. Else,
    1. Set state.[[IsLoading]] to false.
    2. Perform ! Call(state.[[PromiseCapability]].[[Reject]], undefined, « moduleCompletion.[[Value]] »).
  4. Return unused.

16.2.1.6.2 Link ( [ importedNames ] )

The Link concrete method of a Cyclic Module Record module takes optional argument importedNames (all or a List of Strings) 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, unless the exception is thrown after this module has been linked, while linking the modules requested through its export defer declarations or while validating the namespaces that it requests or exposes. (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. If importedNames is not present, set importedNames to all.
  3. Let stack be a new empty List.
  4. Let result be Completion(InnerModuleLinking(module, stack, 0)).
  5. If result is an abrupt completion, then
    1. For each Cyclic Module Record requiredModule of stack, do
      1. Assert: requiredModule.[[Status]] is linking.
      2. Set requiredModule.[[Status]] to unlinked.
    2. Assert: module.[[Status]] is unlinked.
    3. Return ? result.
  6. Assert: module.[[Status]] is one of linked, evaluating-async, or evaluated.
  7. Assert: stack is empty.
  8. Let optionalIndirectRequests be module.GetOptionalIndirectExportsModuleRequests(importedNames).
  9. Let linkingList be « ».
  10. Let previouslyImportedNames be « ».
  11. Perform BuildLinkingList(linkingList, module, optionalIndirectRequests, previouslyImportedNames).
  12. For each Module Record requiredModule of linkingList, do
    1. Assert: If requiredModule is a Cyclic Module Record, requiredModule.[[Status]] is one of unlinked, linked, evaluating-async, or evaluated.
    2. Perform ? requiredModule.Link(« »).
  13. Perform ? ValidateAllRequestedOptionalNamespaceExports(previouslyImportedNames).
  14. Perform ? ValidateRequestedOptionalIndirectExports(module, importedNames).
  15. NOTE: All exports of module other than export defer ones are also validated by the InitializeEnvironment call on module itself, and it is not observable which one throws the SyntaxError.
  16. If importedNames is all, perform ? ValidateOwnNamespaceExports(module, all).
  17. Return unused.

16.2.1.6.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).
  10. Let linkingList be « ».
  11. Let previouslyImportedNames be « ».
  12. Perform BuildLinkingList(linkingList, module, module.[[RequestedModules]], previouslyImportedNames).
  13. For each Module Record requiredModule of linkingList, do
    1. Set index to ? InnerModuleLinking(requiredModule, stack, index).
    2. 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]]).
  14. Perform ? module.InitializeEnvironment().
  15. Perform ? ValidateAllRequestedOptionalNamespaceExports(previouslyImportedNames).
  16. Assert: module occurs exactly once in stack.
  17. Assert: module.[[DFSAncestorIndex]] ≤ moduleIndex.
  18. 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.
  19. Return index.

16.2.1.6.2.2 BuildLinkingList ( linkingList, referrer, moduleRequests, previouslyImportedNames )

The abstract operation BuildLinkingList takes arguments linkingList (a List of Module Records), referrer (a Cyclic Module Record), moduleRequests (a List of ModuleRequest Records), and previouslyImportedNames (a List of Records with fields [[Module]] (a Cyclic Module Record) and [[ImportedNames]] (an ImportedNames Record)) and returns unused. It performs the following steps when called:

  1. For each ModuleRequest Record request of moduleRequests, do
    1. Let requiredModule be GetImportedModule(referrer, request).
    2. If linkingList does not contain requiredModule, then
      1. Append requiredModule to linkingList.
      2. If requiredModule is a Cyclic Module Record, then
        1. Assert: previouslyImportedNames does not contain a Record whose [[Module]] field is requiredModule.
        2. Append the Record { [[Module]]: requiredModule, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: « », [[Namespace]]: « » } } to previouslyImportedNames.
    3. If requiredModule is a Cyclic Module Record, then
      1. Let optionalIndirectRequests be GetNewOptionalIndirectExportsModuleRequests(requiredModule, request.[[ImportedNames]], previouslyImportedNames).
      2. Perform BuildLinkingList(linkingList, requiredModule, optionalIndirectRequests, previouslyImportedNames).
  2. Return unused.

16.2.1.6.2.3 ValidateAllRequestedOptionalNamespaceExports ( previouslyImportedNames )

The abstract operation ValidateAllRequestedOptionalNamespaceExports takes argument previouslyImportedNames (a List of Records with fields [[Module]] (a Cyclic Module Record) and [[ImportedNames]] (an ImportedNames Record)) and returns either a normal completion containing unused or a throw completion. It is performed once BuildLinkingList has collected in previouslyImportedNames the names requested from each module while linking, and it validates the export defer declarations that those requests make reachable. It performs the following steps when called:

  1. For each Record { [[Module]], [[ImportedNames]] } r of previouslyImportedNames, do
    1. Let names be r.[[ImportedNames]].
    2. If names.[[Namespace]] is all, perform ? ValidateOwnNamespaceExports(r.[[Module]], all).
    3. Perform ? ValidateRequestedOptionalIndirectExports(r.[[Module]], MergeImportedNames(names.[[Direct]], names.[[Namespace]])).
  2. Return unused.

16.2.1.6.2.4 ValidateOwnNamespaceExports ( module, names )

The abstract operation ValidateOwnNamespaceExports takes arguments module (a Module Record) and names (all or a List of Strings) and returns either a normal completion containing unused or a throw completion. It is performed when module is requested for a namespace object, either for all of its exports (when names is all) or for a filtered namespace object containing names. It throws a SyntaxError exception if any of those names cannot be resolved, or if any of the names in a List names is ambiguous. It performs the following steps when called:

  1. If names is all, then
    1. If module is not a Cyclic Module Record, return unused.
    2. NOTE: Only Cyclic Module Records can have invalid optional indirect exports.
    3. For each String name of module.GetExportedNames(), do
      1. Perform ? EnsureResolvableBinding(module, name, allow-ambiguous).
  2. Else,
    1. For each String name of names, do
      1. Perform ? EnsureResolvableBinding(module, name, disallow-ambiguous).
  3. Return unused.
Note

ValidateOwnNamespaceExports has no observable side effects other than throwing. Each call with the same arguments produces the same result. An implementation might choose to remember which modules and names have already been successfully validated, and skip validating them again.

16.2.1.6.2.5 ValidateRequestedOptionalIndirectExports ( module, importedNames )

The abstract operation ValidateRequestedOptionalIndirectExports takes arguments module (a Cyclic Module Record) and importedNames (all or a List of Strings) and returns either a normal completion containing unused or a throw completion. It validates the optional indirect exports of module (its export defer declarations) whose export name is in importedNames: each of them must be resolvable and not ambiguous, and the filtered namespaces re-exported through export defer { ... } as ns from "mod" declarations must only contain resolvable and not ambiguous names. It performs the following steps when called:

  1. If importedNames is all, set importedNames to module.GetExportedNames().
  2. For each String name of importedNames, do
    1. For each OptionalModuleRequest Record request of module.GetOptionalIndirectExportsModuleRequests(« name »), do
      1. If request.[[IsStarExport]] is false, then
        1. Perform ? EnsureResolvableBinding(module, name, disallow-ambiguous).
        2. If request.[[ImportedNames]].[[Namespace]] is a List, then
          1. Perform ? ValidateOwnNamespaceExports(GetImportedModule(module, request), request.[[ImportedNames]].[[Namespace]]).
  3. Return unused.
Note

ValidateRequestedOptionalIndirectExports has no observable side effects other than throwing. Each call with the same arguments produces the same result. An implementation might choose to remember which modules and names have already been successfully validated, and skip validating them again.

16.2.1.6.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: None of module or any of its recursive dependencies have [[Status]] set to evaluating, linking, unlinked, or new.
  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 promiseCapability be ! NewPromiseCapability(%Promise%).
  7. Set module.[[TopLevelCapability]] to promiseCapability.
  8. Let result be Completion(InnerModuleEvaluation(module, stack, 0)).
  9. If result is an abrupt completion, then
    1. For each Cyclic Module Record requiredModule of stack, do
      1. Assert: requiredModule.[[Status]] is evaluating.
      2. Set requiredModule.[[Status]] to evaluated.
      3. Set requiredModule.[[EvaluationError]] to result.
    2. Assert: module.[[Status]] is evaluated.
    3. Assert: module.[[EvaluationError]] and result are the same Completion Record.
    4. Perform ! Call(promiseCapability.[[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(promiseCapability.[[Resolve]], undefined, « undefined »).
    4. Assert: stack is empty.
  11. Return promiseCapability.[[Promise]].
Note
Unlike Link, Evaluate does not take an importedNames parameter: it evaluates the module and its dependencies, but not the modules re-exported through the module's own export defer declarations. Those are evaluated by the caller when needed: ContinueDynamicImport evaluates in advance their asynchronous dependencies, and EvaluateModuleSync synchronously evaluates them when the corresponding binding is accessed.

16.2.1.6.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. Otherwise, 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. Let evaluationList be a new empty List.
  11. For each ModuleRequest Record request of module.[[RequestedModules]], do
    1. Let requiredModule be GetImportedModule(module, request).
    2. If request.[[Phase]] is defer, then
      1. Let additionalModules be GatherAsynchronousTransitiveDependencies(requiredModule).
      2. For each Module Record additionalModule of additionalModules, do
        1. If evaluationList does not contain additionalModule, then
          1. Append additionalModule to evaluationList.
    3. Else if evaluationList does not contain requiredModule, then
      1. Append requiredModule to evaluationList.
  12. Let evaluationList be « ».
  13. Perform BuildEvaluationList(evaluationList, module, module.[[RequestedModules]], « », gather-async-deps).
  14. Append module to stack.
  15. For each Module Record requiredModule of evaluationList, do
    1. Set index to ? InnerModuleEvaluation(requiredModule, stack, index).
    2. 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]].
  16. 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).
  17. Else,
    1. Perform ? module.ExecuteModule().
  18. Assert: module occurs exactly once in stack.
  19. Assert: module.[[DFSAncestorIndex]] ≤ moduleIndex.
  20. 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. Otherwise, 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.
  21. 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.3.2 BuildEvaluationList ( evaluationList, referrer, moduleRequests, previouslyImportedNames, onDeferredNamespace )

The abstract operation BuildEvaluationList takes arguments evaluationList (a List of Module Records), referrer (a Cyclic Module Record), moduleRequests (a List of ModuleRequest Records), previouslyImportedNames (a List of Records with fields [[Module]] (a Cyclic Module Record) and [[ImportedNames]] (an ImportedNames Record)), and onDeferredNamespace (ignore-deferred-namespace or gather-async-deps) and returns unused. It collects in evaluationList, in depth-first pre-order, the modules that need to be evaluated for moduleRequests and for the export defer and export * from declarations reachable through them. If onDeferredNamespace is gather-async-deps, it also collects the asynchronous transitive dependencies of modules that are imported with the defer phase or through a namespace object, so that they are already evaluated when those modules are later evaluated synchronously. If onDeferredNamespace is ignore-deferred-namespace, requests with the defer phase are ignored. It performs the following steps when called:

  1. For each ModuleRequest Record request of moduleRequests, do
    1. If request.[[Phase]] is evaluation or onDeferredNamespace is gather-async-deps, then
      1. Let requiredModule be GetImportedModule(referrer, request).
      2. If request.[[Phase]] is defer, then
        1. NOTE: The names requested while gathering the asynchronous dependencies of a deferred module are recorded in a copy of previouslyImportedNames, because the modules re-exporting them are not being scheduled for evaluation: a later request with the evaluation phase for the same names must still add them to evaluationList.
        2. Perform ListAppendUnique(evaluationList, GatherAsynchronousTransitiveDependencies(requiredModule, « », CopyPreviouslyImportedNames(previouslyImportedNames))).
      3. Else if evaluationList does not contain requiredModule, then
        1. Append requiredModule to evaluationList.
      4. If requiredModule is a Cyclic Module Record, then
        1. If previouslyImportedNames does not contain a Record whose [[Module]] field is requiredModule, then
          1. Append the Record { [[Module]]: requiredModule, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: « », [[Namespace]]: « » } } to previouslyImportedNames.
        2. If onDeferredNamespace is gather-async-deps and request.[[ImportedNames]].[[Namespace]] is either all or not empty, then
          1. Let namespaceOptionalIndirectRequests be GetNewOptionalIndirectExportsModuleRequests(requiredModule, the ImportedNames Record { [[Direct]]: « », [[Namespace]]: request.[[ImportedNames]].[[Namespace]] }, previouslyImportedNames).
          2. Let seen be a new empty List.
          3. Let copyPreviouslyImportedNames be CopyPreviouslyImportedNames(previouslyImportedNames).
          4. Perform ListAppendUnique(evaluationList, GatherAsynchronousTransitiveDependenciesForRequests(requiredModule, namespaceOptionalIndirectRequests, seen, copyPreviouslyImportedNames)).
        3. Let optionalIndirectRequests be GetNewOptionalIndirectExportsModuleRequests(requiredModule, the ImportedNames Record { [[Direct]]: request.[[ImportedNames]].[[Direct]], [[Namespace]]: « » }, previouslyImportedNames).
        4. Perform BuildEvaluationList(evaluationList, requiredModule, optionalIndirectRequests, previouslyImportedNames, onDeferredNamespace).
  2. Return unused.
Note 1

Step 1.a.iv.2 is true when there's a namespace import or export. For such case, only asynchronous transitive dependencies of modules loaded through export defer are evaluated at this point, while synchronous dependencies should not be evaluated. They will be evaluated by the module namespace exotic object [[Get]] internal method, upon access of the corresponding binding. If there's another non-namespace import importing same names from [[ImportedNames]].[[Namespace]], they'll be added to the evaluation list on step 1.a.iv.3.

Note 2

Like BuildLinkingList, this operation tracks which names have already been requested from each module in previouslyImportedNames, so that a module graph whose export defer and export * from declarations form a cycle terminates. Such graphs are not rejected when linking: export defer * as self from "./self.js", for example, links successfully.

16.2.1.6.3.2.1 ListAppendUnique ( list1, list2 )

The abstract operation ListAppendUnique takes arguments list1 (a List of Records) and list2 (a List of Records) and returns unused. It performs the following steps when called:

  1. For each Record r of list2, do
    1. If list1 does not contain r, append r to list1.
  2. Return unused.

16.2.1.6.3.3 GatherAsynchronousTransitiveDependencies ( module [ , seen [ , previouslyImportedNames ] ] )

The abstract operation GatherAsynchronousTransitiveDependencies takes argument module (a Module Record) and optional arguments seen (a List of Module Records) and previouslyImportedNames (a List of Records with fields [[Module]] (a Cyclic Module Record) and [[ImportedNames]] (an ImportedNames Record)) and returns a List of Module Records. Collects the direct post-order list of asynchronous unexecuted transitive dependencies, stopping the depth-first search for a branch when an asynchronous dependency is found. It performs the following steps when called:

  1. If seen is not present, set seen to a new empty List.
  2. If previouslyImportedNames is not present, set previouslyImportedNames to a new empty List.
  3. Let result be a new empty List.
  4. If seen contains module, return resulta new empty List.
  5. Append module to seen.
  6. If module is not a Cyclic Module Record, return resulta new empty List.
  7. If module.[[Status]] is either evaluating or IsModuleSCCEvaluated(module), return resulta new empty List.
  8. If module.[[HasTLA]] is true, then
    1. Append module to result.
    2. Return result« module ».
  9. For each ModuleRequest Record request of module.[[RequestedModules]], do
    1. Let requiredModule be GetImportedModule(module, request).
    2. Let additionalModules be GatherAsynchronousTransitiveDependencies(requiredModule, seen).
    3. For each Module Record m of additionalModules, do
      1. If result does not contain m, append m to result.
  10. Return result.
  11. Return GatherAsynchronousTransitiveDependenciesForRequests(module, module.[[RequestedModules]], seen, previouslyImportedNames).

16.2.1.6.3.3.1 GatherAsynchronousTransitiveDependenciesForRequests ( referrer, moduleRequests, seen, previouslyImportedNames )

The abstract operation GatherAsynchronousTransitiveDependenciesForRequests takes arguments referrer (a Cyclic Module Record), moduleRequests (a List of ModuleRequest Records), seen (a List of Module Records), and previouslyImportedNames (a List of Records with fields [[Module]] (a Cyclic Module Record) and [[ImportedNames]] (an ImportedNames Record)) and returns a List of Module Records. Collects the direct post-order list of asynchronous unexecuted transitive dependencies, stopping the depth-first search for a branch when an asynchronous dependency is found. It performs the following steps when called:

  1. Let result be a new empty List.
  2. For each ModuleRequest Record request of moduleRequests, do
    1. Let requiredModule be GetImportedModule(referrer, request).
    2. Perform ListAppendUnique(result, GatherAsynchronousTransitiveDependencies(requiredModule, seen, previouslyImportedNames)).
    3. If requiredModule is a Cyclic Module Record, then
      1. If previouslyImportedNames does not contain a Record whose [[Module]] field is requiredModule, then
        1. Append the Record { [[Module]]: requiredModule, [[ImportedNames]]: the ImportedNames Record { [[Direct]]: « », [[Namespace]]: « » } } to previouslyImportedNames.
      2. Let optionalIndirectRequests be GetNewOptionalIndirectExportsModuleRequests(requiredModule, request.[[ImportedNames]], previouslyImportedNames).
      3. Perform ListAppendUnique(result, GatherAsynchronousTransitiveDependenciesForRequests(requiredModule, optionalIndirectRequests, seen, previouslyImportedNames)).
  3. Return result.

16.2.1.6.4 GetNewOptionalIndirectExportsModuleRequests ( module, importedNames, previouslyImportedNames )

The abstract operation GetNewOptionalIndirectExportsModuleRequests takes arguments module (a Cyclic Module Record), importedNames (an ImportedNames Record), and previouslyImportedNames (a List of Records with fields [[Module]] (a Cyclic Module Record) and [[ImportedNames]] (an ImportedNames Record)) and returns a List of OptionalModuleRequest Records. It returns the Module Requests for the export defer dependencies of module needed for the names in importedNames that have not already been requested from module, and records those names in previouslyImportedNames. It performs the following steps when called:

  1. Assert: previouslyImportedNames contains a Record whose [[Module]] field is module.
  2. Let previous be the Record in previouslyImportedNames whose [[Module]] field is module.
  3. Let previousNames be previous.[[ImportedNames]].
  4. Let newDirectImportedNames be ExcludeImportedNames(importedNames.[[Direct]], previousNames.[[Direct]]).
  5. Let newNamespaceImportedNames be ExcludeImportedNames(importedNames.[[Namespace]], previousNames.[[Namespace]]).
  6. Set previousNames.[[Direct]] to MergeImportedNames(previousNames.[[Direct]], newDirectImportedNames).
  7. Set previousNames.[[Namespace]] to MergeImportedNames(previousNames.[[Namespace]], newNamespaceImportedNames).
  8. Return module.GetOptionalIndirectExportsModuleRequests(MergeImportedNames(newDirectImportedNames, newNamespaceImportedNames)).

16.2.1.6.5 CopyPreviouslyImportedNames ( previouslyImportedNames )

The abstract operation CopyPreviouslyImportedNames takes argument previouslyImportedNames (a List of Records with fields [[Module]] (a Cyclic Module Record) and [[ImportedNames]] (an ImportedNames Record)) and returns a List of Records with fields [[Module]] (a Cyclic Module Record) and [[ImportedNames]] (an ImportedNames Record). It performs the following steps when called:

  1. Let copy be a new empty List.
  2. For each Record { [[Module]], [[ImportedNames]] } r of previouslyImportedNames, do
    1. Let names be r.[[ImportedNames]].
    2. If names.[[Direct]] is all, let direct be all; otherwise, let direct be a copy of the List names.[[Direct]].
    3. If names.[[Namespace]] is all, let namespace be all; otherwise, let namespace be a copy of the List names.[[Namespace]].
    4. Append the Record { [[Module]]: r.[[Module]], [[ImportedNames]]: the ImportedNames Record { [[Direct]]: direct, [[Namespace]]: namespace } } to copy.
  3. Return copy.

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 7, Source Text Module Records have the additional fields listed in Table 10. Each of these fields is initially set in ParseModule.

Table 10: 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.
[[OptionalIndirectExportEntries]] a List of ExportEntry Records whose [[LocalName]] is null. A list of the entries for the export defer ... from "..." declarations, and for the export * from "..." declarations through which the export defer bindings of other modules may be re-exported. The List is in source text occurrence order.
[[PendingOptionalFilteredNamespaceExports]] a List of Strings The local names of the export defer { ... } as ns from "mod" declarations of this module that ResolveExport has resolved while [[Environment]] was still empty, and whose bindings InitializeEnvironment must therefore create and initialize itself. It is initially empty.

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

Table 11: 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, namespace, or filtered-namespace The name under which the desired binding is exported by the module identified by [[ModuleRequest]]. The value namespace indicates that the import request is for the target module's namespace object, and the value filtered-namespace indicates that the import request is for a filtered namespace created from the module.
[[LocalName]] a String The name that is used to locally access the imported value from within the importing module.
[[NamespaceNamesFilter]] a List of Strings or empty When [[ImportName]] is filtered-namespace, this field contains the list of export names to include in the namespace object. For all other values of [[ImportName]], this field is empty.
Note 1

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

Table 12 (Informative): Import Forms Mappings to ImportEntry Records
Import Statement Form [[ModuleRequest]] [[ImportName]] [[LocalName]] [[NamespaceNamesFilter]]
import v from "mod"; "mod" "default" "v" empty
import * as ns from "mod"; "mod" namespace "ns" empty
import {x} from "mod"; "mod" "x" "x" empty
import {x as v} from "mod"; "mod" "x" "v" empty
import {x, y} as ns from "mod"; "mod" filtered-namespace "ns" « "x", "y" »

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

Table 13: 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, namespace, filtered-namespace, 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. namespace is used for export * as ns from "mod" declarations. all-but-default is used for export * from "mod" declarations. filtered-namespace is used for export {x, y} as ns from "mod" declarations where only selected exports are included in the namespace.
[[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.
[[NamespaceNamesFilter]] a List of Strings or empty When [[ImportName]] is filtered-namespace, this field contains the list of export names to include in the namespace object. For all other values of [[ImportName]], this field is empty.
Note 2

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

Table 14 (Informative): Export Forms Mappings to ExportEntry Records
Export Statement Form [[ExportName]] [[ModuleRequest]] [[ImportName]] [[LocalName]] [[NamespaceNamesFilter]]
export var v; "v" null null "v" empty
export default function f() {} "default" null null "f" empty
export default function () {} "default" null null "*default*" empty
export default 42; "default" null null "*default*" empty
export {x}; "x" null null "x" empty
export {v as x}; "x" null null "v" empty
export {x} from "mod"; "x" "mod" "x" null empty
export {v as x} from "mod"; "x" "mod" "v" null empty
export * from "mod"; null "mod" all-but-default null empty
export * as ns from "mod"; "ns" "mod" namespace null empty
export {x, y} as ns from "mod"; "ns" "mod" filtered-namespace null « "x", "y" »

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 exportEntry of exportEntries, do
    1. If exportEntry.[[ModuleRequest]] is null, then
      1. If importedBoundNames does not contain exportEntry.[[LocalName]], then
        1. Append exportEntry 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 10.e.iii of the ResolveExport concrete method of Source Text Module Records.
        2. Let importEntry be the element of importEntries whose [[LocalName]] is exportEntry.[[LocalName]].
        3. Append the ExportEntry Record { [[ModuleRequest]]: importEntry.[[ModuleRequest]], [[ImportName]]: importEntry.[[ImportName]], [[LocalName]]: null, [[ExportName]]: exportEntry.[[ExportName]], [[NamespaceNamesFilter]]: importEntry.[[NamespaceNamesFilter]] } to indirectExportEntries.
    2. Else if exportEntry.[[ImportName]] is all-but-default, then
      1. Assert: exportEntry.[[ExportName]] is null.
      2. Append exportEntry to starExportEntries.
    3. Else,
      1. Append exportEntry to indirectExportEntries.
  11. Let optionalIndirectExportsEntries be OptionalIndirectExportEntries of body.
  12. Let async be body Contains await.
  13. 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, [[OptionalIndirectExportEntries]]: optionalIndirectExportsEntries, [[PendingOptionalFilteredNamespaceExports]]: « », [[DFSAncestorIndex]]: empty }.

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 5.

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 exportEntry of module.[[LocalExportEntries]], do
    1. Assert: module provides the direct binding for this export.
    2. Assert: exportEntry.[[ExportName]] is not null.
    3. Append exportEntry.[[ExportName]] to exportedNames.
  7. For each ExportEntry Record exportEntry of module.[[IndirectExportEntries]], do
    1. Assert: module imports a specific binding for this export.
    2. Assert: exportEntry.[[ExportName]] is not null.
    3. Append exportEntry.[[ExportName]] to exportedNames.
  8. Let exportedNames be GetOwnExportedNames(module).
  9. For each ExportEntry Record exportEntry of module.[[StarExportEntries]], do
    1. Assert: exportEntry.[[ModuleRequest]] is not null.
    2. Let requestedModule be GetImportedModule(module, exportEntry.[[ModuleRequest]]).
    3. Let starNames be requestedModule.GetExportedNames(exportStarSet).
    4. For each element name of starNames, do
      1. If name is not "default", then
        1. If exportedNames does not contain name, then
          1. Append name to exportedNames.
  10. 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.1.1 GetOwnExportedNames ( module )

The abstract operation GetOwnExportedNames takes argument module (a Source Text Module Record) and returns a List of Strings. It performs the following steps when called:

  1. Let exportedNames be a new empty List.
  2. For each ExportEntry Record exportEntry of module.[[LocalExportEntries]], do
    1. Assert: module provides the direct binding for this export.
    2. Assert: exportEntry.[[ExportName]] is not null.
    3. Append exportEntry.[[ExportName]] to exportedNames.
  3. For each ExportEntry Record exportEntry of module.[[IndirectExportEntries]], do
    1. Assert: module imports a specific binding for this export.
    2. Assert: exportEntry.[[ExportName]] is not null.
    3. Append exportEntry.[[ExportName]] to exportedNames.
  4. For each ExportEntry Record exportEntry of module.[[OptionalIndirectExportEntries]], do
    1. If exportEntry.[[ExportName]] is not null, then
      1. Assert: module exposes an export defer binding for this export.
      2. Append exportEntry.[[ExportName]] to exportedNames.
  5. Return exportedNames.
Editor's Note
The steps not marked as new are copied over from GetExportedNames.

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 or deferred-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]] } record of resolveSet, do
    1. If module and record.[[Module]] are the same Module Record and exportName is record.[[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 exportEntry of module.[[LocalExportEntries]], do
    1. If exportEntry.[[ExportName]] is exportName, then
      1. Assert: module provides the direct binding for this export.
      2. Return ResolvedBinding Record { [[Module]]: module, [[BindingName]]: exportEntry.[[LocalName]] }.
  6. Let allIndirectEntries be the list-concatenation of module.[[IndirectExportEntries]] and module.[[OptionalIndirectExportEntries]].
  7. For each ExportEntry Record exportEntry of module.[[IndirectExportEntries]]allIndirectEntries, do
    1. If exportEntry.[[ExportName]] is exportName, then
      1. Assert: exportEntry.[[ModuleRequest]] is not null.
      2. Let importedModule be GetImportedModule(module, exportEntry.[[ModuleRequest]]).
      3. If exportEntry.[[ImportName]] is namespace, then
        1. Assert: module does not provide the direct binding for this export.
        2. Assert: exportEntry.[[NamespaceNamesFilter]] is empty.
        3. If exportEntry.[[ModuleRequest]].[[Phase]] is defer, then
          1. Return ResolvedBinding Record { [[Module]]: importedModule, [[BindingName]]: deferred-namespace }.
        4. Else,
          1. Assert: exportEntry.[[ModuleRequest]].[[Phase]] is evaluation.
          2. Return ResolvedBinding Record { [[Module]]: importedModule, [[BindingName]]: namespace }.
      4. Else if exportEntry.[[ImportName]] is filtered-namespace, then
        1. Assert: exportEntry.[[NamespaceNamesFilter]] is a List of Strings.
        2. Let localName be the string-concatenation of "*", exportName, and "*".
        3. NOTE: export { ... } as ns from "mod" introduces a local internal binding in the module that contains the ExportDeclaration. That binding is created by InitializeEnvironment, but for export defer declarations it is initialized here once a consumer attempts to resolve it.
        4. If module.[[OptionalIndirectExportEntries]] contains exportEntry, then
          1. If module.[[Environment]] is empty, then
            1. Assert: module.[[Status]] is either unlinked or linking.
            2. NOTE: When linking across cycles, module's exports might be resolved by ResolveExport before that InitializeEnvironment on module. In that case the module.[[Environment]] is not set up yet, so we mark the export as needing initialization and it will then be performed by InitializeEnvironment itself.
            3. If module.[[PendingOptionalFilteredNamespaceExports]] does not contain localName, append localName to module.[[PendingOptionalFilteredNamespaceExports]].
          2. Else if ! module.[[Environment]].HasBinding(localName) is false, then
            1. Perform ! module.[[Environment]].CreateImmutableBinding(localName, true).
            2. Let moduleNamespace be GetModuleNamespace(importedModule, exportEntry.[[ModuleRequest]].[[Phase]], exportEntry.[[NamespaceNamesFilter]]).
            3. Perform ! module.[[Environment]].InitializeBinding(localName, moduleNamespace).
        5. Return ResolvedBinding Record { [[Module]]: module, [[BindingName]]: localName }.
      5. Else,
        1. Assert: module imports a specific binding for this export.
        2. Assert: exportEntry.[[ImportName]] is a String.
        3. Return importedModule.ResolveExport(exportEntry.[[ImportName]], resolveSet).
  8. 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.
  9. Let starResolution be null.
  10. For each ExportEntry Record exportEntry of module.[[StarExportEntries]], do
    1. Assert: exportEntry.[[ModuleRequest]] is not null.
    2. Let importedModule be GetImportedModule(module, exportEntry.[[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.
  11. 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 8.

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 exportEntry of module.[[IndirectExportEntries]], do
    1. Let resolution be module.ResolveExport(exportEntry.[[ExportName]]).
    2. If resolution is either null or ambiguous, throw a SyntaxError exception.
    3. Assert: resolution is a ResolvedBinding Record.
    4. Perform ? EnsureResolvableBinding(module, exportEntry.[[ExportName]], disallow-ambiguous).
    5. If exportEntry.[[ImportName]] is namespace, then
      1. Let importedModule be GetImportedModule(module, exportEntry.[[ModuleRequest]]).
      2. NOTE: All exports of importedModule other than export defer ones are also validated by the InitializeEnvironment call on importedModule itself, and it is not observable which of the two InitializeEnvironment calls throws the SyntaxError.
      3. Perform ? ValidateOwnNamespaceExports(importedModule, all).
  2. Assert: All named exports from module are resolvable.
  3. Let realm be module.[[Realm]].
  4. Assert: realm is not undefined.
  5. Let envRecord be NewModuleEnvironment(realm.[[GlobalEnv]]).
  6. Set module.[[Environment]] to envRecord.
  7. For each ImportEntry Record importEntry of module.[[ImportEntries]], do
    1. Let importedModule be GetImportedModule(module, importEntry.[[ModuleRequest]]).
    2. If importEntry.[[ImportName]] is namespace, then
      1. NOTE: All exports of importedModule other than export defer ones are also validated by the InitializeEnvironment call on importedModule itself, and it is not observable which of the two InitializeEnvironment calls throws the SyntaxError.
      2. Perform ? ValidateOwnNamespaceExports(importedModule, all).
      3. Let namespace be GetModuleNamespace(importedModule, importEntry.[[ModuleRequest]].[[Phase]], all).
      4. Perform ! envRecord.CreateImmutableBinding(importEntry.[[LocalName]], true).
      5. Perform ! envRecord.InitializeBinding(importEntry.[[LocalName]], namespace).
    3. Else if importEntry.[[ImportName]] is filtered-namespace, then
      1. Perform ? ValidateOwnNamespaceExports(importedModule, importEntry.[[NamespaceNamesFilter]]).
      2. Let namespace be GetModuleNamespace(importedModule, importEntry.[[ModuleRequest]].[[Phase]], importEntry.[[NamespaceNamesFilter]]).
      3. Perform ! envRecord.CreateImmutableBinding(importEntry.[[LocalName]], true).
      4. Perform ! envRecord.InitializeBinding(importEntry.[[LocalName]], namespace).
    4. Else,
      1. Let resolution be importedModule.ResolveExport(importEntry.[[ImportName]]).
      2. If resolution is either null or ambiguous, throw a SyntaxError exception.
      3. If resolution.[[BindingName]] is namespace or deferred-namespace, then
        1. If resolution.[[BindingName]] is namespace let phase be evaluation, else let phase be defer.
        2. Let namespace be GetModuleNamespace(resolution.[[Module]], phase, all).
        3. Perform ! envRecord.CreateImmutableBinding(importEntry.[[LocalName]], true).
        4. Perform ! envRecord.InitializeBinding(importEntry.[[LocalName]], namespace).
      4. Else,
        1. Perform CreateImportBinding(envRecord, importEntry.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]]).
  8. For each ExportEntry Record exportEntry of the list-concatenation of module.[[IndirectExportEntries]] and module.[[OptionalIndirectExportEntries]], do
    1. If exportEntry.[[ImportName]] is filtered-namespace, then
      1. Let localName be the string-concatenation of "*", exportEntry.[[ExportName]], and "*".
      2. If module.[[IndirectExportEntries]] contains exportEntry, then
        1. Let importedModule be GetImportedModule(module, exportEntry.[[ModuleRequest]]).
        2. Perform ? ValidateOwnNamespaceExports(importedModule, exportEntry.[[NamespaceNamesFilter]]).
        3. Let filteredNamespace be GetModuleNamespace(importedModule, exportEntry.[[ModuleRequest]].[[Phase]], exportEntry.[[NamespaceNamesFilter]]).
        4. Perform ! envRecord.CreateImmutableBinding(localName, true).
        5. Perform ! envRecord.InitializeBinding(localName, filteredNamespace).
      3. Else if module.[[PendingOptionalFilteredNamespaceExports]] contains localName and ! envRecord.HasBinding(localName) is false, then
        1. Perform ! envRecord.CreateImmutableBinding(localName, true).
        2. Let importedModule be GetImportedModule(module, exportEntry.[[ModuleRequest]]).
        3. Let filteredNamespace be GetModuleNamespace(importedModule, exportEntry.[[ModuleRequest]].[[Phase]], exportEntry.[[NamespaceNamesFilter]]).
        4. Perform ! envRecord.InitializeBinding(localName, filteredNamespace).
        5. NOTE: The localName binding of export defer { ... } as ns from "mod" is created and initialized by whichever of ResolveExport and InitializeEnvironment first needs it. If no importer ever resolves that export, it is never created at all.
  9. Let moduleContext be a new ECMAScript code execution context.
  10. Set the Function of moduleContext to null.
  11. Assert: module.[[Realm]] is not undefined.
  12. Set the Realm of moduleContext to module.[[Realm]].
  13. Set the ScriptOrModule of moduleContext to module.
  14. Set the VariableEnvironment of moduleContext to module.[[Environment]].
  15. Set the LexicalEnvironment of moduleContext to module.[[Environment]].
  16. Set the PrivateEnvironment of moduleContext to null.
  17. Set module.[[Context]] to moduleContext.
  18. Push moduleContext onto the execution context stack; moduleContext is now the running execution context.
  19. Let code be module.[[ECMAScriptCode]].
  20. Let variableDecls be the VarScopedDeclarations of code.
  21. Let declaredVariableNames be a new empty List.
  22. For each element variableDecl of variableDecls, do
    1. For each element name of the BoundNames of variableDecl, do
      1. If declaredVariableNames does not contain name, then
        1. Perform ! envRecord.CreateMutableBinding(name, false).
        2. Perform ! envRecord.InitializeBinding(name, undefined).
        3. Append name to declaredVariableNames.
  23. Let lexicalDecls be the LexicallyScopedDeclarations of code.
  24. Let privateEnv be null.
  25. For each element lexicalDecl of lexicalDecls, do
    1. For each element name of the BoundNames of lexicalDecl, do
      1. If IsConstantDeclaration of lexicalDecl is true, then
        1. Perform ! envRecord.CreateImmutableBinding(name, true).
      2. Else,
        1. Perform ! envRecord.CreateMutableBinding(name, false).
      3. If lexicalDecl is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration, then
        1. Let funcObj be InstantiateFunctionObject of lexicalDecl with arguments envRecord and privateEnv.
        2. Perform ! envRecord.InitializeBinding(name, funcObj).
  26. Remove moduleContext from the execution context stack.
  27. Return unused.

16.2.1.7.3.1.1 EnsureResolvableBinding ( module, name, onAmbiguous )

The abstract operation EnsureResolvableBinding takes arguments module (a Module Record), name (a String), and onAmbiguous (allow-ambiguous or disallow-ambiguous) and returns either a normal completion containing unused, or a throw completion. It throws an error if module does not have an unambiguous export for name. It performs the following steps when called:

  1. Let resolution be module.ResolveExport(name).
  2. If resolution is null, throw a SyntaxError exception.
  3. If onAmbiguous is disallow-ambiguous, then
    1. If resolution is ambiguous, throw a SyntaxError exception.
    2. Assert: resolution is a ResolvedBinding Record.
  4. Return unused.
Note

ResolveExport has no observable side effects. Each time this operation is called with a specific module, name, onAmbiguous set of arguments it must return the same result. An implementation might choose to cache the EnsureResolvableBinding results for the exports of a module.

16.2.1.7.3.3 GetOptionalIndirectExportsModuleRequests ( importedNames )

The GetOptionalIndirectExportsModuleRequests concrete method of a Source Text Module Record module takes argument importedNames (all or a List of Strings) and returns a List of OptionalModuleRequest Records. It performs the following steps when called:

  1. Let requests be a new empty List.
  2. For each ExportEntry Record oie of module.[[OptionalIndirectExportEntries]], do
    1. Let processEntry be true.
    2. Let isStarExport be false.
    3. If oie.[[ImportName]] is all-but-default, then
      1. Let newNamespaceImportedNames be « ».
      2. Let newDirectImportedNames be ExcludeImportedNames(ExcludeImportedNames(importedNames, « "default" »), GetOwnExportedNames(module)).
      3. If newDirectImportedNames is an empty List, set processEntry to false.
      4. Set isStarExport to true.
      5. NOTE: We are handling an export * from "mod" declaration. While it's not by itself an optional indirect export, it is treated as one because it may be re-exporting indirect exports of "mod". It is marked as with [[IsStarExport]] in the resulting OptionalModuleRequest Record so that the evaluation logic can handle it appropriately.
    4. Else if importedNames is all or importedNames contains oie.[[ExportName]], then
      1. Let newDirectImportedNames be « ».
      2. Let newNamespaceImportedNames be all.
      3. Assert: oie.[[ImportName]] is a String, filtered-namespace, or namespace.
      4. If oie.[[ImportName]] is a String, then
        1. Set newDirectImportedNames to « oie.[[ImportName]] ».
        2. Set newNamespaceImportedNames to « ».
      5. If oie.[[ImportName]] is filtered-namespace, set newNamespaceImportedNames to oie.[[NamespaceNamesFilter]].
    5. Else,
      1. Set processEntry to false.
    6. If processEntry is true, then
      1. Let nextRequest be oie.[[ModuleRequest]].
      2. Let existingRequest be empty.
      3. For each OptionalModuleRequest Record request of requests, do
        1. If existingRequest is empty, ModuleRequestsKeyEqual(request, nextRequest) is true, request.[[Phase]] is nextRequest.[[Phase]], and request.[[IsStarExport]] is isStarExport, then
          1. Set existingRequest to request.
      4. If existingRequest is empty, then
        1. Let request be the OptionalModuleRequest Record { [[Specifier]]: nextRequest.[[Specifier]], [[Attributes]]: nextRequest.[[Attributes]], [[Phase]]: nextRequest.[[Phase]], [[ImportedNames]]: the ImportedNames Record { [[Direct]]: newDirectImportedNames, [[Namespace]]: newNamespaceImportedNames }, [[IsStarExport]]: isStarExport }.
        2. Append request to requests.
      5. Else,
        1. Set existingRequest.[[ImportedNames]].[[Direct]] to MergeImportedNames(existingRequest.[[ImportedNames]].[[Direct]], newDirectImportedNames).
        2. Set existingRequest.[[ImportedNames]].[[Namespace]] to MergeImportedNames(existingRequest.[[ImportedNames]].[[Namespace]], newNamespaceImportedNames).
  3. Return requests.

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 ModuleRequestsKeyEqual(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, AllImportedNames(moduleRequest)).
  3. Else,
    1. Perform ContinueDynamicImport(payload, result, moduleRequest.[[Phase]], AllImportedNames(moduleRequest)).
  4. Return unused.

16.2.1.13 GetModuleNamespace ( module, phase, importedNames )

The abstract operation GetModuleNamespace takes arguments module (an instance of a concrete subclass of Module Record), phase (defer or evaluation), and importedNames (all or a List of Strings) 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 if importedNames is all 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. NOTE: A filtered namespace object can be requested during linking, by ResolveExport or by InitializeEnvironment, for a module that has not been linked yet. A module's exported names and their resolutions are fully determined once loading has completed, so they do not depend on linking having run.
  3. Let namespace be empty.
  4. If importedNames is all, then
    1. If phase is defer, let set namespace be to module.[[DeferredNamespace]].
    2. Else, let set namespace be to module.[[Namespace]].
  5. 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. If importedNames is all or importedNames contains name, then
        1. If phase is not defer or name is not "then", then
          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, phase).
    5. If importedNames is all, then
      1. If phase is defer, set module.[[DeferredNamespace]] to namespace.
      2. Else, set module.[[Namespace]] to namespace.
  6. 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.2 Imports

Syntax

ImportDeclaration : import ImportClause FromClause WithClauseopt ; import defer NameSpaceImport FromClause WithClauseopt ; import ModuleSpecifier WithClauseopt ; ImportClause : ImportedDefaultBinding NameSpaceImport NamedImports ImportedDefaultBinding , NameSpaceImport ImportedDefaultBinding , NamedImports ImportedDefaultBinding : ImportedBinding NameSpaceImport : * as ImportedBinding NamedImports as ImportedBinding NamedImports : { } { ImportsList } { ImportsList , } FromClause : from ModuleSpecifier ImportsList : ImportSpecifier ImportsList , ImportSpecifier ImportSpecifier : ImportedBinding ModuleExportName as ImportedBinding ModuleExportName AliasedImportSpecifier AliasedImportSpecifier : 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 ImportClause : NamedImports ImportedDefaultBinding , NamedImports Note

The above rules mean that each element of the UnaliasedImportNames of NamedImports is treated as an ImportedBinding.

NameSpaceImport : NamedImports as ImportedBinding WithClause : with { WithEntries ,opt }

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 WithClauseopt ;
  1. Let module be the sole element of the ModuleRequests of ImportDeclaration.
  2. Return the ImportEntriesForModule of ImportClause with argument module.
ImportDeclaration : import defer NameSpaceImport FromClause WithClauseopt ;
  1. Let module be the sole element of the ModuleRequests of ImportDeclaration.
  2. Return the ImportEntriesForModule of NameSpaceImport with argument module.
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  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, [[NamespaceNamesFilter]]: empty }.
  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, [[LocalName]]: localName, [[NamespaceNamesFilter]]: empty }.
  3. Return « entry ».
NameSpaceImport : NamedImports as ImportedBinding
  1. Let localName be the StringValue of ImportedBinding.
  2. Let namespaceImportedNames be the FilteredNamespaceImportedNames of NamedImports.
  3. Let entry be the ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: filtered-namespace, [[LocalName]]: localName, [[NamespaceNamesFilter]]: namespaceImportedNames }.
  4. 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 ImportSpecifier : ModuleExportName
  1. Let localName be the sole element of the BoundNames of ImportedBinding the StringValue of ModuleExportName.
  2. Let entry be the ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: localName, [[LocalName]]: localName, [[NamespaceNamesFilter]]: empty }.
  3. Return « entry ».
ImportSpecifier : ModuleExportName as ImportedBinding AliasedImportSpecifier : 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, [[NamespaceNamesFilter]]: empty }.
  4. Return « entry ».

16.2.2.4 Static Semantics: DirectImportedNames

The syntax-directed operation DirectImportedNames takes no arguments and returns a List of unique Strings. It is defined piecewise over the following productions:

ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. Return the DirectImportedNames of ImportedDefaultBinding.
ImportClause : ImportedDefaultBinding , NamedImports
  1. Let names1 be the DirectImportedNames of ImportedDefaultBinding.
  2. Let names2 be the DirectImportedNames of NamedImports.
  3. Return MergeImportedNames(names1, names2).
ImportedDefaultBinding : ImportedBinding
  1. Return « "default" ».
NameSpaceImport : * as ImportedBinding NameSpaceImport : NamedImports as ImportedBinding NamedImports : { }
  1. Return a new empty List.
ImportsList : ImportsList , ImportSpecifier
  1. Let names1 be DirectImportedNames of ImportsList.
  2. Let names2 be DirectImportedNames of ImportSpecifier.
  3. Return MergeImportedNames(names1, names2).
ImportSpecifier : ImportedBinding ImportSpecifier : ModuleExportName
  1. Let importedName be the StringValue of ImportedBinding ModuleExportName.
  2. Return « importedName ».
ImportSpecifier : ModuleExportName as ImportedBinding AliasedImportSpecifier : ModuleExportName as ImportedBinding
  1. Let importedName be the StringValue of ModuleExportName.
  2. Return « importedName ».
ExportFromClause : *
  1. NOTE: export * from "mod" does not directly cause loading of any of "mod"'s export defer declarations.
  2. Return a new empty List.
ExplicitExportFromClause : NamedExports as ModuleExportName
  1. NOTE: The names are reached through the re-exported namespace object, so they are not directly imported.
  2. Return a new empty List.
ExplicitExportFromClause : * as ModuleExportName NamedExports : { }
  1. Return a new empty List.
ExportsList : ExportsList , ExportSpecifier
  1. Let names1 be the DirectImportedNames of ExportsList.
  2. Let names2 be the DirectImportedNames of ExportSpecifier.
  3. Return MergeImportedNames(names1, names2).
ExportSpecifier : ModuleExportName
  1. Let importedName be the StringValue of ModuleExportName.
  2. Return « importedName ».
AliasedExportSpecifier : ModuleExportName as ModuleExportName
  1. Let importedName be the StringValue of the first ModuleExportName.
  2. Return « importedName ».

16.2.2.4.1 MergeImportedNames ( a, b )

The abstract operation MergeImportedNames takes arguments a (all or a List of Strings) and b (all or a List of Strings) and returns all or a List of Strings. It performs the following steps when called:

  1. If a is all or b is all, return all.
  2. Assert: a and b are a List of Strings.
  3. Let merged be a copy of the List a.
  4. For each String name of b, do
    1. If merged does not contain name, then
      1. Append name to merged.
  5. Return merged.

16.2.2.4.2 ExcludeImportedNames ( a, b )

The abstract operation ExcludeImportedNames takes arguments a (all or a List of Strings) and b (all or a List of Strings) and returns all or a List of Strings. It returns the minimal set of imported names that is guaranteed to include all the names present in a but not in b. It performs the following steps when called:

  1. If b is all, return « ».
  2. If a is all, return all.
  3. Assert: a and b are a List of Strings.
  4. Return a new List containing all the elements of a that are not also elements of b.

16.2.2.5 Static Semantics: FilteredNamespaceImportedNames

The syntax-directed operation FilteredNamespaceImportedNames takes no arguments and returns all or a List of unique Strings. It returns the names that are imported to build a filtered namespace object, that is the names listed in an import { a, b } as ns from "mod" declaration or in an export { a, b } as ns from "mod" declaration. It is an empty List for every other declaration. It is defined piecewise over the following productions:

ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. Return the FilteredNamespaceImportedNames of NameSpaceImport.
ImportClause : ImportedDefaultBinding , NamedImports ImportClause : NamedImports ImportClause : ImportedDefaultBinding
  1. Return a new empty List.
NameSpaceImport : * as ImportedBinding
  1. Return all.
NameSpaceImport : NamedImports as ImportedBinding
  1. Return the FilteredNamespaceImportedNames of NamedImports.
NamedImports : { }
  1. Return a new empty List.
ImportsList : ImportsList , ImportSpecifier
  1. Let names1 be FilteredNamespaceImportedNames of ImportsList.
  2. Let names2 be FilteredNamespaceImportedNames of ImportSpecifier.
  3. Return MergeImportedNames(names1, names2).
ImportSpecifier : ImportedBinding ImportSpecifier : ModuleExportName
  1. Let importedName be the StringValue of ImportedBinding ModuleExportName.
  2. Return « importedName ».
ImportSpecifier : ModuleExportName as ImportedBinding AliasedImportSpecifier : ModuleExportName as ImportedBinding
  1. Let importedName be the StringValue of ModuleExportName.
  2. Return « importedName ».
ExportFromClause : *
  1. NOTE: export * from "mod" does not directly cause loading of any of "mod"'s export defer declarations.
  2. Return a new empty List.
ExplicitExportFromClause : NamedExports NamedExports : { } AliasedExportSpecifier : ModuleExportName as ModuleExportName
  1. Return a new empty List.
ExplicitExportFromClause : * as ModuleExportName
  1. Return all.
ExplicitExportFromClause : NamedExports as ModuleExportName
  1. Return the FilteredNamespaceImportedNames of NamedExports.
ExportsList : ExportsList , ExportSpecifier
  1. Let names1 be the FilteredNamespaceImportedNames of ExportsList.
  2. Let names2 be the FilteredNamespaceImportedNames of ExportSpecifier.
  3. Return MergeImportedNames(names1, names2).
ExportSpecifier : ModuleExportName
  1. Let importedName be the StringValue of ModuleExportName.
  2. Return « importedName ».
AliasedExportSpecifier : ModuleExportName as ModuleExportName
  1. Let importedName be the StringValue of the first ModuleExportName.
  2. Return « importedName ».

16.2.2.6 Static Semantics: UnaliasedImportNames

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

NamedImports : { }
  1. Return a new empty List.
ImportsList : ImportsList , ImportSpecifier
  1. Let names1 be UnaliasedImportNames of ImportsList.
  2. Let names2 be UnaliasedImportNames of ImportSpecifier.
  3. Return the list-concatenation of names1 and names2.
AliasedImportSpecifier : ModuleExportName as ImportedBinding
  1. Return a new empty List.
ModuleExportName : IdentifierName
  1. Return a List whose sole element is IdentifierName.
ModuleExportName : StringLiteral
  1. Return a List whose sole element is StringLiteral.

16.2.2.7 Static Semantics: FilteredNamespaceNames

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

NamedImports : { } NamedExports : { }
  1. Return a new empty List.
ImportsList : ImportsList , ImportSpecifier
  1. Let names1 be FilteredNamespaceNames of ImportsList.
  2. Let names2 be FilteredNamespaceNames of ImportSpecifier.
  3. Return the list-concatenation of names1 and names2.
ExportsList : ExportsList , ExportSpecifier
  1. Let names1 be FilteredNamespaceNames of ExportsList.
  2. Let names2 be FilteredNamespaceNames of ExportSpecifier.
  3. Return the list-concatenation of names1 and names2.
ImportSpecifier : ModuleExportName ExportSpecifier : ModuleExportName
  1. Return a List whose sole element is the StringValue of ModuleExportName.
ImportSpecifier : AliasedImportSpecifier ExportSpecifier : AliasedExportSpecifier
  1. NOTE: It is an early error if a filtered namespace contains an AliasedImportSpecifier or AliasedExportSpecifier (see 16.2.2.1 and 16.2.3.1).
  2. Return a new empty List.

16.2.3 Exports

Syntax

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

16.2.3.1 Static Semantics: Early Errors

ExportDeclaration : export NamedExports ; Note

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

ExplicitExportFromClause : NamedExports as ModuleExportName

16.2.3.2 Static Semantics: ExportedBindings

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

ExportDeclaration : export defer ExplicitExportFromClause FromClause WithClauseopt ;
  1. Return a new empty List.
ExportSpecifier : ModuleExportName as ModuleExportName AliasedExportSpecifier : 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 WithClauseopt ;
  1. Return the ExportedNames of ExportFromClause.
ExportDeclaration : export defer ExplicitExportFromClause FromClause WithClauseopt ;
  1. Return the ExportedNames of ExplicitExportFromClause.
ExportFromClause : *
  1. Return a new empty List.
ExportFromClause : * as ModuleExportName ExplicitExportFromClause : * as ModuleExportName NamedExports as ModuleExportName
  1. Return a List whose sole element is the StringValue of ModuleExportName.
ExportFromClause : NamedExports ExplicitExportFromClause : 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 AliasedExportSpecifier : 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 WithClauseopt ;
  1. Let module be the sole element of the ModuleRequests of FromClauseExportDeclaration.
  2. Return the ExportEntriesForModule of ExportFromClause with argument module.
ExportDeclaration : export defer ExplicitExportFromClause FromClause WithClauseopt ;
  1. Return a new empty List.
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, [[NamespaceNamesFilter]]: empty } 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, [[NamespaceNamesFilter]]: empty } to entries.
  4. Return entries.
ExportDeclaration : export default HoistableDeclaration
  1. Let names be 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", [[NamespaceNamesFilter]]: empty }.
ExportDeclaration : export default ClassDeclaration
  1. Let names be 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", [[NamespaceNamesFilter]]: empty }.
ExportDeclaration : export default AssignmentExpression ;
  1. Let entry be the ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: "*default*", [[ExportName]]: "default", [[NamespaceNamesFilter]]: empty }.
  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, [[NamespaceNamesFilter]]: empty }.
  2. Return « entry ».
ExportFromClause : * as ModuleExportName ExplicitExportFromClause : * as ModuleExportName
  1. Let exportName be the StringValue of ModuleExportName.
  2. Let entry be the ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: namespace, [[LocalName]]: null, [[ExportName]]: exportName, [[NamespaceNamesFilter]]: empty }.
  3. Return « entry ».
ExplicitExportFromClause : NamedExports as ModuleExportName
  1. Let exportName be the StringValue of ModuleExportName.
  2. Let importedNames be the FilteredNamespaceImportedNames of NamedExports.
  3. Let entry be the ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: filtered-namespace, [[LocalName]]: null, [[ExportName]]: exportName, [[NamespaceNamesFilter]]: importedNames }.
  4. 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, [[NamespaceNamesFilter]]: empty }.
ExportSpecifier : ModuleExportName as ModuleExportName AliasedExportSpecifier : 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, [[NamespaceNamesFilter]]: empty }.

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:

ExportSpecifier : ModuleExportName as ModuleExportName AliasedExportSpecifier : ModuleExportName as ModuleExportName
  1. Return the ReferencedBindings of the first ModuleExportName.

16.2.3.7 Runtime Semantics: Evaluation

ExportDeclaration : export defer ExplicitExportFromClause FromClause WithClauseopt ;
  1. Return empty.

16.2.3.8 Static Semantics: OptionalIndirectExportEntries

The syntax-directed operation OptionalIndirectExportEntries 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 OptionalIndirectExportEntries of ModuleItemList.
  2. Let entries2 be OptionalIndirectExportEntries of ModuleItem.
  3. Return the list-concatenation of entries1 and entries2.
ModuleItem : ImportDeclaration StatementListItem ExportDeclaration : export NamedExports ; export VariableStatement export Declaration export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. Return a new empty List.
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. If ExportFromClause is not *, return a new empty List.
  2. If WithClause is present, let request be ExportFromDeclarationModuleRequest(ExportFromClause, FromClause, evaluation, WithClause).
  3. Else, let request be ExportFromDeclarationModuleRequest(ExportFromClause, FromClause, evaluation).
  4. Return ExportEntriesForModule of ExportFromClause with argument request.
ExportDeclaration : export defer ExplicitExportFromClause FromClause WithClauseopt ;
  1. If ExplicitExportFromClause is * as ModuleExportName or NamedExports as ModuleExportName, let phase be defer.
  2. Else, let phase be evaluation.
  3. NOTE: A deferred re-export of a namespace object creates a deferred namespace, in the same way as import defer. A deferred re-export of individual bindings only defers loading and evaluating the dependency until the bindings are imported.
  4. If WithClause is present, let request be ExportFromDeclarationModuleRequest(ExplicitExportFromClause, FromClause, phase, WithClause).
  5. Else, let request be ExportFromDeclarationModuleRequest(ExplicitExportFromClause, FromClause, phase).
  6. Return ExportEntriesForModule of ExplicitExportFromClause with argument request.

Copyright & Software License

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.