/
iterable_weak_map.js
86 lines (74 loc) Β· 2.01 KB
/
iterable_weak_map.js
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
81
82
83
84
85
86
'use strict';
const {
makeSafe,
Object,
SafeSet,
SafeWeakMap,
SymbolIterator,
} = primordials;
// TODO(aduh95): Add FinalizationRegistry to primordials
const SafeFinalizationRegistry = makeSafe(
globalThis.FinalizationRegistry,
class SafeFinalizationRegistry extends globalThis.FinalizationRegistry {}
);
// TODO(aduh95): Add WeakRef to primordials
const SafeWeakRef = makeSafe(
globalThis.WeakRef,
class SafeWeakRef extends globalThis.WeakRef {}
);
// This class is modified from the example code in the WeakRefs specification:
// https://github.com/tc39/proposal-weakrefs
// Licensed under ECMA's MIT-style license, see:
// https://github.com/tc39/ecma262/blob/master/LICENSE.md
class IterableWeakMap {
#weakMap = new SafeWeakMap();
#refSet = new SafeSet();
#finalizationGroup = new SafeFinalizationRegistry(cleanup);
set(key, value) {
const entry = this.#weakMap.get(key);
if (entry) {
// If there's already an entry for the object represented by "key",
// the value can be updated without creating a new WeakRef:
this.#weakMap.set(key, { value, ref: entry.ref });
} else {
const ref = new SafeWeakRef(key);
this.#weakMap.set(key, { value, ref });
this.#refSet.add(ref);
this.#finalizationGroup.register(key, {
set: this.#refSet,
ref
}, ref);
}
}
get(key) {
return this.#weakMap.get(key)?.value;
}
has(key) {
return this.#weakMap.has(key);
}
delete(key) {
const entry = this.#weakMap.get(key);
if (!entry) {
return false;
}
this.#weakMap.delete(key);
this.#refSet.delete(entry.ref);
this.#finalizationGroup.unregister(entry.ref);
return true;
}
*[SymbolIterator]() {
for (const ref of this.#refSet) {
const key = ref.deref();
if (!key) continue;
const { value } = this.#weakMap.get(key);
yield value;
}
}
}
function cleanup({ set, ref }) {
set.delete(ref);
}
Object.freeze(IterableWeakMap.prototype);
module.exports = {
IterableWeakMap,
};