Stage 3 Draft / April 8, 2024

Source Phase Imports

1 ECMAScript Data Types and Values

1.1 ECMAScript Language Types

1.1.1 Object Type

1.1.1.1 Well-Known Intrinsic Objects

Well-known intrinsics are built-in objects that are explicitly referenced by the algorithms of this specification and which usually have realm-specific identities. Unless otherwise specified each intrinsic object actually corresponds to a set of similar objects, one per realm.

Within this specification a reference such as %name% means the intrinsic object, associated with the current realm, corresponding to the name. A reference such as %name.a.b% means, as if the "b" property of the value of the "a" property of the intrinsic object %name% was accessed prior to any ECMAScript code being evaluated. Determination of the current realm and its intrinsics is described in 9.4. The well-known intrinsics are listed in Table 1.

Table 1: Well-Known Intrinsic Objects
Intrinsic Name Global Name ECMAScript Language Association
%AbstractModuleSource% The %AbstractModuleSource% constructor (28.1.1)
%AggregateError% AggregateError The AggregateError constructor (20.5.7.1)
%Array% Array The Array constructor (23.1.1)
%ArrayBuffer% ArrayBuffer The ArrayBuffer constructor (25.1.3)
%ArrayIteratorPrototype% The prototype of Array iterator objects (23.1.5)
%AsyncFromSyncIteratorPrototype% The prototype of async-from-sync iterator objects (27.1.4)
%AsyncFunction% The constructor of async function objects (27.7.1)
%AsyncGeneratorFunction% The constructor of async generator function objects (27.4.1)
%AsyncGeneratorPrototype% The prototype of async generator objects (27.6)
%AsyncIteratorPrototype% An object that all standard built-in async iterator objects indirectly inherit from
%Atomics% Atomics The Atomics object (25.4)
%BigInt% BigInt The BigInt constructor (21.2.1)
%BigInt64Array% BigInt64Array The BigInt64Array constructor (23.2)
%BigUint64Array% BigUint64Array The BigUint64Array constructor (23.2)
%Boolean% Boolean The Boolean constructor (20.3.1)
%DataView% DataView The DataView constructor (25.3.2)
%Date% Date The Date constructor (21.4.2)
%decodeURI% decodeURI The decodeURI function (19.2.6.1)
%decodeURIComponent% decodeURIComponent The decodeURIComponent function (19.2.6.2)
%encodeURI% encodeURI The encodeURI function (19.2.6.3)
%encodeURIComponent% encodeURIComponent The encodeURIComponent function (19.2.6.4)
%Error% Error The Error constructor (20.5.1)
%eval% eval The eval function (19.2.1)
%EvalError% EvalError The EvalError constructor (20.5.5.1)
%FinalizationRegistry% FinalizationRegistry The FinalizationRegistry constructor (26.2.1)
%Float32Array% Float32Array The Float32Array constructor (23.2)
%Float64Array% Float64Array The Float64Array constructor (23.2)
%ForInIteratorPrototype% The prototype of For-In iterator objects (14.7.5.10)
%Function% Function The Function constructor (20.2.1)
%GeneratorFunction% The constructor of generator function objects (27.3.1)
%GeneratorPrototype% The prototype of generator objects (27.5)
%Int8Array% Int8Array The Int8Array constructor (23.2)
%Int16Array% Int16Array The Int16Array constructor (23.2)
%Int32Array% Int32Array The Int32Array constructor (23.2)
%isFinite% isFinite The isFinite function (19.2.2)
%isNaN% isNaN The isNaN function (19.2.3)
%IteratorPrototype% An object that all standard built-in iterator objects indirectly inherit from
%JSON% JSON The JSON object (25.5)
%Map% Map The Map constructor (24.1.1)
%MapIteratorPrototype% The prototype of Map iterator objects (24.1.5)
%Math% Math The Math object (21.3)
%Number% Number The Number constructor (21.1.1)
%Object% Object The Object constructor (20.1.1)
%parseFloat% parseFloat The parseFloat function (19.2.4)
%parseInt% parseInt The parseInt function (19.2.5)
%Promise% Promise The Promise constructor (27.2.3)
%Proxy% Proxy The Proxy constructor (28.2.1)
%RangeError% RangeError The RangeError constructor (20.5.5.2)
%ReferenceError% ReferenceError The ReferenceError constructor (20.5.5.3)
%Reflect% Reflect The Reflect object (28.1)
%RegExp% RegExp The RegExp constructor (22.2.4)
%RegExpStringIteratorPrototype% The prototype of RegExp String Iterator objects (22.2.9)
%Set% Set The Set constructor (24.2.1)
%SetIteratorPrototype% The prototype of Set iterator objects (24.2.5)
%SharedArrayBuffer% SharedArrayBuffer The SharedArrayBuffer constructor (25.2.2)
%String% String The String constructor (22.1.1)
%StringIteratorPrototype% The prototype of String iterator objects (22.1.5)
%Symbol% Symbol The Symbol constructor (20.4.1)
%SyntaxError% SyntaxError The SyntaxError constructor (20.5.5.4)
%ThrowTypeError% A function object that unconditionally throws a new instance of %TypeError%
%TypedArray% The super class of all typed Array constructors (23.2.1)
%TypeError% TypeError The TypeError constructor (20.5.5.5)
%Uint8Array% Uint8Array The Uint8Array constructor (23.2)
%Uint8ClampedArray% Uint8ClampedArray The Uint8ClampedArray constructor (23.2)
%Uint16Array% Uint16Array The Uint16Array constructor (23.2)
%Uint32Array% Uint32Array The Uint32Array constructor (23.2)
%URIError% URIError The URIError constructor (20.5.5.6)
%WeakMap% WeakMap The WeakMap constructor (24.3.1)
%WeakRef% WeakRef The WeakRef constructor (26.1.1)
%WeakSet% WeakSet The WeakSet constructor (24.4.1)
Note

Additional entries in Table 91.

13 ECMAScript Language: Expressions

13.3 Left-Hand-Side Expressions

Syntax

ImportCall[Yield, Await] : import ( AssignmentExpression[+In, ?Yield, ?Await] ) import . source ( AssignmentExpression[+In, ?Yield, ?Await] )

13.3.10 Import Calls

13.3.10.1 Runtime Semantics: Evaluation

ImportCall : import ( AssignmentExpression[+In, ?Yield, ?Await] )
  1. Let referrer be GetActiveScriptOrModule().
  2. If referrer is null, set referrer to the current Realm Record.
  3. Let argRef be ? Evaluation of AssignmentExpression.
  4. Let specifier be ? GetValue(argRef).
  5. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  6. Let specifierString be Completion(ToString(specifier)).
  7. IfAbruptRejectPromise(specifierString, promiseCapability).
  8. Perform HostLoadImportedModule(referrer, specifierString, empty, promiseCapability).
  9. Return promiseCapability.[[Promise]].
  10. Return ? EvaluateImportCall(AssignmentExpression, evaluation).
ImportCall : import . source ( AssignmentExpression[+In, ?Yield, ?Await] )
  1. Return ? EvaluateImportCall(AssignmentExpression, source).

13.3.10.2 EvaluateImportCall ( specifierExpression, phase )

The abstract operation EvaluateImportCall takes arguments specifierExpression (a Parse Node) and phase (source or evaluation) and returns either a normal completion containing a Promise or a throw 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 specifierRef be ? Evaluation of evaluating specifierExpression.
  4. Let specifier be ? GetValue(specifierRef).
  5. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  6. Let specifierString be Completion(ToString(specifier)).
  7. IfAbruptRejectPromise(specifierString, promiseCapability).
  8. Let moduleRequest be a new ModuleRequest Record { [[Specifier]]: specifierString, [[Phase]]: phase }.
  9. Perform HostLoadImportedModule(referrer, moduleRequest, empty, promiseCapability).
  10. Return promiseCapability.[[Promise]].

13.3.10.2.1 ContinueDynamicImport ( promiseCapability, phase, moduleCompletion )

The abstract operation ContinueDynamicImport takes arguments promiseCapability (a PromiseCapability Record), phase (source or evaluation), and moduleCompletion (either a normal completion containing a Module Record or a throw completion) 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. If phase is source, then
    1. Let moduleSourceCompletion be Completion(module.GetModuleSource()).
    2. If moduleSourceCompletion is an abrupt completion, then
      1. Perform ! Call(promiseCapability.[[Reject]], undefined, « moduleSourceCompletion.[[Value]] »).
    3. Else,
      1. Perform ! Call(promiseCapability.[[Resolve]], undefined, « moduleSourceCompletion.[[Value]] »).
    4. Return unused.
  4. Let loadPromise be module.LoadRequestedModules().
  5. 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.
  6. Let onRejected be CreateBuiltinFunction(rejectedClosure, 1, "", « »).
  7. Let linkAndEvaluateClosure be a new Abstract Closure with no parameters that captures module, promiseCapability, and onRejected and performs the following steps when called:
    1. Let link be Completion(module.Link()).
    2. If link is an abrupt completion, then
      1. Perform ! Call(promiseCapability.[[Reject]], undefined, « link.[[Value]] »).
      2. Return unused.
    3. Let evaluatePromise be module.Evaluate().
    4. Let fulfilledClosure be a new Abstract Closure with no parameters that captures module and promiseCapability and performs the following steps when called:
      1. Let namespace be GetModuleNamespace(module).
      2. Perform ! Call(promiseCapability.[[Resolve]], undefined, « namespace »).
      3. Return unused.
    5. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, "", 0, « »).
    6. Perform PerformPromiseThen(evaluatePromise, onFulfilled, onRejected).
  8. Let linkAndEvaluate be CreateBuiltinFunction(linkAndEvaluateClosure, "", 0, « »).
  9. Perform PerformPromiseThen(loadPromise, linkAndEvaluate, onRejected).
  10. Return unused.

16 ECMAScript Language: Scripts and Modules

16.1 Modules

16.1.1 Module Semantics

16.1.1.1 ModuleRequest Records

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

Table 2: ModuleRequest Record fields
Field Name Value Type Meaning
[[Specifier]] a String The module specifier
[[Phase]] source or evaluation The target import phase
Editor's Note
In general, this proposal replaces places where module specifiers are passed around with ModuleRequest Records. For example, several syntax-directed operations, such as ModuleRequests produce Lists of ModuleRequest Records rather than Lists of Strings which are interpreted as module specifiers. Some algorithms like ImportEntries and ImportEntriesForModule pass around ModuleRequest Records rather than Strings, in a way which doesn't require any particular textual change. Additionally, record fields in Cyclic Module Records and Source Text Module Records which contained Lists of Strings are replaced by Lists of ModuleRequest Records, as indicated above.

16.1.1.3 Static Semantics: ModuleRequests

The syntax-directed operation ModuleRequests takes no arguments and returns a List of StringsModuleRequest 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 moduleNamesrequests be ModuleRequests of ModuleItemList.
  2. Let additionalNamesadditionalRequests be ModuleRequests of ModuleItem.
  3. For each String name of additionalNames, do
  4. For each ModuleRequest Record mr of additionalRequests, do
    1. Let found be false.
    2. For each ModuleRequest Record mr2 of requests, do
      1. If mr.[[Specifer]] is mr2.[[Specifer]] and mr.[[Phase]] is mr2.[[Phase]], then
        1. Assert: found is false.
        2. Set found to true.
    3. If moduleNames does not contain name, then
    4. If found is false, then
      1. Append namemr to moduleNamesrequests.
  5. Return moduleNamesrequests.
ModuleItem : StatementListItem
  1. Return a new empty List.
ImportDeclaration : import ImportClause FromClause ;
  1. Return ModuleRequests of FromClause.
  2. Let specifier be SV of FromClause.
  3. Return a List whose sole element is the ModuleRequest Record { [[Specifer]]: specifier, [[Phase]]: evaluation }.
ImportDeclaration : import source ImportedBinding FromClause ;
  1. Let specifier be SV of FromClause.
  2. Return a List whose sole element is the ModuleRequest Record { [[Specifer]]: specifier, [[Phase]]: source }.
ModuleSpecifier : StringLiteral
  1. Return a List whose sole element is the SV of StringLiteral.
ExportDeclaration : export ExportFromClause FromClause ;
  1. Return ModuleRequests of FromClause.
  2. Let specifier be SV of FromClause.
  3. Return a List whose sole element is the ModuleRequest Record { [[Specifer]]: specifier, [[Phase]]: evaluation }.
ExportDeclaration : export NamedExports ; export VariableStatement export Declaration export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. Return a new empty List.

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

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

Prepares the module for linking by recursively loading all its dependencies, and returns a promise.

GetExportedNames([exportStarSet])

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

ResolveExport(exportName [, resolveSet])

Return the binding of a name exported by this module. Bindings are represented by a ResolvedBinding Record, of the form { [[Module]]: Module Record, [[BindingName]]: String | namespace }. If the export is a Module Namespace Object without a direct binding in any module, [[BindingName]] will be set to namespace. Return 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.

Link()

Prepare the module for evaluation by transitively resolving all module dependencies and creating a Module Environment Record.

LoadRequestedModules must have completed successfully prior to invoking this method.

Evaluate()

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.

Link must have completed successfully prior to invoking this method.

GetModuleSource()

It returns either a normal completion containing the Module Source Object corresponding to this source Module Record's source phase (28.1), or a throw completion.

When called multiple times on the same Module Record, if GetModuleSource() returns a normal completion it must always return a normal completion containing the same object.

The returned object should have a [[Prototype]] internal slot whose value is %AbstractModuleSource.prototype%.

For Module Records that do not have a source representation, GetModuleSource() must always return a throw completion whose [[Value]] is a ReferenceError.

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

Table 5: Additional Fields of Cyclic Module Records
Field Name Value Type Meaning
[[Status]] unlinked, linking, linked, evaluating, evaluating-async, or evaluated Initially unlinked. Transitions to 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.
[[DFSIndex]] an integer or empty Auxiliary field used during Link and Evaluate only. If [[Status]] is linking or evaluating, this non-negative number records the point at which the module was first visited during the depth-first traversal of the dependency graph.
[[DFSAncestorIndex]] an integer or empty Auxiliary field used during Link and Evaluate only. If [[Status]] is linking or evaluating, this is either the module's own [[DFSIndex]] or that of an "earlier" module in the same strongly connected component.
[[RequestedModules]] a List of StringsModuleRequest Records A List of all the ModuleSpecifier strings used by the module represented by this record to request the importation of a module, along with their associated phase (source or evaluation). The List is in source text occurrence order.
[[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 equal to the [[DFSIndex]] 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.
[[AsyncEvaluation]] a Boolean Whether this module is either itself asynchronous or has an asynchronous dependency. Note: The order in which this field is set is used to order queued executions, see 16.2.1.5.3.4.
[[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.

16.1.1.5.1 LoadRequestedModules ( [ hostDefined ] )

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

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

16.1.1.5.1.1 InnerModuleLoading ( state, module, loadType )

The abstract operation InnerModuleLoading takes arguments state (a GraphLoadingState Record), module (a Module Record), and loadType (single or recursive-load) 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 loadType is recursive-load, module is a Cyclic Module Record, module.[[Status]] is new, and state.[[Visited]] does not contain module, then
    1. Append module to state.[[Visited]].
    2. Let requestedModulesCount be the number of elements in module.[[RequestedModules]].
    3. Set state.[[PendingModulesCount]] to state.[[PendingModulesCount]] + requestedModulesCount.
    4. For each String required of module.[[RequestedModules]], do
    5. For each ModuleRequest Record required of module.[[RequestedModules]], do
      1. If module.[[LoadedModules]] contains a Record whose [[Specifier]] is required.[[Specifier]], then
        1. Let record be that Record.
        2. If required.[[Phase]] is source, let innerLoadType be single; otherwise let innerLoadType be recursive-load.
        3. Perform InnerModuleLoading(state, record.[[Module]], innerLoadType).
      2. Else,
        1. Perform HostLoadImportedModule(module, required, state.[[HostDefined]], state).
        2. NOTE: HostLoadImportedModule will call FinishLoadingImportedModule, which re-enters the graph loading process through ContinueModuleLoading.
      3. If state.[[IsLoading]] is false, return unused.
  3. Assert: state.[[PendingModulesCount]] ≥ 1.
  4. Set state.[[PendingModulesCount]] to state.[[PendingModulesCount]] - 1.
  5. If state.[[PendingModulesCount]] = 0, then
    1. Set state.[[IsLoading]] to false.
    2. For each Cyclic Module Record loaded of state.[[Visited]], do
      1. If loaded.[[Status]] is new, set loaded.[[Status]] to unlinked.
    3. Perform ! Call(state.[[PromiseCapability]].[[Resolve]], undefined, « undefined »).
  6. Return unused.

16.1.1.5.1.2 ContinueModuleLoading ( state, phase, moduleCompletion )

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

  1. If state.[[IsLoading]] is false, return unused.
  2. If moduleCompletion is a normal completion, then
    1. If phase is source, let loadType be single; otherwise let loadType be recursive-load.
    2. Perform InnerModuleLoading(state, moduleCompletion.[[Value]], loadType).
  3. Else,
    1. Set state.[[IsLoading]] to false.
    2. Perform ! Call(state.[[PromiseCapability]].[[Reject]], undefined, « moduleCompletion.[[Value]] »).
  4. Return unused.

16.1.1.5.2 Link ( )

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

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

16.1.1.5.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.)

16.1.1.5.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 [[DFSIndex]] and [[DFSAncestorIndex]] fields, 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. Let promise be ! module.Evaluate().
    2. Assert: promise.[[PromiseState]] is not pending.
    3. If promise.[[PromiseState]] is rejected, then
      1. Return ThrowCompletion(promise.[[PromiseResult]]).
    4. 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. Set module.[[DFSIndex]] to index.
  7. Set module.[[DFSAncestorIndex]] to index.
  8. Set module.[[PendingAsyncDependencies]] to 0.
  9. Set index to index + 1.
  10. Append module to stack.
  11. For each String required of module.[[RequestedModules]], do
  12. For each ModuleRequest Record required of module.[[RequestedModules]], do
    1. Let requiredModule be GetImportedModule(module, required.[[Specifier]]).
    2. If requiredModule.[[Phase]] is evaluation, then
      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.[[AsyncEvaluation]] is true, then
          1. Set module.[[PendingAsyncDependencies]] to module.[[PendingAsyncDependencies]] + 1.
          2. Append module to requiredModule.[[AsyncParentModules]].
  13. If module.[[PendingAsyncDependencies]] > 0 or module.[[HasTLA]] is true, then
    1. Assert: module.[[AsyncEvaluation]] is false and was never previously set to true.
    2. Set module.[[AsyncEvaluation]] to true.
    3. NOTE: The order in which module records have their [[AsyncEvaluation]] fields transition to true is significant. (See 16.2.1.5.3.4.)
    4. If module.[[PendingAsyncDependencies]] = 0, perform ExecuteAsyncModule(module).
  14. Else,
    1. Perform ? module.ExecuteModule().
  15. Assert: module occurs exactly once in stack.
  16. Assert: module.[[DFSAncestorIndex]] ≤ module.[[DFSIndex]].
  17. If module.[[DFSAncestorIndex]] = module.[[DFSIndex]], 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. If requiredModule.[[AsyncEvaluation]] is false, set requiredModule.[[Status]] to evaluated.
      5. Otherwise, set requiredModule.[[Status]] to evaluating-async.
      6. If requiredModule and module are the same Module Record, set done to true.
      7. Set requiredModule.[[CycleRoot]] to module.
  18. Return index.

16.1.1.6 Source Text Module Records

16.1.1.6.1 GetModuleSource ( )

The GetModuleSource concrete method of a Source Text Module Record module takes no arguments and returns either a normal completion containing an Object or a throw completion.

Source Text Module Record provides a GetModuleSource implementation that always returns an abrupt completion indicating that a source phase import is not available.

It performs the following steps when called:

  1. Throw a ReferenceError exception.

16.1.1.6.2 InitializeEnvironment ( )

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

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

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

Table 6: ImportEntry Record Fields
Field Name Value Type Meaning
[[ModuleRequest]] a String String value of the ModuleSpecifier of the ImportDeclaration.
[[ImportName]] a String or namespace-object, namespace-object or source The name under which the desired binding is exported by the module identified by [[ModuleRequest]]. The value namespace-object indicates that the import request is for the target module's namespace object. The value source represents an import at the source phase.
[[LocalName]] a String The name that is used to locally access the imported value from within the importing module.
Note

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

Table 7 (Informative): Import Forms Mappings to ImportEntry Records
Import Statement Form [[ModuleRequest]] [[ImportName]] [[LocalName]]
import v from "mod"; "mod" "default" "v"
import * as ns from "mod"; "mod" namespace-object "ns"
import {x} from "mod"; "mod" "x" "x"
import {x as v} from "mod"; "mod" "x" "v"
import "mod"; An ImportEntry Record is not created.

16.1.1.7 HostLoadImportedModule ( referrer, specifier, moduleRequest, hostDefined, payload )

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

Note 1

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

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

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

An implementation of HostLoadImportedModule must conform to the following requirements:

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

Note 2

Implementations may provide unobservable module loading optimizations, such as speculative preloading of modules that are likely to be requested next. When doing so, they should consider whether the module is being imported for its source phase, which won't cause calls to the HostLoadImportedModule hook for its transitive dependencies, or for its evaluation phase, which will.

16.1.1.8 FinishLoadingImportedModule ( referrer, specifier, moduleRequest, payload, result )

The abstract operation FinishLoadingImportedModule takes arguments referrer (a Script Record, a Cyclic Module Record, or a Realm Record), specifier (a String), 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 Record whose [[Specifier]] is specifiermoduleRequest.[[Specifier]], then
      1. Assert: record.[[Module]] is result.[[Value]].
    2. Else, append the Record { [[Specifier]]: specifiermoduleRequest.[[Specifier]], [[Module]]: result.[[Value]] } to referrer.[[LoadedModules]].
  2. If payload is a GraphLoadingState Record, then
    1. Perform ContinueModuleLoading(payload, moduleRequest.[[Phase]], result).
  3. Else,
    1. Perform ContinueDynamicImport(payload, moduleRequest.[[Phase]], result).

16.1.1.9 HostGetModuleSourceName ( moduleSource )

The host-defined abstract operation HostGetModuleSourceName takes argument moduleSource (an Object) and returns either a normal completion containing a String or a throw completion.

An implementation of HostGetModuleSourceName must conform to the following requirements:

16.2 Imports

Syntax

ImportDeclaration : import ImportClause FromClause ; import ModuleSpecifier ; import source ImportedBinding FromClause ; ImportClause : ImportedDefaultBinding NameSpaceImport NamedImports ImportedDefaultBinding , NameSpaceImport ImportedDefaultBinding , NamedImports ImportedDefaultBinding : ImportedBinding NameSpaceImport : * as ImportedBinding NamedImports : { } { ImportsList } { ImportsList , } FromClause : from ModuleSpecifier ImportsList : ImportSpecifier ImportsList , ImportSpecifier ImportSpecifier : ImportedBinding ModuleExportName as ImportedBinding ModuleSpecifier : StringLiteral ImportedBinding : BindingIdentifier[~Yield, +Await]

16.2.1 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 ImportEntries of ModuleItemList.
  2. Let entries2 be 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 ;
  1. Let module be the sole element of ModuleRequestsSV of FromClause.
  2. Return ImportEntriesForModule of ImportClause with argument module.
ImportDeclaration : import ModuleSpecifier ;
  1. Return a new empty List.
ImportDeclaration : import source ImportedBinding FromClause ;
  1. Let module be the SV of FromClause.
  2. Let localName be the sole element of BoundNames of ImportedBinding.
  3. Let entry be the ImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: source, [[LocalName]]: localName }.
  4. Return « entry ».

28 Reflection

28.1 Module Source Objects

Module Source Objects represent modules in their source import phase, which are not linked, instantiated or executed.

A Module Source Object is an object for which HostGetModuleSourceName returns a normal completion.

All Module Source Objects should have a prototype of %AbstractModuleSource%.prototype.

Hosts may define their own %AbstractModuleSource% subclasses for custom module types.

28.1.1 The %AbstractModuleSource% Constructor

The %AbstractModuleSource% constructor:

  • along with its corresponding prototype object, provides common properties that are inherited by Module Source constructors and their instances.
  • does not have a global name or appear as a property of the global object.
  • acts as a common superclass of the constructors of Module Source Objects.
  • will throw an error when invoked, because it is an abstract class constructor. The module source constructors do not perform a super call to it.

28.1.1.1 %AbstractModuleSource% ( )

This function performs the following steps when called:

  1. Throw a TypeError exception.

28.1.2 Properties of the %AbstractModuleSource% Intrinsic Object

The %AbstractModuleSource% intrinsic object:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has a "name" property whose value is "AbstractModuleSource".
  • has the following properties:

28.1.2.1 %AbstractModuleSource%.prototype

The initial value of %AbstractModuleSource%.prototype is the %AbstractModuleSource% prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

28.1.3 Properties of the %AbstractModuleSource% Prototype Object

The %AbstractModuleSource% prototype object:

28.1.3.1 %AbstractModuleSource%.prototype.constructor

The initial value of %AbstractModuleSource%.prototype.constructor is %AbstractModuleSource%.

28.1.3.2 get %AbstractModuleSource%.prototype [ @@toStringTag ]

%AbstractModuleSource%.prototype [@@toStringTag] is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, return undefined.
  3. Let sourceNameResult be Completion(HostGetModuleSourceName(O)).
  4. If sourceNameResult is an abrupt completion, return undefined.
  5. Let name be ! sourceNameResult.
  6. Assert: name is a String.
  7. Return name.

This property has the attributes { [[Enumerable]]: false, [[Configurable]]: true }.

The initial value of the "name" property of this function is "get [Symbol.toStringTag]".

A Host Layering Points

A.1 Host Hooks

HostCallJobCallback(...)

HostEnqueueFinalizationRegistryCleanupJob(...)

HostEnqueueGenericJob(...)

HostEnqueuePromiseJob(...)

HostEnqueueTimeoutJob(...)

HostEnsureCanCompileStrings(...)

HostFinalizeImportMeta(...)

HostGetImportMetaProperties(...)

HostGetModuleSourceName(...)

HostGrowSharedArrayBuffer(...)

HostHasSourceTextAvailable(...)

HostLoadImportedModule(...)

HostMakeJobCallback(...)

HostPromiseRejectionTracker(...)

HostResizeArrayBuffer(...)

InitializeHostDefinedRealm(...)

B Copyright & Software License

Copyright Notice

© 2024 Luca Casonato, Guy Bedford, Nicolò Ribaudo

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.