blob: fd668a57fddceb2222d31d91ccad806dc5395bc8 [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;
303 return TypedArraySpeciesCreate(this, %TypedArrayGetBuffer(this),
304 beginByteOffset, newLength, true);
305}
306endmacro
307
308TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR)
309
310function TypedArraySubArray(begin, end) {
311 switch (%_ClassOf(this)) {
312macro TYPED_ARRAY_SUBARRAY_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
313 case "NAME":
314 return %_Call(NAMESubArray, this, begin, end);
315endmacro
316TYPED_ARRAYS(TYPED_ARRAY_SUBARRAY_CASE)
317 }
318 throw MakeTypeError(kIncompatibleMethodReceiver,
319 "get TypedArray.prototype.subarray", this);
320}
321%SetForceInlineFlag(TypedArraySubArray);
322
323function TypedArrayGetBuffer() {
324 if (!%_IsTypedArray(this)) {
325 throw MakeTypeError(kIncompatibleMethodReceiver,
326 "get TypedArray.prototype.buffer", this);
327 }
328 return %TypedArrayGetBuffer(this);
329}
330%SetForceInlineFlag(TypedArrayGetBuffer);
331
332function TypedArrayGetByteLength() {
333 if (!%_IsTypedArray(this)) {
334 throw MakeTypeError(kIncompatibleMethodReceiver,
335 "get TypedArray.prototype.byteLength", this);
336 }
337 return %_ArrayBufferViewGetByteLength(this);
338}
339%SetForceInlineFlag(TypedArrayGetByteLength);
340
341function TypedArrayGetByteOffset() {
342 if (!%_IsTypedArray(this)) {
343 throw MakeTypeError(kIncompatibleMethodReceiver,
344 "get TypedArray.prototype.byteOffset", this);
345 }
346 return %_ArrayBufferViewGetByteOffset(this);
347}
348%SetForceInlineFlag(TypedArrayGetByteOffset);
349
350function TypedArrayGetLength() {
351 if (!%_IsTypedArray(this)) {
352 throw MakeTypeError(kIncompatibleMethodReceiver,
353 "get TypedArray.prototype.length", this);
354 }
355 return %_TypedArrayGetLength(this);
356}
357%SetForceInlineFlag(TypedArrayGetLength);
358
359
360
361function TypedArraySetFromArrayLike(target, source, sourceLength, offset) {
362 if (offset > 0) {
363 for (var i = 0; i < sourceLength; i++) {
364 target[offset + i] = source[i];
365 }
366 }
367 else {
368 for (var i = 0; i < sourceLength; i++) {
369 target[i] = source[i];
370 }
371 }
372}
373
374function TypedArraySetFromOverlappingTypedArray(target, source, offset) {
375 var sourceElementSize = source.BYTES_PER_ELEMENT;
376 var targetElementSize = target.BYTES_PER_ELEMENT;
377 var sourceLength = source.length;
378
379 // Copy left part.
380 function CopyLeftPart() {
381 // First un-mutated byte after the next write
382 var targetPtr = target.byteOffset + (offset + 1) * targetElementSize;
383 // Next read at sourcePtr. We do not care for memory changing before
384 // sourcePtr - we have already copied it.
385 var sourcePtr = source.byteOffset;
386 for (var leftIndex = 0;
387 leftIndex < sourceLength && targetPtr <= sourcePtr;
388 leftIndex++) {
389 target[offset + leftIndex] = source[leftIndex];
390 targetPtr += targetElementSize;
391 sourcePtr += sourceElementSize;
392 }
393 return leftIndex;
394 }
395 var leftIndex = CopyLeftPart();
396
397 // Copy rigth part;
398 function CopyRightPart() {
399 // First unmutated byte before the next write
400 var targetPtr =
401 target.byteOffset + (offset + sourceLength - 1) * targetElementSize;
402 // Next read before sourcePtr. We do not care for memory changing after
403 // sourcePtr - we have already copied it.
404 var sourcePtr =
405 source.byteOffset + sourceLength * sourceElementSize;
406 for(var rightIndex = sourceLength - 1;
407 rightIndex >= leftIndex && targetPtr >= sourcePtr;
408 rightIndex--) {
409 target[offset + rightIndex] = source[rightIndex];
410 targetPtr -= targetElementSize;
411 sourcePtr -= sourceElementSize;
412 }
413 return rightIndex;
414 }
415 var rightIndex = CopyRightPart();
416
417 var temp = new GlobalArray(rightIndex + 1 - leftIndex);
418 for (var i = leftIndex; i <= rightIndex; i++) {
419 temp[i - leftIndex] = source[i];
420 }
421 for (i = leftIndex; i <= rightIndex; i++) {
422 target[offset + i] = temp[i - leftIndex];
423 }
424}
425
426function TypedArraySet(obj, offset) {
427 var intOffset = IS_UNDEFINED(offset) ? 0 : TO_INTEGER(offset);
428 if (intOffset < 0) throw MakeTypeError(kTypedArraySetNegativeOffset);
429
430 if (intOffset > %_MaxSmi()) {
431 throw MakeRangeError(kTypedArraySetSourceTooLarge);
432 }
433 switch (%TypedArraySetFastCases(this, obj, intOffset)) {
434 // These numbers should be synchronized with runtime.cc.
435 case 0: // TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE
436 return;
437 case 1: // TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING
438 TypedArraySetFromOverlappingTypedArray(this, obj, intOffset);
439 return;
440 case 2: // TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING
441 TypedArraySetFromArrayLike(this, obj, obj.length, intOffset);
442 return;
443 case 3: // TYPED_ARRAY_SET_NON_TYPED_ARRAY
444 var l = obj.length;
445 if (IS_UNDEFINED(l)) {
446 if (IS_NUMBER(obj)) {
447 // For number as a first argument, throw TypeError
448 // instead of silently ignoring the call, so that
449 // the user knows (s)he did something wrong.
450 // (Consistent with Firefox and Blink/WebKit)
451 throw MakeTypeError(kInvalidArgument);
452 }
453 return;
454 }
455 l = TO_LENGTH(l);
456 if (intOffset + l > this.length) {
457 throw MakeRangeError(kTypedArraySetSourceTooLarge);
458 }
459 TypedArraySetFromArrayLike(this, obj, l, intOffset);
460 return;
461 }
462}
463
464function TypedArrayGetToStringTag() {
465 if (!%_IsTypedArray(this)) return;
466 var name = %_ClassOf(this);
467 if (IS_UNDEFINED(name)) return;
468 return name;
469}
470
471
472function TypedArrayCopyWithin(target, start, end) {
473 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
474
475 var length = %_TypedArrayGetLength(this);
476
477 // TODO(littledan): Replace with a memcpy for better performance
478 return InnerArrayCopyWithin(target, start, end, this, length);
479}
480%FunctionSetLength(TypedArrayCopyWithin, 2);
481
482
483// ES6 draft 05-05-15, section 22.2.3.7
484function TypedArrayEvery(f, receiver) {
485 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
486
487 var length = %_TypedArrayGetLength(this);
488
489 return InnerArrayEvery(f, receiver, this, length);
490}
491%FunctionSetLength(TypedArrayEvery, 1);
492
493
494// ES6 draft 08-24-14, section 22.2.3.12
495function TypedArrayForEach(f, receiver) {
496 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
497
498 var length = %_TypedArrayGetLength(this);
499
500 InnerArrayForEach(f, receiver, this, length);
501}
502%FunctionSetLength(TypedArrayForEach, 1);
503
504
505// ES6 draft 04-05-14 section 22.2.3.8
506function TypedArrayFill(value, start, end) {
507 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
508
509 var length = %_TypedArrayGetLength(this);
510
511 return InnerArrayFill(value, start, end, this, length);
512}
513%FunctionSetLength(TypedArrayFill, 1);
514
515
516// ES6 draft 07-15-13, section 22.2.3.9
517function TypedArrayFilter(f, thisArg) {
518 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
519
520 var length = %_TypedArrayGetLength(this);
521 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
522 var result = new InternalArray();
523 InnerArrayFilter(f, thisArg, this, length, result);
524 var captured = result.length;
525 var output = TypedArraySpeciesCreate(this, captured);
526 for (var i = 0; i < captured; i++) {
527 output[i] = result[i];
528 }
529 return output;
530}
531%FunctionSetLength(TypedArrayFilter, 1);
532
533
534// ES6 draft 07-15-13, section 22.2.3.10
535function TypedArrayFind(predicate, thisArg) {
536 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
537
538 var length = %_TypedArrayGetLength(this);
539
540 return InnerArrayFind(predicate, thisArg, this, length);
541}
542%FunctionSetLength(TypedArrayFind, 1);
543
544
545// ES6 draft 07-15-13, section 22.2.3.11
546function TypedArrayFindIndex(predicate, thisArg) {
547 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
548
549 var length = %_TypedArrayGetLength(this);
550
551 return InnerArrayFindIndex(predicate, thisArg, this, length);
552}
553%FunctionSetLength(TypedArrayFindIndex, 1);
554
555
556// ES6 draft 05-18-15, section 22.2.3.21
557function TypedArrayReverse() {
558 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
559
560 var length = %_TypedArrayGetLength(this);
561
562 return PackedArrayReverse(this, length);
563}
564
565
566function TypedArrayComparefn(x, y) {
567 if (IsNaN(x) && IsNaN(y)) {
568 return IsNaN(y) ? 0 : 1;
569 }
570 if (IsNaN(x)) {
571 return 1;
572 }
573 if (x === 0 && x === y) {
574 if (%_IsMinusZero(x)) {
575 if (!%_IsMinusZero(y)) {
576 return -1;
577 }
578 } else if (%_IsMinusZero(y)) {
579 return 1;
580 }
581 }
582 return x - y;
583}
584
585
586// ES6 draft 05-18-15, section 22.2.3.25
587function TypedArraySort(comparefn) {
588 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
589
590 var length = %_TypedArrayGetLength(this);
591
592 if (IS_UNDEFINED(comparefn)) {
593 comparefn = TypedArrayComparefn;
594 }
595
596 return InnerArraySort(this, length, comparefn);
597}
598
599
600// ES6 section 22.2.3.13
601function TypedArrayIndexOf(element, index) {
602 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
603
604 var length = %_TypedArrayGetLength(this);
605 return InnerArrayIndexOf(this, element, index, length);
606}
607%FunctionSetLength(TypedArrayIndexOf, 1);
608
609
610// ES6 section 22.2.3.16
611function TypedArrayLastIndexOf(element, index) {
612 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
613
614 var length = %_TypedArrayGetLength(this);
615
616 return InnerArrayLastIndexOf(this, element, index, length,
617 %_ArgumentsLength());
618}
619%FunctionSetLength(TypedArrayLastIndexOf, 1);
620
621
622// ES6 draft 07-15-13, section 22.2.3.18
623function TypedArrayMap(f, thisArg) {
624 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
625
626 var length = %_TypedArrayGetLength(this);
627 var result = TypedArraySpeciesCreate(this, length);
628 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
629 for (var i = 0; i < length; i++) {
630 var element = this[i];
631 result[i] = %_Call(f, thisArg, element, i, this);
632 }
633 return result;
634}
635%FunctionSetLength(TypedArrayMap, 1);
636
637
638// ES6 draft 05-05-15, section 22.2.3.24
639function TypedArraySome(f, receiver) {
640 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
641
642 var length = %_TypedArrayGetLength(this);
643
644 return InnerArraySome(f, receiver, this, length);
645}
646%FunctionSetLength(TypedArraySome, 1);
647
648
649// ES6 section 22.2.3.27
650function TypedArrayToLocaleString() {
651 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
652
653 var length = %_TypedArrayGetLength(this);
654
655 return InnerArrayToLocaleString(this, length);
656}
657
658
659// ES6 section 22.2.3.28
660function TypedArrayToString() {
661 return %_Call(ArrayToString, this);
662}
663
664
665// ES6 section 22.2.3.14
666function TypedArrayJoin(separator) {
667 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
668
669 var length = %_TypedArrayGetLength(this);
670
671 return InnerArrayJoin(separator, this, length);
672}
673
674
675// ES6 draft 07-15-13, section 22.2.3.19
676function TypedArrayReduce(callback, current) {
677 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
678
679 var length = %_TypedArrayGetLength(this);
680 return InnerArrayReduce(callback, current, this, length,
681 %_ArgumentsLength());
682}
683%FunctionSetLength(TypedArrayReduce, 1);
684
685
686// ES6 draft 07-15-13, section 22.2.3.19
687function TypedArrayReduceRight(callback, current) {
688 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
689
690 var length = %_TypedArrayGetLength(this);
691 return InnerArrayReduceRight(callback, current, this, length,
692 %_ArgumentsLength());
693}
694%FunctionSetLength(TypedArrayReduceRight, 1);
695
696
697function TypedArraySlice(start, end) {
698 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
699 var len = %_TypedArrayGetLength(this);
700
701 var relativeStart = TO_INTEGER(start);
702
703 var k;
704 if (relativeStart < 0) {
705 k = MaxSimple(len + relativeStart, 0);
706 } else {
707 k = MinSimple(relativeStart, len);
708 }
709
710 var relativeEnd;
711 if (IS_UNDEFINED(end)) {
712 relativeEnd = len;
713 } else {
714 relativeEnd = TO_INTEGER(end);
715 }
716
717 var final;
718 if (relativeEnd < 0) {
719 final = MaxSimple(len + relativeEnd, 0);
720 } else {
721 final = MinSimple(relativeEnd, len);
722 }
723
724 var count = MaxSimple(final - k, 0);
725 var array = TypedArraySpeciesCreate(this, count);
726 // The code below is the 'then' branch; the 'else' branch species
727 // a memcpy. Because V8 doesn't canonicalize NaN, the difference is
728 // unobservable.
729 var n = 0;
730 while (k < final) {
731 var kValue = this[k];
732 array[n] = kValue;
733 k++;
734 n++;
735 }
736 return array;
737}
738
739
740// ES2016 draft, section 22.2.3.14
741function TypedArrayIncludes(searchElement, fromIndex) {
742 if (!%_IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
743
744 var length = %_TypedArrayGetLength(this);
745
746 return InnerArrayIncludes(searchElement, fromIndex, this, length);
747}
748%FunctionSetLength(TypedArrayIncludes, 1);
749
750
751// ES6 draft 08-24-14, section 22.2.2.2
752function TypedArrayOf() {
753 var length = %_ArgumentsLength();
754 var array = TypedArrayCreate(this, length);
755 for (var i = 0; i < length; i++) {
756 array[i] = %_Arguments(i);
757 }
758 return array;
759}
760
761
762function TypedArrayFrom(source, mapfn, thisArg) {
763 // TODO(littledan): Investigate if there is a receiver which could be
764 // faster to accumulate on than Array, e.g., a TypedVector.
765 // TODO(littledan): Rewrite this code to ensure that things happen
766 // in the right order, e.g., the constructor needs to be called before
767 // the mapping function on array-likes.
768 var array = %_Call(ArrayFrom, GlobalArray, source, mapfn, thisArg);
769 return TypedArrayCreate(this, array);
770}
771%FunctionSetLength(TypedArrayFrom, 1);
772
773function TypedArray() {
774 if (IS_UNDEFINED(new.target)) {
775 throw MakeTypeError(kConstructorNonCallable, "TypedArray");
776 }
777 if (new.target === TypedArray) {
778 throw MakeTypeError(kConstructAbstractClass, "TypedArray");
779 }
780}
781
782// -------------------------------------------------------------------
783
784%FunctionSetPrototype(TypedArray, new GlobalObject());
785%AddNamedProperty(TypedArray.prototype,
786 "constructor", TypedArray, DONT_ENUM);
787utils.InstallFunctions(TypedArray, DONT_ENUM | DONT_DELETE | READ_ONLY, [
788 "from", TypedArrayFrom,
789 "of", TypedArrayOf
790]);
791utils.InstallGetter(TypedArray.prototype, "buffer", TypedArrayGetBuffer);
792utils.InstallGetter(TypedArray.prototype, "byteOffset", TypedArrayGetByteOffset,
793 DONT_ENUM | DONT_DELETE);
794utils.InstallGetter(TypedArray.prototype, "byteLength",
795 TypedArrayGetByteLength, DONT_ENUM | DONT_DELETE);
796utils.InstallGetter(TypedArray.prototype, "length", TypedArrayGetLength,
797 DONT_ENUM | DONT_DELETE);
798utils.InstallGetter(TypedArray.prototype, toStringTagSymbol,
799 TypedArrayGetToStringTag);
800utils.InstallFunctions(TypedArray.prototype, DONT_ENUM, [
801 "subarray", TypedArraySubArray,
802 "set", TypedArraySet,
803 "copyWithin", TypedArrayCopyWithin,
804 "every", TypedArrayEvery,
805 "fill", TypedArrayFill,
806 "filter", TypedArrayFilter,
807 "find", TypedArrayFind,
808 "findIndex", TypedArrayFindIndex,
809 "includes", TypedArrayIncludes,
810 "indexOf", TypedArrayIndexOf,
811 "join", TypedArrayJoin,
812 "lastIndexOf", TypedArrayLastIndexOf,
813 "forEach", TypedArrayForEach,
814 "map", TypedArrayMap,
815 "reduce", TypedArrayReduce,
816 "reduceRight", TypedArrayReduceRight,
817 "reverse", TypedArrayReverse,
818 "slice", TypedArraySlice,
819 "some", TypedArraySome,
820 "sort", TypedArraySort,
821 "toString", TypedArrayToString,
822 "toLocaleString", TypedArrayToLocaleString
823]);
824
825
826macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE)
827 %SetCode(GlobalNAME, NAMEConstructor);
828 %FunctionSetPrototype(GlobalNAME, new GlobalObject());
829 %InternalSetPrototype(GlobalNAME, TypedArray);
830 %InternalSetPrototype(GlobalNAME.prototype, TypedArray.prototype);
831
832 %AddNamedProperty(GlobalNAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE,
833 READ_ONLY | DONT_ENUM | DONT_DELETE);
834
835 %AddNamedProperty(GlobalNAME.prototype,
836 "constructor", global.NAME, DONT_ENUM);
837 %AddNamedProperty(GlobalNAME.prototype,
838 "BYTES_PER_ELEMENT", ELEMENT_SIZE,
839 READ_ONLY | DONT_ENUM | DONT_DELETE);
840 // TODO(littledan): Remove this performance workaround BUG(chromium:579905)
841 utils.InstallGetter(GlobalNAME.prototype, "length", NAME_GetLength,
842 DONT_ENUM | DONT_DELETE);
843endmacro
844
845TYPED_ARRAYS(SETUP_TYPED_ARRAY)
846
847// --------------------------- DataView -----------------------------
848
849function DataViewConstructor(buffer, byteOffset, byteLength) { // length = 3
850 if (IS_UNDEFINED(new.target)) {
851 throw MakeTypeError(kConstructorNotFunction, "DataView");
852 }
853
854 // TODO(binji): support SharedArrayBuffers?
855 if (!IS_ARRAYBUFFER(buffer)) throw MakeTypeError(kDataViewNotArrayBuffer);
856 if (!IS_UNDEFINED(byteOffset)) {
857 byteOffset = ToPositiveInteger(byteOffset, kInvalidDataViewOffset);
858 }
859 if (!IS_UNDEFINED(byteLength)) {
860 byteLength = TO_INTEGER(byteLength);
861 }
862
863 var bufferByteLength = %_ArrayBufferGetByteLength(buffer);
864
865 var offset = IS_UNDEFINED(byteOffset) ? 0 : byteOffset;
866 if (offset > bufferByteLength) throw MakeRangeError(kInvalidDataViewOffset);
867
868 var length = IS_UNDEFINED(byteLength)
869 ? bufferByteLength - offset
870 : byteLength;
871 if (length < 0 || offset + length > bufferByteLength) {
872 throw new MakeRangeError(kInvalidDataViewLength);
873 }
874 var result = %NewObject(GlobalDataView, new.target);
875 %_DataViewInitialize(result, buffer, offset, length);
876 return result;
877}
878
879function DataViewGetBufferJS() {
880 if (!IS_DATAVIEW(this)) {
881 throw MakeTypeError(kIncompatibleMethodReceiver, 'DataView.buffer', this);
882 }
883 return %DataViewGetBuffer(this);
884}
885
886function DataViewGetByteOffset() {
887 if (!IS_DATAVIEW(this)) {
888 throw MakeTypeError(kIncompatibleMethodReceiver,
889 'DataView.byteOffset', this);
890 }
891 return %_ArrayBufferViewGetByteOffset(this);
892}
893
894function DataViewGetByteLength() {
895 if (!IS_DATAVIEW(this)) {
896 throw MakeTypeError(kIncompatibleMethodReceiver,
897 'DataView.byteLength', this);
898 }
899 return %_ArrayBufferViewGetByteLength(this);
900}
901
902macro DATA_VIEW_TYPES(FUNCTION)
903 FUNCTION(Int8)
904 FUNCTION(Uint8)
905 FUNCTION(Int16)
906 FUNCTION(Uint16)
907 FUNCTION(Int32)
908 FUNCTION(Uint32)
909 FUNCTION(Float32)
910 FUNCTION(Float64)
911endmacro
912
913
914macro DATA_VIEW_GETTER_SETTER(TYPENAME)
915function DataViewGetTYPENAMEJS(offset, little_endian) {
916 if (!IS_DATAVIEW(this)) {
917 throw MakeTypeError(kIncompatibleMethodReceiver,
918 'DataView.getTYPENAME', this);
919 }
920 if (%_ArgumentsLength() < 1) throw MakeTypeError(kInvalidArgument);
921 offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
922 return %DataViewGetTYPENAME(this, offset, !!little_endian);
923}
924
925function DataViewSetTYPENAMEJS(offset, value, little_endian) {
926 if (!IS_DATAVIEW(this)) {
927 throw MakeTypeError(kIncompatibleMethodReceiver,
928 'DataView.setTYPENAME', this);
929 }
930 if (%_ArgumentsLength() < 2) throw MakeTypeError(kInvalidArgument);
931 offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
932 %DataViewSetTYPENAME(this, offset, TO_NUMBER(value), !!little_endian);
933}
934endmacro
935
936DATA_VIEW_TYPES(DATA_VIEW_GETTER_SETTER)
937
938// Setup the DataView constructor.
939%SetCode(GlobalDataView, DataViewConstructor);
940%FunctionSetPrototype(GlobalDataView, new GlobalObject);
941
942// Set up constructor property on the DataView prototype.
943%AddNamedProperty(GlobalDataView.prototype, "constructor", GlobalDataView,
944 DONT_ENUM);
945%AddNamedProperty(GlobalDataView.prototype, toStringTagSymbol, "DataView",
946 READ_ONLY|DONT_ENUM);
947
948utils.InstallGetter(GlobalDataView.prototype, "buffer", DataViewGetBufferJS);
949utils.InstallGetter(GlobalDataView.prototype, "byteOffset",
950 DataViewGetByteOffset);
951utils.InstallGetter(GlobalDataView.prototype, "byteLength",
952 DataViewGetByteLength);
953
954utils.InstallFunctions(GlobalDataView.prototype, DONT_ENUM, [
955 "getInt8", DataViewGetInt8JS,
956 "setInt8", DataViewSetInt8JS,
957
958 "getUint8", DataViewGetUint8JS,
959 "setUint8", DataViewSetUint8JS,
960
961 "getInt16", DataViewGetInt16JS,
962 "setInt16", DataViewSetInt16JS,
963
964 "getUint16", DataViewGetUint16JS,
965 "setUint16", DataViewSetUint16JS,
966
967 "getInt32", DataViewGetInt32JS,
968 "setInt32", DataViewSetInt32JS,
969
970 "getUint32", DataViewGetUint32JS,
971 "setUint32", DataViewSetUint32JS,
972
973 "getFloat32", DataViewGetFloat32JS,
974 "setFloat32", DataViewSetFloat32JS,
975
976 "getFloat64", DataViewGetFloat64JS,
977 "setFloat64", DataViewSetFloat64JS
978]);
979
980})