Skip to content

Commit

Permalink
Fix error cases of <script type=module>
Browse files Browse the repository at this point in the history
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.

Fixes #2567.
  • Loading branch information
domenic committed May 1, 2017
1 parent e704140 commit b7d7ee5
Showing 1 changed file with 84 additions and 61 deletions.
145 changes: 84 additions & 61 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -86658,24 +86658,24 @@ interface <dfn>NavigatorOnLine</dfn> {

</dd>

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

<dd>

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

</dd>

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

<dd>

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

</dd>

Expand Down Expand Up @@ -87142,49 +87142,41 @@ interface <dfn>NavigatorOnLine</dfn> {
<li><p>If <var>result</var> is null, asynchronously complete this algorithm with null and abort
these steps.</p></li>

<li><p>If <var>result</var>'s <span data-x="concept-module-script-state">state</span> is "<code
data-x="">instantiated</code>" or "<code data-x="">errored</code>", asynchronously complete this
algorithm with <var>result</var>, and abort these steps.</p></li>

<li><p>Assert: <var>result</var>'s <span data-x="concept-module-script-state">state</span> is
"<code data-x="">uninstantiated</code>".</p></li>

<li>
<p>Otherwise, <var>result</var> is a <span>module script</span>. <span data-x="fetch the
descendants of a module script">Fetch the descendants</span> of <var>result</var> given
<var>destination</var> and an ancestor list obtained by appending <var>url</var> to <var>ancestor
list</var>. Wait for <span data-x="fetch the descendants of a module script">fetching the
descendants of a module script</span> to asynchronously complete with <var>descendants
result</var> before proceeding to the next step.</p>
<p><span data-x="fetch the descendants of a module script">Fetch the
descendants</span> of <var>result</var> given <var>destination</var> and an ancestor list
obtained by appending <var>url</var> to <var>ancestor list</var>. Wait for <span data-x="fetch
the descendants of a module script">fetching the descendants of a module script</span> to
asynchronously complete with <var>descendants result</var> before proceeding to the next step.</p>

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

<li><p>Let <var>instantiationStatus</var> be null.</p></li>

<li><p>If <var>result</var>'s <span data-x="concept-module-script-instantiation-state">instantiation
state</span> is "<code data-x="">errored</code>", then set <var>instantiationStatus</var> to
Completion { [[Type]]: throw, [[Value]]: <var>result</var>'s <span
data-x="concept-module-script-instantiation-error">instantiation error</span>, [[Target]]:
empty }.</p></li>
<li><p>Let <var>record</var> be <var>result</var>'s <span
data-x="concept-module-script-module-record">module record</span>.</p></li>

<li>
<p>Otherwise:</p>

<ol>
<li><p>Let <var>record</var> be <var>result</var>'s <span
data-x="concept-module-script-module-record">module record</span>.</p></li>
<p>Let <var>instantiationStatus</var> be <var>record</var>.<span
data-x="js-ModuleDeclarationInstantiation">ModuleDeclarationInstantiation</span>().</p>

<li>
<p>Set <var>instantiationStatus</var> to <var>record</var>.<span
data-x="js-ModuleDeclarationInstantiation">ModuleDeclarationInstantiation</span>().</p>

<p class="note">This step will recursively call <span
data-x="js-ModuleDeclarationInstantiation">ModuleDeclarationInstantiation</span> all of the
module's uninstantiated dependencies.</p>
</li>
</ol>
<p class="note">This step will recursively call <span
data-x="js-ModuleDeclarationInstantiation">ModuleDeclarationInstantiation</span> all of the
module's uninstantiated dependencies.</p>
</li>

<li>
<p>For each <var>script</var> in <var>result</var>'s <span>uninstantiated inclusive descendant module
scripts</span>, perform the following steps:</p>
<p>For each <var>script</var> in <var>result</var>'s <span>uninstantiated inclusive descendant
module scripts</span>, perform the following steps:</p>

<ol>
<li>
Expand All @@ -87197,18 +87189,16 @@ interface <dfn>NavigatorOnLine</dfn> {
<li><p>Set <var>script</var>'s <span data-x="concept-module-script-module-record">module
record</span> to null.</p></li>

<li><p>Set <var>script</var>'s <span
data-x="concept-module-script-instantiation-state">instantiation state</span> to "<code
data-x="">errored</code>".</p></li>
<li><p>Set <var>script</var>'s <span data-x="concept-module-script-state">state</span> to
"<code data-x="">errored</code>".</p></li>

<li><p>Set <var>script</var>'s <span
data-x="concept-module-script-instantiation-error">instantiation error</span> to
<li><p>Set <var>script</var>'s <span data-x="concept-module-script-error">error</span> to
<var>instantiationStatus</var>.[[Value]].</p></li>
</ol>
</li>

<li><p>Otherwise, set <var>script</var>'s <span
data-x="concept-module-script-instantiation-state">instantiation state</span> to "<code
data-x="concept-module-script-state">state</span> to "<code
data-x="">instantiated</code>".</p></li>
</ol>
</li>
Expand All @@ -87226,6 +87216,9 @@ interface <dfn>NavigatorOnLine</dfn> {
data-x="module script">module scripts</span> determined as follows:</p>

<ol>
<li><p>If <var>script</var>'s <span data-x="concept-module-script-module-record">module
record</span> is null, return the empty set.</p></li>

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

Expand Down Expand Up @@ -87284,7 +87277,7 @@ interface <dfn>NavigatorOnLine</dfn> {
</li>

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

Expand Down Expand Up @@ -87417,10 +87410,14 @@ interface <dfn>NavigatorOnLine</dfn> {
<ol>
<li><p>Let <var>error</var> be a new <code>TypeError</code> exception.</p></li>

<li><p><span>Report the exception</span> <var>error</var> for <var>module
script</var>.</p></li>
<li><p>Set <var>module script</var>'s <span data-x="concept-module-script-state">state</span>
to "<code data-x="">errored</code>".</p></li>

<li><p>Set <var>module script</var>'s <span data-x="concept-module-script-error">error</span>
to <var>error</var>.</p></li>

<li><p>Abort this algorithm, and asynchronously complete it with null.</p></li>
<li><p>Abort this algorithm, and asynchronously complete it with <var>module
script</var>.</p></li>
</ol>
</li>

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

<p>Wait for all of the <span>internal module script graph fetching procedure</span> invocations
to asynchronously complete. If any of them asynchronously complete with null, then
asynchronously complete this algorithm with null. Otherwise, asynchronously complete this
algorithm with <var>module script</var>.</p>
<p>These invocations of the <span>internal module script graph fetching procedure</span> should
be performed in parallel to each other.</p>

<p>If any invocation of the <span>internal module script graph fetching procedure</span>
asynchronously completes with null, optionally abort all other invocations, and then
asynchronously complete this algorithm with null.</p>

<p>If any invocation of the <span>internal module script graph fetching procedure</span>
asynchronously completes with a <span>module script</span> whose <span
data-x="concept-module-script-state">state</span> is "<code data-x="">errored</code>",
optionally abort all other invocations, and then asynchronously complete this algorithm with
<var>module script</var>. (The errored descendant will cause errors later in the module-fetching
process, but for now we treat it as a premature "success".)</p>

<p>Otherwise, wait for all of the <span>internal module script graph fetching procedure</span>
invocations to asynchronously complete, with <span data-x="module script">module scripts</span>
whose <span data-x="concept-module-script-state">states</span> are not "<code
data-x="">errored</code>". Then, asynchronously complete this algorithm with <var>module
script</var>.</p>
</li>
</ol>

Expand Down Expand Up @@ -87507,9 +87519,22 @@ interface <dfn>NavigatorOnLine</dfn> {
<var>result</var>.[[HostDefined]] will be <var>script</var>.</p>
</li>

<li><p>If <var>result</var> is a <span>List</span> of errors, <span>report the exception</span>
given by the first element of <var>result</var> for <var>script</var>, return null, and abort
these steps.</p></li>
<li>
<p>If <var>result</var> is a <span>List</span> of errors, then:</p>

<ol>
<li><p>Set <var>script</var>'s <span data-x="concept-module-script-state">state</span> to
"<code data-x="">errored</code>".</p></li>

<li><p>Set <var>script</var>'s <span data-x="concept-module-script-error">error</span> to
<var>errors</var>[0].</p></li>

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

<li><p>Set <var>script</var>'s <span data-x="concept-module-script-state">state</span> to "<code
data-x="">uninstantiated</code>".</p></li>

<li><p>Set <var>script</var>'s <span data-x="concept-module-script-module-record">module
record</span> to <var>result</var>.</p></li>
Expand Down Expand Up @@ -87607,14 +87632,12 @@ interface <dfn>NavigatorOnLine</dfn> {
<li><p><span>Check if we can run script</span> with <var>settings</var>. If this returns "do
not run" then abort these steps.</p></li>

<li><p>If <var>s</var>'s <span data-x="concept-module-script-instantiation-state">instantiation
state</span> is "<code data-x="">errored</code>", then <span>report the
exception</span> given by <var>s</var>'s <span
data-x="concept-module-script-instantiation-error">instantiation error</span> for <var>s</var>
and abort these steps.</p></li>
<li><p>If <var>s</var>'s <span data-x="concept-module-script-state">state</span> is "<code
data-x="">errored</code>", then <span>report the exception</span> given by <var>s</var>'s <span
data-x="concept-module-script-error">error</span> for <var>s</var> and abort these
steps.</p></li>

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

Expand Down Expand Up @@ -88490,9 +88513,9 @@ import "https://example.com/foo/../module2.js";</pre>
steps.</p></li>

<li><p>If <var>resolved module script</var>'s <span
data-x="concept-module-script-instantiation-state">instantiation state</span> is "<code
data-x="">errored</code>", then throw <var>resolved module script</var>'s <span
data-x="concept-module-script-instantiation-error">instantiation error</span>.</p></li>
data-x="concept-module-script-state">state</span> is "<code data-x="">errored</code>", then throw
<var>resolved module script</var>'s <span
data-x="concept-module-script-error">error</span>.</p></li>

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

0 comments on commit b7d7ee5

Please sign in to comment.