2 var defineProperty = require('../internals/object-define-property').f;
3 var create = require('../internals/object-create');
4 var redefineAll = require('../internals/redefine-all');
5 var bind = require('../internals/function-bind-context');
6 var anInstance = require('../internals/an-instance');
7 var iterate = require('../internals/iterate');
8 var defineIterator = require('../internals/define-iterator');
9 var setSpecies = require('../internals/set-species');
10 var DESCRIPTORS = require('../internals/descriptors');
11 var fastKey = require('../internals/internal-metadata').fastKey;
12 var InternalStateModule = require('../internals/internal-state');
14 var setInternalState = InternalStateModule.set;
15 var internalStateGetterFor = InternalStateModule.getterFor;
18 getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
19 var Constructor = wrapper(function (that, iterable) {
20 anInstance(that, Prototype);
21 setInternalState(that, {
22 type: CONSTRUCTOR_NAME,
28 if (!DESCRIPTORS) that.size = 0;
29 if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
32 var Prototype = Constructor.prototype;
34 var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
36 var define = function (that, key, value) {
37 var state = getInternalState(that);
38 var entry = getEntry(that, key);
40 // change existing entry
45 state.last = entry = {
46 index: index = fastKey(key, true),
49 previous: previous = state.last,
53 if (!state.first) state.first = entry;
54 if (previous) previous.next = entry;
55 if (DESCRIPTORS) state.size++;
58 if (index !== 'F') state.index[index] = entry;
62 var getEntry = function (that, key) {
63 var state = getInternalState(that);
65 var index = fastKey(key);
67 if (index !== 'F') return state.index[index];
69 for (entry = state.first; entry; entry = entry.next) {
70 if (entry.key == key) return entry;
74 redefineAll(Prototype, {
75 // `{ Map, Set }.prototype.clear()` methods
76 // https://tc39.es/ecma262/#sec-map.prototype.clear
77 // https://tc39.es/ecma262/#sec-set.prototype.clear
78 clear: function clear() {
80 var state = getInternalState(that);
81 var data = state.index;
82 var entry = state.first;
85 if (entry.previous) entry.previous = entry.previous.next = undefined;
86 delete data[entry.index];
89 state.first = state.last = undefined;
90 if (DESCRIPTORS) state.size = 0;
93 // `{ Map, Set }.prototype.delete(key)` methods
94 // https://tc39.es/ecma262/#sec-map.prototype.delete
95 // https://tc39.es/ecma262/#sec-set.prototype.delete
96 'delete': function (key) {
98 var state = getInternalState(that);
99 var entry = getEntry(that, key);
101 var next = entry.next;
102 var prev = entry.previous;
103 delete state.index[entry.index];
104 entry.removed = true;
105 if (prev) prev.next = next;
106 if (next) next.previous = prev;
107 if (state.first == entry) state.first = next;
108 if (state.last == entry) state.last = prev;
109 if (DESCRIPTORS) state.size--;
113 // `{ Map, Set }.prototype.forEach(callbackfn, thisArg = undefined)` methods
114 // https://tc39.es/ecma262/#sec-map.prototype.foreach
115 // https://tc39.es/ecma262/#sec-set.prototype.foreach
116 forEach: function forEach(callbackfn /* , that = undefined */) {
117 var state = getInternalState(this);
118 var boundFunction = bind(callbackfn, arguments.length > 1 ? arguments[1] : undefined);
120 while (entry = entry ? entry.next : state.first) {
121 boundFunction(entry.value, entry.key, this);
122 // revert to the last existing entry
123 while (entry && entry.removed) entry = entry.previous;
126 // `{ Map, Set}.prototype.has(key)` methods
127 // https://tc39.es/ecma262/#sec-map.prototype.has
128 // https://tc39.es/ecma262/#sec-set.prototype.has
129 has: function has(key) {
130 return !!getEntry(this, key);
134 redefineAll(Prototype, IS_MAP ? {
135 // `Map.prototype.get(key)` method
136 // https://tc39.es/ecma262/#sec-map.prototype.get
137 get: function get(key) {
138 var entry = getEntry(this, key);
139 return entry && entry.value;
141 // `Map.prototype.set(key, value)` method
142 // https://tc39.es/ecma262/#sec-map.prototype.set
143 set: function set(key, value) {
144 return define(this, key === 0 ? 0 : key, value);
147 // `Set.prototype.add(value)` method
148 // https://tc39.es/ecma262/#sec-set.prototype.add
149 add: function add(value) {
150 return define(this, value = value === 0 ? 0 : value, value);
153 if (DESCRIPTORS) defineProperty(Prototype, 'size', {
155 return getInternalState(this).size;
160 setStrong: function (Constructor, CONSTRUCTOR_NAME, IS_MAP) {
161 var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator';
162 var getInternalCollectionState = internalStateGetterFor(CONSTRUCTOR_NAME);
163 var getInternalIteratorState = internalStateGetterFor(ITERATOR_NAME);
164 // `{ Map, Set }.prototype.{ keys, values, entries, @@iterator }()` methods
165 // https://tc39.es/ecma262/#sec-map.prototype.entries
166 // https://tc39.es/ecma262/#sec-map.prototype.keys
167 // https://tc39.es/ecma262/#sec-map.prototype.values
168 // https://tc39.es/ecma262/#sec-map.prototype-@@iterator
169 // https://tc39.es/ecma262/#sec-set.prototype.entries
170 // https://tc39.es/ecma262/#sec-set.prototype.keys
171 // https://tc39.es/ecma262/#sec-set.prototype.values
172 // https://tc39.es/ecma262/#sec-set.prototype-@@iterator
173 defineIterator(Constructor, CONSTRUCTOR_NAME, function (iterated, kind) {
174 setInternalState(this, {
177 state: getInternalCollectionState(iterated),
182 var state = getInternalIteratorState(this);
183 var kind = state.kind;
184 var entry = state.last;
185 // revert to the last existing entry
186 while (entry && entry.removed) entry = entry.previous;
188 if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) {
189 // or finish the iteration
190 state.target = undefined;
191 return { value: undefined, done: true };
193 // return step by kind
194 if (kind == 'keys') return { value: entry.key, done: false };
195 if (kind == 'values') return { value: entry.value, done: false };
196 return { value: [entry.key, entry.value], done: false };
197 }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);
199 // `{ Map, Set }.prototype[@@species]` accessors
200 // https://tc39.es/ecma262/#sec-get-map-@@species
201 // https://tc39.es/ecma262/#sec-get-set-@@species
202 setSpecies(CONSTRUCTOR_NAME);