-
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.36 KB
/
weak.ts
File metadata and controls
46 lines (42 loc) · 1.36 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
/**
* @file `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.
*
* @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
*
* @param fn - Function to memoize.
*
* @returns Memoized version using WeakMap
*/
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
}
}