Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 1536619 [wpt PR 15852] - service worker: Improve WPT tests for as…
…ync respondWith/waitUntil., a=testonly Automatic update from web-platform-tests service worker: Improve WPT tests for async respondWith/waitUntil. (#15852) See discussion at [1] and [2]. This makes the following changes. 1. Adds a test for: self.addEventListener('fetch', e => { Promise.resolve().then(() => { e.respondWith(new Response('hi')); }); }); This should not throw because respondWith() is called while the event dispatch flag is still set. The microtask checkpoint is in "Cleanup After Running Scripts" here: https://html.spec.whatwg.org/multipage/webappapis.html#clean-up-after-running-script This is called from step 16.2 here: https://heycam.github.io/webidl/#call-a-user-objects-operation Which in turn is called from the DOM spec's "Inner Invoke" to call event targets: https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke 2. Changes the expectation for: addEventListener('message', event => { Promise.resolve().then(event.waitUntil(p)); }); From throws to not throws, for the same reasoning as above. 3. Changes the expectation for: addEventListener('message', event => { waitPromise = Promise.resolve(); event.waitUntil(waitPromise); waitPromise.then(() => { Promise.resolve().then(() => {event.waitUntil();}); }); }); From throws to not throws. This is subtle. Because all the promises are just Promise.resolve(), the event dispatch flag is still set by the time the second waitUntil() is called. 4. To test what 3. originally intended, a new test is added which makes waitPromise a promise that does not immediately resolve. 5. Changes the expectation for: addEventListener(‘fetch’, event => { response = Promise.resolve(new Response('RESP')); event.respondWith(response); response.then(() => { Promise.resolve().then(() => {event.waitUntil();}); }) }); Again this is because the promises used resolve immediately, so the event dispatch flag is still set. Similarly, a new test is added to cover the original intent. These WPT changes appear to match the behavior of Safari and Edge while diverging from Chrome and (partially) Firefox. [1] w3c/ServiceWorker#1213 [2] w3c/ServiceWorker#1394 Bug: 942414 Change-Id: I9a4a56d71d3919ed614ff78df2bdc6cc0251dadd Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1524393 Commit-Queue: Matt Falkenhagen <falken@chromium.org> Reviewed-by: Ben Kelly <wanderview@chromium.org> Cr-Commit-Position: refs/heads/master@{#641514} -- wpt-commits: cecb3eba4dae3d795876f7b4be71bd49afa03356 wpt-pr: 15852
- Loading branch information
1 parent
7ce83e5
commit 43a34a8
Showing
4 changed files
with
243 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 55 additions & 30 deletions
85
...b-platform/tests/service-workers/service-worker/fetch-event-async-respond-with.https.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,61 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<title>respondWith cannot be called asynchronously</title> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="resources/test-helpers.sub.js"></script> | ||
<script> | ||
promise_test(function(t) { | ||
var script = 'resources/fetch-event-async-respond-with-worker.js'; | ||
var scope = 'resources/simple.html'; | ||
|
||
return service_worker_unregister_and_register(t, script, scope) | ||
.then(function(registration) { | ||
t.add_cleanup(function() { | ||
return service_worker_unregister(t, scope); | ||
}); | ||
|
||
return wait_for_state(t, registration.installing, 'activated'); | ||
}) | ||
.then(function() { | ||
return with_iframe(scope); | ||
}) | ||
.then(function(frame) { | ||
add_completion_callback(function() { frame.remove(); }); | ||
var channel = new MessageChannel(); | ||
var saw_message = new Promise(function(resolve) { | ||
channel.port1.onmessage = function(e) { resolve(e.data); } | ||
}); | ||
var worker = frame.contentWindow.navigator.serviceWorker.controller; | ||
|
||
worker.postMessage({port: channel.port2}, [channel.port2]); | ||
return saw_message; | ||
}) | ||
.then(function(message) { | ||
assert_equals(message, 'PASS'); | ||
}) | ||
}, 'Calling respondWith asynchronously throws an exception'); | ||
// This file has tests that call respondWith() asynchronously. | ||
|
||
let frame; | ||
let worker; | ||
const script = 'resources/fetch-event-async-respond-with-worker.js'; | ||
const scope = 'resources/simple.html'; | ||
|
||
// Global setup: this must be the first promise_test. | ||
promise_test(async (t) => { | ||
const registration = | ||
await service_worker_unregister_and_register(t, script, scope); | ||
worker = registration.installing; | ||
await wait_for_state(t, worker, 'activated'); | ||
frame = await with_iframe(scope); | ||
}, 'global setup'); | ||
|
||
// Does one test case. It fetches |url|. The service worker gets a fetch event | ||
// for |url| and attempts to call respondWith() asynchronously. It reports back | ||
// to the test whether an exception was thrown. | ||
async function do_test(url) { | ||
// Send a message to tell the worker a new test case is starting. | ||
const sawMessage = new Promise(resolve => { | ||
navigator.serviceWorker.onmessage = (event) => { | ||
resolve(event.data); | ||
}; | ||
worker.postMessage(''); | ||
}); | ||
|
||
// Start a fetch. | ||
frame.contentWindow.fetch(url); | ||
|
||
// Receive the test result from the service worker. | ||
return await sawMessage; | ||
}; | ||
|
||
promise_test(async (t) => { | ||
const result = await do_test('respondWith-in-task'); | ||
assert_true(result.didThrow, 'should throw'); | ||
assert_equals(result.error, 'InvalidStateError'); | ||
}, 'respondWith in a task throws InvalidStateError'); | ||
|
||
promise_test(async (t) => { | ||
const result = await do_test('respondWith-in-microtask'); | ||
assert_equals(result.didThrow, false, 'should not throw'); | ||
}, 'respondWith in a microtask does not throw'); | ||
|
||
// Global cleanup: the final promise_test. | ||
promise_test(async (t) => { | ||
if (frame) | ||
frame.remove(); | ||
await service_worker_unregister(t, scope); | ||
}, 'global cleanup'); | ||
</script> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.