HostResolveImportedModule is an implementation-defined abstract operation that provides the concrete Module Record subclass instance that corresponds to the |ModuleSpecifier| String, _specifier_,the ModuleRequest Record _moduleRequest_ occurring within the context of the script or module represented by the Script Record or Module Record _referencingScriptOrModule_. _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.
+
+ 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~.
- An example of when _referencingScriptOrModule_ can be *null* is in a web browser host. There, if a user clicks on a control given by
+ 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.
- The implementation of HostResolveImportedModule must conform to the following requirements:
+ An implementation of HostLoadImportedModule must conform to the following requirements:
-
- The normal return value must be an instance of a concrete subclass of Module Record.
+ The host environment must perform FinishLoadingImportedModule(_referrer_,
_specifier__moduleRequest_, _payload_, _result_), where _result_ is either a normal completion containing the loaded Module Record or a throw completion, either synchronously or asynchronously.
-
- If a Module Record corresponding to the pair _referencingScriptOrModule_,
_specifier_, _moduleRequest_ does not exist or cannot be created, an exception must be thrown.
-
- -
- Each time this operation is called with a specific _referencingScriptOrModule_,
_specifier_ pair _moduleRequest_.[[Specifier]], _moduleRequest_.[[Assertions]] triple as arguments it must return the same Module Record instance if it completes normally.
+ If this operation is called multiple times with the same (_referrer_, _specifier_) pair(_referrer_, _moduleRequest_.[[Specifier]], _moduleRequest_.[[Assertions]]) triple and it performs FinishLoadingImportedModule(_referrer_, _specifier__moduleRequest_, _payload_, _result_) where _result_ is a normal completion, then it must perform FinishLoadingImportedModule(_referrer_, _specifier__moduleRequest_, _payload_, _result_) with the same _result_ each time.
+
+ It is recommended but not required that implementations additionally conform to the following stronger constraint:
-
- It is recommended but not required that implementations additionally conform to the following stronger constraint: each time this operation is called with a specific _referencingScriptOrModule_, _moduleRequest_.[[Specifier]] pair as arguments it must return the same Module Record instance if it completes normally.
+ If this operation is called multiple times with the same (_referrer_, _moduleRequest_.[[Specifier]]) pair and it performs FinishLoadingImportedModule(_referrer_, _moduleRequest_, _payload_, _result_) where _result_ is a normal completion, then it must perform FinishLoadingImportedModule(_referrer_, _moduleRequest_, _payload_, _result_) with the same _result_ each time.
-
_moduleRequest_.[[Assertions]] must not influence the interpretation of the module or the module specifier; instead, it may be used to determine whether the algorithm completes normally or with an abrupt completion.
+ -
+ The operation must treat _payload_ as an opaque value to be passed through to FinishLoadingImportedModule.
+
- Multiple different _referencingScriptOrModule_, _specifier_ _moduleRequest_.[[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.
+
+ 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_, _specifier__moduleRequest_.[[Specifier]]) pairs may map to the same Module Record instance. The actual mapping semantic is host-defined but typically a normalization process is applied to _specifier__moduleRequest_.[[Specifier]] as part of the mapping process. A typical normalization process would include actions such as expansion of relative and abbreviated path specifiers.
The above text implies that is recommended but not required that hosts do not use _moduleRequest_.[[Assertions]] as part of the module cache key. In either case, an exception thrown from an import with a given assertion list does not rule out success of another import with the same specifier but a different assertion list.
@@ -166,67 +169,41 @@ Runtime Semantics: HostResolveImportedModule ( _referencingScriptOrModule_,
-
- Runtime Semantics: HostImportModuleDynamically ( _referencingScriptOrModule_, _specifier_, _moduleRequest_, _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_,ModuleRequest Record _moduleRequest_ 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_, _moduleRequest_, _promiseCapability_, NormalCompletion(*undefined*)).
-
- - Any subsequent call to HostResolveImportedModule after FinishDynamicImport has completed, given the arguments _referencingScriptOrModule_, and
_specifier_ _moduleRequest_ must complete normally.
-
- - The completion value of any subsequent call to HostResolveImportedModule after FinishDynamicImport has completed, given the arguments _referencingScriptOrModule_, and
_specifier_, _moduleRequest_ 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
-
- -
-
- - At some future time, the host environment must perform FinishDynamicImport(_referencingScriptOrModule_,
_specifier_, _moduleRequest_, _promiseCapability_, an abrupt completion), with the abrupt completion representing the cause of failure.
-
-
-
-
- -
- If the host environment takes the success path once for a given _referencingScriptOrModule_,
_specifier_, _moduleRequest_ pair, it must always do so for subsequent calls.
-
- -
- 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.
-
-
-
- Runtime Semantics: FinishDynamicImport ( _referencingScriptOrModule_, _specifier_, _moduleRequest_, _promiseCapability_, _completion_ )
- The abstract operation FinishDynamicImport takes arguments _referencingScriptOrModule_, _specifier_, _moduleRequest_ (a ModuleRequest Record), _promiseCapability_, and _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. It performs the following steps when called:
-
+
+ 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~.
- 1. If _completion_ is an abrupt completion, then perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _completion_.[[Value]] »).
+ 1. If _result_ is a normal completion, then
+ 1. If _referrer_.[[LoadedModules]] contains a Record _record_ such that _record_.[[Specifier]] is _moduleRequest_.[[Specifier]] and AssertionsEqual(_record_.[[Assertions]], _moduleRequest_.[[Assertions]]) is *true*, then
+ 1. Assert: _record_.[[Module]] is _result_.[[Value]].
+ 1. Else, add Record { [[Specifier]]: _moduleRequest_.[[Specifier]], [[Assertions]]: _moduleRequest_.[[Assertions]], [[Module]]: _result_.[[Value]] } to _referrer_.[[LoadedModules]].
+ 1. If _payload_ is a GraphLoadingState Record, then
+ 1. Perform ContinueModuleLoading(_payload_, _result_).
1. Else,
- 1. Assert: _completion_ is a normal completion and _completion_.[[Value]] is *undefined*.
- 1. Let _moduleRecord_ be ! HostResolveImportedModule(_referencingScriptOrModule_, _specifier_, _moduleRequest_).
- 1. Assert: Evaluate has already been invoked on _moduleRecord_ and successfully completed.
- 1. Let _namespace_ be GetModuleNamespace(_moduleRecord_).
- 1. If _namespace_ is an abrupt completion, perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _namespace_.[[Value]] »).
- 1. Else, perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _namespace_.[[Value]] »).
+ 1. Perform ContinueDynamicImport(_payload_, _result_).
+ 1. Return ~unused~.
+
+
+ The description of the [[LoadedModules]] field of Realm Record, Script Record, and Cyclic Module Record should be updated to include the [[Assertions]] field.
+
+
+
+ AssertionsEqual(_left_, _right_)
+ The abstract operation AssertionsEqual takes arguments _left_ and _right_ (two Lists of Records { [[Key]]: a String, [[Value]]: a String }), and returns a Boolean.
+
+
+ 1. If the number of elements in _left_ is not the same as the number of elements in _right_, return *false*.
+ 1. For each Record { [[Key]], [[Value]] } _r_ of _left_, do
+ 1. Let _found_ be *false*.
+ 1. For each Record { [[Key]], [[Value]] } _s_ of _right_, do
+ 1. If _r_.[[Key]] is _s_.[[Key]] and _r_.[[Value]] is _s_.[[Value]], then
+ 1. Set _found_ to *true*.
+ 1. If _found_ is *false*, return *false*.
+ 1. Return *true*.
+
+
@@ -312,7 +289,7 @@ Static Semantics: StringValue
ModuleRequest Records
A ModuleRequest Record represents the request to import a module with given import assertions. It consists of the following fields:
-
+
@@ -558,7 +535,7 @@ Sample host integration: The Web embedding
- The module script would have an additional item, which would be the module type, as a string (e.g., *"json"*), or *undefined* for a JavaScript module.
- - HostResolveImportedModule and HostImportModuleDynamically would take a ModuleRequest Record parameter in place of a specifier string, which would be passed down through several abstract operations to reach the fetch a single module script algorithm. Somewhere near the entrypoint, if the ModuleRequest Record's [[Assertions]] field has an element _entry_ such that _entry_.[[Key]] is *"type"*, then let _type_ be _entry_.[[Value]]; otherwise let _type_ be *undefined*. If the type is invalid, then an exception is thrown and module loading fails. Otherwise, this will equal the module type, if the module can be successfully fetched with a matching MIME type.
+ - HostLoadImportedModule would take a ModuleRequest Record parameter in place of a specifier string, which would be passed down through several abstract operations to reach the fetch a single module script algorithm. Somewhere near the entrypoint, if the ModuleRequest Record's [[Assertions]] field has an element _entry_ such that _entry_.[[Key]] is *"type"*, then let _type_ be _entry_.[[Value]]; otherwise let _type_ be *undefined*. If the type is invalid, then an exception is thrown and module loading fails. Otherwise, this will equal the module type, if the module can be successfully fetched with a matching MIME type.
- In the fetch the descendents of a module script algorithm, when iterating over [[RequestedModules]], the elements are ModuleRequest Records rather than just specifier strings; these Records is passed on to the internal module script graph fetching procedure (which sends it to "fetch a single module script". Other usage sites of [[RequestedModules]] ignore the assertion.
- "Fetch a single module script" would check the assertion in two places: