From 0723904bfb00ffc41d1bbda2a11ae7d7f8ac5bc8 Mon Sep 17 00:00:00 2001 From: ExE Boss <3889017+ExE-Boss@users.noreply.github.com> Date: Fri, 19 Feb 2021 01:43:36 +0100 Subject: [PATCH] =?UTF-8?q?feat(lib/es2021):=20Add=C2=A0type=C2=A0paramete?= =?UTF-8?q?r=20to=C2=A0`FinalizationRegistry`=20(#42274)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(lib/es2021): Add type parameter to `FinalizationRegistry` * test(lib/es2021): Add test for generic `FinalizationRegistry` --- src/lib/esnext.weakref.d.ts | 10 +- .../esNextWeakRefs_IterableWeakMap.js | 189 +++++++++ .../esNextWeakRefs_IterableWeakMap.symbols | 358 ++++++++++++++++ .../esNextWeakRefs_IterableWeakMap.types | 383 ++++++++++++++++++ .../esNextWeakRefs_IterableWeakMap.ts | 107 +++++ 5 files changed, 1042 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/esNextWeakRefs_IterableWeakMap.js create mode 100644 tests/baselines/reference/esNextWeakRefs_IterableWeakMap.symbols create mode 100644 tests/baselines/reference/esNextWeakRefs_IterableWeakMap.types create mode 100644 tests/cases/compiler/esNextWeakRefs_IterableWeakMap.ts diff --git a/src/lib/esnext.weakref.d.ts b/src/lib/esnext.weakref.d.ts index 337aa11f3e..d36ddb6a19 100644 --- a/src/lib/esnext.weakref.d.ts +++ b/src/lib/esnext.weakref.d.ts @@ -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(target?: T): WeakRef; + new(target: T): WeakRef; } declare var WeakRef: WeakRefConstructor; -interface FinalizationRegistry { +interface FinalizationRegistry { 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; /** * 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(cleanupCallback: (heldValue: T) => void): FinalizationRegistry; } declare var FinalizationRegistry: FinalizationRegistryConstructor; diff --git a/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.js b/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.js new file mode 100644 index 0000000000..4597c8585c --- /dev/null +++ b/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.js @@ -0,0 +1,189 @@ +//// [esNextWeakRefs_IterableWeakMap.ts] +/** `static #cleanup` */ +const IterableWeakMap_cleanup = ({ ref, set }: { + readonly ref: WeakRef; + readonly set: Set>; +}) => { + set.delete(ref); +}; + +// Based on: https://github.com/tc39/proposal-weakrefs/blob/master/README.md#iterable-weakmaps +export class IterableWeakMap implements WeakMap { + declare readonly [Symbol.toStringTag]: "IterableWeakMap"; + + #weakMap = new WeakMap; value: V }>(); + #refSet = new Set>(); + #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", + }, +}); diff --git a/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.symbols b/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.symbols new file mode 100644 index 0000000000..d07a230756 --- /dev/null +++ b/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.symbols @@ -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; +>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>; +>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 implements WeakMap { +>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; 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>(); +>#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)) + + }, +}); + diff --git a/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.types b/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.types new file mode 100644 index 0000000000..5b7566bd5d --- /dev/null +++ b/tests/baselines/reference/esNextWeakRefs_IterableWeakMap.types @@ -0,0 +1,383 @@ +=== tests/cases/compiler/esNextWeakRefs_IterableWeakMap.ts === +/** `static #cleanup` */ +const IterableWeakMap_cleanup = ({ ref, set }: { +>IterableWeakMap_cleanup : ({ ref, set }: { readonly ref: WeakRef; readonly set: Set>; }) => void +>({ ref, set }: { readonly ref: WeakRef; readonly set: Set>;}) => { set.delete(ref);} : ({ ref, set }: { readonly ref: WeakRef; readonly set: Set>; }) => void +>ref : WeakRef +>set : Set> + + readonly ref: WeakRef; +>ref : WeakRef + + readonly set: Set>; +>set : Set> + +}) => { + set.delete(ref); +>set.delete(ref) : boolean +>set.delete : (value: WeakRef) => boolean +>set : Set> +>delete : (value: WeakRef) => boolean +>ref : WeakRef + +}; + +// Based on: https://github.com/tc39/proposal-weakrefs/blob/master/README.md#iterable-weakmaps +export class IterableWeakMap implements WeakMap { +>IterableWeakMap : IterableWeakMap + + declare readonly [Symbol.toStringTag]: "IterableWeakMap"; +>[Symbol.toStringTag] : "IterableWeakMap" +>Symbol.toStringTag : symbol +>Symbol : SymbolConstructor +>toStringTag : symbol + + #weakMap = new WeakMap; value: V }>(); +>#weakMap : WeakMap; value: V; }> +>new WeakMap; value: V }>() : WeakMap; value: V; }> +>WeakMap : WeakMapConstructor +>ref : WeakRef +>value : V + + #refSet = new Set>(); +>#refSet : Set> +>new Set>() : Set> +>Set : SetConstructor + + #finalizationGroup = new FinalizationRegistry(IterableWeakMap_cleanup); +>#finalizationGroup : FinalizationRegistry<{ readonly ref: WeakRef; readonly set: Set>; }> +>new FinalizationRegistry(IterableWeakMap_cleanup) : FinalizationRegistry<{ readonly ref: WeakRef; readonly set: Set>; }> +>FinalizationRegistry : FinalizationRegistryConstructor +>IterableWeakMap_cleanup : ({ ref, set }: { readonly ref: WeakRef; readonly set: Set>; }) => 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; value: V; } | undefined +>this.#weakMap.get(key) : { readonly ref: WeakRef; value: V; } | undefined +>this.#weakMap.get : (key: K) => { readonly ref: WeakRef; value: V; } | undefined +>this.#weakMap : WeakMap; value: V; }> +>this : this +>get : (key: K) => { readonly ref: WeakRef; value: V; } | undefined +>key : K + + if (entry !== undefined) { +>entry !== undefined : boolean +>entry : { readonly ref: WeakRef; value: V; } | undefined +>undefined : undefined + + entry.value = value; +>entry.value = value : V +>entry.value : V +>entry : { readonly ref: WeakRef; value: V; } +>value : V +>value : V + + } else { + const ref = new WeakRef(key); +>ref : WeakRef +>new WeakRef(key) : WeakRef +>WeakRef : WeakRefConstructor +>key : K + + this.#weakMap.set(key, { ref, value }); +>this.#weakMap.set(key, { ref, value }) : WeakMap; value: V; }> +>this.#weakMap.set : (key: K, value: { readonly ref: WeakRef; value: V; }) => WeakMap; value: V; }> +>this.#weakMap : WeakMap; value: V; }> +>this : this +>set : (key: K, value: { readonly ref: WeakRef; value: V; }) => WeakMap; value: V; }> +>key : K +>{ ref, value } : { ref: WeakRef; value: V; } +>ref : WeakRef +>value : V + + this.#refSet.add(ref); +>this.#refSet.add(ref) : Set> +>this.#refSet.add : (value: WeakRef) => Set> +>this.#refSet : Set> +>this : this +>add : (value: WeakRef) => Set> +>ref : WeakRef + + this.#finalizationGroup.register(key, { +>this.#finalizationGroup.register(key, { set: this.#refSet, ref, }, ref) : void +>this.#finalizationGroup.register : (target: object, heldValue: { readonly ref: WeakRef; readonly set: Set>; }, unregisterToken?: object | undefined) => void +>this.#finalizationGroup : FinalizationRegistry<{ readonly ref: WeakRef; readonly set: Set>; }> +>this : this +>register : (target: object, heldValue: { readonly ref: WeakRef; readonly set: Set>; }, unregisterToken?: object | undefined) => void +>key : K +>{ set: this.#refSet, ref, } : { set: Set>; ref: WeakRef; } + + set: this.#refSet, +>set : Set> +>this.#refSet : Set> +>this : this + + ref, +>ref : WeakRef + + }, ref); +>ref : WeakRef + } + 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; 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; value: V; } | undefined +>this.#weakMap.get : (key: K) => { readonly ref: WeakRef; value: V; } | undefined +>this.#weakMap : WeakMap; value: V; }> +>this : this +>get : (key: K) => { readonly ref: WeakRef; 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; value: V; } | undefined +>this.#weakMap.get(key) : { readonly ref: WeakRef; value: V; } | undefined +>this.#weakMap.get : (key: K) => { readonly ref: WeakRef; value: V; } | undefined +>this.#weakMap : WeakMap; value: V; }> +>this : this +>get : (key: K) => { readonly ref: WeakRef; value: V; } | undefined +>key : K + + if (entry === undefined) { +>entry === undefined : boolean +>entry : { readonly ref: WeakRef; value: V; } | undefined +>undefined : undefined + + return false; +>false : false + } + + const { ref } = entry; +>ref : WeakRef +>entry : { readonly ref: WeakRef; value: V; } + + this.#weakMap.delete(key); +>this.#weakMap.delete(key) : boolean +>this.#weakMap.delete : (key: K) => boolean +>this.#weakMap : WeakMap; value: V; }> +>this : this +>delete : (key: K) => boolean +>key : K + + this.#refSet.delete(ref); +>this.#refSet.delete(ref) : boolean +>this.#refSet.delete : (value: WeakRef) => boolean +>this.#refSet : Set> +>this : this +>delete : (value: WeakRef) => boolean +>ref : WeakRef + + this.#finalizationGroup.unregister(ref); +>this.#finalizationGroup.unregister(ref) : void +>this.#finalizationGroup.unregister : (unregisterToken: object) => void +>this.#finalizationGroup : FinalizationRegistry<{ readonly ref: WeakRef; readonly set: Set>; }> +>this : this +>unregister : (unregisterToken: object) => void +>ref : WeakRef + + 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 +>this.#refSet : Set> +>this : this + + const key = ref.deref(); +>key : K | undefined +>ref.deref() : K | undefined +>ref.deref : () => K | undefined +>ref : WeakRef +>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; value: V; } +>this.#weakMap.get(key) : { readonly ref: WeakRef; value: V; } | undefined +>this.#weakMap.get : (key: K) => { readonly ref: WeakRef; value: V; } | undefined +>this.#weakMap : WeakMap; value: V; }> +>this : this +>get : (key: K) => { readonly ref: WeakRef; value: V; } | undefined +>key : K + + yield [key, value]; +>yield [key, value] : unknown +>[key, value] : [K, V] +>key : K +>value : V + } + } + + *keys() { +>keys : () => Generator + + for (const { 0: key } of this) { +>key : K +>this : this + + yield key; +>yield key : any +>key : K + } + } + + *values() { +>values : () => Generator + + 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 +>Object : ObjectConstructor +>defineProperties : (o: any, properties: PropertyDescriptorMap & ThisType) => any +>IterableWeakMap.prototype : IterableWeakMap +>IterableWeakMap : typeof IterableWeakMap +>prototype : IterableWeakMap +>{ [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 +>IterableWeakMap : typeof IterableWeakMap +>prototype : IterableWeakMap + + "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" + + }, +}); + diff --git a/tests/cases/compiler/esNextWeakRefs_IterableWeakMap.ts b/tests/cases/compiler/esNextWeakRefs_IterableWeakMap.ts new file mode 100644 index 0000000000..220b56a3d8 --- /dev/null +++ b/tests/cases/compiler/esNextWeakRefs_IterableWeakMap.ts @@ -0,0 +1,107 @@ +// @lib: ESNext +// @target: ESNext +// @useDefineForClassFields: true +// @strictNullChecks: true + +/** `static #cleanup` */ +const IterableWeakMap_cleanup = ({ ref, set }: { + readonly ref: WeakRef; + readonly set: Set>; +}) => { + set.delete(ref); +}; + +// Based on: https://github.com/tc39/proposal-weakrefs/blob/master/README.md#iterable-weakmaps +export class IterableWeakMap implements WeakMap { + declare readonly [Symbol.toStringTag]: "IterableWeakMap"; + + #weakMap = new WeakMap; value: V }>(); + #refSet = new Set>(); + #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", + }, +});