fix: take over with the new build's service worker also when it was still installing #523

This commit is contained in:
Linus Rath
2026-11-01 12:56:28 +01:00
parent 46012f2b80
commit 0b51a06fbc
2 changed files with 20 additions and 6 deletions
+12
View File
@@ -83,4 +83,16 @@ describe('app update', () => {
adoptWaitingWorker({ waiting: other, addEventListener: () => {} } as unknown as ServiceWorkerRegistration);
expect(other.postMessage).not.toHaveBeenCalled();
});
it('also when the worker of this tab’s build was still installing', () => {
const listeners: Array<() => void> = [];
const installing = { scriptURL: 'https://mail.example.com/sw.js?v=build-a', state: 'installing', postMessage: vi.fn(), addEventListener: (_: string, fn: () => void) => listeners.push(fn) };
const registration = { waiting: null as unknown, installing, addEventListener: () => {} };
adoptWaitingWorker(registration as unknown as ServiceWorkerRegistration);
expect(installing.postMessage).not.toHaveBeenCalled();
installing.state = 'installed';
registration.waiting = installing;
listeners.forEach((fn) => fn());
expect(installing.postMessage).toHaveBeenCalledWith({ type: 'skip-waiting' });
});
});
+8 -6
View File
@@ -91,13 +91,15 @@ export function adoptWaitingWorker(registration: ServiceWorkerRegistration): voi
const adopt = () => {
if (ours(registration.waiting)) registration.waiting!.postMessage({ type: 'skip-waiting' });
};
adopt();
registration.addEventListener('updatefound', () => {
const installing = registration.installing;
installing?.addEventListener('statechange', () => {
if (installing.state === 'installed') adopt();
const watch = (worker: ServiceWorker | null) => {
worker?.addEventListener('statechange', () => {
if (worker.state === 'installed') adopt();
});
});
};
adopt();
// Still installing when the registration resolved, or installed later.
watch(registration.installing);
registration.addEventListener('updatefound', () => watch(registration.installing));
}
/** Tells the service worker which build this tab runs, so it keeps that build's files while the tab is open. */