Skip to content

Instantly share code, notes, and snippets.

@dsherret
Last active September 27, 2018 23:53
Show Gist options
  • Save dsherret/dde191b7a68c19c14155def5b157fe51 to your computer and use it in GitHub Desktop.
Save dsherret/dde191b7a68c19c14155def5b157fe51 to your computer and use it in GitHub Desktop.
A weak cache with support for ES5.
export class WeakCache<T extends object, U> {
private readonly cacheItems: WeakDictionary<T, U>;
constructor() {
if (typeof WeakMap !== "undefined")
this.cacheItems = new WeakMap<T, U>();
else
this.cacheItems = new Es5WeakMap();
}
getOrCreate<TCreate extends U = U>(key: T, createFunc: () => TCreate) {
let item = this.get(key) as TCreate;
if (item == null) {
item = createFunc();
this.set(key, item);
}
return item;
}
has(key: T) {
return this.cacheItems.has(key);
}
get(key: T) {
return this.cacheItems.get(key);
}
set(key: T, value: U) {
this.cacheItems.set(key, value);
}
removeByKey(key: T) {
this.cacheItems.delete(key);
}
}
export interface WeakDictionary<K extends object, V> {
get(key: K): V | undefined;
set(key: K, value: V): void;
has(key: K): boolean;
delete(key: K): void;
}
export class Es5WeakMap<K extends object, V> implements WeakDictionary<K, V> {
private propSaver = new Es5PropSaver<K, V>();
get(key: K) {
return this.propSaver.get(key);
}
set(key: K, value: V) {
this.propSaver.set(key, value);
}
has(key: K) {
return this.propSaver.get(key) != null;
}
delete(key: K) {
this.propSaver.remove(key);
}
}
export class Es5PropSaver<TObject, TValue> {
private readonly propName = `__key_${Es5PropSaver.instanceCount++}`;
private static instanceCount = 0;
get(obj: TObject) {
return (obj as any)[this.propName] as TValue | undefined;
}
set(obj: TObject, value: TValue) {
Object.defineProperty(obj, this.propName, {
configurable: true,
enumerable: false,
writable: false,
value
});
}
remove(obj: TObject) {
delete (obj as any)[this.propName];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment