-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathweak.ts
More file actions
46 lines (42 loc) · 1.35 KB
/
weak.ts
File metadata and controls
46 lines (42 loc) · 1.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* @fileoverview `memoizeWeak` — memoizer keyed by an object reference
* via `WeakMap`. Cache entries are eligible for GC as soon as the
* keying object becomes unreachable, so there's no need for explicit
* eviction. First (and only) argument must be an object.
*/
import { debugLog } from '../debug/output'
import { WeakMapCtor } from '../primordials/map-set'
/**
* Memoize with WeakMap for object keys.
* Allows garbage collection when objects are no longer referenced.
* Only works when first argument is an object.
*
* @param fn - Function to memoize
* @returns Memoized version using WeakMap
*
* @example
* import { memoizeWeak } from '@socketsecurity/lib/memo/weak'
*
* const processConfig = memoizeWeak((config: Config) => {
* return expensiveTransform(config)
* })
*
* processConfig(config1) // Computed
* processConfig(config1) // Cached
* // When config1 is no longer referenced, cache entry is GC'd
*/
export function memoizeWeak<K extends object, Result>(
fn: (key: K) => Result,
): (key: K) => Result {
const cache = new WeakMapCtor<K, Result>()
return function memoized(key: K): Result {
if (cache.has(key)) {
debugLog(`[memoizeWeak:${fn.name}] hit`)
return cache.get(key) as Result
}
debugLog(`[memoizeWeak:${fn.name}] miss`)
const result = fn(key)
cache.set(key, result)
return result
}
}