-
Notifications
You must be signed in to change notification settings - Fork 1
/
weak_value_map.ts
80 lines (67 loc) · 1.75 KB
/
weak_value_map.ts
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
export class WeakValueMap<K, V extends object> implements Map<K, V> {
#map = new Map<K, WeakRef<V>>();
#registry = new FinalizationRegistry<K>(this.#map.delete.bind(this.#map));
constructor(entries?: readonly (readonly [K, V])[] | null);
constructor(iterable: Iterable<readonly [K, V]>);
constructor(iterable?: Iterable<readonly [K, V]> | null) {
for (const [key, value] of iterable ?? []) {
this.set(key, value);
}
}
get size(): number {
return this.#map.size;
}
clear(): void {
for (const key of this.#map.keys()) {
this.delete(key);
}
}
delete(key: K): boolean {
const ref = this.#map.get(key);
if (ref) {
this.#map.delete(key);
this.#registry.unregister(ref);
return true;
}
return false;
}
get(key: K): V | undefined {
return this.#map.get(key)?.deref();
}
has(key: K): boolean {
return this.#map.has(key);
}
set(key: K, value: V): this {
const ref = new WeakRef(value);
this.#map.set(key, ref);
this.#registry.register(value, key, ref);
return this;
}
get [Symbol.toStringTag](): string {
return "WeakValueMap";
}
forEach(
callbackfn: (value: V, key: K, map: Map<K, V>) => void,
thisArg?: unknown,
): void {
for (const [key, value] of this[Symbol.iterator]()) {
callbackfn.call(thisArg, value, key, this);
}
}
*[Symbol.iterator](): IterableIterator<[K, V]> {
for (const [key, ref] of this.#map) {
yield [key, ref.deref()!];
}
}
entries(): IterableIterator<[K, V]> {
return this[Symbol.iterator]();
}
keys(): IterableIterator<K> {
return this.#map.keys();
}
*values(): IterableIterator<V> {
for (const ref of this.#map.values()) {
yield ref.deref()!;
}
}
}