diff --git a/spec.html b/spec.html index 470d505..3667c98 100644 --- a/spec.html +++ b/spec.html @@ -16,349 +16,222 @@

Introduction

In addition, they provide late definition of export bindings at the execution phase, to support named exports compatibility with legacy module systems.

- -

ECMAScript Language: Scripts and Modules

- -

Modules

- - -

Module Semantics

- - -

Abstract Module Records

- - - - - - - - - - - - - - - - - - - - - - - - - -
- Method - - Purpose -
- GetExportedNames(_exportStarSet_, _nsModule_) - - Return a list of all names that are either directly or indirectly exported from this module. -
- 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 }. Return *null* if the name cannot be resolved, or `"ambiguous"` if multiple bindings were found.

-

This operation must be idempotent if it completes normally. Each time it is called with a specific _exportName_, _resolveSet_ pair as arguments it must return the same result.

-
- Instantiate() - -

Prepare the module for evaluation by transitively resolving all module dependencies and creating a module Environment Record.

-
- Evaluate() - -

If this module has already been evaluated successfully, return *undefined*; if it has already been evaluated unsuccessfully, throw the exception that was produced. Otherwise, transitively evaluate all module dependencies of this module and then evaluate this module.

-

Instantiate must have completed successfully prior to invoking this method.

-
-
-
- - -

Source Text Module Records

- - -

GetExportedNames ( _exportStarSet_, _nsModule_ ) Concrete Method

-

The GetExportedNames concrete method of a Source Text Module Record implements the corresponding Module Record abstract method.

-

It performs the following steps:

- - 1. Let _module_ be this Source Text Module Record. - 1. If _exportStarSet_ contains _module_, then - 1. Assert: We've reached the starting point of an `import *` circularity. - 1. Return a new empty List. - 1. Append _module_ to _exportStarSet_. - 1. Let _exportedNames_ be a new empty List. - 1. For each ExportEntry Record _e_ in _module_.[[LocalExportEntries]], do - 1. Assert: _module_ provides the direct binding for this export. - 1. Append _e_.[[ExportName]] to _exportedNames_. - 1. For each ExportEntry Record _e_ in _module_.[[IndirectExportEntries]], do - 1. Assert: _module_ imports a specific binding for this export. - 1. Append _e_.[[ExportName]] to _exportedNames_. - 1. For each ExportEntry Record _e_ in _module_.[[StarExportEntries]], do - 1. Let _requestedModule_ be ? HostResolveImportedModule(_module_, _e_.[[ModuleRequest]]). - 1. Let _starNames_ be ? _requestedModule_.GetExportedNames(_exportStarSet_, _nsModule_). - 1. If _starNames_ is *null* then, - 1. Return *null*. - 1. For each element _n_ of _starNames_, do - 1. If SameValue(_n_, `"default"`) is *false*, then - 1. If _n_ is not an element of _exportedNames_, then - 1. Append _n_ to _exportedNames_. - 1. Return _exportedNames_. - - -

GetExportedNames does not filter out or throw an exception for names that have ambiguous star export bindings.

-
-
-
- - -

Dynamic Module Records

- -

A Dynamic Module Record is used to represent information about a module that is defined programatically. Its fields contain digested information about the names that are exported by the module and its concrete methods use this digest to link, instantiate, and evaluate the module alongside other Abstract Module Records.

- -

Dependency cycles with Source Text Module Records are avoided since these modules can only export, and not import from other Abstract Module Records.

- -

Dynamic Module Records support late export binding, in that export names are only validated after execution.

- -

In addition to the fields, defined in , Dynamic Module Records have the additional fields listed in . Each of these fields is initially set in CreateDynamicModule.

- - - - - - - - - - - - - - - - - - - - - - - - - -
- Field Name - - Value Type - - Meaning -
- [[ExportNames]] - - A string List of exported names. - - The list of export bindings associated with this Dynamic Module Record. -
- [[PendingNamespaceModules]] - - A List of Module Record - - The list of module records whose module namespace objects are already created and require this dynamic module to execution for their finalization. -
- [[EvaluationError]] - - An abrupt completion | *undefined* - - A completion of type ~throw~ representing the exception that occurred during evaluation. *undefined* if no exception occurred or if [[Status]] is not `"evaluated"`. -
-
- - -

CreateDynamicModule ( _realm_, _hostDefined_ )

-

This method would be expected to be called by the host when constructing a Module Record in _HostResolveImportedModule_.

-

The abstract operation CreateDynamicModule with arguments _realm_, and _hostDefined_ creates a new Dynamic Module Record performing the following steps:

- - 1. Let _exportNames_ be a new empty List. - 1. Let _nsModules_ be a new empty List. - 1. Let _module_ be the Dynamic Module Record { [[Realm]]: _realm_, [[Environment]]: *undefined*, [[Namespace]]: *undefined*, [[Status]]: `"uninstantiated"`, [[ExportNames]]: _exportNames_, [[PendingNamespaceModules]]: _nsModules_, [[EvaluationError]]: *undefined*, [[HostDefined]]: _hostDefined_ }. - 1. Return _module_. - -
- -

The following definitions specify the required concrete methods for Dynamic Module Records.

- - -

GetExportedNames ( _exportStarSet_, _nsModule_ ) Concrete Method

-

The GetExportedNames concrete method of a Dynamic Module Record implements the corresponding Module Record abstract method.

-

Any modules exporting names from this Dynamic Module Record are stored so their exports can be amended on execution of this Dynamic Module.

-

It performs the following steps:

- - 1. Let _module_ be this Dynamic Module Record. - 1. If _module_.[[Status]] is `"uninstantiated"` then, - 1. If _module_.[[PendingNamespaceModules]] does not contain _nsModule_ then, - 1. Add _nsModule_ to _module_.[[PendingNamespaceModules]]. - 1. If _nsModule_.[[HostDefined]] is *undefined* then, - 1. Set _nsModule_.[[HostDefined]] to *1*. - 1. Otherwise, - 1. Let _n_ be the value of _nsModule_.[[HostDefined]]. - 1. Assert: _n_ is a positive integer. - 1. Set _nsModule_.[[HostDefined]] to _n + 1_. - 1. Return *null*. - 1. Return _module_.[[exportNames]]. - - -

For each Module Namespace Exotic Object created that star exports from a Dynamic Module Record before that the dynamic module has executed, we track the number of these under [[HostDefined]] on the namespace. This way namespace finalization to set the exports can be performed by the last dynamic module to execute.

-
-
- - -

ResolveExport ( _exportName_, _resolveSet_ ) Concrete Method

-

The ResolveExport concrete method of a Dynamic Module Record implements the corresponding Module Record abstract method.

- -

ResolveExport ensures that a binding is created for the dynamic Module Record, lazily creating a binding if needed.

- -

This abstract method performs the following steps:

- - - 1. Let _module_ be this Dynamic Module Record. - 1. If _module_.[[Status]] is `"uninstantiated"` then, - 1. Perform ? _module_.Instantiate(). - 1. Let _exportNames_ be _module_.[[ExportNames]]. - 1. If _exportNames_ does not contain _exportName_ then, - 1. Let _envRec_ be the Module Environment Record _module_.[[Environment]] - 1. If _envRec_ does not already have a binding for _exportName_ then, - 1. Perform ! _envRec_.CreateMutableBinding(_exportName_, *false*). - 1. Append _exportName_ to the end of _exportNames_. - 1. Return ResolvedBinding Record { [[Module]]: _module_, [[BindingName]]: _exportName_ }. - -
- - -

Instantiate ( ) Concrete Method

- -

The Instantiate concrete method of a Dynamic Module Record implements the corresponding Module Record abstract method.

-

On success, Instantiate transitions this module's [[Status]] from `"uninstantiated"` to `"instantiated"`. On failure, an exception is thrown and this module's [[Status]] remains `"uninstantiated"`.

- -

This abstract method performs the following steps:

- - - 1. Let _module_ be this Dynamic Module Record. - 1. If _module_.[[Status]] is "instantiated", or "evaluated", then - 1. Return *undefined*. - 1. Assert: _module_.[[Status]] is not `"instantiating"` or `"evaluating"`. - 1. Let _realm_ be module.[[Realm]]. - 1. Assert: _realm_ is a valid Realm. - 1. Let _env_ be NewModuleEnvironment(_realm_.[[GlobalEnv]]). - 1. Set _module_.[[Environment]] to _env_. - 1. Set _module_.[[Status]] to `"instantiated"`. - 1. Return *undefined*. - -
- - -

Evaluate ( ) Concrete Method

- -

The Evaluate concrete method of a Dynamic Module Record implements the corresponding Module Record abstract method.

-

Evaluate transitions this module's [[Status]] from `"instantiated"` to `"evaluated"`.

- -

If execution results in an exception, that exception is recorded in the [[EvaluationError]] field and rethrown by future invocations of Evaluate.

+ +

Dynamic Module Records

+ +

A Dynamic Module Record is used to represent information about a module that is defined programatically. Its fields contain digested information about the names that are exported by the module and its concrete methods use this digest to link, instantiate, and evaluate the module alongside other Abstract Module Records.

+ +

Dependency cycles with Source Text Module Records are avoided since these modules can only export, and not import from other Abstract Module Records.

+ +

Dynamic Module Records support late export binding, in that export names are only validated after execution.

+ +

In addition to the fields, defined in , Dynamic Module Records have the additional fields listed in . Each of these fields is initially set in CreateDynamicModule.

+ + + + + + + + + + + + + + + + + + + + +
+ Field Name + + Value Type + + Meaning +
+ [[ExportNames]] + + A string List of exported names. + + The list of export bindings associated with this Dynamic Module Record. +
+ [[EvaluationError]] + + An abrupt completion | *undefined* + + A completion of type ~throw~ representing the exception that occurred during evaluation. *undefined* if no exception occurred or if [[Status]] is not `"evaluated"`. +
+
+ + +

CreateDynamicModule ( _realm_, _hostDefined_ )

+

This method would be expected to be called by the host when constructing a Module Record in _HostResolveImportedModule_.

+

The abstract operation CreateDynamicModule with arguments _realm_, and _hostDefined_ creates a new Dynamic Module Record performing the following steps:

+ + 1. Let _exportNames_ be a new empty List. + 1. Let _nsModules_ be a new empty List. + 1. Let _module_ be the Dynamic Module Record { [[Realm]]: _realm_, [[Environment]]: *undefined*, [[Namespace]]: *undefined*, [[Status]]: `"uninstantiated"`, [[ExportNames]]: _exportNames_, [[EvaluationError]]: *undefined*, [[HostDefined]]: _hostDefined_ }. + 1. Return _module_. + +
-

Evaluation of dynamic modules calls out to _HostEvaluateDynamicModule_, before finalising the export names of the dynamic modules. Any uninitialized export bindings throw a reference error at this stage.

+

The following definitions specify the required concrete methods for Dynamic Module Records.

+ + +

GetExportedNames ( _exportStarSet_, _nsModule_ ) Concrete Method

+

The GetExportedNames concrete method of a Dynamic Module Record implements the corresponding Module Record abstract method.

+

Any modules exporting names from this Dynamic Module Record are stored so their exports can be amended on execution of this Dynamic Module.

+

It performs the following steps:

+ + 1. Let _module_ be this Dynamic Module Record. + 1. If _module_ is not equal to _nsModule_ or _module_.[[Status]] is not `"evaluated"`, then + 1. Return *null*. + 1. Return _module_.[[exportNames]]. + + +

The *null* return results in an error being thrown for star exports from dynamic modules, and creating an "unfinalized" namespace in the case of an uninstantiated dynamic namespace creation in cycles.

+
+
-

This abstract method performs the following steps:

+ +

ResolveExport ( _exportName_, _resolveSet_ ) Concrete Method

+

The ResolveExport concrete method of a Dynamic Module Record implements the corresponding Module Record abstract method.

+ +

ResolveExport ensures that a binding is created for the dynamic Module Record, lazily creating a binding if needed.

+ +

This abstract method performs the following steps:

+ + + 1. Let _module_ be this Dynamic Module Record. + 1. If _module_.[[Status]] is `"uninstantiated"` then, + 1. Perform ? _module_.Instantiate(). + 1. Let _exportNames_ be _module_.[[ExportNames]]. + 1. If _exportNames_ does not contain _exportName_ then, + 1. Let _envRec_ be the Module Environment Record _module_.[[Environment]] + 1. If _envRec_ does not already have a binding for _exportName_ then, + 1. Perform ! _envRec_.CreateMutableBinding(_exportName_, *false*). + 1. Append _exportName_ to the end of _exportNames_. + 1. Return ResolvedBinding Record { [[Module]]: _module_, [[BindingName]]: _exportName_ }. + +
- - 1. Let _m_ be this Dynamic Module Record. - 1. If _m_.[[Status]]_ is `"evaluated"` then, - 1. Return _m_.[[EvaluationError]]. - 1. Assert: _m_.[[Status]] is `"instantiated"`. - 1. Set _m_.[[Status]] to `"evaluating"`. - 1. Let _result_ be HostEvaluateDynamicModule(_m_). - 1. If _result_ is an abrupt completion, then - 1. Assert: _m_.[[Status]] is `"evaluating"`. - 1. Set _m_.[[Status]] to `"evaluated"`. - 1. Set _m_.[[EvaluationError]] to _result_. - 1. Return _result_. - 1. Let _envRec_ be the value of _module_.[[Environment]]. - 1. For each string _exportName_ in _m_.[[ExportNames]], do - 1. Assert: _envRec_ has a binding for _exportName_. - 1. If the binding for _exportName_ in _envRec_ is uninitialized then, - 1. Let _error_ be a *ReferenceError* exception. - 1. Set _m_.[[Status]] to `"evaluated"`. - 1. Set _m_.[[EvaluationError]] to _error_. - 1. Return _error_. - 1. For each module _exportModule_ in the list _m_.[[PendingNamespaceModules]]. - 1. Let _ns_ be the value of _exportModule_.[[Namespace]]. - 1. Assert: _ns_ is a Module Namespace Exotic Object. - 1. Let _n_ be the value of _ns_.[[HostDefined]]. - 1. Assert: _n_ is a positive integer. - 1. Set _ns_.[[HostDefined]] to _n - 1_. - 1. If _n_ is equal to *1* then, - 1. Let _exportedNames_ be ? _module_.GetExportedNames(« », _module_). - 1. Assert: _exportedNames_ is not *null*. - 1. Let _unambiguousNames_ be a new empty List. - 1. For each _name_ that is an element of _exportedNames_, do - 1. Let _resolution_ be ? _module_.ResolveExport(_name_, « »). - 1. If _resolution_ is a ResolvedBinding Record, append _name_ to _unambiguousNames_. - 1. For each string _exportName_ in _m_.[[ExportNames]], do - 1. Let _namespaceExports_ be _ns_.[[Exports]]. - 1. If _namespaceExports_ does not contain _exportName_ then, - 1. If SameValue(_exportName_, `"default"`) is *false* or _exportModule_ and _m_ are not the same Module Record then, - 1. Insert _exportName_ in the list _namespaceExports_ at the position corresponding to the sort order of `Array.prototype.sort` with *undefined* as _comparefn_. - 1. Set _m_.[[Status]] to `"evaluated"`. - 1. Assert: _m_.[[EvaluationError]] is *undefined*. - 1. Return *undefined*. - -
+ +

Instantiate ( ) Concrete Method

+ +

The Instantiate concrete method of a Dynamic Module Record implements the corresponding Module Record abstract method.

+

On success, Instantiate transitions this module's [[Status]] from `"uninstantiated"` to `"instantiated"`. On failure, an exception is thrown and this module's [[Status]] remains `"uninstantiated"`.

+ +

This abstract method performs the following steps:

+ + + 1. Let _module_ be this Dynamic Module Record. + 1. If _module_.[[Status]] is "instantiated", or "evaluated", then + 1. Return *undefined*. + 1. Assert: _module_.[[Status]] is not `"instantiating"` or `"evaluating"`. + 1. Let _realm_ be module.[[Realm]]. + 1. Assert: _realm_ is a valid Realm. + 1. Let _env_ be NewModuleEnvironment(_realm_.[[GlobalEnv]]). + 1. Set _module_.[[Environment]] to _env_. + 1. Set _module_.[[Status]] to `"instantiated"`. + 1. Return *undefined*. + +
- -

SetDynamicExportBinding ( _name_, _value_ ) Concrete Method

-

The SetDynamicExportBinding concrete method of a Dynamic Module Record implements the corresponding Module Record abstract method for a string _name_ and initialization value _value_.

-

After execution completion, only binding mutation is supported.

-

This method can return an error on abrupt completion.

- - 1. Let _module_ be this Dynamic Module Record. - 1. Let _envRec_ be the module Environment Record _module_.[[Environment]]. - 1. If _module_.[[exportNames]] does not contain _name_ then, - 1. If _module_.[[Status]] is `"evaluated"` then, - 1. Let _error_ be a *ReferenceError* exception. - 1. Return _error_. - 1. Append _name_ to the end of _module_.[[exportNames]]. - 1. Perform _envRec_.CreateMutableBinding(_name_, *false*). - 1. Perform _envRec_.InitializeBinding(_name_, _value_). - 1. Otherwise, - 1. Assert: _envRec_ has a binding for _name_. - 1. If the binding for _name_ in _envRec_ has not been initialized then, - 1. If _module_.[[Status]] is `"evaluated"` then, - 1. Let _error_ be a *ReferenceError* exception. - 1. Return _error_. - 1. Perform _envRec_.InitializeBinding(_name_, _value_). - 1. Otherwise, - 1. Perform _envRec_.SetMutableBinding(_name_, _value_, *true*). - 1. Return *undefined*. - -
-
+ +

Evaluate ( ) Concrete Method

+ +

The Evaluate concrete method of a Dynamic Module Record implements the corresponding Module Record abstract method.

+

Evaluate transitions this module's [[Status]] from `"instantiated"` to `"evaluated"`.

+ +

If execution results in an exception, that exception is recorded in the [[EvaluationError]] field and rethrown by future invocations of Evaluate.

+ +

Evaluation of dynamic modules calls out to _HostEvaluateDynamicModule_, before finalising the export names of the dynamic modules. Any uninitialized export bindings throw a reference error at this stage.

+ +

This abstract method performs the following steps:

+ + + 1. Let _m_ be this Dynamic Module Record. + 1. If _m_.[[Status]]_ is `"evaluated"` then, + 1. Return _m_.[[EvaluationError]]. + 1. Assert: _m_.[[Status]] is `"instantiated"`. + 1. Set _m_.[[Status]] to `"evaluating"`. + 1. Let _result_ be HostEvaluateDynamicModule(_m_). + 1. If _result_ is an abrupt completion, then + 1. Assert: _m_.[[Status]] is `"evaluating"`. + 1. Set _m_.[[Status]] to `"evaluated"`. + 1. Set _m_.[[EvaluationError]] to _result_. + 1. Return _result_. + 1. Let _envRec_ be the value of _module_.[[Environment]]. + 1. For each string _exportName_ in _m_.[[ExportNames]], do + 1. Assert: _envRec_ has a binding for _exportName_. + 1. If the binding for _exportName_ in _envRec_ is uninitialized then, + 1. Let _error_ be a *ReferenceError* exception. + 1. Set _m_.[[Status]] to `"evaluated"`. + 1. Set _m_.[[EvaluationError]] to _error_. + 1. Return _error_. + 1. Let _ns_ be ? GetModuleNamespace(_m_). + 1. Assert: _ns_ is a Module Namespace Exotic Object. + 1. Assert: _ns_.[[Exports]] is *null*. + 1. Let _exportedNames_ be ? _m_.GetExportedNames(« », _m_). + 1. Assert: _exportedNames_ is not *null*. + 1. Let _unambiguousNames_ be a new empty List. + 1. For each _name_ that is an element of _exportedNames_, do + 1. Let _resolution_ be ? _m_.ResolveExport(_name_, « »). + 1. If _resolution_ is a ResolvedBinding Record, append _name_ to _unambiguousNames_. + 1. Let _sortedExports_ be a new List containing the same values as the list _unambiguousNames_ where the values are ordered as if an Array of the same values had been sorted using `Array.prototype.sort` using *undefined* as _comparefn_. + 1. Set _ns_.[[Exports]] to _sortedExports_. + 1. Set _m_.[[Status]] to `"evaluated"`. + 1. Assert: _m_.[[EvaluationError]] is *undefined*. + 1. Return *undefined*. + +
- -

Runtime Semantics: HostEvaluateDynamicModule ( _dynamicModule_ )

-

HostEvaluateDynamicModule is an implementation-defined abstract operation that performs programmatic execution of a Dynamic Module Record, _dynamicModule_.

-

The implementation of HostEvaluateDynamicModule must conform to the following requirements:

-
    -
  • - HostEvaluateDynamicModule will call the SetDynamicExportBinding concrete method on the _dynamicModule_ to initialize the export bindings. -
  • -
  • - If there is an evaluation error, it must be thrown. -
  • -
- -

HostEvaluateDynamicModule must not itself rely on checking what lexical bindings have already been initialized for the module. It is important that the bindings defined in evaluation are fully independent of what bindings are imported.

-
-
-
+ +

SetDynamicExportBinding ( _name_, _value_ ) Concrete Method

+

The SetDynamicExportBinding concrete method of a Dynamic Module Record implements the corresponding Module Record abstract method for a string _name_ and initialization value _value_.

+

After execution completion, only binding mutation is supported.

+

This method can return an error on abrupt completion.

+ + 1. Let _module_ be this Dynamic Module Record. + 1. Let _envRec_ be the module Environment Record _module_.[[Environment]]. + 1. If _module_.[[exportNames]] does not contain _name_ then, + 1. If _module_.[[Status]] is `"evaluated"` then, + 1. Let _error_ be a *ReferenceError* exception. + 1. Return _error_. + 1. Append _name_ to the end of _module_.[[exportNames]]. + 1. Perform _envRec_.CreateMutableBinding(_name_, *false*). + 1. Perform _envRec_.InitializeBinding(_name_, _value_). + 1. Otherwise, + 1. Assert: _envRec_ has a binding for _name_. + 1. If the binding for _name_ in _envRec_ has not been initialized then, + 1. If _module_.[[Status]] is `"evaluated"` then, + 1. Let _error_ be a *ReferenceError* exception. + 1. Return _error_. + 1. Perform _envRec_.InitializeBinding(_name_, _value_). + 1. Otherwise, + 1. Perform _envRec_.SetMutableBinding(_name_, _value_, *true*). + 1. Return *undefined*. +
+
+ + +

Runtime Semantics: HostEvaluateDynamicModule ( _dynamicModule_ )

+

HostEvaluateDynamicModule is an implementation-defined abstract operation that performs programmatic execution of a Dynamic Module Record, _dynamicModule_.

+

The implementation of HostEvaluateDynamicModule must conform to the following requirements:

+
    +
  • + HostEvaluateDynamicModule will call the SetDynamicExportBinding concrete method on the _dynamicModule_ to initialize the export bindings. +
  • +
  • + If there is an evaluation error, it must be thrown. +
  • +
+ +

HostEvaluateDynamicModule must not itself rely on checking what lexical bindings have already been initialized for the module. It is important that the bindings defined in evaluation are fully independent of what bindings are imported.

+
\ No newline at end of file