OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 macro TYPED_ARRAYS(FUNCTION) | |
15 // arrayIds below should be synchronized with Runtime_TypedArrayInitialize. | |
16 FUNCTION(Uint8Array) | |
17 FUNCTION(Int8Array) | |
18 FUNCTION(Uint16Array) | |
19 FUNCTION(Int16Array) | |
20 FUNCTION(Uint32Array) | |
21 FUNCTION(Int32Array) | |
22 FUNCTION(Float32Array) | |
23 FUNCTION(Float64Array) | |
24 FUNCTION(Uint8ClampedArray) | |
25 endmacro | |
26 | |
27 macro DECLARE_GLOBALS(NAME) | |
28 var GlobalNAME = global.NAME; | |
29 endmacro | |
30 | |
31 TYPED_ARRAYS(DECLARE_GLOBALS) | |
32 DECLARE_GLOBALS(Array) | |
33 | |
34 var ArrayFrom; | |
35 var ArrayToString; | |
36 var InnerArrayCopyWithin; | |
37 var InnerArrayEvery; | |
38 var InnerArrayFill; | |
39 var InnerArrayFilter; | |
40 var InnerArrayFind; | |
41 var InnerArrayFindIndex; | |
42 var InnerArrayForEach; | |
43 var InnerArrayIndexOf; | |
44 var InnerArrayJoin; | |
45 var InnerArrayLastIndexOf; | |
46 var InnerArrayMap; | |
47 var InnerArraySome; | |
48 var InnerArraySort; | |
49 var InnerArrayToLocaleString; | |
50 var IsNaN; | |
51 var MathMax; | |
52 var MathMin; | |
53 var PackedArrayReverse; | |
54 | |
55 utils.Import(function(from) { | |
56 ArrayFrom = from.ArrayFrom; | |
57 ArrayToString = from.ArrayToString; | |
58 InnerArrayCopyWithin = from.InnerArrayCopyWithin; | |
59 InnerArrayEvery = from.InnerArrayEvery; | |
60 InnerArrayFill = from.InnerArrayFill; | |
61 InnerArrayFilter = from.InnerArrayFilter; | |
62 InnerArrayFind = from.InnerArrayFind; | |
63 InnerArrayFindIndex = from.InnerArrayFindIndex; | |
64 InnerArrayForEach = from.InnerArrayForEach; | |
65 InnerArrayIndexOf = from.InnerArrayIndexOf; | |
66 InnerArrayJoin = from.InnerArrayJoin; | |
67 InnerArrayLastIndexOf = from.InnerArrayLastIndexOf; | |
68 InnerArrayMap = from.InnerArrayMap; | |
69 InnerArrayReduce = from.InnerArrayReduce; | |
70 InnerArrayReduceRight = from.InnerArrayReduceRight; | |
71 InnerArraySome = from.InnerArraySome; | |
72 InnerArraySort = from.InnerArraySort; | |
73 InnerArrayToLocaleString = from.InnerArrayToLocaleString; | |
74 IsNaN = from.IsNaN; | |
75 MathMax = from.MathMax; | |
76 MathMin = from.MathMin; | |
77 PackedArrayReverse = from.PackedArrayReverse; | |
78 }); | |
79 | |
80 // ------------------------------------------------------------------- | |
81 | |
82 function ConstructTypedArray(constructor, arg) { | |
83 // TODO(littledan): This is an approximation of the spec, which requires | |
84 // that only real TypedArray classes should be accepted (22.2.2.1.1) | |
85 if (!%IsConstructor(constructor) || IS_UNDEFINED(constructor.prototype) || | |
86 !%HasOwnProperty(constructor.prototype, "BYTES_PER_ELEMENT")) { | |
87 throw MakeTypeError(kNotTypedArray); | |
88 } | |
89 | |
90 // TODO(littledan): The spec requires that, rather than directly calling | |
91 // the constructor, a TypedArray is created with the proper proto and | |
92 // underlying size and element size, and elements are put in one by one. | |
93 // By contrast, this would allow subclasses to make a radically different | |
94 // constructor with different semantics. | |
95 return new constructor(arg); | |
96 } | |
97 | |
98 function ConstructTypedArrayLike(typedArray, arg) { | |
99 // TODO(littledan): The spec requires that we actuallly use | |
100 // typedArray.constructor[Symbol.species] (bug v8:4093) | |
101 // Also, it should default to the default constructor from | |
102 // table 49 if typedArray.constructor doesn't exist. | |
103 return ConstructTypedArray(typedArray.constructor, arg); | |
104 } | |
105 | |
106 function TypedArrayCopyWithin(target, start, end) { | |
107 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
108 | |
109 var length = %_TypedArrayGetLength(this); | |
110 | |
111 // TODO(littledan): Replace with a memcpy for better performance | |
112 return InnerArrayCopyWithin(target, start, end, this, length); | |
113 } | |
114 %FunctionSetLength(TypedArrayCopyWithin, 2); | |
115 | |
116 // ES6 draft 05-05-15, section 22.2.3.7 | |
117 function TypedArrayEvery(f, receiver) { | |
118 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
119 | |
120 var length = %_TypedArrayGetLength(this); | |
121 | |
122 return InnerArrayEvery(f, receiver, this, length); | |
123 } | |
124 %FunctionSetLength(TypedArrayEvery, 1); | |
125 | |
126 // ES6 draft 08-24-14, section 22.2.3.12 | |
127 function TypedArrayForEach(f, receiver) { | |
128 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
129 | |
130 var length = %_TypedArrayGetLength(this); | |
131 | |
132 InnerArrayForEach(f, receiver, this, length); | |
133 } | |
134 %FunctionSetLength(TypedArrayForEach, 1); | |
135 | |
136 // ES6 draft 04-05-14 section 22.2.3.8 | |
137 function TypedArrayFill(value, start, end) { | |
138 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
139 | |
140 var length = %_TypedArrayGetLength(this); | |
141 | |
142 return InnerArrayFill(value, start, end, this, length); | |
143 } | |
144 %FunctionSetLength(TypedArrayFill, 1); | |
145 | |
146 // ES6 draft 07-15-13, section 22.2.3.9 | |
147 function TypedArrayFilter(predicate, thisArg) { | |
148 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
149 | |
150 var length = %_TypedArrayGetLength(this); | |
151 var array = InnerArrayFilter(predicate, thisArg, this, length); | |
152 return ConstructTypedArrayLike(this, array); | |
153 } | |
154 %FunctionSetLength(TypedArrayFilter, 1); | |
155 | |
156 // ES6 draft 07-15-13, section 22.2.3.10 | |
157 function TypedArrayFind(predicate, thisArg) { | |
158 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
159 | |
160 var length = %_TypedArrayGetLength(this); | |
161 | |
162 return InnerArrayFind(predicate, thisArg, this, length); | |
163 } | |
164 %FunctionSetLength(TypedArrayFind, 1); | |
165 | |
166 // ES6 draft 07-15-13, section 22.2.3.11 | |
167 function TypedArrayFindIndex(predicate, thisArg) { | |
168 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
169 | |
170 var length = %_TypedArrayGetLength(this); | |
171 | |
172 return InnerArrayFindIndex(predicate, thisArg, this, length); | |
173 } | |
174 %FunctionSetLength(TypedArrayFindIndex, 1); | |
175 | |
176 // ES6 draft 05-18-15, section 22.2.3.21 | |
177 function TypedArrayReverse() { | |
178 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
179 | |
180 var length = %_TypedArrayGetLength(this); | |
181 | |
182 return PackedArrayReverse(this, length); | |
183 } | |
184 | |
185 | |
186 function TypedArrayComparefn(x, y) { | |
187 if (IsNaN(x) && IsNaN(y)) { | |
188 return IsNaN(y) ? 0 : 1; | |
189 } | |
190 if (IsNaN(x)) { | |
191 return 1; | |
192 } | |
193 if (x === 0 && x === y) { | |
194 if (%_IsMinusZero(x)) { | |
195 if (!%_IsMinusZero(y)) { | |
196 return -1; | |
197 } | |
198 } else if (%_IsMinusZero(y)) { | |
199 return 1; | |
200 } | |
201 } | |
202 return x - y; | |
203 } | |
204 | |
205 | |
206 // ES6 draft 05-18-15, section 22.2.3.25 | |
207 function TypedArraySort(comparefn) { | |
208 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
209 | |
210 var length = %_TypedArrayGetLength(this); | |
211 | |
212 if (IS_UNDEFINED(comparefn)) { | |
213 comparefn = TypedArrayComparefn; | |
214 } | |
215 | |
216 return InnerArraySort(this, length, comparefn); | |
217 } | |
218 | |
219 | |
220 // ES6 section 22.2.3.13 | |
221 function TypedArrayIndexOf(element, index) { | |
222 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
223 | |
224 var length = %_TypedArrayGetLength(this); | |
225 return InnerArrayIndexOf(this, element, index, length); | |
226 } | |
227 %FunctionSetLength(TypedArrayIndexOf, 1); | |
228 | |
229 | |
230 // ES6 section 22.2.3.16 | |
231 function TypedArrayLastIndexOf(element, index) { | |
232 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
233 | |
234 var length = %_TypedArrayGetLength(this); | |
235 | |
236 return InnerArrayLastIndexOf(this, element, index, length, | |
237 %_ArgumentsLength()); | |
238 } | |
239 %FunctionSetLength(TypedArrayLastIndexOf, 1); | |
240 | |
241 | |
242 // ES6 draft 07-15-13, section 22.2.3.18 | |
243 function TypedArrayMap(predicate, thisArg) { | |
244 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
245 | |
246 // TODO(littledan): Preallocate rather than making an intermediate | |
247 // InternalArray, for better performance. | |
248 var length = %_TypedArrayGetLength(this); | |
249 var array = InnerArrayMap(predicate, thisArg, this, length); | |
250 return ConstructTypedArrayLike(this, array); | |
251 } | |
252 %FunctionSetLength(TypedArrayMap, 1); | |
253 | |
254 | |
255 // ES6 draft 05-05-15, section 22.2.3.24 | |
256 function TypedArraySome(f, receiver) { | |
257 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
258 | |
259 var length = %_TypedArrayGetLength(this); | |
260 | |
261 return InnerArraySome(f, receiver, this, length); | |
262 } | |
263 %FunctionSetLength(TypedArraySome, 1); | |
264 | |
265 | |
266 // ES6 section 22.2.3.27 | |
267 function TypedArrayToLocaleString() { | |
268 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
269 | |
270 var length = %_TypedArrayGetLength(this); | |
271 | |
272 return InnerArrayToLocaleString(this, length); | |
273 } | |
274 | |
275 | |
276 // ES6 section 22.2.3.28 | |
277 function TypedArrayToString() { | |
278 return %_Call(ArrayToString, this); | |
279 } | |
280 | |
281 | |
282 // ES6 section 22.2.3.14 | |
283 function TypedArrayJoin(separator) { | |
284 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
285 | |
286 var length = %_TypedArrayGetLength(this); | |
287 | |
288 return InnerArrayJoin(separator, this, length); | |
289 } | |
290 | |
291 | |
292 // ES6 draft 07-15-13, section 22.2.3.19 | |
293 function TypedArrayReduce(callback, current) { | |
294 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
295 | |
296 var length = %_TypedArrayGetLength(this); | |
297 return InnerArrayReduce(callback, current, this, length, | |
298 %_ArgumentsLength()); | |
299 } | |
300 %FunctionSetLength(TypedArrayReduce, 1); | |
301 | |
302 | |
303 // ES6 draft 07-15-13, section 22.2.3.19 | |
304 function TypedArrayReduceRight(callback, current) { | |
305 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
306 | |
307 var length = %_TypedArrayGetLength(this); | |
308 return InnerArrayReduceRight(callback, current, this, length, | |
309 %_ArgumentsLength()); | |
310 } | |
311 %FunctionSetLength(TypedArrayReduceRight, 1); | |
312 | |
313 | |
314 function TypedArraySlice(start, end) { | |
315 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray); | |
316 var len = %_TypedArrayGetLength(this); | |
317 | |
318 var relativeStart = TO_INTEGER(start); | |
319 | |
320 var k; | |
321 if (relativeStart < 0) { | |
322 k = MathMax(len + relativeStart, 0); | |
323 } else { | |
324 k = MathMin(relativeStart, len); | |
325 } | |
326 | |
327 var relativeEnd; | |
328 if (IS_UNDEFINED(end)) { | |
329 relativeEnd = len; | |
330 } else { | |
331 relativeEnd = TO_INTEGER(end); | |
332 } | |
333 | |
334 var final; | |
335 if (relativeEnd < 0) { | |
336 final = MathMax(len + relativeEnd, 0); | |
337 } else { | |
338 final = MathMin(relativeEnd, len); | |
339 } | |
340 | |
341 var count = MathMax(final - k, 0); | |
342 var array = ConstructTypedArrayLike(this, count); | |
343 // The code below is the 'then' branch; the 'else' branch species | |
344 // a memcpy. Because V8 doesn't canonicalize NaN, the difference is | |
345 // unobservable. | |
346 var n = 0; | |
347 while (k < final) { | |
348 var kValue = this[k]; | |
349 // TODO(littledan): The spec says to throw on an error in setting; | |
350 // does this throw? | |
351 array[n] = kValue; | |
352 k++; | |
353 n++; | |
354 } | |
355 return array; | |
356 } | |
357 | |
358 | |
359 // ES6 draft 08-24-14, section 22.2.2.2 | |
360 function TypedArrayOf() { | |
361 var length = %_ArgumentsLength(); | |
362 var array = new this(length); | |
363 for (var i = 0; i < length; i++) { | |
364 array[i] = %_Arguments(i); | |
365 } | |
366 return array; | |
367 } | |
368 | |
369 | |
370 function TypedArrayFrom(source, mapfn, thisArg) { | |
371 // TODO(littledan): Investigate if there is a receiver which could be | |
372 // faster to accumulate on than Array, e.g., a TypedVector. | |
373 var array = %_Call(ArrayFrom, GlobalArray, source, mapfn, thisArg); | |
374 return ConstructTypedArray(this, array); | |
375 } | |
376 %FunctionSetLength(TypedArrayFrom, 1); | |
377 | |
378 // TODO(littledan): Fix the TypedArray proto chain (bug v8:4085). | |
379 macro EXTEND_TYPED_ARRAY(NAME) | |
380 // Set up non-enumerable functions on the object. | |
381 utils.InstallFunctions(GlobalNAME, DONT_ENUM | DONT_DELETE | READ_ONLY, [ | |
382 "from", TypedArrayFrom, | |
383 "of", TypedArrayOf | |
384 ]); | |
385 | |
386 // Set up non-enumerable functions on the prototype object. | |
387 utils.InstallFunctions(GlobalNAME.prototype, DONT_ENUM, [ | |
388 "copyWithin", TypedArrayCopyWithin, | |
389 "every", TypedArrayEvery, | |
390 "fill", TypedArrayFill, | |
391 "filter", TypedArrayFilter, | |
392 "find", TypedArrayFind, | |
393 "findIndex", TypedArrayFindIndex, | |
394 "indexOf", TypedArrayIndexOf, | |
395 "join", TypedArrayJoin, | |
396 "lastIndexOf", TypedArrayLastIndexOf, | |
397 "forEach", TypedArrayForEach, | |
398 "map", TypedArrayMap, | |
399 "reduce", TypedArrayReduce, | |
400 "reduceRight", TypedArrayReduceRight, | |
401 "reverse", TypedArrayReverse, | |
402 "slice", TypedArraySlice, | |
403 "some", TypedArraySome, | |
404 "sort", TypedArraySort, | |
405 "toString", TypedArrayToString, | |
406 "toLocaleString", TypedArrayToLocaleString | |
407 ]); | |
408 endmacro | |
409 | |
410 TYPED_ARRAYS(EXTEND_TYPED_ARRAY) | |
411 | |
412 }) | |
OLD | NEW |