| <!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> |
| // 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'); |
| |
| // Waits for a single message from the service worker and then removes the |
| // message handler. Not safe for concurrent use. |
| function wait_for_message() { |
| return new Promise((resolve) => { |
| const handler = (event) => { |
| navigator.serviceWorker.removeEventListener('message', handler); |
| resolve(event.data); |
| }; |
| navigator.serviceWorker.addEventListener('message', handler); |
| }); |
| } |
| |
| // 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 message = wait_for_message(); |
| worker.postMessage('initializeMessageHandler'); |
| const response = await message; |
| assert_equals(response, 'messageHandlerInitialized'); |
| |
| // Start a fetch. |
| const fetchPromise = frame.contentWindow.fetch(url); |
| |
| // Receive the test result from the service worker. |
| const result = wait_for_message(); |
| await fetchPromise.then(()=> {}, () => {}); |
| return result; |
| }; |
| |
| 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> |