-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Top-level await integration #4352
Conversation
Twin dynamic import PR tc39/proposal-dynamic-import#71 |
For concreteness, this patch specifies how the WebAssembly JavaScript module integration proposal [1] could work in HTML. It is not yet ready to merge, as the proposal is still in a relatively early state. Note that this change depends on the ability for modules to block in the evaluation phase, to permit WebAssembly module instantiation to yield, as is necessary on some platforms where compilation work is performed during the first instantiation. Such an ability to yield is provided by the JavaScript top-level await proposal [2] and associated HTML integration patch whatwg#4352. [1] https://github.com/webassembly/esm-integration [2] https://github.com/tc39/proposal-top-level-await
For concreteness, this patch specifies how the WebAssembly JavaScript module integration proposal [1] could work in HTML. It is not yet ready to merge, as the proposal is still in a relatively early state. Note that this change depends on the ability for modules to block in the evaluation phase, to permit WebAssembly module instantiation to yield, as is necessary on some platforms where compilation work is performed during the first instantiation. Such an ability to yield is provided by the JavaScript top-level await proposal [2] and associated HTML integration patch whatwg#4352. [1] https://github.com/webassembly/esm-integration [2] https://github.com/tc39/proposal-top-level-await
For concreteness, this patch specifies how the WebAssembly JavaScript module integration proposal [1] could work in HTML. It is not yet ready to merge, as the proposal is still in a relatively early state. Note that this change depends on the ability for modules to block in the evaluation phase, to permit WebAssembly module instantiation to yield, as is necessary on some platforms where compilation work is performed during the first instantiation. Such an ability to yield is provided by the JavaScript top-level await proposal [2] and associated HTML integration patch whatwg#4352. [1] https://github.com/webassembly/esm-integration [2] https://github.com/tc39/proposal-top-level-await
For concreteness, this patch specifies how the WebAssembly JavaScript module integration proposal [1] could work in HTML. It is not yet ready to merge, as the proposal is still in a relatively early state. Note that this change depends on the ability for modules to block in the evaluation phase, to permit WebAssembly module instantiation to yield, as is necessary on some platforms where compilation work is performed during the first instantiation. Such an ability to yield is provided by the JavaScript top-level await proposal [2] and associated HTML integration patch whatwg#4352. [1] https://github.com/webassembly/esm-integration [2] https://github.com/tc39/proposal-top-level-await
source
Outdated
@@ -87776,35 +87780,26 @@ interface <dfn>ApplicationCache</dfn> : <span>EventTarget</span> { | |||
data-x="concept-script-record">record</span>.</p> | |||
|
|||
<li> | |||
<p>Set <var>evaluationStatus</var> to <var>record</var>.<span | |||
<p>Let <var>evaluationPromise</var> be <var>record</var>.<span |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note, nobody waits on this Promise (except possibly JS code called by FinishDynamicImport).
From discussion with @domenic and @nyaxt , a few changes to this PR are planned:
|
Even if the module is completely sync? Would that be an observable change?
After starting to evaluate the module, but not waiting until the evaluation is finished, right? |
Oh, hmm, I guess it would be for the case where the JS stack is non-empty (which blocks the microtask checkpoint). I am not sure whether this would be a web compatibility problem, though. |
I'm not even sure this is desirable for the async case. Consider <script type=module>
await new Promise(() => {})
</script>
<script>
setInterval(() => document.write("FAIL"), 1000);
</script>
xxx In this case, the |
"Desirable" is relative. Someone did something weird, and now a weird legacy discouraged feature of the web platform (document.write) fails, in a loud way. I'm OK with that, personally. |
@domenic Where's the right line? I guess none of us are proposing that the |
In cases like these, I'm happy for the line to be governed by what's easier to spec/implement. |
I'm trying to follow up on #4352 (comment) . I've landed a revert 4ed3b12 in conjunction with tc39/proposal-top-level-await#74 , which makes Evaluate() always return a Promise (thanks @guybedford!), so this should reduce a bit of the incidental complexity in the previous revision. About the other items to update, I'm having trouble piecing together what we had previously identified as things to update:
|
Sorry, the relevant counter here is the "ignore-destructive-writes counter"
This was a recent refactoring with d329a0f. That refactoring implies the clear path is to just not do anything with currentScript for top-level await, indeed. |
Ah, thanks for clarifying. I updated this PR to decrement the ignore-destructive-writes counter just when it settles. |
For concreteness, this patch specifies how the WebAssembly JavaScript module integration proposal [1] could work in HTML. It is not yet ready to merge, as the proposal is still in a relatively early state. Note that this change depends on the ability for modules to block in the evaluation phase, to permit WebAssembly module instantiation to yield, as is necessary on some platforms where compilation work is performed during the first instantiation. Such an ability to yield is provided by the JavaScript top-level await proposal [2] and associated HTML integration patch whatwg#4352. [1] https://github.com/webassembly/esm-integration [2] https://github.com/tc39/proposal-top-level-await
source
Outdated
<var>evaluationStatus</var>.[[Value]].</p></li> | ||
|
||
<li><p>Otherwise, <span>report the exception</span> given by | ||
<li><p>If <var>rethrow errors</var> is false, then upon rejection of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"rethrow errors" no longer makes sense as an argument name.
source
Outdated
|
||
<li><p><span>Clean up after running script</span> with <var>settings</var>.</p></li> | ||
|
||
<li><p>Return <var>evaluationStatus</var>.</p></li> | ||
<li><p>Return <var>evaluationPromise</var>.</p></li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://w3c.github.io/ServiceWorker/#run-service-worker-algorithm needs to be updated for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tracked at w3c/ServiceWorker#1407
source
Outdated
|
||
<li><p>Perform <span>FinishDynamicImport</span>(<var>referencingScriptOrModule</var>, | ||
<var>specifier</var>, <var>promiseCapability</var>, <var>completion</var>).</p></li> | ||
<var>specifier</var>, <var>promiseCapability</var>, <var>promise</var>).</p></li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should make sure tc39/proposal-dynamic-import#71 lands
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tracked at tc39/proposal-top-level-await#46
Thanks for the help and guidance, everyone. I don't have any more planned changes for this PR; is anything missing? We'll be considering top-level await for Stage 3 in the June 4, 2019 TC39 meeting, and so any more thoughts you have here would be very helpful. I'm wondering whether the relationship between top-level await and ServiceWorkers in w3c/ServiceWorker#1407 has any implications for HTML (probably not?). |
It seems that |
It's on my TODO list for while to double check the tests again. Thanks for the pointer. |
We also need to integrate top-level await and worklets, since worklets ended up landing in the HTML spec before this PR did. From what I understand you've been doing that implementation work, @camillobruni; would you be able to outline a rough sketch of how it's implemented? I can try to finish up the spec for it. In particular I'm unsure what the final decision was on the question in w3c/css-houdini-drafts#984 (comment) , as to how we run multiple top-level-await-using scripts into a new worklet global scope. |
I have done a bit of testing with this. I am a bit stuck about what to do because I am not very familiar with the html spec. Sorry this is super beginner stuff, I just don't know where to look in the spec to answer my questions. My naive implementation suggests that But looking at how chrome handles it -- this test appears to pass? I ran it with chrome canary with the Oddly, the
to this:
While it fixes my problem, this times out with chrome as well. So, where I am stuck is I am not too sure where to look to figure out which behaviour is right. If it turns out that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While looking at this PR again I found some minor nits.
@codehag I don't see anything in the specification that would further delay the main |
@domenic looking at this again I don't think changes to worklets are needed (they'll continue to invoke run the module script and ignore the result and as long as their global doesn't implement |
This is one possible behavior. The other possible behavior is to have each module script wait for the previous one's to complete. That latter behavior would need spec changes, I believe. And we haven't gotten any answer on which behavior we want. I believe @camillobruni is writing some worklet tests, but I don't know which behavior he's testing. |
I think your take that it shouldn't be different from multiple |
Re: The way this test is currently done in chromium is that the timing is changed when the TLA flag is passed to the renderer. There's a virtual test suite that changes the timing expectations to the one described by this PR if the TLA flag is on: The base WPT doesn't have the TLA flag, so it has the old timing. I imagine the test will be updated once the TLA flag is flipped on by default. To clarify @annevk's question: are you asking for the test to be updated ahead of time? To clarify @codehag's comment: the chromium implementation follows this PR, but only under the flag. |
This is discussed in #5824. |
@syg typically there's at least a PR open for test changes that can be merged together with the change to the standard. See https://whatwg.org/working-mode#changes. |
I was imagining this would be done via the WPT 2-way sync if Chromium flips it on first. Is that acceptable? |
How is this envisioned to work with synthetic module records, btw? I imagine all synthetic module records will also change to always returning promises? |
@syg that's fine, assuming there's some diff for editors to review. |
Synthetic module records were removed from Web IDL, so I don't think they're an issue any more. |
web-platform-tests/wpt#26771 has been merged, which I believe contains the test updates discussed upthread. And I just wrote web-platform-tests/wpt#26826 to get us some basic worklet test coverage. So, I think this can be merged! I'll do so tomorrow-ish, unless folks have any objections. |
<span>"<code>QuotaExceededError</code>"</span> <code>DOMException</code>, [[Target]]: empty | ||
}.</p> | ||
<var>evaluationPromise</var> to <span>a promise rejected with</span> a new | ||
<span>"<code>QuotaExceededError</code>"</span> <code>DOMException</code>.</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't the user agent abort a module evaluation after the first await
? Unless I'm missing something, in that case evaluationPromise
would never resolve.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, very interesting. So an instance of the case we're wondering about is
<script type="module">
try {
await import("./bad.mjs");
} catch (e) {
// e should ideally be a "QuotaExceededError" DOMException
}
</script>
// bad.mjs
await 1;
while (true) { }
await 2;
Any ideas what implementations are planning to do, @codehag and @camillobruni?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good find! I tested in Chrome that an infinite looping module can hang the renderer when dynamically imported. The slow script killer doesn't kill dynamic imports correctly, even without top-level await. That is, the following also hangs:
<script>
(async function() {
await import("./bad.mjs");
} catch (e) {
// e should ideally be a "QuotaExceededError" DOMException
}
})();
</script>
// bad.mjs
while (true) { }
Filed https://bugs.chromium.org/p/chromium/issues/detail?id=1157321
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can confirm that firefox has the same behavior as what @syg described for chrome above: both the test cases result in the tab hanging.
We do show a user prompt however, about a slow script and let the user respond. When the user responds on the second use case, the script is stopped and the page becomes usable again. Crashes with TLA though.
The bug tracking this on the firefox side is https://bugzilla.mozilla.org/show_bug.cgi?id=1681664
cc @annevk
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright. A simpler example without dynamic import is the following:
<script>
window.onerror = event => {
console.log(event.error); // should ideally log a "QuotaExceededError" DOMException
};
</script>
<script type="module">
await 1;
while (true) { }
</script>
I'll try and work on some spec text giving UAs license to terminate top-level-await using scripts in the same way they are currently given license to terminate other scripts, and I'll be sure it also covers dynamic import(). I might merge this first if the fix seems especially separable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking like more of a mess than I thought. The script-killing section of the spec isn't very well defined or aligned with UAs; e.g. as far as I can tell from Chrome it kills the entire process after prompting, which is not really allowed by the current spec text. And we're not sure if any browser actually bothers with the "QuotaExceededError" DOMException business.
So I'll merge this as-is and file a followup bug.
For concreteness, this patch specifies how the WebAssembly JavaScript module integration proposal [1] could work in HTML. It is not yet ready to merge, as the proposal is still in a relatively early state. Note that this change depends on the ability for modules to block in the evaluation phase, to permit WebAssembly module instantiation to yield, as is necessary on some platforms where compilation work is performed during the first instantiation. Such an ability to yield is provided by the JavaScript top-level await proposal [2] and associated HTML integration patch whatwg#4352. [1] https://github.com/webassembly/esm-integration [2] https://github.com/tc39/proposal-top-level-await
For concreteness, this patch specifies how the WebAssembly JavaScript module integration proposal [1] could work in HTML. It is not yet ready to merge, as the proposal is still in a relatively early state. Note that this change depends on the ability for modules to block in the evaluation phase, to permit WebAssembly module instantiation to yield, as is necessary on some platforms where compilation work is performed during the first instantiation. Such an ability to yield is provided by the JavaScript top-level await proposal [2] and associated HTML integration patch whatwg#4352. [1] https://github.com/webassembly/esm-integration [2] https://github.com/tc39/proposal-top-level-await
For concreteness, this patch specifies how the WebAssembly JavaScript module integration proposal [1] could work in HTML. It is not yet ready to merge, as the proposal is still in a relatively early state. Note that this change depends on the ability for modules to block in the evaluation phase, to permit WebAssembly module instantiation to yield, as is necessary on some platforms where compilation work is performed during the first instantiation. Such an ability to yield is provided by the JavaScript top-level await proposal [2] and associated HTML integration patch whatwg#4352. [1] https://github.com/webassembly/esm-integration [2] https://github.com/tc39/proposal-top-level-await
- Enable tests with TLA enabled - Fix top-level error reporting with TLA Based on the discussions on the spec, we fire error events on rejection of the result promise: whatwg/html#4352 (comment) Bug: 1022182, 1096455, 1127215, v8:9344 Change-Id: I16e83cb4e279c1e44be7fa70a51a103ee94aacc3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2228881 Commit-Queue: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Hiroshige Hayashizaki <hiroshige@chromium.org> Reviewed-by: Kouhei Ueno <kouhei@chromium.org> Reviewed-by: Dominic Farolino <dom@chromium.org> Reviewed-by: Domenic Denicola <domenic@chromium.org> Cr-Commit-Position: refs/heads/master@{#806593} GitOrigin-RevId: 077d63da3268e6761d20c56409d37c57d37f1685
This reverts commit 077d63da3268e6761d20c56409d37c57d37f1685. Reason for revert: https://ci.chromium.org/p/chromium/builders/ci/WebKit%20Linux%20Leak is constantly failing on * virtual/module-top-level-await/external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-order-4-tla.html * virtual/module-top-level-await/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/module-tla-delayed.html * virtual/module-top-level-await/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/module-tla-immediate-promise.html * virtual/module-top-level-await/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/module-tla-import.html Original change's description: > [blink] Fix top-level-await error reporting > > - Enable tests with TLA enabled > - Fix top-level error reporting with TLA > > Based on the discussions on the spec, we fire error events on rejection > of the result promise: > whatwg/html#4352 (comment) > > Bug: 1022182, 1096455, 1127215, v8:9344 > Change-Id: I16e83cb4e279c1e44be7fa70a51a103ee94aacc3 > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2228881 > Commit-Queue: Camillo Bruni <cbruni@chromium.org> > Reviewed-by: Hiroshige Hayashizaki <hiroshige@chromium.org> > Reviewed-by: Kouhei Ueno <kouhei@chromium.org> > Reviewed-by: Dominic Farolino <dom@chromium.org> > Reviewed-by: Domenic Denicola <domenic@chromium.org> > Cr-Commit-Position: refs/heads/master@{#806593} TBR=hiroshige@chromium.org,kouhei@chromium.org,cbruni@chromium.org,dom@chromium.org,domenic@chromium.org Change-Id: I66b085b05ad30020772e80324e226275e41a8782 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: 1022182 Bug: 1096455 Bug: 1127215 Bug: v8:9344 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2410725 Reviewed-by: Avi Drissman <avi@chromium.org> Commit-Queue: Avi Drissman <avi@chromium.org> Cr-Commit-Position: refs/heads/master@{#806724} GitOrigin-RevId: 593ef19ebb9255397222180a3bacf9a78bfbbffd
- Add better assertion failure messages - Use better content for document.write The tests assume that the ignore-destructive-writes counter is only incremented during the synchronous part of module evaluation (see whatwg/html#4352 (comment)). This also fixes document-write/module-delayed.html which accidentally had wrong test expectations checked in that made it pass. Bug: 1127215 Bug: 1022182 Bug: v8:9344 Change-Id: I01a75534f7efd0bd8e376dfd049432e52661604d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2397696 Reviewed-by: Hiroshige Hayashizaki <hiroshige@chromium.org> Commit-Queue: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/master@{#807384} GitOrigin-RevId: 8168e512fcecd52c45ffe99b425b9e392959f895
This is a reland of 077d63da3268e6761d20c56409d37c57d37f1685 - Add missing test expections Original change's description: > [blink] Fix top-level-await error reporting > > - Enable tests with TLA enabled > - Fix top-level error reporting with TLA > > Based on the discussions on the spec, we fire error events on rejection > of the result promise: > whatwg/html#4352 (comment) > > Bug: 1022182, 1096455, 1127215, v8:9344 > Change-Id: I16e83cb4e279c1e44be7fa70a51a103ee94aacc3 > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2228881 > Commit-Queue: Camillo Bruni <cbruni@chromium.org> > Reviewed-by: Hiroshige Hayashizaki <hiroshige@chromium.org> > Reviewed-by: Kouhei Ueno <kouhei@chromium.org> > Reviewed-by: Dominic Farolino <dom@chromium.org> > Reviewed-by: Domenic Denicola <domenic@chromium.org> > Cr-Commit-Position: refs/heads/master@{#806593} TBR=kouhei@chromium.org Bug: 1022182 Bug: 1096455 Bug: 1128296 Bug: 1127215 Bug: v8:9344 Change-Id: Icecaccf34efc4354e0faac362da6f6cbdd49f50d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2410075 Reviewed-by: Dominic Farolino <dom@chromium.org> Commit-Queue: Dominic Farolino <dom@chromium.org> Cr-Commit-Position: refs/heads/master@{#808128} GitOrigin-RevId: 5e17eba0f8ba762b3e9ce72052057f56ba0f716d
The purpose of this patch is to nail down how HTML would
adjust to the needs of top-level await. The relevant change is,
the module.Evaluate() method will return a Promise that resolves
when the module is ready, and this will be passed to
FinishDynamicImport to wait on before resolving the Promise it returns.
It doesn't seem like anyone else needs to wait for a module script
to "finish" evaluating besides dynamic import.
(See WHATWG Working Mode: Changes for more details.)
/infrastructure.html ( diff )
/references.html ( diff )
/webappapis.html ( diff )