Stage 4 Draft / June 20, 2019

import()

Introduction

Background explanatory material for this specification can be found in the tc39/proposal-dynamic-import repository. See also the issues and the HTML integration spec that builds on top of the below JavaScript specification.

1Modules

1.1Module Semantics

1.1.1Runtime Semantics: HostResolveImportedModule ( referencingModulereferencingScriptOrModule, specifier )

HostResolveImportedModule is an implementation defined abstract operation that provides the concrete Module Record subclass instance that corresponds to the ModuleSpecifier String, specifier, occurring within the context of the script or module represented by the Script Record or Module Record referencingModulereferencingScriptOrModule. referencingScriptOrModule may also be null, if the resolution is being performed in the context of an import() expression, and there is no active script or module at that time.

Note

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

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

The implementation of HostResolveImportedModule must conform to the following requirements:

  • The normal return value must be an instance of a concrete subclass of Module Record.
  • If a Module Record corresponding to the pair referencingModulereferencingScriptOrModule, specifier does not exist or cannot be created, an exception must be thrown.
  • This operation must be idempotent if it completes normally. Each time it is called with a specific referencingModulereferencingScriptOrModule, specifier pair as arguments it must return the same Module Record instance.

Multiple different referencingModulereferencingScriptOrModule, specifier pairs may map to the same Module Record instance. The actual mapping semantic is implementation 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 alphabetic case folding and expansion of relative and abbreviated path specifiers.

1.1.2Runtime Semantics: HostImportModuleDynamically ( referencingScriptOrModule, specifier, promiseCapability )

HostImportModuleDynamically is an implementation defined abstract operation that performs any necessary setup work in order to make available the module corresponding to the ModuleSpecifier String, specifier, occurring within the context of the script or module represented by the Script Record or Module Record referencingScriptOrModule. (referencingScriptOrModule may also be null, if there is no active script or module when the import() expression occurs.) It then performs FinishDynamicImport to finish the dynamic import process.

The implementation of HostImportModuleDynamically must conform to the following requirements:

  • The abstract operation must always complete normally with undefined. Success or failure must instead be signaled as discussed below.
  • The host environment must conform to one of the two following sets of requirements:
    Success path
    • At some future time, the host environment must perform FinishDynamicImport(referencingScriptOrModule, specifier, promiseCapability, NormalCompletion(undefined)).
    • Any subsequent call to HostResolveImportedModule after FinishDynamicImport has completed, given the arguments referencingScriptOrModule and specifier, must complete normally.
    • The completion value of any subsequent call to HostResolveImportedModule after FinishDynamicImport has completed, given the arguments referencingScriptOrModule and specifier, must be a module which has already been evaluated, i.e. whose Evaluate concrete method has already been called and returned a normal completion.
    Failure path

    The intent of this specification is to not violate run to completion semantics. The spec-level formalization of this is a work-in-progress.

  • Every call to HostImportModuleDynamically with the same referencingScriptOrModule and specifier arguments must conform to the same set of requirements above as previous calls do. That is, if the host environment takes the success path once for a given referencingScriptOrModule, specifier pair, it must always do so, and the same for the failure path.
  • The operation must not call promiseCapability.[[Resolve]] or promiseCapability.[[Reject]], but instead must treat promiseCapability as an opaque identifying value to be passed through to FinishDynamicImport.

The actual process performed is implementation defined, but typically consists of performing whatever I/O operations are necessary to allow HostResolveImportedModule to synchronously retrieve the appropriate Module Record, and then calling its Evaluate concrete method. This might require performing similar normalization as HostResolveImportedModule does.

1.1.3Runtime Semantics: FinishDynamicImport ( referencingScriptOrModule, specifier, promiseCapability, completion )

FinishDynamicImport completes the process of a dynamic import originally started by an import() call, resolving or rejecting the promise returned by that call as appropriate according to completion. It is performed by host environments as part of HostImportModuleDynamically.

  1. If completion is an abrupt completion, then perform ! Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] »).
  2. Otherwise,
    1. Assert: completion is a normal completion and completion.[[Value]] is undefined.
    2. Let moduleRecord be ! HostResolveImportedModule(referencingScriptOrModule, specifier).
    3. Assert: Evaluate has already been invoked on moduleRecord and successfully completed.
    4. Let namespace be GetModuleNamespace(moduleRecord).
    5. If namespace is an abrupt completion, perform ! Call(promiseCapability.[[Reject]], undefined, « namespace.[[Value]] »).
    6. Otherwise, perform ! Call(promiseCapability.[[Resolve]], undefined, « namespace.[[Value]] »).

2Left-Hand-Side Expressions

Syntax

CallExpression[Yield, Await]:MemberExpression[?Yield, ?Await]Arguments[?Yield, ?Await] SuperCall[?Yield, ?Await] ImportCall[?Yield, ?Await] CallExpression[?Yield, ?Await]Arguments[?Yield, ?Await] CallExpression[?Yield, ?Await][Expression[+In, ?Yield, ?Await]] CallExpression[?Yield, ?Await].IdentifierName CallExpression[?Yield, ?Await]TemplateLiteral[?Yield, ?Await] ImportCall[Yield, Await]:import(AssignmentExpression[+In, ?Yield, ?Await])

2.1Static Semantics

2.1.1Static Semantics: AssignmentTargetType

CallExpression:CallExpression[Expression] CallExpression.IdentifierName MemberExpression:MemberExpression[Expression] MemberExpression.IdentifierName SuperProperty
  1. Return simple.
CallExpression:CoverCallExpressionAndAsyncArrowHead SuperCall ImportCall CallExpressionArguments CallExpressionTemplateLiteral NewExpression:newNewExpression MemberExpression:MemberExpressionTemplateLiteral newMemberExpressionArguments NewTarget:new.target
  1. Return invalid.

2.2Import Calls

2.2.1Runtime Semantics: Evaluation

ImportCall:import(AssignmentExpression)
  1. Let referencingScriptOrModule be ! GetActiveScriptOrModule().
  2. Let argRef be the result of evaluating AssignmentExpression.
  3. Let specifier be ? GetValue(argRef).
  4. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  5. Let specifierString be ToString(specifier).
  6. IfAbruptRejectPromise(specifierString, promiseCapability).
  7. Perform ! HostImportModuleDynamically(referencingScriptOrModule, specifierString, promiseCapability).
  8. Return promiseCapability.[[Promise]].

3Forbidden Extensions

An implementation must not extend this specification in the following ways: