Skip to content

Instantly share code, notes, and snippets.

@PaperStrike
Last active July 17, 2022 17:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PaperStrike/69df82e48b185df2be555715d972117d to your computer and use it in GitHub Desktop.
Save PaperStrike/69df82e48b185df2be555715d972117d to your computer and use it in GitHub Desktop.
Request a callback when registered objects are all garbage-collected
export default class GroupFinalizationRegistry<T> extends FinalizationRegistry<T> {
#members: WeakRef<object>[] = [];
constructor(cleanupCallback: (heldValue: T) => void) {
super((heldValue) => {
if (this.#members.length === 0) return;
this.#members = this.#members.filter((member) => (
member.deref() !== undefined
));
if (this.#members.length === 0) {
this.#tokenMembersMap = new WeakMap();
cleanupCallback(heldValue);
}
});
}
#tokenMembersMap: WeakMap<object, WeakRef<object>[]> = new WeakMap();
register(target: object, heldValue: T, unregisterToken?: object) {
super.register(target, heldValue, unregisterToken);
const member = new WeakRef(target);
this.#members.push(member);
if (unregisterToken !== undefined) {
const tokenMembers = this.#tokenMembersMap.get(unregisterToken);
if (tokenMembers) {
tokenMembers.push(member);
} else {
this.#tokenMembersMap.set(unregisterToken, [member]);
}
}
}
unregister(unregisterToken: object) {
super.unregister(unregisterToken);
const tokenMembers = this.#tokenMembersMap.get(unregisterToken);
if (tokenMembers === undefined) return false;
this.#members = this.#members.filter((member) => (
!tokenMembers.includes(member)
));
this.#tokenMembersMap.delete(unregisterToken);
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment