Asynchronous call of FetchEvent.respondWith silently fails
Categories
(Core :: DOM: Service Workers, defect)
Tracking
()
People
(Reporter: pigido6116, Unassigned, NeedInfo)
Details
Steps to reproduce:
In the latest Firefox Developer Edition (133.0b3), start a Service Worker which calls FetchEvent.respondWith asynchronously (example code below).
Actual results:
It failed silently. No error was raised.
Expected results:
It should have failed with an error message.
As far as I can tell, Service Worker spec defines that FetchEvent.respondWith cannot be called in an asynchronous context and if it is, it will release the thread. It's very confusing for the thread to be released silently because afterwards, the browser defaults to calling the internet directly and so it appears no different from normal.
In Chromium, the error thrown in this case is "InvalidStateError: Failed to execute 'respondWith' on 'FetchEvent': The event handler is already finished.".
Example Service Worker code for reproduction
self.addEventListener("install", async event => {
console.log("V1 installing…");
});
self.addEventListener("fetch", async event => {
console.log("fetching");
let exPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(true);
}, 0);
});
//await exPromise;
console.log("request", event.request);
let response;
if (event.request.url === "http://localhost:8000/blahblah") {
response = fetch("https://cdn.jwplayer.com/libraries/Xt5rBv5b.js");
} else {
response = fetch(event.request);
}
console.log("response", response);
event.respondWith(response);
});
self.addEventListener("activate", event => {
console.log("V1 now ready to handle fetches!");
event.waitUntil(self.clients.claim());
});
self.addEventListener("message", async event => {
console.log(event.data)
});
If fetch("blahblah")
is called in the client, the JavaScript library is fetched and returned as expected. Now, uncomment //await exPromise;
and fetch("blahblah")
will 404 because await releases the thread before the JavaScript library can be fetched and returned. This releasing of the thread is expected per Service Worker spec but Firefox releases the thread silently. Chromium will throw "InvalidStateError: Failed to execute 'respondWith' on 'FetchEvent': The event handler is already finished."
As you mentioned, this is expected behavior, covered by Web Platform Tests which all browsers currently pass: https://wpt.fyi/results/service-workers/service-worker/fetch-event-async-respond-with.https.html?label=master&label=experimental&aligned&q=fetch-event-async-respond-with.https.html
How did you check Firefox does not throw error here? Note that Firefox doesn't show console messages into usual devtools console tab right now, you may need to confirm by inspecting service worker separately in about:debugging.
Comment 4•16 days ago
|
||
Indeed we definitely throw consistent with the spec:
void FetchEvent::RespondWith(JSContext* aCx, Promise& aArg, ErrorResult& aRv) {
if (!GetDispatchFlag() || mWaitToRespond) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
Description
•