blob: 3d500a379ec8786d324600b6c9a77b8f54199b61 [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
14var ArrayFrom;
15var ArrayToString;
16var ArrayValues;
17var GlobalArray = global.Array;
18var GlobalArrayBuffer = global.ArrayBuffer;
19var GlobalDataView = global.DataView;
20var GlobalObject = global.Object;
21var InternalArray = utils.InternalArray;
22var InnerArrayCopyWithin;
23var InnerArrayEvery;
24var InnerArrayFill;
25var InnerArrayFilter;
26var InnerArrayFind;
27var InnerArrayFindIndex;
28var InnerArrayForEach;
29var InnerArrayIncludes;
30var InnerArrayIndexOf;
31var InnerArrayJoin;
32var InnerArrayLastIndexOf;
33var InnerArrayReduce;
34var InnerArrayReduceRight;
35var InnerArraySome;
36var InnerArraySort;
37var InnerArrayToLocaleString;
38var InternalArray = utils.InternalArray;
39var IsNaN;
40var MakeRangeError;
41var MakeTypeError;
42var MaxSimple;
43var MinSimple;
44var PackedArrayReverse;
45var SpeciesConstructor;
46var ToPositiveInteger;
47var iteratorSymbol = utils.ImportNow("iterator_symbol");
48var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
49
50macro TYPED_ARRAYS(FUNCTION)
51// arrayIds below should be synchronized with Runtime_TypedArrayInitialize.
52FUNCTION(1, Uint8Array, 1)
53FUNCTION(2, Int8Array, 1)
54FUNCTION(3, Uint16Array, 2)
55FUNCTION(4, Int16Array, 2)
56FUNCTION(5, Uint32Array, 4)
57FUNCTION(6, Int32Array, 4)
58FUNCTION(7, Float32Array, 4)
59FUNCTION(8, Float64Array, 8)
60FUNCTION(9, Uint8ClampedArray, 1)
61endmacro
62
63macro DECLARE_GLOBALS(INDEX, NAME, SIZE)
64var GlobalNAME = global.NAME;
65endmacro
66
67TYPED_ARRAYS(DECLARE_GLOBALS)
68
69utils.Import(function(from) {
70 ArrayFrom = from.ArrayFrom;
71 ArrayToString = from.ArrayToString;
72 ArrayValues = from.ArrayValues;
73 InnerArrayCopyWithin = from.InnerArrayCopyWithin;
74 InnerArrayEvery = from.InnerArrayEvery;
75 InnerArrayFill = from.InnerArrayFill;
76 InnerArrayFilter = from.InnerArrayFilter;
77 InnerArrayFind = from.InnerArrayFind;
78 InnerArrayFindIndex = from.InnerArrayFindIndex;
79 InnerArrayForEach = from.InnerArrayForEach;
80 InnerArrayIncludes = from.InnerArrayIncludes;
81 InnerArrayIndexOf = from.InnerArrayIndexOf;
82 InnerArrayJoin = from.InnerArrayJoin;
83 InnerArrayLastIndexOf = from.InnerArrayLastIndexOf;
84 InnerArrayReduce = from.InnerArrayReduce;
85 InnerArrayReduceRight = from.InnerArrayReduceRight;
86 InnerArraySome = from.InnerArraySome;
87 InnerArraySort = from.InnerArraySort;
88 InnerArrayToLocaleString = from.InnerArrayToLocaleString;
89 IsNaN = from.IsNaN;
90 MakeRangeError = from.MakeRangeError;
91 MakeTypeError = from.MakeTypeError;
92 MaxSimple = from.MaxSimple;
93 MinSimple = from.MinSimple;
94 PackedArrayReverse = from.PackedArrayReverse;
95 SpeciesConstructor = from.SpeciesConstructor;
96 ToPositiveInteger = from.ToPositiveInteger;
97});
98
99// --------------- Typed Arrays ---------------------
100
101function TypedArrayDefaultConstructor(typedArray) {
102 switch (%_ClassOf(typedArray)) {
103macro TYPED_ARRAY_CONSTRUCTOR_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
104 case "NAME":
105 return GlobalNAME;
106endmacro
107TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR_CASE)
108 }
109 // The TypeError should not be generated since all callers should
110 // have already called ValidateTypedArray.
111 throw MakeTypeError(kIncompatibleMethodReceiver,
112 "TypedArrayDefaultConstructor", this);
113}
114
115function TypedArrayCreate(constructor, arg0, arg1, arg2) {
116 if (IS_UNDEFINED(arg1)) {
117 var newTypedArray = new constructor(arg0);
118 } else {
119 var newTypedArray = new constructor(arg0, arg1, arg2);
120 }
121 if (!%_IsTypedArray(newTypedArray)) throw MakeTypeError(kNotTypedArray);
122 // TODO(littledan): Check for being detached, here and elsewhere
123 // All callers where the first argument is a Number have no additional
124 // arguments.
125 if (IS_NUMBER(arg0) && %_TypedArrayGetLength(newTypedArray) < arg0) {
126 throw MakeTypeError(kTypedArrayTooShort);
127 }
128 return newTypedArray;
129}
130
131function TypedArraySpeciesCreate(exemplar, arg0, arg1, arg2, conservative) {
132 var defaultConstructor = TypedArrayDefaultConstructor(exemplar);
133 var constructor = SpeciesConstructor(exemplar, defaultConstructor,
134 conservative);
135 return TypedArrayCreate(constructor, arg0, arg1, arg2);
136}
137
138macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE)
139function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
140 if (!IS_UNDEFINED(byteOffset)) {
141 byteOffset = ToPositiveInteger(byteOffset, kInvalidTypedArrayLength);
142 }
143 if (!IS_UNDEFINED(length)) {
144 length = ToPositiveInteger(length, kInvalidTypedArrayLength);
145 }
146
147 var bufferByteLength = %_ArrayBufferGetByteLength(buffer);
148 var offset;
149 if (IS_UNDEFINED(byteOffset)) {
150 offset = 0;
151 } else {
152 offset = byteOffset;
153
154 if (offset % ELEMENT_SIZE !== 0) {
155 throw MakeRangeError(kInvalidTypedArrayAlignment,
156 "start offset", "NAME", ELEMENT_SIZE);
157 }
158 if (offset > bufferByteLength) {
159 throw MakeRangeError(kInvalidTypedArrayOffset);
160 }
161 }
162
163 var newByteLength;
164 var newLength;
165 if (IS_UNDEFINED(length)) {
166 if (bufferByteLength % ELEMENT_SIZE !== 0) {
167 throw MakeRangeError(kInvalidTypedArrayAlignment,
168 "byte length", "NAME", ELEMENT_SIZE);
169 }
170 newByteLength = bufferByteLength - offset;
171 newLength = newByteLength / ELEMENT_SIZE;
172 } else {
173 var newLength = length;
174 newByteLength = newLength * ELEMENT_SIZE;
175 }
176 if ((offset + newByteLength > bufferByteLength)
177 || (newLength > %_MaxSmi())) {
178 throw MakeRangeError(kInvalidTypedArrayLength);
179 }
180 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength, true);
181}
182
183function NAMEConstructByLength(obj, length) {
184 var l = IS_UNDEFINED(length) ?
185 0 : ToPositiveInteger(length, kInvalidTypedArrayLength);
186 if (l > %_MaxSmi()) {
187 throw MakeRangeError(kInvalidTypedArrayLength);
188 }
189 var byteLength = l * ELEMENT_SIZE;
190 if (byteLength > %_TypedArrayMaxSizeInHeap()) {
191 var buffer = new GlobalArrayBuffer(byteLength);
192 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, 0, byteLength, true);
193 } else {
194 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, true);
195 }
196}
197
198function NAMEConstructByArrayLike(obj, arrayLike) {
199 var length = arrayLike.length;
200 var l = ToPositiveInteger(length, kInvalidTypedArrayLength);
201
202 if (l > %_MaxSmi()) {
203 throw MakeRangeError(kInvalidTypedArrayLength);
204 }
205 var initialized = false;
206 var byteLength = l * ELEMENT_SIZE;
207 if (byteLength <= %_TypedArrayMaxSizeInHeap()) {
208 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, false);
209 } else {
210 initialized =
211 %TypedArrayInitializeFromArrayLike(obj, ARRAY_ID, arrayLike, l);
212 }
213 if (!initialized) {
214 for (var i = 0; i < l; i++) {
215 // It is crucial that we let any execptions from arrayLike[i]
216 // propagate outside the function.
217 obj[i] = arrayLike[i];
218 }
219 }
220}
221
222function NAMEConstructByIterable(obj, iterable, iteratorFn) {
223 var list = new InternalArray();
224 // Reading the Symbol.iterator property of iterable twice would be
225 // observable with getters, so instead, we call the function which
226 // was already looked up, and wrap it in another iterable. The
227 // __proto__ of the new iterable is set to null to avoid any chance
228 // of modifications to Object.prototype being observable here.
229 var iterator = %_Call(iteratorFn, iterable);
230 var newIterable = {
231 __proto__: null
232 };
233 // TODO(littledan): Computed properties don't work yet in nosnap.
234 // Rephrase when they do.
235 newIterable[iteratorSymbol] = function() { return iterator; }
236 for (var value of newIterable) {
237 list.push(value);
238 }
239 NAMEConstructByArrayLike(obj, list);
240}
241
242function NAMEConstructor(arg1, arg2, arg3) {
243 if (!IS_UNDEFINED(new.target)) {
244 if (IS_ARRAYBUFFER(arg1) || IS_SHAREDARRAYBUFFER(arg1)) {
245 NAMEConstructByArrayBuffer(this, arg1, arg2, arg3);
246 } else if (IS_NUMBER(arg1) || IS_STRING(arg1) ||
247 IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) {
248 NAMEConstructByLength(this, arg1);
249 } else {
250 // TODO(littledan): If arg1 is a TypedArray, follow the constructor
251 // path in ES2015 22.2.4.3, and call SpeciesConstructor, in a
252 // path that seems to be an optimized version of what's below, but
253 // in an observably different way.
254 var iteratorFn = arg1[iteratorSymbol];
255 if (IS_UNDEFINED(iteratorFn) || iteratorFn === ArrayValues) {
256 NAMEConstructByArrayLike(this, arg1);
257 } else {
258 NAMEConstructByIterable(this, arg1, iteratorFn);
259 }
260 }
261 } else {
262 throw MakeTypeError(kConstructorNotFunction, "NAME")
263 }
264}
265
266// TODO(littledan): Remove this performance workaround BUG(chromium:579905)
267function NAME_GetLength() {
268 if (!(%_ClassOf(this) === 'NAME')) {
269 throw MakeTypeError(kIncompatibleMethodReceiver, "NAME.length", this);
270 }
271 return %_TypedArrayGetLength(this);
272}
273
274function NAMESubArray(begin, end) {
275 var beginInt = TO_INTEGER(begin);
276 if (!IS_UNDEFINED(end)) {
277 var endInt = TO_INTEGER(end);
278 var srcLength = %_TypedArrayGetLength(this);
279 } else {
280 var srcLength = %_TypedArrayGetLength(this);
281 var endInt = srcLength;
282 }
283
284 if (beginInt < 0) {
285 beginInt = MaxSimple(0, srcLength + beginInt);
286 } else {
287 beginInt = MinSimple(beginInt, srcLength);
288 }
289
290 if (endInt < 0) {
291 endInt = MaxSimple(0, srcLength + endInt);
292 } else {
293 endInt = MinSimple(endInt, srcLength);
294 }
295
296 if (endInt < beginInt) {
297 endInt = beginInt;
298 }
299
300 var newLength = endInt - beginInt;
301 var beginByteOffset =
302 %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100303 // BUG(v8:4665): For web compatibility, subarray needs to always build an
304 // instance of the default constructor.
305 // TODO(littledan): Switch to the standard or standardize the fix
306 return new GlobalNAME(%TypedArrayGetBuffer(this), beginByteOffset, newLength);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000307}
308endmacro
309
310TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR)
311
312function TypedArraySubArray(begin, end) {
313 switch (%_ClassOf(this)) {
314macro TYPED_ARRAY_SUBARRAY_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
315 case "NAME":
316 return %_Call(NAMESubArray, this, begin, end);
317endmacro
318TYPED_ARRAYS(TYPED_ARRAY_SUBARRAY_CASE)
319 }
320 throw MakeTypeError(kIncompatibleMethodReceiver,
321 "get TypedArray.prototype.subarray", this);
322}
323%SetForceInlineFlag(TypedArraySubArray);
324
325function TypedArrayGetBuffer() {
326 if (!%_IsTypedArray(this)) {
327 throw MakeTypeError(kIncompatibleMethodReceiver,
328 "get TypedArray.prototype.buffer", this);
329 }
330 return %TypedArrayGetBuffer(this);
331}
332%SetForceInlineFlag(TypedArrayGetBuffer);
333
334function TypedArrayGetByteLength() {
335 if (!%_IsTypedArray(this)) {
336 throw MakeTypeError(kIncompatibleMethodReceiver,
337 "get TypedArray.prototype.byteLength", this);
338 }
339 return %_ArrayBufferViewGetByteLength(this);
340}
341%SetForceInlineFlag(TypedArrayGetByteLength);
342
343function TypedArrayGetByteOffset() {
344 if (!%_IsTypedArray(this)) {
345 throw MakeTypeError(kIncompatibleMethodReceiver,
346 "get TypedArray.prototype.byteOffset", this);
347 }
348 return %_ArrayBufferViewGetByteOffset(this);
349}
350%SetForceInlineFlag(TypedArrayGetByteOffset);
351
352function TypedArrayGetLength() {
353 if (!%_IsTypedArray(this)) {
354 throw MakeTypeError(kIncompatibleMethodReceiver,
355 "get TypedArray.prototype.length", this);
356 }
357 return %_TypedArrayGetLength(this);
358}
359%SetForceInlineFlag(TypedArrayGetLength);
360
361
362
363function TypedArraySetFromArrayLike(target, source, sourceLength, offset) {
364 if (offset > 0) {
365 for (var i = 0; i < sourceLength; i++) {
366 target[offset + i] = source[i];
367 }
368 }
369 else {
370 for (var i = 0; i < sourceLength; i++) {
371 target[i] = source[i];
372 }
373 }
374}
375
376function TypedArraySetFromOverlappingTypedArray(target, source, offset) {
377 var sourceElementSize = source.BYTES_PER_ELEMENT;
378 var targetElementSize = target.BYTES_PER_ELEMENT;
379 var sourceLength = source.length;
380
381 // Copy left part.
382 function CopyLeftPart() {
383 // First un-mutated byte after the next write
384 var targetPtr = target.byteOffset + (offset + 1) * targetElementSize;
385 // Next read at sourcePtr. We do not care for memory changing before
386 // sourcePtr - we have already copied it.
387 var sourcePtr = source.byteOffset;
388 for (var leftIndex = 0;
389 leftIndex < sourceLength && targetPtr <= sourcePtr;
390 leftIndex++) {
391 target[offset + leftIndex] = source[leftIndex];
392 targetPtr += targetElementSize;
393 sourcePtr += sourceElementSize;
394 }
395 return leftIndex;
396 }
397 var leftIndex = CopyLeftPart();
398
399 // Copy rigth part;
400 function CopyRightPart() {
401 // First unmutated byte before the next write
402 var targetPtr =
403 target.byteOffset + (offset + sourceLength - 1) * targetElementSize;
404 // Next read before sourcePtr. We do not care for memory changing after
405 // sourcePtr - we have already copied it.
406 var sourcePtr =
407 source.byteOffset + sourceLength * sourceElementSize;
408 for(var rightIndex = sourceLength - 1;
409 rightIndex >= leftIndex && targetPtr >= sourcePtr;
410 rightIndex--) {
411 target[offset + rightIndex] = source[rightIndex];
412 targetPtr -= targetElementSize;
413 sourcePtr -= sourceElementSize;
414 }
415 return rightIndex;
416 }
417 var rightIndex = CopyRightPart();
418
419 var temp = new GlobalArray(rightIndex + 1 - leftIndex);
420 for (var i = leftIndex; i <= rightIndex; i++) {
421 temp[i - leftIndex] = source[i];
422 }
423 for (i = leftIndex; i <= rightIndex; i++) {
424 target[offset + i] = temp[i - leftIndex];
425 }
426}
427
428function TypedArraySet(obj, offset) {
429 var intOffset = IS_UNDEFINED(offset) ? 0 : TO_INTEGER(offset);
430 if (intOffset < 0) throw MakeTypeError(kTypedArraySetNegativeOffset);
431
432 if (intOffset > %_MaxSmi()) {
433 throw MakeRangeError(kTypedArraySetSourceTooLarge);
434 }
435 switch (%TypedArraySetFastCases(this, obj, intOffset)) {
436 // These numbers should be synchronized with runtime.cc.
437 case 0: // TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE
438 return;
439 case 1: // TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING
440 TypedArraySetFromOverlappingTypedArray(this, obj, intOffset);
441 return;
442 case 2: // TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING
443 TypedArraySetFromArrayLike(this, obj, obj.length, intOffset);
444 return;
445 case 3: // TYPED_ARRAY_SET_NON_TYPED_ARRAY
446 var l = obj.length;
447 if (IS_UNDEFINED(l)) {
448 if (IS_NUMBER(obj)) {
449 // For number as a first argument, throw TypeError
450 // instead of silently ignoring the call, so that
451 // the user knows (s)he did something wrong.
452 // (Consistent with Firefox and Blink/WebKit)
453 throw MakeTypeError(kInvalidArgument);
454 }
455 return;
456 }
457 l = TO_LENGTH(l);
458 if (intOffset + l > this.length) {
459 throw MakeRangeError(kTypedArraySetSourceTooLarge);
460 }
461 TypedArraySetFromArrayLike(this, obj, l, intOffset);
462 return;
463 }
464}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100465%FunctionSetLength(TypedArraySet, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466
467function TypedArrayGetToStringTag() {
468 if (!%_IsTypedArray(this)) return;
469 var name = %_ClassOf(this);
470 if (IS_UNDEFINED(name)) return;
471 return name;
472}
473
474
475function TypedArrayCopyWithin(target, start, end) {
476 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
477
478 var length = %_TypedArrayGetLength(this);
479
480 // TODO(littledan): Replace with a memcpy for better performance
481 return InnerArrayCopyWithin(target, start, end, this, length);
482}
483%FunctionSetLength(TypedArrayCopyWithin, 2);
484
485
486// ES6 draft 05-05-15, section 22.2.3.7
487function TypedArrayEvery(f, receiver) {
488 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
489
490 var length = %_TypedArrayGetLength(this);
491
492 return InnerArrayEvery(f, receiver, this, length);
493}
494%FunctionSetLength(TypedArrayEvery, 1);
495
496
497// ES6 draft 08-24-14, section 22.2.3.12
498function TypedArrayForEach(f, receiver) {
499 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
500
501 var length = %_TypedArrayGetLength(this);
502
503 InnerArrayForEach(f, receiver, this, length);
504}
505%FunctionSetLength(TypedArrayForEach, 1);
506
507
508// ES6 draft 04-05-14 section 22.2.3.8
509function TypedArrayFill(value, start, end) {
510 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
511
512 var length = %_TypedArrayGetLength(this);
513
514 return InnerArrayFill(value, start, end, this, length);
515}
516%FunctionSetLength(TypedArrayFill, 1);
517
518
519// ES6 draft 07-15-13, section 22.2.3.9
520function TypedArrayFilter(f, thisArg) {
521 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
522
523 var length = %_TypedArrayGetLength(this);
524 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
525 var result = new InternalArray();
526 InnerArrayFilter(f, thisArg, this, length, result);
527 var captured = result.length;
528 var output = TypedArraySpeciesCreate(this, captured);
529 for (var i = 0; i < captured; i++) {
530 output[i] = result[i];
531 }
532 return output;
533}
534%FunctionSetLength(TypedArrayFilter, 1);
535
536
537// ES6 draft 07-15-13, section 22.2.3.10
538function TypedArrayFind(predicate, thisArg) {
539 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
540
541 var length = %_TypedArrayGetLength(this);
542
543 return InnerArrayFind(predicate, thisArg, this, length);
544}
545%FunctionSetLength(TypedArrayFind, 1);
546
547
548// ES6 draft 07-15-13, section 22.2.3.11
549function TypedArrayFindIndex(predicate, thisArg) {
550 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
551
552 var length = %_TypedArrayGetLength(this);
553
554 return InnerArrayFindIndex(predicate, thisArg, this, length);
555}
556%FunctionSetLength(TypedArrayFindIndex, 1);
557
558
559// ES6 draft 05-18-15, section 22.2.3.21
560function TypedArrayReverse() {
561 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
562
563 var length = %_TypedArrayGetLength(this);
564
565 return PackedArrayReverse(this, length);
566}
567
568
569function TypedArrayComparefn(x, y) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100570 if (x === 0 && x === y) {
571 x = 1 / x;
572 y = 1 / y;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000573 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100574 if (x < y) {
575 return -1;
576 } else if (x > y) {
577 return 1;
578 } else if (IsNaN(x) && IsNaN(y)) {
579 return IsNaN(y) ? 0 : 1;
580 } else if (IsNaN(x)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000581 return 1;
582 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100583 return 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000584}
585
586
587// ES6 draft 05-18-15, section 22.2.3.25
588function TypedArraySort(comparefn) {
589 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
590
591 var length = %_TypedArrayGetLength(this);
592
593 if (IS_UNDEFINED(comparefn)) {
594 comparefn = TypedArrayComparefn;
595 }
596
597 return InnerArraySort(this, length, comparefn);
598}
599
600
601// ES6 section 22.2.3.13
602function TypedArrayIndexOf(element, index) {
603 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
604
605 var length = %_TypedArrayGetLength(this);
606 return InnerArrayIndexOf(this, element, index, length);
607}
608%FunctionSetLength(TypedArrayIndexOf, 1);
609
610
611// ES6 section 22.2.3.16
612function TypedArrayLastIndexOf(element, index) {
613 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
614
615 var length = %_TypedArrayGetLength(this);
616
617 return InnerArrayLastIndexOf(this, element, index, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100618 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000619}
620%FunctionSetLength(TypedArrayLastIndexOf, 1);
621
622
623// ES6 draft 07-15-13, section 22.2.3.18
624function TypedArrayMap(f, thisArg) {
625 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
626
627 var length = %_TypedArrayGetLength(this);
628 var result = TypedArraySpeciesCreate(this, length);
629 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
630 for (var i = 0; i < length; i++) {
631 var element = this[i];
632 result[i] = %_Call(f, thisArg, element, i, this);
633 }
634 return result;
635}
636%FunctionSetLength(TypedArrayMap, 1);
637
638
639// ES6 draft 05-05-15, section 22.2.3.24
640function TypedArraySome(f, receiver) {
641 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
642
643 var length = %_TypedArrayGetLength(this);
644
645 return InnerArraySome(f, receiver, this, length);
646}
647%FunctionSetLength(TypedArraySome, 1);
648
649
650// ES6 section 22.2.3.27
651function TypedArrayToLocaleString() {
652 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
653
654 var length = %_TypedArrayGetLength(this);
655
656 return InnerArrayToLocaleString(this, length);
657}
658
659
660// ES6 section 22.2.3.28
661function TypedArrayToString() {
662 return %_Call(ArrayToString, this);
663}
664
665
666// ES6 section 22.2.3.14
667function TypedArrayJoin(separator) {
668 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
669
670 var length = %_TypedArrayGetLength(this);
671
672 return InnerArrayJoin(separator, this, length);
673}
674
675
676// ES6 draft 07-15-13, section 22.2.3.19
677function TypedArrayReduce(callback, current) {
678 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
679
680 var length = %_TypedArrayGetLength(this);
681 return InnerArrayReduce(callback, current, this, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100682 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683}
684%FunctionSetLength(TypedArrayReduce, 1);
685
686
687// ES6 draft 07-15-13, section 22.2.3.19
688function TypedArrayReduceRight(callback, current) {
689 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
690
691 var length = %_TypedArrayGetLength(this);
692 return InnerArrayReduceRight(callback, current, this, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100693 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000694}
695%FunctionSetLength(TypedArrayReduceRight, 1);
696
697
698function TypedArraySlice(start, end) {
699 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
700 var len = %_TypedArrayGetLength(this);
701
702 var relativeStart = TO_INTEGER(start);
703
704 var k;
705 if (relativeStart < 0) {
706 k = MaxSimple(len + relativeStart, 0);
707 } else {
708 k = MinSimple(relativeStart, len);
709 }
710
711 var relativeEnd;
712 if (IS_UNDEFINED(end)) {
713 relativeEnd = len;
714 } else {
715 relativeEnd = TO_INTEGER(end);
716 }
717
718 var final;
719 if (relativeEnd < 0) {
720 final = MaxSimple(len + relativeEnd, 0);
721 } else {
722 final = MinSimple(relativeEnd, len);
723 }
724
725 var count = MaxSimple(final - k, 0);
726 var array = TypedArraySpeciesCreate(this, count);
727 // The code below is the 'then' branch; the 'else' branch species
728 // a memcpy. Because V8 doesn't canonicalize NaN, the difference is
729 // unobservable.
730 var n = 0;
731 while (k < final) {
732 var kValue = this[k];
733 array[n] = kValue;
734 k++;
735 n++;
736 }
737 return array;
738}
739
740
741// ES2016 draft, section 22.2.3.14
742function TypedArrayIncludes(searchElement, fromIndex) {
743 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
744
745 var length = %_TypedArrayGetLength(this);
746
747 return InnerArrayIncludes(searchElement, fromIndex, this, length);
748}
749%FunctionSetLength(TypedArrayIncludes, 1);
750
751
752// ES6 draft 08-24-14, section 22.2.2.2
753function TypedArrayOf() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100754 var length = arguments.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000755 var array = TypedArrayCreate(this, length);
756 for (var i = 0; i < length; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100757 array[i] = arguments[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000758 }
759 return array;
760}
761
762
763function TypedArrayFrom(source, mapfn, thisArg) {
764 // TODO(littledan): Investigate if there is a receiver which could be
765 // faster to accumulate on than Array, e.g., a TypedVector.
766 // TODO(littledan): Rewrite this code to ensure that things happen
767 // in the right order, e.g., the constructor needs to be called before
768 // the mapping function on array-likes.
769 var array = %_Call(ArrayFrom, GlobalArray, source, mapfn, thisArg);
770 return TypedArrayCreate(this, array);
771}
772%FunctionSetLength(TypedArrayFrom, 1);
773
774function TypedArray() {
775 if (IS_UNDEFINED(new.target)) {
776 throw MakeTypeError(kConstructorNonCallable, "TypedArray");
777 }
778 if (new.target === TypedArray) {
779 throw MakeTypeError(kConstructAbstractClass, "TypedArray");
780 }
781}
782
783// -------------------------------------------------------------------
784
785%FunctionSetPrototype(TypedArray, new GlobalObject());
786%AddNamedProperty(TypedArray.prototype,
787 "constructor", TypedArray, DONT_ENUM);
788utils.InstallFunctions(TypedArray, DONT_ENUM | DONT_DELETE | READ_ONLY, [
789 "from", TypedArrayFrom,
790 "of", TypedArrayOf
791]);
792utils.InstallGetter(TypedArray.prototype, "buffer", TypedArrayGetBuffer);
793utils.InstallGetter(TypedArray.prototype, "byteOffset", TypedArrayGetByteOffset,
794 DONT_ENUM | DONT_DELETE);
795utils.InstallGetter(TypedArray.prototype, "byteLength",
796 TypedArrayGetByteLength, DONT_ENUM | DONT_DELETE);
797utils.InstallGetter(TypedArray.prototype, "length", TypedArrayGetLength,
798 DONT_ENUM | DONT_DELETE);
799utils.InstallGetter(TypedArray.prototype, toStringTagSymbol,
800 TypedArrayGetToStringTag);
801utils.InstallFunctions(TypedArray.prototype, DONT_ENUM, [
802 "subarray", TypedArraySubArray,
803 "set", TypedArraySet,
804 "copyWithin", TypedArrayCopyWithin,
805 "every", TypedArrayEvery,
806 "fill", TypedArrayFill,
807 "filter", TypedArrayFilter,
808 "find", TypedArrayFind,
809 "findIndex", TypedArrayFindIndex,
810 "includes", TypedArrayIncludes,
811 "indexOf", TypedArrayIndexOf,
812 "join", TypedArrayJoin,
813 "lastIndexOf", TypedArrayLastIndexOf,
814 "forEach", TypedArrayForEach,
815 "map", TypedArrayMap,
816 "reduce", TypedArrayReduce,
817 "reduceRight", TypedArrayReduceRight,
818 "reverse", TypedArrayReverse,
819 "slice", TypedArraySlice,
820 "some", TypedArraySome,
821 "sort", TypedArraySort,
822 "toString", TypedArrayToString,
823 "toLocaleString", TypedArrayToLocaleString
824]);
825
826
827macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE)
828 %SetCode(GlobalNAME, NAMEConstructor);
829 %FunctionSetPrototype(GlobalNAME, new GlobalObject());
830 %InternalSetPrototype(GlobalNAME, TypedArray);
831 %InternalSetPrototype(GlobalNAME.prototype, TypedArray.prototype);
832
833 %AddNamedProperty(GlobalNAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE,
834 READ_ONLY | DONT_ENUM | DONT_DELETE);
835
836 %AddNamedProperty(GlobalNAME.prototype,
837 "constructor", global.NAME, DONT_ENUM);
838 %AddNamedProperty(GlobalNAME.prototype,
839 "BYTES_PER_ELEMENT", ELEMENT_SIZE,
840 READ_ONLY | DONT_ENUM | DONT_DELETE);
841 // TODO(littledan): Remove this performance workaround BUG(chromium:579905)
842 utils.InstallGetter(GlobalNAME.prototype, "length", NAME_GetLength,
843 DONT_ENUM | DONT_DELETE);
844endmacro
845
846TYPED_ARRAYS(SETUP_TYPED_ARRAY)
847
848// --------------------------- DataView -----------------------------
849
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000850function DataViewGetBufferJS() {
851 if (!IS_DATAVIEW(this)) {
852 throw MakeTypeError(kIncompatibleMethodReceiver, 'DataView.buffer', this);
853 }
854 return %DataViewGetBuffer(this);
855}
856
857function DataViewGetByteOffset() {
858 if (!IS_DATAVIEW(this)) {
859 throw MakeTypeError(kIncompatibleMethodReceiver,
860 'DataView.byteOffset', this);
861 }
862 return %_ArrayBufferViewGetByteOffset(this);
863}
864
865function DataViewGetByteLength() {
866 if (!IS_DATAVIEW(this)) {
867 throw MakeTypeError(kIncompatibleMethodReceiver,
868 'DataView.byteLength', this);
869 }
870 return %_ArrayBufferViewGetByteLength(this);
871}
872
873macro DATA_VIEW_TYPES(FUNCTION)
874 FUNCTION(Int8)
875 FUNCTION(Uint8)
876 FUNCTION(Int16)
877 FUNCTION(Uint16)
878 FUNCTION(Int32)
879 FUNCTION(Uint32)
880 FUNCTION(Float32)
881 FUNCTION(Float64)
882endmacro
883
884
885macro DATA_VIEW_GETTER_SETTER(TYPENAME)
886function DataViewGetTYPENAMEJS(offset, little_endian) {
887 if (!IS_DATAVIEW(this)) {
888 throw MakeTypeError(kIncompatibleMethodReceiver,
889 'DataView.getTYPENAME', this);
890 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100891 if (arguments.length < 1) throw MakeTypeError(kInvalidArgument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892 offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
893 return %DataViewGetTYPENAME(this, offset, !!little_endian);
894}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100895%FunctionSetLength(DataViewGetTYPENAMEJS, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896
897function DataViewSetTYPENAMEJS(offset, value, little_endian) {
898 if (!IS_DATAVIEW(this)) {
899 throw MakeTypeError(kIncompatibleMethodReceiver,
900 'DataView.setTYPENAME', this);
901 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100902 if (arguments.length < 2) throw MakeTypeError(kInvalidArgument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000903 offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
904 %DataViewSetTYPENAME(this, offset, TO_NUMBER(value), !!little_endian);
905}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100906%FunctionSetLength(DataViewSetTYPENAMEJS, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000907endmacro
908
909DATA_VIEW_TYPES(DATA_VIEW_GETTER_SETTER)
910
911// Setup the DataView constructor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000912%FunctionSetPrototype(GlobalDataView, new GlobalObject);
913
914// Set up constructor property on the DataView prototype.
915%AddNamedProperty(GlobalDataView.prototype, "constructor", GlobalDataView,
916 DONT_ENUM);
917%AddNamedProperty(GlobalDataView.prototype, toStringTagSymbol, "DataView",
918 READ_ONLY|DONT_ENUM);
919
920utils.InstallGetter(GlobalDataView.prototype, "buffer", DataViewGetBufferJS);
921utils.InstallGetter(GlobalDataView.prototype, "byteOffset",
922 DataViewGetByteOffset);
923utils.InstallGetter(GlobalDataView.prototype, "byteLength",
924 DataViewGetByteLength);
925
926utils.InstallFunctions(GlobalDataView.prototype, DONT_ENUM, [
927 "getInt8", DataViewGetInt8JS,
928 "setInt8", DataViewSetInt8JS,
929
930 "getUint8", DataViewGetUint8JS,
931 "setUint8", DataViewSetUint8JS,
932
933 "getInt16", DataViewGetInt16JS,
934 "setInt16", DataViewSetInt16JS,
935
936 "getUint16", DataViewGetUint16JS,
937 "setUint16", DataViewSetUint16JS,
938
939 "getInt32", DataViewGetInt32JS,
940 "setInt32", DataViewSetInt32JS,
941
942 "getUint32", DataViewGetUint32JS,
943 "setUint32", DataViewSetUint32JS,
944
945 "getFloat32", DataViewGetFloat32JS,
946 "setFloat32", DataViewSetFloat32JS,
947
948 "getFloat64", DataViewGetFloat64JS,
949 "setFloat64", DataViewSetFloat64JS
950]);
951
952})