blob: 4fb174bc57059146a0678093cb07c6e6aabb2771 [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 +010014var AddIndexedProperty;
15// array.js has to come before typedarray.js for this to work
16var ArrayToString = utils.ImportNow("ArrayToString");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017var ArrayValues;
Ben Murdochda12d292016-06-02 14:46:10 +010018var GetIterator;
19var GetMethod;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020var GlobalArray = global.Array;
21var GlobalArrayBuffer = global.ArrayBuffer;
Ben Murdochda12d292016-06-02 14:46:10 +010022var GlobalArrayBufferPrototype = GlobalArrayBuffer.prototype;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023var GlobalDataView = global.DataView;
24var GlobalObject = global.Object;
25var InternalArray = utils.InternalArray;
26var InnerArrayCopyWithin;
27var InnerArrayEvery;
28var InnerArrayFill;
29var InnerArrayFilter;
30var InnerArrayFind;
31var InnerArrayFindIndex;
32var InnerArrayForEach;
33var InnerArrayIncludes;
34var InnerArrayIndexOf;
35var InnerArrayJoin;
36var InnerArrayLastIndexOf;
37var InnerArrayReduce;
38var InnerArrayReduceRight;
39var InnerArraySome;
40var InnerArraySort;
41var InnerArrayToLocaleString;
42var InternalArray = utils.InternalArray;
43var IsNaN;
44var MakeRangeError;
45var MakeTypeError;
46var MaxSimple;
47var MinSimple;
48var PackedArrayReverse;
49var SpeciesConstructor;
50var ToPositiveInteger;
51var iteratorSymbol = utils.ImportNow("iterator_symbol");
52var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
53
54macro TYPED_ARRAYS(FUNCTION)
55// arrayIds below should be synchronized with Runtime_TypedArrayInitialize.
56FUNCTION(1, Uint8Array, 1)
57FUNCTION(2, Int8Array, 1)
58FUNCTION(3, Uint16Array, 2)
59FUNCTION(4, Int16Array, 2)
60FUNCTION(5, Uint32Array, 4)
61FUNCTION(6, Int32Array, 4)
62FUNCTION(7, Float32Array, 4)
63FUNCTION(8, Float64Array, 8)
64FUNCTION(9, Uint8ClampedArray, 1)
65endmacro
66
67macro DECLARE_GLOBALS(INDEX, NAME, SIZE)
68var GlobalNAME = global.NAME;
69endmacro
70
71TYPED_ARRAYS(DECLARE_GLOBALS)
72
73utils.Import(function(from) {
Ben Murdochda12d292016-06-02 14:46:10 +010074 AddIndexedProperty = from.AddIndexedProperty;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 ArrayValues = from.ArrayValues;
Ben Murdochda12d292016-06-02 14:46:10 +010076 GetIterator = from.GetIterator;
77 GetMethod = from.GetMethod;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078 InnerArrayCopyWithin = from.InnerArrayCopyWithin;
79 InnerArrayEvery = from.InnerArrayEvery;
80 InnerArrayFill = from.InnerArrayFill;
81 InnerArrayFilter = from.InnerArrayFilter;
82 InnerArrayFind = from.InnerArrayFind;
83 InnerArrayFindIndex = from.InnerArrayFindIndex;
84 InnerArrayForEach = from.InnerArrayForEach;
85 InnerArrayIncludes = from.InnerArrayIncludes;
86 InnerArrayIndexOf = from.InnerArrayIndexOf;
87 InnerArrayJoin = from.InnerArrayJoin;
88 InnerArrayLastIndexOf = from.InnerArrayLastIndexOf;
89 InnerArrayReduce = from.InnerArrayReduce;
90 InnerArrayReduceRight = from.InnerArrayReduceRight;
91 InnerArraySome = from.InnerArraySome;
92 InnerArraySort = from.InnerArraySort;
93 InnerArrayToLocaleString = from.InnerArrayToLocaleString;
94 IsNaN = from.IsNaN;
95 MakeRangeError = from.MakeRangeError;
96 MakeTypeError = from.MakeTypeError;
97 MaxSimple = from.MaxSimple;
98 MinSimple = from.MinSimple;
99 PackedArrayReverse = from.PackedArrayReverse;
100 SpeciesConstructor = from.SpeciesConstructor;
101 ToPositiveInteger = from.ToPositiveInteger;
102});
103
104// --------------- Typed Arrays ---------------------
105
106function TypedArrayDefaultConstructor(typedArray) {
107 switch (%_ClassOf(typedArray)) {
108macro TYPED_ARRAY_CONSTRUCTOR_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
109 case "NAME":
110 return GlobalNAME;
111endmacro
112TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR_CASE)
113 }
114 // The TypeError should not be generated since all callers should
115 // have already called ValidateTypedArray.
116 throw MakeTypeError(kIncompatibleMethodReceiver,
117 "TypedArrayDefaultConstructor", this);
118}
119
120function TypedArrayCreate(constructor, arg0, arg1, arg2) {
121 if (IS_UNDEFINED(arg1)) {
122 var newTypedArray = new constructor(arg0);
123 } else {
124 var newTypedArray = new constructor(arg0, arg1, arg2);
125 }
Ben Murdochda12d292016-06-02 14:46:10 +0100126 if (!IS_TYPEDARRAY(newTypedArray)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127 // TODO(littledan): Check for being detached, here and elsewhere
128 // All callers where the first argument is a Number have no additional
129 // arguments.
130 if (IS_NUMBER(arg0) && %_TypedArrayGetLength(newTypedArray) < arg0) {
131 throw MakeTypeError(kTypedArrayTooShort);
132 }
133 return newTypedArray;
134}
135
136function TypedArraySpeciesCreate(exemplar, arg0, arg1, arg2, conservative) {
137 var defaultConstructor = TypedArrayDefaultConstructor(exemplar);
138 var constructor = SpeciesConstructor(exemplar, defaultConstructor,
139 conservative);
140 return TypedArrayCreate(constructor, arg0, arg1, arg2);
141}
142
143macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE)
144function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
145 if (!IS_UNDEFINED(byteOffset)) {
146 byteOffset = ToPositiveInteger(byteOffset, kInvalidTypedArrayLength);
147 }
148 if (!IS_UNDEFINED(length)) {
149 length = ToPositiveInteger(length, kInvalidTypedArrayLength);
150 }
151
152 var bufferByteLength = %_ArrayBufferGetByteLength(buffer);
153 var offset;
154 if (IS_UNDEFINED(byteOffset)) {
155 offset = 0;
156 } else {
157 offset = byteOffset;
158
159 if (offset % ELEMENT_SIZE !== 0) {
160 throw MakeRangeError(kInvalidTypedArrayAlignment,
161 "start offset", "NAME", ELEMENT_SIZE);
162 }
163 if (offset > bufferByteLength) {
164 throw MakeRangeError(kInvalidTypedArrayOffset);
165 }
166 }
167
168 var newByteLength;
169 var newLength;
170 if (IS_UNDEFINED(length)) {
171 if (bufferByteLength % ELEMENT_SIZE !== 0) {
172 throw MakeRangeError(kInvalidTypedArrayAlignment,
173 "byte length", "NAME", ELEMENT_SIZE);
174 }
175 newByteLength = bufferByteLength - offset;
176 newLength = newByteLength / ELEMENT_SIZE;
177 } else {
178 var newLength = length;
179 newByteLength = newLength * ELEMENT_SIZE;
180 }
181 if ((offset + newByteLength > bufferByteLength)
182 || (newLength > %_MaxSmi())) {
183 throw MakeRangeError(kInvalidTypedArrayLength);
184 }
185 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength, true);
186}
187
188function NAMEConstructByLength(obj, length) {
189 var l = IS_UNDEFINED(length) ?
190 0 : ToPositiveInteger(length, kInvalidTypedArrayLength);
191 if (l > %_MaxSmi()) {
192 throw MakeRangeError(kInvalidTypedArrayLength);
193 }
194 var byteLength = l * ELEMENT_SIZE;
195 if (byteLength > %_TypedArrayMaxSizeInHeap()) {
196 var buffer = new GlobalArrayBuffer(byteLength);
197 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, 0, byteLength, true);
198 } else {
199 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, true);
200 }
201}
202
Ben Murdochda12d292016-06-02 14:46:10 +0100203function NAMEConstructByArrayLike(obj, arrayLike, length) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 var l = ToPositiveInteger(length, kInvalidTypedArrayLength);
205
206 if (l > %_MaxSmi()) {
207 throw MakeRangeError(kInvalidTypedArrayLength);
208 }
209 var initialized = false;
210 var byteLength = l * ELEMENT_SIZE;
211 if (byteLength <= %_TypedArrayMaxSizeInHeap()) {
212 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, false);
213 } else {
214 initialized =
215 %TypedArrayInitializeFromArrayLike(obj, ARRAY_ID, arrayLike, l);
216 }
217 if (!initialized) {
218 for (var i = 0; i < l; i++) {
219 // It is crucial that we let any execptions from arrayLike[i]
220 // propagate outside the function.
221 obj[i] = arrayLike[i];
222 }
223 }
224}
225
226function NAMEConstructByIterable(obj, iterable, iteratorFn) {
227 var list = new InternalArray();
228 // Reading the Symbol.iterator property of iterable twice would be
229 // observable with getters, so instead, we call the function which
230 // was already looked up, and wrap it in another iterable. The
231 // __proto__ of the new iterable is set to null to avoid any chance
232 // of modifications to Object.prototype being observable here.
233 var iterator = %_Call(iteratorFn, iterable);
234 var newIterable = {
235 __proto__: null
236 };
237 // TODO(littledan): Computed properties don't work yet in nosnap.
238 // Rephrase when they do.
239 newIterable[iteratorSymbol] = function() { return iterator; }
240 for (var value of newIterable) {
241 list.push(value);
242 }
Ben Murdochda12d292016-06-02 14:46:10 +0100243 NAMEConstructByArrayLike(obj, list, list.length);
244}
245
246// ES#sec-typedarray-typedarray TypedArray ( typedArray )
247function NAMEConstructByTypedArray(obj, typedArray) {
248 // TODO(littledan): Throw on detached typedArray
249 var srcData = %TypedArrayGetBuffer(typedArray);
250 var length = %_TypedArrayGetLength(typedArray);
251 var byteLength = %_ArrayBufferViewGetByteLength(typedArray);
252 var newByteLength = length * ELEMENT_SIZE;
253 NAMEConstructByArrayLike(obj, typedArray, length);
254 var bufferConstructor = SpeciesConstructor(srcData, GlobalArrayBuffer);
255 var prototype = bufferConstructor.prototype;
256 // TODO(littledan): Use the right prototype based on bufferConstructor's realm
257 if (IS_RECEIVER(prototype) && prototype !== GlobalArrayBufferPrototype) {
258 %InternalSetPrototype(%TypedArrayGetBuffer(obj), prototype);
259 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260}
261
262function NAMEConstructor(arg1, arg2, arg3) {
263 if (!IS_UNDEFINED(new.target)) {
264 if (IS_ARRAYBUFFER(arg1) || IS_SHAREDARRAYBUFFER(arg1)) {
265 NAMEConstructByArrayBuffer(this, arg1, arg2, arg3);
266 } else if (IS_NUMBER(arg1) || IS_STRING(arg1) ||
267 IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) {
268 NAMEConstructByLength(this, arg1);
Ben Murdochda12d292016-06-02 14:46:10 +0100269 } else if (IS_TYPEDARRAY(arg1)) {
270 NAMEConstructByTypedArray(this, arg1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 var iteratorFn = arg1[iteratorSymbol];
273 if (IS_UNDEFINED(iteratorFn) || iteratorFn === ArrayValues) {
Ben Murdochda12d292016-06-02 14:46:10 +0100274 NAMEConstructByArrayLike(this, arg1, arg1.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275 } else {
276 NAMEConstructByIterable(this, arg1, iteratorFn);
277 }
278 }
279 } else {
280 throw MakeTypeError(kConstructorNotFunction, "NAME")
281 }
282}
283
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284function NAMESubArray(begin, end) {
285 var beginInt = TO_INTEGER(begin);
286 if (!IS_UNDEFINED(end)) {
287 var endInt = TO_INTEGER(end);
288 var srcLength = %_TypedArrayGetLength(this);
289 } else {
290 var srcLength = %_TypedArrayGetLength(this);
291 var endInt = srcLength;
292 }
293
294 if (beginInt < 0) {
295 beginInt = MaxSimple(0, srcLength + beginInt);
296 } else {
297 beginInt = MinSimple(beginInt, srcLength);
298 }
299
300 if (endInt < 0) {
301 endInt = MaxSimple(0, srcLength + endInt);
302 } else {
303 endInt = MinSimple(endInt, srcLength);
304 }
305
306 if (endInt < beginInt) {
307 endInt = beginInt;
308 }
309
310 var newLength = endInt - beginInt;
311 var beginByteOffset =
312 %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100313 // BUG(v8:4665): For web compatibility, subarray needs to always build an
314 // instance of the default constructor.
315 // TODO(littledan): Switch to the standard or standardize the fix
316 return new GlobalNAME(%TypedArrayGetBuffer(this), beginByteOffset, newLength);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317}
318endmacro
319
320TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR)
321
322function TypedArraySubArray(begin, end) {
323 switch (%_ClassOf(this)) {
324macro TYPED_ARRAY_SUBARRAY_CASE(ARRAY_ID, NAME, ELEMENT_SIZE)
325 case "NAME":
326 return %_Call(NAMESubArray, this, begin, end);
327endmacro
328TYPED_ARRAYS(TYPED_ARRAY_SUBARRAY_CASE)
329 }
330 throw MakeTypeError(kIncompatibleMethodReceiver,
331 "get TypedArray.prototype.subarray", this);
332}
333%SetForceInlineFlag(TypedArraySubArray);
334
335function TypedArrayGetBuffer() {
Ben Murdochda12d292016-06-02 14:46:10 +0100336 if (!IS_TYPEDARRAY(this)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000337 throw MakeTypeError(kIncompatibleMethodReceiver,
338 "get TypedArray.prototype.buffer", this);
339 }
340 return %TypedArrayGetBuffer(this);
341}
342%SetForceInlineFlag(TypedArrayGetBuffer);
343
344function TypedArrayGetByteLength() {
Ben Murdochda12d292016-06-02 14:46:10 +0100345 if (!IS_TYPEDARRAY(this)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000346 throw MakeTypeError(kIncompatibleMethodReceiver,
347 "get TypedArray.prototype.byteLength", this);
348 }
349 return %_ArrayBufferViewGetByteLength(this);
350}
351%SetForceInlineFlag(TypedArrayGetByteLength);
352
353function TypedArrayGetByteOffset() {
Ben Murdochda12d292016-06-02 14:46:10 +0100354 if (!IS_TYPEDARRAY(this)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355 throw MakeTypeError(kIncompatibleMethodReceiver,
356 "get TypedArray.prototype.byteOffset", this);
357 }
358 return %_ArrayBufferViewGetByteOffset(this);
359}
360%SetForceInlineFlag(TypedArrayGetByteOffset);
361
362function TypedArrayGetLength() {
Ben Murdochda12d292016-06-02 14:46:10 +0100363 if (!IS_TYPEDARRAY(this)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 throw MakeTypeError(kIncompatibleMethodReceiver,
365 "get TypedArray.prototype.length", this);
366 }
367 return %_TypedArrayGetLength(this);
368}
369%SetForceInlineFlag(TypedArrayGetLength);
370
371
372
373function TypedArraySetFromArrayLike(target, source, sourceLength, offset) {
374 if (offset > 0) {
375 for (var i = 0; i < sourceLength; i++) {
376 target[offset + i] = source[i];
377 }
378 }
379 else {
380 for (var i = 0; i < sourceLength; i++) {
381 target[i] = source[i];
382 }
383 }
384}
385
386function TypedArraySetFromOverlappingTypedArray(target, source, offset) {
387 var sourceElementSize = source.BYTES_PER_ELEMENT;
388 var targetElementSize = target.BYTES_PER_ELEMENT;
389 var sourceLength = source.length;
390
391 // Copy left part.
392 function CopyLeftPart() {
393 // First un-mutated byte after the next write
394 var targetPtr = target.byteOffset + (offset + 1) * targetElementSize;
395 // Next read at sourcePtr. We do not care for memory changing before
396 // sourcePtr - we have already copied it.
397 var sourcePtr = source.byteOffset;
398 for (var leftIndex = 0;
399 leftIndex < sourceLength && targetPtr <= sourcePtr;
400 leftIndex++) {
401 target[offset + leftIndex] = source[leftIndex];
402 targetPtr += targetElementSize;
403 sourcePtr += sourceElementSize;
404 }
405 return leftIndex;
406 }
407 var leftIndex = CopyLeftPart();
408
409 // Copy rigth part;
410 function CopyRightPart() {
411 // First unmutated byte before the next write
412 var targetPtr =
413 target.byteOffset + (offset + sourceLength - 1) * targetElementSize;
414 // Next read before sourcePtr. We do not care for memory changing after
415 // sourcePtr - we have already copied it.
416 var sourcePtr =
417 source.byteOffset + sourceLength * sourceElementSize;
418 for(var rightIndex = sourceLength - 1;
419 rightIndex >= leftIndex && targetPtr >= sourcePtr;
420 rightIndex--) {
421 target[offset + rightIndex] = source[rightIndex];
422 targetPtr -= targetElementSize;
423 sourcePtr -= sourceElementSize;
424 }
425 return rightIndex;
426 }
427 var rightIndex = CopyRightPart();
428
429 var temp = new GlobalArray(rightIndex + 1 - leftIndex);
430 for (var i = leftIndex; i <= rightIndex; i++) {
431 temp[i - leftIndex] = source[i];
432 }
433 for (i = leftIndex; i <= rightIndex; i++) {
434 target[offset + i] = temp[i - leftIndex];
435 }
436}
437
438function TypedArraySet(obj, offset) {
439 var intOffset = IS_UNDEFINED(offset) ? 0 : TO_INTEGER(offset);
440 if (intOffset < 0) throw MakeTypeError(kTypedArraySetNegativeOffset);
441
442 if (intOffset > %_MaxSmi()) {
443 throw MakeRangeError(kTypedArraySetSourceTooLarge);
444 }
445 switch (%TypedArraySetFastCases(this, obj, intOffset)) {
446 // These numbers should be synchronized with runtime.cc.
447 case 0: // TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE
448 return;
449 case 1: // TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING
450 TypedArraySetFromOverlappingTypedArray(this, obj, intOffset);
451 return;
452 case 2: // TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING
453 TypedArraySetFromArrayLike(this, obj, obj.length, intOffset);
454 return;
455 case 3: // TYPED_ARRAY_SET_NON_TYPED_ARRAY
456 var l = obj.length;
457 if (IS_UNDEFINED(l)) {
458 if (IS_NUMBER(obj)) {
459 // For number as a first argument, throw TypeError
460 // instead of silently ignoring the call, so that
461 // the user knows (s)he did something wrong.
462 // (Consistent with Firefox and Blink/WebKit)
463 throw MakeTypeError(kInvalidArgument);
464 }
465 return;
466 }
467 l = TO_LENGTH(l);
468 if (intOffset + l > this.length) {
469 throw MakeRangeError(kTypedArraySetSourceTooLarge);
470 }
471 TypedArraySetFromArrayLike(this, obj, l, intOffset);
472 return;
473 }
474}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100475%FunctionSetLength(TypedArraySet, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000476
477function TypedArrayGetToStringTag() {
Ben Murdochda12d292016-06-02 14:46:10 +0100478 if (!IS_TYPEDARRAY(this)) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479 var name = %_ClassOf(this);
480 if (IS_UNDEFINED(name)) return;
481 return name;
482}
483
484
485function TypedArrayCopyWithin(target, start, end) {
Ben Murdochda12d292016-06-02 14:46:10 +0100486 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000487
488 var length = %_TypedArrayGetLength(this);
489
490 // TODO(littledan): Replace with a memcpy for better performance
491 return InnerArrayCopyWithin(target, start, end, this, length);
492}
493%FunctionSetLength(TypedArrayCopyWithin, 2);
494
495
496// ES6 draft 05-05-15, section 22.2.3.7
497function TypedArrayEvery(f, receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100498 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499
500 var length = %_TypedArrayGetLength(this);
501
502 return InnerArrayEvery(f, receiver, this, length);
503}
504%FunctionSetLength(TypedArrayEvery, 1);
505
506
507// ES6 draft 08-24-14, section 22.2.3.12
508function TypedArrayForEach(f, receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100509 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000510
511 var length = %_TypedArrayGetLength(this);
512
513 InnerArrayForEach(f, receiver, this, length);
514}
515%FunctionSetLength(TypedArrayForEach, 1);
516
517
518// ES6 draft 04-05-14 section 22.2.3.8
519function TypedArrayFill(value, start, end) {
Ben Murdochda12d292016-06-02 14:46:10 +0100520 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000521
522 var length = %_TypedArrayGetLength(this);
523
524 return InnerArrayFill(value, start, end, this, length);
525}
526%FunctionSetLength(TypedArrayFill, 1);
527
528
529// ES6 draft 07-15-13, section 22.2.3.9
530function TypedArrayFilter(f, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100531 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532
533 var length = %_TypedArrayGetLength(this);
534 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
535 var result = new InternalArray();
536 InnerArrayFilter(f, thisArg, this, length, result);
537 var captured = result.length;
538 var output = TypedArraySpeciesCreate(this, captured);
539 for (var i = 0; i < captured; i++) {
540 output[i] = result[i];
541 }
542 return output;
543}
544%FunctionSetLength(TypedArrayFilter, 1);
545
546
547// ES6 draft 07-15-13, section 22.2.3.10
548function TypedArrayFind(predicate, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100549 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000550
551 var length = %_TypedArrayGetLength(this);
552
553 return InnerArrayFind(predicate, thisArg, this, length);
554}
555%FunctionSetLength(TypedArrayFind, 1);
556
557
558// ES6 draft 07-15-13, section 22.2.3.11
559function TypedArrayFindIndex(predicate, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100560 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000561
562 var length = %_TypedArrayGetLength(this);
563
564 return InnerArrayFindIndex(predicate, thisArg, this, length);
565}
566%FunctionSetLength(TypedArrayFindIndex, 1);
567
568
569// ES6 draft 05-18-15, section 22.2.3.21
570function TypedArrayReverse() {
Ben Murdochda12d292016-06-02 14:46:10 +0100571 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000572
573 var length = %_TypedArrayGetLength(this);
574
575 return PackedArrayReverse(this, length);
576}
577
578
579function TypedArrayComparefn(x, y) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100580 if (x === 0 && x === y) {
581 x = 1 / x;
582 y = 1 / y;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100584 if (x < y) {
585 return -1;
586 } else if (x > y) {
587 return 1;
588 } else if (IsNaN(x) && IsNaN(y)) {
589 return IsNaN(y) ? 0 : 1;
590 } else if (IsNaN(x)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000591 return 1;
592 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100593 return 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000594}
595
596
597// ES6 draft 05-18-15, section 22.2.3.25
598function TypedArraySort(comparefn) {
Ben Murdochda12d292016-06-02 14:46:10 +0100599 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000600
601 var length = %_TypedArrayGetLength(this);
602
603 if (IS_UNDEFINED(comparefn)) {
604 comparefn = TypedArrayComparefn;
605 }
606
607 return InnerArraySort(this, length, comparefn);
608}
609
610
611// ES6 section 22.2.3.13
612function TypedArrayIndexOf(element, index) {
Ben Murdochda12d292016-06-02 14:46:10 +0100613 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000614
615 var length = %_TypedArrayGetLength(this);
616 return InnerArrayIndexOf(this, element, index, length);
617}
618%FunctionSetLength(TypedArrayIndexOf, 1);
619
620
621// ES6 section 22.2.3.16
622function TypedArrayLastIndexOf(element, index) {
Ben Murdochda12d292016-06-02 14:46:10 +0100623 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624
625 var length = %_TypedArrayGetLength(this);
626
627 return InnerArrayLastIndexOf(this, element, index, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100628 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629}
630%FunctionSetLength(TypedArrayLastIndexOf, 1);
631
632
633// ES6 draft 07-15-13, section 22.2.3.18
634function TypedArrayMap(f, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100635 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000636
637 var length = %_TypedArrayGetLength(this);
638 var result = TypedArraySpeciesCreate(this, length);
639 if (!IS_CALLABLE(f)) throw MakeTypeError(kCalledNonCallable, f);
640 for (var i = 0; i < length; i++) {
641 var element = this[i];
642 result[i] = %_Call(f, thisArg, element, i, this);
643 }
644 return result;
645}
646%FunctionSetLength(TypedArrayMap, 1);
647
648
649// ES6 draft 05-05-15, section 22.2.3.24
650function TypedArraySome(f, receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100651 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652
653 var length = %_TypedArrayGetLength(this);
654
655 return InnerArraySome(f, receiver, this, length);
656}
657%FunctionSetLength(TypedArraySome, 1);
658
659
660// ES6 section 22.2.3.27
661function TypedArrayToLocaleString() {
Ben Murdochda12d292016-06-02 14:46:10 +0100662 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000663
664 var length = %_TypedArrayGetLength(this);
665
666 return InnerArrayToLocaleString(this, length);
667}
668
669
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670// ES6 section 22.2.3.14
671function TypedArrayJoin(separator) {
Ben Murdochda12d292016-06-02 14:46:10 +0100672 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000673
674 var length = %_TypedArrayGetLength(this);
675
676 return InnerArrayJoin(separator, this, length);
677}
678
679
680// ES6 draft 07-15-13, section 22.2.3.19
681function TypedArrayReduce(callback, current) {
Ben Murdochda12d292016-06-02 14:46:10 +0100682 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683
684 var length = %_TypedArrayGetLength(this);
685 return InnerArrayReduce(callback, current, this, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100686 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000687}
688%FunctionSetLength(TypedArrayReduce, 1);
689
690
691// ES6 draft 07-15-13, section 22.2.3.19
692function TypedArrayReduceRight(callback, current) {
Ben Murdochda12d292016-06-02 14:46:10 +0100693 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000694
695 var length = %_TypedArrayGetLength(this);
696 return InnerArrayReduceRight(callback, current, this, length,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100697 arguments.length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000698}
699%FunctionSetLength(TypedArrayReduceRight, 1);
700
701
702function TypedArraySlice(start, end) {
Ben Murdochda12d292016-06-02 14:46:10 +0100703 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000704 var len = %_TypedArrayGetLength(this);
705
706 var relativeStart = TO_INTEGER(start);
707
708 var k;
709 if (relativeStart < 0) {
710 k = MaxSimple(len + relativeStart, 0);
711 } else {
712 k = MinSimple(relativeStart, len);
713 }
714
715 var relativeEnd;
716 if (IS_UNDEFINED(end)) {
717 relativeEnd = len;
718 } else {
719 relativeEnd = TO_INTEGER(end);
720 }
721
722 var final;
723 if (relativeEnd < 0) {
724 final = MaxSimple(len + relativeEnd, 0);
725 } else {
726 final = MinSimple(relativeEnd, len);
727 }
728
729 var count = MaxSimple(final - k, 0);
730 var array = TypedArraySpeciesCreate(this, count);
731 // The code below is the 'then' branch; the 'else' branch species
732 // a memcpy. Because V8 doesn't canonicalize NaN, the difference is
733 // unobservable.
734 var n = 0;
735 while (k < final) {
736 var kValue = this[k];
737 array[n] = kValue;
738 k++;
739 n++;
740 }
741 return array;
742}
743
744
745// ES2016 draft, section 22.2.3.14
746function TypedArrayIncludes(searchElement, fromIndex) {
Ben Murdochda12d292016-06-02 14:46:10 +0100747 if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000748
749 var length = %_TypedArrayGetLength(this);
750
751 return InnerArrayIncludes(searchElement, fromIndex, this, length);
752}
753%FunctionSetLength(TypedArrayIncludes, 1);
754
755
756// ES6 draft 08-24-14, section 22.2.2.2
757function TypedArrayOf() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100758 var length = arguments.length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759 var array = TypedArrayCreate(this, length);
760 for (var i = 0; i < length; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100761 array[i] = arguments[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000762 }
763 return array;
764}
765
766
Ben Murdochda12d292016-06-02 14:46:10 +0100767// ES#sec-iterabletoarraylike Runtime Semantics: IterableToArrayLike( items )
768function IterableToArrayLike(items) {
769 var iterable = GetMethod(items, iteratorSymbol);
770 if (!IS_UNDEFINED(iterable)) {
771 var internal_array = new InternalArray();
772 var i = 0;
773 for (var value of
774 { [iteratorSymbol]() { return GetIterator(items, iterable) } }) {
775 internal_array[i] = value;
776 i++;
777 }
778 var array = [];
779 %MoveArrayContents(internal_array, array);
780 return array;
781 }
782 return TO_OBJECT(items);
783}
784
785
786// ES#sec-%typedarray%.from
787// %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] )
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000788function TypedArrayFrom(source, mapfn, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100789 if (!%IsConstructor(this)) throw MakeTypeError(kNotConstructor, this);
790 var mapping;
791 if (!IS_UNDEFINED(mapfn)) {
792 if (!IS_CALLABLE(mapfn)) throw MakeTypeError(kCalledNonCallable, this);
793 mapping = true;
794 } else {
795 mapping = false;
796 }
797 var arrayLike = IterableToArrayLike(source);
798 var length = TO_LENGTH(arrayLike.length);
799 var targetObject = TypedArrayCreate(this, length);
800 var value, mappedValue;
801 for (var i = 0; i < length; i++) {
802 value = arrayLike[i];
803 if (mapping) {
804 mappedValue = %_Call(mapfn, thisArg, value, i);
805 } else {
806 mappedValue = value;
807 }
808 targetObject[i] = mappedValue;
809 }
810 return targetObject;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000811}
812%FunctionSetLength(TypedArrayFrom, 1);
813
814function TypedArray() {
815 if (IS_UNDEFINED(new.target)) {
816 throw MakeTypeError(kConstructorNonCallable, "TypedArray");
817 }
818 if (new.target === TypedArray) {
819 throw MakeTypeError(kConstructAbstractClass, "TypedArray");
820 }
821}
822
823// -------------------------------------------------------------------
824
825%FunctionSetPrototype(TypedArray, new GlobalObject());
826%AddNamedProperty(TypedArray.prototype,
827 "constructor", TypedArray, DONT_ENUM);
Ben Murdochda12d292016-06-02 14:46:10 +0100828utils.InstallFunctions(TypedArray, DONT_ENUM, [
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000829 "from", TypedArrayFrom,
830 "of", TypedArrayOf
831]);
832utils.InstallGetter(TypedArray.prototype, "buffer", TypedArrayGetBuffer);
833utils.InstallGetter(TypedArray.prototype, "byteOffset", TypedArrayGetByteOffset,
834 DONT_ENUM | DONT_DELETE);
835utils.InstallGetter(TypedArray.prototype, "byteLength",
836 TypedArrayGetByteLength, DONT_ENUM | DONT_DELETE);
837utils.InstallGetter(TypedArray.prototype, "length", TypedArrayGetLength,
838 DONT_ENUM | DONT_DELETE);
839utils.InstallGetter(TypedArray.prototype, toStringTagSymbol,
840 TypedArrayGetToStringTag);
841utils.InstallFunctions(TypedArray.prototype, DONT_ENUM, [
842 "subarray", TypedArraySubArray,
843 "set", TypedArraySet,
844 "copyWithin", TypedArrayCopyWithin,
845 "every", TypedArrayEvery,
846 "fill", TypedArrayFill,
847 "filter", TypedArrayFilter,
848 "find", TypedArrayFind,
849 "findIndex", TypedArrayFindIndex,
850 "includes", TypedArrayIncludes,
851 "indexOf", TypedArrayIndexOf,
852 "join", TypedArrayJoin,
853 "lastIndexOf", TypedArrayLastIndexOf,
854 "forEach", TypedArrayForEach,
855 "map", TypedArrayMap,
856 "reduce", TypedArrayReduce,
857 "reduceRight", TypedArrayReduceRight,
858 "reverse", TypedArrayReverse,
859 "slice", TypedArraySlice,
860 "some", TypedArraySome,
861 "sort", TypedArraySort,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000862 "toLocaleString", TypedArrayToLocaleString
863]);
864
Ben Murdochda12d292016-06-02 14:46:10 +0100865%AddNamedProperty(TypedArray.prototype, "toString", ArrayToString,
866 DONT_ENUM);
867
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000868
869macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE)
870 %SetCode(GlobalNAME, NAMEConstructor);
871 %FunctionSetPrototype(GlobalNAME, new GlobalObject());
872 %InternalSetPrototype(GlobalNAME, TypedArray);
873 %InternalSetPrototype(GlobalNAME.prototype, TypedArray.prototype);
874
875 %AddNamedProperty(GlobalNAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE,
876 READ_ONLY | DONT_ENUM | DONT_DELETE);
877
878 %AddNamedProperty(GlobalNAME.prototype,
879 "constructor", global.NAME, DONT_ENUM);
880 %AddNamedProperty(GlobalNAME.prototype,
881 "BYTES_PER_ELEMENT", ELEMENT_SIZE,
882 READ_ONLY | DONT_ENUM | DONT_DELETE);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000883endmacro
884
885TYPED_ARRAYS(SETUP_TYPED_ARRAY)
886
887// --------------------------- DataView -----------------------------
888
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889function DataViewGetBufferJS() {
890 if (!IS_DATAVIEW(this)) {
891 throw MakeTypeError(kIncompatibleMethodReceiver, 'DataView.buffer', this);
892 }
893 return %DataViewGetBuffer(this);
894}
895
896function DataViewGetByteOffset() {
897 if (!IS_DATAVIEW(this)) {
898 throw MakeTypeError(kIncompatibleMethodReceiver,
899 'DataView.byteOffset', this);
900 }
901 return %_ArrayBufferViewGetByteOffset(this);
902}
903
904function DataViewGetByteLength() {
905 if (!IS_DATAVIEW(this)) {
906 throw MakeTypeError(kIncompatibleMethodReceiver,
907 'DataView.byteLength', this);
908 }
909 return %_ArrayBufferViewGetByteLength(this);
910}
911
912macro DATA_VIEW_TYPES(FUNCTION)
913 FUNCTION(Int8)
914 FUNCTION(Uint8)
915 FUNCTION(Int16)
916 FUNCTION(Uint16)
917 FUNCTION(Int32)
918 FUNCTION(Uint32)
919 FUNCTION(Float32)
920 FUNCTION(Float64)
921endmacro
922
923
924macro DATA_VIEW_GETTER_SETTER(TYPENAME)
925function DataViewGetTYPENAMEJS(offset, little_endian) {
926 if (!IS_DATAVIEW(this)) {
927 throw MakeTypeError(kIncompatibleMethodReceiver,
928 'DataView.getTYPENAME', this);
929 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100930 if (arguments.length < 1) throw MakeTypeError(kInvalidArgument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
932 return %DataViewGetTYPENAME(this, offset, !!little_endian);
933}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100934%FunctionSetLength(DataViewGetTYPENAMEJS, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000935
936function DataViewSetTYPENAMEJS(offset, value, little_endian) {
937 if (!IS_DATAVIEW(this)) {
938 throw MakeTypeError(kIncompatibleMethodReceiver,
939 'DataView.setTYPENAME', this);
940 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100941 if (arguments.length < 2) throw MakeTypeError(kInvalidArgument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000942 offset = ToPositiveInteger(offset, kInvalidDataViewAccessorOffset);
943 %DataViewSetTYPENAME(this, offset, TO_NUMBER(value), !!little_endian);
944}
Ben Murdoch097c5b22016-05-18 11:27:45 +0100945%FunctionSetLength(DataViewSetTYPENAMEJS, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000946endmacro
947
948DATA_VIEW_TYPES(DATA_VIEW_GETTER_SETTER)
949
950// Setup the DataView constructor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951%FunctionSetPrototype(GlobalDataView, new GlobalObject);
952
953// Set up constructor property on the DataView prototype.
954%AddNamedProperty(GlobalDataView.prototype, "constructor", GlobalDataView,
955 DONT_ENUM);
956%AddNamedProperty(GlobalDataView.prototype, toStringTagSymbol, "DataView",
957 READ_ONLY|DONT_ENUM);
958
959utils.InstallGetter(GlobalDataView.prototype, "buffer", DataViewGetBufferJS);
960utils.InstallGetter(GlobalDataView.prototype, "byteOffset",
961 DataViewGetByteOffset);
962utils.InstallGetter(GlobalDataView.prototype, "byteLength",
963 DataViewGetByteLength);
964
965utils.InstallFunctions(GlobalDataView.prototype, DONT_ENUM, [
966 "getInt8", DataViewGetInt8JS,
967 "setInt8", DataViewSetInt8JS,
968
969 "getUint8", DataViewGetUint8JS,
970 "setUint8", DataViewSetUint8JS,
971
972 "getInt16", DataViewGetInt16JS,
973 "setInt16", DataViewSetInt16JS,
974
975 "getUint16", DataViewGetUint16JS,
976 "setUint16", DataViewSetUint16JS,
977
978 "getInt32", DataViewGetInt32JS,
979 "setInt32", DataViewSetInt32JS,
980
981 "getUint32", DataViewGetUint32JS,
982 "setUint32", DataViewSetUint32JS,
983
984 "getFloat32", DataViewGetFloat32JS,
985 "setFloat32", DataViewSetFloat32JS,
986
987 "getFloat64", DataViewGetFloat64JS,
988 "setFloat64", DataViewSetFloat64JS
989]);
990
991})