Stage 2 Draft / January 20, 2026

Import Sync

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

13 ECMAScript Language: Expressions

13.3 Left-Hand-Side Expressions

Syntax

ImportCall[Yield, Await] : import ImportCallArguments[?Yield, ?Await] import . defer ImportCallArguments[?Yield, ?Await] import . sync ImportCallArguments[?Yield, ?Await] ImportCallArguments[Yield, Await] : ( AssignmentExpression[+In, ?Yield, ?Await] ,opt ) ( AssignmentExpression[+In, ?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ,opt )

13.3.10 Import Calls

Editor's Note
The changes to this section are intended to mirror the changes proposed by the Source Phase Imports proposal, but adapted to the defer phase.

13.3.10.1 Runtime Semantics: Evaluation

ImportCall : import ImportCallArguments
  1. Return ? EvaluateImportCall(ImportCallArguments, evaluation).
ImportCall : import . defer ImportCallArguments
  1. Return ? EvaluateImportCall(ImportCallArguments, defer).
ImportCall : import . sync ImportCallArguments
  1. Return ? ImportCallSync(ImportCallArguments).

13.3.10.2 ImportCallSync ( arguments )

The abstract operation ImportCallSync takes argument arguments (a Parse Node) and returns either a normal completion 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 specifierString be ? ToString(specifier).
  6. Let attributes be a new empty List.
  7. If options is not undefined, then
    1. If options is not an Object, then
      1. Throw a TypeError exception.
    2. Let attributesObj be ? Get(options, "with").
    3. If attributesObj is not undefined, then
      1. If attributesObj is not an Object, then
        1. Throw a TypeError exception.
      2. Let entries be ? EnumerableOwnProperties(attributesObj, key+value).
      3. 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. Throw a TypeError exception.
          2. Append the ImportAttribute Record { [[Key]]: key, [[Value]]: value } to attributes.
    4. If AllImportAttributesSupported(attributes) is false, then
      1. Throw a TypeError exception.
    5. Sort attributes according to the lexicographic order of their [[Key]] field, treating the value of each such field as a sequence of UTF-16 code unit values. NOTE: This sorting is observable only in that hosts are prohibited from changing behaviour based on the order in which attributes are enumerated.
  8. Let moduleRequest be a new ModuleRequest Record { [[Specifier]]: specifierString, [[Attributes]]: attributes, [[Phase]]: evaluation }.
  9. Let moduleCompletion be NormalCompletion(empty).
  10. Perform HostLoadImportedModule(referrer, moduleRequest, empty, moduleCompletion).
  11. NOTE: HostLoadImportedModule will update moduleCompletion synchronously either updating its value to be a Module Record, or setting it to be a throw completion.
  12. Let module be ? moduleCompletion.
  13. Perform ? module.LoadRequestedModulesSync().
  14. Perform ? module.Link().
  15. If ReadyForSyncExecution(module) is false, throw a TypeError exception.
  16. Perform ? EvaluateModuleSync(module).
  17. Return GetModuleNamespace(module, evaluation).

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

Table 1: 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 2: Abstract Methods of Module Records
Method Purpose
LoadRequestedModules([hostDefined])

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

LoadRequestedModulesSync([hostDefined])

Prepares the module for linking by recursively loading all its dependencies synchronously.

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.

16.2.1.5.1 EvaluateModuleSync ( module )

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

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

16.2.1.6 Cyclic Module Records

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

In addition to the fields defined in Table 1 Cyclic Module Records have the additional fields listed in Table 3

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

In addition to the methods defined in Table 2 Cyclic Module Records have the additional methods listed in Table 4

Table 4: Additional Abstract Methods of Cyclic Module Records
Method Purpose
InitializeEnvironment() Initialize the Environment Record of the module, including resolving all imported bindings, and create the module's execution context.
ExecuteModule( [ promiseCapability ] ) Evaluate 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.

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

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

16.2.1.6.1 LoadRequestedModules ( [ hostDefined ] )

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

  1. If hostDefined is not present, 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).
  5. Return pc.[[Promise]].
Note
The hostDefined parameter can be used to pass additional information necessary to fetch the imported modules. It is used, for example, by HTML to set the correct fetch destination for <link rel="preload" as="..."> tags. import() expressions never set the hostDefined parameter.

16.2.1.6.1.1 InnerModuleLoadingSync ( state, module )

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

  1. TODO.

16.2.1.6.1.2 InnerModuleLoading ( state, module )

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

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

16.2.1.6.1.3 ContinueModuleLoading ( state, moduleCompletion )

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

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

16.2.1.6.2 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, set module to module.[[CycleRoot]].
  4. If module.[[TopLevelCapability]] is not empty, then
    1. Return module.[[TopLevelCapability]].[[Promise]].
  5. Let stack be a new empty List.
  6. Let capability be ! NewPromiseCapability(%Promise%).
  7. Set module.[[TopLevelCapability]] to capability.
  8. Let result be Completion(InnerModuleEvaluation(module, stack, 0)).
  9. If result is an abrupt completion, then
    1. For each Cyclic Module Record m of stack, do
      1. Assert: m.[[Status]] is evaluating.
      2. Set m.[[Status]] to evaluated.
      3. Set m.[[EvaluationError]] to result.
    2. Assert: module.[[Status]] is evaluated.
    3. Assert: module.[[EvaluationError]] is result.
    4. Perform ! Call(capability.[[Reject]], undefined, « result.[[Value]] »).
  10. Else,
    1. Assert: module.[[Status]] is either evaluating-async or evaluated.
    2. Assert: module.[[EvaluationError]] is empty.
    3. If module.[[Status]] is evaluated, then
      1. NOTE: This implies that evaluation of module completed synchronously.
      2. Assert: module.[[AsyncEvaluationOrder]] is unset.
      3. Perform ! Call(capability.[[Resolve]], undefined, « undefined »).
    4. Assert: stack is empty.
  11. Return capability.[[Promise]].

16.2.1.6.2.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 required of module.[[RequestedModules]], do
    1. Let requiredModule be GetImportedModule(module, required.[[Specifier]]).
    2. If required.[[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. Append module to stack.
  13. 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]].
  14. 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).
  15. Else,
    1. Perform ? module.ExecuteModule().
  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. 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.
  19. 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.2.2 GatherAsynchronousTransitiveDependencies ( module [ , seen ] )

The abstract operation GatherAsynchronousTransitiveDependencies takes argument module (a Module Record) and optional argument seen (a List of Module Records) 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. Let result be a new empty List.
  3. If seen contains module, return result.
  4. Append module to seen.
  5. If module is not a Cyclic Module Record, return result.
  6. If module.[[Status]] is either evaluating or evaluated, return result.
  7. If module.[[HasTLA]] is true, then
    1. Append module to result.
    2. Return result.
  8. For each ModuleRequest Record required of module.[[RequestedModules]], do
    1. Let requiredModule be GetImportedModule(module, required).
    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.
  9. Return result.

16.2.1.7 HostLoadImportedModule ( referrer, moduleRequest, hostDefined, payload, payload )

The host-defined abstract operation HostLoadImportedModule takes arguments referrer (a Script Record, a Cyclic Module Record, or a Realm Record), moduleRequest (a ModuleRequest Record), hostDefined (anything), payload (a GraphLoadingState Record or a PromiseCapability Record), and payload (a GraphLoadingState Record, a PromiseCapability Record, or a Completion 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, moduleRequest.[[Specifier]], moduleRequest.[[Attributes]]) triples may map to the same Module Record instance. The actual mapping semantics is host-defined but typically a normalization process is applied to specifier as part of the mapping process. A typical normalization process would include actions such as expansion of relative and abbreviated path specifiers.

Note 2

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

16.2.1.11 FinishLoadingImportedModule ( referrer, moduleRequest, payload, 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), payload (a GraphLoadingState Record, a PromiseCapability Record, or a Completion Record), and result (either a normal completion containing a Module Record or a throw completion) and returns unused. It performs the following steps when called:

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

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.