index.js
 1  'use strict';
 2  
 3  var GetIntrinsic = require('get-intrinsic');
 4  var callBound = require('call-bound');
 5  var inspect = require('object-inspect');
 6  var getSideChannelMap = require('side-channel-map');
 7  
 8  var $TypeError = require('es-errors/type');
 9  var $WeakMap = GetIntrinsic('%WeakMap%', true);
10  
11  /** @type {<K extends object, V>(thisArg: WeakMap<K, V>, key: K) => V} */
12  var $weakMapGet = callBound('WeakMap.prototype.get', true);
13  /** @type {<K extends object, V>(thisArg: WeakMap<K, V>, key: K, value: V) => void} */
14  var $weakMapSet = callBound('WeakMap.prototype.set', true);
15  /** @type {<K extends object, V>(thisArg: WeakMap<K, V>, key: K) => boolean} */
16  var $weakMapHas = callBound('WeakMap.prototype.has', true);
17  /** @type {<K extends object, V>(thisArg: WeakMap<K, V>, key: K) => boolean} */
18  var $weakMapDelete = callBound('WeakMap.prototype.delete', true);
19  
20  /** @type {import('.')} */
21  module.exports = $WeakMap
22  	? /** @type {Exclude<import('.'), false>} */ function getSideChannelWeakMap() {
23  		/** @typedef {ReturnType<typeof getSideChannelWeakMap>} Channel */
24  		/** @typedef {Parameters<Channel['get']>[0]} K */
25  		/** @typedef {Parameters<Channel['set']>[1]} V */
26  
27  		/** @type {WeakMap<K & object, V> | undefined} */ var $wm;
28  		/** @type {Channel | undefined} */ var $m;
29  
30  		/** @type {Channel} */
31  		var channel = {
32  			assert: function (key) {
33  				if (!channel.has(key)) {
34  					throw new $TypeError('Side channel does not contain ' + inspect(key));
35  				}
36  			},
37  			'delete': function (key) {
38  				if ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) {
39  					if ($wm) {
40  						return $weakMapDelete($wm, key);
41  					}
42  				} else if (getSideChannelMap) {
43  					if ($m) {
44  						return $m['delete'](key);
45  					}
46  				}
47  				return false;
48  			},
49  			get: function (key) {
50  				if ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) {
51  					if ($wm) {
52  						return $weakMapGet($wm, key);
53  					}
54  				}
55  				return $m && $m.get(key);
56  			},
57  			has: function (key) {
58  				if ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) {
59  					if ($wm) {
60  						return $weakMapHas($wm, key);
61  					}
62  				}
63  				return !!$m && $m.has(key);
64  			},
65  			set: function (key, value) {
66  				if ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) {
67  					if (!$wm) {
68  						$wm = new $WeakMap();
69  					}
70  					$weakMapSet($wm, key, value);
71  				} else if (getSideChannelMap) {
72  					if (!$m) {
73  						$m = getSideChannelMap();
74  					}
75  					// eslint-disable-next-line no-extra-parens
76  					/** @type {NonNullable<typeof $m>} */ ($m).set(key, value);
77  				}
78  			}
79  		};
80  
81  		// @ts-expect-error TODO: figure out why this is erroring
82  		return channel;
83  	}
84  	: getSideChannelMap;