source: imaps-frontend/node_modules/side-channel/index.js@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 3.9 KB
Line 
1'use strict';
2
3var GetIntrinsic = require('get-intrinsic');
4var callBound = require('call-bind/callBound');
5var inspect = require('object-inspect');
6
7var $TypeError = require('es-errors/type');
8var $WeakMap = GetIntrinsic('%WeakMap%', true);
9var $Map = GetIntrinsic('%Map%', true);
10
11var $weakMapGet = callBound('WeakMap.prototype.get', true);
12var $weakMapSet = callBound('WeakMap.prototype.set', true);
13var $weakMapHas = callBound('WeakMap.prototype.has', true);
14var $mapGet = callBound('Map.prototype.get', true);
15var $mapSet = callBound('Map.prototype.set', true);
16var $mapHas = callBound('Map.prototype.has', true);
17
18/*
19* This function traverses the list returning the node corresponding to the given key.
20*
21* That node is also moved to the head of the list, so that if it's accessed again we don't need to traverse the whole list. By doing so, all the recently used nodes can be accessed relatively quickly.
22*/
23/** @type {import('.').listGetNode} */
24var listGetNode = function (list, key) { // eslint-disable-line consistent-return
25 /** @type {typeof list | NonNullable<(typeof list)['next']>} */
26 var prev = list;
27 /** @type {(typeof list)['next']} */
28 var curr;
29 for (; (curr = prev.next) !== null; prev = curr) {
30 if (curr.key === key) {
31 prev.next = curr.next;
32 // eslint-disable-next-line no-extra-parens
33 curr.next = /** @type {NonNullable<typeof list.next>} */ (list.next);
34 list.next = curr; // eslint-disable-line no-param-reassign
35 return curr;
36 }
37 }
38};
39
40/** @type {import('.').listGet} */
41var listGet = function (objects, key) {
42 var node = listGetNode(objects, key);
43 return node && node.value;
44};
45/** @type {import('.').listSet} */
46var listSet = function (objects, key, value) {
47 var node = listGetNode(objects, key);
48 if (node) {
49 node.value = value;
50 } else {
51 // Prepend the new node to the beginning of the list
52 objects.next = /** @type {import('.').ListNode<typeof value>} */ ({ // eslint-disable-line no-param-reassign, no-extra-parens
53 key: key,
54 next: objects.next,
55 value: value
56 });
57 }
58};
59/** @type {import('.').listHas} */
60var listHas = function (objects, key) {
61 return !!listGetNode(objects, key);
62};
63
64/** @type {import('.')} */
65module.exports = function getSideChannel() {
66 /** @type {WeakMap<object, unknown>} */ var $wm;
67 /** @type {Map<object, unknown>} */ var $m;
68 /** @type {import('.').RootNode<unknown>} */ var $o;
69
70 /** @type {import('.').Channel} */
71 var channel = {
72 assert: function (key) {
73 if (!channel.has(key)) {
74 throw new $TypeError('Side channel does not contain ' + inspect(key));
75 }
76 },
77 get: function (key) { // eslint-disable-line consistent-return
78 if ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) {
79 if ($wm) {
80 return $weakMapGet($wm, key);
81 }
82 } else if ($Map) {
83 if ($m) {
84 return $mapGet($m, key);
85 }
86 } else {
87 if ($o) { // eslint-disable-line no-lonely-if
88 return listGet($o, key);
89 }
90 }
91 },
92 has: function (key) {
93 if ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) {
94 if ($wm) {
95 return $weakMapHas($wm, key);
96 }
97 } else if ($Map) {
98 if ($m) {
99 return $mapHas($m, key);
100 }
101 } else {
102 if ($o) { // eslint-disable-line no-lonely-if
103 return listHas($o, key);
104 }
105 }
106 return false;
107 },
108 set: function (key, value) {
109 if ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) {
110 if (!$wm) {
111 $wm = new $WeakMap();
112 }
113 $weakMapSet($wm, key, value);
114 } else if ($Map) {
115 if (!$m) {
116 $m = new $Map();
117 }
118 $mapSet($m, key, value);
119 } else {
120 if (!$o) {
121 // Initialize the linked list as an empty node, so that we don't have to special-case handling of the first node: we can always refer to it as (previous node).next, instead of something like (list).head
122 $o = { key: {}, next: null };
123 }
124 listSet($o, key, value);
125 }
126 }
127 };
128 return channel;
129};
Note: See TracBrowser for help on using the repository browser.