import { Reflect } from '../../utils/reflect'; import type { IsEqualFn } from './areArgsEqual'; type MemoizeCache = { lastArgs: Args; lastResult: Return; }; export function modernDecorator( target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext Return>, isEqual: IsEqualFn, ): (this: This, ...args: Args) => Return { const propertyKey = String(context.name); const cacheKey = `memoized_${propertyKey}`; function replacementMethod(this: This, ...args: Args): Return { const cache = Reflect.getMetadata(cacheKey, this) as MemoizeCache | undefined; if (cache && isEqual(args, cache.lastArgs)) { return cache.lastResult; } const result = target.call(this, ...args); Reflect.defineMetadata(cacheKey, { lastArgs: args, lastResult: result }, this); return result; } return replacementMethod; }