ExtendableEvent.waitUntil() shall be valid in microtask-checkpoint while event dispatch is still active
Categories
(Core :: DOM: Service Workers, enhancement, P3)
Tracking
()
People
(Reporter: bevis, Assigned: perry)
References
(Blocks 1 open bug)
Details
Attachments
(2 files)
3.03 KB,
patch
|
bkelly
:
review-
|
Details | Diff | Splinter Review |
47 bytes,
text/x-phabricator-request
|
RyanVM
:
approval-mozilla-beta+
|
Details | Review |
Reporter | ||
Comment 1•8 years ago
|
||
Reporter | ||
Comment 2•8 years ago
|
||
Comment 3•8 years ago
|
||
Reporter | ||
Comment 4•8 years ago
|
||
Comment 5•8 years ago
|
||
Comment 6•8 years ago
|
||
Comment 7•8 years ago
|
||
Comment 8•8 years ago
|
||
Comment 9•8 years ago
|
||
Reporter | ||
Comment 10•8 years ago
|
||
Comment 11•8 years ago
|
||
Reporter | ||
Comment 12•8 years ago
|
||
Reporter | ||
Updated•8 years ago
|
Comment 13•6 years ago
|
||
I think the current status in regards to this bug and https://github.com/w3c/ServiceWorker/issues/1213 is that after falken's pending changes in https://github.com/web-platform-tests/wpt/pull/15852 we fail:
in wpt/service-workers/service-worker/extendable-event-async-waituntil.https.html
promise_test(msg_event_test.bind(this, 'current-extension-expired-same-microtask-turn-extra'),
'Test calling waitUntil in a microtask at the end of an existing extension promise handler succeeds (event is still being dispatched)');
promise_test(function(t) {
var testBody = function(worker) {
return with_iframe('./resources/respondwith-microtask-async-waituntil');
}
return runTest(t, 'respondwith-microtask-async-waituntil', testBody);
}, 'Test calling waitUntil asynchronously inside microtask of respondWith promise (event is being dispatched).');
which corresponds to the test logic cases:
in a "message" handler:
case 'current-extension-expired-same-microtask-turn-extra':
waitPromise = Promise.resolve();
event.waitUntil(waitPromise);
waitPromise.then(() => { return async_microtask_waituntil(event); })
.then(reportResultExpecting('OK'))
break;
in a "fetch" handler:
case 'respondwith-microtask-async-waituntil':
response = Promise.resolve(new Response('RESP'));
event.respondWith(response);
response.then(() => { return async_microtask_waituntil(event); })
.then(reportResultExpecting('OK'));
break;
where the helper is:
function async_microtask_waituntil(event) {
return new Promise((res, rej) => {
Promise.resolve().then(() => {
try {
event.waitUntil(Promise.resolve());
res('OK');
} catch (error) {
res(error.name);
}
});
});
}
The basic issue appears to be that we're throwing when the dispatch flag is still set. The spec calls for us to throw if not active, where active is defined at https://w3c.github.io/ServiceWorker/#extendableevent-active as "An ExtendableEvent object is said to be active when its timed out flag is unset and either its pending promises count is greater than zero or its dispatch flag is set."
Our implementation implements the wait-another-microtask-turn heuristic, but MaybeDone doesn't handle the possibility that we're still in the initial microtask checkpoint that happens as part of event dispatch and where event dispatch is still happening. In general, we expect that when MaybeDone() is called in DispatchExtendableEventOnWorkerScope[1], event dispatch will be completed and the microtask checkpoint will have occurred (as long as their isn't JS on the stack), but it's more correct to do a check of the event's EventPhase() like FetchEvent::RespondWith() does[2].
1: https://searchfox.org/mozilla-central/rev/f1c7ba91fad60bfea184006f3728dd6ac48c8e56/dom/serviceworkers/ServiceWorkerPrivate.cpp#427
2: https://searchfox.org/mozilla-central/rev/f1c7ba91fad60bfea184006f3728dd6ac48c8e56/dom/serviceworkers/ServiceWorkerEvents.cpp#778
Updated•6 years ago
|
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Comment 15•6 years ago
|
||
This patch allows ExtendableEvent.waitUntil to be successfully called while
an ExtendableEvent is being dispatched. Initially, calls would fail if the
internal "pending promises count" reached zero during a microtask checkpoint
in between two event handler invocation tasks. This patch add the additional
condition that the dispatch flag must be unset for subsequent calls to fail.
Assignee | ||
Comment 16•6 years ago
|
||
This is seen on a real website via https://m.indiamart.com's ServiceWorker, as reported by https://bugzilla.mozilla.org/show_bug.cgi?id=1593156#c0.
Comment 17•6 years ago
|
||
Comment 18•6 years ago
|
||
bugherder |
Comment 19•6 years ago
|
||
I reproduced the issue with Firefox 74.0a1 (20200113204142) on Windows 10x64 using STR from 1593156#c0 and 1593156#c8.
The issue is verified fixed with Firefox 74.0a1 (20200120154412) on Windows 10x64, macOS 10.15 and Ubuntu 18.04. I can no longer reproduce the issue using the mentioned STR.
Assignee | ||
Comment 20•6 years ago
|
||
Comment on attachment 9120886 [details]
Bug 1409979 - ExtendableEvent.waitUntil should account for dispatch flag r?asuth
Beta/Release Uplift Approval Request
- User impact if declined: https://m.indiamart.com won't work on GeckoView. It'll crash when trying to visit it after the first time. There are probably other websites that would be broken, given that this bug is not specific to a particular web application.
- Is this code covered by automated tests?: Yes
- Has the fix been verified in Nightly?: Yes
- Needs manual test from QE?: No
- If yes, steps to reproduce:
- List of other uplifts needed: None
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): This changes the
ExtendableEvent
behavior to match that the specification says. - String changes made/needed:
Comment 21•6 years ago
|
||
Comment on attachment 9120886 [details]
Bug 1409979 - ExtendableEvent.waitUntil should account for dispatch flag r?asuth
Fixes a bug causing web compat issue for GV-based browsers. Approved for 73.0b9.
Comment 22•6 years ago
|
||
bugherder uplift |
Updated•3 years ago
|
Updated•3 years ago
|
Description
•