Dynamic Modules

Introduction

Dynamic Modules allow non-source-text module records to be created and used by host environments.

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

1Dynamic 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 Table 37, Dynamic Module Records have the additional fields listed in Table 1. Each of these fields is initially set in CreateDynamicModule.

Table 1: Additional Fields of Dynamic Module Records
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".

1.1CreateDynamicModule ( 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.
  2. Let nsModules be a new empty List.
  3. Let module be the Dynamic Module Record { [[Realm]]: realm, [[Environment]]: undefined, [[Namespace]]: undefined, [[Status]]: "uninstantiated", [[ExportNames]]: exportNames, [[EvaluationError]]: undefined, [[HostDefined]]: hostDefined }.
  4. Return module.

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

1.2GetExportedNames ( 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.
  2. If module is not equal to nsModule or module.[[Status]] is not "evaluated", then
    1. Return null.
  3. Return module.[[exportNames]].
Note

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.

1.3ResolveExport ( 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.
  2. If module.[[Status]] is "uninstantiated" then,
    1. Perform ? module.Instantiate().
  3. Let exportNames be module.[[ExportNames]].
  4. If exportNames does not contain exportName then,
    1. Let envRec be the Module Environment Record module.[[Environment]]
    2. If envRec does not already have a binding for exportName then,
      1. Perform ! envRec.CreateMutableBinding(exportName, false).
    3. Append exportName to the end of exportNames.
  5. Return ResolvedBinding Record { [[Module]]: module, [[BindingName]]: exportName }.

1.4Instantiate ( ) 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.
  2. If module.[[Status]] is "instantiated", or "evaluated", then
    1. Return undefined.
  3. Assert: module.[[Status]] is not "instantiating" or "evaluating".
  4. Let realm be module.[[Realm]].
  5. Assert: realm is a valid Realm.
  6. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]).
  7. Set module.[[Environment]] to env.
  8. Set module.[[Status]] to "instantiated".
  9. Return undefined.

1.5Evaluate ( ) 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.
  2. If m.[[Status]]_ is "evaluated" then,
    1. Return m.[[EvaluationError]].
  3. Assert: m.[[Status]] is "instantiated".
  4. Set m.[[Status]] to "evaluating".
  5. Let result be HostEvaluateDynamicModule(m).
  6. If result is an abrupt completion, then
    1. Assert: m.[[Status]] is "evaluating".
    2. Set m.[[Status]] to "evaluated".
    3. Set m.[[EvaluationError]] to result.
    4. Return result.
  7. Let envRec be the value of module.[[Environment]].
  8. For each string exportName in m.[[ExportNames]], do
    1. Assert: envRec has a binding for exportName.
    2. If the binding for exportName in envRec is uninitialized then,
      1. Let error be a ReferenceError exception.
      2. Set m.[[Status]] to "evaluated".
      3. Set m.[[EvaluationError]] to error.
      4. Return error.
  9. Let ns be ? GetModuleNamespace(m).
  10. Assert: ns is a Module Namespace Exotic Object.
  11. Assert: ns.[[Exports]] is null.
  12. Let exportedNames be ? m.GetExportedNames(« », m).
  13. Assert: exportedNames is not null.
  14. Let unambiguousNames be a new empty List.
  15. For each name that is an element of exportedNames, do
    1. Let resolution be ? m.ResolveExport(name, « »).
    2. If resolution is a ResolvedBinding Record, append name to unambiguousNames.
  16. 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.
  17. Set ns.[[Exports]] to sortedExports.
  18. Set m.[[Status]] to "evaluated".
  19. Assert: m.[[EvaluationError]] is undefined.
  20. Return undefined.

1.6SetDynamicExportBinding ( 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.
  2. Let envRec be the module Environment Record module.[[Environment]].
  3. If module.[[exportNames]] does not contain name then,
    1. If module.[[Status]] is "evaluated" then,
      1. Let error be a ReferenceError exception.
      2. Return error.
    2. Append name to the end of module.[[exportNames]].
    3. Perform envRec.CreateMutableBinding(name, false).
    4. Perform envRec.InitializeBinding(name, value).
  4. Otherwise,
    1. Assert: envRec has a binding for name.
    2. 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.
        2. Return error.
      2. Perform envRec.InitializeBinding(name, value).
    3. Otherwise,
      1. Perform envRec.SetMutableBinding(name, value, true).
  5. Return undefined.

2Runtime 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:

Note

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.