feat(lib/es2021): Add type parameter to FinalizationRegistry (#42274)

* feat(lib/es2021): Add type parameter to `FinalizationRegistry`

* test(lib/es2021): Add test for generic `FinalizationRegistry`
This commit is contained in:
ExE Boss 2021-02-19 01:43:36 +01:00 committed by GitHub
parent 9950b6e596
commit 0723904bfb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 1042 additions and 5 deletions

View file

@ -15,12 +15,12 @@ interface WeakRefConstructor {
* Creates a WeakRef instance for the given target object.
* @param target The target object for the WeakRef instance.
*/
new<T extends object>(target?: T): WeakRef<T>;
new<T extends object>(target: T): WeakRef<T>;
}
declare var WeakRef: WeakRefConstructor;
interface FinalizationRegistry {
interface FinalizationRegistry<T> {
readonly [Symbol.toStringTag]: "FinalizationRegistry";
/**
@ -32,7 +32,7 @@ interface FinalizationRegistry {
* object. If provided (and not undefined), this must be an object. If not provided, the target
* cannot be unregistered.
*/
register(target: object, heldValue: any, unregisterToken?: object): void;
register(target: object, heldValue: T, unregisterToken?: object): void;
/**
* Unregisters an object from the registry.
@ -43,13 +43,13 @@ interface FinalizationRegistry {
}
interface FinalizationRegistryConstructor {
readonly prototype: FinalizationRegistry;
readonly prototype: FinalizationRegistry<any>;
/**
* Creates a finalization registry with an associated cleanup callback
* @param cleanupCallback The callback to call after an object in the registry has been reclaimed.
*/
new(cleanupCallback: (heldValue: any) => void): FinalizationRegistry;
new<T>(cleanupCallback: (heldValue: T) => void): FinalizationRegistry<T>;
}
declare var FinalizationRegistry: FinalizationRegistryConstructor;

View file

@ -0,0 +1,189 @@
//// [esNextWeakRefs_IterableWeakMap.ts]
/** `static #cleanup` */
const IterableWeakMap_cleanup = ({ ref, set }: {
readonly ref: WeakRef<object>;
readonly set: Set<WeakRef<object>>;
}) => {
set.delete(ref);
};
// Based on: https://github.com/tc39/proposal-weakrefs/blob/master/README.md#iterable-weakmaps
export class IterableWeakMap<K extends object, V> implements WeakMap<K, V> {
declare readonly [Symbol.toStringTag]: "IterableWeakMap";
#weakMap = new WeakMap<K, { readonly ref: WeakRef<K>; value: V }>();
#refSet = new Set<WeakRef<K>>();
#finalizationGroup = new FinalizationRegistry(IterableWeakMap_cleanup);
constructor(iterable: Iterable<[key: K, value: V]> | null = null) {
if (iterable !== null) {
for (const { 0: key, 1: value } of iterable) {
this.set(key, value);
}
}
}
set(key: K, value: V): this {
const entry = this.#weakMap.get(key);
if (entry !== undefined) {
entry.value = value;
} else {
const ref = new WeakRef(key);
this.#weakMap.set(key, { ref, value });
this.#refSet.add(ref);
this.#finalizationGroup.register(key, {
set: this.#refSet,
ref,
}, ref);
}
return this;
}
has(key: K): boolean {
return this.#weakMap.has(key);
}
get(key: K): V | undefined {
return this.#weakMap.get(key)?.value;
}
delete(key: K): boolean {
const entry = this.#weakMap.get(key);
if (entry === undefined) {
return false;
}
const { ref } = entry;
this.#weakMap.delete(key);
this.#refSet.delete(ref);
this.#finalizationGroup.unregister(ref);
return true;
}
declare [Symbol.iterator]: this["entries"];
*entries(): Generator<[key: K, value: V], void> {
for (const ref of this.#refSet) {
const key = ref.deref();
if (key === undefined) continue;
const { value } = this.#weakMap.get(key)!;
yield [key, value];
}
}
*keys() {
for (const { 0: key } of this) {
yield key;
}
}
*values() {
for (const { 1: value } of this) {
yield value;
}
}
}
Object.defineProperties(IterableWeakMap.prototype, {
[Symbol.iterator]: {
configurable: true,
enumerable: false,
writable: true,
value: Object.getOwnPropertyDescriptor(
IterableWeakMap.prototype,
"entries",
)!.value,
},
[Symbol.toStringTag]: {
configurable: true,
enumerable: false,
writable: false,
value: "IterableWeakMap",
},
});
//// [esNextWeakRefs_IterableWeakMap.js]
/** `static #cleanup` */
const IterableWeakMap_cleanup = ({ ref, set }) => {
set.delete(ref);
};
// Based on: https://github.com/tc39/proposal-weakrefs/blob/master/README.md#iterable-weakmaps
export class IterableWeakMap {
#weakMap = new WeakMap();
#refSet = new Set();
#finalizationGroup = new FinalizationRegistry(IterableWeakMap_cleanup);
constructor(iterable = null) {
if (iterable !== null) {
for (const { 0: key, 1: value } of iterable) {
this.set(key, value);
}
}
}
set(key, value) {
const entry = this.#weakMap.get(key);
if (entry !== undefined) {
entry.value = value;
}
else {
const ref = new WeakRef(key);
this.#weakMap.set(key, { ref, value });
this.#refSet.add(ref);
this.#finalizationGroup.register(key, {
set: this.#refSet,
ref,
}, ref);
}
return this;
}
has(key) {
return this.#weakMap.has(key);
}
get(key) {
return this.#weakMap.get(key)?.value;
}
delete(key) {
const entry = this.#weakMap.get(key);
if (entry === undefined) {
return false;
}
const { ref } = entry;
this.#weakMap.delete(key);
this.#refSet.delete(ref);
this.#finalizationGroup.unregister(ref);
return true;
}
*entries() {
for (const ref of this.#refSet) {
const key = ref.deref();
if (key === undefined)
continue;
const { value } = this.#weakMap.get(key);
yield [key, value];
}
}
*keys() {
for (const { 0: key } of this) {
yield key;
}
}
*values() {
for (const { 1: value } of this) {
yield value;
}
}
}
Object.defineProperties(IterableWeakMap.prototype, {
[Symbol.iterator]: {
configurable: true,
enumerable: false,
writable: true,
value: Object.getOwnPropertyDescriptor(IterableWeakMap.prototype, "entries").value,
},
[Symbol.toStringTag]: {
configurable: true,
enumerable: false,
writable: false,
value: "IterableWeakMap",
},
});

View file

@ -0,0 +1,358 @@
=== tests/cases/compiler/esNextWeakRefs_IterableWeakMap.ts ===
/** `static #cleanup` */
const IterableWeakMap_cleanup = ({ ref, set }: {
>IterableWeakMap_cleanup : Symbol(IterableWeakMap_cleanup, Decl(esNextWeakRefs_IterableWeakMap.ts, 1, 5))
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 1, 34))
>set : Symbol(set, Decl(esNextWeakRefs_IterableWeakMap.ts, 1, 39))
readonly ref: WeakRef<object>;
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 1, 48))
>WeakRef : Symbol(WeakRef, Decl(lib.esnext.weakref.d.ts, --, --), Decl(lib.esnext.weakref.d.ts, --, --))
readonly set: Set<WeakRef<object>>;
>set : Symbol(set, Decl(esNextWeakRefs_IterableWeakMap.ts, 2, 34))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>WeakRef : Symbol(WeakRef, Decl(lib.esnext.weakref.d.ts, --, --), Decl(lib.esnext.weakref.d.ts, --, --))
}) => {
set.delete(ref);
>set.delete : Symbol(Set.delete, Decl(lib.es2015.collection.d.ts, --, --))
>set : Symbol(set, Decl(esNextWeakRefs_IterableWeakMap.ts, 1, 39))
>delete : Symbol(Set.delete, Decl(lib.es2015.collection.d.ts, --, --))
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 1, 34))
};
// Based on: https://github.com/tc39/proposal-weakrefs/blob/master/README.md#iterable-weakmaps
export class IterableWeakMap<K extends object, V> implements WeakMap<K, V> {
>IterableWeakMap : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))
>V : Symbol(V, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 46))
>WeakMap : Symbol(WeakMap, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))
>V : Symbol(V, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 46))
declare readonly [Symbol.toStringTag]: "IterableWeakMap";
>[Symbol.toStringTag] : Symbol(IterableWeakMap[Symbol.toStringTag], Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 76))
>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
#weakMap = new WeakMap<K, { readonly ref: WeakRef<K>; value: V }>();
>#weakMap : Symbol(IterableWeakMap.#weakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 10, 61))
>WeakMap : Symbol(WeakMap, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 31))
>WeakRef : Symbol(WeakRef, Decl(lib.esnext.weakref.d.ts, --, --), Decl(lib.esnext.weakref.d.ts, --, --))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 57))
>V : Symbol(V, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 46))
#refSet = new Set<WeakRef<K>>();
>#refSet : Symbol(IterableWeakMap.#refSet, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 72))
>Set : Symbol(Set, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>WeakRef : Symbol(WeakRef, Decl(lib.esnext.weakref.d.ts, --, --), Decl(lib.esnext.weakref.d.ts, --, --))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))
#finalizationGroup = new FinalizationRegistry(IterableWeakMap_cleanup);
>#finalizationGroup : Symbol(IterableWeakMap.#finalizationGroup, Decl(esNextWeakRefs_IterableWeakMap.ts, 13, 36))
>FinalizationRegistry : Symbol(FinalizationRegistry, Decl(lib.esnext.weakref.d.ts, --, --), Decl(lib.esnext.weakref.d.ts, --, --))
>IterableWeakMap_cleanup : Symbol(IterableWeakMap_cleanup, Decl(esNextWeakRefs_IterableWeakMap.ts, 1, 5))
constructor(iterable: Iterable<[key: K, value: V]> | null = null) {
>iterable : Symbol(iterable, Decl(esNextWeakRefs_IterableWeakMap.ts, 16, 16))
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))
>V : Symbol(V, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 46))
if (iterable !== null) {
>iterable : Symbol(iterable, Decl(esNextWeakRefs_IterableWeakMap.ts, 16, 16))
for (const { 0: key, 1: value } of iterable) {
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 18, 24))
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 18, 32))
>iterable : Symbol(iterable, Decl(esNextWeakRefs_IterableWeakMap.ts, 16, 16))
this.set(key, value);
>this.set : Symbol(IterableWeakMap.set, Decl(esNextWeakRefs_IterableWeakMap.ts, 22, 5))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>set : Symbol(IterableWeakMap.set, Decl(esNextWeakRefs_IterableWeakMap.ts, 22, 5))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 18, 24))
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 18, 32))
}
}
}
set(key: K, value: V): this {
>set : Symbol(IterableWeakMap.set, Decl(esNextWeakRefs_IterableWeakMap.ts, 22, 5))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 24, 8))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 24, 15))
>V : Symbol(V, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 46))
const entry = this.#weakMap.get(key);
>entry : Symbol(entry, Decl(esNextWeakRefs_IterableWeakMap.ts, 25, 13))
>this.#weakMap.get : Symbol(WeakMap.get, Decl(lib.es2015.collection.d.ts, --, --))
>this.#weakMap : Symbol(IterableWeakMap.#weakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 10, 61))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>get : Symbol(WeakMap.get, Decl(lib.es2015.collection.d.ts, --, --))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 24, 8))
if (entry !== undefined) {
>entry : Symbol(entry, Decl(esNextWeakRefs_IterableWeakMap.ts, 25, 13))
>undefined : Symbol(undefined)
entry.value = value;
>entry.value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 57))
>entry : Symbol(entry, Decl(esNextWeakRefs_IterableWeakMap.ts, 25, 13))
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 57))
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 24, 15))
} else {
const ref = new WeakRef(key);
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 29, 17))
>WeakRef : Symbol(WeakRef, Decl(lib.esnext.weakref.d.ts, --, --), Decl(lib.esnext.weakref.d.ts, --, --))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 24, 8))
this.#weakMap.set(key, { ref, value });
>this.#weakMap.set : Symbol(WeakMap.set, Decl(lib.es2015.collection.d.ts, --, --))
>this.#weakMap : Symbol(IterableWeakMap.#weakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 10, 61))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>set : Symbol(WeakMap.set, Decl(lib.es2015.collection.d.ts, --, --))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 24, 8))
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 31, 36))
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 31, 41))
this.#refSet.add(ref);
>this.#refSet.add : Symbol(Set.add, Decl(lib.es2015.collection.d.ts, --, --))
>this.#refSet : Symbol(IterableWeakMap.#refSet, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 72))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>add : Symbol(Set.add, Decl(lib.es2015.collection.d.ts, --, --))
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 29, 17))
this.#finalizationGroup.register(key, {
>this.#finalizationGroup.register : Symbol(FinalizationRegistry.register, Decl(lib.esnext.weakref.d.ts, --, --))
>this.#finalizationGroup : Symbol(IterableWeakMap.#finalizationGroup, Decl(esNextWeakRefs_IterableWeakMap.ts, 13, 36))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>register : Symbol(FinalizationRegistry.register, Decl(lib.esnext.weakref.d.ts, --, --))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 24, 8))
set: this.#refSet,
>set : Symbol(set, Decl(esNextWeakRefs_IterableWeakMap.ts, 33, 51))
>this.#refSet : Symbol(IterableWeakMap.#refSet, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 72))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
ref,
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 34, 34))
}, ref);
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 29, 17))
}
return this;
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
}
has(key: K): boolean {
>has : Symbol(IterableWeakMap.has, Decl(esNextWeakRefs_IterableWeakMap.ts, 39, 5))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 41, 8))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))
return this.#weakMap.has(key);
>this.#weakMap.has : Symbol(WeakMap.has, Decl(lib.es2015.collection.d.ts, --, --))
>this.#weakMap : Symbol(IterableWeakMap.#weakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 10, 61))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>has : Symbol(WeakMap.has, Decl(lib.es2015.collection.d.ts, --, --))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 41, 8))
}
get(key: K): V | undefined {
>get : Symbol(IterableWeakMap.get, Decl(esNextWeakRefs_IterableWeakMap.ts, 43, 5))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 45, 8))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))
>V : Symbol(V, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 46))
return this.#weakMap.get(key)?.value;
>this.#weakMap.get(key)?.value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 57))
>this.#weakMap.get : Symbol(WeakMap.get, Decl(lib.es2015.collection.d.ts, --, --))
>this.#weakMap : Symbol(IterableWeakMap.#weakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 10, 61))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>get : Symbol(WeakMap.get, Decl(lib.es2015.collection.d.ts, --, --))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 45, 8))
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 57))
}
delete(key: K): boolean {
>delete : Symbol(IterableWeakMap.delete, Decl(esNextWeakRefs_IterableWeakMap.ts, 47, 5))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 49, 11))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))
const entry = this.#weakMap.get(key);
>entry : Symbol(entry, Decl(esNextWeakRefs_IterableWeakMap.ts, 50, 13))
>this.#weakMap.get : Symbol(WeakMap.get, Decl(lib.es2015.collection.d.ts, --, --))
>this.#weakMap : Symbol(IterableWeakMap.#weakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 10, 61))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>get : Symbol(WeakMap.get, Decl(lib.es2015.collection.d.ts, --, --))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 49, 11))
if (entry === undefined) {
>entry : Symbol(entry, Decl(esNextWeakRefs_IterableWeakMap.ts, 50, 13))
>undefined : Symbol(undefined)
return false;
}
const { ref } = entry;
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 55, 15))
>entry : Symbol(entry, Decl(esNextWeakRefs_IterableWeakMap.ts, 50, 13))
this.#weakMap.delete(key);
>this.#weakMap.delete : Symbol(WeakMap.delete, Decl(lib.es2015.collection.d.ts, --, --))
>this.#weakMap : Symbol(IterableWeakMap.#weakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 10, 61))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>delete : Symbol(WeakMap.delete, Decl(lib.es2015.collection.d.ts, --, --))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 49, 11))
this.#refSet.delete(ref);
>this.#refSet.delete : Symbol(Set.delete, Decl(lib.es2015.collection.d.ts, --, --))
>this.#refSet : Symbol(IterableWeakMap.#refSet, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 72))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>delete : Symbol(Set.delete, Decl(lib.es2015.collection.d.ts, --, --))
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 55, 15))
this.#finalizationGroup.unregister(ref);
>this.#finalizationGroup.unregister : Symbol(FinalizationRegistry.unregister, Decl(lib.esnext.weakref.d.ts, --, --))
>this.#finalizationGroup : Symbol(IterableWeakMap.#finalizationGroup, Decl(esNextWeakRefs_IterableWeakMap.ts, 13, 36))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>unregister : Symbol(FinalizationRegistry.unregister, Decl(lib.esnext.weakref.d.ts, --, --))
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 55, 15))
return true;
}
declare [Symbol.iterator]: this["entries"];
>[Symbol.iterator] : Symbol(IterableWeakMap[Symbol.iterator], Decl(esNextWeakRefs_IterableWeakMap.ts, 60, 5))
>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
*entries(): Generator<[key: K, value: V], void> {
>entries : Symbol(IterableWeakMap.entries, Decl(esNextWeakRefs_IterableWeakMap.ts, 62, 47))
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
>K : Symbol(K, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 29))
>V : Symbol(V, Decl(esNextWeakRefs_IterableWeakMap.ts, 9, 46))
for (const ref of this.#refSet) {
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 64, 18))
>this.#refSet : Symbol(IterableWeakMap.#refSet, Decl(esNextWeakRefs_IterableWeakMap.ts, 12, 72))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
const key = ref.deref();
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 65, 17))
>ref.deref : Symbol(WeakRef.deref, Decl(lib.esnext.weakref.d.ts, --, --))
>ref : Symbol(ref, Decl(esNextWeakRefs_IterableWeakMap.ts, 64, 18))
>deref : Symbol(WeakRef.deref, Decl(lib.esnext.weakref.d.ts, --, --))
if (key === undefined) continue;
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 65, 17))
>undefined : Symbol(undefined)
const { value } = this.#weakMap.get(key)!;
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 67, 19))
>this.#weakMap.get : Symbol(WeakMap.get, Decl(lib.es2015.collection.d.ts, --, --))
>this.#weakMap : Symbol(IterableWeakMap.#weakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 10, 61))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>get : Symbol(WeakMap.get, Decl(lib.es2015.collection.d.ts, --, --))
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 65, 17))
yield [key, value];
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 65, 17))
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 67, 19))
}
}
*keys() {
>keys : Symbol(IterableWeakMap.keys, Decl(esNextWeakRefs_IterableWeakMap.ts, 70, 5))
for (const { 0: key } of this) {
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 73, 20))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
yield key;
>key : Symbol(key, Decl(esNextWeakRefs_IterableWeakMap.ts, 73, 20))
}
}
*values() {
>values : Symbol(IterableWeakMap.values, Decl(esNextWeakRefs_IterableWeakMap.ts, 76, 5))
for (const { 1: value } of this) {
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 79, 20))
>this : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
yield value;
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 79, 20))
}
}
}
Object.defineProperties(IterableWeakMap.prototype, {
>Object.defineProperties : Symbol(ObjectConstructor.defineProperties, Decl(lib.es5.d.ts, --, --))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>defineProperties : Symbol(ObjectConstructor.defineProperties, Decl(lib.es5.d.ts, --, --))
>IterableWeakMap.prototype : Symbol(IterableWeakMap.prototype)
>IterableWeakMap : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>prototype : Symbol(IterableWeakMap.prototype)
[Symbol.iterator]: {
>[Symbol.iterator] : Symbol([Symbol.iterator], Decl(esNextWeakRefs_IterableWeakMap.ts, 85, 52))
>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
configurable: true,
>configurable : Symbol(configurable, Decl(esNextWeakRefs_IterableWeakMap.ts, 86, 24))
enumerable: false,
>enumerable : Symbol(enumerable, Decl(esNextWeakRefs_IterableWeakMap.ts, 87, 27))
writable: true,
>writable : Symbol(writable, Decl(esNextWeakRefs_IterableWeakMap.ts, 88, 26))
value: Object.getOwnPropertyDescriptor(
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 89, 23))
>Object.getOwnPropertyDescriptor( IterableWeakMap.prototype, "entries", )!.value : Symbol(PropertyDescriptor.value, Decl(lib.es5.d.ts, --, --))
>Object.getOwnPropertyDescriptor : Symbol(ObjectConstructor.getOwnPropertyDescriptor, Decl(lib.es5.d.ts, --, --))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>getOwnPropertyDescriptor : Symbol(ObjectConstructor.getOwnPropertyDescriptor, Decl(lib.es5.d.ts, --, --))
IterableWeakMap.prototype,
>IterableWeakMap.prototype : Symbol(IterableWeakMap.prototype)
>IterableWeakMap : Symbol(IterableWeakMap, Decl(esNextWeakRefs_IterableWeakMap.ts, 6, 2))
>prototype : Symbol(IterableWeakMap.prototype)
"entries",
)!.value,
>value : Symbol(PropertyDescriptor.value, Decl(lib.es5.d.ts, --, --))
},
[Symbol.toStringTag]: {
>[Symbol.toStringTag] : Symbol([Symbol.toStringTag], Decl(esNextWeakRefs_IterableWeakMap.ts, 94, 6))
>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
configurable: true,
>configurable : Symbol(configurable, Decl(esNextWeakRefs_IterableWeakMap.ts, 95, 27))
enumerable: false,
>enumerable : Symbol(enumerable, Decl(esNextWeakRefs_IterableWeakMap.ts, 96, 27))
writable: false,
>writable : Symbol(writable, Decl(esNextWeakRefs_IterableWeakMap.ts, 97, 26))
value: "IterableWeakMap",
>value : Symbol(value, Decl(esNextWeakRefs_IterableWeakMap.ts, 98, 24))
},
});

View file

@ -0,0 +1,383 @@
=== tests/cases/compiler/esNextWeakRefs_IterableWeakMap.ts ===
/** `static #cleanup` */
const IterableWeakMap_cleanup = ({ ref, set }: {
>IterableWeakMap_cleanup : ({ ref, set }: { readonly ref: WeakRef<object>; readonly set: Set<WeakRef<object>>; }) => void
>({ ref, set }: { readonly ref: WeakRef<object>; readonly set: Set<WeakRef<object>>;}) => { set.delete(ref);} : ({ ref, set }: { readonly ref: WeakRef<object>; readonly set: Set<WeakRef<object>>; }) => void
>ref : WeakRef<object>
>set : Set<WeakRef<object>>
readonly ref: WeakRef<object>;
>ref : WeakRef<object>
readonly set: Set<WeakRef<object>>;
>set : Set<WeakRef<object>>
}) => {
set.delete(ref);
>set.delete(ref) : boolean
>set.delete : (value: WeakRef<object>) => boolean
>set : Set<WeakRef<object>>
>delete : (value: WeakRef<object>) => boolean
>ref : WeakRef<object>
};
// Based on: https://github.com/tc39/proposal-weakrefs/blob/master/README.md#iterable-weakmaps
export class IterableWeakMap<K extends object, V> implements WeakMap<K, V> {
>IterableWeakMap : IterableWeakMap<K, V>
declare readonly [Symbol.toStringTag]: "IterableWeakMap";
>[Symbol.toStringTag] : "IterableWeakMap"
>Symbol.toStringTag : symbol
>Symbol : SymbolConstructor
>toStringTag : symbol
#weakMap = new WeakMap<K, { readonly ref: WeakRef<K>; value: V }>();
>#weakMap : WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>new WeakMap<K, { readonly ref: WeakRef<K>; value: V }>() : WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>WeakMap : WeakMapConstructor
>ref : WeakRef<K>
>value : V
#refSet = new Set<WeakRef<K>>();
>#refSet : Set<WeakRef<K>>
>new Set<WeakRef<K>>() : Set<WeakRef<K>>
>Set : SetConstructor
#finalizationGroup = new FinalizationRegistry(IterableWeakMap_cleanup);
>#finalizationGroup : FinalizationRegistry<{ readonly ref: WeakRef<object>; readonly set: Set<WeakRef<object>>; }>
>new FinalizationRegistry(IterableWeakMap_cleanup) : FinalizationRegistry<{ readonly ref: WeakRef<object>; readonly set: Set<WeakRef<object>>; }>
>FinalizationRegistry : FinalizationRegistryConstructor
>IterableWeakMap_cleanup : ({ ref, set }: { readonly ref: WeakRef<object>; readonly set: Set<WeakRef<object>>; }) => void
constructor(iterable: Iterable<[key: K, value: V]> | null = null) {
>iterable : Iterable<[key: K, value: V]> | null
>null : null
>null : null
if (iterable !== null) {
>iterable !== null : boolean
>iterable : Iterable<[key: K, value: V]> | null
>null : null
for (const { 0: key, 1: value } of iterable) {
>key : K
>value : V
>iterable : Iterable<[key: K, value: V]>
this.set(key, value);
>this.set(key, value) : this
>this.set : (key: K, value: V) => this
>this : this
>set : (key: K, value: V) => this
>key : K
>value : V
}
}
}
set(key: K, value: V): this {
>set : (key: K, value: V) => this
>key : K
>value : V
const entry = this.#weakMap.get(key);
>entry : { readonly ref: WeakRef<K>; value: V; } | undefined
>this.#weakMap.get(key) : { readonly ref: WeakRef<K>; value: V; } | undefined
>this.#weakMap.get : (key: K) => { readonly ref: WeakRef<K>; value: V; } | undefined
>this.#weakMap : WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>this : this
>get : (key: K) => { readonly ref: WeakRef<K>; value: V; } | undefined
>key : K
if (entry !== undefined) {
>entry !== undefined : boolean
>entry : { readonly ref: WeakRef<K>; value: V; } | undefined
>undefined : undefined
entry.value = value;
>entry.value = value : V
>entry.value : V
>entry : { readonly ref: WeakRef<K>; value: V; }
>value : V
>value : V
} else {
const ref = new WeakRef(key);
>ref : WeakRef<K>
>new WeakRef(key) : WeakRef<K>
>WeakRef : WeakRefConstructor
>key : K
this.#weakMap.set(key, { ref, value });
>this.#weakMap.set(key, { ref, value }) : WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>this.#weakMap.set : (key: K, value: { readonly ref: WeakRef<K>; value: V; }) => WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>this.#weakMap : WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>this : this
>set : (key: K, value: { readonly ref: WeakRef<K>; value: V; }) => WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>key : K
>{ ref, value } : { ref: WeakRef<K>; value: V; }
>ref : WeakRef<K>
>value : V
this.#refSet.add(ref);
>this.#refSet.add(ref) : Set<WeakRef<K>>
>this.#refSet.add : (value: WeakRef<K>) => Set<WeakRef<K>>
>this.#refSet : Set<WeakRef<K>>
>this : this
>add : (value: WeakRef<K>) => Set<WeakRef<K>>
>ref : WeakRef<K>
this.#finalizationGroup.register(key, {
>this.#finalizationGroup.register(key, { set: this.#refSet, ref, }, ref) : void
>this.#finalizationGroup.register : (target: object, heldValue: { readonly ref: WeakRef<object>; readonly set: Set<WeakRef<object>>; }, unregisterToken?: object | undefined) => void
>this.#finalizationGroup : FinalizationRegistry<{ readonly ref: WeakRef<object>; readonly set: Set<WeakRef<object>>; }>
>this : this
>register : (target: object, heldValue: { readonly ref: WeakRef<object>; readonly set: Set<WeakRef<object>>; }, unregisterToken?: object | undefined) => void
>key : K
>{ set: this.#refSet, ref, } : { set: Set<WeakRef<K>>; ref: WeakRef<K>; }
set: this.#refSet,
>set : Set<WeakRef<K>>
>this.#refSet : Set<WeakRef<K>>
>this : this
ref,
>ref : WeakRef<K>
}, ref);
>ref : WeakRef<K>
}
return this;
>this : this
}
has(key: K): boolean {
>has : (key: K) => boolean
>key : K
return this.#weakMap.has(key);
>this.#weakMap.has(key) : boolean
>this.#weakMap.has : (key: K) => boolean
>this.#weakMap : WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>this : this
>has : (key: K) => boolean
>key : K
}
get(key: K): V | undefined {
>get : (key: K) => V | undefined
>key : K
return this.#weakMap.get(key)?.value;
>this.#weakMap.get(key)?.value : V | undefined
>this.#weakMap.get(key) : { readonly ref: WeakRef<K>; value: V; } | undefined
>this.#weakMap.get : (key: K) => { readonly ref: WeakRef<K>; value: V; } | undefined
>this.#weakMap : WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>this : this
>get : (key: K) => { readonly ref: WeakRef<K>; value: V; } | undefined
>key : K
>value : V | undefined
}
delete(key: K): boolean {
>delete : (key: K) => boolean
>key : K
const entry = this.#weakMap.get(key);
>entry : { readonly ref: WeakRef<K>; value: V; } | undefined
>this.#weakMap.get(key) : { readonly ref: WeakRef<K>; value: V; } | undefined
>this.#weakMap.get : (key: K) => { readonly ref: WeakRef<K>; value: V; } | undefined
>this.#weakMap : WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>this : this
>get : (key: K) => { readonly ref: WeakRef<K>; value: V; } | undefined
>key : K
if (entry === undefined) {
>entry === undefined : boolean
>entry : { readonly ref: WeakRef<K>; value: V; } | undefined
>undefined : undefined
return false;
>false : false
}
const { ref } = entry;
>ref : WeakRef<K>
>entry : { readonly ref: WeakRef<K>; value: V; }
this.#weakMap.delete(key);
>this.#weakMap.delete(key) : boolean
>this.#weakMap.delete : (key: K) => boolean
>this.#weakMap : WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>this : this
>delete : (key: K) => boolean
>key : K
this.#refSet.delete(ref);
>this.#refSet.delete(ref) : boolean
>this.#refSet.delete : (value: WeakRef<K>) => boolean
>this.#refSet : Set<WeakRef<K>>
>this : this
>delete : (value: WeakRef<K>) => boolean
>ref : WeakRef<K>
this.#finalizationGroup.unregister(ref);
>this.#finalizationGroup.unregister(ref) : void
>this.#finalizationGroup.unregister : (unregisterToken: object) => void
>this.#finalizationGroup : FinalizationRegistry<{ readonly ref: WeakRef<object>; readonly set: Set<WeakRef<object>>; }>
>this : this
>unregister : (unregisterToken: object) => void
>ref : WeakRef<K>
return true;
>true : true
}
declare [Symbol.iterator]: this["entries"];
>[Symbol.iterator] : this["entries"]
>Symbol.iterator : symbol
>Symbol : SymbolConstructor
>iterator : symbol
*entries(): Generator<[key: K, value: V], void> {
>entries : () => Generator<[key: K, value: V], void>
for (const ref of this.#refSet) {
>ref : WeakRef<K>
>this.#refSet : Set<WeakRef<K>>
>this : this
const key = ref.deref();
>key : K | undefined
>ref.deref() : K | undefined
>ref.deref : () => K | undefined
>ref : WeakRef<K>
>deref : () => K | undefined
if (key === undefined) continue;
>key === undefined : boolean
>key : K | undefined
>undefined : undefined
const { value } = this.#weakMap.get(key)!;
>value : V
>this.#weakMap.get(key)! : { readonly ref: WeakRef<K>; value: V; }
>this.#weakMap.get(key) : { readonly ref: WeakRef<K>; value: V; } | undefined
>this.#weakMap.get : (key: K) => { readonly ref: WeakRef<K>; value: V; } | undefined
>this.#weakMap : WeakMap<K, { readonly ref: WeakRef<K>; value: V; }>
>this : this
>get : (key: K) => { readonly ref: WeakRef<K>; value: V; } | undefined
>key : K
yield [key, value];
>yield [key, value] : unknown
>[key, value] : [K, V]
>key : K
>value : V
}
}
*keys() {
>keys : () => Generator<K, void, unknown>
for (const { 0: key } of this) {
>key : K
>this : this
yield key;
>yield key : any
>key : K
}
}
*values() {
>values : () => Generator<V, void, unknown>
for (const { 1: value } of this) {
>value : V
>this : this
yield value;
>yield value : any
>value : V
}
}
}
Object.defineProperties(IterableWeakMap.prototype, {
>Object.defineProperties(IterableWeakMap.prototype, { [Symbol.iterator]: { configurable: true, enumerable: false, writable: true, value: Object.getOwnPropertyDescriptor( IterableWeakMap.prototype, "entries", )!.value, }, [Symbol.toStringTag]: { configurable: true, enumerable: false, writable: false, value: "IterableWeakMap", },}) : any
>Object.defineProperties : (o: any, properties: PropertyDescriptorMap & ThisType<any>) => any
>Object : ObjectConstructor
>defineProperties : (o: any, properties: PropertyDescriptorMap & ThisType<any>) => any
>IterableWeakMap.prototype : IterableWeakMap<any, any>
>IterableWeakMap : typeof IterableWeakMap
>prototype : IterableWeakMap<any, any>
>{ [Symbol.iterator]: { configurable: true, enumerable: false, writable: true, value: Object.getOwnPropertyDescriptor( IterableWeakMap.prototype, "entries", )!.value, }, [Symbol.toStringTag]: { configurable: true, enumerable: false, writable: false, value: "IterableWeakMap", },} : { [Symbol.iterator]: { configurable: true; enumerable: false; writable: true; value: any; }; [Symbol.toStringTag]: { configurable: true; enumerable: false; writable: false; value: string; }; }
[Symbol.iterator]: {
>[Symbol.iterator] : { configurable: true; enumerable: false; writable: true; value: any; }
>Symbol.iterator : symbol
>Symbol : SymbolConstructor
>iterator : symbol
>{ configurable: true, enumerable: false, writable: true, value: Object.getOwnPropertyDescriptor( IterableWeakMap.prototype, "entries", )!.value, } : { configurable: true; enumerable: false; writable: true; value: any; }
configurable: true,
>configurable : true
>true : true
enumerable: false,
>enumerable : false
>false : false
writable: true,
>writable : true
>true : true
value: Object.getOwnPropertyDescriptor(
>value : any
>Object.getOwnPropertyDescriptor( IterableWeakMap.prototype, "entries", )!.value : any
>Object.getOwnPropertyDescriptor( IterableWeakMap.prototype, "entries", )! : PropertyDescriptor
>Object.getOwnPropertyDescriptor( IterableWeakMap.prototype, "entries", ) : PropertyDescriptor | undefined
>Object.getOwnPropertyDescriptor : (o: any, p: PropertyKey) => PropertyDescriptor | undefined
>Object : ObjectConstructor
>getOwnPropertyDescriptor : (o: any, p: PropertyKey) => PropertyDescriptor | undefined
IterableWeakMap.prototype,
>IterableWeakMap.prototype : IterableWeakMap<any, any>
>IterableWeakMap : typeof IterableWeakMap
>prototype : IterableWeakMap<any, any>
"entries",
>"entries" : "entries"
)!.value,
>value : any
},
[Symbol.toStringTag]: {
>[Symbol.toStringTag] : { configurable: true; enumerable: false; writable: false; value: string; }
>Symbol.toStringTag : symbol
>Symbol : SymbolConstructor
>toStringTag : symbol
>{ configurable: true, enumerable: false, writable: false, value: "IterableWeakMap", } : { configurable: true; enumerable: false; writable: false; value: string; }
configurable: true,
>configurable : true
>true : true
enumerable: false,
>enumerable : false
>false : false
writable: false,
>writable : false
>false : false
value: "IterableWeakMap",
>value : string
>"IterableWeakMap" : "IterableWeakMap"
},
});

View file

@ -0,0 +1,107 @@
// @lib: ESNext
// @target: ESNext
// @useDefineForClassFields: true
// @strictNullChecks: true
/** `static #cleanup` */
const IterableWeakMap_cleanup = ({ ref, set }: {
readonly ref: WeakRef<object>;
readonly set: Set<WeakRef<object>>;
}) => {
set.delete(ref);
};
// Based on: https://github.com/tc39/proposal-weakrefs/blob/master/README.md#iterable-weakmaps
export class IterableWeakMap<K extends object, V> implements WeakMap<K, V> {
declare readonly [Symbol.toStringTag]: "IterableWeakMap";
#weakMap = new WeakMap<K, { readonly ref: WeakRef<K>; value: V }>();
#refSet = new Set<WeakRef<K>>();
#finalizationGroup = new FinalizationRegistry(IterableWeakMap_cleanup);
constructor(iterable: Iterable<[key: K, value: V]> | null = null) {
if (iterable !== null) {
for (const { 0: key, 1: value } of iterable) {
this.set(key, value);
}
}
}
set(key: K, value: V): this {
const entry = this.#weakMap.get(key);
if (entry !== undefined) {
entry.value = value;
} else {
const ref = new WeakRef(key);
this.#weakMap.set(key, { ref, value });
this.#refSet.add(ref);
this.#finalizationGroup.register(key, {
set: this.#refSet,
ref,
}, ref);
}
return this;
}
has(key: K): boolean {
return this.#weakMap.has(key);
}
get(key: K): V | undefined {
return this.#weakMap.get(key)?.value;
}
delete(key: K): boolean {
const entry = this.#weakMap.get(key);
if (entry === undefined) {
return false;
}
const { ref } = entry;
this.#weakMap.delete(key);
this.#refSet.delete(ref);
this.#finalizationGroup.unregister(ref);
return true;
}
declare [Symbol.iterator]: this["entries"];
*entries(): Generator<[key: K, value: V], void> {
for (const ref of this.#refSet) {
const key = ref.deref();
if (key === undefined) continue;
const { value } = this.#weakMap.get(key)!;
yield [key, value];
}
}
*keys() {
for (const { 0: key } of this) {
yield key;
}
}
*values() {
for (const { 1: value } of this) {
yield value;
}
}
}
Object.defineProperties(IterableWeakMap.prototype, {
[Symbol.iterator]: {
configurable: true,
enumerable: false,
writable: true,
value: Object.getOwnPropertyDescriptor(
IterableWeakMap.prototype,
"entries",
)!.value,
},
[Symbol.toStringTag]: {
configurable: true,
enumerable: false,
writable: false,
value: "IterableWeakMap",
},
});