OLD | NEW |
| (Empty) |
1 // Copyright 2013 the V8 project authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 (function(global, utils) { | |
6 | |
7 'use strict'; | |
8 | |
9 %CheckIsBootstrapping(); | |
10 | |
11 // ------------------------------------------------------------------- | |
12 // Imports | |
13 | |
14 var GetIterator; | |
15 var GetMethod; | |
16 var GlobalArray = global.Array; | |
17 var iteratorSymbol = utils.ImportNow("iterator_symbol"); | |
18 var MathMax; | |
19 var MathMin; | |
20 var ObjectIsFrozen; | |
21 var ObjectDefineProperty; | |
22 | |
23 utils.Import(function(from) { | |
24 GetIterator = from.GetIterator; | |
25 GetMethod = from.GetMethod; | |
26 MathMax = from.MathMax; | |
27 MathMin = from.MathMin; | |
28 ObjectIsFrozen = from.ObjectIsFrozen; | |
29 ObjectDefineProperty = from.ObjectDefineProperty; | |
30 }); | |
31 | |
32 // ------------------------------------------------------------------- | |
33 | |
34 function InnerArrayCopyWithin(target, start, end, array, length) { | |
35 target = TO_INTEGER(target); | |
36 var to; | |
37 if (target < 0) { | |
38 to = MathMax(length + target, 0); | |
39 } else { | |
40 to = MathMin(target, length); | |
41 } | |
42 | |
43 start = TO_INTEGER(start); | |
44 var from; | |
45 if (start < 0) { | |
46 from = MathMax(length + start, 0); | |
47 } else { | |
48 from = MathMin(start, length); | |
49 } | |
50 | |
51 end = IS_UNDEFINED(end) ? length : TO_INTEGER(end); | |
52 var final; | |
53 if (end < 0) { | |
54 final = MathMax(length + end, 0); | |
55 } else { | |
56 final = MathMin(end, length); | |
57 } | |
58 | |
59 var count = MathMin(final - from, length - to); | |
60 var direction = 1; | |
61 if (from < to && to < (from + count)) { | |
62 direction = -1; | |
63 from = from + count - 1; | |
64 to = to + count - 1; | |
65 } | |
66 | |
67 while (count > 0) { | |
68 if (from in array) { | |
69 array[to] = array[from]; | |
70 } else { | |
71 delete array[to]; | |
72 } | |
73 from = from + direction; | |
74 to = to + direction; | |
75 count--; | |
76 } | |
77 | |
78 return array; | |
79 } | |
80 | |
81 // ES6 draft 03-17-15, section 22.1.3.3 | |
82 function ArrayCopyWithin(target, start, end) { | |
83 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.copyWithin"); | |
84 | |
85 var array = TO_OBJECT(this); | |
86 var length = TO_LENGTH(array.length); | |
87 | |
88 return InnerArrayCopyWithin(target, start, end, array, length); | |
89 } | |
90 | |
91 function InnerArrayFind(predicate, thisArg, array, length) { | |
92 if (!IS_CALLABLE(predicate)) { | |
93 throw MakeTypeError(kCalledNonCallable, predicate); | |
94 } | |
95 | |
96 for (var i = 0; i < length; i++) { | |
97 var element = array[i]; | |
98 if (%_Call(predicate, thisArg, element, i, array)) { | |
99 return element; | |
100 } | |
101 } | |
102 | |
103 return; | |
104 } | |
105 | |
106 // ES6 draft 07-15-13, section 15.4.3.23 | |
107 function ArrayFind(predicate, thisArg) { | |
108 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find"); | |
109 | |
110 var array = TO_OBJECT(this); | |
111 var length = TO_INTEGER(array.length); | |
112 | |
113 return InnerArrayFind(predicate, thisArg, array, length); | |
114 } | |
115 | |
116 function InnerArrayFindIndex(predicate, thisArg, array, length) { | |
117 if (!IS_CALLABLE(predicate)) { | |
118 throw MakeTypeError(kCalledNonCallable, predicate); | |
119 } | |
120 | |
121 for (var i = 0; i < length; i++) { | |
122 var element = array[i]; | |
123 if (%_Call(predicate, thisArg, element, i, array)) { | |
124 return i; | |
125 } | |
126 } | |
127 | |
128 return -1; | |
129 } | |
130 | |
131 // ES6 draft 07-15-13, section 15.4.3.24 | |
132 function ArrayFindIndex(predicate, thisArg) { | |
133 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex"); | |
134 | |
135 var array = TO_OBJECT(this); | |
136 var length = TO_INTEGER(array.length); | |
137 | |
138 return InnerArrayFindIndex(predicate, thisArg, array, length); | |
139 } | |
140 | |
141 // ES6, draft 04-05-14, section 22.1.3.6 | |
142 function InnerArrayFill(value, start, end, array, length) { | |
143 var i = IS_UNDEFINED(start) ? 0 : TO_INTEGER(start); | |
144 var end = IS_UNDEFINED(end) ? length : TO_INTEGER(end); | |
145 | |
146 if (i < 0) { | |
147 i += length; | |
148 if (i < 0) i = 0; | |
149 } else { | |
150 if (i > length) i = length; | |
151 } | |
152 | |
153 if (end < 0) { | |
154 end += length; | |
155 if (end < 0) end = 0; | |
156 } else { | |
157 if (end > length) end = length; | |
158 } | |
159 | |
160 if ((end - i) > 0 && ObjectIsFrozen(array)) { | |
161 throw MakeTypeError(kArrayFunctionsOnFrozen); | |
162 } | |
163 | |
164 for (; i < end; i++) | |
165 array[i] = value; | |
166 return array; | |
167 } | |
168 | |
169 // ES6, draft 04-05-14, section 22.1.3.6 | |
170 function ArrayFill(value, start, end) { | |
171 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill"); | |
172 | |
173 var array = TO_OBJECT(this); | |
174 var length = TO_LENGTH_OR_UINT32(array.length); | |
175 | |
176 return InnerArrayFill(value, start, end, array, length); | |
177 } | |
178 | |
179 function AddArrayElement(constructor, array, i, value) { | |
180 if (constructor === GlobalArray) { | |
181 %AddElement(array, i, value); | |
182 } else { | |
183 ObjectDefineProperty(array, i, { | |
184 value: value, writable: true, configurable: true, enumerable: true | |
185 }); | |
186 } | |
187 } | |
188 | |
189 // ES6, draft 10-14-14, section 22.1.2.1 | |
190 function ArrayFrom(arrayLike, mapfn, receiver) { | |
191 var items = TO_OBJECT(arrayLike); | |
192 var mapping = !IS_UNDEFINED(mapfn); | |
193 | |
194 if (mapping) { | |
195 if (!IS_CALLABLE(mapfn)) { | |
196 throw MakeTypeError(kCalledNonCallable, mapfn); | |
197 } | |
198 } | |
199 | |
200 var iterable = GetMethod(items, iteratorSymbol); | |
201 var k; | |
202 var result; | |
203 var mappedValue; | |
204 var nextValue; | |
205 | |
206 if (!IS_UNDEFINED(iterable)) { | |
207 result = %IsConstructor(this) ? new this() : []; | |
208 | |
209 var iterator = GetIterator(items, iterable); | |
210 | |
211 k = 0; | |
212 while (true) { | |
213 var next = iterator.next(); | |
214 | |
215 if (!IS_OBJECT(next)) { | |
216 throw MakeTypeError(kIteratorResultNotAnObject, next); | |
217 } | |
218 | |
219 if (next.done) { | |
220 result.length = k; | |
221 return result; | |
222 } | |
223 | |
224 nextValue = next.value; | |
225 if (mapping) { | |
226 mappedValue = %_Call(mapfn, receiver, nextValue, k); | |
227 } else { | |
228 mappedValue = nextValue; | |
229 } | |
230 AddArrayElement(this, result, k, mappedValue); | |
231 k++; | |
232 } | |
233 } else { | |
234 var len = TO_LENGTH(items.length); | |
235 result = %IsConstructor(this) ? new this(len) : new GlobalArray(len); | |
236 | |
237 for (k = 0; k < len; ++k) { | |
238 nextValue = items[k]; | |
239 if (mapping) { | |
240 mappedValue = %_Call(mapfn, receiver, nextValue, k); | |
241 } else { | |
242 mappedValue = nextValue; | |
243 } | |
244 AddArrayElement(this, result, k, mappedValue); | |
245 } | |
246 | |
247 result.length = k; | |
248 return result; | |
249 } | |
250 } | |
251 | |
252 // ES6, draft 05-22-14, section 22.1.2.3 | |
253 function ArrayOf() { | |
254 var length = %_ArgumentsLength(); | |
255 var constructor = this; | |
256 // TODO: Implement IsConstructor (ES6 section 7.2.5) | |
257 var array = %IsConstructor(constructor) ? new constructor(length) : []; | |
258 for (var i = 0; i < length; i++) { | |
259 AddArrayElement(constructor, array, i, %_Arguments(i)); | |
260 } | |
261 array.length = length; | |
262 return array; | |
263 } | |
264 | |
265 // ------------------------------------------------------------------- | |
266 | |
267 %FunctionSetLength(ArrayCopyWithin, 2); | |
268 %FunctionSetLength(ArrayFrom, 1); | |
269 %FunctionSetLength(ArrayFill, 1); | |
270 %FunctionSetLength(ArrayFind, 1); | |
271 %FunctionSetLength(ArrayFindIndex, 1); | |
272 | |
273 // Set up non-enumerable functions on the Array object. | |
274 utils.InstallFunctions(GlobalArray, DONT_ENUM, [ | |
275 "from", ArrayFrom, | |
276 "of", ArrayOf | |
277 ]); | |
278 | |
279 // Set up the non-enumerable functions on the Array prototype object. | |
280 utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [ | |
281 "copyWithin", ArrayCopyWithin, | |
282 "find", ArrayFind, | |
283 "findIndex", ArrayFindIndex, | |
284 "fill", ArrayFill | |
285 ]); | |
286 | |
287 // ------------------------------------------------------------------- | |
288 // Exports | |
289 | |
290 utils.Export(function(to) { | |
291 to.ArrayFrom = ArrayFrom; | |
292 to.InnerArrayCopyWithin = InnerArrayCopyWithin; | |
293 to.InnerArrayFill = InnerArrayFill; | |
294 to.InnerArrayFind = InnerArrayFind; | |
295 to.InnerArrayFindIndex = InnerArrayFindIndex; | |
296 }); | |
297 | |
298 }) | |
OLD | NEW |