blob: 8e7d9ee77e4ed3c8011e400c490e132cf6ef1664 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
Ben Murdochda12d292016-06-02 14:46:10 +010014// array.js has to come before typedarray.js for this to work
15var ArrayToString = utils.ImportNow("ArrayToString");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016var ArrayValues;
Ben Murdochda12d292016-06-02 14:46:10 +010017var GetIterator;
18var GetMethod;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019var GlobalArray = global.Array;
20var GlobalArrayBuffer = global.ArrayBuffer;
Ben Murdochda12d292016-06-02 14:46:10 +010021var GlobalArrayBufferPrototype = GlobalArrayBuffer.prototype;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022var GlobalDataView = global.DataView;
23var GlobalObject = global.Object;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024var InnerArrayCopyWithin;
25var InnerArrayEvery;
26var InnerArrayFill;
27var InnerArrayFilter;
28var InnerArrayFind;
29var InnerArrayFindIndex;
30var InnerArrayForEach;
31var InnerArrayIncludes;
32var InnerArrayIndexOf;
33var InnerArrayJoin;
34var InnerArrayLastIndexOf;
35var InnerArrayReduce;
36var InnerArrayReduceRight;
37var InnerArraySome;
38var InnerArraySort;
39var InnerArrayToLocaleString;
40var InternalArray = utils.InternalArray;
41var IsNaN;
42var MakeRangeError;
43var MakeTypeError;
44var MaxSimple;
45var MinSimple;
46var PackedArrayReverse;
47var SpeciesConstructor;
48var ToPositiveInteger;
49var iteratorSymbol = utils.ImportNow("iterator_symbol");
Ben Murdoch61f157c2016-09-16 13:49:30 +010050var speciesSymbol = utils.ImportNow("species_symbol");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
52
53macro TYPED_ARRAYS(FUNCTION)
54// arrayIds below should be synchronized with Runtime_TypedArrayInitialize.
55FUNCTION(1, Uint8Array, 1)
56FUNCTION(2, Int8Array, 1)
57FUNCTION(3, Uint16Array, 2)
58FUNCTION(4, Int16Array, 2)
59FUNCTION(5, Uint32Array, 4)
60FUNCTION(6, Int32Array, 4)
61FUNCTION(7, Float32Array, 4)
62FUNCTION(8, Float64Array, 8)
63FUNCTION(9, Uint8ClampedArray, 1)
64endmacro
65
66macro DECLARE_GLOBALS(INDEX, NAME, SIZE)
67var GlobalNAME = global.NAME;
68endmacro
69
70TYPED_ARRAYS(DECLARE_GLOBALS)
71
Ben Murdoch61f157c2016-09-16 13:49:30 +010072var GlobalTypedArray = %object_get_prototype_of(GlobalUint8Array);
73
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074utils.Import(function(from) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 ArrayValues = from.ArrayValues;
Ben Murdochda12d292016-06-02 14:46:10 +010076 GetIterator = from.GetIterator;
77 GetMethod = from.GetMethod;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078 InnerArrayCopyWithin = from.InnerArrayCopyWithin;
79 InnerArrayEvery = from.InnerArrayEvery;
80 InnerArrayFill = from.InnerArrayFill;
81 InnerArrayFilter = from.InnerArrayFilter;
82 InnerArrayFind = from.InnerArrayFind;
83 InnerArrayFindIndex = from.InnerArrayFindIndex;
84 InnerArrayForEach = from.InnerArrayForEach;
85 InnerArrayIncludes = from.InnerArrayIncludes;
86 InnerArrayIndexOf = from.InnerArrayIndexOf;
87 InnerArrayJoin = from.InnerArrayJoin;
88 InnerArrayLastIndexOf = from.InnerArrayLastIndexOf;
89 InnerArrayReduce = from.InnerArrayReduce;
90 InnerArrayReduceRight = from.InnerArrayReduceRight;
91 InnerArraySome = from.InnerArraySome;
92 InnerArraySort = from.InnerArraySort;
93 InnerArrayToLocaleString = from.InnerArrayToLocaleString;
94 IsNaN = from.IsNaN;
95 MakeRangeError = from.MakeRangeError;
96 MakeTypeError = from.MakeTypeError;
97 MaxSimple = from.MaxSimple;
98 MinSimple = from.MinSimple;
99 PackedArrayReverse = from.PackedArrayReverse;
100 SpeciesConstructor = from.SpeciesConstructor;
101 ToPositiveInteger = from.ToPositiveInteger;
102});
103
104// --------------- Typed Arrays ---------------------
105
106function TypedArrayDefaultConstructor(typedArray) {
107 switch (%_ClassOf(typedArray)) {
108macro TYPED_ARRAY_CONSTRUCTOR_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
109 case "NAME":
110 return GlobalNAME;
111endmacro
112TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR_CASE)
113 }
114 // The TypeError should not be generated since all callers should
115 // have already called ValidateTypedArray.
116 throw MakeTypeError(kIncompatibleMethodReceiver,
117 "TypedArrayDefaultConstructor", this);
118}
119
120function TypedArrayCreate(constructor, arg0, arg1, arg2) {
121 if (IS_UNDEFINED(arg1)) {
122 var newTypedArray = new constructor(arg0);
123 } else {
124 var newTypedArray = new constructor(arg0, arg1, arg2);
125 }
Ben Murdochda12d292016-06-02 14:46:10 +0100126 if (!IS_TYPEDARRAY(newTypedArray)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127 // TODO(littledan): Check for being detached, here and elsewhere
128 // All callers where the first argument is a Number have no additional
129 // arguments.
130 if (IS_NUMBER(arg0) && %_TypedArrayGetLength(newTypedArray) < arg0) {
131 throw MakeTypeError(kTypedArrayTooShort);
132 }
133 return newTypedArray;
134}
135
136function TypedArraySpeciesCreate(exemplar, arg0, arg1, arg2, conservative) {
137 var defaultConstructor = TypedArrayDefaultConstructor(exemplar);
138 var constructor = SpeciesConstructor(exemplar, defaultConstructor,
139 conservative);
140 return TypedArrayCreate(constructor, arg0, arg1, arg2);
141}
142
143macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE)
144function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
145 if (!IS_UNDEFINED(byteOffset)) {
146 byteOffset = ToPositiveInteger(byteOffset, kInvalidTypedArrayLength);
147 }
148 if (!IS_UNDEFINED(length)) {
149 length = ToPositiveInteger(length, kInvalidTypedArrayLength);
150 }
151
152 var bufferByteLength = %_ArrayBufferGetByteLength(buffer);
153 var offset;
154 if (IS_UNDEFINED(byteOffset)) {
155 offset = 0;
156 } else {
157 offset = byteOffset;
158
159 if (offset % ELEMENT_SIZE !== 0) {
160 throw MakeRangeError(kInvalidTypedArrayAlignment,
161 "start offset", "NAME", ELEMENT_SIZE);
162 }
163 if (offset > bufferByteLength) {
164 throw MakeRangeError(kInvalidTypedArrayOffset);
165 }
166 }
167
168 var newByteLength;
169 var newLength;
170 if (IS_UNDEFINED(length)) {
171 if (bufferByteLength % ELEMENT_SIZE !== 0) {
172 throw MakeRangeError(kInvalidTypedArrayAlignment,
173 "byte length", "NAME", ELEMENT_SIZE);
174 }
175 newByteLength = bufferByteLength - offset;
176 newLength = newByteLength / ELEMENT_SIZE;
177 } else {
178 var newLength = length;
179 newByteLength = newLength * ELEMENT_SIZE;
180 }
181 if ((offset + newByteLength > bufferByteLength)
182 || (newLength > %_MaxSmi())) {
183 throw MakeRangeError(kInvalidTypedArrayLength);
184 }
185 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength, true);
186}
187
188function NAMEConstructByLength(obj, length) {
189 var l = IS_UNDEFINED(length) ?
190 0 : ToPositiveInteger(length, kInvalidTypedArrayLength);
191 if (l > %_MaxSmi()) {
192 throw MakeRangeError(kInvalidTypedArrayLength);
193 }
194 var byteLength = l * ELEMENT_SIZE;
195 if (byteLength > %_TypedArrayMaxSizeInHeap()) {
196 var buffer = new GlobalArrayBuffer(byteLength);
197 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, 0, byteLength, true);
198 } else {
199 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, true);
200 }
201}
202
Ben Murdochda12d292016-06-02 14:46:10 +0100203function NAMEConstructByArrayLike(obj, arrayLike, length) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 var l = ToPositiveInteger(length, kInvalidTypedArrayLength);
205
206 if (l > %_MaxSmi()) {
207 throw MakeRangeError(kInvalidTypedArrayLength);
208 }
209 var initialized = false;
210 var byteLength = l * ELEMENT_SIZE;
211 if (byteLength <= %_TypedArrayMaxSizeInHeap()) {
212 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, false);
213 } else {
214 initialized =
215 %TypedArrayInitializeFromArrayLike(obj, ARRAY_ID, arrayLike, l);
216 }
217 if (!initialized) {
218 for (var i = 0; i < l; i++) {
219 // It is crucial that we let any execptions from arrayLike[i]
220 // propagate outside the function.
221 obj[i] = arrayLike[i];
222 }
223 }
224}
225
226function NAMEConstructByIterable(obj, iterable, iteratorFn) {
227 var list = new InternalArray();
228 // Reading the Symbol.iterator property of iterable twice would be
229 // observable with getters, so instead, we call the function which
230 // was already looked up, and wrap it in another iterable. The
231 // __proto__ of the new iterable is set to null to avoid any chance
232 // of modifications to Object.prototype being observable here.
233 var iterator = %_Call(iteratorFn, iterable);
234 var newIterable = {
235 __proto__: null
236 };
237 // TODO(littledan): Computed properties don't work yet in nosnap.
238 // Rephrase when they do.
239 newIterable[iteratorSymbol] = function() { return iterator; }
240 for (var value of newIterable) {
241 list.push(value);
242 }
Ben Murdochda12d292016-06-02 14:46:10 +0100243 NAMEConstructByArrayLike(obj, list, list.length);
244}
245
246// ES#sec-typedarray-typedarray TypedArray ( typedArray )
247function NAMEConstructByTypedArray(obj, typedArray) {
248 // TODO(littledan): Throw on detached typedArray
249 var srcData = %TypedArrayGetBuffer(typedArray);
250 var length = %_TypedArrayGetLength(typedArray);
251 var byteLength = %_ArrayBufferViewGetByteLength(typedArray);
252 var newByteLength = length * ELEMENT_SIZE;
253 NAMEConstructByArrayLike(obj, typedArray, length);
254 var bufferConstructor = SpeciesConstructor(srcData, GlobalArrayBuffer);
255 var prototype = bufferConstructor.prototype;
256 // TODO(littledan): Use the right prototype based on bufferConstructor's realm
257 if (IS_RECEIVER(prototype) && prototype !== GlobalArrayBufferPrototype) {
258 %InternalSetPrototype(%TypedArrayGetBuffer(obj), prototype);
259 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260}
261
262function NAMEConstructor(arg1, arg2, arg3) {
263 if (!IS_UNDEFINED(new.target)) {
264 if (IS_ARRAYBUFFER(arg1) || IS_SHAREDARRAYBUFFER(arg1)) {
265 NAMEConstructByArrayBuffer(this, arg1, arg2, arg3);
266 } else if (IS_NUMBER(arg1) || IS_STRING(arg1) ||
267 IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) {
268 NAMEConstructByLength(this, arg1);
Ben Murdochda12d292016-06-02 14:46:10 +0100269 } else if (IS_TYPEDARRAY(arg1)) {
270 NAMEConstructByTypedArray(this, arg1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 var iteratorFn = arg1[iteratorSymbol];
273 if (IS_UNDEFINED(iteratorFn) || iteratorFn === ArrayValues) {
Ben Murdochda12d292016-06-02 14:46:10 +0100274 NAMEConstructByArrayLike(this, arg1, arg1.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275 } else {
276 NAMEConstructByIterable(this, arg1, iteratorFn);
277 }
278 }
279 } else {
280 throw MakeTypeError(kConstructorNotFunction, "NAME")
281 }
282}
283
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284function NAMESubArray(begin, end) {
285 var beginInt = TO_INTEGER(begin);
286 if (!IS_UNDEFINED(end)) {
287 var endInt = TO_INTEGER(end);
288 var srcLength = %_TypedArrayGetLength(this);
289 } else {
290 var srcLength = %_TypedArrayGetLength(this);
291 var endInt = srcLength;
292 }
293
294 if (beginInt < 0) {
295 beginInt = MaxSimple(0, srcLength + beginInt);
296 } else {
297 beginInt = MinSimple(beginInt, srcLength);
298 }
299
300 if (endInt < 0) {
301 endInt = MaxSimple(0, srcLength + endInt);
302 } else {
303 endInt = MinSimple(endInt, srcLength);
304 }
305
306 if (endInt < beginInt) {
307 endInt = beginInt;
308 }
309
310 var newLength = endInt - beginInt;
311 var beginByteOffset =
312 %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100313 // BUG(v8:4665): For web compatibility, subarray needs to always build an
314 // instance of the default constructor.
315 // TODO(littledan): Switch to the standard or standardize the fix
316 return new GlobalNAME(%TypedArrayGetBuffer(this), beginByteOffset, newLength);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317}
318endmacro
319
320TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR)
321
322function TypedArraySubArray(begin, end) {
323 switch (%_ClassOf(this)) {
324macro TYPED_ARRAY_SUBARRAY_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
325 case "NAME":
326 return %_Call(NAMESubArray, this, begin, end);
327endmacro
328TYPED_ARRAYS(TYPED_ARRAY_SUBARRAY_CASE)
329 }
330 throw MakeTypeError(kIncompatibleMethodReceiver,
331 "get TypedArray.prototype.subarray", this);
332}
333%SetForceInlineFlag(TypedArraySubArray);
334
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335
336
337function TypedArraySetFromArrayLike(target, source, sourceLength, offset) {
338 if (offset > 0) {
339 for (var i = 0; i < sourceLength; i++) {
340 target[offset + i] = source[i];
341 }
342 }
343 else {
344 for (var i = 0; i < sourceLength; i++) {
345 target[i] = source[i];
346 }
347 }
348}
349
350function TypedArraySetFromOverlappingTypedArray(target, source, offset) {
351 var sourceElementSize = source.BYTES_PER_ELEMENT;
352 var targetElementSize = target.BYTES_PER_ELEMENT;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100353 var sourceLength = %_TypedArrayGetLength(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354
355 // Copy left part.
356 function CopyLeftPart() {
357 // First un-mutated byte after the next write
358 var targetPtr = target.byteOffset + (offset + 1) * targetElementSize;
359 // Next read at sourcePtr. We do not care for memory changing before
360 // sourcePtr - we have already copied it.
361 var sourcePtr = source.byteOffset;
362 for (var leftIndex = 0;
363 leftIndex < sourceLength && targetPtr <= sourcePtr;
364 leftIndex++) {
365 target[offset + leftIndex] = source[leftIndex];
366 targetPtr += targetElementSize;
367 sourcePtr += sourceElementSize;
368 }
369 return leftIndex;
370 }
371 var leftIndex = CopyLeftPart();
372
Ben Murdoch61f157c2016-09-16 13:49:30 +0100373 // Copy right part;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000374 function CopyRightPart() {
375 // First unmutated byte before the next write
376 var targetPtr =
377 target.byteOffset + (offset + sourceLength - 1) * targetElementSize;
378 // Next read before sourcePtr. We do not care for memory changing after
379 // sourcePtr - we have already copied it.
380 var sourcePtr =
381 source.byteOffset + sourceLength * sourceElementSize;
382 for(var rightIndex = sourceLength - 1;
383 rightIndex >= leftIndex && targetPtr >= sourcePtr;
384 rightIndex--) {
385 target[offset + rightIndex] = source[rightIndex];
386 targetPtr -= targetElementSize;
387 sourcePtr -= sourceElementSize;
388 }
389 return rightIndex;
390 }
391 var rightIndex = CopyRightPart();
392
393 var temp = new GlobalArray(rightIndex + 1 - leftIndex);
394 for (var i = leftIndex; i <= rightIndex; i++) {
395 temp[i - leftIndex] = source[i];
396 }
397 for (i = leftIndex; i <= rightIndex; i++) {
398 target[offset + i] = temp[i - leftIndex];
399 }
400}
401
402function TypedArraySet(obj, offset) {
403 var intOffset = IS_UNDEFINED(offset) ? 0 : TO_INTEGER(offset);
404 if (intOffset < 0) throw MakeTypeError(kTypedArraySetNegativeOffset);
405
406 if (intOffset > %_MaxSmi()) {
407 throw MakeRangeError(kTypedArraySetSourceTooLarge);
408 }
409 switch (%TypedArraySetFastCases(this, obj, intOffset)) {
410 // These numbers should be synchronized with runtime.cc.
411 case 0: // TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE
412 return;
413 case 1: // TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING
414 TypedArraySetFromOverlappingTypedArray(this, obj, intOffset);
415 return;
416 case 2: // TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING
Ben Murdoch61f157c2016-09-16 13:49:30 +0100417 TypedArraySetFromArrayLike(this,
418 obj, %_TypedArrayGetLength(obj), intOffset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 return;
420 case 3: // TYPED_ARRAY_SET_NON_TYPED_ARRAY
421 var l = obj.length;
422 if (IS_UNDEFINED(l)) {
423 if (IS_NUMBER(obj)) {
424 // For number as a first argument, throw TypeError
425 // instead of silently ignoring the call, so that
426 // the user knows (s)he did something wrong.
427 // (Consistent with Firefox and Blink/WebKit)
428 throw MakeTypeError(kInvalidArgument);
429 }
430 return;
431 }
432 l = TO_LENGTH(l);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100433 if (intOffset + l > %_TypedArrayGetLength(this)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 throw MakeRangeError(kTypedArraySetSourceTooLarge);
435 }
436 TypedArraySetFromArrayLike(this, obj, l, intOffset);
437 return;
438 }
439}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100440%FunctionSetLength(TypedArraySet, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441
442function TypedArrayGetToStringTag() {
Ben Murdochda12d292016-06-02 14:46:10 +0100443 if (!IS_TYPEDARRAY(this)) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444 var name = %_ClassOf(this);
445 if (IS_UNDEFINED(name)) return;
446 return name;
447}
448
449
450function TypedArrayCopyWithin(target, start, end) {
Ben Murdochda12d292016-06-02 14:46:10 +0100451 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000452
453 var length = %_TypedArrayGetLength(this);
454
455 // TODO(littledan): Replace with a memcpy for better performance
456 return InnerArrayCopyWithin(target, start, end, this, length);
457}
458%FunctionSetLength(TypedArrayCopyWithin, 2);
459
460
461// ES6 draft 05-05-15, section 22.2.3.7
462function TypedArrayEvery(f, receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100463 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464
465 var length = %_TypedArrayGetLength(this);
466
467 return InnerArrayEvery(f, receiver, this, length);
468}
469%FunctionSetLength(TypedArrayEvery, 1);
470
471
472// ES6 draft 08-24-14, section 22.2.3.12
473function TypedArrayForEach(f, receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100474 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475
476 var length = %_TypedArrayGetLength(this);
477
478 InnerArrayForEach(f, receiver, this, length);
479}
480%FunctionSetLength(TypedArrayForEach, 1);
481
482
483// ES6 draft 04-05-14 section 22.2.3.8
484function TypedArrayFill(value, start, end) {
Ben Murdochda12d292016-06-02 14:46:10 +0100485 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000486
487 var length = %_TypedArrayGetLength(this);
488
489 return InnerArrayFill(value, start, end, this, length);
490}
491%FunctionSetLength(TypedArrayFill, 1);
492
493
494// ES6 draft 07-15-13, section 22.2.3.9
495function TypedArrayFilter(f, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100496 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497
498 var length = %_TypedArrayGetLength(this);
499 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
500 var result = new InternalArray();
501 InnerArrayFilter(f, thisArg, this, length, result);
502 var captured = result.length;
503 var output = TypedArraySpeciesCreate(this, captured);
504 for (var i = 0; i < captured; i++) {
505 output[i] = result[i];
506 }
507 return output;
508}
509%FunctionSetLength(TypedArrayFilter, 1);
510
511
512// ES6 draft 07-15-13, section 22.2.3.10
513function TypedArrayFind(predicate, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100514 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000515
516 var length = %_TypedArrayGetLength(this);
517
518 return InnerArrayFind(predicate, thisArg, this, length);
519}
520%FunctionSetLength(TypedArrayFind, 1);
521
522
523// ES6 draft 07-15-13, section 22.2.3.11
524function TypedArrayFindIndex(predicate, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100525 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000526
527 var length = %_TypedArrayGetLength(this);
528
529 return InnerArrayFindIndex(predicate, thisArg, this, length);
530}
531%FunctionSetLength(TypedArrayFindIndex, 1);
532
533
534// ES6 draft 05-18-15, section 22.2.3.21
535function TypedArrayReverse() {
Ben Murdochda12d292016-06-02 14:46:10 +0100536 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537
538 var length = %_TypedArrayGetLength(this);
539
540 return PackedArrayReverse(this, length);
541}
542
543
544function TypedArrayComparefn(x, y) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100545 if (x === 0 && x === y) {
546 x = 1 / x;
547 y = 1 / y;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000548 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100549 if (x < y) {
550 return -1;
551 } else if (x > y) {
552 return 1;
553 } else if (IsNaN(x) && IsNaN(y)) {
554 return IsNaN(y) ? 0 : 1;
555 } else if (IsNaN(x)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000556 return 1;
557 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100558 return 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000559}
560
561
562// ES6 draft 05-18-15, section 22.2.3.25
563function TypedArraySort(comparefn) {
Ben Murdochda12d292016-06-02 14:46:10 +0100564 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565
566 var length = %_TypedArrayGetLength(this);
567
568 if (IS_UNDEFINED(comparefn)) {
569 comparefn = TypedArrayComparefn;
570 }
571
572 return InnerArraySort(this, length, comparefn);
573}
574
575
576// ES6 section 22.2.3.13
577function TypedArrayIndexOf(element, index) {
Ben Murdochda12d292016-06-02 14:46:10 +0100578 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579
580 var length = %_TypedArrayGetLength(this);
581 return InnerArrayIndexOf(this, element, index, length);
582}
583%FunctionSetLength(TypedArrayIndexOf, 1);
584
585
586// ES6 section 22.2.3.16
587function TypedArrayLastIndexOf(element, index) {
Ben Murdochda12d292016-06-02 14:46:10 +0100588 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000589
590 var length = %_TypedArrayGetLength(this);
591
592 return InnerArrayLastIndexOf(this, element, index, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100593 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000594}
595%FunctionSetLength(TypedArrayLastIndexOf, 1);
596
597
598// ES6 draft 07-15-13, section 22.2.3.18
599function TypedArrayMap(f, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100600 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000601
602 var length = %_TypedArrayGetLength(this);
603 var result = TypedArraySpeciesCreate(this, length);
604 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
605 for (var i = 0; i < length; i++) {
606 var element = this[i];
607 result[i] = %_Call(f, thisArg, element, i, this);
608 }
609 return result;
610}
611%FunctionSetLength(TypedArrayMap, 1);
612
613
614// ES6 draft 05-05-15, section 22.2.3.24
615function TypedArraySome(f, receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100616 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000617
618 var length = %_TypedArrayGetLength(this);
619
620 return InnerArraySome(f, receiver, this, length);
621}
622%FunctionSetLength(TypedArraySome, 1);
623
624
625// ES6 section 22.2.3.27
626function TypedArrayToLocaleString() {
Ben Murdochda12d292016-06-02 14:46:10 +0100627 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000628
629 var length = %_TypedArrayGetLength(this);
630
631 return InnerArrayToLocaleString(this, length);
632}
633
634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635// ES6 section 22.2.3.14
636function TypedArrayJoin(separator) {
Ben Murdochda12d292016-06-02 14:46:10 +0100637 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000638
639 var length = %_TypedArrayGetLength(this);
640
641 return InnerArrayJoin(separator, this, length);
642}
643
644
645// ES6 draft 07-15-13, section 22.2.3.19
646function TypedArrayReduce(callback, current) {
Ben Murdochda12d292016-06-02 14:46:10 +0100647 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000648
649 var length = %_TypedArrayGetLength(this);
650 return InnerArrayReduce(callback, current, this, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100651 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652}
653%FunctionSetLength(TypedArrayReduce, 1);
654
655
656// ES6 draft 07-15-13, section 22.2.3.19
657function TypedArrayReduceRight(callback, current) {
Ben Murdochda12d292016-06-02 14:46:10 +0100658 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000659
660 var length = %_TypedArrayGetLength(this);
661 return InnerArrayReduceRight(callback, current, this, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100662 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000663}
664%FunctionSetLength(TypedArrayReduceRight, 1);
665
666
667function TypedArraySlice(start, end) {
Ben Murdochda12d292016-06-02 14:46:10 +0100668 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000669 var len = %_TypedArrayGetLength(this);
670
671 var relativeStart = TO_INTEGER(start);
672
673 var k;
674 if (relativeStart < 0) {
675 k = MaxSimple(len + relativeStart, 0);
676 } else {
677 k = MinSimple(relativeStart, len);
678 }
679
680 var relativeEnd;
681 if (IS_UNDEFINED(end)) {
682 relativeEnd = len;
683 } else {
684 relativeEnd = TO_INTEGER(end);
685 }
686
687 var final;
688 if (relativeEnd < 0) {
689 final = MaxSimple(len + relativeEnd, 0);
690 } else {
691 final = MinSimple(relativeEnd, len);
692 }
693
694 var count = MaxSimple(final - k, 0);
695 var array = TypedArraySpeciesCreate(this, count);
696 // The code below is the 'then' branch; the 'else' branch species
697 // a memcpy. Because V8 doesn't canonicalize NaN, the difference is
698 // unobservable.
699 var n = 0;
700 while (k < final) {
701 var kValue = this[k];
702 array[n] = kValue;
703 k++;
704 n++;
705 }
706 return array;
707}
708
709
710// ES2016 draft, section 22.2.3.14
711function TypedArrayIncludes(searchElement, fromIndex) {
Ben Murdochda12d292016-06-02 14:46:10 +0100712 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000713
714 var length = %_TypedArrayGetLength(this);
715
716 return InnerArrayIncludes(searchElement, fromIndex, this, length);
717}
718%FunctionSetLength(TypedArrayIncludes, 1);
719
720
721// ES6 draft 08-24-14, section 22.2.2.2
722function TypedArrayOf() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100723 var length = arguments.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000724 var array = TypedArrayCreate(this, length);
725 for (var i = 0; i < length; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100726 array[i] = arguments[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000727 }
728 return array;
729}
730
731
Ben Murdochda12d292016-06-02 14:46:10 +0100732// ES#sec-iterabletoarraylike Runtime Semantics: IterableToArrayLike( items )
733function IterableToArrayLike(items) {
734 var iterable = GetMethod(items, iteratorSymbol);
735 if (!IS_UNDEFINED(iterable)) {
736 var internal_array = new InternalArray();
737 var i = 0;
738 for (var value of
739 { [iteratorSymbol]() { return GetIterator(items, iterable) } }) {
740 internal_array[i] = value;
741 i++;
742 }
743 var array = [];
744 %MoveArrayContents(internal_array, array);
745 return array;
746 }
747 return TO_OBJECT(items);
748}
749
750
751// ES#sec-%typedarray%.from
752// %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] )
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000753function TypedArrayFrom(source, mapfn, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100754 if (!%IsConstructor(this)) throw MakeTypeError(kNotConstructor, this);
755 var mapping;
756 if (!IS_UNDEFINED(mapfn)) {
757 if (!IS_CALLABLE(mapfn)) throw MakeTypeError(kCalledNonCallable, this);
758 mapping = true;
759 } else {
760 mapping = false;
761 }
762 var arrayLike = IterableToArrayLike(source);
763 var length = TO_LENGTH(arrayLike.length);
764 var targetObject = TypedArrayCreate(this, length);
765 var value, mappedValue;
766 for (var i = 0; i < length; i++) {
767 value = arrayLike[i];
768 if (mapping) {
769 mappedValue = %_Call(mapfn, thisArg, value, i);
770 } else {
771 mappedValue = value;
772 }
773 targetObject[i] = mappedValue;
774 }
775 return targetObject;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000776}
777%FunctionSetLength(TypedArrayFrom, 1);
778
Ben Murdoch61f157c2016-09-16 13:49:30 +0100779// TODO(bmeurer): Migrate this to a proper builtin.
780function TypedArrayConstructor() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000781 if (IS_UNDEFINED(new.target)) {
782 throw MakeTypeError(kConstructorNonCallable, "TypedArray");
783 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100784 if (new.target === GlobalTypedArray) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000785 throw MakeTypeError(kConstructAbstractClass, "TypedArray");
786 }
787}
788
Ben Murdoch61f157c2016-09-16 13:49:30 +0100789function TypedArraySpecies() {
790 return this;
791}
792
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000793// -------------------------------------------------------------------
794
Ben Murdoch61f157c2016-09-16 13:49:30 +0100795%SetCode(GlobalTypedArray, TypedArrayConstructor);
796utils.InstallFunctions(GlobalTypedArray, DONT_ENUM, [
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000797 "from", TypedArrayFrom,
798 "of", TypedArrayOf
799]);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100800utils.InstallGetter(GlobalTypedArray, speciesSymbol, TypedArraySpecies);
801utils.InstallGetter(GlobalTypedArray.prototype, toStringTagSymbol,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 TypedArrayGetToStringTag);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100803utils.InstallFunctions(GlobalTypedArray.prototype, DONT_ENUM, [
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000804 "subarray", TypedArraySubArray,
805 "set", TypedArraySet,
806 "copyWithin", TypedArrayCopyWithin,
807 "every", TypedArrayEvery,
808 "fill", TypedArrayFill,
809 "filter", TypedArrayFilter,
810 "find", TypedArrayFind,
811 "findIndex", TypedArrayFindIndex,
812 "includes", TypedArrayIncludes,
813 "indexOf", TypedArrayIndexOf,
814 "join", TypedArrayJoin,
815 "lastIndexOf", TypedArrayLastIndexOf,
816 "forEach", TypedArrayForEach,
817 "map", TypedArrayMap,
818 "reduce", TypedArrayReduce,
819 "reduceRight", TypedArrayReduceRight,
820 "reverse", TypedArrayReverse,
821 "slice", TypedArraySlice,
822 "some", TypedArraySome,
823 "sort", TypedArraySort,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000824 "toLocaleString", TypedArrayToLocaleString
825]);
826
Ben Murdoch61f157c2016-09-16 13:49:30 +0100827%AddNamedProperty(GlobalTypedArray.prototype, "toString", ArrayToString,
Ben Murdochda12d292016-06-02 14:46:10 +0100828 DONT_ENUM);
829
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830
831macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE)
832 %SetCode(GlobalNAME, NAMEConstructor);
833 %FunctionSetPrototype(GlobalNAME, new GlobalObject());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100834 %InternalSetPrototype(GlobalNAME, GlobalTypedArray);
835 %InternalSetPrototype(GlobalNAME.prototype, GlobalTypedArray.prototype);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000836
837 %AddNamedProperty(GlobalNAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE,
838 READ_ONLY | DONT_ENUM | DONT_DELETE);
839
840 %AddNamedProperty(GlobalNAME.prototype,
841 "constructor", global.NAME, DONT_ENUM);
842 %AddNamedProperty(GlobalNAME.prototype,
843 "BYTES_PER_ELEMENT", ELEMENT_SIZE,
844 READ_ONLY | DONT_ENUM | DONT_DELETE);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000845endmacro
846
847TYPED_ARRAYS(SETUP_TYPED_ARRAY)
848
849// --------------------------- DataView -----------------------------
850
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000851macro DATA_VIEW_TYPES(FUNCTION)
852 FUNCTION(Int8)
853 FUNCTION(Uint8)
854 FUNCTION(Int16)
855 FUNCTION(Uint16)
856 FUNCTION(Int32)
857 FUNCTION(Uint32)
858 FUNCTION(Float32)
859 FUNCTION(Float64)
860endmacro
861
862
863macro DATA_VIEW_GETTER_SETTER(TYPENAME)
864function DataViewGetTYPENAMEJS(offset, little_endian) {
865 if (!IS_DATAVIEW(this)) {
866 throw MakeTypeError(kIncompatibleMethodReceiver,
867 'DataView.getTYPENAME', this);
868 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100869 if (arguments.length < 1) throw MakeTypeError(kInvalidArgument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000870 offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
871 return %DataViewGetTYPENAME(this, offset, !!little_endian);
872}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100873%FunctionSetLength(DataViewGetTYPENAMEJS, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000874
875function DataViewSetTYPENAMEJS(offset, value, little_endian) {
876 if (!IS_DATAVIEW(this)) {
877 throw MakeTypeError(kIncompatibleMethodReceiver,
878 'DataView.setTYPENAME', this);
879 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100880 if (arguments.length < 2) throw MakeTypeError(kInvalidArgument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000881 offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
882 %DataViewSetTYPENAME(this, offset, TO_NUMBER(value), !!little_endian);
883}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100884%FunctionSetLength(DataViewSetTYPENAMEJS, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000885endmacro
886
887DATA_VIEW_TYPES(DATA_VIEW_GETTER_SETTER)
888
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889utils.InstallFunctions(GlobalDataView.prototype, DONT_ENUM, [
890 "getInt8", DataViewGetInt8JS,
891 "setInt8", DataViewSetInt8JS,
892
893 "getUint8", DataViewGetUint8JS,
894 "setUint8", DataViewSetUint8JS,
895
896 "getInt16", DataViewGetInt16JS,
897 "setInt16", DataViewSetInt16JS,
898
899 "getUint16", DataViewGetUint16JS,
900 "setUint16", DataViewSetUint16JS,
901
902 "getInt32", DataViewGetInt32JS,
903 "setInt32", DataViewSetInt32JS,
904
905 "getUint32", DataViewGetUint32JS,
906 "setUint32", DataViewSetUint32JS,
907
908 "getFloat32", DataViewGetFloat32JS,
909 "setFloat32", DataViewSetFloat32JS,
910
911 "getFloat64", DataViewGetFloat64JS,
912 "setFloat64", DataViewSetFloat64JS
913]);
914
915})