1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
'use strict';
var dP = require('./_object-dp').f
, create = require('./_object-create')
, redefineAll = require('./_redefine-all')
, ctx = require('./_ctx')
, anInstance = require('./_an-instance')
, defined = require('./_defined')
, forOf = require('./_for-of')
, $iterDefine = require('./_iter-define')
, step = require('./_iter-step')
, setSpecies = require('./_set-species')
, DESCRIPTORS = require('./_descriptors')
, fastKey = require('./_meta').fastKey
, SIZE = DESCRIPTORS ? '_s' : 'size';
var getEntry = function(that, key){
// fast case
var index = fastKey(key), entry;
if(index !== 'F')return that._i[index];
// frozen object case
for(entry = that._f; entry; entry = entry.n){
if(entry.k == key)return entry;
}
};
module.exports = {
getConstructor: function(wrapper, NAME, IS_MAP, ADDER){
var C = wrapper(function(that, iterable){
anInstance(that, C, NAME, '_i');
that._i = create(null); // index
that._f = undefined; // first entry
that._l = undefined; // last entry
that[SIZE] = 0; // size
if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that);
});
redefineAll(C.prototype, {
// 23.1.3.1 Map.prototype.clear()
// 23.2.3.2 Set.prototype.clear()
clear: function clear(){
for(var that = this, data = that._i, entry = that._f; entry; entry = entry.n){
entry.r = true;
if(entry.p)entry.p = entry.p.n = undefined;
delete data[entry.i];
}
that._f = that._l = undefined;
that[SIZE] = 0;
},
// 23.1.3.3 Map.prototype.delete(key)
// 23.2.3.4 Set.prototype.delete(value)
'delete': function(key){
var that = this
, entry = getEntry(that, key);
if(entry){
var next = entry.n
, prev = entry.p;
delete that._i[entry.i];
entry.r = true;
if(prev)prev.n = next;
if(next)next.p = prev;
if(that._f == entry)that._f = next;
if(that._l == entry)that._l = prev;
that[SIZE]--;
} return !!entry;
},
// 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined)
// 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined)
forEach: function forEach(callbackfn /*, that = undefined */){
anInstance(this, C, 'forEach');
var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3)
, entry;
while(entry = entry ? entry.n : this._f){
f(entry.v, entry.k, this);
// revert to the last existing entry
while(entry && entry.r)entry = entry.p;
}
},
// 23.1.3.7 Map.prototype.has(key)
// 23.2.3.7 Set.prototype.has(value)
has: function has(key){
return !!getEntry(this, key);
}
});
if(DESCRIPTORS)dP(C.prototype, 'size', {
get: function(){
return defined(this[SIZE]);
}
});
return C;
},
def: function(that, key, value){
var entry = getEntry(that, key)
, prev, index;
// change existing entry
if(entry){
entry.v = value;
// create new entry
} else {
that._l = entry = {
i: index = fastKey(key, true), // <- index
k: key, // <- key
v: value, // <- value
p: prev = that._l, // <- previous entry
n: undefined, // <- next entry
r: false // <- removed
};
if(!that._f)that._f = entry;
if(prev)prev.n = entry;
that[SIZE]++;
// add to index
if(index !== 'F')that._i[index] = entry;
} return that;
},
getEntry: getEntry,
setStrong: function(C, NAME, IS_MAP){
// add .keys, .values, .entries, [@@iterator]
// 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11
$iterDefine(C, NAME, function(iterated, kind){
this._t = iterated; // target
this._k = kind; // kind
this._l = undefined; // previous
}, function(){
var that = this
, kind = that._k
, entry = that._l;
// revert to the last existing entry
while(entry && entry.r)entry = entry.p;
// get next entry
if(!that._t || !(that._l = entry = entry ? entry.n : that._t._f)){
// or finish the iteration
that._t = undefined;
return step(1);
}
// return step by kind
if(kind == 'keys' )return step(0, entry.k);
if(kind == 'values')return step(0, entry.v);
return step(0, [entry.k, entry.v]);
}, IS_MAP ? 'entries' : 'values' , !IS_MAP, true);
// add [@@species], 23.1.2.2, 23.2.2.2
setSpecies(NAME);
}
};
|