Skip to content

Commit 1157631

Browse files
authored
Fix error cases of <script type=module>
There are several different ways things can go wrong with <script type=module>. In order from earliest to latest, for a single module script, they are: - Fetching failures - Parsing failures - Invalid module specifiers - Instantiation failures - Evaluation failures This tweaks the way that these errors interact, to ensure that fetching failures are treated one way, causing the <script>'s "error" event to fire, and the other failures are uniformly treated as errors running the script, causing the global's "error" event to fire. This also makes it clear that when fetching descendant module scripts, you can bail out early if one of them fails to fetch or has previously been discovered to be errored. Evaluation failures are particularly tricky for dependencies, as usually ModuleEvaluation() is a no-op if it has happened previously (either successfully or not). This is discussed in more depth in tc39/ecma262#862. To work around this, we need to store the evaluation error, if one occurs, similar to what we already do for instantiation errors. Fixes #2567. However, there are still problems with this setup, which may need further infrastructure changes; see: - #2595 (comment) - #2629 - #2630 But for now the improvement given by this commit is enough to merge it.
1 parent 8192a2e commit 1157631

File tree

1 file changed

+121
-80
lines changed

1 file changed

+121
-80
lines changed

source

+121-80
Original file line numberDiff line numberDiff line change
@@ -86542,24 +86542,24 @@ interface <dfn>NavigatorOnLine</dfn> {
8654286542

8654386543
</dd>
8654486544

86545-
<dt>An <dfn data-x="concept-module-script-instantiation-state">instantiation state</dfn></dt>
86545+
<dt>A <dfn data-x="concept-module-script-state">state</dfn></dt>
8654686546

8654786547
<dd>
8654886548

8654986549
<p>One of "<code data-x="">uninstantiated</code>", "<code data-x="">errored</code>", or "<code
8655086550
data-x="">instantiated</code>", used to prevent reinvocation of <span
8655186551
data-x="js-ModuleDeclarationInstantiation">ModuleDeclarationInstantiation</span> on modules that
86552-
failed to instantiate previously.</p>
86552+
failed to instantiate previously, and to ensure errors during parsing, instantiation, or
86553+
evaluation are remembered and propagated correctly.</p>
8655386554

8655486555
</dd>
8655586556

86556-
<dt>An <dfn data-x="concept-module-script-instantiation-error">instantiation error</dfn></dt>
86557+
<dt>An <dfn data-x="concept-module-script-error">error</dfn></dt>
8655786558

8655886559
<dd>
8655986560

8656086561
<p>A JavaScript value, which has meaning only if the <span
86561-
data-x="concept-module-script-instantiation-state">instantiation state</span> is "<code
86562-
data-x="">errored</code>".</p>
86562+
data-x="concept-module-script-state">state</span> is "<code data-x="">errored</code>".</p>
8656386563

8656486564
</dd>
8656586565

@@ -86592,6 +86592,33 @@ interface <dfn>NavigatorOnLine</dfn> {
8659286592

8659386593
</dl>
8659486594

86595+
<p>To <dfn>error a module script</dfn> <var>script</var> with a given value <var>error</var>,
86596+
perform the following steps:</p>
86597+
86598+
<ol>
86599+
<li><p>Assert: <var>script</var>'s <span data-x="concept-module-script-state">state</span> is not
86600+
"<code data-x="">errored</code>".</p></li>
86601+
86602+
<li>
86603+
<p>If <var>script</var>'s <span data-x="concept-module-script-module-record">module
86604+
record</span> is set, then:</p>
86605+
86606+
<ol>
86607+
<li><p>Set <var>script</var> <span data-x="concept-module-script-module-record">module
86608+
record</span>'s [[HostDefined]] field to undefined.</p></li>
86609+
86610+
<li><p>Set <var>script</var>'s <span data-x="concept-module-script-module-record">module
86611+
record</span> to null.</p></li>
86612+
</ol>
86613+
</li>
86614+
86615+
<li><p>Set <var>script</var>'s <span data-x="concept-module-script-state">state</span> to
86616+
"<code data-x="">errored</code>".</p></li>
86617+
86618+
<li><p>Set <var>script</var>'s <span data-x="concept-module-script-error">error</span> to
86619+
<var>error</var>.</p></li>
86620+
</ol>
86621+
8659586622
<hr>
8659686623

8659786624
<p>An <dfn data-export="">environment</dfn> is an object that identifies the settings of a
@@ -87026,73 +87053,49 @@ interface <dfn>NavigatorOnLine</dfn> {
8702687053
<li><p>If <var>result</var> is null, asynchronously complete this algorithm with null and abort
8702787054
these steps.</p></li>
8702887055

87056+
<li><p>If <var>result</var>'s <span data-x="concept-module-script-state">state</span> is "<code
87057+
data-x="">instantiated</code>" or "<code data-x="">errored</code>", asynchronously complete this
87058+
algorithm with <var>result</var>, and abort these steps.</p></li>
87059+
87060+
<li><p>Assert: <var>result</var>'s <span data-x="concept-module-script-state">state</span> is
87061+
"<code data-x="">uninstantiated</code>".</p></li>
87062+
8702987063
<li>
87030-
<p>Otherwise, <var>result</var> is a <span>module script</span>. <span data-x="fetch the
87031-
descendants of a module script">Fetch the descendants</span> of <var>result</var> given
87032-
<var>destination</var> and an ancestor list obtained by appending <var>url</var> to <var>ancestor
87033-
list</var>. Wait for <span data-x="fetch the descendants of a module script">fetching the
87034-
descendants of a module script</span> to asynchronously complete with <var>descendants
87035-
result</var> before proceeding to the next step.</p>
87064+
<p><span data-x="fetch the descendants of a module script">Fetch the
87065+
descendants</span> of <var>result</var> given <var>destination</var> and an ancestor list
87066+
obtained by appending <var>url</var> to <var>ancestor list</var>. Wait for <span data-x="fetch
87067+
the descendants of a module script">fetching the descendants of a module script</span> to
87068+
asynchronously complete with <var>descendants result</var> before proceeding to the next step.</p>
8703687069

8703787070
<p class="note">If the asynchronous completion result is null, meaning that fetching one of the
8703887071
descendants failed, we still proceed through the next set of steps. A failure will shortly occur
8703987072
during instantiation, which we then react to appropriately. The error signal is eventually
8704087073
propagated to the caller of this algorithm in the last step.</p>
8704187074
</li>
8704287075

87043-
<li><p>Let <var>instantiationStatus</var> be null.</p></li>
87044-
87045-
<li><p>If <var>result</var>'s <span data-x="concept-module-script-instantiation-state">instantiation
87046-
state</span> is "<code data-x="">errored</code>", then set <var>instantiationStatus</var> to
87047-
Completion { [[Type]]: throw, [[Value]]: <var>result</var>'s <span
87048-
data-x="concept-module-script-instantiation-error">instantiation error</span>, [[Target]]:
87049-
empty }.</p></li>
87076+
<li><p>Let <var>record</var> be <var>result</var>'s <span
87077+
data-x="concept-module-script-module-record">module record</span>.</p></li>
8705087078

8705187079
<li>
87052-
<p>Otherwise:</p>
87053-
87054-
<ol>
87055-
<li><p>Let <var>record</var> be <var>result</var>'s <span
87056-
data-x="concept-module-script-module-record">module record</span>.</p></li>
87057-
87058-
<li>
87059-
<p>Set <var>instantiationStatus</var> to <var>record</var>.<span
87060-
data-x="js-ModuleDeclarationInstantiation">ModuleDeclarationInstantiation</span>().</p>
87080+
<p>Let <var>instantiationStatus</var> be <var>record</var>.<span
87081+
data-x="js-ModuleDeclarationInstantiation">ModuleDeclarationInstantiation</span>().</p>
8706187082

87062-
<p class="note">This step will recursively call <span
87063-
data-x="js-ModuleDeclarationInstantiation">ModuleDeclarationInstantiation</span> all of the
87064-
module's uninstantiated dependencies.</p>
87065-
</li>
87066-
</ol>
87083+
<p class="note">This step will recursively call <span
87084+
data-x="js-ModuleDeclarationInstantiation">ModuleDeclarationInstantiation</span> all of the
87085+
module's uninstantiated dependencies.</p>
8706787086
</li>
8706887087

8706987088
<li>
87070-
<p>For each <var>script</var> in <var>result</var>'s <span>uninstantiated inclusive descendant module
87071-
scripts</span>, perform the following steps:</p>
87089+
<p>For each <var>script</var> in <var>result</var>'s <span>uninstantiated inclusive descendant
87090+
module scripts</span>, perform the following steps:</p>
8707287091

8707387092
<ol>
87074-
<li>
87075-
<p>If <var>instantiationStatus</var> is an abrupt completion, then:</p>
87076-
87077-
<ol>
87078-
<li><p>Set <var>script</var> <span data-x="concept-module-script-module-record">module
87079-
record</span>'s [[HostDefined]] field to undefined.</p></li>
87080-
87081-
<li><p>Set <var>script</var>'s <span data-x="concept-module-script-module-record">module
87082-
record</span> to null.</p></li>
87083-
87084-
<li><p>Set <var>script</var>'s <span
87085-
data-x="concept-module-script-instantiation-state">instantiation state</span> to "<code
87086-
data-x="">errored</code>".</p></li>
87087-
87088-
<li><p>Set <var>script</var>'s <span
87089-
data-x="concept-module-script-instantiation-error">instantiation error</span> to
87090-
<var>instantiationStatus</var>.[[Value]].</p></li>
87091-
</ol>
87092-
</li>
87093+
<li><p>If <var>instantiationStatus</var> is an abrupt completion, then <span data-x="error a
87094+
module script">error</span> <var>script</var> with
87095+
<var>instantiationStatus</var>.[[Value]].</p></li>
8709387096

8709487097
<li><p>Otherwise, set <var>script</var>'s <span
87095-
data-x="concept-module-script-instantiation-state">instantiation state</span> to "<code
87098+
data-x="concept-module-script-state">state</span> to "<code
8709687099
data-x="">instantiated</code>".</p></li>
8709787100
</ol>
8709887101
</li>
@@ -87110,6 +87113,9 @@ interface <dfn>NavigatorOnLine</dfn> {
8711087113
data-x="module script">module scripts</span> determined as follows:</p>
8711187114

8711287115
<ol>
87116+
<li><p>If <var>script</var>'s <span data-x="concept-module-script-module-record">module
87117+
record</span> is null, return the empty set.</p></li>
87118+
8711387119
<li><p>Let <var>moduleMap</var> be <var>script</var>'s <span>settings object</span>'s
8711487120
<span data-x="concept-settings-object-module-map">module map</span>.</p></li>
8711587121

@@ -87168,7 +87174,7 @@ interface <dfn>NavigatorOnLine</dfn> {
8716887174
</li>
8716987175

8717087176
<li><p>Return a <span>set</span> containing all items of <var>inclusive descendants</var> whose
87171-
<span data-x="concept-module-script-instantiation-state">instantiation state</span> is "<code
87177+
<span data-x="concept-module-script-state">state</span> is "<code
8717287178
data-x="">uninstantiated</code>".</p></li>
8717387179
</ol>
8717487180

@@ -87301,10 +87307,11 @@ interface <dfn>NavigatorOnLine</dfn> {
8730187307
<ol>
8730287308
<li><p>Let <var>error</var> be a new <code>TypeError</code> exception.</p></li>
8730387309

87304-
<li><p><span>Report the exception</span> <var>error</var> for <var>module
87305-
script</var>.</p></li>
87310+
<li><p><span data-x="error a module script">Error</span> <var>module script</var> with
87311+
<var>error</var>.</p></li>
8730687312

87307-
<li><p>Abort this algorithm, and asynchronously complete it with null.</p></li>
87313+
<li><p>Abort this algorithm, and asynchronously complete it with <var>module
87314+
script</var>.</p></li>
8730887315
</ol>
8730987316
</li>
8731087317

@@ -87327,10 +87334,25 @@ interface <dfn>NavigatorOnLine</dfn> {
8732787334
<span data-x="fetching-scripts-perform-fetch">perform the fetch</span> steps, pass those along
8732887335
while performing the <span>internal module script graph fetching procedure</span>.</p>
8732987336

87330-
<p>Wait for all of the <span>internal module script graph fetching procedure</span> invocations
87331-
to asynchronously complete. If any of them asynchronously complete with null, then
87332-
asynchronously complete this algorithm with null. Otherwise, asynchronously complete this
87333-
algorithm with <var>module script</var>.</p>
87337+
<p>These invocations of the <span>internal module script graph fetching procedure</span> should
87338+
be performed in parallel to each other.</p>
87339+
87340+
<p>If any invocation of the <span>internal module script graph fetching procedure</span>
87341+
asynchronously completes with null, optionally abort all other invocations, and then
87342+
asynchronously complete this algorithm with null.</p>
87343+
87344+
<p>If any invocation of the <span>internal module script graph fetching procedure</span>
87345+
asynchronously completes with a <span>module script</span> whose <span
87346+
data-x="concept-module-script-state">state</span> is "<code data-x="">errored</code>",
87347+
optionally abort all other invocations, and then asynchronously complete this algorithm with
87348+
<var>module script</var>. (The errored descendant will cause errors later in the module-fetching
87349+
process, but for now we treat it as a premature "success".)</p>
87350+
87351+
<p>Otherwise, wait for all of the <span>internal module script graph fetching procedure</span>
87352+
invocations to asynchronously complete, with <span data-x="module script">module scripts</span>
87353+
whose <span data-x="concept-module-script-state">states</span> are not "<code
87354+
data-x="">errored</code>". Then, asynchronously complete this algorithm with <var>module
87355+
script</var>.</p>
8733487356
</li>
8733587357
</ol>
8733687358

@@ -87391,9 +87413,19 @@ interface <dfn>NavigatorOnLine</dfn> {
8739187413
<var>result</var>.[[HostDefined]] will be <var>script</var>.</p>
8739287414
</li>
8739387415

87394-
<li><p>If <var>result</var> is a <span>List</span> of errors, <span>report the exception</span>
87395-
given by the first element of <var>result</var> for <var>script</var>, return null, and abort
87396-
these steps.</p></li>
87416+
<li>
87417+
<p>If <var>result</var> is a <span>List</span> of errors, then:</p>
87418+
87419+
<ol>
87420+
<li><p><span data-x="error a module script">Error</span> <var>script</var> with
87421+
<var>errors</var>[0].</p></li>
87422+
87423+
<li><p>Return <var>script</var>.</p></li>
87424+
</ol>
87425+
</li>
87426+
87427+
<li><p>Set <var>script</var>'s <span data-x="concept-module-script-state">state</span> to "<code
87428+
data-x="">uninstantiated</code>".</p></li>
8739787429

8739887430
<li><p>Set <var>script</var>'s <span data-x="concept-module-script-module-record">module
8739987431
record</span> to <var>result</var>.</p></li>
@@ -87491,14 +87523,12 @@ interface <dfn>NavigatorOnLine</dfn> {
8749187523
<li><p><span>Check if we can run script</span> with <var>settings</var>. If this returns "do
8749287524
not run" then abort these steps.</p></li>
8749387525

87494-
<li><p>If <var>s</var>'s <span data-x="concept-module-script-instantiation-state">instantiation
87495-
state</span> is "<code data-x="">errored</code>", then <span>report the
87496-
exception</span> given by <var>s</var>'s <span
87497-
data-x="concept-module-script-instantiation-error">instantiation error</span> for <var>s</var>
87498-
and abort these steps.</p></li>
87526+
<li><p>If <var>s</var>'s <span data-x="concept-module-script-state">state</span> is "<code
87527+
data-x="">errored</code>", then <span>report the exception</span> given by <var>s</var>'s <span
87528+
data-x="concept-module-script-error">error</span> for <var>s</var> and abort these
87529+
steps.</p></li>
8749987530

87500-
<li><p>Assert: <var>s</var>'s <span
87501-
data-x="concept-module-script-instantiation-state">instantiation state</span> is "<code
87531+
<li><p>Assert: <var>s</var>'s <span data-x="concept-module-script-state">state</span> is "<code
8750287532
data-x="">instantiated</code>" (and thus its <span
8750387533
data-x="concept-module-script-module-record">module record</span> is not null).</p></li>
8750487534

@@ -87512,13 +87542,24 @@ interface <dfn>NavigatorOnLine</dfn> {
8751287542
data-x="js-ModuleEvaluation">ModuleEvaluation</span>().</p>
8751387543

8751487544
<p class="note">This step will recursively evaluate all of the module's dependencies.</p>
87545+
87546+
<p>If <span data-x="js-ModuleEvaluation">ModuleEvaluation</span> fails to complete as a result
87547+
of the user agent <span data-x="abort a running script">aborting the running script</span>, then
87548+
set <var>evaluationStatus</var> to Completion { [[Type]]: throw, [[Value]]: a new
87549+
<span>"<code>QuotaExceededError</code>"</span> <code>DOMException</code>, [[Target]]: empty }.
8751587550
</li>
8751687551

87517-
<li><p>If <var>evaluationStatus</var> is an abrupt completion, then <span>report the
87518-
exception</span> given by <var>evaluationStatus</var>.[[Value]] for <var>s</var>. (Do not perform
87519-
this step if <span data-x="js-ModuleEvaluation">ModuleEvaluation</span> fails to complete as a
87520-
result of the user agent <span data-x="abort a running script">aborting the running
87521-
script</span>.)</p></li>
87552+
<li>
87553+
<p>If <var>evaluationStatus</var> is an abrupt completion, then:</p>
87554+
87555+
<ol>
87556+
<li><p><span data-x="error a module script">Error</span> <var>script</var> with
87557+
<var>evaluationStatus</var>.[[Value]].</p></li>
87558+
87559+
<li><p><span>Report the exception</span> given by <var>evaluationStatus</var>.[[Value]] for
87560+
<var>s</var>.</p>
87561+
</ol>
87562+
</li>
8752287563

8752387564
<li><p><span>Clean up after running script</span> with <var>settings</var>.</p></li>
8752487565
</ol>
@@ -88374,9 +88415,9 @@ import "https://example.com/foo/../module2.js";</pre>
8837488415
steps.</p></li>
8837588416

8837688417
<li><p>If <var>resolved module script</var>'s <span
88377-
data-x="concept-module-script-instantiation-state">instantiation state</span> is "<code
88378-
data-x="">errored</code>", then throw <var>resolved module script</var>'s <span
88379-
data-x="concept-module-script-instantiation-error">instantiation error</span>.</p></li>
88418+
data-x="concept-module-script-state">state</span> is "<code data-x="">errored</code>", then throw
88419+
<var>resolved module script</var>'s <span
88420+
data-x="concept-module-script-error">error</span>.</p></li>
8838088421

8838188422
<li><p>Assert: <var>resolved module script</var>'s <span
8838288423
data-x="concept-module-script-module-record">module record</span> is not null.</p></li>

0 commit comments

Comments
 (0)