blob: 18f6dde29975de4ba34b824b5c9f57fa84061efe [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5(function(global, utils) {
6
7"use strict";
8
9%CheckIsBootstrapping();
10
11// -------------------------------------------------------------------
12// Imports
13
Ben Murdochda12d292016-06-02 14:46:10 +010014// array.js has to come before typedarray.js for this to work
15var ArrayToString = utils.ImportNow("ArrayToString");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016var ArrayValues;
Ben Murdochda12d292016-06-02 14:46:10 +010017var GetIterator;
18var GetMethod;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019var GlobalArray = global.Array;
20var GlobalArrayBuffer = global.ArrayBuffer;
Ben Murdochda12d292016-06-02 14:46:10 +010021var GlobalArrayBufferPrototype = GlobalArrayBuffer.prototype;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022var GlobalDataView = global.DataView;
23var GlobalObject = global.Object;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024var InnerArrayCopyWithin;
25var InnerArrayEvery;
26var InnerArrayFill;
27var InnerArrayFilter;
28var InnerArrayFind;
29var InnerArrayFindIndex;
30var InnerArrayForEach;
31var InnerArrayIncludes;
32var InnerArrayIndexOf;
33var InnerArrayJoin;
34var InnerArrayLastIndexOf;
35var InnerArrayReduce;
36var InnerArrayReduceRight;
37var InnerArraySome;
38var InnerArraySort;
39var InnerArrayToLocaleString;
40var InternalArray = utils.InternalArray;
41var IsNaN;
42var MakeRangeError;
43var MakeTypeError;
44var MaxSimple;
45var MinSimple;
46var PackedArrayReverse;
47var SpeciesConstructor;
48var ToPositiveInteger;
49var iteratorSymbol = utils.ImportNow("iterator_symbol");
50var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
51
52macro TYPED_ARRAYS(FUNCTION)
53// arrayIds below should be synchronized with Runtime_TypedArrayInitialize.
54FUNCTION(1, Uint8Array, 1)
55FUNCTION(2, Int8Array, 1)
56FUNCTION(3, Uint16Array, 2)
57FUNCTION(4, Int16Array, 2)
58FUNCTION(5, Uint32Array, 4)
59FUNCTION(6, Int32Array, 4)
60FUNCTION(7, Float32Array, 4)
61FUNCTION(8, Float64Array, 8)
62FUNCTION(9, Uint8ClampedArray, 1)
63endmacro
64
65macro DECLARE_GLOBALS(INDEX, NAME, SIZE)
66var GlobalNAME = global.NAME;
67endmacro
68
69TYPED_ARRAYS(DECLARE_GLOBALS)
70
71utils.Import(function(from) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 ArrayValues = from.ArrayValues;
Ben Murdochda12d292016-06-02 14:46:10 +010073 GetIterator = from.GetIterator;
74 GetMethod = from.GetMethod;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 InnerArrayCopyWithin = from.InnerArrayCopyWithin;
76 InnerArrayEvery = from.InnerArrayEvery;
77 InnerArrayFill = from.InnerArrayFill;
78 InnerArrayFilter = from.InnerArrayFilter;
79 InnerArrayFind = from.InnerArrayFind;
80 InnerArrayFindIndex = from.InnerArrayFindIndex;
81 InnerArrayForEach = from.InnerArrayForEach;
82 InnerArrayIncludes = from.InnerArrayIncludes;
83 InnerArrayIndexOf = from.InnerArrayIndexOf;
84 InnerArrayJoin = from.InnerArrayJoin;
85 InnerArrayLastIndexOf = from.InnerArrayLastIndexOf;
86 InnerArrayReduce = from.InnerArrayReduce;
87 InnerArrayReduceRight = from.InnerArrayReduceRight;
88 InnerArraySome = from.InnerArraySome;
89 InnerArraySort = from.InnerArraySort;
90 InnerArrayToLocaleString = from.InnerArrayToLocaleString;
91 IsNaN = from.IsNaN;
92 MakeRangeError = from.MakeRangeError;
93 MakeTypeError = from.MakeTypeError;
94 MaxSimple = from.MaxSimple;
95 MinSimple = from.MinSimple;
96 PackedArrayReverse = from.PackedArrayReverse;
97 SpeciesConstructor = from.SpeciesConstructor;
98 ToPositiveInteger = from.ToPositiveInteger;
99});
100
101// --------------- Typed Arrays ---------------------
102
103function TypedArrayDefaultConstructor(typedArray) {
104 switch (%_ClassOf(typedArray)) {
105macro TYPED_ARRAY_CONSTRUCTOR_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
106 case "NAME":
107 return GlobalNAME;
108endmacro
109TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR_CASE)
110 }
111 // The TypeError should not be generated since all callers should
112 // have already called ValidateTypedArray.
113 throw MakeTypeError(kIncompatibleMethodReceiver,
114 "TypedArrayDefaultConstructor", this);
115}
116
117function TypedArrayCreate(constructor, arg0, arg1, arg2) {
118 if (IS_UNDEFINED(arg1)) {
119 var newTypedArray = new constructor(arg0);
120 } else {
121 var newTypedArray = new constructor(arg0, arg1, arg2);
122 }
Ben Murdochda12d292016-06-02 14:46:10 +0100123 if (!IS_TYPEDARRAY(newTypedArray)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 // TODO(littledan): Check for being detached, here and elsewhere
125 // All callers where the first argument is a Number have no additional
126 // arguments.
127 if (IS_NUMBER(arg0) && %_TypedArrayGetLength(newTypedArray) < arg0) {
128 throw MakeTypeError(kTypedArrayTooShort);
129 }
130 return newTypedArray;
131}
132
133function TypedArraySpeciesCreate(exemplar, arg0, arg1, arg2, conservative) {
134 var defaultConstructor = TypedArrayDefaultConstructor(exemplar);
135 var constructor = SpeciesConstructor(exemplar, defaultConstructor,
136 conservative);
137 return TypedArrayCreate(constructor, arg0, arg1, arg2);
138}
139
140macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE)
141function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
142 if (!IS_UNDEFINED(byteOffset)) {
143 byteOffset = ToPositiveInteger(byteOffset, kInvalidTypedArrayLength);
144 }
145 if (!IS_UNDEFINED(length)) {
146 length = ToPositiveInteger(length, kInvalidTypedArrayLength);
147 }
148
149 var bufferByteLength = %_ArrayBufferGetByteLength(buffer);
150 var offset;
151 if (IS_UNDEFINED(byteOffset)) {
152 offset = 0;
153 } else {
154 offset = byteOffset;
155
156 if (offset % ELEMENT_SIZE !== 0) {
157 throw MakeRangeError(kInvalidTypedArrayAlignment,
158 "start offset", "NAME", ELEMENT_SIZE);
159 }
160 if (offset > bufferByteLength) {
161 throw MakeRangeError(kInvalidTypedArrayOffset);
162 }
163 }
164
165 var newByteLength;
166 var newLength;
167 if (IS_UNDEFINED(length)) {
168 if (bufferByteLength % ELEMENT_SIZE !== 0) {
169 throw MakeRangeError(kInvalidTypedArrayAlignment,
170 "byte length", "NAME", ELEMENT_SIZE);
171 }
172 newByteLength = bufferByteLength - offset;
173 newLength = newByteLength / ELEMENT_SIZE;
174 } else {
175 var newLength = length;
176 newByteLength = newLength * ELEMENT_SIZE;
177 }
178 if ((offset + newByteLength > bufferByteLength)
179 || (newLength > %_MaxSmi())) {
180 throw MakeRangeError(kInvalidTypedArrayLength);
181 }
182 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength, true);
183}
184
185function NAMEConstructByLength(obj, length) {
186 var l = IS_UNDEFINED(length) ?
187 0 : ToPositiveInteger(length, kInvalidTypedArrayLength);
188 if (l > %_MaxSmi()) {
189 throw MakeRangeError(kInvalidTypedArrayLength);
190 }
191 var byteLength = l * ELEMENT_SIZE;
192 if (byteLength > %_TypedArrayMaxSizeInHeap()) {
193 var buffer = new GlobalArrayBuffer(byteLength);
194 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, 0, byteLength, true);
195 } else {
196 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, true);
197 }
198}
199
Ben Murdochda12d292016-06-02 14:46:10 +0100200function NAMEConstructByArrayLike(obj, arrayLike, length) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 var l = ToPositiveInteger(length, kInvalidTypedArrayLength);
202
203 if (l > %_MaxSmi()) {
204 throw MakeRangeError(kInvalidTypedArrayLength);
205 }
206 var initialized = false;
207 var byteLength = l * ELEMENT_SIZE;
208 if (byteLength <= %_TypedArrayMaxSizeInHeap()) {
209 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, false);
210 } else {
211 initialized =
212 %TypedArrayInitializeFromArrayLike(obj, ARRAY_ID, arrayLike, l);
213 }
214 if (!initialized) {
215 for (var i = 0; i < l; i++) {
216 // It is crucial that we let any execptions from arrayLike[i]
217 // propagate outside the function.
218 obj[i] = arrayLike[i];
219 }
220 }
221}
222
223function NAMEConstructByIterable(obj, iterable, iteratorFn) {
224 var list = new InternalArray();
225 // Reading the Symbol.iterator property of iterable twice would be
226 // observable with getters, so instead, we call the function which
227 // was already looked up, and wrap it in another iterable. The
228 // __proto__ of the new iterable is set to null to avoid any chance
229 // of modifications to Object.prototype being observable here.
230 var iterator = %_Call(iteratorFn, iterable);
231 var newIterable = {
232 __proto__: null
233 };
234 // TODO(littledan): Computed properties don't work yet in nosnap.
235 // Rephrase when they do.
236 newIterable[iteratorSymbol] = function() { return iterator; }
237 for (var value of newIterable) {
238 list.push(value);
239 }
Ben Murdochda12d292016-06-02 14:46:10 +0100240 NAMEConstructByArrayLike(obj, list, list.length);
241}
242
243// ES#sec-typedarray-typedarray TypedArray ( typedArray )
244function NAMEConstructByTypedArray(obj, typedArray) {
245 // TODO(littledan): Throw on detached typedArray
246 var srcData = %TypedArrayGetBuffer(typedArray);
247 var length = %_TypedArrayGetLength(typedArray);
248 var byteLength = %_ArrayBufferViewGetByteLength(typedArray);
249 var newByteLength = length * ELEMENT_SIZE;
250 NAMEConstructByArrayLike(obj, typedArray, length);
251 var bufferConstructor = SpeciesConstructor(srcData, GlobalArrayBuffer);
252 var prototype = bufferConstructor.prototype;
253 // TODO(littledan): Use the right prototype based on bufferConstructor's realm
254 if (IS_RECEIVER(prototype) && prototype !== GlobalArrayBufferPrototype) {
255 %InternalSetPrototype(%TypedArrayGetBuffer(obj), prototype);
256 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000257}
258
259function NAMEConstructor(arg1, arg2, arg3) {
260 if (!IS_UNDEFINED(new.target)) {
261 if (IS_ARRAYBUFFER(arg1) || IS_SHAREDARRAYBUFFER(arg1)) {
262 NAMEConstructByArrayBuffer(this, arg1, arg2, arg3);
263 } else if (IS_NUMBER(arg1) || IS_STRING(arg1) ||
264 IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) {
265 NAMEConstructByLength(this, arg1);
Ben Murdochda12d292016-06-02 14:46:10 +0100266 } else if (IS_TYPEDARRAY(arg1)) {
267 NAMEConstructByTypedArray(this, arg1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000269 var iteratorFn = arg1[iteratorSymbol];
270 if (IS_UNDEFINED(iteratorFn) || iteratorFn === ArrayValues) {
Ben Murdochda12d292016-06-02 14:46:10 +0100271 NAMEConstructByArrayLike(this, arg1, arg1.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 } else {
273 NAMEConstructByIterable(this, arg1, iteratorFn);
274 }
275 }
276 } else {
277 throw MakeTypeError(kConstructorNotFunction, "NAME")
278 }
279}
280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281function NAMESubArray(begin, end) {
282 var beginInt = TO_INTEGER(begin);
283 if (!IS_UNDEFINED(end)) {
284 var endInt = TO_INTEGER(end);
285 var srcLength = %_TypedArrayGetLength(this);
286 } else {
287 var srcLength = %_TypedArrayGetLength(this);
288 var endInt = srcLength;
289 }
290
291 if (beginInt < 0) {
292 beginInt = MaxSimple(0, srcLength + beginInt);
293 } else {
294 beginInt = MinSimple(beginInt, srcLength);
295 }
296
297 if (endInt < 0) {
298 endInt = MaxSimple(0, srcLength + endInt);
299 } else {
300 endInt = MinSimple(endInt, srcLength);
301 }
302
303 if (endInt < beginInt) {
304 endInt = beginInt;
305 }
306
307 var newLength = endInt - beginInt;
308 var beginByteOffset =
309 %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100310 // BUG(v8:4665): For web compatibility, subarray needs to always build an
311 // instance of the default constructor.
312 // TODO(littledan): Switch to the standard or standardize the fix
313 return new GlobalNAME(%TypedArrayGetBuffer(this), beginByteOffset, newLength);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000314}
315endmacro
316
317TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR)
318
319function TypedArraySubArray(begin, end) {
320 switch (%_ClassOf(this)) {
321macro TYPED_ARRAY_SUBARRAY_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
322 case "NAME":
323 return %_Call(NAMESubArray, this, begin, end);
324endmacro
325TYPED_ARRAYS(TYPED_ARRAY_SUBARRAY_CASE)
326 }
327 throw MakeTypeError(kIncompatibleMethodReceiver,
328 "get TypedArray.prototype.subarray", this);
329}
330%SetForceInlineFlag(TypedArraySubArray);
331
332function TypedArrayGetBuffer() {
Ben Murdochda12d292016-06-02 14:46:10 +0100333 if (!IS_TYPEDARRAY(this)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334 throw MakeTypeError(kIncompatibleMethodReceiver,
335 "get TypedArray.prototype.buffer", this);
336 }
337 return %TypedArrayGetBuffer(this);
338}
339%SetForceInlineFlag(TypedArrayGetBuffer);
340
341function TypedArrayGetByteLength() {
Ben Murdochda12d292016-06-02 14:46:10 +0100342 if (!IS_TYPEDARRAY(this)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343 throw MakeTypeError(kIncompatibleMethodReceiver,
344 "get TypedArray.prototype.byteLength", this);
345 }
346 return %_ArrayBufferViewGetByteLength(this);
347}
348%SetForceInlineFlag(TypedArrayGetByteLength);
349
350function TypedArrayGetByteOffset() {
Ben Murdochda12d292016-06-02 14:46:10 +0100351 if (!IS_TYPEDARRAY(this)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000352 throw MakeTypeError(kIncompatibleMethodReceiver,
353 "get TypedArray.prototype.byteOffset", this);
354 }
355 return %_ArrayBufferViewGetByteOffset(this);
356}
357%SetForceInlineFlag(TypedArrayGetByteOffset);
358
359function TypedArrayGetLength() {
Ben Murdochda12d292016-06-02 14:46:10 +0100360 if (!IS_TYPEDARRAY(this)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000361 throw MakeTypeError(kIncompatibleMethodReceiver,
362 "get TypedArray.prototype.length", this);
363 }
364 return %_TypedArrayGetLength(this);
365}
366%SetForceInlineFlag(TypedArrayGetLength);
367
368
369
370function TypedArraySetFromArrayLike(target, source, sourceLength, offset) {
371 if (offset > 0) {
372 for (var i = 0; i < sourceLength; i++) {
373 target[offset + i] = source[i];
374 }
375 }
376 else {
377 for (var i = 0; i < sourceLength; i++) {
378 target[i] = source[i];
379 }
380 }
381}
382
383function TypedArraySetFromOverlappingTypedArray(target, source, offset) {
384 var sourceElementSize = source.BYTES_PER_ELEMENT;
385 var targetElementSize = target.BYTES_PER_ELEMENT;
386 var sourceLength = source.length;
387
388 // Copy left part.
389 function CopyLeftPart() {
390 // First un-mutated byte after the next write
391 var targetPtr = target.byteOffset + (offset + 1) * targetElementSize;
392 // Next read at sourcePtr. We do not care for memory changing before
393 // sourcePtr - we have already copied it.
394 var sourcePtr = source.byteOffset;
395 for (var leftIndex = 0;
396 leftIndex < sourceLength && targetPtr <= sourcePtr;
397 leftIndex++) {
398 target[offset + leftIndex] = source[leftIndex];
399 targetPtr += targetElementSize;
400 sourcePtr += sourceElementSize;
401 }
402 return leftIndex;
403 }
404 var leftIndex = CopyLeftPart();
405
406 // Copy rigth part;
407 function CopyRightPart() {
408 // First unmutated byte before the next write
409 var targetPtr =
410 target.byteOffset + (offset + sourceLength - 1) * targetElementSize;
411 // Next read before sourcePtr. We do not care for memory changing after
412 // sourcePtr - we have already copied it.
413 var sourcePtr =
414 source.byteOffset + sourceLength * sourceElementSize;
415 for(var rightIndex = sourceLength - 1;
416 rightIndex >= leftIndex && targetPtr >= sourcePtr;
417 rightIndex--) {
418 target[offset + rightIndex] = source[rightIndex];
419 targetPtr -= targetElementSize;
420 sourcePtr -= sourceElementSize;
421 }
422 return rightIndex;
423 }
424 var rightIndex = CopyRightPart();
425
426 var temp = new GlobalArray(rightIndex + 1 - leftIndex);
427 for (var i = leftIndex; i <= rightIndex; i++) {
428 temp[i - leftIndex] = source[i];
429 }
430 for (i = leftIndex; i <= rightIndex; i++) {
431 target[offset + i] = temp[i - leftIndex];
432 }
433}
434
435function TypedArraySet(obj, offset) {
436 var intOffset = IS_UNDEFINED(offset) ? 0 : TO_INTEGER(offset);
437 if (intOffset < 0) throw MakeTypeError(kTypedArraySetNegativeOffset);
438
439 if (intOffset > %_MaxSmi()) {
440 throw MakeRangeError(kTypedArraySetSourceTooLarge);
441 }
442 switch (%TypedArraySetFastCases(this, obj, intOffset)) {
443 // These numbers should be synchronized with runtime.cc.
444 case 0: // TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE
445 return;
446 case 1: // TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING
447 TypedArraySetFromOverlappingTypedArray(this, obj, intOffset);
448 return;
449 case 2: // TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING
450 TypedArraySetFromArrayLike(this, obj, obj.length, intOffset);
451 return;
452 case 3: // TYPED_ARRAY_SET_NON_TYPED_ARRAY
453 var l = obj.length;
454 if (IS_UNDEFINED(l)) {
455 if (IS_NUMBER(obj)) {
456 // For number as a first argument, throw TypeError
457 // instead of silently ignoring the call, so that
458 // the user knows (s)he did something wrong.
459 // (Consistent with Firefox and Blink/WebKit)
460 throw MakeTypeError(kInvalidArgument);
461 }
462 return;
463 }
464 l = TO_LENGTH(l);
465 if (intOffset + l > this.length) {
466 throw MakeRangeError(kTypedArraySetSourceTooLarge);
467 }
468 TypedArraySetFromArrayLike(this, obj, l, intOffset);
469 return;
470 }
471}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100472%FunctionSetLength(TypedArraySet, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000473
474function TypedArrayGetToStringTag() {
Ben Murdochda12d292016-06-02 14:46:10 +0100475 if (!IS_TYPEDARRAY(this)) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000476 var name = %_ClassOf(this);
477 if (IS_UNDEFINED(name)) return;
478 return name;
479}
480
481
482function TypedArrayCopyWithin(target, start, end) {
Ben Murdochda12d292016-06-02 14:46:10 +0100483 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484
485 var length = %_TypedArrayGetLength(this);
486
487 // TODO(littledan): Replace with a memcpy for better performance
488 return InnerArrayCopyWithin(target, start, end, this, length);
489}
490%FunctionSetLength(TypedArrayCopyWithin, 2);
491
492
493// ES6 draft 05-05-15, section 22.2.3.7
494function TypedArrayEvery(f, receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100495 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000496
497 var length = %_TypedArrayGetLength(this);
498
499 return InnerArrayEvery(f, receiver, this, length);
500}
501%FunctionSetLength(TypedArrayEvery, 1);
502
503
504// ES6 draft 08-24-14, section 22.2.3.12
505function TypedArrayForEach(f, receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100506 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000507
508 var length = %_TypedArrayGetLength(this);
509
510 InnerArrayForEach(f, receiver, this, length);
511}
512%FunctionSetLength(TypedArrayForEach, 1);
513
514
515// ES6 draft 04-05-14 section 22.2.3.8
516function TypedArrayFill(value, start, end) {
Ben Murdochda12d292016-06-02 14:46:10 +0100517 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000518
519 var length = %_TypedArrayGetLength(this);
520
521 return InnerArrayFill(value, start, end, this, length);
522}
523%FunctionSetLength(TypedArrayFill, 1);
524
525
526// ES6 draft 07-15-13, section 22.2.3.9
527function TypedArrayFilter(f, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100528 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529
530 var length = %_TypedArrayGetLength(this);
531 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
532 var result = new InternalArray();
533 InnerArrayFilter(f, thisArg, this, length, result);
534 var captured = result.length;
535 var output = TypedArraySpeciesCreate(this, captured);
536 for (var i = 0; i < captured; i++) {
537 output[i] = result[i];
538 }
539 return output;
540}
541%FunctionSetLength(TypedArrayFilter, 1);
542
543
544// ES6 draft 07-15-13, section 22.2.3.10
545function TypedArrayFind(predicate, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100546 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000547
548 var length = %_TypedArrayGetLength(this);
549
550 return InnerArrayFind(predicate, thisArg, this, length);
551}
552%FunctionSetLength(TypedArrayFind, 1);
553
554
555// ES6 draft 07-15-13, section 22.2.3.11
556function TypedArrayFindIndex(predicate, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100557 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558
559 var length = %_TypedArrayGetLength(this);
560
561 return InnerArrayFindIndex(predicate, thisArg, this, length);
562}
563%FunctionSetLength(TypedArrayFindIndex, 1);
564
565
566// ES6 draft 05-18-15, section 22.2.3.21
567function TypedArrayReverse() {
Ben Murdochda12d292016-06-02 14:46:10 +0100568 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569
570 var length = %_TypedArrayGetLength(this);
571
572 return PackedArrayReverse(this, length);
573}
574
575
576function TypedArrayComparefn(x, y) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100577 if (x === 0 && x === y) {
578 x = 1 / x;
579 y = 1 / y;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000580 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100581 if (x < y) {
582 return -1;
583 } else if (x > y) {
584 return 1;
585 } else if (IsNaN(x) && IsNaN(y)) {
586 return IsNaN(y) ? 0 : 1;
587 } else if (IsNaN(x)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588 return 1;
589 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100590 return 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000591}
592
593
594// ES6 draft 05-18-15, section 22.2.3.25
595function TypedArraySort(comparefn) {
Ben Murdochda12d292016-06-02 14:46:10 +0100596 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000597
598 var length = %_TypedArrayGetLength(this);
599
600 if (IS_UNDEFINED(comparefn)) {
601 comparefn = TypedArrayComparefn;
602 }
603
604 return InnerArraySort(this, length, comparefn);
605}
606
607
608// ES6 section 22.2.3.13
609function TypedArrayIndexOf(element, index) {
Ben Murdochda12d292016-06-02 14:46:10 +0100610 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000611
612 var length = %_TypedArrayGetLength(this);
613 return InnerArrayIndexOf(this, element, index, length);
614}
615%FunctionSetLength(TypedArrayIndexOf, 1);
616
617
618// ES6 section 22.2.3.16
619function TypedArrayLastIndexOf(element, index) {
Ben Murdochda12d292016-06-02 14:46:10 +0100620 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621
622 var length = %_TypedArrayGetLength(this);
623
624 return InnerArrayLastIndexOf(this, element, index, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100625 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000626}
627%FunctionSetLength(TypedArrayLastIndexOf, 1);
628
629
630// ES6 draft 07-15-13, section 22.2.3.18
631function TypedArrayMap(f, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100632 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633
634 var length = %_TypedArrayGetLength(this);
635 var result = TypedArraySpeciesCreate(this, length);
636 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
637 for (var i = 0; i < length; i++) {
638 var element = this[i];
639 result[i] = %_Call(f, thisArg, element, i, this);
640 }
641 return result;
642}
643%FunctionSetLength(TypedArrayMap, 1);
644
645
646// ES6 draft 05-05-15, section 22.2.3.24
647function TypedArraySome(f, receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100648 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000649
650 var length = %_TypedArrayGetLength(this);
651
652 return InnerArraySome(f, receiver, this, length);
653}
654%FunctionSetLength(TypedArraySome, 1);
655
656
657// ES6 section 22.2.3.27
658function TypedArrayToLocaleString() {
Ben Murdochda12d292016-06-02 14:46:10 +0100659 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000660
661 var length = %_TypedArrayGetLength(this);
662
663 return InnerArrayToLocaleString(this, length);
664}
665
666
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000667// ES6 section 22.2.3.14
668function TypedArrayJoin(separator) {
Ben Murdochda12d292016-06-02 14:46:10 +0100669 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670
671 var length = %_TypedArrayGetLength(this);
672
673 return InnerArrayJoin(separator, this, length);
674}
675
676
677// ES6 draft 07-15-13, section 22.2.3.19
678function TypedArrayReduce(callback, current) {
Ben Murdochda12d292016-06-02 14:46:10 +0100679 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000680
681 var length = %_TypedArrayGetLength(this);
682 return InnerArrayReduce(callback, current, this, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100683 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000684}
685%FunctionSetLength(TypedArrayReduce, 1);
686
687
688// ES6 draft 07-15-13, section 22.2.3.19
689function TypedArrayReduceRight(callback, current) {
Ben Murdochda12d292016-06-02 14:46:10 +0100690 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691
692 var length = %_TypedArrayGetLength(this);
693 return InnerArrayReduceRight(callback, current, this, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100694 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000695}
696%FunctionSetLength(TypedArrayReduceRight, 1);
697
698
699function TypedArraySlice(start, end) {
Ben Murdochda12d292016-06-02 14:46:10 +0100700 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000701 var len = %_TypedArrayGetLength(this);
702
703 var relativeStart = TO_INTEGER(start);
704
705 var k;
706 if (relativeStart < 0) {
707 k = MaxSimple(len + relativeStart, 0);
708 } else {
709 k = MinSimple(relativeStart, len);
710 }
711
712 var relativeEnd;
713 if (IS_UNDEFINED(end)) {
714 relativeEnd = len;
715 } else {
716 relativeEnd = TO_INTEGER(end);
717 }
718
719 var final;
720 if (relativeEnd < 0) {
721 final = MaxSimple(len + relativeEnd, 0);
722 } else {
723 final = MinSimple(relativeEnd, len);
724 }
725
726 var count = MaxSimple(final - k, 0);
727 var array = TypedArraySpeciesCreate(this, count);
728 // The code below is the 'then' branch; the 'else' branch species
729 // a memcpy. Because V8 doesn't canonicalize NaN, the difference is
730 // unobservable.
731 var n = 0;
732 while (k < final) {
733 var kValue = this[k];
734 array[n] = kValue;
735 k++;
736 n++;
737 }
738 return array;
739}
740
741
742// ES2016 draft, section 22.2.3.14
743function TypedArrayIncludes(searchElement, fromIndex) {
Ben Murdochda12d292016-06-02 14:46:10 +0100744 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000745
746 var length = %_TypedArrayGetLength(this);
747
748 return InnerArrayIncludes(searchElement, fromIndex, this, length);
749}
750%FunctionSetLength(TypedArrayIncludes, 1);
751
752
753// ES6 draft 08-24-14, section 22.2.2.2
754function TypedArrayOf() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100755 var length = arguments.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000756 var array = TypedArrayCreate(this, length);
757 for (var i = 0; i < length; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100758 array[i] = arguments[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759 }
760 return array;
761}
762
763
Ben Murdochda12d292016-06-02 14:46:10 +0100764// ES#sec-iterabletoarraylike Runtime Semantics: IterableToArrayLike( items )
765function IterableToArrayLike(items) {
766 var iterable = GetMethod(items, iteratorSymbol);
767 if (!IS_UNDEFINED(iterable)) {
768 var internal_array = new InternalArray();
769 var i = 0;
770 for (var value of
771 { [iteratorSymbol]() { return GetIterator(items, iterable) } }) {
772 internal_array[i] = value;
773 i++;
774 }
775 var array = [];
776 %MoveArrayContents(internal_array, array);
777 return array;
778 }
779 return TO_OBJECT(items);
780}
781
782
783// ES#sec-%typedarray%.from
784// %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] )
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000785function TypedArrayFrom(source, mapfn, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100786 if (!%IsConstructor(this)) throw MakeTypeError(kNotConstructor, this);
787 var mapping;
788 if (!IS_UNDEFINED(mapfn)) {
789 if (!IS_CALLABLE(mapfn)) throw MakeTypeError(kCalledNonCallable, this);
790 mapping = true;
791 } else {
792 mapping = false;
793 }
794 var arrayLike = IterableToArrayLike(source);
795 var length = TO_LENGTH(arrayLike.length);
796 var targetObject = TypedArrayCreate(this, length);
797 var value, mappedValue;
798 for (var i = 0; i < length; i++) {
799 value = arrayLike[i];
800 if (mapping) {
801 mappedValue = %_Call(mapfn, thisArg, value, i);
802 } else {
803 mappedValue = value;
804 }
805 targetObject[i] = mappedValue;
806 }
807 return targetObject;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000808}
809%FunctionSetLength(TypedArrayFrom, 1);
810
811function TypedArray() {
812 if (IS_UNDEFINED(new.target)) {
813 throw MakeTypeError(kConstructorNonCallable, "TypedArray");
814 }
815 if (new.target === TypedArray) {
816 throw MakeTypeError(kConstructAbstractClass, "TypedArray");
817 }
818}
819
820// -------------------------------------------------------------------
821
822%FunctionSetPrototype(TypedArray, new GlobalObject());
823%AddNamedProperty(TypedArray.prototype,
824 "constructor", TypedArray, DONT_ENUM);
Ben Murdochda12d292016-06-02 14:46:10 +0100825utils.InstallFunctions(TypedArray, DONT_ENUM, [
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000826 "from", TypedArrayFrom,
827 "of", TypedArrayOf
828]);
829utils.InstallGetter(TypedArray.prototype, "buffer", TypedArrayGetBuffer);
830utils.InstallGetter(TypedArray.prototype, "byteOffset", TypedArrayGetByteOffset,
831 DONT_ENUM | DONT_DELETE);
832utils.InstallGetter(TypedArray.prototype, "byteLength",
833 TypedArrayGetByteLength, DONT_ENUM | DONT_DELETE);
834utils.InstallGetter(TypedArray.prototype, "length", TypedArrayGetLength,
835 DONT_ENUM | DONT_DELETE);
836utils.InstallGetter(TypedArray.prototype, toStringTagSymbol,
837 TypedArrayGetToStringTag);
838utils.InstallFunctions(TypedArray.prototype, DONT_ENUM, [
839 "subarray", TypedArraySubArray,
840 "set", TypedArraySet,
841 "copyWithin", TypedArrayCopyWithin,
842 "every", TypedArrayEvery,
843 "fill", TypedArrayFill,
844 "filter", TypedArrayFilter,
845 "find", TypedArrayFind,
846 "findIndex", TypedArrayFindIndex,
847 "includes", TypedArrayIncludes,
848 "indexOf", TypedArrayIndexOf,
849 "join", TypedArrayJoin,
850 "lastIndexOf", TypedArrayLastIndexOf,
851 "forEach", TypedArrayForEach,
852 "map", TypedArrayMap,
853 "reduce", TypedArrayReduce,
854 "reduceRight", TypedArrayReduceRight,
855 "reverse", TypedArrayReverse,
856 "slice", TypedArraySlice,
857 "some", TypedArraySome,
858 "sort", TypedArraySort,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000859 "toLocaleString", TypedArrayToLocaleString
860]);
861
Ben Murdochda12d292016-06-02 14:46:10 +0100862%AddNamedProperty(TypedArray.prototype, "toString", ArrayToString,
863 DONT_ENUM);
864
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000865
866macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE)
867 %SetCode(GlobalNAME, NAMEConstructor);
868 %FunctionSetPrototype(GlobalNAME, new GlobalObject());
869 %InternalSetPrototype(GlobalNAME, TypedArray);
870 %InternalSetPrototype(GlobalNAME.prototype, TypedArray.prototype);
871
872 %AddNamedProperty(GlobalNAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE,
873 READ_ONLY | DONT_ENUM | DONT_DELETE);
874
875 %AddNamedProperty(GlobalNAME.prototype,
876 "constructor", global.NAME, DONT_ENUM);
877 %AddNamedProperty(GlobalNAME.prototype,
878 "BYTES_PER_ELEMENT", ELEMENT_SIZE,
879 READ_ONLY | DONT_ENUM | DONT_DELETE);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880endmacro
881
882TYPED_ARRAYS(SETUP_TYPED_ARRAY)
883
884// --------------------------- DataView -----------------------------
885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886function DataViewGetBufferJS() {
887 if (!IS_DATAVIEW(this)) {
888 throw MakeTypeError(kIncompatibleMethodReceiver, 'DataView.buffer', this);
889 }
890 return %DataViewGetBuffer(this);
891}
892
893function DataViewGetByteOffset() {
894 if (!IS_DATAVIEW(this)) {
895 throw MakeTypeError(kIncompatibleMethodReceiver,
896 'DataView.byteOffset', this);
897 }
898 return %_ArrayBufferViewGetByteOffset(this);
899}
900
901function DataViewGetByteLength() {
902 if (!IS_DATAVIEW(this)) {
903 throw MakeTypeError(kIncompatibleMethodReceiver,
904 'DataView.byteLength', this);
905 }
906 return %_ArrayBufferViewGetByteLength(this);
907}
908
909macro DATA_VIEW_TYPES(FUNCTION)
910 FUNCTION(Int8)
911 FUNCTION(Uint8)
912 FUNCTION(Int16)
913 FUNCTION(Uint16)
914 FUNCTION(Int32)
915 FUNCTION(Uint32)
916 FUNCTION(Float32)
917 FUNCTION(Float64)
918endmacro
919
920
921macro DATA_VIEW_GETTER_SETTER(TYPENAME)
922function DataViewGetTYPENAMEJS(offset, little_endian) {
923 if (!IS_DATAVIEW(this)) {
924 throw MakeTypeError(kIncompatibleMethodReceiver,
925 'DataView.getTYPENAME', this);
926 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100927 if (arguments.length < 1) throw MakeTypeError(kInvalidArgument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000928 offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
929 return %DataViewGetTYPENAME(this, offset, !!little_endian);
930}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100931%FunctionSetLength(DataViewGetTYPENAMEJS, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932
933function DataViewSetTYPENAMEJS(offset, value, little_endian) {
934 if (!IS_DATAVIEW(this)) {
935 throw MakeTypeError(kIncompatibleMethodReceiver,
936 'DataView.setTYPENAME', this);
937 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100938 if (arguments.length < 2) throw MakeTypeError(kInvalidArgument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000939 offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
940 %DataViewSetTYPENAME(this, offset, TO_NUMBER(value), !!little_endian);
941}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100942%FunctionSetLength(DataViewSetTYPENAMEJS, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000943endmacro
944
945DATA_VIEW_TYPES(DATA_VIEW_GETTER_SETTER)
946
947// Setup the DataView constructor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948%FunctionSetPrototype(GlobalDataView, new GlobalObject);
949
950// Set up constructor property on the DataView prototype.
951%AddNamedProperty(GlobalDataView.prototype, "constructor", GlobalDataView,
952 DONT_ENUM);
953%AddNamedProperty(GlobalDataView.prototype, toStringTagSymbol, "DataView",
954 READ_ONLY|DONT_ENUM);
955
956utils.InstallGetter(GlobalDataView.prototype, "buffer", DataViewGetBufferJS);
957utils.InstallGetter(GlobalDataView.prototype, "byteOffset",
958 DataViewGetByteOffset);
959utils.InstallGetter(GlobalDataView.prototype, "byteLength",
960 DataViewGetByteLength);
961
962utils.InstallFunctions(GlobalDataView.prototype, DONT_ENUM, [
963 "getInt8", DataViewGetInt8JS,
964 "setInt8", DataViewSetInt8JS,
965
966 "getUint8", DataViewGetUint8JS,
967 "setUint8", DataViewSetUint8JS,
968
969 "getInt16", DataViewGetInt16JS,
970 "setInt16", DataViewSetInt16JS,
971
972 "getUint16", DataViewGetUint16JS,
973 "setUint16", DataViewSetUint16JS,
974
975 "getInt32", DataViewGetInt32JS,
976 "setInt32", DataViewSetInt32JS,
977
978 "getUint32", DataViewGetUint32JS,
979 "setUint32", DataViewSetUint32JS,
980
981 "getFloat32", DataViewGetFloat32JS,
982 "setFloat32", DataViewSetFloat32JS,
983
984 "getFloat64", DataViewGetFloat64JS,
985 "setFloat64", DataViewSetFloat64JS
986]);
987
988})