blob: ac8a413a31050565dcc8d56f507274455acfe136 [file] [log] [blame]
'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, 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, {
// 23.3.3.2 WeakMap.prototype.delete(key)
// 23.4.3.3 WeakSet.prototype.delete(value)
'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];
},
// 23.3.3.4 WeakMap.prototype.has(key)
// 23.4.3.4 WeakSet.prototype.has(value)
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 ? {
// 23.3.3.3 WeakMap.prototype.get(key)
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;
}
},
// 23.3.3.5 WeakMap.prototype.set(key, value)
set: function set(key, value) {
return define(this, key, value);
}
} : {
// 23.4.3.1 WeakSet.prototype.add(value)
add: function add(value) {
return define(this, value, true);
}
});
return C;
}
};