Skip to content

Commit

Permalink
Properly instantiate inline module scripts
Browse files Browse the repository at this point in the history
This moves the latter half of the "internal module script graph fetching
procedure" into "fetch the descendants of a module script", which is
then renamed "fetch the descendants of and instantiate a module script".
Then, the inline script code can properly call this new algorithm to
take care of everything once it has an initial module script prepared
from the inline script source.

Fixes #2544.
  • Loading branch information
domenic committed May 12, 2017
1 parent 1157631 commit 3a3405a
Showing 1 changed file with 142 additions and 137 deletions.
279 changes: 142 additions & 137 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -58362,10 +58362,11 @@ o............A....e
<li><p>If this returns null, set <span data-x="concept-script-script">the script's
script</span> to null and abort these substeps; <span>the script is ready</span>.</p></li>

<li><p><span data-x="fetch the descendants of a module script">Fetch the
descendants</span> of <var>script</var> (using an empty ancestor list). When this
asynchronously completes, set <span data-x="concept-script-script">the script's
script</span> to the result. At that time, <span>the script is ready</span>.</p></li>
<li><p><span data-x="fetch the descendants of and instantiate a module script">Fetch the
descendants of and instantiate</span> <var>script</var>, given the destination "<code
data-x="">script</code>". When this asynchronously completes, set <span
data-x="concept-script-script">the script's script</span> to the result. At that time,
<span>the script is ready</span>.</p></li>
</ol>
</dd>
</dl>
Expand Down Expand Up @@ -87060,130 +87061,15 @@ interface <dfn>NavigatorOnLine</dfn> {
<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><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>record</var> be <var>result</var>'s <span
data-x="concept-module-script-module-record">module record</span>.</p></li>

<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 uninstantiated dependencies.</p>
</li>
<li><p><span data-x="fetch the descendants of and instantiate a module script">Fetch the
descendants of and instantiate</span> <var>result</var> given <var>destination</var> and an
ancestor list obtained by appending <var>url</var> to <var>ancestor list</var>.</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>

<ol>
<li><p>If <var>instantiationStatus</var> is an abrupt completion, then <span data-x="error a
module script">error</span> <var>script</var> with
<var>instantiationStatus</var>.[[Value]].</p></li>

<li><p>Otherwise, set <var>script</var>'s <span
data-x="concept-module-script-state">state</span> to "<code
data-x="">instantiated</code>".</p></li>
</ol>
</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>
<li><p>When the <span>fetch the descendants of and instantiate a module script</span> algorithm
asynchronously completes with <var>final result</var>, asynchronously complete this algorithm
with <var>final result</var>.</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 <span>set</span> of <span
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>

<li><p>Let <var>stack</var> be the <span>stack</span> « <var>script</var> ».</p></li>

<li><p>Let <var>inclusive descendants</var> be an empty <span>set</span>.</p></li>

<li>
<p>While <var>stack</var> <span data-x="list is empty">is not empty</span>:</p>

<ol>
<li><p>Let <var>current</var> the result of <span data-x="stack pop">popping</span> from
<var>stack</var>.</p></li>

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

<li>
<p>If <var>inclusive descendants</var> and <var>stack</var> both do not <span
data-x="list contains">contain</span> <var>current</var>, then:</p>

<ol>
<li><p><span data-x="list append">Append</span> <var>current</var> to
<var>inclusive descendants</var>.</p></li>

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

<li><p>Let <var>child URLs</var> be the <span>list</span> obtained by calling
<span>resolve a module specifier</span> once for each item of <var>child specifiers</var>,
given <var>current</var> and that item. Omit any failures.</p></li>

<li><p>Let <var>child modules</var> be the <span>list</span> obtained by <span
data-x="map get">getting each value</span> in <var>moduleMap</var> whose key is given by an
item of <var>child URLs</var>.</p></li>

<li>
<p><span data-x="list iterate">For each</span> <var>s</var> of <var>child modules</var>:</p>

<ol>
<li><p>If <var>inclusive descendants</var> already <span data-x="list
contains">contains</span> <var>s</var>, <span>continue</span>.</p></li>

<li><p>If <var>s</var> is null, <span>continue</span>.</p></li>

<li><p>Assert: <var>s</var> is a <span>module script</span> (i.e., it is not
"<code data-x="">fetching</code>", since by this point all child modules must have been
fetched).</p></li>

<li><p><span data-x="stack push">Push</span> <var>s</var> onto <var>stack</var>.</p></li>
</ol>
</ol>
</li>
</ol>
</li>

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

<p class="note">The above algorithm gives a depth-first search of the module dependency graph. The
main interesting part is in how the "edges" of this graph are determined. The actual search
implementation is not important; any other technique for exploring the graph will suffice, given
that the output is a <span>set</span> only used for membership testing and whose order is thus not
important.</p>

<p>To <dfn>fetch a single module script</dfn>, given a <var>url</var>, a <var>fetch client
settings object</var>, a <var>destination</var>, a <var>cryptographic nonce</var>, a <var>parser
state</var>, a <var>credentials mode</var>, a <var>module map settings object</var>, a
Expand Down Expand Up @@ -87279,12 +87165,21 @@ interface <dfn>NavigatorOnLine</dfn> {
</li>
</ol>

<p>To <dfn>fetch the descendants of a module script</dfn> <var>module script</var>, given a
<var>destination</var> and an <var>ancestor list</var>, run these steps. The algorithm will
asynchronously complete with either null (on failure) or with <var>module script</var> (on
success).</p>
<p>To <dfn>fetch the descendants of and instantiate a module script</dfn> <var>module
script</var>, given a <var>destination</var> and an optional <var>ancestor list</var>, run these
steps. The algorithm will asynchronously complete with either null (on failure) or with
<var>module script</var> (on success).</p>

<ol>
<li><p>If <var>ancestor list</var> was not given, let it be the empty <span>list</span>.</p></li>

<li><p>If <var>module script</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>module script</var>, and abort these steps.</p></li>

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

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

Expand Down Expand Up @@ -87321,6 +87216,8 @@ interface <dfn>NavigatorOnLine</dfn> {
</ol>
</li>

<li><p>Let <var>descendants result</var> be null.</p></li>

<li>
<p><span data-x="list iterate">For each</span> <var>url</var> in <var>urls</var>, perform the
<span>internal module script graph fetching procedure</span> given <var>url</var>, <var>module
Expand All @@ -87338,24 +87235,132 @@ interface <dfn>NavigatorOnLine</dfn> {
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>
asynchronously completes with null, then optionally abort all other invocations, set
<var>descendants result</var> to null, and proceed to the next step. (The un-fetched descendant
will cause errors during instantiation.)</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>
data-x="concept-module-script-state">state</span> is "<code data-x="">errored</code>", then
optionally abort all other invocations, set <var>descendants result</var> to <var>module
script</var>, and proceed to the next step. (The errored descendant will cause errors during
instantiation.)</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>
data-x="">errored</code>". Then, set <var>descendants result</var> to <var>module script</var>,
and proceed to the next step.</p>
</li>

<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 uninstantiated dependencies.</p>
</li>

<li>
<p>For each <var>script</var> in <var>module script</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, then <span data-x="error a
module script">error</span> <var>script</var> with
<var>instantiationStatus</var>.[[Value]].</p></li>

<li><p>Otherwise, set <var>script</var>'s <span
data-x="concept-module-script-state">state</span> to "<code
data-x="">instantiated</code>".</p></li>
</ol>
</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>module script</var>, as this allows us to notify the caller of fetching errors.</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 <span>set</span> of <span
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>

<li><p>Let <var>stack</var> be the <span>stack</span> « <var>script</var> ».</p></li>

<li><p>Let <var>inclusive descendants</var> be an empty <span>set</span>.</p></li>

<li>
<p>While <var>stack</var> <span data-x="list is empty">is not empty</span>:</p>

<ol>
<li><p>Let <var>current</var> the result of <span data-x="stack pop">popping</span> from
<var>stack</var>.</p></li>

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

<li>
<p>If <var>inclusive descendants</var> and <var>stack</var> both do not <span
data-x="list contains">contain</span> <var>current</var>, then:</p>

<ol>
<li><p><span data-x="list append">Append</span> <var>current</var> to
<var>inclusive descendants</var>.</p></li>

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

<li><p>Let <var>child URLs</var> be the <span>list</span> obtained by calling
<span>resolve a module specifier</span> once for each item of <var>child specifiers</var>,
given <var>current</var> and that item. Omit any failures.</p></li>

<li><p>Let <var>child modules</var> be the <span>list</span> obtained by <span
data-x="map get">getting each value</span> in <var>moduleMap</var> whose key is given by an
item of <var>child URLs</var>.</p></li>

<li>
<p><span data-x="list iterate">For each</span> <var>s</var> of <var>child modules</var>:</p>

<ol>
<li><p>If <var>inclusive descendants</var> already <span data-x="list
contains">contains</span> <var>s</var>, <span>continue</span>.</p></li>

<li><p>If <var>s</var> is null, <span>continue</span>.</p></li>

<li><p>Assert: <var>s</var> is a <span>module script</span> (i.e., it is not
"<code data-x="">fetching</code>", since by this point all child modules must have been
fetched).</p></li>

<li><p><span data-x="stack push">Push</span> <var>s</var> onto <var>stack</var>.</p></li>
</ol>
</ol>
</li>
</ol>
</li>

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

<p class="note">The above algorithm gives a depth-first search of the module dependency graph. The
main interesting part is in how the "edges" of this graph are determined. The actual search
implementation is not important; any other technique for exploring the graph will suffice, given
that the output is a <span>set</span> only used for membership testing and whose order is thus not
important.</p>

<h5 id="creating-scripts">Creating scripts</h5>

<p>To <dfn data-x="creating a classic script">create a classic script</dfn>, given some script
Expand Down

0 comments on commit 3a3405a

Please sign in to comment.