Skip to content

Commit

Permalink
refactor(service-worker): remove backward compatibility code (angular…
Browse files Browse the repository at this point in the history
…#51246)

Remove backward compatibility code from service worker package.

Fixes angular#43403

PR Close angular#51246
  • Loading branch information
jsaguet authored and devversion committed Oct 9, 2024
1 parent 66cca86 commit 95bee15
Show file tree
Hide file tree
Showing 3 changed files with 1 addition and 155 deletions.
10 changes: 0 additions & 10 deletions packages/service-worker/worker/src/app-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ import {DebugHandler} from './debug';
import {IdleScheduler} from './idle';
import {Manifest} from './manifest';

const BACKWARDS_COMPATIBILITY_NAVIGATION_URLS = [
{positive: true, regex: '^/.*$'},
{positive: false, regex: '^/.*\\.[^/]*$'},
{positive: false, regex: '^/.*__'},
];

/**
* A specific version of the application, identified by a unique manifest
* as determined by its hash.
Expand Down Expand Up @@ -115,10 +109,6 @@ export class AppVersion implements UpdateSource {
new DataGroup(scope, adapter, config, database, debugHandler, `${config.version}:data`),
);

// This keeps backwards compatibility with app versions without navigation urls.
// Fix: https://github.com/angular/angular/issues/27209
manifest.navigationUrls = manifest.navigationUrls || BACKWARDS_COMPATIBILITY_NAVIGATION_URLS;

// Create `include`/`exclude` RegExps for the `navigationUrls` declared in the manifest.
const includeUrls = manifest.navigationUrls.filter((spec) => spec.positive);
const excludeUrls = manifest.navigationUrls.filter((spec) => !spec.positive);
Expand Down
29 changes: 0 additions & 29 deletions packages/service-worker/worker/src/driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,20 +163,6 @@ export class Driver implements Debuggable, UpdateSource {
// As above, it's safe to take over from existing clients immediately, since the new SW
// version will continue to serve the old application.
await this.scope.clients.claim();

// Once all clients have been taken over, we can delete caches used by old versions of
// `@angular/service-worker`, which are no longer needed. This can happen in the background.
this.idle.schedule('activate: cleanup-old-sw-caches', async () => {
try {
await this.cleanupOldSwCaches();
} catch (err) {
// Nothing to do - cleanup failed. Just log it.
this.debugger.log(
err as Error,
'cleanupOldSwCaches @ activate: cleanup-old-sw-caches',
);
}
});
})(),
);

Expand Down Expand Up @@ -1038,21 +1024,6 @@ export class Driver implements Debuggable, UpdateSource {
}
}

/**
* Delete caches that were used by older versions of `@angular/service-worker` to avoid running
* into storage quota limitations imposed by browsers.
* (Since at this point the SW has claimed all clients, it is safe to remove those caches.)
*/
async cleanupOldSwCaches(): Promise<void> {
// This is an exceptional case, where we need to interact with caches that would not be
// generated by this ServiceWorker (but by old versions of it). Use the native `CacheStorage`
// directly.
const caches = this.adapter.caches.original;
const cacheNames = await caches.keys();
const oldSwCacheNames = cacheNames.filter((name) => /^ngsw:(?!\/)/.test(name));
await Promise.all(oldSwCacheNames.map((name) => caches.delete(name)));
}

/**
* Determine if a specific version of the given resource is cached anywhere within the SW,
* and fetch it if so.
Expand Down
117 changes: 1 addition & 116 deletions packages/service-worker/worker/test/happy_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import {processNavigationUrls} from '../../config/src/generator';
import {CacheDatabase} from '../src/db-cache';
import {Driver, DriverReadyState} from '../src/driver';
import {AssetGroupConfig, DataGroupConfig, Manifest} from '../src/manifest';
import {Manifest} from '../src/manifest';
import {sha1} from '../src/sha1';
import {clearAllCaches, MockCache} from '../testing/cache';
import {MockWindowClient} from '../testing/clients';
Expand Down Expand Up @@ -115,24 +115,6 @@ import {envIsSupported} from '../testing/utils';
hashTable: tmpHashTableForFs(brokenFs, {'/bar.txt': true}),
};

// Manifest without navigation urls to test backward compatibility with
// versions < 6.0.0.
interface ManifestV5 {
configVersion: number;
appData?: {[key: string]: string};
index: string;
assetGroups?: AssetGroupConfig[];
dataGroups?: DataGroupConfig[];
hashTable: {[url: string]: string};
}

// To simulate versions < 6.0.0
const manifestOld: ManifestV5 = {
configVersion: 1,
index: '/foo.txt',
hashTable: tmpHashTableForFs(dist),
};

const manifest: Manifest = {
configVersion: 1,
timestamp: 1234567890123,
Expand Down Expand Up @@ -293,36 +275,6 @@ import {envIsSupported} from '../testing/utils';
expect(claimSpy).toHaveBeenCalledTimes(1);
});

it('cleans up old `@angular/service-worker` caches, after activation', async () => {
const claimSpy = spyOn(scope.clients, 'claim');
const cleanupOldSwCachesSpy = spyOn(driver, 'cleanupOldSwCaches');

// Automatically advance time to trigger idle tasks as they are added.
scope.autoAdvanceTime = true;
await scope.startup(true);
await scope.resolveSelfMessages();
scope.autoAdvanceTime = false;

expect(cleanupOldSwCachesSpy).toHaveBeenCalledTimes(1);
expect(claimSpy).toHaveBeenCalledBefore(cleanupOldSwCachesSpy);
});

it('does not blow up if cleaning up old `@angular/service-worker` caches fails', async () => {
spyOn(driver, 'cleanupOldSwCaches').and.callFake(() => Promise.reject('Ooops'));

// Automatically advance time to trigger idle tasks as they are added.
scope.autoAdvanceTime = true;
await scope.startup(true);
await scope.resolveSelfMessages();
scope.autoAdvanceTime = false;

server.clearRequests();

expect(driver.state).toBe(DriverReadyState.NORMAL);
expect(await makeRequest(scope, '/foo.txt')).toBe('this is foo');
server.assertNoOtherRequests();
});

it('initializes prefetched content correctly, after activation', async () => {
// Automatically advance time to trigger idle tasks as they are added.
scope.autoAdvanceTime = true;
Expand Down Expand Up @@ -2029,53 +1981,6 @@ import {envIsSupported} from '../testing/utils';
});
});

describe('cleanupOldSwCaches()', () => {
it('should delete the correct caches', async () => {
const oldSwCacheNames = [
// Example cache names from the beta versions of `@angular/service-worker`.
'ngsw:active',
'ngsw:staged',
'ngsw:manifest:a1b2c3:super:duper',
// Example cache names from the beta versions of `@angular/service-worker`.
'ngsw:a1b2c3:assets:foo',
'ngsw:db:a1b2c3:assets:bar',
];
const otherCacheNames = [
'ngsuu:active',
'not:ngsw:active',
'NgSw:StAgEd',
'ngsw:/:db:control',
'ngsw:/foo/:active',
'ngsw:/bar/:staged',
];
const allCacheNames = oldSwCacheNames.concat(otherCacheNames);

await Promise.all(allCacheNames.map((name) => scope.caches.original.open(name)));
expect(await scope.caches.original.keys()).toEqual(
jasmine.arrayWithExactContents(allCacheNames),
);

await driver.cleanupOldSwCaches();
expect(await scope.caches.original.keys()).toEqual(
jasmine.arrayWithExactContents(otherCacheNames),
);
});

it('should delete other caches even if deleting one of them fails', async () => {
const oldSwCacheNames = ['ngsw:active', 'ngsw:staged', 'ngsw:manifest:a1b2c3:super:duper'];
const deleteSpy = spyOn(scope.caches.original, 'delete').and.callFake((cacheName: string) =>
Promise.reject(`Failed to delete cache '${cacheName}'.`),
);

await Promise.all(oldSwCacheNames.map((name) => scope.caches.original.open(name)));
const error = await driver.cleanupOldSwCaches().catch((err) => err);

expect(error).toBe("Failed to delete cache 'ngsw:active'.");
expect(deleteSpy).toHaveBeenCalledTimes(3);
oldSwCacheNames.forEach((name) => expect(deleteSpy).toHaveBeenCalledWith(name));
});
});

describe('bugs', () => {
it('does not crash with bad index hash', async () => {
scope = new SwTestHarnessBuilder().withServerState(brokenServer).build();
Expand Down Expand Up @@ -2610,26 +2515,6 @@ import {envIsSupported} from '../testing/utils';
expect(driver.state).toEqual(DriverReadyState.EXISTING_CLIENTS_ONLY);
});
});

describe('backwards compatibility with v5', () => {
beforeEach(() => {
const serverV5 = new MockServerStateBuilder()
.withStaticFiles(dist)
.withManifest(<Manifest>manifestOld)
.build();

scope = new SwTestHarnessBuilder().withServerState(serverV5).build();
driver = new Driver(scope, scope, new CacheDatabase(scope));
});

// Test this bug: https://github.com/angular/angular/issues/27209
it('fills previous versions of manifests with default navigation urls for backwards compatibility', async () => {
expect(await makeRequest(scope, '/foo.txt')).toEqual('this is foo');
await driver.initialized;
scope.updateServerState(serverUpdate);
expect(await driver.checkForUpdate()).toEqual(true);
});
});
});

describe('navigationRequestStrategy', () => {
Expand Down

0 comments on commit 95bee15

Please sign in to comment.