diff --git a/packages/service-worker/worker/src/app-version.ts b/packages/service-worker/worker/src/app-version.ts index 1329c9aaf4..dafdcabfe0 100644 --- a/packages/service-worker/worker/src/app-version.ts +++ b/packages/service-worker/worker/src/app-version.ts @@ -15,6 +15,12 @@ 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. @@ -85,6 +91,10 @@ export class AppVersion implements UpdateSource { this.scope, this.adapter, config, this.database, `ngsw:${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); diff --git a/packages/service-worker/worker/test/happy_spec.ts b/packages/service-worker/worker/test/happy_spec.ts index d1278434bf..a4fba8680a 100644 --- a/packages/service-worker/worker/test/happy_spec.ts +++ b/packages/service-worker/worker/test/happy_spec.ts @@ -9,7 +9,7 @@ import {processNavigationUrls} from '../../config/src/generator'; import {CacheDatabase} from '../src/db-cache'; import {Driver, DriverReadyState} from '../src/driver'; -import {Manifest} from '../src/manifest'; +import {AssetGroupConfig, DataGroupConfig, Manifest} from '../src/manifest'; import {sha1} from '../src/sha1'; import {MockCache, clearAllCaches} from '../testing/cache'; import {MockRequest} from '../testing/fetch'; @@ -66,6 +66,24 @@ const brokenManifest: Manifest = { hashTable: tmpHashTableForFs(brokenFs, {'/foo.txt': true}), }; +// Manifest without navigation urls to test backward compatibility with +// versions < 6.0.0. +export 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, appData: { @@ -989,6 +1007,28 @@ const manifestUpdateHash = sha1(JSON.stringify(manifestUpdate)); expect(await requestFoo('only-if-cached', 'same-origin')).toBe('this is foo'); expect(await requestFoo('only-if-cached', 'no-cors')).toBeNull(); }); + + describe('Backwards compatibility with v5', () => { + beforeEach(() => { + const serverV5 = new MockServerStateBuilder() + .withStaticFiles(dist) + .withManifest(manifestOld) + .build(); + + scope = new SwTestHarnessBuilder().withServerState(serverV5).build(); + driver = new Driver(scope, scope, new CacheDatabase(scope, scope)); + }); + + // Test this bug: https://github.com/angular/angular/issues/27209 + async_it( + 'Fill 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); + }); + }); }); }); })();