UNPKG

node-weak-ref

Version:

Make weak references to JavaScript Objects.

129 lines (111 loc) 3.7 kB
/** * Module dependencies. */ import { EventEmitter } from "events" import b from "bindings" const bindings = b("weakref.node") /** * Set global weak callback function. */ bindings._setCallback(callback) /** * Internal emitter event name. * This is completely arbitrary... * Could be any value.... */ const CB = "_CB" export type WeakRef<T> = { [key in keyof T]: T[key] } /** * Makes weak references to JavaScript Objects * * @param object can be a regular Object, an Array, a Function, a RegExp, or any of the primitive types or constructor function created with new * @param callback a callback function to be invoked before the object is garbage collected */ export function create<T extends object>(object: T, callback?: (obj: T) => void): WeakRef<T> { const weakref = bindings._create(object, new EventEmitter()) if ("function" == typeof callback) { exports.addCallback(weakref, callback) } return weakref } type FunctionsType = { get?(ref: WeakRef<any>): unknown | undefined isWeakRef?(ref: any): ref is WeakRef<any> isDead?(ref: WeakRef<any> | WeakRef<undefined>): ref is WeakRef<undefined> } const functions: FunctionsType = {} Object.keys(bindings).forEach(function (name) { functions[name] = bindings[name] }) /** * Adds callback to the Array of callback functions that will be invoked before the Object gets garbage collected. The callbacks get executed in the order that they are added. * * @param ref weak reference object * @param callback function to be called */ export function addCallback(ref: WeakRef<any>, callback: () => void): NodeJS.EventEmitter { const emitter = bindings._getEmitter(ref) return emitter.on(CB, callback) } /** * Removes callback from the Array of callback functions that will be invoked before the Object gets garbage collected. * * @param ref weak reference object * @param callback function to be called */ export function removeCallback(ref: WeakRef<any>, callback: () => void): NodeJS.EventEmitter { const emitter = bindings._getEmitter(ref) return emitter.removeListener(CB, callback) } /** * Returns an Array that ref iterates through to invoke the GC callbacks. This utilizes node's EventEmitter#listeners() function and therefore returns a copy in node 0.10 and newer. * * @param ref weak reference object */ export function callbacks(ref) { const emitter = bindings._getEmitter(ref) return emitter.listeners(CB) } /** * Empties the Array of callback functions that will be invoked before the Object gets garbage collected. * * @param ref weak reference object */ export function removeCallbacks(ref) { const emitter = bindings._getEmitter(ref) return emitter.removeAllListeners(CB) } /** * Common weak callback function. * * @api private */ function callback(emitter) { emitter.emit(CB) emitter = null } /** * Returns the actual reference to the Object that this weak reference was created with. If this is called with a dead reference, undefined is returned. * @param ref weak reference object */ export function get<T>(ref: WeakRef<T>): T | undefined { return functions.get!(ref) as T } /** * Checks to see if ref is a dead reference. Returns true if the original Object has already been GC'd, false otherwise * * @param ref weak reference object */ export function isDead(ref: WeakRef<any> | WeakRef<undefined>): ref is WeakRef<undefined> { return functions.isDead!(ref) } /** * Checks to see if obj is "weak reference" instance. Returns true if the passed in object is a "weak reference", false otherwise. * * @param obj object to check */ export function isWeakRef(obj: any): obj is WeakRef<any> { return functions.isWeakRef!(obj) }