diff --git a/source b/source index 9a7c3ac5a18..288df4e4c2d 100644 --- a/source +++ b/source @@ -2448,6 +2448,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute pop
A script is one of two possible structures. - All scripts have:
+A script is one of two possible structs. All scripts have:
A classic script is a script - that has the following additional fields:
+ that has the following additional items:A module script is a script - that has the following additional fields:
+ that has the following additional items:A Source Text Module Record representing the parsed module, ready to be - evaluated.
+ evaluated, or null if the module could not be parsed or instantiated.One of "uninstantiated
", "errored
", or "instantiated
", used to prevent reinvocation of ModuleDeclarationInstantiation on modules that
- failed to instantiate previously, and to ensure errors during parsing, instantiation, or
- evaluation are remembered and propagated correctly.
A JavaScript value, which has meaning only if the state is "errored
".
This stores errors that will prevent the module from successfully instantiating, + such as parse errors or errors in its dependencies. A module script can also be errored due to errors recorded by the + JavaScript specification as part of its module record.
To error a module script script with a given value error, - perform the following steps:
+We say that a module script is
+ errored if either its module
+ record is null, or its module
+ record's [[Status]] field has the value "errored
".
Assert: script's state is not
- "errored
".
When a module script is + errored, we say that its error is either + its pre-instantiation error, + when its module record is null, or its + module record's [[ErrorCompletion]] + field's [[Value]] field, otherwise.
-If script's module - record is set, then:
+To set the pre-instantiation + error of a module script script:
-Set script module - record's [[HostDefined]] field to undefined.
Let moduleRecord be script's module record.
Set script's module - record to null.
If moduleRecord is not null, set moduleRecord.[[HostDefined]] to + undefined.
Set script's state to
- "errored
".
Set script's module + record to null.
Set script's error to +
Set script's pre-instantiation error to error.
We say that a module script has instantiated if its module record is not null, and its module record's [[Status]] field is either
+ "instantiated
" or "evaluated
".
An environment is an object that identifies the settings of a @@ -86376,8 +86382,9 @@ interface NavigatorOnLine { JavaScript realm. When we run a classic script or run a module script, this execution context becomes the top of the JavaScript execution context stack, on top of which another execution context specific to the script in question is - pushed. (This setup ensures ParseScript and ModuleEvaluation know which Realm to use.)
+ pushed. (This setup ensures ParseScript and Source + Text Module Record's Evaluate know which Realm to + use.) @@ -86753,23 +86760,22 @@ interface NavigatorOnLine { module script">fetching a single module script asynchronously completes with result: -If result is null, asynchronously complete this algorithm with null and abort - these steps.
If result's state is "instantiated
" or "errored
", asynchronously complete this
- algorithm with result, and abort these steps.
If result is null, is + errored, or has instantiated, + asynchronously complete this algorithm with result, and abort these steps.
Assert: result's state is
- "uninstantiated
".
Assert: result's module
+ record's [[Status]] is "uninstantiated
".
Fetch the - descendants of and instantiate result given destination and an - ancestor list obtained by appending url to ancestor list.
If the top-level module fetch flag is set, fetch the descendants of and instantiate + result given destination and an ancestor list obtained by appending url to ancestor list. Otherwise, + fetch the descendants of + result given the same arguments.
When the fetch the descendants of and instantiate a module script algorithm - asynchronously completes with final result, asynchronously complete this algorithm - with final result.
When the appropriate algorithm asynchronously completes with final result, + asynchronously complete this algorithm with final result.
To fetch a single module script, given a url, a fetch client
@@ -86867,20 +86873,18 @@ interface NavigatorOnLine {
- To fetch the descendants of and instantiate a module script module
- script, given a destination and an optional ancestor list, run these
- steps. The algorithm will asynchronously complete with either null (on failure) or with
- module script (on success). To fetch the descendants of a module script module script, given a
+ destination and an optional ancestor list, run these steps. The algorithm
+ will asynchronously complete with either null (on failure) or with module script (on
+ success). If ancestor list was not given, let it be the empty list. If ancestor list was not given, let it be an empty list. If module script's state is
- " Assert: module script's state
- is " If module script is
+ errored or has instantiated,
+ asynchronously complete this algorithm with module script, and abort these
+ steps. Let record be module script's module record. Let url be the result of resolving
a module specifier given module script and requested. If url is failure: Assert: url is never failure, because resolving a module specifier must have been previously successful with these same two
+ arguments. Let error be a new Error module script with
- error. Abort this algorithm, and asynchronously complete it with module
- script. Otherwise, if ancestor list does not contain url, append
- url to urls. If ancestor list does not contain
+ url, append url to
+ urls. Let descendants result be null. For each url in urls, perform the
internal module script graph fetching procedure given url, module
@@ -86936,133 +86929,80 @@ interface NavigatorOnLine {
These invocations of the internal module script graph fetching procedure should
be performed in parallel to each other. If any invocation of the internal module script graph fetching procedure
- asynchronously completes with null, then optionally abort all other invocations, set
- descendants result to null, and proceed to the next step. (The un-fetched descendant
- will cause errors during instantiation.) If any invocation of the internal module script graph fetching procedure
- asynchronously completes with a module script whose state is " Otherwise, wait for all of the internal module script graph fetching procedure
- invocations to asynchronously complete, with module scripts
- whose states are not " Let instantiationStatus be record.ModuleDeclarationInstantiation(). This step will recursively call ModuleDeclarationInstantiation all of the
- module's uninstantiated dependencies. For each script in module script's uninstantiated inclusive
- descendant module scripts, perform the following steps: Wait for all invocations of the internal module script graph fetching procedure
+ to asynchronously complete, and let results be a list of the results,
+ corresponding to the same order they appeared in urls. Then, for each result of results: If instantiationStatus is an abrupt completion, then error script with
- instantiationStatus.[[Value]]. If result is null, asynchronously complete this algorithm with null, aborting
+ these steps. Otherwise, set script's state to " If result is errored,
+ then set the pre-instantiation
+ error for module script to result's error. Asynchronously complete this algorithm with
+ module script, aborting these steps. Asynchronously complete this algorithm with descendants result. It is important to wait for all invocations to complete, and then iterate the results in
+ order, so that any fetching or pre-instantiation errors are deterministically surfaced to the
+ developer. Otherwise, a module script graph with multiple errors would surface a
+ nondeterministically chosen error, making debugging quite difficult. As an unobservable optimization, implementations can quit early if an invocation returns
+ null or an errored module
+ script, and all previous invocations have completed already. However, this is optimizing
+ for the rare failure case, so likely not worth the trouble. It is intentional that we complete with descendants result here, and
- not module script, as this allows us to notify the caller of fetching errors. If we've reached this point, all of the internal module script graph fetching
+ procedure invocations have asynchronously completed, with module scripts that are not errored. Asynchronously complete this algorithm
+ with module script. In the above algorithm, a module script script's uninstantiated
- inclusive descendant module scripts is a set of module scripts determined as follows: To fetch the descendants of and instantiate a module script module
+ script, given a destination and an optional ancestor list, run these
+ steps. The algorithm will asynchronously complete with either null (on failure) or with
+ module script (on success). If script's module
- record is null, return the empty set. Fetch the descendants of
+ module script, given destination and ancestor list. Let moduleMap be script's settings object's
- module map. Let stack be the stack « script ». Let inclusive descendants be an empty set. Return from this algorithm, and run the following steps when fetching the descendants of a module script asynchronously
+ completes with result. While stack is not empty: If result is null or is
+ errored, then asynchronously complete this algorithm with result. Let current the result of popping from
- stack. Assert: current is a module script (i.e., it is not " If inclusive descendants and stack both do not contain current, then: Append current to
- inclusive descendants. Let child specifiers be the value of current's module record's [[RequestedModules]]
- internal slot. Let child URLs be the list obtained by calling
- resolve a module specifier once for each item of child specifiers,
- given current and that item. Omit any failures. Let child modules be the list obtained by getting each value in moduleMap whose key is given by an
- item of child URLs. For each s of child modules: In this case, there was an error fetching the descendants, or one of them
+ failed to parse, or was previously marked as errored. We will not attempt to instantiate. If inclusive descendants already contains s, continue. Let record be result's module record. If s is null, continue. Perform record.Instantiate(). Assert: s is a module script (i.e., it is not
- " This step will recursively call Instantiate
+ on all of the module's uninstantiated dependencies. Push s onto stack. If this throws an exception, ignore it for now; it is stored as result's error, and will be reported when we run result. Return a set containing all items of inclusive descendants whose
- state is " Asynchronously complete this algorithm with result. 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 set only used for membership testing and whose order is thus not
- important. To create a classic script, given some script
@@ -87098,7 +87038,8 @@ interface NavigatorOnLine {
Let script be a new module script that this algorithm will
- subsequently initialize.
-
- instantiated
" or "errored
", asynchronously
- complete this algorithm with module script, and abort these steps.uninstantiated
".
-
-
-
- TypeError
exception.errored
", then
- optionally abort all other invocations, set descendants result to module
- script, and proceed to the next step. (The errored descendant will cause errors during
- instantiation.)errored
". Then, set descendants result to module script,
- and proceed to the next step.
-
- instantiated
".
-
-
-
+ fetching
" or null).
-
-
-
- fetching
", since by this point all child modules must have been
- fetched).uninstantiated
".Creating scripts
Set script's settings object to the environment settings object provided.
If result is a List of errors, then:
Error script with - errors[0].
Set the + pre-instantiation error of script to errors[0].
Return script.
Set script's state to "uninstantiated
".
For each string requested of + record.[[RequestedModules]]:
+ +Let url be the result of resolving + a module specifier given module script and requested.
If url is failure:
+ +Let error be a new TypeError
exception.
Set the + pre-instantiation error of script to error.
Return script.
This step is essentially validating all of the requested module specifiers. We + treat a module with unresolvable module specifiers the same as one that cannot be parsed; in + both cases, a syntactic issue makes it impossible to ever contemplate instantiating the module + later.
+Set script's module record to result.
Check if we can run script with settings. If this returns "do not run" then abort these steps.
If s's state is "errored
", then report the exception given by s's error for s and abort these
- steps.
If s is errored, then + report the exception given by s's error and abort these steps.
Assert: s's state is "instantiated
" (and thus its module record is not null).
Prepare to run script given settings.
Let record be s's module record.
-Prepare to run script given settings.
Let evaluationStatus be record.ModuleEvaluation().
+ data-x="js-Evaluate">Evaluate().This step will recursively evaluate all of the module's dependencies.
-If ModuleEvaluation fails to complete as a result - of the user agent aborting the running script, then - set evaluationStatus to Completion { [[Type]]: throw, [[Value]]: a new +
If Evaluate fails to complete as a result of the user agent
+ aborting the running script, then set
+ evaluationStatus to Completion { [[Type]]: throw, [[Value]]: a new
"QuotaExceededError
" DOMException
, [[Target]]: empty }.
If evaluationStatus is an abrupt completion, then:
- -Error script with - evaluationStatus.[[Value]].
Report the exception given by evaluationStatus.[[Value]] for - s.
-If evaluationStatus is an abrupt completion, then report the + exception given by evaluationStatus.[[Value]] for s.
Clean up after running script with settings.
Although the JavaScript specification does not account for this possibility, it's sometimes
necessary to abort a running script. This causes any ScriptEvaluation or ModuleEvaluation to cease immediately, emptying the
+ data-x="js-ScriptEvaluation">ScriptEvaluation or Source Text Module Record
+ Evaluate invocations to cease immediately, emptying the
JavaScript execution context stack without triggering any of the normal mechanisms
like finally
blocks.
Assert: url is never failure, because resolving a module specifier must have been previously successful with these - same two arguments during the appropriate invocation of fetch the descendants of and - instantiate a module script.
Let resolved module script be moduleMap[url]. (This entry must exist for us to have gotten to this point.)
If resolved module script is null, then throw a TypeError
- exception and abort these steps.
This occurs when we have previously tried to fetch url, and failed, but are now rediscovering that fact in a new
- module script graph. For example, given a file module.js
whose contents
- are
import "./404.js";- -
then we could get here as part of fetching the
- graph for the second script
element in the following HTML:
<script type="module" src="404.js"></script> -<script type="module" src="module.js"></script>-
Assert: resolved module script is a module script (i.e., is not
- "fetching
").
If resolved module script's state is "errored
", then throw
- resolved module script's error.
fetching
").
- Assert: resolved module script's module record is not null.
Assert: resolved module script is not errored.
Return resolved module script's module record.