interface WeakMapEntry { ref: WeakRef token: any } export class WeakRefSet implements Set { constructor(readonly onItemCleaned?: () => void) { this._registry = new FinalizationRegistry>(key => { this._set.delete(key) this.onItemCleaned?.() }) } private _set = new Set>() private _map = new WeakMap>() private _registry: FinalizationRegistry> get size() { return this._size() } [Symbol.toStringTag]: string = "[Object object]" protected _size() { return this._set.size } add(value: T): this { const entry: WeakMapEntry = { ref: new WeakRef(value), token: {} } this._set.add(entry.ref) this._map.set(value, entry) this._registry.register(value, entry.ref, entry.token) return this } clear(): void { this._set.clear() this._map = new WeakMap() } delete(value: T): boolean { const entry = this._map.get(value) if (!entry) { return false } this._map.delete(value) this._registry.unregister(entry.token) return this._set.delete(entry.ref) } forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void { for (let v of this.values()) { callbackfn.call(thisArg, v, v, this) } } has(value: T): boolean { return this._map.has(value) } *values(): IterableIterator { for (let v of this._set) { const ref = v.deref() if (ref == undefined) { continue } yield ref } } *entries(): IterableIterator<[T, T]> { for (let ref of this) { yield [ref, ref] } } *keys(): IterableIterator { yield* this } [Symbol.iterator]() { return this.values() } }