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