From 3feb1ba6e7cd182956af8f46545a22bd682a4c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Tue, 18 Feb 2025 16:44:04 -0800 Subject: [PATCH] Normative: Add JSON modules (#3391) --- spec.html | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) diff --git a/spec.html b/spec.html index f366e57696..8fdf0480d6 100644 --- a/spec.html +++ b/spec.html @@ -28527,6 +28527,192 @@

+ +

Synthetic Module Records

+ +

A Synthetic Module Record is used to represent information about a module that is defined by specifications. Its exported names are statically defined at creation, while their corresponding values can change 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, JSON modules or CSS modules. + +

In addition to the fields defined in Synthetic Module Records have the additional fields listed in .

+ + + + + + + + + + + + + + + + + + + + +
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. It must not modify [[ExportNames]]. It may return an abrupt completion.
+
+ + +

+ 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 NormalCompletion(~unused~). + 1. Return the Synthetic Module Record { [[Realm]]: _realm_, [[Environment]]: ~empty~, [[Namespace]]: ~empty~, [[HostDefined]]: *undefined*, [[ExportNames]]: « *"default"* », [[EvaluationSteps]]: _setDefaultExport_ }. + +
+ + +

+ 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 an existing 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 ( ): a normal completion containing ~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_ of _module_.[[ExportNames]], do + 1. Perform ! _env_.CreateMutableBinding(_exportName_, *false*). + 1. Perform ! _env_.InitializeBinding(_exportName_, *undefined*). + 1. Return NormalCompletion(~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 running execution context. + 1. Push _moduleContext_ onto 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 ! Call(_pc_.[[Resolve]], *undefined*, « *undefined* »). + 1. Return _pc_.[[Promise]]. + +
+
+
+

GetImportedModule ( @@ -28582,12 +28768,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"*, 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.
  • The actual process performed is host-defined, but typically consists of performing whatever I/O operations are necessary to load the appropriate Module Record. Multiple different (_referrer_, _moduleRequest_.[[Specifier]], _moduleRequest_.[[Attributes]]) triples may map to the same Module Record instance. The actual mapping semantics is host-defined but typically a normalization process is applied to _specifier_ as part of the mapping process. A typical normalization process would include actions such as expansion of relative and abbreviated path specifiers.

    + + +

    The above text requires that hosts support JSON modules when imported with `type: "json"` (and HostLoadImportedModule completes normally), but it does not prohibit hosts from supporting JSON modules when imported without `type: "json"`.

    +