• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5(function(global, utils) {
6
7"use strict";
8
9%CheckIsBootstrapping();
10
11// -------------------------------------------------------------------
12// Imports
13
14// array.js has to come before typedarray.js for this to work
15var ArrayToString = utils.ImportNow("ArrayToString");
16var ArrayValues;
17var GetIterator;
18var GetMethod;
19var GlobalArray = global.Array;
20var GlobalArrayBuffer = global.ArrayBuffer;
21var GlobalArrayBufferPrototype = GlobalArrayBuffer.prototype;
22var GlobalDataView = global.DataView;
23var GlobalObject = global.Object;
24var 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");
50var speciesSymbol = utils.ImportNow("species_symbol");
51var 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
72var GlobalTypedArray = %object_get_prototype_of(GlobalUint8Array);
73
74utils.Import(function(from) {
75  ArrayValues = from.ArrayValues;
76  GetIterator = from.GetIterator;
77  GetMethod = from.GetMethod;
78  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  }
126  if (!IS_TYPEDARRAY(newTypedArray)) throw MakeTypeError(kNotTypedArray);
127  // 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
203function NAMEConstructByArrayLike(obj, arrayLike, length) {
204  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  }
243  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  }
260}
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);
269    } else if (IS_TYPEDARRAY(arg1)) {
270      NAMEConstructByTypedArray(this, arg1);
271    } else {
272      var iteratorFn = arg1[iteratorSymbol];
273      if (IS_UNDEFINED(iteratorFn) || iteratorFn === ArrayValues) {
274        NAMEConstructByArrayLike(this, arg1, arg1.length);
275      } else {
276        NAMEConstructByIterable(this, arg1, iteratorFn);
277      }
278    }
279  } else {
280    throw MakeTypeError(kConstructorNotFunction, "NAME")
281  }
282}
283
284function 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;
313  // 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);
317}
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
335
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;
353  var sourceLength = %_TypedArrayGetLength(source);
354
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
373  // Copy right part;
374  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
417      TypedArraySetFromArrayLike(this,
418          obj, %_TypedArrayGetLength(obj), intOffset);
419      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);
433      if (intOffset + l > %_TypedArrayGetLength(this)) {
434        throw MakeRangeError(kTypedArraySetSourceTooLarge);
435      }
436      TypedArraySetFromArrayLike(this, obj, l, intOffset);
437      return;
438  }
439}
440%FunctionSetLength(TypedArraySet, 1);
441
442function TypedArrayGetToStringTag() {
443  if (!IS_TYPEDARRAY(this)) return;
444  var name = %_ClassOf(this);
445  if (IS_UNDEFINED(name)) return;
446  return name;
447}
448
449
450function TypedArrayCopyWithin(target, start, end) {
451  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
452
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) {
463  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
464
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) {
474  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
475
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) {
485  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
486
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) {
496  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
497
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) {
514  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
515
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) {
525  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
526
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() {
536  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
537
538  var length = %_TypedArrayGetLength(this);
539
540  return PackedArrayReverse(this, length);
541}
542
543
544function TypedArrayComparefn(x, y) {
545  if (x === 0 && x === y) {
546    x = 1 / x;
547    y = 1 / y;
548  }
549  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)) {
556    return 1;
557  }
558  return 0;
559}
560
561
562// ES6 draft 05-18-15, section 22.2.3.25
563function TypedArraySort(comparefn) {
564  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
565
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) {
578  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
579
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) {
588  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
589
590  var length = %_TypedArrayGetLength(this);
591
592  return InnerArrayLastIndexOf(this, element, index, length,
593                               arguments.length);
594}
595%FunctionSetLength(TypedArrayLastIndexOf, 1);
596
597
598// ES6 draft 07-15-13, section 22.2.3.18
599function TypedArrayMap(f, thisArg) {
600  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
601
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) {
616  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
617
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() {
627  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
628
629  var length = %_TypedArrayGetLength(this);
630
631  return InnerArrayToLocaleString(this, length);
632}
633
634
635// ES6 section 22.2.3.14
636function TypedArrayJoin(separator) {
637  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
638
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) {
647  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
648
649  var length = %_TypedArrayGetLength(this);
650  return InnerArrayReduce(callback, current, this, length,
651                          arguments.length);
652}
653%FunctionSetLength(TypedArrayReduce, 1);
654
655
656// ES6 draft 07-15-13, section 22.2.3.19
657function TypedArrayReduceRight(callback, current) {
658  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
659
660  var length = %_TypedArrayGetLength(this);
661  return InnerArrayReduceRight(callback, current, this, length,
662                               arguments.length);
663}
664%FunctionSetLength(TypedArrayReduceRight, 1);
665
666
667function TypedArraySlice(start, end) {
668  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
669  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) {
712  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
713
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() {
723  var length = arguments.length;
724  var array = TypedArrayCreate(this, length);
725  for (var i = 0; i < length; i++) {
726    array[i] = arguments[i];
727  }
728  return array;
729}
730
731
732// 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 ] ] )
753function TypedArrayFrom(source, mapfn, thisArg) {
754  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;
776}
777%FunctionSetLength(TypedArrayFrom, 1);
778
779// TODO(bmeurer): Migrate this to a proper builtin.
780function TypedArrayConstructor() {
781  if (IS_UNDEFINED(new.target)) {
782    throw MakeTypeError(kConstructorNonCallable, "TypedArray");
783  }
784  if (new.target === GlobalTypedArray) {
785    throw MakeTypeError(kConstructAbstractClass, "TypedArray");
786  }
787}
788
789function TypedArraySpecies() {
790  return this;
791}
792
793// -------------------------------------------------------------------
794
795%SetCode(GlobalTypedArray, TypedArrayConstructor);
796utils.InstallFunctions(GlobalTypedArray, DONT_ENUM, [
797  "from", TypedArrayFrom,
798  "of", TypedArrayOf
799]);
800utils.InstallGetter(GlobalTypedArray, speciesSymbol, TypedArraySpecies);
801utils.InstallGetter(GlobalTypedArray.prototype, toStringTagSymbol,
802                    TypedArrayGetToStringTag);
803utils.InstallFunctions(GlobalTypedArray.prototype, DONT_ENUM, [
804  "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,
824  "toLocaleString", TypedArrayToLocaleString
825]);
826
827%AddNamedProperty(GlobalTypedArray.prototype, "toString", ArrayToString,
828                  DONT_ENUM);
829
830
831macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE)
832  %SetCode(GlobalNAME, NAMEConstructor);
833  %FunctionSetPrototype(GlobalNAME, new GlobalObject());
834  %InternalSetPrototype(GlobalNAME, GlobalTypedArray);
835  %InternalSetPrototype(GlobalNAME.prototype, GlobalTypedArray.prototype);
836
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);
845endmacro
846
847TYPED_ARRAYS(SETUP_TYPED_ARRAY)
848
849// --------------------------- DataView -----------------------------
850
851macro 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  }
869  if (arguments.length < 1) throw MakeTypeError(kInvalidArgument);
870  offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
871  return %DataViewGetTYPENAME(this, offset, !!little_endian);
872}
873%FunctionSetLength(DataViewGetTYPENAMEJS, 1);
874
875function DataViewSetTYPENAMEJS(offset, value, little_endian) {
876  if (!IS_DATAVIEW(this)) {
877    throw MakeTypeError(kIncompatibleMethodReceiver,
878                        'DataView.setTYPENAME', this);
879  }
880  if (arguments.length < 2) throw MakeTypeError(kInvalidArgument);
881  offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
882  %DataViewSetTYPENAME(this, offset, TO_NUMBER(value), !!little_endian);
883}
884%FunctionSetLength(DataViewSetTYPENAMEJS, 2);
885endmacro
886
887DATA_VIEW_TYPES(DATA_VIEW_GETTER_SETTER)
888
889utils.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})
916