Skip to content

Instantly share code, notes, and snippets.

@think49
Last active July 1, 2017 21:46
Show Gist options
  • Save think49/283b7374e352e09fc131 to your computer and use it in GitHub Desktop.
Save think49/283b7374e352e09fc131 to your computer and use it in GitHub Desktop.
es6-weakmap.js: ECMA-262 6th Edition (ECMAScript 2015) WeakMap polyfill
/**
* es6-weakmap.js
* WeakMap (ECMA-262 6th Edition / ECMAScript 2015)
*
*
* @version 0.9.2
* @author think49
* @url https://gist.github.com/think49/283b7374e352e09fc131
* @license http://www.opensource.org/licenses/mit-license.php (The MIT License)
* @see <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-weakmap-constructor">23.3.1 The WeakMap Constructor – ECMA-262 6th Edition</a>
*/
'use strict';
if (typeof WeakMap !== 'function' && typeof Object.defineProperties === 'function') {
var WeakMap = (function (Object, isArray) {
var weakMapDataList = []; // [[WeakMapData]] internal slot
function WeakMap (/* [iterable] */) {
weakMapDataList.push([this, []]);
}
Object.defineProperties(WeakMap.prototype, {
get: {
writable: true,
enumerable: false,
configurable: true,
value: function get (key) {
if (Object(this) !== this) { // 2. If Type(thisArg) is not Object, throw a TypeError exception.
throw new TypeError('Method WeakMap.prototype.get called on incompatible receiver ' + this);
}
var i = 0,
l = weakMapDataList.length,
weakMapData, map, data;
while (i < l) {
weakMapData = weakMapDataList[i++];
if (weakMapData[0] === this) {
if (Object(key) !== key) { // 5. If Type(key) is not Object, return undefined.
return;
}
map = weakMapData[1];
i = 0,
l = map.length;
while (i < l) {
data = map[i++];
if (data[0] === key) {
return data[1];
}
}
return;
}
}
throw new TypeError('Method WeakMap.prototype.get called on incompatible receiver ' + this); // 3. If thisArg does not have a [[WeakMapData]] internal slot, throw a TypeError exception.
}
},
set: {
writable: true,
enumerable: false,
configurable: true,
value: function set (key, value) {
if (Object(this) !== this) { // 2. If Type(thisArg) is not Object, throw a TypeError exception.
throw new TypeError('Method WeakMap.prototype.set called on incompatible receiver ' + this);
}
var i = 0,
l = weakMapDataList.length,
weakMapData, map, data;
while (i < l) {
weakMapData = weakMapDataList[i++];
if (weakMapData[0] === this) {
if (Object(key) !== key) { // 5. If Type(key) is not Object, throw a TypeError exception.
throw new TypeError('Invalid value used as weak map key');
}
map = weakMapData[1];
i = 0,
l = map.length;
while (i < l) {
data = map[i++];
if (data[0] === key) {
data[1] = value;
return this;
}
}
map.push([key, value]);
return this;
}
}
throw new TypeError('Method WeakMap.prototype.set called on incompatible receiver ' + this); // 3. If thisArg does not have a [[WeakMapData]] internal slot, throw a TypeError exception.
}
},
has: {
writable: true,
enumerable: false,
configurable: true,
value: function has (key) {
if (Object(this) !== this) { // 2. If Type(thisArg) is not Object, throw a TypeError exception.exception.
throw new TypeError('Method WeakMap.prototype.has called on incompatible receiver ' + this);
}
var i = 0,
l = weakMapDataList.length,
weakMapData, map;
while (i < l) {
weakMapData = weakMapDataList[i++]; // [[WeakMapData]] internal slot
if (weakMapData[0] === this) {
if (Object(key) !== key) { // 5. If Type(key) is not Object, return false.
return false;
}
map = weakMapData[1];
i = 0,
l = map.length;
while (i < l) {
if (map[i++][0] === key) {
return true;
}
}
return false;
}
}
throw new TypeError('Method WeakMap.prototype.has called on incompatible receiver ' + this); // 3. If thisArg does not have a [[WeakMapData]] internal slot, throw a TypeError exception.
}
},
delete: {
writable: true,
enumerable: false,
configurable: true,
value: function delete_ (key) { // Note: If you specify the "delete" for SyntaxError occurs, it is replaced by "delete_"
if (Object(this) !== this) { // 2. If Type(thisArg) is not Object, throw a TypeError exception.
throw new TypeError('Method WeakMap.prototype.delete called on incompatible receiver ' + this);
}
var i = 0,
l = weakMapDataList.length,
weakMapData, map;
while (i < l) {
weakMapData = weakMapDataList[i++]; // [[WeakMapData]] internal slot
if (weakMapData[0] === this) {
if (Object(key) !== key) { // 5. If Type(key) is not Object, return false.
return false;
}
map = weakMapData[1];
i = 0,
l = map.length;
while (i < l) {
if (map[i++][0] === key) {
weakMapData[1] = map.slice(0, i - 1).concat(map.slice(i));
return true;
}
}
return false;
}
}
throw new TypeError('Method WeakMap.prototype.delete called on incompatible receiver ' + this); // 3. If thisArg does not have a [[WeakMapData]] internal slot, throw a TypeError exception.
}
}
});
return WeakMap;
}(Object, Array.isArray));
}