UNPKG

4.52 kBJavaScriptView Raw
1'use strict';
2var uncurryThis = require('../internals/function-uncurry-this');
3var defineBuiltIns = require('../internals/define-built-ins');
4var getWeakData = require('../internals/internal-metadata').getWeakData;
5var anInstance = require('../internals/an-instance');
6var anObject = require('../internals/an-object');
7var isNullOrUndefined = require('../internals/is-null-or-undefined');
8var isObject = require('../internals/is-object');
9var iterate = require('../internals/iterate');
10var ArrayIterationModule = require('../internals/array-iteration');
11var hasOwn = require('../internals/has-own-property');
12var InternalStateModule = require('../internals/internal-state');
13
14var setInternalState = InternalStateModule.set;
15var internalStateGetterFor = InternalStateModule.getterFor;
16var find = ArrayIterationModule.find;
17var findIndex = ArrayIterationModule.findIndex;
18var splice = uncurryThis([].splice);
19var id = 0;
20
21// fallback for uncaught frozen keys
22var uncaughtFrozenStore = function (state) {
23 return state.frozen || (state.frozen = new UncaughtFrozenStore());
24};
25
26var UncaughtFrozenStore = function () {
27 this.entries = [];
28};
29
30var findUncaughtFrozen = function (store, key) {
31 return find(store.entries, function (it) {
32 return it[0] === key;
33 });
34};
35
36UncaughtFrozenStore.prototype = {
37 get: function (key) {
38 var entry = findUncaughtFrozen(this, key);
39 if (entry) return entry[1];
40 },
41 has: function (key) {
42 return !!findUncaughtFrozen(this, key);
43 },
44 set: function (key, value) {
45 var entry = findUncaughtFrozen(this, key);
46 if (entry) entry[1] = value;
47 else this.entries.push([key, value]);
48 },
49 'delete': function (key) {
50 var index = findIndex(this.entries, function (it) {
51 return it[0] === key;
52 });
53 if (~index) splice(this.entries, index, 1);
54 return !!~index;
55 }
56};
57
58module.exports = {
59 getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
60 var Constructor = wrapper(function (that, iterable) {
61 anInstance(that, Prototype);
62 setInternalState(that, {
63 type: CONSTRUCTOR_NAME,
64 id: id++,
65 frozen: undefined
66 });
67 if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
68 });
69
70 var Prototype = Constructor.prototype;
71
72 var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
73
74 var define = function (that, key, value) {
75 var state = getInternalState(that);
76 var data = getWeakData(anObject(key), true);
77 if (data === true) uncaughtFrozenStore(state).set(key, value);
78 else data[state.id] = value;
79 return that;
80 };
81
82 defineBuiltIns(Prototype, {
83 // `{ WeakMap, WeakSet }.prototype.delete(key)` methods
84 // https://tc39.es/ecma262/#sec-weakmap.prototype.delete
85 // https://tc39.es/ecma262/#sec-weakset.prototype.delete
86 'delete': function (key) {
87 var state = getInternalState(this);
88 if (!isObject(key)) return false;
89 var data = getWeakData(key);
90 if (data === true) return uncaughtFrozenStore(state)['delete'](key);
91 return data && hasOwn(data, state.id) && delete data[state.id];
92 },
93 // `{ WeakMap, WeakSet }.prototype.has(key)` methods
94 // https://tc39.es/ecma262/#sec-weakmap.prototype.has
95 // https://tc39.es/ecma262/#sec-weakset.prototype.has
96 has: function has(key) {
97 var state = getInternalState(this);
98 if (!isObject(key)) return false;
99 var data = getWeakData(key);
100 if (data === true) return uncaughtFrozenStore(state).has(key);
101 return data && hasOwn(data, state.id);
102 }
103 });
104
105 defineBuiltIns(Prototype, IS_MAP ? {
106 // `WeakMap.prototype.get(key)` method
107 // https://tc39.es/ecma262/#sec-weakmap.prototype.get
108 get: function get(key) {
109 var state = getInternalState(this);
110 if (isObject(key)) {
111 var data = getWeakData(key);
112 if (data === true) return uncaughtFrozenStore(state).get(key);
113 return data ? data[state.id] : undefined;
114 }
115 },
116 // `WeakMap.prototype.set(key, value)` method
117 // https://tc39.es/ecma262/#sec-weakmap.prototype.set
118 set: function set(key, value) {
119 return define(this, key, value);
120 }
121 } : {
122 // `WeakSet.prototype.add(value)` method
123 // https://tc39.es/ecma262/#sec-weakset.prototype.add
124 add: function add(value) {
125 return define(this, value, true);
126 }
127 });
128
129 return Constructor;
130 }
131};