Skip to content

Commit d554d6d

Browse files
authored
Re-add JSON module scripts
Reland JSON modules (#4315), originally found in db03474 but removed in a530f6f. Importing a JSON module now requires the module type to be specified at every import site with an import assertion, addressing the security concern that led to the revert. Additionally, some of the infrastructure now lives in the TC39 proposal at https://github.com/tc39/proposal-json-modules, and 3d45584 introduced the import assertions integration, so overall this patch is pretty small.
1 parent afc7950 commit d554d6d

File tree

1 file changed

+97
-41
lines changed

1 file changed

+97
-41
lines changed

source

+97-41
Original file line numberDiff line numberDiff line change
@@ -2888,13 +2888,15 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
28882888
<li>The <dfn data-x="js-HostGetSupportedImportAssertions" data-x-href="https://tc39.es/proposal-import-assertions/#sec-hostgetsupportedimportassertions">HostGetSupportedImportAssertions</dfn> abstract operation</li>
28892889
</ul>
28902890

2891-
<p>The following terms are defined in the <cite>JSON modules</cite> proposal and used in this
2892-
specification: <ref spec=JSJSONMODULES></p>
2891+
<p>User agents that support JavaScript must also implement the <cite>JSON modules</cite>
2892+
proposal. The following terms are defined there, and used in this specification: <ref
2893+
spec=JSJSONMODULES></p>
28932894

28942895
<ul class="brief">
2895-
<li><dfn data-x-href="https://tc39.es/proposal-json-modules/#sec-createsyntheticmodule">CreateSyntheticModule</dfn></li>
2896-
<li><dfn data-x-href="https://tc39.es/proposal-json-modules/#sec-setsyntheticmoduleexport">SetSyntheticModuleExport</dfn></li>
2897-
<li><dfn data-x-href="https://tc39.es/proposal-json-modules/#sec-synthetic-module-records">Synthetic Module Record</dfn></li>
2896+
<li>The <dfn data-x-href="https://tc39.es/proposal-json-modules/#sec-create-default-export-synthetic-module">CreateDefaultExportSyntheticModule</dfn> abstract operation</li>
2897+
<li>The <dfn data-x-href="https://tc39.es/proposal-json-modules/#sec-setsyntheticmoduleexport">SetSyntheticModuleExport</dfn> abstract operation</li>
2898+
<li>The <dfn data-x-href="https://tc39.es/proposal-json-modules/#sec-synthetic-module-records">Synthetic Module Record</dfn> specification type</li>
2899+
<li>The <dfn data-x-href="https://tc39.es/proposal-json-modules/#sec-parse-json-module">ParseJSONModule</dfn> abstract operation</li>
28982900
</ul>
28992901
</dd>
29002902

@@ -58396,6 +58398,9 @@ interface <dfn interface>HTMLScriptElement</dfn> : <span>HTMLElement</span> {
5839658398
<p>The contents of the external script resource for <span data-x="CSS module script">CSS module
5839758399
scripts</span> must conform to the requirements of the CSS specification. <ref spec=CSS></p>
5839858400

58401+
<p>The contents of the external script resource for <span data-x="JSON module script">JSON module
58402+
scripts</span> must conform to the requirements of the JSON specification <ref spec=JSON>.</p>
58403+
5839958404
<p>When used to include <span data-x="data block">data blocks</span>, the data must be embedded
5840058405
inline, the format of the data must be given using the <code data-x="attr-script-type">type</code>
5840158406
attribute, and the contents of the <code>script</code> element must conform to the requirements
@@ -58714,7 +58719,29 @@ o............A....e
5871458719
where this <code>script</code> element appears in the document, it will not be evaluated until
5871558720
both document parsing has complete and its dependency (<code data-x="">dom-utils.mjs</code>) has
5871658721
been fetched and evaluated.</p>
58722+
</div>
5871758723

58724+
<div class="example" id="json-module-script-example">
58725+
<p>The following sample shows how a <span>JSON module script</span> can be imported from inside
58726+
a <span>JavaScript module script</span>:</p>
58727+
58728+
<pre><code class="html" data-x="">&lt;script type="module">
58729+
import peopleInSpace from "http://api.open-notify.org/astros.json" assert { type: "json" };
58730+
58731+
const list = document.querySelector("#people-in-space");
58732+
for (const { craft, name } of peopleInSpace.people) {
58733+
const li = document.createElement("li");
58734+
li.textContent = `${name} / ${craft}`;
58735+
list.append(li);
58736+
}
58737+
&lt;/script></code></pre>
58738+
58739+
<p>MIME type checking for module scripts is strict. In order for the fetch of the <span>JSON
58740+
module script</span> to succeed, the HTTP reponse must have a <span>JSON MIME type</span>, for
58741+
example <code data-x="">Content-Type: text/json</code>. On the other hand, if the <code
58742+
data-x="">assert { type: "json" }</code> part of the statement is omitted, it is assumed that the
58743+
intent is to import a <span>JavaScript module script</span>, and the fetch will fail if the HTTP
58744+
response has a MIME type that is not a <span>JavaScript MIME type</span>.</p>
5871858745
</div>
5871958746

5872058747
<div w-nodev>
@@ -90154,8 +90181,8 @@ document.querySelector("button").addEventListener("click", bound);
9015490181
<li><p>a <span>Source Text Module Record</span>, for <span data-x="JavaScript module
9015590182
script">JavaScript module scripts</span>;</p></li>
9015690183

90157-
<li><p>a <span>Synthetic Module Record</span>, for <span data-x="CSS module script">CSS
90158-
module scripts</span>; or</p></li>
90184+
<li><p>a <span>Synthetic Module Record</span>, for <span data-x="CSS module script">CSS module
90185+
scripts</span> and <span data-x="JSON module script">JSON module scripts</span></p></li>
9015990186

9016090187
<li><p>null, representing a parsing failure.</p></li>
9016190188
</ul>
@@ -90221,7 +90248,7 @@ document.querySelector("button").addEventListener("click", bound);
9022190248
data-x="concept-script">script</span>. It has no additional <span data-x="struct
9022290249
item">items</span>.</p>
9022390250

90224-
<p><span data-x="module script">Module scripts</span> can be classified into two types:</p>
90251+
<p><span data-x="module script">Module scripts</span> can be classified into three types:</p>
9022590252

9022690253
<ul>
9022790254
<li><p>A <span>module script</span> is a <dfn data-export="">JavaScript module script</dfn> if
@@ -90233,23 +90260,33 @@ document.querySelector("button").addEventListener("click", bound);
9023390260
data-x="concept-script-record">record</span> is a <span>Synthetic Module Record</span>, and it
9023490261
was created via the <span data-x="creating a CSS module script">create a CSS module
9023590262
script</span> algorithm. CSS module scripts represent a parsed CSS stylesheet.</p>
90236-
<!--
90237-
This definition is not super-rigorous, but it doesn't need to be for now. Technically, the
90238-
"it was created via..." requirement is redundant, since there are no other Synthetic Module
90239-
Record users.
9024090263

90241-
If we ever: (a) get more Synthetic Module Record Users; or (b) start testing if something is a
90242-
CSS module script in algorithms, instead of just referring to the concept, then we should
90243-
consider adding a type item to the module script struct.
90264+
<!--
90265+
This definition is not super-rigorous, but it doesn't need to be for now. If we ever start
90266+
testing if something is a CSS module script in algorithms, instead of just referring to the
90267+
concept, then we should consider adding a type item to the module script struct.
9024490268
-->
90245-
90246-
<p class="note">As CSS stylesheets do not import dependent modules, and do not throw exceptions
90247-
on evaluation, the <span data-x="concept-script-script-fetch-options">fetch options</span> and
90248-
<span data-x="concept-script-base-url">base URL</span> of a <span>CSS module script</span> are
90249-
always null.</p>
9025090269
</li>
90270+
90271+
<li>
90272+
<p>A <span>module script</span> is a <dfn data-export="">JSON module script</dfn> if its <span
90273+
data-x="concept-script-record">record</span> is a <span>Synthetic Module Record</span>, and it
90274+
was created via the <span data-x="creating a JSON module script">create a JSON module
90275+
script</span> algorithm. JSON module scripts represent a parsed JSON document.</p>
90276+
90277+
<!--
90278+
This definition is not super-rigorous, but it doesn't need to be for now. If we ever start
90279+
testing if something is a JSON module script in algorithms, instead of just referring to the
90280+
concept, then we should consider adding a type item to the module script struct.
90281+
-->
9025190282
</ul>
9025290283

90284+
<p class="note">As CSS stylesheets and JSON documents do not import dependent modules, and do not
90285+
throw exceptions on evaluation, the <span data-x="concept-script-script-fetch-options">fetch
90286+
options</span> and <span data-x="concept-script-base-url">base URL</span> of <span data-x="CSS
90287+
module script">CSS module scripts</span> and <span data-x="JSON module script">JSON module
90288+
scripts</span> and are always null.</p>
90289+
9025390290
<p>The <dfn>active script</dfn> is determined by the following algorithm:</p>
9025490291

9025590292
<ol>
@@ -90648,8 +90685,9 @@ document.querySelector("button").addEventListener("click", bound);
9064890685
type</var> be <var>entry</var>.[[Value]]. Otherwise let <var>module type</var> be "<code
9064990686
data-x="">javascript</code>".</p></li>
9065090687

90651-
<li><p>If <var>module type</var> is neither "<code data-x="">javascript</code>" nor "<code
90652-
data-x="">css</code>", then asynchronously complete this algorithm with null, and return.</p></li>
90688+
<li><p>If <var>module type</var> is not "<code data-x="">javascript</code>", "<code
90689+
data-x="">css</code>", or "<code data-x="">json</code>", then asynchronously complete this
90690+
algorithm with null, and return.</p></li>
9065390691

9065490692
<li><p><span>Fetch a single module script</span> given <var>url</var>, <var>settings
9065590693
object</var>, "<code data-x="">script</code>", <var>options</var>, <var>settings object</var>,
@@ -91126,11 +91164,12 @@ document.querySelector("button").addEventListener("click", bound);
9112691164
</ol>
9112791165
</li>
9112891166

91129-
<li><p>Assert: <var>module type</var> is either "<code data-x="">javascript</code>" or "<code
91130-
data-x="">css</code>". Otherwise we would not have reached this point because a failure would
91131-
have been raised when inspecting <var>moduleRequest</var>.[[Assertions]] in <a
91132-
href="#validate-requested-module-specifiers">create a JavaScript module script</a> or <span>fetch
91133-
an import() module script graph</span>.</p></li>
91167+
<li><p>Assert: <var>module type</var> is "<code data-x="">javascript</code>", "<code
91168+
data-x="">css</code>", or "<code data-x="">json</code>". Otherwise we would not have reached
91169+
this point because a failure would have been raised when inspecting
91170+
<var>moduleRequest</var>.[[Assertions]] in <a
91171+
href="#validate-requested-module-specifiers">create a JavaScript module script</a> or
91172+
<span>fetch an import() module script graph</span>.</p></li>
9113491173

9113591174
<li><p>Let <var>moduleMap</var> be <var>module map settings object</var>'s <span
9113691175
data-x="concept-settings-object-module-map">module map</span>.</p></li>
@@ -91215,6 +91254,11 @@ document.querySelector("button").addEventListener("click", bound);
9121591254
result of <span>creating a CSS module script</span> given <var>source text</var> and <var>module
9121691255
map settings object</var>.</p></li>
9121791256

91257+
<li><p>If <var>MIME type essence</var> is a <span>JSON MIME type</span> and <var>module
91258+
type</var> is "<code data-x="">json</code>", then set <var>module script</var> to the result of
91259+
<span>creating a JSON module script</span> given <var>source text</var> and <var>module map
91260+
settings object</var>.</p></li>
91261+
9121891262
<li>
9121991263
<p><span data-x="map set">Set</span> <var>moduleMap</var>[(<var>url</var>, <var>module
9122091264
type</var>)] to <var>module script</var>, and asynchronously complete this algorithm with
@@ -91417,8 +91461,9 @@ document.querySelector("button").addEventListener("click", bound);
9141791461
data-x="">javascript</code>".</p></li>
9141891462

9141991463
<li>
91420-
<p>If <var>url</var> is failure, or if <var>module type</var> is neither "<code
91421-
data-x="">javascript</code>" nor "<code data-x="">css</code>", then:</p>
91464+
<p>If <var>url</var> is failure, or if <var>module type</var> is not "<code
91465+
data-x="">javascript</code>", "<code data-x="">css</code>", or "<code data-x="">json</code>",
91466+
then:</p>
9142291467
<ol>
9142391468
<li><p>Let <var>error</var> be a new <code>TypeError</code> exception.</p></li>
9142491469

@@ -91480,27 +91525,38 @@ document.querySelector("button").addEventListener("click", bound);
9148091525
</li>
9148191526

9148291527
<li><p>Set <var>script</var>'s <span data-x="concept-script-record">record</span> to the result
91483-
of <span data-x="create a synthetic module record with a default export">creating a synthetic
91484-
module record with a default export</span> of <var>sheet</var> with <var>settings</var>.</p>
91485-
</li>
91528+
of <span>CreateDefaultExportSyntheticModule</span>(<var>sheet</var>).</p></li>
9148691529

9148791530
<li><p>Return <var>script</var>.</p></li>
9148891531
</ol>
9148991532

91490-
<p>To <dfn>create a synthetic module record with a default export</dfn> of a JavaScript value
91491-
<var>value</var> with an <span>environment settings object</span> <var>settings</var>:</p>
91533+
<p>To <dfn data-x="creating a JSON module script">create a JSON module script</dfn>, given a
91534+
string <var>source</var> and an <span>environment settings object</span> <var>settings</var>:</p>
9149291535

9149391536
<ol>
91537+
<li><p>Let <var>script</var> be a new <span>module script</span> that this algorithm will
91538+
subsequently initialize.</p></li>
91539+
91540+
<li><p>Set <var>script</var>'s <span>settings object</span> to <var>settings</var>.</p></li>
91541+
91542+
<li><p>Set <var>script</var>'s <span data-x="concept-script-base-url">base URL</span> and
91543+
<span data-x="concept-script-script-fetch-options">fetch options</span> to null.</p></li>
91544+
91545+
<li><p>Set <var>script</var>'s <span data-x="concept-script-parse-error">parse error</span> and
91546+
<span data-x="concept-script-error-to-rethrow">error to rethrow</span> to null.</p></li>
91547+
9149491548
<li>
91495-
<p>Return <span>CreateSyntheticModule</span>(« "<code data-x="">default</code>" », the following
91496-
steps, <var>settings</var>'s <span data-x="environment settings object's Realm">Realm</span>,
91497-
<var>value</var>) with the following steps given <var>module</var> as an argument:</p>
91549+
<p>Let <var>result</var> be <span>ParseJSONModule</span>(<var>source</var>).</p>
9149891550

91499-
<ol>
91500-
<li>Perform ! <span>SetSyntheticModuleExport</span>(<var>module</var>, "<code
91501-
data-x="">default</code>", <var>module</var>.[[HostDefined]]).</li>
91502-
</ol>
91551+
<p>If this throws an exception, set <var>script</var>'s <span
91552+
data-x="concept-script-parse-error">parse error</span> to that exception, and return
91553+
<var>script</var>.</p>
9150391554
</li>
91555+
91556+
<li><p>Set <var>script</var>'s <span data-x="concept-script-record">record</span> to
91557+
<var>result</var>.</p></li>
91558+
91559+
<li><p>Return <var>script</var>.</p></li>
9150491560
</ol>
9150591561

9150691562
<h5 id="calling-scripts">Calling scripts</h5>

0 commit comments

Comments
 (0)