packages/jsii-reflect/lib/_memoized.ts (54 lines of code) (raw):

import { TypeSystem } from './type-system'; const CACHE = new WeakMap<object, Map<string, unknown>>(); function memoizedGet(original: () => any, propertyKey: string): () => any { return function (this: object): unknown { let cache = CACHE.get(this); if (cache == null) { cache = new Map(); CACHE.set(this, cache); } if (cache.has(propertyKey)) { const result = cache.get(propertyKey); if (Array.isArray(result)) { // Return a copy of arrays as a precaution return Array.from(result); } return result; } const result = original.call(this); // If the result is an array, memoize a copy for safety. cache.set(propertyKey, Array.isArray(result) ? Array.from(result) : result); return result; }; } /** * Decorates property readers for readonly properties so that their results are * memoized in a `WeakMap`-based cache. Those properties will consequently be * computed exactly once. * * This can only be applied to property accessors (`public get foo(): any`), and not to * property declarations (`public readonly foo: any`). * * This should not be applied to any computations relying on a typesystem. * The typesystem can be changed and thus change the result of the call. * Use `memoizedWhenLocked` instead. */ export function memoized( _prototype: unknown, propertyKey: string, descriptor: PropertyDescriptor, ): void { if (!descriptor.get) { throw new Error(`@memoized can only be applied to property getters!`); } if (descriptor.set) { throw new Error(`@memoized can only be applied to readonly properties!`); } const original = descriptor.get; descriptor.get = memoizedGet(original, propertyKey); } export function memoizedWhenLocked<T extends { system: TypeSystem }>( _prototype: T, propertyKey: string, descriptor: PropertyDescriptor, ): void { if (!descriptor.get) { throw new Error(`@memoized can only be applied to property getters!`); } if (descriptor.set) { throw new Error(`@memoized can only be applied to readonly properties!`); } const original = descriptor.get; descriptor.get = function (this: T): unknown { if (this.system.isLocked) { return memoizedGet(original, propertyKey).call(this); } return original.call(this); }; }