Skip to content

Commit

Permalink
feat(esl-utils): add ability check if the memoized property create a …
Browse files Browse the repository at this point in the history
…cache
  • Loading branch information
ala-n committed Aug 25, 2021
1 parent 420f8bc commit 81f2e02
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/modules/esl-utils/decorators/memoize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,12 @@ memoize.clear = function (target: any, property: string) {
if (typeof desc.value === 'function' && typeof desc.value.clear === 'function') return desc.value.clear();
if (Object.hasOwnProperty.call(target, property)) delete target[property];
};

/** Check if property has cache for the passed params */
memoize.has = function (target: any, property: string, ...params: any[]) {
const desc = getPropertyDescriptor(target, property);
if (!desc) return false;
if (typeof desc.get === 'function' && typeof (desc.get as any).has === 'function') return (desc.get as any).has(...params);
if (typeof desc.value === 'function' && typeof desc.value.has === 'function') return desc.value.has(...params);
return Object.hasOwnProperty.call(target, property);
};
12 changes: 12 additions & 0 deletions src/modules/esl-utils/decorators/test/memoize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ describe('common @memoize decorator test', () => {
expect(instance.test).toBe(NaN);
expect(fn).toBeCalledTimes(1);

expect(memoize.has(instance, 'test')).toBe(true);
memoize.clear(instance, 'test');
expect(memoize.has(instance, 'test')).toBe(false);

expect(instance.test).toBe(NaN);
expect(fn).toBeCalledTimes(2);
});
Expand All @@ -38,7 +41,10 @@ describe('common @memoize decorator test', () => {
expect(TestClass.test).toBe(NaN);
expect(fn).toBeCalledTimes(1);

expect(memoize.has(TestClass, 'test')).toBe(true);
memoize.clear(TestClass, 'test');
expect(memoize.has(TestClass, 'test')).toBe(false);

expect(TestClass.test).toBe(NaN);
expect(fn).toBeCalledTimes(2);
});
Expand All @@ -60,7 +66,10 @@ describe('common @memoize decorator test', () => {
expect(instance.test()).toBe('a');
expect(fn).toBeCalledTimes(1);

expect(memoize.has(instance, 'test')).toBe(true);
memoize.clear(instance, 'test');
expect(memoize.has(instance, 'test')).toBe(false);

expect(instance.test()).toBe('a');
expect(instance.test()).toBe('a');
expect(fn).toBeCalledTimes(2);
Expand All @@ -82,7 +91,10 @@ describe('common @memoize decorator test', () => {
expect(TestClass.test()).toBe('a');
expect(fn).toBeCalledTimes(1);

expect(memoize.has(TestClass, 'test')).toBe(true);
memoize.clear(TestClass, 'test');
expect(memoize.has(TestClass, 'test')).toBe(false);

expect(TestClass.test()).toBe('a');
expect(TestClass.test()).toBe('a');
expect(fn).toBeCalledTimes(2);
Expand Down
6 changes: 6 additions & 0 deletions src/modules/esl-utils/misc/memoize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export type MemoizedFn<T extends AnyToAnyFnSignature> = T & {
cache: Map<null | string, ReturnType<T>>;
/** Clear memoization cache */
clear: () => void;
/** Check existence of cache fore passed params */
has: (...params: Parameters<T>) => boolean;
};

/**
Expand All @@ -28,6 +30,10 @@ export function memoizeFn<F extends AnyToAnyFnSignature>(fn: F, hashFn: MemoHash

memo.cache = new Map<null | string, ReturnType<F>>();
memo.clear = () => memo.cache.clear();
memo.has = (...args: Parameters<F>) => {
const key = hashFn(...args);
return key === undefined ? false : memo.cache.has(key);
};
return memo as MemoizedFn<F>;
}

Expand Down
11 changes: 11 additions & 0 deletions src/modules/esl-utils/misc/test/memoize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ describe('misc/memoize', () => {
expect(memoFn()).toBe(null);
expect(memoFn()).toBe(null);
expect(fn).toBeCalledTimes(1);
expect(memoFn.has()).toBe(true);

memoFn.clear();
fn.mockReturnValue(1);
expect(memoFn.has()).toBe(false);
expect(memoFn()).toBe(1);
expect(memoFn()).toBe(1);
expect(memoFn.has()).toBe(true);
expect(fn).toBeCalledTimes(2);
});

Expand All @@ -22,9 +25,12 @@ describe('misc/memoize', () => {
expect(memoFn(1)).toBe(2);
expect(memoFn(1)).toBe(2);
expect(fn).toBeCalledTimes(1);
expect(memoFn.has(1)).toBe(true);
expect(memoFn.has(2)).toBe(false);

expect(memoFn(2)).toBe(3);
expect(memoFn(2)).toBe(3);
expect(memoFn.has(2)).toBe(true);
expect(fn).toBeCalledTimes(2);
});

Expand All @@ -34,6 +40,9 @@ describe('misc/memoize', () => {
expect(memoFn(1, 2)).toBe(3);
expect(memoFn(1, 1)).toBe(2);
expect(memoFn(1, 2)).toBe(3);
expect(memoFn.has(1, 1)).toBe(true);
expect(memoFn.has(1, 2)).toBe(true);
expect(memoFn.has(1, 3)).toBe(false);
expect(fn).toBeCalledTimes(2);
expect(memoFn(1, 1)).toBe(2);
expect(fn).toBeCalledTimes(2);
Expand All @@ -46,6 +55,8 @@ describe('misc/memoize', () => {
expect(memoFn(1, 2)).toBe(3);
expect(memoFn(1, 1)).toBe(2);
expect(memoFn(1, 2)).toBe(3);
expect(memoFn.has(1, 1)).toBe(false);
expect(memoFn.has(1, 2)).toBe(false);
expect(fn).toBeCalledTimes(3);
});
});

0 comments on commit 81f2e02

Please sign in to comment.