This repository has been archived by the owner on Jan 25, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 41
WeakKeySet: a Set that holds its elements weakly
Mark S. Miller edited this page Feb 22, 2018
·
6 revisions
The following code implements the Set
API, including enumeration, and thus makes visible the non-determinism of garbage collection.
In the following code, NULL
stands for either null
or undefined
depending on
https://github.com/tc39/proposal-weakrefs/issues/25
function makeDerefIterator(refIter, isPair = false) {
return {
next() {
while (true) {
const refResult = refIter.next();
if (refResult.done) {
return refResult;
}
let value = refResult.value.deref();
if (value !== NULL) {
if (isPair) {
value = [value, value];
}
return { value, done: false };
}
}
},
[Symbol.toStringTag]: 'WeakKeySet Iterator'
};
}
/**
* Set API, but does not inherit from Set
*/
class WeakKeySet {
#wm = undefined;
#group = undefined;
#refSet = undefined;
#init() {
this.#wm = new WeakMap();
const refSet = new Set();
this.#group = new WeakRefGroup(iter => {
for (const wr of iter) {
refSet.delete(wr);
}
});
this.#refSet = refSet;
}
constructor(opt_iterable = undefined) {
this.#init();
if (opt_iterable) {
for (const k of opt_iterable) {
this.add(k);
}
}
}
static get [Symbol.species]() { return this; }
has(k) { return this.#wm.has(k); }
add(k) {
if (!this.#wm.has(k)) {
const wr = this.#group.makeRef(k, undefined);
this.#wm.set(k, wr);
this.#refSet.add(wr);
}
return this;
}
delete(k) {
const wr = this.#wm.get(k);
this.#wm.delete(k);
return this.#refMap.delete(wr);
}
clear() {
this.#group.shutdown();
this.#refSet.clear();
this.#init();
}
values() {
const refIter = this.#refSet[Symbol.iterator]();
return makeDerefIterator(refIter);
}
entries() {
const refIter = this.#refSet[Symbol.iterator]();
return makeDerefIterator(refIter, true);
}
forEach(callback, thisArg = undefined) {
for (const e of this) {
callback.call(thisArg, e, e, this);
}
}
get size() {
let count = 0;
for (const e of this) {
count++;
}
return count;
}
}
WeakKeySet.prototype[Symbol.iterator] =
WeakKeySet.prototype.keys =
WeakKeySet.prototype.values;
WeakKeySet.prototype[Symbol.toStringTag] = 'WeakKeySet';