1 /* 2 * Filename: WeakMap.js 3 * Created By: Ranando D. King 4 * License: Apache 2.0 5 * 6 * Copyright 2014 Ranando D. King 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 var WEAKMAP = "__$WEAKMAP$__", 21 WEAKMAPDATA = "__$WEAKMAPDATA$__"; 22 23 var WeakMapShim = function createWeakMapShim() { 24 //Unique key bank. 25 var keys = []; 26 27 var guid = function guid() { 28 function s4() { 29 return Math.floor((1 + Math.random()) * 0x10000) 30 .toString(16) 31 .substring(1); 32 } 33 34 return s4() + s4() + '-' + s4() + '-' + s4() + '-' + 35 s4() + '-' + s4() + s4() + s4(); 36 }; 37 38 //Constructor 39 var $ = function WeakMap(preload) { 40 Object.defineProperty(this, "_id", { 41 enumerable: false, 42 configurable: false, 43 writable: true, 44 value: guid() 45 }); 46 47 var isArray = Array.isArray(preload); 48 for (var elementId in preload) { 49 if (preload.hasOwnProperty(elementId)) { 50 var element = preload[elementId]; 51 52 if (isArray) 53 this.set(element[0], element[1]); 54 else 55 this.set(elementId, element); 56 } 57 } 58 }; 59 60 Object.defineProperty($.prototype, "get", { 61 enumerable: false, 62 configurable: false, 63 writable: false, 64 value: function (key) { 65 var retval; 66 if ((typeof key == "object") && 67 key[WEAKMAP] && key[WEAKMAPDATA] && 68 key[WEAKMAPDATA][this._id]) { 69 retval = key[WEAKMAPDATA][this._id][keys.indexOf(key[WEAKMAP])]; 70 } 71 72 return retval; 73 } 74 }); 75 76 Object.defineProperty($.prototype, "set", { 77 enumerable: false, 78 configurable: false, 79 writable: false, 80 value: function (key, value) { 81 if (typeof key != "object") 82 throw new Error("Invalid Key! WeakMap keys must be Objects!"); 83 84 //Get a unique value for this key if it doesn't already have one. 85 if (!key.hasOwnProperty(WEAKMAP)) { 86 Object.defineProperty(key, WEAKMAP, { 87 enumerable: false, 88 configurable: false, 89 writable: false, 90 value: (function () { 91 var retval = null; 92 93 do{ 94 var newKey = guid(); 95 96 if (keys.indexOf(newKey) == -1) { 97 keys.push(newKey); 98 retval = newKey; 99 } 100 } while (retval == null); 101 102 return retval; 103 })() 104 }); 105 } 106 107 //Make sure key has a datastore for the weak map's data. 108 if (!key.hasOwnProperty(WEAKMAPDATA)) { 109 Object.defineProperty(key, WEAKMAPDATA, { 110 enumerable: false, 111 configurable: false, 112 writable: false, 113 value: {} 114 }); 115 } 116 117 if (!key[WEAKMAPDATA][this._id]) 118 key[WEAKMAPDATA][this._id] = []; 119 120 key[WEAKMAPDATA][this._id][keys.indexOf(key[WEAKMAP])] = value; 121 } 122 }); 123 124 Object.defineProperty($.prototype, "has", { 125 enumerable: false, 126 configurable: false, 127 writable: false, 128 value: function (key) { 129 var retval = false; 130 if ((typeof key != "object") && 131 key[WEAKMAP] && key[WEAKMAPDATA] && 132 key[WEAKMAPDATA][this._id]) { 133 retval = key[WEAKMAPDATA][this._id].hasOwnProperty(keys.indexOf(key[WEAKMAP])); 134 } 135 136 return retval; 137 } 138 }); 139 140 Object.defineProperty($.prototype, "delete", { 141 enumerable: false, 142 configurable: false, 143 writable: false, 144 value: function (key) { 145 if ((typeof key != "object") && 146 key[WEAKMAP] && key[WEAKMAPDATA] && 147 key[WEAKMAPDATA][this._id]) { 148 delete key[WEAKMAPDATA][this._id][keys.indexOf(key[WEAKMAP])]; 149 } 150 } 151 }); 152 153 Object.defineProperty($.prototype, "clear", { 154 enumerable: false, 155 configurable: false, 156 writable: false, 157 value: function() { 158 this._id = guid(); 159 } 160 }); 161 162 Object.defineProperty($.prototype, "length", { 163 enumerable: false, 164 configurable: false, 165 writable: false, 166 value: 1 167 }); 168 169 Object.seal($); 170 return $; 171 }; 172 173 var WM; 174 if (typeof WeakMap != "function") 175 WM = WeakMapShim(); 176 else 177 /*eslint-disable-next-line no-undef */ 178 WM = WeakMap; 179 180 //If some form of require.js exists, export the class 181 if (module && exports && module.exports === exports) 182 module.exports = WM; 183