Skip to content

Commit

Permalink
Handle error cases during module script tree fetching/running better
Browse files Browse the repository at this point in the history
As discussed in #1545 and in
https://esdiscuss.org/topic/moduledeclarationinstantiation-behaviour-after-failure,
the spec would potentially call ModuleDeclarationInstantiation on a
module that previously failed to instantiate, with cascading bad
consequences for the rest of the spec's algorithms. The JavaScript spec
expects us to track these failures and avoid calling
ModuleDeclarationInstantiation a second time. This commit adds such
state tracking, partially by moving the ModuleDeclarationInstantiation
calls to fetch time (with any errors stored for later rethrowing during
evaluation time).

Fixes #1545.
  • Loading branch information
domenic committed Aug 1, 2016
1 parent d0f0d6c commit 9ed4c2c
Showing 1 changed file with 113 additions and 23 deletions.
136 changes: 113 additions & 23 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -85871,6 +85871,27 @@ interface <dfn>NavigatorOnLine</dfn> {

</dd>

<dt>An <dfn data-x="concept-module-script-instantiation-state">instantiation 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>

</dd>

<dt>An <dfn data-x="concept-module-script-instantiation-error">instantiation 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>

</dd>

<dt>A <dfn data-x="concept-module-script-credentials-mode">credentials mode</dfn></dt>

<dd>
Expand Down Expand Up @@ -86300,11 +86321,74 @@ interface <dfn>NavigatorOnLine</dfn> {
<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>.</p></li>
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></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>
<p>Let <var>instantiationStatus</var> be <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 dependencies.</p>
</li>

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

<ol>
<li><p>If <var>instantiationStatus</var> is an abrupt completion, set <var>script</var>'s
<span data-x="concept-module-script-instantiation-state">instantiation state</span> to "<code
data-x="">errored</code>", its <span
data-x="concept-module-script-instantiation-error">instantiation error</span> to
<var>instantiationStatus</var>.[[Value]], and its <span
data-x="concept-module-script-module-record">module record</span> to null.</p></li>

<li><p>Otherwise, set <var>script</var>'s <span
data-x="concept-module-script-instantiation-state">instantiation state</span> to "<code
data-x="">instantiated</code>".</p></li>
</ol>
</li>

<li><p>When <span data-x="fetch the descendants of a module script">fetching the descendants of
a module script</span> asynchronously completes with <var>descendants result</var>,
asynchronously complete this algorithm with <var>descendants result</var>.</p></li>
<li>
<p>Asynchronously complete this algorithm with <var>descendants result</var>.</p>

<p class="note">It is intentional that we complete with <var>descendants result</var> here, and
not <var>result</var>, as this allows us to propagate error signals to the caller.</p>
</li>
</ol>

<p>In the above algorithm, a <span>module script</span> <var>script</var>'s <dfn>uninstantiated
inclusive descendant module scripts</dfn> is a list of <span data-x="module script">module
scripts</span> determined as follows:</p>

<ol>
<li><p>Let <var>module map</var> be <var>script</var>'s <span>settings object</span>'s
<span>module map</span>.</p></li>

<li><p>Let <var>descendant specifiers</var> be the value of <var>script</var>'s <span
data-x="concept-module-script-module-record">module record</span>'s [[RequestedModules]] internal
slot.</p></li>

<li><p>Let <var>descendant URLs</var> be the list obtained by applying <span>resolve a module
specifier</span> to each element of <var>descendant specifiers</var>, omitting any
failures.</p></li>

<li><p>Let <var>descendant modules</var> be the list obtained by looking up each value in
<var>module map</var> whose key is given by an element of <var>descendant URLs</var>.</p></li>

<li><p>Let <var>inclusive descendants</var> be the list obtained by appending <var>script</var>
to <var>descendant modules</var>.</p></li>

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

<p>To <dfn>fetch a single module script</dfn>, given a <var>url</var>, a <var>fetch client
Expand Down Expand Up @@ -86454,14 +86538,10 @@ 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 tree fetching procedure</span>.</p>

<p>If any of the <span>internal module script tree fetching procedure</span> invocations
asynchronously complete with null, the user agent may <span
data-x="concept-fetch-terminate">terminate</span> any or all of the other fetches, and must then
asynchronously complete this algorithm with null.</p>

<p>Once all of the <span>internal module script tree fetching procedure</span> invocations
asynchronously complete with a <span>module script</span>, asynchronously complete this
algorithm with <var>module script</var>.</p>
<p>Wait for all of the <span>internal module script tree fetching procedure</span> invocations
to asynchronously complete. If any of them asynchronously complete with null, asynchronously
complete this algorithm with null. Otherwise, asynchronously complete this algorithm with
<var>module script</var>.</p>
</li>
</ol>

Expand Down Expand Up @@ -86611,19 +86691,19 @@ 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>Let <var>record</var> be <var>s</var>'s <span
data-x="concept-module-script-module-record">module record</span>.</p>
<li><p>If <var>s</var>'s <span data-x="concept-module-script-instantiation-state">instantiation
state</span> is "<code data-x="">errored</code>", <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>Let <var>instantiationStatus</var> be <var>record</var>.<span
data-x="js-ModuleDeclarationInstantiation">ModuleDeclarationInstantiation</span>().</p>
<li><p>Assert: <var>s</var>'s <span
data-x="concept-module-script-instantiation-state">instantiation 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>

<p class="note">This step will recursively instantiate all of the module's dependencies.</p>
</li>

<li><p>If <var>instantiationStatus</var> is an abrupt completion, <span>report the
exception</span> given by <var>instantiationStatus</var>.[[Value]] for <var>s</var> and abort
these steps.</p></li>
<li><p>Let <var>record</var> be <var>s</var>'s <span
data-x="concept-module-script-module-record">module record</span>.</p>

<li><p><span>Prepare to run script</span> given <var>settings</var>.</p></li>

Expand Down Expand Up @@ -87421,6 +87501,16 @@ document.querySelector("button").addEventListener("click", bound);
data-x="">fetching</code>", throw a <code>TypeError</code> exception and abort these
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>", throw <var>resolved module script</var>'s <span
data-x="concept-module-script-instantiation-error">instantiation error</span>.</p></li>

<li><p>Assert: <var>resolved module script</var>'s <span
data-x="concept-module-script-instantiation-state">instantiation 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>

<li><p>Return <var>resolved module script</var>'s <span
data-x="concept-module-script-module-record">module record</span>.</p></li>
</ol>
Expand Down

0 comments on commit 9ed4c2c

Please sign in to comment.