From 9e016c19bfb583ee52edc392f80969decc9457d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Wed, 14 Aug 2024 13:54:49 +0200 Subject: [PATCH] Normative: Add JSON modules --- spec.html | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/spec.html b/spec.html index 0af02f1bc4..394805cbb0 100644 --- a/spec.html +++ b/spec.html @@ -28440,6 +28440,209 @@

+ +

Synthetic Module Records

+ +

A Synthetic Module Record is used to represent information about a module given a list of export names with their corresponding values. The set of exported names is static, and determined at creation time (as an argument to CreateSyntheticModule), while the set of exported values can be changed over time using SetSyntheticModuleExport. It has no imports or dependencies.

+ + A Synthetic Module Record could be used for defining a variety of module types: for example, built-in modules, or JSON modules, or CSS modules. + +

In addition to the fields defined in Synthetic Module Records have the additional fields listed in . Each of these fields is initially set in CreateSyntheticModule.

+ + + + + + + + + + + + + + + + + + + + +
Field NameValue TypeMeaning
[[ExportNames]]a List of StringsThe names of the exports of the module. This list does not contain duplicates.
[[EvaluationSteps]]an Abstract ClosureThe initialization logic to perform upon evaluation of the module, taking the Synthetic Module Record as its sole argument. These will usually set up the exported values, by using SetSyntheticModuleExport. It must not modify [[ExportNames]]. It may return an abrupt completion.
+
+ + +

+ CreateSyntheticModule ( + _exportNames_: a List of Strings without duplicates, + _evaluationSteps_: an Abstract Closure, + _realm_: a Realm Record, + ): a Synthetic Module Record +

+
+
description
+
+
+ + + 1. Return the Synthetic Module Record { [[Realm]]: _realm_, [[Environment]]: ~empty~, [[Namespace]]: ~empty~, [[HostDefined]]: *undefined*, [[ExportNames]]: _exportNames_, [[EvaluationSteps]]: _evaluationSteps_ }. + +
+ + +

+ CreateDefaultExportSyntheticModule ( + _defaultExport_: an ECMAScript Language value, + ): a Synthetic Module Record +

+
+
description
+
It creates a Synthetic Module Record whose default export is _defaultExport_.
+
+ + 1. Let _realm_ be the current Realm Record. + 1. Let _setDefaultExport_ be a new Abstract Closure with parameters (_module_) that captures _defaultExport_ and performs the following steps when called: + 1. Perform SetSyntheticModuleExport(_module_, *"default"*, _defaultExport_). + 1. Return CreateSyntheticModule(« *"default"* », _setDefaultExport_, _realm_). + +
+ + +

+ ParseJSONModule ( + _source_: a String, + ): either a normal completion containing a Synthetic Module Record, or a throw completion +

+
+
description
+
+
+ + + 1. Let _json_ be ? Call(%JSON.parse%, *undefined*, « _source_ »). + 1. Return CreateDefaultExportSyntheticModule(_json_). + +
+ + +

+ SetSyntheticModuleExport ( + _module_: a Synthetic Module Record, + _exportName_: a String, + _exportValue_: an ECMAScript language value, + ): ~unused~ +

+
+
description
+
It can be used to set or change the exported value for a pre-established export of a Synthetic Module Record.
+
+ + + 1. Assert: _module_.[[ExportNames]] contains _exportName_. + 1. Let _envRec_ be _module_.[[Environment]]. + 1. Assert: _envRec_ is not ~empty~. + 1. Perform _envRec_.SetMutableBinding(_exportName_, _exportValue_, *true*). + 1. Return ~unused~. + +
+ + +

Implementation of Module Record abstract methods

+ +

The following are the concrete methods for Synthetic Module Record that implement the corresponding Module Record abstract methods defined in .

+ + +

LoadRequestedModules ( ): a Promise

+
+
for
+
a Synthetic Module Record _module_
+
+ + + 1. Return ! PromiseResolve(%Promise%, *undefined*). + + + + Synthetic Module Records have no dependencies. + +
+ + +

GetExportedNames ( ): a List of Strings

+
+
for
+
a Synthetic Module Record _module_
+
+ + + 1. Return _module_.[[ExportNames]]. + +
+ + +

+ ResolveExport ( + _exportName_: a String, + ): a ResolvedBinding Record or *null* +

+
+
for
+
a Synthetic Module Record _module_
+
+ + + 1. If _module_.[[ExportNames]] does not contain _exportName_, return *null*. + 1. Return ResolvedBinding Record { [[Module]]: _module_, [[BindingName]]: _exportName_ }. + +
+ + +

Link ( ): ~unused~

+
+
for
+
a Synthetic Module Record _module_
+
+ + + 1. Let _realm_ be _module_.[[Realm]]. + 1. Let _env_ be NewModuleEnvironment(_realm_.[[GlobalEnv]]). + 1. Set _module_.[[Environment]] to _env_. + 1. For each String _exportName_ in _module_.[[ExportNames]], do + 1. Perform ! _env_.CreateMutableBinding(_exportName_, *false*). + 1. Perform ! _env_.InitializeBinding(_exportName_, *undefined*). + 1. Return ~unused~. + +
+ + +

Evaluate ( ): a Promise

+
+
for
+
a Synthetic Module Record _module_
+
+ + + 1. Let _moduleContext_ be a new ECMAScript code execution context. + 1. Set the Function of _moduleContext_ to *null*. + 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. Suspend the currently running execution context. + 1. Push _moduleContext_ on to the execution context stack; _moduleContext_ is now the running execution context. + 1. Let _steps_ be _module_.[[EvaluationSteps]]. + 1. Let _result_ be Completion(_steps_(_module_)). + 1. Suspend _moduleContext_ and remove it from the execution context stack. + 1. Resume the context that is now on the top of the execution context stack as the running execution context. + 1. Let _pc_ be ! NewPromiseCapability(%Promise%). + 1. IfAbruptRejectPromise(_result_, _pc_). + 1. Perform ! _pc_.[[Resolve]](_result_). + 1. Return _pc_.[[Promise]]. + +
+
+
+

GetImportedModule ( @@ -28495,12 +28698,19 @@

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"*, the host environment must perform FinishLoadingImportedModule(_referrer_, _moduleRequest_, _payload_, _result_), where _result_ is either the Completion Record returned by an invokation of ParseJSONModule or a throw completion.

    +
  • The operation must treat _payload_ as an opaque value to be passed through to FinishLoadingImportedModule.
  • The actual process performed is host-defined, but typically consists of performing whatever I/O operations are necessary to load the appropriate Module Record. Multiple different (_referrer_, _moduleRequest_.[[Specifier]], _moduleRequest_.[[Attributes]]) triples may map to the same Module Record instance. The actual mapping semantics is host-defined but typically a normalization process is applied to _specifier_ as part of the mapping process. A typical normalization process would include actions such as expansion of relative and abbreviated path specifiers.

    + + +

    The above text implies that hosts *must* support JSON modules imported with `type: "json"` (if it completes normally), but it doesn't prohibit hosts from supporting JSON modules imported with no type specified.

    +