diff --git a/biblio/proposal-defer-import-eval.json b/biblio/proposal-defer-import-eval.json
new file mode 100644
index 0000000..7922b19
--- /dev/null
+++ b/biblio/proposal-defer-import-eval.json
@@ -0,0 +1 @@
+{"location":"https://tc39.es/proposal-defer-import-eval","entries":[{"type":"term","term":"module namespace exotic object","id":"module-namespace-exotic-object","variants":["module namespace exotic objects"]},{"type":"table","id":"table-internal-slots-of-module-namespace-exotic-objects","number":1,"caption":"Table 1: Internal Slots of Module Namespace Exotic Objects"},{"type":"clause","id":"sec-module-namespace-exotic-objects-getownproperty-p","aoid":null,"title":"[[GetOwnProperty]] ( P )","titleHTML":"[[GetOwnProperty]] ( P )","number":"10.4.6.5"},{"type":"clause","id":"sec-module-namespace-exotic-objects-defineownproperty-p-desc","aoid":null,"title":"[[DefineOwnProperty]] ( P, Desc )","titleHTML":"[[DefineOwnProperty]] ( P, Desc )","number":"10.4.6.6"},{"type":"clause","id":"sec-module-namespace-exotic-objects-hasproperty-p","aoid":null,"title":"[[HasProperty]] ( P )","titleHTML":"[[HasProperty]] ( P )","number":"10.4.6.7"},{"type":"clause","id":"sec-module-namespace-exotic-objects-get-p-receiver","aoid":null,"title":"[[Get]] ( P, Receiver )","titleHTML":"[[Get]] ( P, Receiver )","number":"10.4.6.8"},{"type":"clause","id":"sec-module-namespace-exotic-objects-set-p-v-receiver","aoid":null,"title":"[[Set]] ( P, V, Receiver )","titleHTML":"[[Set]] ( P, V, Receiver )","number":"10.4.6.9"},{"type":"clause","id":"sec-module-namespace-exotic-objects-delete-p","aoid":null,"title":"[[Delete]] ( P )","titleHTML":"[[Delete]] ( P )","number":"10.4.6.10"},{"type":"clause","id":"sec-module-namespace-exotic-objects-ownpropertykeys","aoid":null,"title":"[[OwnPropertyKeys]] ( )","titleHTML":"[[OwnPropertyKeys]] ( )","number":"10.4.6.11"},{"type":"op","aoid":"ModuleNamespaceCreate","refId":"sec-modulenamespacecreate","kind":"abstract operation","signature":{"parameters":[{"name":"_module_","type":{"kind":"opaque","type":"a Module Record"}},{"name":"_exports_","type":{"kind":"list","elements":{"kind":"opaque","type":"Strings"}}},{"name":"_phase_","type":{"kind":"union","types":[{"kind":"opaque","type":"~defer~"},{"kind":"opaque","type":"~evaluation~"}]}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a module namespace exotic object"}},"effects":[]},{"type":"clause","id":"sec-modulenamespacecreate","aoid":"ModuleNamespaceCreate","title":"ModuleNamespaceCreate ( module, exports, phase )","titleHTML":"ModuleNamespaceCreate ( module, exports, phase )","number":"10.4.6.12"},{"type":"op","aoid":"IsSymbolLikeNamespaceKey","refId":"sec-IsSymbolLikeNamespaceKey","kind":"abstract operation","signature":{"parameters":[{"name":"_P_","type":{"kind":"opaque","type":"a property key"}},{"name":"_ns_","type":{"kind":"opaque","type":"a module namespace exotic object"}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a Boolean"}},"effects":[]},{"type":"clause","id":"sec-IsSymbolLikeNamespaceKey","aoid":"IsSymbolLikeNamespaceKey","title":"IsSymbolLikeNamespaceKey ( P, ns )","titleHTML":"IsSymbolLikeNamespaceKey ( P, ns )","number":"10.4.6.13"},{"type":"op","aoid":"ReadyForSyncExecution","refId":"sec-ReadyForSyncExecution","kind":"abstract operation","signature":{"parameters":[{"name":"_module_","type":{"kind":"opaque","type":"a Module Record"}}],"optionalParameters":[{"name":"_seen_","type":{"kind":"list","elements":{"kind":"opaque","type":"Module Records"}}}],"return":{"kind":"opaque","type":"a Boolean"}},"effects":[]},{"type":"clause","id":"sec-ReadyForSyncExecution","aoid":"ReadyForSyncExecution","title":"ReadyForSyncExecution ( module [ , seen ] )","titleHTML":"ReadyForSyncExecution ( module [ , seen ] )","number":"10.4.6.14.1"},{"type":"op","aoid":"GetModuleExportsList","refId":"sec-GetModuleExportsList","kind":"abstract operation","signature":{"parameters":[{"name":"_O_","type":{"kind":"opaque","type":"a module namespace exotic object"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"list","elements":{"kind":"opaque","type":"Strings"}}}},"effects":[]},{"type":"clause","id":"sec-GetModuleExportsList","aoid":"GetModuleExportsList","title":"GetModuleExportsList ( O )","titleHTML":"GetModuleExportsList ( O )","number":"10.4.6.14"},{"type":"clause","id":"sec-module-namespace-exotic-objects","aoid":null,"title":"Module Namespace Exotic Objects","titleHTML":"Module Namespace Exotic Objects","number":"10.4.6"},{"type":"clause","id":"sec-built-in-exotic-object-internal-methods-and-slots","aoid":null,"title":"Built-in Exotic Object Internal Methods and Slots","titleHTML":"Built-in Exotic Object Internal Methods and Slots","number":"10.4"},{"type":"clause","id":"sec-ordinary-and-exotic-objects-behaviours","aoid":null,"title":"Ordinary and Exotic Objects Behaviours","titleHTML":"Ordinary and Exotic Objects Behaviours","number":"10"},{"type":"production","id":"prod-ImportCall","name":"ImportCall"},{"type":"production","id":"prod-ImportCallArguments","name":"ImportCallArguments"},{"type":"clause","id":"sec-import-call-runtime-semantics-evaluation","aoid":null,"title":"Runtime Semantics: Evaluation","titleHTML":"Runtime Semantics: Evaluation","number":"13.3.10.1"},{"type":"clause","id":"sec-import-call-runtime-semantics-EvaluateImportCallSpecifier","aoid":null,"title":"Runtime Semantics: EvaluateImportCallSpecifier","titleHTML":"Runtime Semantics: EvaluateImportCallSpecifier","number":"13.3.10.2"},{"type":"clause","id":"sec-import-call-runtime-semantics-EvaluateImportCallOptions","aoid":null,"title":"Runtime Semantics: EvaluateImportCallOptions","titleHTML":"Runtime Semantics: EvaluateImportCallOptions","number":"13.3.10.3"},{"type":"op","aoid":"ContinueDynamicImport","refId":"sec-ContinueDynamicImport","kind":"abstract operation","signature":{"parameters":[{"name":"_promiseCapability_","type":{"kind":"opaque","type":"a PromiseCapability Record"}},{"name":"_moduleCompletion_","type":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"opaque","type":"a Module Record"}}},{"name":"_phase_","type":{"kind":"union","types":[{"kind":"opaque","type":"~defer~"},{"kind":"opaque","type":"~evaluation~"}]}}],"optionalParameters":[],"return":{"kind":"unused"}},"effects":[]},{"type":"clause","id":"sec-ContinueDynamicImport","aoid":"ContinueDynamicImport","title":"ContinueDynamicImport ( promiseCapability, moduleCompletion, phase )","titleHTML":"ContinueDynamicImport ( promiseCapability, moduleCompletion, phase )","number":"13.3.10.4.1"},{"type":"op","aoid":"EvaluateImportCall","refId":"sec-evaluate-import-call","kind":"abstract operation","signature":{"parameters":[{"name":"_arguments_","type":{"kind":"opaque","type":"a Parse Node"}},{"name":"_phase_","type":{"kind":"union","types":[{"kind":"opaque","type":"~defer~"},{"kind":"opaque","type":"~evaluation~"}]}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"opaque","type":"a Promise"}}},"effects":["user-code"]},{"type":"clause","id":"sec-evaluate-import-call","aoid":"EvaluateImportCall","title":"EvaluateImportCall ( arguments, phase, specifierExpression [ , optionsExpression ] )","titleHTML":"EvaluateImportCall ( arguments, phase, specifierExpression [ , optionsExpression ] )","number":"13.3.10.4"},{"type":"clause","id":"sec-import-calls","aoid":null,"title":"Import Calls","titleHTML":"Import Calls","number":"13.3.10"},{"type":"clause","id":"sec-left-hand-side-expressions","aoid":null,"title":"Left-Hand-Side Expressions","titleHTML":"Left-Hand-Side Expressions","number":"13.3"},{"type":"clause","id":"sec-ecmascript-language-expressions","aoid":null,"title":"ECMAScript Language: Expressions","titleHTML":"ECMAScript Language: Expressions","number":"13"},{"type":"production","id":"prod-Module","name":"Module"},{"type":"production","id":"prod-ModuleBody","name":"ModuleBody"},{"type":"production","id":"prod-ModuleItemList","name":"ModuleItemList"},{"type":"production","id":"prod-ModuleItem","name":"ModuleItem"},{"type":"production","id":"prod-ModuleExportName","name":"ModuleExportName"},{"type":"term","term":"ModuleRequest Record","id":"modulerequest-record","variants":["ModuleRequest Records"]},{"type":"table","id":"table-modulerequest-fields","number":2,"caption":"Table 2: ModuleRequest Record Fields"},{"type":"op","aoid":"ModuleRequestsEqual","refId":"sec-ModuleRequestsEqual","kind":"abstract operation","signature":{"parameters":[{"name":"_left_","type":{"kind":"union","types":[{"kind":"opaque","type":"a ModuleRequest Record"},{"kind":"opaque","type":"a LoadedModuleRequest Record"}]}},{"name":"_right_","type":{"kind":"union","types":[{"kind":"opaque","type":"a ModuleRequest Record"},{"kind":"opaque","type":"a LoadedModuleRequest Record"}]}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a Boolean"}},"effects":[]},{"type":"clause","id":"sec-ModuleRequestsEqual","aoid":"ModuleRequestsEqual","title":"ModuleRequestsEqual ( left, right )","titleHTML":"ModuleRequestsEqual ( left, right )","number":"16.2.1.1.1"},{"type":"clause","id":"sec-modulerequest-record","aoid":null,"title":"ModuleRequest Records","titleHTML":"ModuleRequest Records","number":"16.2.1.1"},{"type":"op","aoid":"ModuleRequests","refId":"sec-static-semantics-modulerequests","kind":"syntax-directed operation","signature":{"parameters":[],"optionalParameters":[],"return":{"kind":"list","elements":{"kind":"opaque","type":"ModuleRequest Records"}}},"effects":[]},{"type":"clause","id":"sec-static-semantics-modulerequests","aoid":"ModuleRequests","title":"Static Semantics: ModuleRequests","titleHTML":"Static Semantics: ModuleRequests","number":"16.2.1.3"},{"type":"term","term":"Module Record","refId":"sec-abstract-module-records","variants":["Module Records"]},{"type":"table","id":"table-module-record-fields","number":3,"caption":"Table 3: Module Record Fields"},{"type":"op","aoid":"EvaluateModuleSync","refId":"sec-EvaluateModuleSync","kind":"abstract operation","signature":{"parameters":[{"name":"_module_","type":{"kind":"opaque","type":"a Module Record"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"unused"}}},"effects":[]},{"type":"clause","id":"sec-EvaluateModuleSync","aoid":"EvaluateModuleSync","title":"EvaluateModuleSync ( module )","titleHTML":"EvaluateModuleSync ( module )","number":"16.2.1.4.1"},{"type":"clause","id":"sec-abstract-module-records","aoid":null,"title":"Abstract Module Records","titleHTML":"Abstract Module Records","number":"16.2.1.4"},{"type":"term","term":"Cyclic Module Record","id":"cyclic-module-record","variants":["Cyclic Module Records"]},{"type":"op","aoid":"InnerModuleLoading","refId":"sec-InnerModuleLoading","kind":"abstract operation","signature":{"parameters":[{"name":"_state_","type":{"kind":"opaque","type":"a GraphLoadingState Record"}},{"name":"_module_","type":{"kind":"opaque","type":"a Module Record"}}],"optionalParameters":[],"return":{"kind":"unused"}},"effects":[]},{"type":"clause","id":"sec-InnerModuleLoading","aoid":"InnerModuleLoading","title":"InnerModuleLoading ( state, module )","titleHTML":"InnerModuleLoading ( state, module )","number":"16.2.1.5.1.1"},{"type":"clause","id":"sec-LoadRequestedModules","aoid":null,"title":"LoadRequestedModules ( [ hostDefined ] )","titleHTML":"LoadRequestedModules ( [ hostDefined ] )","number":"16.2.1.5.1"},{"type":"op","aoid":"InnerModuleLinking","refId":"sec-InnerModuleLinking","kind":"abstract operation","signature":{"parameters":[{"name":"_module_","type":{"kind":"opaque","type":"a Module Record"}},{"name":"_stack_","type":{"kind":"list","elements":{"kind":"opaque","type":"Cyclic Module Records"}}},{"name":"_index_","type":{"kind":"opaque","type":"a non-negative integer"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"opaque","type":"a non-negative integer"}}},"effects":[]},{"type":"clause","id":"sec-InnerModuleLinking","aoid":"InnerModuleLinking","title":"InnerModuleLinking ( module, stack, index )","titleHTML":"InnerModuleLinking ( module, stack, index )","number":"16.2.1.5.2.1"},{"type":"clause","id":"sec-moduledeclarationlinking","aoid":null,"title":"Link ( )","titleHTML":"Link ( )","number":"16.2.1.5.2"},{"type":"op","aoid":"InnerModuleEvaluation","refId":"sec-innermoduleevaluation","kind":"abstract operation","signature":{"parameters":[{"name":"_module_","type":{"kind":"opaque","type":"a Module Record"}},{"name":"_stack_","type":{"kind":"list","elements":{"kind":"opaque","type":"Cyclic Module Records"}}},{"name":"_index_","type":{"kind":"opaque","type":"a non-negative integer"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"opaque","type":"a non-negative integer"}}},"effects":["user-code"]},{"type":"clause","id":"sec-innermoduleevaluation","aoid":"InnerModuleEvaluation","title":"InnerModuleEvaluation ( module, stack, index )","titleHTML":"InnerModuleEvaluation ( module, stack, index )","number":"16.2.1.5.3.1"},{"type":"op","aoid":"GatherAsynchronousTransitiveDependencies","refId":"sec-GatherAsynchronousTransitiveDependencies","kind":"abstract operation","signature":{"parameters":[{"name":"_module_","type":{"kind":"opaque","type":"a Module Record"}}],"optionalParameters":[{"name":"_seen_","type":{"kind":"list","elements":{"kind":"opaque","type":"Module Records"}}}],"return":{"kind":"list","elements":{"kind":"opaque","type":"Module Records"}}},"effects":[]},{"type":"clause","id":"sec-GatherAsynchronousTransitiveDependencies","aoid":"GatherAsynchronousTransitiveDependencies","title":"GatherAsynchronousTransitiveDependencies ( module [ , seen ] )","titleHTML":"GatherAsynchronousTransitiveDependencies ( module [ , seen ] )","number":"16.2.1.5.3.2"},{"type":"clause","id":"sec-moduleevaluation","aoid":null,"title":"Evaluate ( )","titleHTML":"Evaluate ( )","number":"16.2.1.5.3"},{"type":"figure","id":"figure-module-graph-simple","number":1,"caption":"Figure 1: A simple module graph"},{"type":"figure","id":"figure-module-graph-missing","number":2,"caption":"Figure 2: A module graph with an unresolvable module"},{"type":"figure","id":"figure-module-graph-cycle","number":3,"caption":"Figure 3: A cyclic module graph"},{"type":"figure","id":"figure-module-graph-cycle-async","number":4,"caption":"Figure 4: An asynchronous cyclic module graph"},{"type":"table","id":"table-module-graph-cycle-async-fields-1","number":4,"caption":"Table 4: Module fields after the initial Evaluate() call"},{"type":"table","id":"table-module-graph-cycle-async-fields-2","number":5,"caption":"Table 5: Module fields after module _E_ finishes executing"},{"type":"table","id":"table-module-graph-cycle-async-fields-3","number":6,"caption":"Table 6: Module fields after module _D_ finishes executing"},{"type":"table","id":"table-module-graph-cycle-async-fields-4","number":7,"caption":"Table 7: Module fields after module _C_ finishes executing"},{"type":"table","id":"table-module-graph-cycle-async-fields-5","number":8,"caption":"Table 8: Module fields after module _B_ finishes executing"},{"type":"table","id":"table-module-graph-cycle-async-fields-6","number":9,"caption":"Table 9: Module fields after module _A_ finishes executing"},{"type":"table","id":"table-module-graph-cycle-async-fields-7","number":10,"caption":"Table 10: Module fields after module _C_ finishes with an error"},{"type":"table","id":"table-module-graph-cycle-async-fields-8","number":11,"caption":"Table 11: Module fields after module _A_ is rejected"},{"type":"table","id":"table-module-graph-cycle-async-fields-9","number":12,"caption":"Table 12: Module fields after module _B_ finishes executing in an erroring graph"},{"type":"figure","id":"figure-module-graph-deferred-simple","number":5,"caption":"Figure 5: A simple module graph with a deferred import"},{"type":"figure","id":"figure-module-graph-deferred-async","number":6,"caption":"Figure 6: A simple module graph with a deferred import and a transitive asynchronous dependency"},{"type":"table","id":"table-module-graph-deferred-async-fields-1","number":13,"caption":"Table 13: Module fields after the initial Evaluate() call"},{"type":"table","id":"table-module-graph-deferred-async-fields-2","number":14,"caption":"Table 14: Module fields after _C_ finishes executing"},{"type":"table","id":"table-module-graph-deferred-async-fields-3","number":15,"caption":"Table 15: Module fields after _C_ finishes executing with an exception"},{"type":"figure","id":"figure-module-graph-deferred-async-cycle-root","number":7,"caption":"Figure 7: A module graph with a deferred import and a cycle back to the root"},{"type":"table","id":"table-module-graph-deferred-async-cycle-root-fields-1","number":16,"caption":"Table 16: Module fields after the initial Evaluate() call"},{"type":"table","id":"table-module-graph-deferred-async-cycle-root-fields-2","number":17,"caption":"Table 17: Module fields after the _B_.ExecuteModule() call"},{"type":"clause","id":"sec-example-cyclic-module-record-graphs-deferred-imports","aoid":null,"title":"Example Cyclic Module Record Graphs with Deferred Imports","titleHTML":"Example Cyclic Module Record Graphs with Deferred Imports","number":"16.2.1.5.4.1"},{"type":"clause","id":"sec-example-cyclic-module-record-graphs","aoid":null,"title":"Example Cyclic Module Record Graphs","titleHTML":"Example Cyclic Module Record Graphs","number":"16.2.1.5.4"},{"type":"clause","id":"sec-cyclic-module-records","aoid":null,"title":"Cyclic Module Records","titleHTML":"Cyclic Module Records","number":"16.2.1.5"},{"type":"clause","id":"sec-source-text-module-record-initialize-environment","aoid":null,"title":"InitializeEnvironment ( )","titleHTML":"InitializeEnvironment ( )","number":"16.2.1.6.4"},{"type":"clause","id":"sec-source-text-module-records","aoid":null,"title":"Source Text Module Records","titleHTML":"Source Text Module Records","number":"16.2.1.6"},{"type":"op","aoid":"FinishLoadingImportedModule","refId":"sec-FinishLoadingImportedModule","kind":"abstract operation","signature":{"parameters":[{"name":"_referrer_","type":{"kind":"union","types":[{"kind":"opaque","type":"a Script Record"},{"kind":"opaque","type":"a Cyclic Module Record"},{"kind":"opaque","type":"a Realm Record"}]}},{"name":"_moduleRequest_","type":{"kind":"opaque","type":"a ModuleRequest Record"}},{"name":"_payload_","type":{"kind":"union","types":[{"kind":"opaque","type":"a GraphLoadingState Record"},{"kind":"opaque","type":"a PromiseCapability Record"}]}},{"name":"_result_","type":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"opaque","type":"a Module Record"}}}],"optionalParameters":[],"return":{"kind":"unused"}},"effects":[]},{"type":"clause","id":"sec-FinishLoadingImportedModule","aoid":"FinishLoadingImportedModule","title":"FinishLoadingImportedModule ( referrer, moduleRequest, payload, result )","titleHTML":"FinishLoadingImportedModule ( referrer, moduleRequest, payload, result )","number":"16.2.1.11"},{"type":"op","aoid":"GetModuleNamespace","refId":"sec-getmodulenamespace","kind":"abstract operation","signature":{"parameters":[{"name":"_module_","type":{"kind":"opaque","type":"an instance of a concrete subclass of Module Record"}},{"name":"_phase_","type":{"kind":"union","types":[{"kind":"opaque","type":"~defer~"},{"kind":"opaque","type":"~evaluation~"}]}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a Module Namespace Object"}},"effects":[]},{"type":"clause","id":"sec-getmodulenamespace","aoid":"GetModuleNamespace","title":"GetModuleNamespace ( module, phase )","titleHTML":"GetModuleNamespace ( module, phase )","number":"16.2.1.13"},{"type":"clause","id":"sec-module-semantics","aoid":null,"title":"Module Semantics","titleHTML":"Module Semantics","number":"16.2.1"},{"type":"production","id":"prod-ImportDeclaration","name":"ImportDeclaration"},{"type":"production","id":"prod-ImportClause","name":"ImportClause"},{"type":"production","id":"prod-ImportedDefaultBinding","name":"ImportedDefaultBinding"},{"type":"production","id":"prod-NameSpaceImport","name":"NameSpaceImport"},{"type":"production","id":"prod-NamedImports","name":"NamedImports"},{"type":"production","id":"prod-FromClause","name":"FromClause"},{"type":"production","id":"prod-ImportsList","name":"ImportsList"},{"type":"production","id":"prod-ImportSpecifier","name":"ImportSpecifier"},{"type":"production","id":"prod-ModuleSpecifier","name":"ModuleSpecifier"},{"type":"production","id":"prod-ImportedBinding","name":"ImportedBinding"},{"type":"production","id":"prod-WithClause","name":"WithClause"},{"type":"production","id":"prod-WithEntries","name":"WithEntries"},{"type":"production","id":"prod-AttributeKey","name":"AttributeKey"},{"type":"clause","id":"sec-imports-static-semantics-early-errors","aoid":null,"title":"Static Semantics: Early Errors","titleHTML":"Static Semantics: Early Errors","number":"16.2.2.1"},{"type":"op","aoid":"ImportEntries","refId":"sec-static-semantics-importentries","kind":"syntax-directed operation","signature":{"parameters":[],"optionalParameters":[],"return":{"kind":"list","elements":{"kind":"opaque","type":"ImportEntry Records"}}},"effects":[]},{"type":"clause","id":"sec-static-semantics-importentries","aoid":"ImportEntries","title":"Static Semantics: ImportEntries","titleHTML":"Static Semantics: ImportEntries","number":"16.2.2.2"},{"type":"clause","id":"sec-imports","aoid":null,"title":"Imports","titleHTML":"Imports","number":"16.2.2"},{"type":"clause","id":"sec-modules","aoid":null,"title":"Modules","titleHTML":"Modules","number":"16.2"},{"type":"clause","id":"sec-ecmascript-language-scripts-and-modules","aoid":null,"title":"ECMAScript Language: Scripts and Modules","titleHTML":"ECMAScript Language: Scripts and Modules","number":"16"},{"type":"clause","id":"sec-%symbol.tostringtag%","aoid":null,"title":"%Symbol.toStringTag%","titleHTML":"%Symbol.toStringTag%","number":"28.3.1"},{"type":"clause","id":"sec-module-namespace-objects","aoid":null,"title":"Module Namespace Objects","titleHTML":"Module Namespace Objects","number":"28.3"},{"type":"clause","id":"sec-reflection","aoid":null,"title":"Reflection","titleHTML":"Reflection","number":"28"},{"type":"clause","id":"sec-copyright-and-software-license","aoid":null,"title":"Copyright & Software License","titleHTML":"Copyright & Software License","number":"A"}]}
\ No newline at end of file
diff --git a/package.json b/package.json
index 364cd45..9062b8c 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"scripts": {
"start": "npm run build-loose -- --watch",
"build": "npm run build-loose -- --strict",
- "build-loose": "ecmarkup --load-biblio @tc39/ecma262-biblio --verbose spec.emu build/index.html --lint-spec"
+ "build-loose": "node -e 'fs.mkdirSync(\"build\", { recursive: true })' && ecmarkup --load-biblio @tc39/ecma262-biblio --load-biblio ./biblio/proposal-defer-import-eval.json --verbose spec.emu build/index.html --lint-spec"
},
"homepage": "https://github.com/tc39/template-for-proposals#readme",
"repository": {
@@ -14,10 +14,10 @@
},
"license": "MIT",
"devDependencies": {
- "@tc39/ecma262-biblio": "^2.1.2857",
- "ecmarkup": "^21.0.0"
+ "@tc39/ecma262-biblio": "^2.1.2909",
+ "ecmarkup": "^21.3.0"
},
"engines": {
- "node": ">= 12"
+ "node": ">= 18"
}
}
diff --git a/spec.emu b/spec.emu
index b1526d1..dd22e48 100644
--- a/spec.emu
+++ b/spec.emu
@@ -6,316 +6,12 @@
title: Import Sync stage: 1 -contributors: Guy Bedford, Marco Ippolito +contributors: Guy Bedford-
This specification defines several kinds of built-in exotic objects. These objects generally behave similar to ordinary objects except for a few specific situations. The following exotic objects use the ordinary object internal methods except where it is explicitly specified otherwise below:
- - -A module namespace exotic object is an exotic object that exposes the bindings exported from an ECMAScript |Module| (See
An object is a module namespace exotic object if its [[GetPrototypeOf]], [[SetPrototypeOf]], [[IsExtensible]], [[PreventExtensions]], [[GetOwnProperty]], [[DefineOwnProperty]], [[HasProperty]], [[Get]], [[Set]], [[Delete]], and [[OwnPropertyKeys]] internal methods use the definitions in this section, and its other essential internal methods use the definitions found in
Module namespace exotic objects have the internal slots defined in
| - Internal Slot - | -- Type - | -- Description - | -
|---|---|---|
| - [[Module]] - | -- a Module Record - | -- The Module Record whose exports this namespace exposes. - | -
| - [[Exports]] - | -- a List of Strings - | -- A List whose elements are the String values of the exported names exposed as own properties of this object. The list is ordered as if an Array of those String values had been sorted using %Array.prototype.sort% using *undefined* as _comparefn_. - | -
| - [[Deferred]] - | -- a Boolean - | -- Whether this module namespace was obtained through `import defer`/`import.defer()`. Deferred namespaces can have side effects when accessing properties on them. - | -
ResolveExport is side-effect free. Each time this operation is called with a specific _exportName_, _resolveSet_ pair as arguments it must return the same result. An implementation might choose to pre-compute or cache the ResolveExport results for the [[Exports]] of each module namespace exotic object.
-NOTE: The diff markers are on top of https://tc39.es/proposal-defer-import-eval/.
+A ModuleRequest Record represents the request to import a module with given import attributes and import phase. It consists of the following fields:
-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
| Field Name @@ -538,157 +155,321 @@ contributors: Guy Bedford, Marco Ippolito 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 ( |
+
| + [[HostDefined]] + | ++ anything (default value is *undefined*) + | ++ Field reserved for use by host environments that need to associate additional information with a module. + | +
| - [[Specifier]] - | -- a String - | -- The module specifier - | -||
| - [[Attributes]] - | -- a List of ImportAttribute Records - | -- The import attributes - | -||
| - [[Phase]] - | -- ~defer~ or ~evaluation~ - | -- The target import phase - | ++ 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. + |
+
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
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
| + 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 |
+
| + [[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
| + 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
| - [[Realm]] + [[PromiseCapability]] | - a Realm Record + a PromiseCapability Record or ~syncImport~ | - The Realm within which this module was created. + The promise to resolve when the loading process finishes, or ~syncImport~ for a synchronous loading operation. |
| - [[Environment]] + [[IsLoading]] | - a Module Environment Record or ~empty~ + a Boolean | - The Environment Record containing the top level bindings for this module. This field is set when the module is linked. + It is true if the loading process has not finished yet, neither successfully nor with an error. |
| - [[Namespace]] + [[PendingModulesCount]] | - an Object or ~empty~ + a non-negative integer |
- The Module Namespace Object ( |
| - [[DeferredNamespace]] + [[Visited]] | - an Object or ~empty~ + a List of Cyclic Module Records |
- The Module Namespace Object ( |
| - anything (default value is *undefined*) + anything (default value is ~empty~) | - Field reserved for use by host environments that need to associate additional information with a module. + It contains host-defined data to pass from the LoadRequestedModules caller to HostLoadImportedModule. |
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.
<link rel="preload" as="..."> tags.
+ import() expressions never set the _hostDefined_ parameter.
+ This non-normative section gives a series of examples of the linking and evaluation of a few common module graphs, with a specific focus on how errors can occur.
- -First consider the following simple module graph:
- -Let's first assume that there are no error conditions. When a host first calls _A_.LoadRequestedModules(), this will complete successfully by assumption, and recursively load the dependencies of _B_ and _C_ as well (respectively, _C_ and none), and then set _A_.[[Status]] = _B_.[[Status]] = _C_.[[Status]] = ~unlinked~. Then, when the host calls _A_.Link(), it will complete successfully (again by assumption) such that _A_.[[Status]] = _B_.[[Status]] = _C_.[[Status]] = linked. These preparatory steps can be performed at any time. Later, when the host is ready to incur any possible side effects of the modules, it can call _A_.Evaluate(), which will complete successfully, returning a Promise resolving to *undefined* (again by assumption), recursively having evaluated first _C_ and then _B_. Each module's [[Status]] at this point will be ~evaluated~.
- -Consider then cases involving linking errors, after a successful call to _A_.LoadRequestedModules(). If InnerModuleLinking of _C_ succeeds but, thereafter, fails for _B_, for example because it imports something that _C_ does not provide, then the original _A_.Link() will fail, and both _A_ and _B_'s [[Status]] remain ~unlinked~. _C_'s [[Status]] has become ~linked~, though.
- -Finally, consider a case involving evaluation errors after a successful call to Link(). If InnerModuleEvaluation of _C_ succeeds but, thereafter, fails for _B_, for example because _B_ contains code that throws an exception, then the original _A_.Evaluate() will fail, returning a rejected Promise. The resulting exception will be recorded in both _A_ and _B_'s [[EvaluationError]] fields, and their [[Status]] will become ~evaluated~. _C_ will also become ~evaluated~ but, in contrast to _A_ and _B_, will remain without an [[EvaluationError]], as it successfully completed evaluation. Storing the exception ensures that any time a host tries to reuse _A_ or _B_ by calling their Evaluate() method, it will encounter the same exception. (Hosts are not required to reuse Cyclic Module Records; similarly, hosts are not required to expose the exception objects thrown by these methods. However, the specification enables such uses.)
- -Now consider a different type of error condition:
- -In this scenario, module _A_ declares a dependency on some other module, but no Module Record exists for that module, i.e. HostLoadImportedModule calls FinishLoadingImportedModule with an exception when asked for it. This could occur for a variety of reasons, such as the corresponding resource not existing, or the resource existing but ParseModule returning some errors when trying to parse the resulting source text. Hosts can choose to expose the cause of failure via the completion they pass to FinishLoadingImportedModule. In any case, this exception causes a loading failure, which results in _A_'s [[Status]] remaining ~new~.
- -The difference here between loading, linking and evaluation errors is due to the following characteristic:
-Now, consider a module graph with a cycle:
- -Here we assume that the entry point is module _A_, so that the host proceeds by calling _A_.LoadRequestedModules(), which performs InnerModuleLoading on _A_. This in turn calls InnerModuleLoading on _B_ and _C_. Because of the cycle, this again triggers InnerModuleLoading on _A_, but at this point it is a no-op since _A_'s dependencies loading has already been triggered during this LoadRequestedModules process. When all the modules in the graph have been successfully loaded, their [[Status]] transitions from ~new~ to ~unlinked~ at the same time.
- -Then the host proceeds by calling _A_.Link(), which performs InnerModuleLinking on _A_. This in turn calls InnerModuleLinking on _B_. Because of the cycle, this again triggers InnerModuleLinking on _A_, but at this point it is a no-op since _A_.[[Status]] is already ~linking~. _B_.[[Status]] itself remains ~linking~ when control gets back to _A_ and InnerModuleLinking is triggered on _C_. After this returns with _C_.[[Status]] being ~linked~, both _A_ and _B_ transition from ~linking~ to ~linked~ together; this is by design, since they form a strongly connected component. It's possible to transition the status of modules in the same SCC at the same time because during this phase the module graph is traversed with a depth-first search.
- -An analogous story occurs for the evaluation phase of a cyclic module graph, in the success case.
- -Now consider a case where _A_ has a linking error; for example, it tries to import a binding from _C_ that does not exist. In that case, the above steps still occur, including the early return from the second call to InnerModuleLinking on _A_. However, once we unwind back to the original InnerModuleLinking on _A_, it fails during InitializeEnvironment, namely right after _C_.ResolveExport(). The thrown *SyntaxError* exception propagates up to _A_.Link, which resets all modules that are currently on its _stack_ (these are always exactly the modules that are still ~linking~). Hence both _A_ and _B_ become ~unlinked~. Note that _C_ is left as ~linked~.
- -Alternatively, consider a case where _A_ has an evaluation error; for example, its source code throws an exception. In that case, the evaluation-time analog of the above steps still occurs, including the early return from the second call to InnerModuleEvaluation on _A_. However, once we unwind back to the original InnerModuleEvaluation on _A_, it fails by assumption. The exception thrown propagates up to _A_.Evaluate(), which records the error in all modules that are currently on its _stack_ (i.e., the modules that are still ~evaluating~) as well as via [[AsyncParentModules]], which form a chain for modules which contain or depend on top-level `await` through the whole dependency graph through the AsyncModuleExecutionRejected algorithm. Hence both _A_ and _B_ become ~evaluated~ and the exception is recorded in both _A_ and _B_'s [[EvaluationError]] fields, while _C_ is left as ~evaluated~ with no [[EvaluationError]].
- -Lastly, consider a module graph with a cycle, where all modules complete asynchronously:
-Loading and linking happen as before, and all modules end up with [[Status]] set to ~linked~.
- -Calling _A_.Evaluate() calls InnerModuleEvaluation on _A_, _B_, and _D_, which all transition to ~evaluating~. Then InnerModuleEvaluation is called on _A_ again, which is a no-op because it is already ~evaluating~. At this point, _D_.[[PendingAsyncDependencies]] is 0, so ExecuteAsyncModule(_D_) is called and we call _D_.ExecuteModule with a new PromiseCapability tracking the asynchronous execution of _D_. We unwind back to the InnerModuleEvaluation on _B_, setting _B_.[[PendingAsyncDependencies]] to 1 and _B_.[[AsyncEvaluation]] to *true*. We unwind back to the original InnerModuleEvaluation on _A_, setting _A_.[[PendingAsyncDependencies]] to 1. In the next iteration of the loop over _A_'s dependencies, we call InnerModuleEvaluation on _C_ and thus on _D_ (again a no-op) and _E_. As _E_ has no dependencies and is not part of a cycle, we call ExecuteAsyncModule(_E_) in the same manner as _D_ and _E_ is immediately removed from the stack. We unwind once more to the original InnerModuleEvaluation on _A_, setting _C_.[[AsyncEvaluation]] to *true*. Now we finish the loop over _A_'s dependencies, set _A_.[[AsyncEvaluation]] to *true*, and remove the entire strongly connected component from the stack, transitioning all of the modules to ~evaluating-async~ at once. At this point, the fields of the modules are as given in
| Module | -[[DFSIndex]] | -[[DFSAncestorIndex]] | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -
|---|---|---|---|---|---|---|
| _A_ | -0 | -0 | -~evaluating-async~ | -*true* | -« » | -2 (_B_ and _C_) | -
| _B_ | -1 | -0 | -~evaluating-async~ | -*true* | -« _A_ » | -1 (_D_) | -
| _C_ | -2 | -0 | -~evaluating-async~ | -*true* | -« _A_ » | -2 (_D_ and _E_) | -
| _D_ | -3 | -0 | -~evaluating-async~ | -*true* | -« _B_, _C_ » | -0 | -
| _E_ | -4 | -4 | -~evaluating-async~ | -*true* | -« _C_ » | -0 | -
Let us assume that _E_ finishes executing first. When that happens, AsyncModuleExecutionFulfilled is called, _E_.[[Status]] is set to ~evaluated~ and _C_.[[PendingAsyncDependencies]] is decremented to become 1. The fields of the updated modules are as given in
| Module | -[[DFSIndex]] | -[[DFSAncestorIndex]] | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -
|---|---|---|---|---|---|---|
| _C_ | -2 | -0 | -~evaluating-async~ | -*true* | -« _A_ » | -1 (_D_) | -
| _E_ | -4 | -4 | -~evaluated~ | -*true* | -« _C_ » | -0 | -
_D_ is next to finish (as it was the only module that was still executing). When that happens, AsyncModuleExecutionFulfilled is called again and _D_.[[Status]] is set to ~evaluated~. Then _B_.[[PendingAsyncDependencies]] is decremented to become 0, ExecuteAsyncModule is called on _B_, and it starts executing. _C_.[[PendingAsyncDependencies]] is also decremented to become 0, and _C_ starts executing (potentially in parallel to _B_ if _B_ contains an `await`). The fields of the updated modules are as given in
| Module | -[[DFSIndex]] | -[[DFSAncestorIndex]] | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -
|---|---|---|---|---|---|---|
| _B_ | -1 | -0 | -~evaluating-async~ | -*true* | -« _A_ » | -0 | -
| _C_ | -2 | -0 | -~evaluating-async~ | -*true* | -« _A_ » | -0 | -
| _D_ | -3 | -0 | -~evaluated~ | -*true* | -« _B_, _C_ » | -0 | -
Let us assume that _C_ finishes executing next. When that happens, AsyncModuleExecutionFulfilled is called again, _C_.[[Status]] is set to ~evaluated~ and _A_.[[PendingAsyncDependencies]] is decremented to become 1. The fields of the updated modules are as given in
| Module | -[[DFSIndex]] | -[[DFSAncestorIndex]] | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -
|---|---|---|---|---|---|---|
| _A_ | -0 | -0 | -~evaluating-async~ | -*true* | -« » | -1 (_B_) | -
| _C_ | -2 | -0 | -~evaluated~ | -*true* | -« _A_ » | -0 | -
Then, _B_ finishes executing. When that happens, AsyncModuleExecutionFulfilled is called again and _B_.[[Status]] is set to ~evaluated~. _A_.[[PendingAsyncDependencies]] is decremented to become 0, so ExecuteAsyncModule is called and it starts executing. The fields of the updated modules are as given in
| Module | -[[DFSIndex]] | -[[DFSAncestorIndex]] | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -
|---|---|---|---|---|---|---|
| _A_ | -0 | -0 | -~evaluating-async~ | -*true* | -« » | -0 | -
| _B_ | -1 | -0 | -~evaluated~ | -*true* | -« _A_ » | -0 | -
Finally, _A_ finishes executing. When that happens, AsyncModuleExecutionFulfilled is called again and _A_.[[Status]] is set to ~evaluated~. At this point, the Promise in _A_.[[TopLevelCapability]] (which was returned from _A_.Evaluate()) is resolved, and this concludes the handling of this module graph. The fields of the updated module are as given in
| Module | -[[DFSIndex]] | -[[DFSAncestorIndex]] | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -
|---|---|---|---|---|---|---|
| _A_ | -0 | -0 | -~evaluated~ | -*true* | -« » | -0 | -
Alternatively, consider a failure case where _C_ fails execution and returns an error before _B_ has finished executing. When that happens, AsyncModuleExecutionRejected is called, which sets _C_.[[Status]] to ~evaluated~ and _C_.[[EvaluationError]] to the error. It then propagates this error to all of the AsyncParentModules by performing AsyncModuleExecutionRejected on each of them. The fields of the updated modules are as given in
| Module | -[[DFSIndex]] | -[[DFSAncestorIndex]] | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -[[EvaluationError]] | -
|---|---|---|---|---|---|---|---|
| _A_ | -0 | -0 | -~evaluated~ | -*true* | -« » | -1 (_B_) | -~empty~ | -
| _C_ | -2 | -1 | -~evaluated~ | -*true* | -« _A_ » | -0 | -_C_'s evaluation error | -
_A_ will be rejected with the same error as _C_ since _C_ will call AsyncModuleExecutionRejected on _A_ with _C_'s error. _A_.[[Status]] is set to ~evaluated~. At this point the Promise in _A_.[[TopLevelCapability]] (which was returned from _A_.Evaluate()) is rejected. The fields of the updated module are as given in
| Module | -[[DFSIndex]] | -[[DFSAncestorIndex]] | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -[[EvaluationError]] | -
|---|---|---|---|---|---|---|---|
| _A_ | -0 | -0 | -~evaluated~ | -*true* | -« » | -0 | -_C_'s Evaluation Error | -
Then, _B_ finishes executing without an error. When that happens, AsyncModuleExecutionFulfilled is called again and _B_.[[Status]] is set to ~evaluated~. GatherAvailableAncestors is called on _B_. However, _A_.[[CycleRoot]] is _A_ which has an evaluation error, so it will not be added to the returned _sortedExecList_ and AsyncModuleExecutionFulfilled will return without further processing. Any future importer of _B_ will resolve the rejection of _B_.[[CycleRoot]].[[EvaluationError]] from the evaluation error from _C_ that was set on the cycle root _A_. The fields of the updated modules are as given in
| Module | -[[DFSIndex]] | -[[DFSAncestorIndex]] | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -[[EvaluationError]] | -
|---|---|---|---|---|---|---|---|
| _A_ | -0 | -0 | -~evaluated~ | -*true* | -« » | -0 | -_C_'s Evaluation Error | -
| _B_ | -1 | -0 | -~evaluated~ | -*true* | -« _A_ » | -0 | -~empty~ | -
Deferred imports complicate handling of module graphs, because they allow deferring evaluation of part of the graph while still eagerly evaluating the asynchronous subgraphs of a deferred portion. In this section, deferred imports are marked with dashed arrows and modules using top-level await are marked with TLA.
- -Consider the following graph, assuming that all the modules have already their [[Status]] set to ~linked~:
- -Calling _A_.Evaluate() calls InnerModuleEvaluation _A_, which transitions _A_.[[Status]] to ~evaluating~. _A_ has a deferred import for _B_, so it performs GatherAsynchronousTransitiveDependencies(_B_). _B_ doesn't have any transitive dependency using top-level await, so that AO doesn't collect any module. _A_ also imports _D_, so the list of modules that _A_'s evaluation depends on is « _D_ »: the InnerModuleEvaluation algorithm run on _A_ performs InnerModuleEvaluation on _D_, transitioning its [[Status]] to ~evaluating~ and then ~evaluated~, and then it calls _A_.ExecuteModule(). If _A_'s execution triggers _B_.Evaluate(), then InnerModuleEvaluation will be called on _B_ and _C_ executing them and transitioning their [[Status]] to ~evaluated~. Finally, _A_.[[Status]] transitions to ~evaluated~.
- -Consider the same graph, but with _C_ using top-level await:
- -Calling _A_.Evaluate() calls InnerModuleEvaluation _A_, which transitions _A_.[[Status]] to ~evaluating~. It then performs GatherAsynchronousTransitiveDependencies(_B_), finding the module _C_: the list of modules whose evaluation _A_'s evaluation depends on is « _C_, _D_ ». It then calls InnerModuleEvaluation on _C_ and _D_, transitioning their [[Status]] respectively to ~evaluating-async~ and ~evaluated~ and registering _A_'s evaluation as pending on the asynchronous dependency _C_. At this point, the fields of the modules are given in
| Module | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -
|---|---|---|---|---|
| _A_ | -~evaluating-async~ | -*true* | -« » | -1 (_C_) | -
| _B_ | -~linked~ | -*false* | -« » | -0 | -
| _C_ | -~evaluating-async~ | -*true* | -« _A_ » | -0 | -
| _D_ | -~evaluated~ | -*false* | -« » | -0 | -
Let us assume that _C_ succesfully finishes evaluating. When that happens, AsyncModuleExecutionFulfilled(_C_) is called, _C_.[[Status]] is set to ~evaluated~, _A_.ExecuteModule() is called and upon successful completion _A_.[[Status]] is set to ~evaluted~. The fields of the modules are now as given in
| Module | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -
|---|---|---|---|---|
| _A_ | -~evaluated~ | -*true* | -« » | -0 | -
| _B_ | -~linked~ | -*false* | -« » | -0 | -
| _C_ | -~evaluated~ | -*true* | -« _A_ » | -0 | -
| _D_ | -~evaluated~ | -*false* | -« » | -0 | -
If later _B_.Evaluate() is called, then the InnerModuleEvaluation call on _B_ will transition _B_.[[Status]] to ~evaluating~ and will call InnerModuleEvaluation on _C_. Since at this point _C_.[[Status]] is already ~evaluated~, _B_.ExecuteModule() will be called synchronously and _B_.[[Status]] will synchronously transition to ~evaluated~.
- -Alternatively, consider a failure case where _C_ fails to execute with an exception _error_. When that happens, AsyncModuleExecutionRejected(_C_, _error_) is called, it sets _C_.[[Status]] = _A_.[[Status]] to ~evaluated~ and _C_.[[EvaluationError]] = _A_.[[EvaluationError]] to ThrowCompletion(_error_). The fields of the modules are this as given in
| Module | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -[[EvaluationError]] | -
|---|---|---|---|---|---|
| _A_ | -~evaluated~ | -*true* | -« » | -1 (_C_) | -_error_ | -
| _B_ | -~linked~ | -*false* | -« » | -0 | -~empty~ | -
| _C_ | -~evaluated~ | -*true* | -« _B_ » | -0 | -_error_ | -
| _D_ | -~evaluated~ | -*false* | -« » | -0 | -~empty~ | -
If at any later point in time _B_.Evaluate() is called, it will perform InnerModuleEvaluation on _C_ which immediately returns with ThrowCompletion(_error_), transitioning _B_.[[Status]] to ~evalauted~ and setting _B_.[[EvaluationError]] to _error_.
- -Consider now a graph with a deferred import taking part in a dependencies cycle, and assume that the evaluation of _A_ calls _B_.Evaluate():
- -As in the previous example, calling _A_.Evaluate() calls InnerModuleEvaluation on _A_, GatherAsynchronousTransitiveDependencies on _B_ will find _C_ and thus it performs InnerModuleEvaluation on _C_, transitioning their _A_ and _C_'s [[Status]] to ~evaluating-async~. When InnerModuleEvaluation iterates over _C_'s dependencies, it finds _A_ and sets _A_.[[CycleRoot]] = _C_.[[CycleRoot]] = _A_. At this point, the fields of the modules are given in
| Module | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -[[CycleRoot]] | -
|---|---|---|---|---|---|
| _A_ | -~evaluating-async~ | -*true* | -« » | -1 (_C_) | -_A_ | -
| _B_ | -~linked~ | -*false* | -« » | -0 | -~empty~ | -
| _C_ | -~evaluating-async~ | -*true* | -« _A_ » | -0 | -_A_ | -
Assume now that _C_ succesfully finishes evaluating. When that happens AsyncModuleExecutionFulfilled(_C_) is called, it sets _C_.[[Status]] to ~evaluated~, and it performs _A_.ExecuteModule(). As stated, _A_'s execution causes a call to _B_.Evaluate(), which calls InnerModuleEvaluation on _B_ and on _C_. Since _C_.[[Status]] is ~evaluated~, _B_.ExecuteModule() is called synchronously and, assuming it completes succesfully, transitions _B_.[[Status]] to ~evaluated~. At this point, the fields of the modules are given in
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
-| Module | -[[Status]] | -[[AsyncEvaluation]] | -[[AsyncParentModules]] | -[[PendingAsyncDependencies]] | -[[CycleRoot]] | -
|---|---|---|---|---|---|
| _A_ | -~evaluating-async~ | -*true* | -« » | -0 | -_A_ | -
| _B_ | -~evaluated~ | -*false* | -« » | -0 | -_B_ | -
| _C_ | -~evaluated~ | -*true* | -« _A_ » | -0 | -_A_ | -
<button type="button" onclick="import('./foo.mjs')">Click me</button>
- Once the call to _A_.ExecuteModule() completes, _A_.[[Status]] transitions to ~evaluated~.
-there will be no active script or module at the time the
An implementation of HostLoadImportedModule must conform to the following requirements:
+If this operation is called multiple times with two (_referrer_, _moduleRequest_) pairs such that:
+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.
+If _moduleRequest_.[[Attributes]] has an entry _entry_ such that _entry_.[[Key]] is *"type"* and _entry_.[[Value]] is *"json"*, when the host environment performs FinishLoadingImportedModule(_referrer_, _moduleRequest_, _payload_, _result_), _result_ must either be the Completion Record returned by an invocation of ParseJSONModule or a throw completion.
+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.
-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"`.
+GetModuleNamespace never throws. Instead, unresolvable names are simply excluded from the namespace at this point. They will lead to a real linking error later unless they are all ambiguous star exports that are not explicitly requested anywhere.
-