| 'use strict'; | 
|   | 
| var GetIntrinsic = require('get-intrinsic'); | 
| var callBound = require('call-bind/callBound'); | 
| var inspect = require('object-inspect'); | 
|   | 
| var $TypeError = GetIntrinsic('%TypeError%'); | 
| var $WeakMap = GetIntrinsic('%WeakMap%', true); | 
| var $Map = GetIntrinsic('%Map%', true); | 
|   | 
| var $weakMapGet = callBound('WeakMap.prototype.get', true); | 
| var $weakMapSet = callBound('WeakMap.prototype.set', true); | 
| var $weakMapHas = callBound('WeakMap.prototype.has', true); | 
| var $mapGet = callBound('Map.prototype.get', true); | 
| var $mapSet = callBound('Map.prototype.set', true); | 
| var $mapHas = callBound('Map.prototype.has', true); | 
|   | 
| /* | 
|  * This function traverses the list returning the node corresponding to the | 
|  * given key. | 
|  * | 
|  * 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. | 
|  */ | 
| var listGetNode = function (list, key) { // eslint-disable-line consistent-return | 
|     for (var prev = list, curr; (curr = prev.next) !== null; prev = curr) { | 
|         if (curr.key === key) { | 
|             prev.next = curr.next; | 
|             curr.next = list.next; | 
|             list.next = curr; // eslint-disable-line no-param-reassign | 
|             return curr; | 
|         } | 
|     } | 
| }; | 
|   | 
| var listGet = function (objects, key) { | 
|     var node = listGetNode(objects, key); | 
|     return node && node.value; | 
| }; | 
| var listSet = function (objects, key, value) { | 
|     var node = listGetNode(objects, key); | 
|     if (node) { | 
|         node.value = value; | 
|     } else { | 
|         // Prepend the new node to the beginning of the list | 
|         objects.next = { // eslint-disable-line no-param-reassign | 
|             key: key, | 
|             next: objects.next, | 
|             value: value | 
|         }; | 
|     } | 
| }; | 
| var listHas = function (objects, key) { | 
|     return !!listGetNode(objects, key); | 
| }; | 
|   | 
| module.exports = function getSideChannel() { | 
|     var $wm; | 
|     var $m; | 
|     var $o; | 
|     var channel = { | 
|         assert: function (key) { | 
|             if (!channel.has(key)) { | 
|                 throw new $TypeError('Side channel does not contain ' + inspect(key)); | 
|             } | 
|         }, | 
|         get: function (key) { // eslint-disable-line consistent-return | 
|             if ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) { | 
|                 if ($wm) { | 
|                     return $weakMapGet($wm, key); | 
|                 } | 
|             } else if ($Map) { | 
|                 if ($m) { | 
|                     return $mapGet($m, key); | 
|                 } | 
|             } else { | 
|                 if ($o) { // eslint-disable-line no-lonely-if | 
|                     return listGet($o, key); | 
|                 } | 
|             } | 
|         }, | 
|         has: function (key) { | 
|             if ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) { | 
|                 if ($wm) { | 
|                     return $weakMapHas($wm, key); | 
|                 } | 
|             } else if ($Map) { | 
|                 if ($m) { | 
|                     return $mapHas($m, key); | 
|                 } | 
|             } else { | 
|                 if ($o) { // eslint-disable-line no-lonely-if | 
|                     return listHas($o, key); | 
|                 } | 
|             } | 
|             return false; | 
|         }, | 
|         set: function (key, value) { | 
|             if ($WeakMap && key && (typeof key === 'object' || typeof key === 'function')) { | 
|                 if (!$wm) { | 
|                     $wm = new $WeakMap(); | 
|                 } | 
|                 $weakMapSet($wm, key, value); | 
|             } else if ($Map) { | 
|                 if (!$m) { | 
|                     $m = new $Map(); | 
|                 } | 
|                 $mapSet($m, key, value); | 
|             } else { | 
|                 if (!$o) { | 
|                     /* | 
|                      * 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 | 
|                      */ | 
|                     $o = { key: {}, next: null }; | 
|                 } | 
|                 listSet($o, key, value); | 
|             } | 
|         } | 
|     }; | 
|     return channel; | 
| }; |