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
 
-The diff markers in this proposal are on top of tc39/proposal-defer-import-eval (Defer Import Proposal). - - -

Ordinary and Exotic Objects Behaviours

- - -

Built-in Exotic Object Internal Methods and Slots

-

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:

- - - -

Module Namespace Exotic Objects

-

A module namespace exotic object is an exotic object that exposes the bindings exported from an ECMAScript |Module| (See ). There is a one-to-one correspondence between the String-keyed own properties of a module namespace exotic object and the binding names exported by the |Module|. The exported bindings include any bindings that are indirectly exported using `export *` export items. Each String-valued own property key is the StringValue of the corresponding exported binding name. These are the only String-keyed properties of a module namespace exotic object. Each such property has the attributes { [[Writable]]: *true*, [[Enumerable]]: *true*, [[Configurable]]: *false* }. Module namespace exotic objects are not extensible.

-

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 . These methods are installed by ModuleNamespaceCreate.

-

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

- [[GetOwnProperty]] ( - _P_: a property key, - ): either a normal completion containing either a Property Descriptor or *undefined*, or a throw completion -

-
-
for
-
a module namespace exotic object _O_
-
- - 1. If IsSymbolLikeNamespaceKey(_P_, _O_) is *true*, return OrdinaryGetOwnProperty(_O_, _P_). - 1. Let _exports_ be ? GetModuleExportsList(_O_). - 1. If _exports_ does not contain _P_, return *undefined*. - 1. Let _value_ be ? _O_.[[Get]](_P_, _O_). - 1. Return PropertyDescriptor { [[Value]]: _value_, [[Writable]]: *true*, [[Enumerable]]: *true*, [[Configurable]]: *false* }. - -
- - -

- [[DefineOwnProperty]] ( - _P_: a property key, - _Desc_: a Property Descriptor, - ): either a normal completion containing a Boolean or a throw completion -

-
-
for
-
a module namespace exotic object _O_
-
- - 1. If IsSymbolLikeNamespaceKey(_P_, _O_), return ! OrdinaryDefineOwnProperty(_O_, _P_, _Desc_). - 1. Let _current_ be ? _O_.[[GetOwnProperty]](_P_). - 1. NOTE: If _O_.[[Deferred]] is *true*, the step above will ensure that the module is evaluated. - 1. If _current_ is *undefined*, return *false*. - 1. If _Desc_ has a [[Configurable]] field and _Desc_.[[Configurable]] is *true*, return *false*. - 1. If _Desc_ has an [[Enumerable]] field and _Desc_.[[Enumerable]] is *false*, return *false*. - 1. If IsAccessorDescriptor(_Desc_) is *true*, return *false*. - 1. If _Desc_ has a [[Writable]] field and _Desc_.[[Writable]] is *false*, return *false*. - 1. If _Desc_ has a [[Value]] field, return SameValue(_Desc_.[[Value]], _current_.[[Value]]). - 1. Return *true*. - -
- - -

- [[HasProperty]] ( - _P_: a property key, - ): a normal completion containing a Boolean -

-
-
for
-
a module namespace exotic object _O_
-
- - 1. If IsSymbolLikeNamespaceKey(_P_, _O_), return ! OrdinaryHasProperty(_O_, _P_). - 1. Let _exports_ be ? GetModuleExportsList(_O_). - 1. If _exports_ contains _P_, return *true*. - 1. Return *false*. - -
- - -

- [[Get]] ( - _P_: a property key, - _Receiver_: an ECMAScript language value, - ): either a normal completion containing an ECMAScript language value or a throw completion -

-
-
for
-
a module namespace exotic object _O_
-
- - 1. If IsSymbolLikeNamespaceKey(_P_, _O_), return ! OrdinaryGet(_O_, _P_, _Receiver_). - 1. Let _exports_ be ? GetModuleExportsList(_O_). - 1. If _exports_ does not contain _P_, return *undefined*. - 1. Let _m_ be _O_.[[Module]]. - 1. Let _binding_ be _m_.ResolveExport(_P_). - 1. Assert: _binding_ is a ResolvedBinding Record. - 1. Let _targetModule_ be _binding_.[[Module]]. - 1. Assert: _targetModule_ is not *undefined*. - 1. If _binding_.[[BindingName]] is ~namespace~, then - 1. Return GetModuleNamespace(_targetModule_, ~evaluation~). - 1. NOTE: The phase here is always ~evaluation~ because in `import defer * as x from "..."; export { x }`, _binding_.[[BindingName]] is *"x"* and not ~namespace~. - 1. Let _targetEnv_ be _targetModule_.[[Environment]]. - 1. If _targetEnv_ is ~empty~, throw a *ReferenceError* exception. - 1. Return ? _targetEnv_.GetBindingValue(_binding_.[[BindingName]], *true*). - - -

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.

-
-
- - -

- [[Set]] ( - _P_: a property key, - _V_: an ECMAScript language value, - _Receiver_: an ECMAScript language value, - ): a normal completion containing *false* -

-
-
for
-
a module namespace exotic object
-
- - 1. Return *false*. - -
- - -

- [[Delete]] ( - _P_: a property key, - ): a normal completion containing a Boolean -

-
-
for
-
a module namespace exotic object _O_
-
- - 1. If IsSymbolLikeNamespaceKey(_P_, _O_), return ! OrdinaryDelete(_O_, _P_). - 1. Let _exports_ be ? GetModuleExportsList(_O_). - 1. If _exports_ contains _P_, return *false*. - 1. Return *true*. - -
- - -

[[OwnPropertyKeys]] ( ): a normal completion containing a List of property keys

-
-
for
-
a module namespace exotic object _O_
-
- - 1. Let _exports_ be ? GetModuleExportsList(_O_). - 1. If _O_.[[Deferred]] is *true*, and _exports_ contains *"then"*, then - 1. Set _exports_ to a copy of _exports_. - 1. Remove *"then"* from _exports_. - 1. Let _symbolKeys_ be OrdinaryOwnPropertyKeys(_O_). - 1. Return the list-concatenation of _exports_ and _symbolKeys_. - -
- - -

- ModuleNamespaceCreate ( - _module_: a Module Record, - _exports_: a List of Strings, - _phase_: ~defer~ or ~evaluation~, - ): a module namespace exotic object -

-
-
description
-
It is used to specify the creation of new module namespace exotic objects.
-
- - 1. Let _internalSlotsList_ be the internal slots listed in . - 1. Let _M_ be MakeBasicObject(_internalSlotsList_). - 1. Set _M_'s essential internal methods to the definitions specified in . - 1. Set _M_.[[Module]] to _module_. - 1. [declared="comparefn"] Let _sortedExports_ be a List whose elements are the elements of _exports_ ordered as if an Array of the same values had been sorted using %Array.prototype.sort% using *undefined* as _comparefn_. - 1. Set _M_.[[Exports]] to _sortedExports_. - 1. If _phase_ is ~defer~, then - 1. Assert: _module_.[[DeferredNamespace]] is ~empty~. - 1. Set _module_.[[DeferredNamespace]] to _M_. - 1. Set _M_.[[Deferred]] to *true*. - 1. Let _toStringTag_ be *"Deferred Module"*. - 1. Else, - 1. Assert: _module_.[[Namespace]] is ~empty~. - 1. Set _module_.[[Namespace]] to _M_. - 1. Set _M_.[[Deferred]] to *false*. - 1. Let _toStringTag_ be *"Module"*. - 1. Create an own data property of _M_ named %Symbol.toStringTag% whose [[Value]] is _toStringTag_ and whose [[Writable]], [[Enumerable]], and [[Configurable]] attributes are *false*. - 1. Return _M_. - -
- - -

- IsSymbolLikeNamespaceKey ( - _P_: a property key, - _ns_: a module namespace exotic object, - ): a Boolean -

-
-
description
-
It determines if a property of _ns_ with key _P_ would be an ordinary property, rather than being mapped to one of the module exports.
-
- - - 1. If _P_ is a Symbol, return *true*. - 1. If _ns_.[[Deferred]] is *true* and _P_ is *"then"*, return *true*. - 1. Return *false*. - -
- - -

- GetModuleExportsList ( - _O_: a module namespace exotic object, - ): either a normal completion containing a List of Strings, or a throw completion -

-
-
description
-
It returns a List whose elements are the names of the module's exports, triggering module evaluation if needed.
-
- - 1. If _O_.[[Deferred]] is *true*, then - 1. Let _m_ be _O_.[[Module]]. - 1. If _m_ is a Cyclic Module Record, _m_.[[Status]] is not ~evaluated~, and ReadyForSyncExecution(_m_) is *false*, throw a *TypeError* exception. - 1. Perform ? EvaluateSync(_m_). - 1. Return _O_.[[Exports]]. - - - -

- ReadyForSyncExecution ( - _module_: a Cyclic Module Record, - optional _seen_: a List of Module Records, - ): a Boolean -

-
- - 1. If _seen_ is not present, set _seen_ to a new empty List. - 1. If _seen_ contains _module_, return *true*. - 1. Append _module_ to _seen_. - 1. If _module_.[[Status]] is ~evaluated~, return *true*. - 1. If _module_.[[Status]] is ~evaluating~ or ~evaluating-async~, return *false*. - 1. Assert: _module_.[[Status]] is ~linked~. - 1. If _module_.[[HasTLA]] is *true*, return *false*. - 1. For each ModuleRequest Record _request_ of _module_.[[RequestedModules]], do - 1. Let _requiredModule_ be GetImportedModule(_module_, _request_). - 1. If ReadyForSyncExecution(_requiredModule_, _seen_) is *false*, then - 1. Return *false*. - 1. Return *true*. - -
-
-
-
-
+ +

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

+

ECMAScript Language: Expressions

@@ -327,10 +23,11 @@ contributors: Guy Bedford, Marco Ippolito ImportCall[Yield, Await] : `import` ImportCallArguments[?Yield, ?Await] `import` `.` `defer` ImportCallArguments[?Yield, ?Await] + `import` `.` `sync` ImportCallArguments[?Yield, ?Await] - ImportCallArguments[Yield, Await] : - `(` AssignmentExpression[+In, ?Yield, ?Await] `,`? `)` - `(` AssignmentExpression[+In, ?Yield, ?Await] `,` AssignmentExpression[+In, ?Yield, ?Await] `,`? `)` + ImportCallArguments[Yield, Await] : + `(` AssignmentExpression[+In, ?Yield, ?Await] `,`? `)` + `(` AssignmentExpression[+In, ?Yield, ?Await] `,` AssignmentExpression[+In, ?Yield, ?Await] `,`? `)` @@ -339,7 +36,7 @@ contributors: Guy Bedford, Marco Ippolito The changes to this section are intended to mirror the changes proposed by the Source - Phase Imports proposal, but adapted to the ~defer~ phase. + Phase Imports proposal, but adapted to the ~defer~ phase. @@ -354,45 +51,18 @@ contributors: Guy Bedford, Marco Ippolito 1. Return ? EvaluateImportCall(|ImportCallArguments|, ~defer~). - - - -

Runtime Semantics: EvaluateImportCallSpecifier

- - ImportCallArguments : `(` AssignmentExpression `,`? `)` - - 1. Let _ref_ be ? Evaluation of |AssignmentExpression|. - 1. Return ? GetValue(_ref_). - - - ImportCallArguments : `(` AssignmentExpression `,` AssignmentExpression `,`? `)` - - 1. Let _ref_ be ? Evaluation of the first |AssignmentExpression|. - 1. Return ? GetValue(_ref_). - -
- - -

Runtime Semantics: EvaluateImportCallOptions

- - ImportCallArguments : `(` AssignmentExpression `,`? `)` - - 1. Return *undefined*. - - ImportCallArguments : `(` AssignmentExpression `,` AssignmentExpression `,`? `)` + ImportCall : `import` `.` `sync` ImportCallArguments - 1. Let _ref_ be ? Evaluation of the second |AssignmentExpression|. - 1. Return ? GetValue(_ref_). + 1. Return ? ImportCallSync(|ImportCallArguments|).
- +

- EvaluateImportCall ( - _arguments_: a Parse Node, - _phase_: ~defer~ or ~evaluation~, - ): either a normal completion containing a Promise or an abrupt completion + ImportCallSync ( + _arguments_: a Parse Node + ): either a normal completion or an abrupt completion

@@ -400,91 +70,37 @@ contributors: Guy Bedford, Marco Ippolito 1. If _referrer_ is *null*, set _referrer_ to the current Realm Record. 1. Let _specifier_ be ? EvaluateImportCallSpecifier of _arguments_. 1. Let _options_ be ? EvaluateImportCallOptions of _arguments_. - 1. Let _promiseCapability_ be ! NewPromiseCapability(%Promise%). - 1. Let _specifierString_ be Completion(ToString(_specifier_)). - 1. IfAbruptRejectPromise(_specifierString_, _promiseCapability_). + 1. Let _specifierString_ be ? ToString(_specifier_). 1. Let _attributes_ be a new empty List. 1. If _options_ is not *undefined*, then 1. If _options_ is not an Object, then - 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « a newly created *TypeError* object »). - 1. Return _promiseCapability_.[[Promise]]. - 1. Let _attributesObj_ be Completion(Get(_options_, *"with"*)). - 1. IfAbruptRejectPromise(_attributesObj_, _promiseCapability_). + 1. Throw a *TypeError* exception. + 1. Let _attributesObj_ be ? Get(_options_, *"with"*). 1. If _attributesObj_ is not *undefined*, then 1. If _attributesObj_ is not an Object, then - 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « a newly created *TypeError* object »). - 1. Return _promiseCapability_.[[Promise]]. - 1. Let _entries_ be Completion(EnumerableOwnProperties(_attributesObj_, ~key+value~)). - 1. IfAbruptRejectPromise(_entries_, _promiseCapability_). + 1. Throw a *TypeError* exception. + 1. Let _entries_ be ? EnumerableOwnProperties(_attributesObj_, ~key+value~). 1. For each element _entry_ of _entries_, do 1. Let _key_ be ! Get(_entry_, *"0"*). 1. Let _value_ be ! Get(_entry_, *"1"*). 1. If _key_ is a String, then 1. If _value_ is not a String, then - 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « a newly created *TypeError* object »). - 1. Return _promiseCapability_.[[Promise]]. + 1. Throw a *TypeError* exception. 1. Append the ImportAttribute Record { [[Key]]: _key_, [[Value]]: _value_ } to _attributes_. 1. If AllImportAttributesSupported(_attributes_) is *false*, then - 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « a newly created *TypeError* object »). - 1. Return _promiseCapability_.[[Promise]]. + 1. Throw a *TypeError* exception. 1. 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. - 1. Let _moduleRequest_ be a new ModuleRequest Record { [[Specifier]]: _specifierString_, [[Attributes]]: _attributes_, [[Phase]]: _phase_ }. - 1. Perform HostLoadImportedModule(_referrer_, _moduleRequest_, ~empty~, _promiseCapability_). - 1. Return _promiseCapability_.[[Promise]]. + 1. Let _moduleRequest_ be a new ModuleRequest Record { [[Specifier]]: _specifierString_, [[Attributes]]: _attributes_, [[Phase]]: ~evaluation~ }. + 1. Let _moduleCompletion_ be NormalCompletion(~empty~). + 1. Perform HostLoadImportedModule(_referrer_, _moduleRequest_, ~empty~, _moduleCompletion_). + 1. NOTE: HostLoadImportedModule will update _moduleCompletion_ synchronously either updating its value to be a Module Record, or setting it to be a throw completion. + 1. Let _module_ be ? _moduleCompletion_. + 1. Perform ? _module_.LoadRequestedModulesSync(). + 1. Perform ? _module_.Link(). + 1. If ReadyForSyncExecution(_module_) is *false*, throw a *TypeError* exception. + 1. Perform ? EvaluateModuleSync(_module_). + 1. Return GetModuleNamespace(_module_, ~evaluation~). - - -

- ContinueDynamicImport ( - _promiseCapability_: a PromiseCapability Record, - _moduleCompletion_: either a normal completion containing a Module Record or a throw completion, - _phase_: ~defer~ or ~evaluation~, - ): ~unused~ -

-
-
description
-
It completes the process of a dynamic import originally started by an `import()` call, resolving or rejecting the promise returned by that call as appropriate.
-
- - 1. If _moduleCompletion_ is an abrupt completion, then - 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _moduleCompletion_.[[Value]] »). - 1. Return ~unused~. - 1. Let _module_ be _moduleCompletion_.[[Value]]. - 1. Let _loadPromise_ be _module_.LoadRequestedModules(). - 1. Let _rejectedClosure_ be a new Abstract Closure with parameters (_reason_) that captures _promiseCapability_ and performs the following steps when called: - 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _reason_ »). - 1. Return ~unused~. - 1. Let _onRejected_ be CreateBuiltinFunction(_rejectedClosure_, 1, *""*, « »). - 1. Let _linkAndEvaluateClosure_ be a new Abstract Closure with no parameters that captures _module_, _promiseCapability_, _phase_ and _onRejected_ and performs the following steps when called: - 1. Let _link_ be Completion(_module_.Link()). - 1. If _link_ is an abrupt completion, then - 1. Perform ! Call(_promiseCapability_.[[Reject]], *undefined*, « _link_.[[Value]] »). - 1. Return ~unused~. - 1. Let _fulfilledClosure_ be a new Abstract Closure with no parameters that captures _module_, _phase_, and _promiseCapability_ and performs the following steps when called: - 1. Let _namespace_ be GetModuleNamespace(_module_, _phase_). - 1. Perform ! Call(_promiseCapability_.[[Resolve]], *undefined*, « _namespace_ »). - 1. Return ~unused~. - 1. If _phase_ is ~defer~, then - 1. Let _evaluationList_ be GatherAsynchronousTransitiveDependencies(_module_). - 1. If _evaluationList_ is empty, then - 1. Perform _fulfilledClosure_(). - 1. Return ~unused~. - 1. Let _asyncDepsEvaluationPromises_ be a new empty List. - 1. For each Module Record _dep_ of _evaluationList_, append _dep_.Evaluate() to _asyncDepsEvaluationPromises_. - 1. Let _iterator_ be CreateListIteratorRecord(_asyncDepsEvaluationPromises_). - 1. Let _pc_ be ! NewPromiseCapability(%Promise%). - 1. Let _evaluatePromise_ be ! PerformPromiseAll(_iterator_, %Promise%, _pc_, %Promise.resolve%). - 1. Else, - 1. Assert: _phase_ is ~evaluation~. - 1. Let _evaluatePromise_ be _module_.Evaluate(). - 1. Let _onFulfilled_ be CreateBuiltinFunction(_fulfilledClosure_, *""*, 0, « »). - 1. Perform PerformPromiseThen(_evaluatePromise_, _onFulfilled_, _onRejected_). - 1. Return ~unused~. - 1. Let _linkAndEvaluate_ be CreateBuiltinFunction(_linkAndEvaluateClosure_, *""*, 0, « »). - 1. Perform PerformPromiseThen(_loadPromise_, _linkAndEvaluate_, _onRejected_). - 1. Return ~unused~. - -
@@ -520,13 +136,14 @@ contributors: Guy Bedford, Marco Ippolito

Module Semantics

- -

ModuleRequest Records

- -

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

- + +

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

+ - + + + + + + + + + + + + + + + + + + + + + + +
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 () 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. +
+
+ + + - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + +
- [[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.

+
- +

- ModuleRequestsEqual ( - _left_: a ModuleRequest Record or a LoadedModuleRequest Record, - _right_: a ModuleRequest Record or a LoadedModuleRequest Record, - ): a Boolean + EvaluateModuleSync ( + _module_: a Module Record, + ): either a normal completion containing ~unused~ or a throw completion

description
-
‍It checks whether the two ModuleRequest Records have the same specifier and attributes.
+
It synchronously evaluates _module_, provided that the caller guarantees that _module_'s evaluation will return an already settled promise.
- 1. If _left_.[[Specifier]] is not _right_.[[Specifier]], return *false*. - 1. Let _leftAttrs_ be _left_.[[Attributes]]. - 1. Let _rightAttrs_ be _right_.[[Attributes]]. - 1. Let _leftAttrsCount_ be the number of elements in _leftAttrs_. - 1. Let _rightAttrsCount_ be the number of elements in _rightAttrs_. - 1. If _leftAttrsCount_ ≠ _rightAttrsCount_, return *false*. - 1. For each ImportAttribute Record _l_ of _leftAttrs_, do - 1. If _rightAttrs_ does not contain an ImportAttribute Record _r_ such that _l_.[[Key]] is _r_.[[Key]] and _l_.[[Value]] is _r_.[[Value]], return *false*. - 1. Return *true*. + 1. Assert: _module_ is not a Cyclic Module Record. + 1. Let _promise_ be _module_.Evaluate(). + 1. Assert: _promise_.[[PromiseState]] is either ~fulfilled~ or ~rejected~. + 1. If _promise_.[[PromiseState]] is ~rejected~, then + 1. If _promise_.[[PromiseIsHandled]] is *false*, perform HostPromiseRejectionTracker(_promise_, *"handle"*). + 1. Set _promise_.[[PromiseIsHandled]] to *true*. + 1. Return ThrowCompletion(_promise_.[[PromiseResult]]). + 1. Return ~unused~.
- -

Static Semantics: ModuleRequests ( ): a List of ModuleRequest Records

-
-
- Module : [empty] - - 1. Return a new empty List. - - ModuleItemList : ModuleItem - - 1. Return ModuleRequests of |ModuleItem|. - - ModuleItemList : ModuleItemList ModuleItem - - 1. Let _requests_ be the ModuleRequests of |ModuleItemList|. - 1. Let _additionalRequests_ be the ModuleRequests of |ModuleItem|. - 1. For each ModuleRequest Record _mr_ of _additionalRequests_, do - 1. If _requests_ does not contain a ModuleRequest Record _mr2_ such that ModuleRequestsEqual(_mr_, _mr2_) is *true* and _mr_.[[Phase]] is _mr2_.[[Phase]], then - 1. Append _mr_ to _requests_. - 1. Return _requests_. - - ModuleItem : StatementListItem - - 1. Return a new empty List. - - - ImportDeclaration : `import` ImportClause FromClause `;` - - - 1. Let _specifier_ be the SV of |FromClause|. - 1. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: _specifier_, [[Attributes]]: « », [[Phase]]: ~evaluation~ }. - - ImportDeclaration : `import` ImportClause FromClause WithClause `;` - - 1. Let _specifier_ be the SV of |FromClause|. - 1. Let _attributes_ be WithClauseToAttributes of |WithClause|. - 1. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: _specifier_, [[Attributes]]: _attributes_, [[Phase]]: ~evaluation~ }. - - - ImportDeclaration : `import` `defer` NameSpaceImport FromClause `;` - - - 1. Let _specifier_ be SV of |FromClause|. - 1. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: _specifier_, [[Attributes]]: « », [[Phase]]: ~defer~ }. - - - ImportDeclaration : `import` `defer` NameSpaceImport FromClause WithClause `;` - - - 1. Let _specifier_ be SV of |FromClause|. - 1. Let _attributes_ be WithClauseToAttributes of |WithClause|. - 1. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: _specifier_, [[Attributes]]: _attributes_, [[Phase]]: ~defer~ }. - - - ExportDeclaration : `export` ExportFromClause FromClause `;` - - - 1. Let _specifier_ be SV of |FromClause|. - 1. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: _specifier_, [[Attributes]]: « », [[Phase]]: ~evaluation~ }. - - - ExportDeclaration : `export` ExportFromClause FromClause WithClause `;` - - - 1. Let _specifier_ be the SV of |FromClause|. - 1. Let _attributes_ be WithClauseToAttributes of |WithClause|. - 1. Return a List whose sole element is the ModuleRequest Record { [[Specifier]]: _specifier_, [[Attributes]]: _attributes_, [[Phase]]: ~evaluation~ }. - - - ExportDeclaration : - `export` NamedExports `;` - `export` VariableStatement - `export` Declaration - `export` `default` HoistableDeclaration - `export` `default` ClassDeclaration - `export` `default` AssignmentExpression `;` - - - 1. Return a new empty List. - -
- - -

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

- + +

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 Cyclic Module Records have the additional fields listed 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 . 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 Cyclic Module Records have the additional methods listed 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 :

+ @@ -705,46 +486,46 @@ contributors: Guy Bedford, Marco Ippolito @@ -752,20 +533,14 @@ contributors: Guy Bedford, Marco Ippolito [[HostDefined]]
- [[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 () whose [[Deferred]] slot is *false*, if one has been created for this module. + It tracks the number of pending HostLoadImportedModule calls.
- [[DeferredNamespace]] + [[Visited]] - an Object or ~empty~ + a List of Cyclic Module Records - The Module Namespace Object () whose [[Deferred]] slot is *true*, if one has been requested for this module. + 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.
- 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.
-
- - -

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.

@@ -776,8 +551,41 @@ contributors: Guy Bedford, Marco Ippolito
for
a Cyclic Module Record _module_
+ +
description
+
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.
+ + 1. If _hostDefined_ is not present, let _hostDefined_ be ~empty~. + 1. Let _pc_ be ! NewPromiseCapability(%Promise%). + 1. Let _state_ be the GraphLoadingState Record { [[IsLoading]]: *true*, [[PendingModulesCount]]: 1, [[Visited]]: « », [[PromiseCapability]]: _pc_, [[HostDefined]]: _hostDefined_ }. + 1. Perform InnerModuleLoading(_state_, _module_). + 1. Return _pc_.[[Promise]]. + + + + 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. + + + +

+ InnerModuleLoadingSync ( + _state_: a GraphLoadingState Record, + _module_: a Module Record, + ): ~unused~ +

+
+
description
+
It is used by LoadRequestedModules to recursively perform the actual loading process for _module_'s dependency graph.
+
+ + + 1. TODO. + +
+

InnerModuleLoading ( @@ -786,35 +594,58 @@ contributors: Guy Bedford, Marco Ippolito ): ~unused~

+
description
+
It is used by LoadRequestedModules to recursively perform the actual loading process for _module_'s dependency graph.
- - There is no special handling for ModuleRequests whose [[Phase]] is ~defer~: any error from loading or parsing the corresponding modules will make InnerModuleLoading fail. - + + 1. Assert: _state_.[[IsLoading]] is *true*. + 1. 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]]. + 1. Let _requestedModulesCount_ be the number of elements in _module_.[[RequestedModules]]. + 1. Set _state_.[[PendingModulesCount]] to _state_.[[PendingModulesCount]] + _requestedModulesCount_. + 1. 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). + 1. Perform ContinueModuleLoading(_state_, _error_). + 1. Else if _module_.[[LoadedModules]] contains a LoadedModuleRequest Record _record_ such that ModuleRequestsEqual(_record_, _request_) is *true*, then + 1. Perform InnerModuleLoading(_state_, _record_.[[Module]]). + 1. Else, + 1. Perform HostLoadImportedModule(_module_, _request_, _state_.[[HostDefined]], _state_). + 1. NOTE: HostLoadImportedModule will call FinishLoadingImportedModule, which re-enters the graph loading process through ContinueModuleLoading. + 1. If _state_.[[IsLoading]] is *false*, return ~unused~. + 1. Assert: _state_.[[PendingModulesCount]] ≥ 1. + 1. Set _state_.[[PendingModulesCount]] to _state_.[[PendingModulesCount]] - 1. + 1. If _state_.[[PendingModulesCount]] = 0, then + 1. Set _state_.[[IsLoading]] to *false*. + 1. For each Record _loaded_ of _state_.[[Visited]], do + 1. If _loaded_.[[Status]] is ~new~, set _loaded_.[[Status]] to ~unlinked~. + 1. Perform ! Call(_state_.[[PromiseCapability]].[[Resolve]], *undefined*, « *undefined* »). + 1. Return ~unused~. +
- - - -

Link ( ): either a normal completion containing ~unused~ or a throw completion

-
-
for
-
a Cyclic Module Record _module_
-
- +

- InnerModuleLinking ( - _module_: a Module Record, - _stack_: a List of Cyclic Module Records, - _index_: a non-negative integer, - ): either a normal completion containing a non-negative integer or a throw completion + ContinueModuleLoading ( + _state_: a GraphLoadingState Record, + _moduleCompletion_: either a normal completion containing a Module Record or a throw completion, + ): ~unused~

+
description
+
It is used to re-enter the loading process after a call to HostLoadImportedModule.
- - There is no special handling for ModuleRequests whose [[Phase]] is ~defer~: any error from linking the corresponding modules will make InnerModuleLinking fail. - + + 1. If _state_.[[IsLoading]] is *false*, return ~unused~. + 1. If _moduleCompletion_ is a normal completion, then + 1. Perform InnerModuleLoading(_state_, _moduleCompletion_.[[Value]]). + 1. Else, + 1. Set _state_.[[IsLoading]] to *false*. + 1. Perform ! Call(_state_.[[PromiseCapability]].[[Reject]], *undefined*, « _moduleCompletion_.[[Value]] »). + 1. Return ~unused~. +
@@ -849,8 +680,9 @@ contributors: Guy Bedford, Marco Ippolito 1. Else, 1. Assert: _module_.[[Status]] is either ~evaluating-async~ or ~evaluated~. 1. Assert: _module_.[[EvaluationError]] is ~empty~. - 1. If _module_.[[AsyncEvaluation]] is *false*, then - 1. Assert: _module_.[[Status]] is ~evaluated~. + 1. If _module_.[[Status]] is ~evaluated~, then + 1. NOTE: This implies that evaluation of _module_ completed synchronously. + 1. Assert: _module_.[[AsyncEvaluationOrder]] is ~unset~. 1. Perform ! Call(_capability_.[[Resolve]], *undefined*, « *undefined* »). 1. Assert: _stack_ is empty. 1. Return _capability_.[[Promise]]. @@ -866,12 +698,12 @@ contributors: Guy Bedford, Marco Ippolito

description
-
It is used by Evaluate to perform the actual evaluation process for _module_, as well as recursively on all other modules in the dependency graph. The _stack_ and _index_ parameters, as well as _module_'s [[DFSIndex]] and [[DFSAncestorIndex]] fields, are used the same way as in InnerModuleLinking.
+
It 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.
1. If _module_ is not a Cyclic Module Record, then - 1. Perform ? EvaluateSync(_module_). + 1. Perform ? EvaluateModuleSync(_module_). 1. Return _index_. 1. If _module_.[[Status]] is either ~evaluating-async~ or ~evaluated~, then 1. If _module_.[[EvaluationError]] is ~empty~, return _index_. @@ -879,14 +711,14 @@ contributors: Guy Bedford, Marco Ippolito 1. If _module_.[[Status]] is ~evaluating~, return _index_. 1. Assert: _module_.[[Status]] is ~linked~. 1. Set _module_.[[Status]] to ~evaluating~. - 1. Set _module_.[[DFSIndex]] to _index_. + 1. Let _moduleIndex_ be _index_. 1. Set _module_.[[DFSAncestorIndex]] to _index_. 1. Set _module_.[[PendingAsyncDependencies]] to 0. 1. Set _index_ to _index_ + 1. 1. Let _evaluationList_ be a new empty List. - 1. For each ModuleRequest Record _request_ of _module_.[[RequestedModules]], do - 1. Let _requiredModule_ be GetImportedModule(_module_, _request_). - 1. If _request_.[[Phase]] is ~defer~, then + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_.[[Specifier]]). + 1. If _required_.[[Phase]] is ~defer~, then 1. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_). 1. For each Module Record _additionalModule_ of _additionalModules_, do 1. If _evaluationList_ does not contain _additionalModule_, then @@ -905,28 +737,26 @@ contributors: Guy Bedford, Marco Ippolito 1. Set _requiredModule_ to _requiredModule_.[[CycleRoot]]. 1. Assert: _requiredModule_.[[Status]] is either ~evaluating-async~ or ~evaluated~. 1. If _requiredModule_.[[EvaluationError]] is not ~empty~, return ? _requiredModule_.[[EvaluationError]]. - 1. If _requiredModule_.[[AsyncEvaluation]] is *true*, then + 1. If _requiredModule_.[[AsyncEvaluationOrder]] is an integer, then 1. Set _module_.[[PendingAsyncDependencies]] to _module_.[[PendingAsyncDependencies]] + 1. 1. Append _module_ to _requiredModule_.[[AsyncParentModules]]. 1. If _module_.[[PendingAsyncDependencies]] > 0 or _module_.[[HasTLA]] is *true*, then - 1. Assert: _module_.[[AsyncEvaluation]] is *false*. - 1. Set _module_.[[AsyncEvaluation]] to *true*. - 1. NOTE: The order in which module records have their [[AsyncEvaluation]] fields transition to *true* is significant. (See .) + 1. Assert: _module_.[[AsyncEvaluationOrder]] is ~unset~. + 1. Set _module_.[[AsyncEvaluationOrder]] to IncrementModuleAsyncEvaluationCount(). 1. If _module_.[[PendingAsyncDependencies]] = 0, perform ExecuteAsyncModule(_module_). 1. Else, 1. Perform ? _module_.ExecuteModule(). 1. Assert: _module_ occurs exactly once in _stack_. - 1. Assert: _module_.[[DFSAncestorIndex]] ≤ _module_.[[DFSIndex]]. - 1. If _module_.[[DFSAncestorIndex]] = _module_.[[DFSIndex]], then + 1. Assert: _module_.[[DFSAncestorIndex]] ≤ _moduleIndex_. + 1. If _module_.[[DFSAncestorIndex]] = _moduleIndex_, then 1. Let _done_ be *false*. 1. Repeat, while _done_ is *false*, 1. Let _requiredModule_ be the last element of _stack_. 1. Remove the last element of _stack_. 1. Assert: _requiredModule_ is a Cyclic Module Record. - 1. If _requiredModule_.[[AsyncEvaluation]] is *false*, then - 1. Set _requiredModule_.[[Status]] to ~evaluated~. - 1. Else, - 1. Set _requiredModule_.[[Status]] to ~evaluating-async~. + 1. Assert: _requiredModule_.[[AsyncEvaluationOrder]] is either an integer or ~unset~. + 1. If _requiredModule_.[[AsyncEvaluationOrder]] is ~unset~, set _requiredModule_.[[Status]] to ~evaluated~. + 1. Otherwise, set _requiredModule_.[[Status]] to ~evaluating-async~. 1. If _requiredModule_ and _module_ are the same Module Record, set _done_ to *true*. 1. Set _requiredModule_.[[CycleRoot]] to _module_. 1. Return _index_. @@ -939,34 +769,12 @@ contributors: Guy Bedford, Marco Ippolito
- -

- EvaluateSync ( - _module_: a Module Record, - ): either a normal completion containing ~unused~ or a throw completion -

-
-
description
-
It synchronously evaluates _module_ provided it is ready for synchronous execution.
-
- - - 1. Assert: If _module_ is a Cyclic Module Record, _module_.[[HasTLA]] is *false*. - 1. [declared="m"] Assert: For each Cyclic Module Record _m_ that it a transitive dependency of _module_, either _m_.[[HasTLA]] is *false* or _m_.[[Status]] is ~evaluated~. - 1. Let _promise_ be ! _module_.Evaluate(). - 1. Assert: _promise_.[[PromiseState]] is either ~fulfilled~ or ~rejected~. - 1. If _promise_.[[PromiseState]] is ~rejected~, then - 1. Throw _promise_.[[PromiseResult]]. - 1. Return ~unused~. - -
-

- GatherAsynchronousTransitiveDependencies ( - _module_: a Module Record, - optional _seen_: a List of Module Records - ): a List of Module Records + GatherAsynchronousTransitiveDependencies ( + _module_: a Module Record, + optional _seen_: a List of Module Records + ): a List of Module Records

description
@@ -983,8 +791,8 @@ contributors: Guy Bedford, Marco Ippolito 1. If _module_.[[HasTLA]] is *true*, then 1. Append _module_ to _result_. 1. Return _result_. - 1. For each ModuleRequest Record _request_ of _module_.[[RequestedModules]], do - 1. Let _requiredModule_ be GetImportedModule(_module_, _request_). + 1. For each ModuleRequest Record _required_ of _module_.[[RequestedModules]], do + 1. Let _requiredModule_ be GetImportedModule(_module_, _required_). 1. Let _additionalModules_ be GatherAsynchronousTransitiveDependencies(_requiredModule_, _seen_). 1. For each Module Record _m_ of _additionalModules_, do 1. If _result_ does not contain _m_, append _m_ to _result_. @@ -992,734 +800,60 @@ contributors: Guy Bedford, Marco Ippolito + - -

Example Cyclic Module Record Graphs

- -

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:

- - - A module graph in which module A depends on module B, and module B depends on module C - - -

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:

- - - A module graph in which module A depends on a missing (unresolvable) module, represented by ??? - - -

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:

-
    -
  • Evaluation must be only performed once, as it can cause side effects; it is thus important to remember whether evaluation has already been performed, even if unsuccessfully. (In the error case, it makes sense to also remember the exception because otherwise subsequent Evaluate() calls would have to synthesize a new one.)
  • -
  • Linking, on the other hand, is side-effect-free, and thus even if it fails, it can be retried at a later time with no issues.
  • -
  • Loading closely interacts with the host, and it may be desiderable for some of them to allow users to retry failed loads (for example, if the failure is caused by temporarily bad network conditions).
  • -
- -

Now, consider a module graph with a cycle:

- - - A module graph in which module A depends on module B and C, but module B also depends on module A - - -

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:

- - A module graph in which module A depends on module B and C, module B depends on module D, module C depends on module D and E, and module D depends on module A - -

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_00~evaluating-async~*true*« »2 (_B_ and _C_)
_B_10~evaluating-async~*true*« _A_ »1 (_D_)
_C_20~evaluating-async~*true*« _A_ »2 (_D_ and _E_)
_D_30~evaluating-async~*true*« _B_, _C_ »0
_E_44~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_20~evaluating-async~*true*« _A_ »1 (_D_)
_E_44~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_10~evaluating-async~*true*« _A_ »0
_C_20~evaluating-async~*true*« _A_ »0
_D_30~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_00~evaluating-async~*true*« »1 (_B_)
_C_20~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_00~evaluating-async~*true*« »0
_B_10~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_00~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_00~evaluated~*true*« »1 (_B_)~empty~
_C_21~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_00~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_00~evaluated~*true*« »0_C_'s Evaluation Error
_B_10~evaluated~*true*« _A_ »0~empty~
-
- - -

Example Cyclic Module Record Graphs with Deferred Imports

- -

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

- - - A module graph in which module A depends on module B with a deferred import, and module B depends on module C - - -

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:

- - - A module graph in which module A depends on module B with a deferred import, and module B depends on module C, which uses 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():

- - - A module graph in which module A depends on module B with a deferred import, module B depends on module C, which uses top-level await and depends on A - - -

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_
-
+ +

+ HostLoadImportedModule ( + _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, + _payload_: a GraphLoadingState Record, a PromiseCapability Record, or a Completion Record, + ): ~unused~ +

+
+
description
+
+
-

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

+ - -

Source Text Module Records

+

An implementation of HostLoadImportedModule must conform to the following requirements:

+
    +
  • + The host environment must perform FinishLoadingImportedModule(_referrer_, _moduleRequest_, _payload_, _result_), where _result_ is either a normal completion containing the loaded Module Record or a throw completion, either synchronously or asynchronously. +
  • +
  • + If _payload_ is a CompletionRecord, or _payload_ is a GraphLoadingState and _payload_.[[PromiseCapability]] is ~syncImport~, then the host environment must call FinishLoadingImportedModule(_referrer_, _moduleRequest_, _payload_, _result_) synchronously. +
  • +
  • +

    If this operation is called multiple times with two (_referrer_, _moduleRequest_) pairs such that:

    +
      +
    • the first _referrer_ is the same as the second _referrer_;
    • +
    • ModuleRequestsEqual(the first _moduleRequest_, the second _moduleRequest_) is *true*;
    • +
    +

    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 operation must treat _payload_ as an opaque value to be passed through to FinishLoadingImportedModule. +
  • +
- -

InitializeEnvironment ( ): either a normal completion containing ~unused~ or a throw completion

-
-
for
-
a Source Text Module Record _module_
-
+

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.

- - 1. For each ExportEntry Record _e_ of _module_.[[IndirectExportEntries]], do - 1. Let _resolution_ be _module_.ResolveExport(_e_.[[ExportName]]). - 1. If _resolution_ is either *null* or ~ambiguous~, throw a *SyntaxError* exception. - 1. Assert: _resolution_ is a ResolvedBinding Record. - 1. Assert: All named exports from _module_ are resolvable. - 1. Let _realm_ be _module_.[[Realm]]. - 1. Assert: _realm_ is not *undefined*. - 1. Let _env_ be NewModuleEnvironment(_realm_.[[GlobalEnv]]). - 1. Set _module_.[[Environment]] to _env_. - 1. For each ImportEntry Record _in_ of _module_.[[ImportEntries]], do - 1. Let _importedModule_ be GetImportedModule(_module_, _in_.[[ModuleRequest]]). - 1. If _in_.[[ImportName]] is ~namespace-object~, then - 1. Let _namespace_ be GetModuleNamespace(_importedModule_, _in_.[[ModuleRequest]].[[Phase]]). - 1. Perform ! _env_.CreateImmutableBinding(_in_.[[LocalName]], *true*). - 1. Perform ! _env_.InitializeBinding(_in_.[[LocalName]], _namespace_). - 1. Else, - 1. Let _resolution_ be _importedModule_.ResolveExport(_in_.[[ImportName]]). - 1. If _resolution_ is either *null* or ~ambiguous~, throw a *SyntaxError* exception. - 1. If _resolution_.[[BindingName]] is ~namespace~, then - 1. NOTE: In this case we have an `export * as ns from "";` declaration. `import * as ns from ""; export { ns }` indirect re-exports have _resolution_.[[BindingName]] set to *"ns"*. - 1. Let _namespace_ be GetModuleNamespace(_resolution_.[[Module]], ~evaluation~). - 1. Perform ! _env_.CreateImmutableBinding(_in_.[[LocalName]], *true*). - 1. Perform ! _env_.InitializeBinding(_in_.[[LocalName]], _namespace_). - 1. Else, - 1. Perform _env_.CreateImportBinding(_in_.[[LocalName]], _resolution_.[[Module]], _resolution_.[[BindingName]]). - 1. Let _moduleContext_ be a new ECMAScript code execution context. - 1. Set the Function of _moduleContext_ to *null*. - 1. Assert: _module_.[[Realm]] is not *undefined*. - 1. Set the Realm of _moduleContext_ to _module_.[[Realm]]. - 1. Set the ScriptOrModule of _moduleContext_ to _module_. - 1. Set the VariableEnvironment of _moduleContext_ to _module_.[[Environment]]. - 1. Set the LexicalEnvironment of _moduleContext_ to _module_.[[Environment]]. - 1. Set the PrivateEnvironment of _moduleContext_ to *null*. - 1. Set _module_.[[Context]] to _moduleContext_. - 1. Push _moduleContext_ onto the execution context stack; _moduleContext_ is now the running execution context. - 1. Let _code_ be _module_.[[ECMAScriptCode]]. - 1. Let _varDeclarations_ be the VarScopedDeclarations of _code_. - 1. Let _declaredVarNames_ be a new empty List. - 1. For each element _d_ of _varDeclarations_, do - 1. For each element _dn_ of the BoundNames of _d_, do - 1. If _declaredVarNames_ does not contain _dn_, then - 1. Perform ! _env_.CreateMutableBinding(_dn_, *false*). - 1. Perform ! _env_.InitializeBinding(_dn_, *undefined*). - 1. Append _dn_ to _declaredVarNames_. - 1. Let _lexDeclarations_ be the LexicallyScopedDeclarations of _code_. - 1. Let _privateEnv_ be *null*. - 1. For each element _d_ of _lexDeclarations_, do - 1. For each element _dn_ of the BoundNames of _d_, do - 1. If IsConstantDeclaration of _d_ is *true*, then - 1. Perform ! _env_.CreateImmutableBinding(_dn_, *true*). - 1. Else, - 1. Perform ! _env_.CreateMutableBinding(_dn_, *false*). - 1. If _d_ is either a |FunctionDeclaration|, a |GeneratorDeclaration|, an |AsyncFunctionDeclaration|, or an |AsyncGeneratorDeclaration|, then - 1. Let _fo_ be InstantiateFunctionObject of _d_ with arguments _env_ and _privateEnv_. - 1. Perform ! _env_.InitializeBinding(_dn_, _fo_). - 1. Remove _moduleContext_ from the execution context stack. - 1. Return ~unused~. - -
+ +

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

+
@@ -1727,7 +861,8 @@ contributors: Guy Bedford, Marco Ippolito FinishLoadingImportedModule ( _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 or a PromiseCapability Record, + _payload_: a GraphLoadingState Record, a PromiseCapability Record, or a Completion Record, _result_: either a normal completion containing a Module Record or a throw completion, ): ~unused~ @@ -1743,146 +878,15 @@ contributors: Guy Bedford, Marco Ippolito 1. Append the LoadedModuleRequest Record { [[Specifier]]: _moduleRequest_.[[Specifier]], [[Attributes]]: _moduleRequest_.[[Attributes]], [[Module]]: _result_.[[Value]] } to _referrer_.[[LoadedModules]]. 1. If _payload_ is a GraphLoadingState Record, then 1. Perform ContinueModuleLoading(_payload_, _result_). + 1. Else if _payload_ is a Completion Record, then + 1. Assert: _result_ is a normal completion or a throw completion. + 1. If _result_ is a throw completion, set _payload_.[[Type]] to ~throw~. + 1. Set _payload_.[[Value]] to _result_.[[Value]]. 1. Else, 1. Perform ContinueDynamicImport(_payload_, _result_, _moduleRequest_.[[Phase]]). 1. Return ~unused~. - - -

- GetModuleNamespace ( - _module_: an instance of a concrete subclass of Module Record, - _phase_: ~defer~ or ~evaluation~, - ): a Module Namespace Object -

-
-
description
-
It retrieves the Module Namespace Object representing _module_'s exports, lazily creating it the first time it was requested, and storing it in _module_.[[Namespace]] for future retrieval.
-
- - - 1. Assert: If _module_ is a Cyclic Module Record, then _module_.[[Status]] is not ~new~ or ~unlinked~. - 1. If _phase_ is ~defer~, let _namespace_ be _module_.[[DeferredNamespace]]. Otherwise, let _namespace_ be _module_.[[Namespace]]. - 1. If _namespace_ is ~empty~, then - 1. Let _exportedNames_ be _module_.GetExportedNames(). - 1. Let _unambiguousNames_ be a new empty List. - 1. For each element _name_ of _exportedNames_, do - 1. Let _resolution_ be _module_.ResolveExport(_name_). - 1. If _resolution_ is a ResolvedBinding Record, append _name_ to _unambiguousNames_. - 1. Set _namespace_ to ModuleNamespaceCreate(_module_, _unambiguousNames_, _phase_). - 1. Return _namespace_. - - -

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.

-
-
- - - -

Imports

-

Syntax

- - ImportDeclaration : - `import` ImportClause FromClause WithClause? `;` - `import` `defer` NameSpaceImport FromClause WithClause? `;` - `import` ModuleSpecifier WithClause? `;` - - ImportClause : - ImportedDefaultBinding - NameSpaceImport - NamedImports - ImportedDefaultBinding `,` NameSpaceImport - ImportedDefaultBinding `,` NamedImports - - ImportedDefaultBinding : - ImportedBinding - - NameSpaceImport : - `*` `as` ImportedBinding - - NamedImports : - `{` `}` - `{` ImportsList `}` - `{` ImportsList `,` `}` - - FromClause : - `from` ModuleSpecifier - - ImportsList : - ImportSpecifier - ImportsList `,` ImportSpecifier - - ImportSpecifier : - ImportedBinding - ModuleExportName `as` ImportedBinding - - ModuleSpecifier : - StringLiteral - - ImportedBinding : - BindingIdentifier[~Yield, +Await] - - WithClause : - `with` `{` `}` - `with` `{` WithEntries `,`? `}` - - WithEntries : - AttributeKey `:` StringLiteral - AttributeKey `:` StringLiteral `,` WithEntries - - AttributeKey : - IdentifierName - StringLiteral - - - -

Static Semantics: Early Errors

- ModuleItem : ImportDeclaration -
    -
  • - It is a Syntax Error if the BoundNames of |ImportDeclaration| contains any duplicate entries. -
  • -
-
- - -

Static Semantics: ImportEntries ( ): a List of ImportEntry Records

-
-
- Module : [empty] - - 1. Return a new empty List. - - ModuleItemList : ModuleItemList ModuleItem - - 1. Let _entries1_ be ImportEntries of |ModuleItemList|. - 1. Let _entries2_ be ImportEntries of |ModuleItem|. - 1. Return the list-concatenation of _entries1_ and _entries2_. - - - ModuleItem : - ExportDeclaration - StatementListItem - - - 1. Return a new empty List. - - ImportDeclaration : `import` ImportClause FromClause WithClause? `;` - - 1. Let _module_ be SV of |FromClause|. - 1. Return ImportEntriesForModule of |ImportClause| with arguments _module_. - - ImportDeclaration : `import` `defer` NameSpaceImport FromClause WithClause? `;` - - 1. Let _module_ be SV of |FromClause|. - 1. Return ImportEntriesForModule of |NameSpaceImport| with arguments _module_. - - ImportDeclaration : `import` ModuleSpecifier WithClause? `;` - - 1. Return a new empty List. - -