From ce916fe08c71ecfa3d2274bb528dbea6d40c8a76 Mon Sep 17 00:00:00 2001 From: arturovt Date: Fri, 2 May 2025 19:43:53 +0300 Subject: [PATCH] fix(service-worker): do not register service worker if app is destroyed before it is ready to register (#61101) In this commit, we check whether the application is destroyed before calling `serviceWorker.register(...)`. We should not register the worker because other resources will not be available. PR Close #61101 --- packages/service-worker/src/provider.ts | 13 ++++++++++--- packages/service-worker/test/provider_spec.ts | 11 +++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/service-worker/src/provider.ts b/packages/service-worker/src/provider.ts index 1cc28695db2..ca20ad30635 100644 --- a/packages/service-worker/src/provider.ts +++ b/packages/service-worker/src/provider.ts @@ -92,7 +92,14 @@ export function ngswAppInitializer(): void { // Don't return anything to avoid blocking the application until the SW is registered. // Catch and log the error if SW registration fails to avoid uncaught rejection warning. - readyToRegister.then(() => + readyToRegister.then(() => { + // If the registration strategy has resolved after the application has + // been explicitly destroyed by the user (e.g., by navigating away to + // another application), we simply should not register the worker. + if (appRef.destroyed) { + return; + } + navigator.serviceWorker .register(script, {scope: options.scope}) .catch((err) => @@ -103,8 +110,8 @@ export function ngswAppInitializer(): void { 'Service worker registration failed with: ' + err, ), ), - ), - ); + ); + }); }); } diff --git a/packages/service-worker/test/provider_spec.ts b/packages/service-worker/test/provider_spec.ts index fd0d11edcf9..867cb792c32 100644 --- a/packages/service-worker/test/provider_spec.ts +++ b/packages/service-worker/test/provider_spec.ts @@ -364,6 +364,17 @@ async function waitForReadyToRegister() { ); expect(swRegisterSpy).not.toHaveBeenCalled(); }); + + it('should not register service worker if app was destroyed before it was ready to register', async () => { + const registerSub = new Subject(); + configTestBedWithMockedStability(() => registerSub); + expect(swRegisterSpy).not.toHaveBeenCalled(); + // Given that the app is destroyed (e.g., by calling `ApplicationRef.destroy()`) + // before the `readyToRegister` promise resolves and `serviceWorker.register(...)` is called. + TestBed.resetTestingModule(); + await waitForReadyToRegister(); + expect(swRegisterSpy).not.toHaveBeenCalled(); + }); }); }); });