Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/lib/esnext.weakref.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";

/**
Expand All @@ -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.
Expand All @@ -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;
189 changes: 189 additions & 0 deletions tests/baselines/reference/esNextWeakRefs_IterableWeakMap.js
Original file line number Diff line number Diff line change
@@ -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",
},
});
Loading