refactor(ngcc): use a special map for memoizing expensive-to-compute values (#34512)

Previously, in cases were values were expensive to compute and would be
used multiple times, a combination of a regular `Map` and a helper
function (`getOrDefault()`) was used to ensure values were only computed
once.

This commit uses a special `Map`-like structure to compute and memoize
such expensive values without the need to a helper function.

PR Close #34512
This commit is contained in:
George Kalpakas
2019-12-25 02:10:01 +02:00
committed by Alex Rickabaugh
parent 6606ce69f6
commit c38195f59e
4 changed files with 117 additions and 76 deletions

View File

@ -66,13 +66,6 @@ export function findAll<T>(node: ts.Node, test: (node: ts.Node) => node is ts.No
}
}
export function getOrDefault<K, V>(map: Map<K, V>, key: K, factory: (key: K) => V): V {
if (!map.has(key)) {
map.set(key, factory(key));
}
return map.get(key) !;
}
/**
* Does the given declaration have a name which is an identifier?
* @param declaration The declaration to test.
@ -98,6 +91,33 @@ export function isRelativePath(path: string): boolean {
return /^\/|^\.\.?($|\/)/.test(path);
}
/**
* A `Map`-like object that can compute and memoize a missing value for any key.
*
* The computed values are memoized, so the factory function is not called more than once per key.
* This is useful for storing values that are expensive to compute and may be used multiple times.
*/
// NOTE:
// Ideally, this class should extend `Map`, but that causes errors in ES5 transpiled code:
// `TypeError: Constructor Map requires 'new'`
export class FactoryMap<K, V> {
private internalMap: Map<K, V>;
constructor(private factory: (key: K) => V, entries?: readonly(readonly[K, V])[]|null) {
this.internalMap = new Map(entries);
}
get(key: K): V {
if (!this.internalMap.has(key)) {
this.internalMap.set(key, this.factory(key));
}
return this.internalMap.get(key) !;
}
set(key: K, value: V): void { this.internalMap.set(key, value); }
}
/**
* Attempt to resolve a `path` to a file by appending the provided `postFixes`
* to the `path` and checking if the file exists on disk.