Skip to content

Commit 6852b20

Browse files
committed
refactor: drop memoize
1 parent faac1a2 commit 6852b20

File tree

3 files changed

+159
-4
lines changed

3 files changed

+159
-4
lines changed

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
"@eslint/js": "^9.19.0",
3131
"@types/debug": "^4.1.7",
3232
"@types/estree": "^1.0.0",
33-
"@types/lodash-es": "^4.17.12",
3433
"@types/mocha": "^9.0.0",
3534
"@types/node": "^18.8.4",
3635
"@types/semver": "^7.3.12",
@@ -48,7 +47,6 @@
4847
"eslint-plugin-unicorn": "^57.0.0",
4948
"fs-extra": "^10.0.0",
5049
"jsonc-eslint-parser": "^2.0.3",
51-
"lodash-es": "^4.17.21",
5250
"mocha": "^9.1.3",
5351
"npm-run-all": "^4.1.5",
5452
"nyc": "^15.1.0",
@@ -84,7 +82,7 @@
8482
"watch:tsc": "tsc --module es2015 --watch",
8583
"watch:rollup": "wait-on .temp/index.js && rollup -c -o index.js --watch",
8684
"watch:test": "wait-on index.js && warun index.js \"test/*.js\" \"test/fixtures/ast/*/*.json\" \"test/fixtures/*\" --debounce 1000 --no-initial -- nyc mocha \"test/*.js\" --reporter dot --timeout 10000",
87-
"watch:update-ast": "wait-on index.js && warun index.js \"test/fixtures/ast/*/*.vue\" -- node scripts/update-fixtures-ast.js",
85+
"watch:update-ast": "wait-on index.js && warun index.js \"test/fixtures/ast/*/*.vue\" -- ts-node scripts/update-fixtures-ast.js",
8886
"watch:coverage-report": "wait-on coverage/lcov-report/index.html && opener coverage/lcov-report/index.html"
8987
},
9088
"repository": {

src/external/node-event-generator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import type EventEmitter from "events"
55
import type { ESQueryOptions, Selector } from "esquery"
66
import esquery from "esquery"
7-
import { memoize } from "lodash-es"
7+
import { memoize } from "../utils/memoize"
88
import { union, intersection } from "../utils/utils"
99
import type { Node } from "../ast/index"
1010

src/utils/memoize.ts

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/**
2+
* Creates a memoized version of the provided function. The memoized function caches
3+
* results based on the argument it receives, so if the same argument is passed again,
4+
* it returns the cached result instead of recomputing it.
5+
*
6+
* This function works with functions that take zero or just one argument. If your function
7+
* originally takes multiple arguments, you should refactor it to take a single object or array
8+
* that combines those arguments.
9+
*
10+
* If the argument is not primitive (e.g., arrays or objects), provide a
11+
* `getCacheKey` function to generate a unique cache key for proper caching.
12+
*
13+
* @template F - The type of the function to be memoized.
14+
* @param {F} fn - The function to be memoized. It should accept a single argument and return a value.
15+
* @param {MemoizeOptions<Parameters<F>[0], ReturnType<F>>} [options={}] - Optional configuration for the memoization.
16+
* @param {MemoizeCache<any, V>} [options.cache] - The cache object used to store results. Defaults to a new `Map`.
17+
* @param {(args: A) => unknown} [options.getCacheKey] - An optional function to generate a unique cache key for each argument.
18+
*
19+
* @returns The memoized function with an additional `cache` property that exposes the internal cache.
20+
*
21+
* @example
22+
* // Example using the default cache
23+
* const add = (x: number) => x + 10;
24+
* const memoizedAdd = memoize(add);
25+
*
26+
* console.log(memoizedAdd(5)); // 15
27+
* console.log(memoizedAdd(5)); // 15 (cached result)
28+
* console.log(memoizedAdd.cache.size); // 1
29+
*
30+
* @example
31+
* // Example using a custom resolver
32+
* const sum = (arr: number[]) => arr.reduce((x, y) => x + y, 0);
33+
* const memoizedSum = memoize(sum, { getCacheKey: (arr: number[]) => arr.join(',') });
34+
* console.log(memoizedSum([1, 2])); // 3
35+
* console.log(memoizedSum([1, 2])); // 3 (cached result)
36+
* console.log(memoizedSum.cache.size); // 1
37+
*
38+
* @example
39+
* // Example using a custom cache implementation
40+
* class CustomCache<K, T> implements MemoizeCache<K, T> {
41+
* private cache = new Map<K, T>();
42+
*
43+
* set(key: K, value: T): void {
44+
* this.cache.set(key, value);
45+
* }
46+
*
47+
* get(key: K): T | undefined {
48+
* return this.cache.get(key);
49+
* }
50+
*
51+
* has(key: K): boolean {
52+
* return this.cache.has(key);
53+
* }
54+
*
55+
* delete(key: K): boolean {
56+
* return this.cache.delete(key);
57+
* }
58+
*
59+
* clear(): void {
60+
* this.cache.clear();
61+
* }
62+
*
63+
* get size(): number {
64+
* return this.cache.size;
65+
* }
66+
* }
67+
* const customCache = new CustomCache<string, number>();
68+
* const memoizedSumWithCustomCache = memoize(sum, { cache: customCache });
69+
* console.log(memoizedSumWithCustomCache([1, 2])); // 3
70+
* console.log(memoizedSumWithCustomCache([1, 2])); // 3 (cached result)
71+
* console.log(memoizedAddWithCustomCache.cache.size); // 1
72+
*
73+
* MIT © Viva Republica, Inc. | https://es-toolkit.dev/
74+
*
75+
* The implementation is copied from es-toolkit package:
76+
* https://github.com/toss/es-toolkit/blob/16709839f131269b84cdd96e9645df52648ccedf/src/function/memoize.ts
77+
*/
78+
export function memoize<F extends (...args: any) => any>(
79+
fn: F,
80+
options: {
81+
cache?: MemoizeCache<any, ReturnType<F>>
82+
getCacheKey?: (args: Parameters<F>[0]) => unknown
83+
} = {},
84+
): F & { cache: MemoizeCache<any, ReturnType<F>> } {
85+
const { cache = new Map<unknown, ReturnType<F>>(), getCacheKey } = options
86+
87+
const memoizedFn = function (
88+
this: unknown,
89+
arg: Parameters<F>[0],
90+
): ReturnType<F> {
91+
const key = getCacheKey ? getCacheKey(arg) : arg
92+
93+
if (cache.has(key)) {
94+
return cache.get(key)!
95+
}
96+
97+
const result = fn.call(this, arg)
98+
99+
cache.set(key, result)
100+
101+
return result
102+
}
103+
104+
memoizedFn.cache = cache
105+
106+
return memoizedFn as F & { cache: MemoizeCache<any, ReturnType<F>> }
107+
}
108+
109+
/**
110+
* Represents a cache for memoization, allowing storage and retrieval of computed values.
111+
*
112+
* @template K - The type of keys used to store values in the cache.
113+
* @template V - The type of values stored in the cache.
114+
*/
115+
interface MemoizeCache<K, V> {
116+
/**
117+
* Stores a value in the cache with the specified key.
118+
*
119+
* @param key - The key to associate with the value.
120+
* @param value - The value to store in the cache.
121+
*/
122+
set(key: K, value: V): void
123+
124+
/**
125+
* Retrieves a value from the cache by its key.
126+
*
127+
* @param key - The key of the value to retrieve.
128+
* @returns The value associated with the key, or undefined if the key does not exist.
129+
*/
130+
get(key: K): V | undefined
131+
132+
/**
133+
* Checks if a value exists in the cache for the specified key.
134+
*
135+
* @param key - The key to check for existence in the cache.
136+
* @returns True if the cache contains the key, false otherwise.
137+
*/
138+
has(key: K): boolean
139+
140+
/**
141+
* Deletes a value from the cache by its key.
142+
*
143+
* @param key - The key of the value to delete.
144+
* @returns True if the value was successfully deleted, false otherwise.
145+
*/
146+
delete(key: K): boolean | void
147+
148+
/**
149+
* Clears all values from the cache.
150+
*/
151+
clear(): void
152+
153+
/**
154+
* The number of entries in the cache.
155+
*/
156+
size: number
157+
}

0 commit comments

Comments
 (0)