import { assertMethodDecorator } from "../common/decorators.js"; import type { Method } from "../common/types.js"; import { isWeakMapKey } from "../common/utils.js"; export function createDebouncedMethod( originalMethod: Method, delayMs: number, ): Method { let handler: ReturnType | undefined; return function(this: This, ...args: Args): void { if (handler !== undefined) { clearTimeout(handler); } handler = setTimeout(() => { originalMethod.apply(this, args); }, delayMs); }; } export function debounce(delayMs: number) { return function( value: Method, context: ClassMethodDecoratorContext>, ): Method { assertMethodDecorator("debounce", value, context); const methodsMap = new WeakMap>(); const fallbackMethod = createDebouncedMethod(value, delayMs); return function(this: This, ...args: Args): void { if (!isWeakMapKey(this)) { fallbackMethod.apply(this, args); return; } const instanceKey = this as object; if (!methodsMap.has(instanceKey)) { methodsMap.set(instanceKey, createDebouncedMethod(value, delayMs)); } methodsMap.get(instanceKey)?.apply(this, args); }; }; }