Skip to content

Commit

Permalink
feat(lib/es2021): Add type parameter to FinalizationRegistry (#42274)
Browse files Browse the repository at this point in the history
* feat(lib/es2021): Add type parameter to `FinalizationRegistry`

* test(lib/es2021): Add test for generic `FinalizationRegistry`
  • Loading branch information
ExE-Boss authored Feb 19, 2021
1 parent 9950b6e commit 0723904
Show file tree
Hide file tree
Showing 5 changed files with 1,042 additions and 5 deletions.
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

0 comments on commit 0723904

Please sign in to comment.