You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
2.7 KiB
85 lines
2.7 KiB
'use strict'; |
|
var redefineAll = require('./_redefine-all'); |
|
var getWeak = require('./_meta').getWeak; |
|
var anObject = require('./_an-object'); |
|
var isObject = require('./_is-object'); |
|
var anInstance = require('./_an-instance'); |
|
var forOf = require('./_for-of'); |
|
var createArrayMethod = require('./_array-methods'); |
|
var $has = require('./_has'); |
|
var validate = require('./_validate-collection'); |
|
var arrayFind = createArrayMethod(5); |
|
var arrayFindIndex = createArrayMethod(6); |
|
var id = 0; |
|
|
|
// fallback for uncaught frozen keys |
|
var uncaughtFrozenStore = function (that) { |
|
return that._l || (that._l = new UncaughtFrozenStore()); |
|
}; |
|
var UncaughtFrozenStore = function () { |
|
this.a = []; |
|
}; |
|
var findUncaughtFrozen = function (store, key) { |
|
return arrayFind(store.a, function (it) { |
|
return it[0] === key; |
|
}); |
|
}; |
|
UncaughtFrozenStore.prototype = { |
|
get: function (key) { |
|
var entry = findUncaughtFrozen(this, key); |
|
if (entry) return entry[1]; |
|
}, |
|
has: function (key) { |
|
return !!findUncaughtFrozen(this, key); |
|
}, |
|
set: function (key, value) { |
|
var entry = findUncaughtFrozen(this, key); |
|
if (entry) entry[1] = value; |
|
else this.a.push([key, value]); |
|
}, |
|
'delete': function (key) { |
|
var index = arrayFindIndex(this.a, function (it) { |
|
return it[0] === key; |
|
}); |
|
if (~index) this.a.splice(index, 1); |
|
return !!~index; |
|
} |
|
}; |
|
|
|
module.exports = { |
|
getConstructor: function (wrapper, NAME, IS_MAP, ADDER) { |
|
var C = wrapper(function (that, iterable) { |
|
anInstance(that, C, NAME, '_i'); |
|
that._t = NAME; // collection type |
|
that._i = id++; // collection id |
|
that._l = undefined; // leak store for uncaught frozen objects |
|
if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that); |
|
}); |
|
redefineAll(C.prototype, { |
|
// 23.3.3.2 WeakMap.prototype.delete(key) |
|
// 23.4.3.3 WeakSet.prototype.delete(value) |
|
'delete': function (key) { |
|
if (!isObject(key)) return false; |
|
var data = getWeak(key); |
|
if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key); |
|
return data && $has(data, this._i) && delete data[this._i]; |
|
}, |
|
// 23.3.3.4 WeakMap.prototype.has(key) |
|
// 23.4.3.4 WeakSet.prototype.has(value) |
|
has: function has(key) { |
|
if (!isObject(key)) return false; |
|
var data = getWeak(key); |
|
if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key); |
|
return data && $has(data, this._i); |
|
} |
|
}); |
|
return C; |
|
}, |
|
def: function (that, key, value) { |
|
var data = getWeak(anObject(key), true); |
|
if (data === true) uncaughtFrozenStore(that).set(key, value); |
|
else data[that._i] = value; |
|
return that; |
|
}, |
|
ufstore: uncaughtFrozenStore |
|
};
|
|
|