-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
52 lines (46 loc) · 2.1 KB
/
index.js
File metadata and controls
52 lines (46 loc) · 2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// (c) Andrea Giammarchi - ISC
const registry = new FinalizationRegistry(
([onGarbageCollected, held, debug]) => {
// "%cThis is a green text", "color:green"
if (debug) console.debug(`%c${String(held)}`, 'font-weight:bold', 'collected');
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<object>} [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<H>} [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;
};
/**
* 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);
export { create, drop };