Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent modules from being imported with a type: 'javascript' assertion #7350

Merged
merged 10 commits into from
Nov 23, 2021
163 changes: 94 additions & 69 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -58801,6 +58801,21 @@ o............A....e
where this <code>script</code> element appears in the document, it will not be evaluated until
both document parsing has complete and its dependency (<code data-x="">dom-utils.mjs</code>) has
been fetched and evaluated.</p>

<p>JavaScript module scripts are the default import type when importing from another JavaScript
dandclark marked this conversation as resolved.
Show resolved Hide resolved
module; that is, when an import statement lacks a "type" import assertion the import's type will
dandclark marked this conversation as resolved.
Show resolved Hide resolved
be JavaScript. Attempting to import a JavaScript resource using an import statement with a "type"
import assertion will fai:</p>
dandclark marked this conversation as resolved.
Show resolved Hide resolved

<pre><code class="html">&lt;script type="module">
// All of the following will fail, assuming that the imported mjs files are served with a
dandclark marked this conversation as resolved.
Show resolved Hide resolved
// JavaScript MIME type. JavaScript module scripts are the default and cannot be imported with
// any import assertion.
dandclark marked this conversation as resolved.
Show resolved Hide resolved
import foo from "./bar.mjs" assert { type: "javascript" };
import foo2 from "./bar2.mjs" assert { type: "js" };
import foo3 from "./bar3.mjs" assert { type: "" };
await import("./bar4.mjs", { assert: { type: null } });
dandclark marked this conversation as resolved.
Show resolved Hide resolved
&lt;/script></code></pre>
</div>

<div class="example" id="json-module-script-example">
Expand Down Expand Up @@ -91374,14 +91389,12 @@ document.querySelector("button").addEventListener("click", bound);
we only asked for "<code data-x="">type</code>" assertions in
<span>HostGetSupportedImportAssertions</span>.</p></li>

<li><p>If <var>moduleRequest</var>.[[Assertions]] has a <span>Record</span> <var>entry</var>
such that <var>entry</var>.[[Key]] is "<code data-x="">type</code>", then let <var>module
type</var> be <var>entry</var>.[[Value]]. Otherwise let <var>module type</var> be "<code
data-x="">javascript</code>".</p></li>
<li><p>Let <var>moduleType</var> be the result of running the <span>module type from module
request</span> steps given <var>moduleRequest</var>.</p></li>

<li><p>If the result of running the <span>module type allowed</span> steps given <var>module
type</var> and <var>settings object</var> is false, then asynchronously complete this algorithm
with null, and return.</p></li>
<li><p>If the result of running the <span>module type allowed</span> steps given
<var>moduleType</var> and <var>settings object</var> is false, then asynchronously complete this
algorithm with null, and return.</p></li>

<li><p><span>Fetch a single module script</span> given <var>url</var>, <var>settings
object</var>, "<code data-x="">script</code>", <var>options</var>, <var>settings object</var>,
Expand All @@ -91393,7 +91406,7 @@ document.querySelector("button").addEventListener("click", bound);
<li><p>If <var>result</var> is null, asynchronously complete this algorithm with null, and
return.</p></li>

<li><p>Let <var>visited set</var> be « (<var>url</var>, <var>module type</var>) ».</p></li>
<li><p>Let <var>visited set</var> be « (<var>url</var>, <var>moduleType</var>) ».</p></li>

<li><p><span data-x="fetch the descendants of and link a module script">Fetch the
descendants of and link</span> <var>result</var> given <var>settings object</var>,
Expand Down Expand Up @@ -91741,20 +91754,18 @@ document.querySelector("button").addEventListener("click", bound);
href="#validate-requested-module-specifiers">previously successful</a> with these same two
arguments.</p></li>

<li><p>If <var>requested</var>.[[Assertions]] has a <span>Record</span> <var>entry</var> such
that <var>entry</var>.[[Key]] is "<code data-x="">type</code>", then let <var>module type</var>
be <var>entry</var>.[[Value]]. Otherwise let <var>module type</var> be "<code
data-x="">javascript</code>".</p></li>
<li><p>Let <var>moduleType</var> be the result of running the <span>module type from module
request</span> steps given <var>requested</var>.</p></li>

<li>
<p>If <var>visited set</var> does not <span data-x="list contains">contain</span>
(<var>url</var>, <var>module type</var>), then:</p>
(<var>url</var>, <var>moduleType</var>), then:</p>

<ol>
<li><p><span data-x="list append">Append</span> <var>requested</var> to
<var>moduleRequests</var>.</p></li>

<li><p><span data-x="set append">Append</span> (<var>url</var>, <var>module type</var>) to
<li><p><span data-x="set append">Append</span> (<var>url</var>, <var>moduleType</var>) to
<var>visited set</var>.</p></li>
</ol>
</li>
Expand Down Expand Up @@ -91807,13 +91818,11 @@ document.querySelector("button").addEventListener("click", bound);
href="#validate-requested-module-specifiers">previously successful</a> with these same two
arguments.</p></li>

<li><p>If <var>moduleRequest</var>.[[Assertions]] has a <span>Record</span> <var>entry</var>
such that <var>entry</var>.[[Key]] is "<code data-x="">type</code>", then let <var>module
type</var> be <var>entry</var>.[[Value]]. Otherwise let <var>module type</var> be "<code
data-x="">javascript</code>".</p></li>
<li><p>Let <var>moduleType</var> be the result of running the <span>module type from module
request</span> steps given <var>moduleRequest</var>.</p></li>

<li><p>Assert: <var>visited set</var> <span data-x="list contains">contains</span>
(<var>url</var>, <var>module type</var>).</p></li>
(<var>url</var>, <var>moduleType</var>).</p></li>

<li><p><span>Fetch a single module script</span> given <var>url</var>, <var>fetch client settings
object</var>, <var>destination</var>, <var>options</var>, <var>module map settings object</var>,
Expand Down Expand Up @@ -91844,41 +91853,33 @@ document.querySelector("button").addEventListener("click", bound);
complete with either null (on failure) or a <span>module script</span> (on success).</p>

<ol>
<li><p>Let <var>module type</var> be "<code data-x="">javascript</code>".</p></li>
<li><p>Let <var>moduleType</var> be "<code data-x="">javascript</code>".</p></li>

<li>
<p>If <var>moduleRequest</var> was given and <var>moduleRequest</var>.[[Assertions]] has a
<span>Record</span> <var>entry</var> such that <var>entry</var>.[[Key]] is "<code
data-x="">type</code>", then:</p>

<ol>
<li><p>Assert: No more than one such <span>Record</span> exists.</p></li>
<li><p>If <var>moduleRequest</var> was given, then set <var>moduleType</var> to the result of
running the <span>module type from module request</span> steps given
<var>moduleRequest</var>.</p></li>

<li><p>Set <var>module type</var> to <var>entry</var>.[[Value]].</p></li>
</ol>
</li>

<li><p>Assert: the result of running the <span>module type allowed</span> steps given <var>module
type</var> and <var>module map settings object</var> is true. Otherwise we would not have reached
this point because a failure would have been raised when inspecting
<li><p>Assert: the result of running the <span>module type allowed</span> steps given
<var>moduleType</var> and <var>module map settings object</var> is true. Otherwise we would not
have reached this point because a failure would have been raised when inspecting
<var>moduleRequest</var>.[[Assertions]] in <a
href="#validate-requested-module-specifiers">create a JavaScript module script</a> or
<span>fetch an import() module script graph</span>.</p></li>

<li><p>Let <var>moduleMap</var> be <var>module map settings object</var>'s <span
data-x="concept-settings-object-module-map">module map</span>.</p></li>

<li><p>If <var>moduleMap</var>[(<var>url</var>, <var>module type</var>)] is
<li><p>If <var>moduleMap</var>[(<var>url</var>, <var>moduleType</var>)] is
"<code data-x="">fetching</code>", wait <span>in parallel</span> until that entry's value
changes, then <span>queue a task</span> on the <span>networking task source</span> to proceed
with running the following steps.</p></li>

<li><p>If <var>moduleMap</var>[(<var>url</var>, <var>module type</var>)] <span
<li><p>If <var>moduleMap</var>[(<var>url</var>, <var>moduleType</var>)] <span
data-x="map exists">exists</span>, asynchronously complete this algorithm with
<var>moduleMap</var>[<var>url</var> / <var>module type</var>], and return.</p></li>
<var>moduleMap</var>[<var>url</var> / <var>moduleType</var>], and return.</p></li>

<li><p><span data-x="map set">Set</span> <var>moduleMap</var>[(<var>url</var>, <var>module
type</var>)] to "<code data-x="">fetching</code>".</p></li>
<li><p><span data-x="map set">Set</span> <var>moduleMap</var>[(<var>url</var>,
<var>moduleType</var>)] to "<code data-x="">fetching</code>".</p></li>

<li><p>Let <var>request</var> be a new <span data-x="concept-request">request</span> whose
<span data-x="concept-request-url">URL</span> is <var>url</var>, <span
Expand Down Expand Up @@ -91928,8 +91929,9 @@ document.querySelector("button").addEventListener("click", bound);
<span>ok status</span>.</p></li>
</ul>

<p>then <span data-x="map set">set</span> <var>moduleMap</var>[(<var>url</var>, <var>module
type</var>)] to null, asynchronously complete this algorithm with null, and return.</p>
<p>then <span data-x="map set">set</span> <var>moduleMap</var>[(<var>url</var>,
<var>moduleType</var>)] to null, asynchronously complete this algorithm with null, and
return.</p>
</li>

<li><p>Let <var>source text</var> be the result of <span data-x="UTF-8 decode">UTF-8
Expand All @@ -91941,26 +91943,26 @@ document.querySelector("button").addEventListener("click", bound);

<li><p>Let <var>module script</var> be null.</p></li>

<li><p>If <var>MIME type</var> is a <span>JavaScript MIME type</span> and <var>module type</var>
<li><p>If <var>MIME type</var> is a <span>JavaScript MIME type</span> and <var>moduleType</var>
is "<code data-x="">javascript</code>", then set <var>module script</var> to the result of
<span>creating a JavaScript module script</span> given <var>source text</var>, <var>module map
settings object</var>, <var>response</var>'s <span data-x="concept-response-url">url</span>, and
<var>options</var>.</p></li>

<li><p>If the <span>MIME type essence</span> of <var>MIME type</var> is "<code>text/css</code>"
and <var>module type</var> is "<code data-x="">css</code>", then set <var>module script</var> to
and <var>moduleType</var> is "<code data-x="">css</code>", then set <var>module script</var> to
the result of <span>creating a CSS module script</span> given <var>source text</var> and
<var>module map settings object</var>.</p></li>

<li><p>If <var>MIME type essence</var> is a <span>JSON MIME type</span> and <var>module
type</var> is "<code data-x="">json</code>", then set <var>module script</var> to the result of
<li><p>If <var>MIME type essence</var> is a <span>JSON MIME type</span> and <var>moduleType</var>
is "<code data-x="">json</code>", then set <var>module script</var> to the result of
<span>creating a JSON module script</span> given <var>source text</var> and <var>module map
settings object</var>.</p></li>

<li>
<p><span data-x="map set">Set</span> <var>moduleMap</var>[(<var>url</var>, <var>module
type</var>)] to <var>module script</var>, and asynchronously complete this algorithm with
<var>module script</var>.</p>
<p><span data-x="map set">Set</span> <var>moduleMap</var>[(<var>url</var>,
<var>moduleType</var>)] to <var>module script</var>, and asynchronously complete this algorithm
with <var>module script</var>.</p>

<p class="note">It is intentional that the <span>module map</span> is keyed by the <span
data-x="concept-request-url">request URL</span>, whereas the <span
Expand Down Expand Up @@ -92004,13 +92006,11 @@ document.querySelector("button").addEventListener("click", bound);
href="#validate-requested-module-specifiers">marked as itself having a parse
error</a>.)</p></li>

<li><p>If <var>moduleRequest</var>.[[Assertions]] has a <span>Record</span> <var>entry</var>
such that <var>entry</var>.[[Key]] is "<code data-x="">type</code>", then let <var>module
type</var> be <var>entry</var>.[[Value]]. Otherwise let <var>module type</var> be "<code
data-x="">javascript</code>".</p></li>
<li><p>Let <var>moduleType</var> be the result of running the <span>module type from module
request</span> steps given <var>moduleRequest</var>.</p></li>

<li><p>Let <var>childModule</var> be <var>moduleMap</var>[(<var>childURL</var>, <var>module
type</var>)].</p></li>
<li><p>Let <var>childModule</var> be <var>moduleMap</var>[(<var>childURL</var>,
<var>moduleType</var>)].</p></li>

<li><p>Assert: <var>childModule</var> is a <span>module script</span> (i.e., it is not "<code
data-x="">fetching</code>" or null); by now all <span data-x="module script">module
Expand Down Expand Up @@ -92153,14 +92153,12 @@ document.querySelector("button").addEventListener("click", bound);
a module specifier</span> given <var>script</var>'s <span data-x="concept-script-base-url">base
URL</span> and <var>requested</var>.[[Specifier]].</p></li>

<li><p>If <var>requested</var>.[[Assertions]] has a <span>Record</span> <var>entry</var> such
that <var>entry</var>.[[Key]] is "<code data-x="">type</code>", then let <var>module type</var>
be <var>entry</var>.[[Value]]. Otherwise let <var>module type</var> be "<code
data-x="">javascript</code>".</p></li>
<li><p>Let <var>moduleType</var> be the result of running the <span>module type from module
request</span> steps given <var>requested</var>.</p></li>

<li>
<p>If <var>url</var> is failure, or if the result of running the <span>module type
allowed</span> steps given <var>module type</var> and <var>settings</var> is false, then:</p>
allowed</span> steps given <var>moduleType</var> and <var>settings</var> is false, then:</p>
<ol>
<li><p>Let <var>error</var> be a new <code>TypeError</code> exception.</p></li>

Expand Down Expand Up @@ -92252,14 +92250,43 @@ document.querySelector("button").addEventListener("click", bound);
<li><p>Return <var>script</var>.</p></li>
dandclark marked this conversation as resolved.
Show resolved Hide resolved
</ol>

<p>The <dfn>module type allowed</dfn> steps, given a <span>string</span> <var>module type</var>
<p>The <dfn>module type from module request</dfn> steps, given a <span>ModuleRequest
Record</span> <var>moduleRequest</var>, are as follows:</p>

dandclark marked this conversation as resolved.
Show resolved Hide resolved
<ol>
<li><p>Let <var>moduleType</var> be "<code data-x="">javascript</code>".</p></li>

<li>
<p>If <var>moduleRequest</var>.[[Assertions]] has a <span>Record</span> <var>entry</var> such
that <var>entry</var>.[[Key]] is "<code data-x="">type</code>", then:</p>

<ol>
<li>
<p>If <var>entry</var>.[[Value]] is "<code data-x="">javascript</code>", then set
<var>moduleType</var> to null.</p>

<p class="note">This specification uses the "<code data-x="">javascript</code>" module type
internally for <span data-x="JavaScript module script">JavaScript module scripts</span>, so
this step is needed to prevent modules from being imported using a "<code
data-x="">javascript</code>" type assertion (a null <var>moduleType</var> will cause the
<span>module type allowed</span> check to fail).</p>
</li>

<li><p>Otherwise, set <var>moduleType</var> to <var>entry</var>.[[Value]].</p></li>
</ol>
</li>

<li><p>Return <var>moduleType</var>.</p></li>
</ol>

<p>The <dfn>module type allowed</dfn> steps, given a <span>string</span> <var>moduleType</var>
and an <span>environment settings object</span> <var>settings</var>, are as follows:</p>

<ol>
<li><p>If <var>module type</var> is not "<code data-x="">javascript</code>", "<code
<li><p>If <var>moduleType</var> is not "<code data-x="">javascript</code>", "<code
data-x="">css</code>", or "<code data-x="">json</code>", then return false.</p></li>

<li><p>If <var>module type</var> is "<code data-x="">css</code>" and the
<li><p>If <var>moduleType</var> is "<code data-x="">css</code>" and the
<code>CSSStyleSheet</code> interface is not <span data-x="idl-exposed">exposed</span> in
<var>setting</var>'s <span data-x="environment settings object's Realm">Realm</span>, then
return false.</p></li>
dandclark marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -93401,14 +93428,12 @@ import "https://example.com/foo/../module2.mjs";</code></pre>
same two arguments (either <a href="#validate-requested-module-specifiers">while creating the
corresponding module script</a>, or in <span>fetch an import() module script graph</span>).</p></li>

<li><p>If <var>moduleRequest</var>.[[Assertions]] has a <span>Record</span> <var>entry</var> such
that <var>entry</var>.[[Key]] is "<code data-x="">type</code>", then let <var>module type</var>
be <var>entry</var>.[[Value]]. Otherwise let <var>module type</var> be "<code
data-x="">javascript</code>".</p></li>
<li><p>Let <var>moduleType</var> be the result of running the <span>module type from module
request</span> steps given <var>moduleRequest</var>.</p></li>

<li><p>Let <var>resolved module script</var> be <var>moduleMap</var>[(<var>url</var>, <var>module
type</var>)]. (This entry must <span data-x="map exists">exist</span> for us to have gotten to
this point.)</p></li>
<li><p>Let <var>resolved module script</var> be <var>moduleMap</var>[(<var>url</var>,
<var>moduleType</var>)]. (This entry must <span data-x="map exists">exist</span> for us to have
gotten to this point.)</p></li>

<li><p>Assert: <var>resolved module script</var> is a <span>module script</span> (i.e., is not
null or "<code data-x="">fetching</code>").</p></li>
Expand Down