diff --git a/packages/service-worker/worker/src/adapter.ts b/packages/service-worker/worker/src/adapter.ts index cebad8aeef..5174ef670a 100644 --- a/packages/service-worker/worker/src/adapter.ts +++ b/packages/service-worker/worker/src/adapter.ts @@ -6,6 +6,9 @@ * found in the LICENSE file at https://angular.io/license */ +import {NormalizedUrl} from './api'; + + /** * Adapts the service worker to its runtime environment. * @@ -75,16 +78,10 @@ export class Adapter { * @param url The raw request URL. * @return A normalized representation of the URL. */ - normalizeUrl(url: string): string { + normalizeUrl(url: string): NormalizedUrl { // Check the URL's origin against the ServiceWorker's. const parsed = this.parseUrl(url, this.scopeUrl); - if (parsed.origin === this.origin) { - // The URL is relative to the SW's origin: Return the path only. - return parsed.path; - } else { - // The URL is not relative to the SW's origin: Return the full URL. - return url; - } + return (parsed.origin === this.origin ? parsed.path : url) as NormalizedUrl; } /** diff --git a/packages/service-worker/worker/src/api.ts b/packages/service-worker/worker/src/api.ts index def3794115..d597d75648 100644 --- a/packages/service-worker/worker/src/api.ts +++ b/packages/service-worker/worker/src/api.ts @@ -12,6 +12,18 @@ export enum UpdateCacheStatus { CACHED, } +/** + * A `string` representing a URL that has been normalized relative to an origin (usually that of the + * ServiceWorker). + * + * If the URL is relative to the origin, then it is representated by the path part only. Otherwise, + * the full URL is used. + * + * NOTE: A `string` is not assignable to a `NormalizedUrl`, but a `NormalizedUrl` is assignable to a + * `string`. + */ +export type NormalizedUrl = string&{_brand: 'normalizedUrl'}; + /** * A source for old versions of URL contents and other resources. * @@ -27,7 +39,7 @@ export interface UpdateSource { * If an old version of the resource doesn't exist, or exists but does * not match the hash given, this returns null. */ - lookupResourceWithHash(url: string, hash: string): Promise; + lookupResourceWithHash(url: NormalizedUrl, hash: string): Promise; /** * Lookup an older version of a resource for which the hash is not known. @@ -37,7 +49,7 @@ export interface UpdateSource { * `Response`, but the cache metadata needed to re-cache the resource in * a newer `AppVersion`. */ - lookupResourceWithoutHash(url: string): Promise; + lookupResourceWithoutHash(url: NormalizedUrl): Promise; /** * List the URLs of all of the resources which were previously cached. @@ -45,7 +57,7 @@ export interface UpdateSource { * This allows for the discovery of resources which are not listed in the * manifest but which were picked up because they matched URL patterns. */ - previouslyCachedResources(): Promise; + previouslyCachedResources(): Promise; /** * Check whether a particular resource exists in the most recent cache. diff --git a/packages/service-worker/worker/src/app-version.ts b/packages/service-worker/worker/src/app-version.ts index 01924454aa..a4c0cc9823 100644 --- a/packages/service-worker/worker/src/app-version.ts +++ b/packages/service-worker/worker/src/app-version.ts @@ -7,7 +7,7 @@ */ import {Adapter, Context} from './adapter'; -import {CacheState, UpdateCacheStatus, UpdateSource} from './api'; +import {CacheState, NormalizedUrl, UpdateCacheStatus, UpdateSource} from './api'; import {AssetGroup, LazyAssetGroup, PrefetchAssetGroup} from './assets'; import {DataGroup} from './data'; import {Database} from './database'; @@ -31,10 +31,9 @@ const BACKWARDS_COMPATIBILITY_NAVIGATION_URLS = [ */ export class AppVersion implements UpdateSource { /** - * A Map of absolute URL paths (/foo.txt) to the known hash of their - * contents (if available). + * A Map of absolute URL paths (`/foo.txt`) to the known hash of their contents (if available). */ - private hashTable = new Map(); + private hashTable = new Map(); /** * All of the asset groups active in this version of the app. @@ -218,7 +217,7 @@ export class AppVersion implements UpdateSource { /** * Check this version for a given resource with a particular hash. */ - async lookupResourceWithHash(url: string, hash: string): Promise { + async lookupResourceWithHash(url: NormalizedUrl, hash: string): Promise { // Verify that this version has the requested resource cached. If not, // there's no point in trying. if (!this.hashTable.has(url)) { @@ -238,7 +237,7 @@ export class AppVersion implements UpdateSource { /** * Check this version for a given resource regardless of its hash. */ - lookupResourceWithoutHash(url: string): Promise { + lookupResourceWithoutHash(url: NormalizedUrl): Promise { // Limit the search to asset groups, and only scan the cache, don't // load resources from the network. return this.assetGroups.reduce(async (potentialResponse, group) => { @@ -256,10 +255,10 @@ export class AppVersion implements UpdateSource { /** * List all unhashed resources from all asset groups. */ - previouslyCachedResources(): Promise { - return this.assetGroups.reduce(async (resources, group) => { - return (await resources).concat(await group.unhashedResources()); - }, Promise.resolve([])); + previouslyCachedResources(): Promise { + return this.assetGroups.reduce( + async (resources, group) => (await resources).concat(await group.unhashedResources()), + Promise.resolve([])); } async recentCacheStatus(url: string): Promise { diff --git a/packages/service-worker/worker/src/assets.ts b/packages/service-worker/worker/src/assets.ts index 4323c5400f..90e639d651 100644 --- a/packages/service-worker/worker/src/assets.ts +++ b/packages/service-worker/worker/src/assets.ts @@ -7,7 +7,7 @@ */ import {Adapter, Context} from './adapter'; -import {CacheState, UpdateCacheStatus, UpdateSource, UrlMetadata} from './api'; +import {CacheState, NormalizedUrl, UpdateCacheStatus, UpdateSource, UrlMetadata} from './api'; import {Database, Table} from './database'; import {errorToString, SwCriticalError} from './error'; import {IdleScheduler} from './idle'; @@ -29,7 +29,7 @@ export abstract class AssetGroup { /** * Normalized resource URLs. */ - protected urls: string[] = []; + protected urls: NormalizedUrl[] = []; /** * Regular expression patterns. @@ -266,7 +266,7 @@ export abstract class AssetGroup { /** * Lookup all resources currently stored in the cache which have no associated hash. */ - async unhashedResources(): Promise { + async unhashedResources(): Promise { const cache = await this.cache; // Start with the set of all cached requests. return (await cache.keys()) diff --git a/packages/service-worker/worker/src/driver.ts b/packages/service-worker/worker/src/driver.ts index e3585fee50..86c31d843d 100644 --- a/packages/service-worker/worker/src/driver.ts +++ b/packages/service-worker/worker/src/driver.ts @@ -7,7 +7,7 @@ */ import {Adapter} from './adapter'; -import {CacheState, Debuggable, DebugIdleState, DebugState, DebugVersion, UpdateCacheStatus, UpdateSource} from './api'; +import {CacheState, Debuggable, DebugIdleState, DebugState, DebugVersion, NormalizedUrl, UpdateCacheStatus, UpdateSource} from './api'; import {AppVersion} from './app-version'; import {Database} from './database'; import {DebugHandler} from './debug'; @@ -959,7 +959,7 @@ export class Driver implements Debuggable, UpdateSource { * Determine if a specific version of the given resource is cached anywhere within the SW, * and fetch it if so. */ - lookupResourceWithHash(url: string, hash: string): Promise { + lookupResourceWithHash(url: NormalizedUrl, hash: string): Promise { return Array // Scan through the set of all cached versions, valid or otherwise. It's safe to do such // lookups even for invalid versions as the cached version of a resource will have the @@ -981,13 +981,13 @@ export class Driver implements Debuggable, UpdateSource { }, Promise.resolve(null)); } - async lookupResourceWithoutHash(url: string): Promise { + async lookupResourceWithoutHash(url: NormalizedUrl): Promise { await this.initialized; const version = this.versions.get(this.latestHash!); return version ? version.lookupResourceWithoutHash(url) : null; } - async previouslyCachedResources(): Promise { + async previouslyCachedResources(): Promise { await this.initialized; const version = this.versions.get(this.latestHash!); return version ? version.previouslyCachedResources() : []; diff --git a/packages/service-worker/worker/testing/utils.ts b/packages/service-worker/worker/testing/utils.ts index 51be5b4a0d..761907eecf 100644 --- a/packages/service-worker/worker/testing/utils.ts +++ b/packages/service-worker/worker/testing/utils.ts @@ -6,6 +6,9 @@ * found in the LICENSE file at https://angular.io/license */ +import {NormalizedUrl} from '../src/api'; + + /** * Get a normalized representation of a URL relative to a provided base URL. * @@ -19,11 +22,11 @@ * (This is usually the ServiceWorker's origin or registration scope). * @return A normalized representation of the URL. */ -export function normalizeUrl(url: string, relativeTo: string): string { +export function normalizeUrl(url: string, relativeTo: string): NormalizedUrl { const {origin, path, search} = parseUrl(url, relativeTo); const {origin: relativeToOrigin} = parseUrl(relativeTo); - return (origin === relativeToOrigin) ? path + search : url; + return ((origin === relativeToOrigin) ? path + search : url) as NormalizedUrl; } /**