'use strict'; // (c) Andrea Giammarchi - ISC const registry = new FinalizationRegistry( ([onGarbageCollected, held, debug]) => { if (debug) console.debug(`Held value ${String(held)} not relevant anymore`); onGarbageCollected(held); } ); const nullHandler = Object.create(null); /** * @template {unknown} H * @typedef {Object} GCHookOptions * @prop {boolean} [debug=false] if `true`, logs values once these can get collected. * @prop {ProxyHandler} [handler] optional proxy handler to use instead of the default one. * @prop {H} [return=H] if specified, overrides the returned proxy with its value. * @prop {unknown} [token=H] it's the held value by default, but it can be any other token except the returned value itself. */ /** * @template {unknown} H * @param {H} hold the reference to hold behind the scene and passed along the callback once it triggers. * @param {(held:H) => void} onGarbageCollected the callback that will receive the held value once its wrapper or indirect reference is no longer needed. * @param {GCHookOptions} [options] an optional configuration object to change some default behavior. */ const create = ( hold, onGarbageCollected, { debug, handler, return: r, token = hold } = nullHandler ) => { // if no reference to return is defined, // create a proxy for the held one and register that instead. /** @type {H} */ const target = r || new Proxy(hold, handler || nullHandler); const args = [target, [onGarbageCollected, hold, !!debug]]; if (token !== false) args.push(token); // register the target reference in a way that // the `onGarbageCollected(held)` callback will eventually notify. registry.register(...args); return target; }; exports.create = create; /** * If previously registered as either `token` or `hold` value, allow explicit removal of the entry in the registry. * @param {unknown} token the token used during registration. If no `token` was passed, this can be the same `hold` reference. * @returns {boolean} `true` if successfully unregistered. */ const drop = token => registry.unregister(token); exports.drop = drop;