127 lines
4.2 KiB
JavaScript
127 lines
4.2 KiB
JavaScript
'use strict';
|
|
var redefineAll = require('../internals/redefine-all');
|
|
var getWeakData = require('../internals/internal-metadata').getWeakData;
|
|
var anObject = require('../internals/an-object');
|
|
var isObject = require('../internals/is-object');
|
|
var anInstance = require('../internals/an-instance');
|
|
var iterate = require('../internals/iterate');
|
|
var ArrayIterationModule = require('../internals/array-iteration');
|
|
var $has = require('../internals/has');
|
|
var InternalStateModule = require('../internals/internal-state');
|
|
|
|
var setInternalState = InternalStateModule.set;
|
|
var internalStateGetterFor = InternalStateModule.getterFor;
|
|
var find = ArrayIterationModule.find;
|
|
var findIndex = ArrayIterationModule.findIndex;
|
|
var id = 0;
|
|
|
|
// fallback for uncaught frozen keys
|
|
var uncaughtFrozenStore = function (store) {
|
|
return store.frozen || (store.frozen = new UncaughtFrozenStore());
|
|
};
|
|
|
|
var UncaughtFrozenStore = function () {
|
|
this.entries = [];
|
|
};
|
|
|
|
var findUncaughtFrozen = function (store, key) {
|
|
return find(store.entries, 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.entries.push([key, value]);
|
|
},
|
|
'delete': function (key) {
|
|
var index = findIndex(this.entries, function (it) {
|
|
return it[0] === key;
|
|
});
|
|
if (~index) this.entries.splice(index, 1);
|
|
return !!~index;
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
|
|
var C = wrapper(function (that, iterable) {
|
|
anInstance(that, C, CONSTRUCTOR_NAME);
|
|
setInternalState(that, {
|
|
type: CONSTRUCTOR_NAME,
|
|
id: id++,
|
|
frozen: undefined
|
|
});
|
|
if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
|
|
});
|
|
|
|
var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
|
|
|
|
var define = function (that, key, value) {
|
|
var state = getInternalState(that);
|
|
var data = getWeakData(anObject(key), true);
|
|
if (data === true) uncaughtFrozenStore(state).set(key, value);
|
|
else data[state.id] = value;
|
|
return that;
|
|
};
|
|
|
|
redefineAll(C.prototype, {
|
|
// `{ WeakMap, WeakSet }.prototype.delete(key)` methods
|
|
// https://tc39.es/ecma262/#sec-weakmap.prototype.delete
|
|
// https://tc39.es/ecma262/#sec-weakset.prototype.delete
|
|
'delete': function (key) {
|
|
var state = getInternalState(this);
|
|
if (!isObject(key)) return false;
|
|
var data = getWeakData(key);
|
|
if (data === true) return uncaughtFrozenStore(state)['delete'](key);
|
|
return data && $has(data, state.id) && delete data[state.id];
|
|
},
|
|
// `{ WeakMap, WeakSet }.prototype.has(key)` methods
|
|
// https://tc39.es/ecma262/#sec-weakmap.prototype.has
|
|
// https://tc39.es/ecma262/#sec-weakset.prototype.has
|
|
has: function has(key) {
|
|
var state = getInternalState(this);
|
|
if (!isObject(key)) return false;
|
|
var data = getWeakData(key);
|
|
if (data === true) return uncaughtFrozenStore(state).has(key);
|
|
return data && $has(data, state.id);
|
|
}
|
|
});
|
|
|
|
redefineAll(C.prototype, IS_MAP ? {
|
|
// `WeakMap.prototype.get(key)` method
|
|
// https://tc39.es/ecma262/#sec-weakmap.prototype.get
|
|
get: function get(key) {
|
|
var state = getInternalState(this);
|
|
if (isObject(key)) {
|
|
var data = getWeakData(key);
|
|
if (data === true) return uncaughtFrozenStore(state).get(key);
|
|
return data ? data[state.id] : undefined;
|
|
}
|
|
},
|
|
// `WeakMap.prototype.set(key, value)` method
|
|
// https://tc39.es/ecma262/#sec-weakmap.prototype.set
|
|
set: function set(key, value) {
|
|
return define(this, key, value);
|
|
}
|
|
} : {
|
|
// `WeakSet.prototype.add(value)` method
|
|
// https://tc39.es/ecma262/#sec-weakset.prototype.add
|
|
add: function add(value) {
|
|
return define(this, value, true);
|
|
}
|
|
});
|
|
|
|
return C;
|
|
}
|
|
};
|