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 GlobalObject = global.Object; 23var InnerArrayEvery; 24var InnerArrayFill; 25var InnerArrayFilter; 26var InnerArrayFind; 27var InnerArrayFindIndex; 28var InnerArrayForEach; 29var InnerArrayJoin; 30var InnerArrayReduce; 31var InnerArrayReduceRight; 32var InnerArraySome; 33var InnerArraySort; 34var InnerArrayToLocaleString; 35var InternalArray = utils.InternalArray; 36var MaxSimple; 37var MinSimple; 38var PackedArrayReverse; 39var SpeciesConstructor; 40var ToPositiveInteger; 41var ToIndex; 42var iteratorSymbol = utils.ImportNow("iterator_symbol"); 43var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol"); 44 45macro TYPED_ARRAYS(FUNCTION) 46// arrayIds below should be synchronized with Runtime_TypedArrayInitialize. 47FUNCTION(1, Uint8Array, 1) 48FUNCTION(2, Int8Array, 1) 49FUNCTION(3, Uint16Array, 2) 50FUNCTION(4, Int16Array, 2) 51FUNCTION(5, Uint32Array, 4) 52FUNCTION(6, Int32Array, 4) 53FUNCTION(7, Float32Array, 4) 54FUNCTION(8, Float64Array, 8) 55FUNCTION(9, Uint8ClampedArray, 1) 56endmacro 57 58macro DECLARE_GLOBALS(INDEX, NAME, SIZE) 59var GlobalNAME = global.NAME; 60endmacro 61 62TYPED_ARRAYS(DECLARE_GLOBALS) 63 64var GlobalTypedArray = %object_get_prototype_of(GlobalUint8Array); 65 66utils.Import(function(from) { 67 ArrayValues = from.ArrayValues; 68 GetIterator = from.GetIterator; 69 GetMethod = from.GetMethod; 70 InnerArrayEvery = from.InnerArrayEvery; 71 InnerArrayFill = from.InnerArrayFill; 72 InnerArrayFilter = from.InnerArrayFilter; 73 InnerArrayFind = from.InnerArrayFind; 74 InnerArrayFindIndex = from.InnerArrayFindIndex; 75 InnerArrayForEach = from.InnerArrayForEach; 76 InnerArrayJoin = from.InnerArrayJoin; 77 InnerArrayReduce = from.InnerArrayReduce; 78 InnerArrayReduceRight = from.InnerArrayReduceRight; 79 InnerArraySome = from.InnerArraySome; 80 InnerArraySort = from.InnerArraySort; 81 InnerArrayToLocaleString = from.InnerArrayToLocaleString; 82 MaxSimple = from.MaxSimple; 83 MinSimple = from.MinSimple; 84 PackedArrayReverse = from.PackedArrayReverse; 85 SpeciesConstructor = from.SpeciesConstructor; 86 ToPositiveInteger = from.ToPositiveInteger; 87 ToIndex = from.ToIndex; 88}); 89 90// --------------- Typed Arrays --------------------- 91 92function TypedArrayDefaultConstructor(typedArray) { 93 switch (%_ClassOf(typedArray)) { 94macro TYPED_ARRAY_CONSTRUCTOR_CASE(ARRAY_ID, NAME, ELEMENT_SIZE) 95 case "NAME": 96 return GlobalNAME; 97endmacro 98TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR_CASE) 99 } 100 // The TypeError should not be generated since all callers should 101 // have already called ValidateTypedArray. 102 throw %make_type_error(kIncompatibleMethodReceiver, 103 "TypedArrayDefaultConstructor", this); 104} 105 106function TypedArrayCreate(constructor, arg0, arg1, arg2) { 107 if (IS_UNDEFINED(arg1)) { 108 var newTypedArray = new constructor(arg0); 109 } else { 110 var newTypedArray = new constructor(arg0, arg1, arg2); 111 } 112 if (!IS_TYPEDARRAY(newTypedArray)) throw %make_type_error(kNotTypedArray); 113 // TODO(littledan): Check for being detached, here and elsewhere 114 // All callers where the first argument is a Number have no additional 115 // arguments. 116 if (IS_NUMBER(arg0) && %_TypedArrayGetLength(newTypedArray) < arg0) { 117 throw %make_type_error(kTypedArrayTooShort); 118 } 119 return newTypedArray; 120} 121 122function TypedArraySpeciesCreate(exemplar, arg0, arg1, arg2, conservative) { 123 var defaultConstructor = TypedArrayDefaultConstructor(exemplar); 124 var constructor = SpeciesConstructor(exemplar, defaultConstructor, 125 conservative); 126 return TypedArrayCreate(constructor, arg0, arg1, arg2); 127} 128 129macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE) 130function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) { 131 if (!IS_UNDEFINED(byteOffset)) { 132 byteOffset = ToIndex(byteOffset, kInvalidTypedArrayLength); 133 } 134 if (!IS_UNDEFINED(length)) { 135 length = ToIndex(length, kInvalidTypedArrayLength); 136 } 137 if (length > %_MaxSmi()) { 138 // Note: this is not per spec, but rather a constraint of our current 139 // representation (which uses smi's). 140 throw %make_range_error(kInvalidTypedArrayLength); 141 } 142 143 var bufferByteLength = %_ArrayBufferGetByteLength(buffer); 144 var offset; 145 if (IS_UNDEFINED(byteOffset)) { 146 offset = 0; 147 } else { 148 offset = byteOffset; 149 150 if (offset % ELEMENT_SIZE !== 0) { 151 throw %make_range_error(kInvalidTypedArrayAlignment, 152 "start offset", "NAME", ELEMENT_SIZE); 153 } 154 } 155 156 var newByteLength; 157 if (IS_UNDEFINED(length)) { 158 if (bufferByteLength % ELEMENT_SIZE !== 0) { 159 throw %make_range_error(kInvalidTypedArrayAlignment, 160 "byte length", "NAME", ELEMENT_SIZE); 161 } 162 newByteLength = bufferByteLength - offset; 163 if (newByteLength < 0) { 164 throw %make_range_error(kInvalidOffset, offset); 165 } 166 } else { 167 newByteLength = length * ELEMENT_SIZE; 168 if (offset + newByteLength > bufferByteLength) { 169 throw %make_range_error(kInvalidTypedArrayLength); 170 } 171 } 172 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength, true); 173} 174 175function NAMEConstructByLength(obj, length) { 176 var l = IS_UNDEFINED(length) ? 177 0 : ToIndex(length, kInvalidTypedArrayLength); 178 if (length > %_MaxSmi()) { 179 // Note: this is not per spec, but rather a constraint of our current 180 // representation (which uses smi's). 181 throw %make_range_error(kInvalidTypedArrayLength); 182 } 183 var byteLength = l * ELEMENT_SIZE; 184 if (byteLength > %_TypedArrayMaxSizeInHeap()) { 185 var buffer = new GlobalArrayBuffer(byteLength); 186 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, 0, byteLength, true); 187 } else { 188 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, true); 189 } 190} 191 192function NAMEConstructByArrayLike(obj, arrayLike, length) { 193 var l = ToPositiveInteger(length, kInvalidTypedArrayLength); 194 195 if (l > %_MaxSmi()) { 196 throw %make_range_error(kInvalidTypedArrayLength); 197 } 198 var initialized = false; 199 var byteLength = l * ELEMENT_SIZE; 200 if (byteLength <= %_TypedArrayMaxSizeInHeap()) { 201 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, false); 202 } else { 203 initialized = 204 %TypedArrayInitializeFromArrayLike(obj, ARRAY_ID, arrayLike, l); 205 } 206 if (!initialized) { 207 for (var i = 0; i < l; i++) { 208 // It is crucial that we let any execptions from arrayLike[i] 209 // propagate outside the function. 210 obj[i] = arrayLike[i]; 211 } 212 } 213} 214 215function NAMEConstructByIterable(obj, iterable, iteratorFn) { 216 var list = new InternalArray(); 217 // Reading the Symbol.iterator property of iterable twice would be 218 // observable with getters, so instead, we call the function which 219 // was already looked up, and wrap it in another iterable. The 220 // __proto__ of the new iterable is set to null to avoid any chance 221 // of modifications to Object.prototype being observable here. 222 var iterator = %_Call(iteratorFn, iterable); 223 var newIterable = { 224 __proto__: null 225 }; 226 // TODO(littledan): Computed properties don't work yet in nosnap. 227 // Rephrase when they do. 228 newIterable[iteratorSymbol] = function() { return iterator; } 229 for (var value of newIterable) { 230 list.push(value); 231 } 232 NAMEConstructByArrayLike(obj, list, list.length); 233} 234 235// ES#sec-typedarray-typedarray TypedArray ( typedArray ) 236function NAMEConstructByTypedArray(obj, typedArray) { 237 // TODO(littledan): Throw on detached typedArray 238 var srcData = %TypedArrayGetBuffer(typedArray); 239 var length = %_TypedArrayGetLength(typedArray); 240 var byteLength = %_ArrayBufferViewGetByteLength(typedArray); 241 var newByteLength = length * ELEMENT_SIZE; 242 NAMEConstructByArrayLike(obj, typedArray, length); 243 var bufferConstructor = SpeciesConstructor(srcData, GlobalArrayBuffer); 244 var prototype = bufferConstructor.prototype; 245 // TODO(littledan): Use the right prototype based on bufferConstructor's realm 246 if (IS_RECEIVER(prototype) && prototype !== GlobalArrayBufferPrototype) { 247 %InternalSetPrototype(%TypedArrayGetBuffer(obj), prototype); 248 } 249} 250 251function NAMEConstructor(arg1, arg2, arg3) { 252 if (!IS_UNDEFINED(new.target)) { 253 if (IS_ARRAYBUFFER(arg1) || IS_SHAREDARRAYBUFFER(arg1)) { 254 NAMEConstructByArrayBuffer(this, arg1, arg2, arg3); 255 } else if (IS_TYPEDARRAY(arg1)) { 256 NAMEConstructByTypedArray(this, arg1); 257 } else if (IS_RECEIVER(arg1)) { 258 var iteratorFn = arg1[iteratorSymbol]; 259 if (IS_UNDEFINED(iteratorFn)) { 260 NAMEConstructByArrayLike(this, arg1, arg1.length); 261 } else { 262 NAMEConstructByIterable(this, arg1, iteratorFn); 263 } 264 } else { 265 NAMEConstructByLength(this, arg1); 266 } 267 } else { 268 throw %make_type_error(kConstructorNotFunction, "NAME") 269 } 270} 271 272function NAMESubArray(begin, end) { 273 var beginInt = TO_INTEGER(begin); 274 if (!IS_UNDEFINED(end)) { 275 var endInt = TO_INTEGER(end); 276 var srcLength = %_TypedArrayGetLength(this); 277 } else { 278 var srcLength = %_TypedArrayGetLength(this); 279 var endInt = srcLength; 280 } 281 282 if (beginInt < 0) { 283 beginInt = MaxSimple(0, srcLength + beginInt); 284 } else { 285 beginInt = MinSimple(beginInt, srcLength); 286 } 287 288 if (endInt < 0) { 289 endInt = MaxSimple(0, srcLength + endInt); 290 } else { 291 endInt = MinSimple(endInt, srcLength); 292 } 293 294 if (endInt < beginInt) { 295 endInt = beginInt; 296 } 297 298 var newLength = endInt - beginInt; 299 var beginByteOffset = 300 %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE; 301 // BUG(v8:4665): For web compatibility, subarray needs to always build an 302 // instance of the default constructor. 303 // TODO(littledan): Switch to the standard or standardize the fix 304 return new GlobalNAME(%TypedArrayGetBuffer(this), beginByteOffset, newLength); 305} 306endmacro 307 308TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR) 309 310function TypedArraySubArray(begin, end) { 311 switch (%_ClassOf(this)) { 312macro TYPED_ARRAY_SUBARRAY_CASE(ARRAY_ID, NAME, ELEMENT_SIZE) 313 case "NAME": 314 return %_Call(NAMESubArray, this, begin, end); 315endmacro 316TYPED_ARRAYS(TYPED_ARRAY_SUBARRAY_CASE) 317 } 318 throw %make_type_error(kIncompatibleMethodReceiver, 319 "get TypedArray.prototype.subarray", this); 320} 321%SetForceInlineFlag(TypedArraySubArray); 322 323 324 325function TypedArraySetFromArrayLike(target, source, sourceLength, offset) { 326 if (offset > 0) { 327 for (var i = 0; i < sourceLength; i++) { 328 target[offset + i] = source[i]; 329 } 330 } 331 else { 332 for (var i = 0; i < sourceLength; i++) { 333 target[i] = source[i]; 334 } 335 } 336} 337 338function TypedArraySetFromOverlappingTypedArray(target, source, offset) { 339 var sourceElementSize = source.BYTES_PER_ELEMENT; 340 var targetElementSize = target.BYTES_PER_ELEMENT; 341 var sourceLength = %_TypedArrayGetLength(source); 342 343 // Copy left part. 344 function CopyLeftPart() { 345 // First un-mutated byte after the next write 346 var targetPtr = target.byteOffset + (offset + 1) * targetElementSize; 347 // Next read at sourcePtr. We do not care for memory changing before 348 // sourcePtr - we have already copied it. 349 var sourcePtr = source.byteOffset; 350 for (var leftIndex = 0; 351 leftIndex < sourceLength && targetPtr <= sourcePtr; 352 leftIndex++) { 353 target[offset + leftIndex] = source[leftIndex]; 354 targetPtr += targetElementSize; 355 sourcePtr += sourceElementSize; 356 } 357 return leftIndex; 358 } 359 var leftIndex = CopyLeftPart(); 360 361 // Copy right part; 362 function CopyRightPart() { 363 // First unmutated byte before the next write 364 var targetPtr = 365 target.byteOffset + (offset + sourceLength - 1) * targetElementSize; 366 // Next read before sourcePtr. We do not care for memory changing after 367 // sourcePtr - we have already copied it. 368 var sourcePtr = 369 source.byteOffset + sourceLength * sourceElementSize; 370 for(var rightIndex = sourceLength - 1; 371 rightIndex >= leftIndex && targetPtr >= sourcePtr; 372 rightIndex--) { 373 target[offset + rightIndex] = source[rightIndex]; 374 targetPtr -= targetElementSize; 375 sourcePtr -= sourceElementSize; 376 } 377 return rightIndex; 378 } 379 var rightIndex = CopyRightPart(); 380 381 var temp = new GlobalArray(rightIndex + 1 - leftIndex); 382 for (var i = leftIndex; i <= rightIndex; i++) { 383 temp[i - leftIndex] = source[i]; 384 } 385 for (i = leftIndex; i <= rightIndex; i++) { 386 target[offset + i] = temp[i - leftIndex]; 387 } 388} 389 390function TypedArraySet(obj, offset) { 391 var intOffset = IS_UNDEFINED(offset) ? 0 : TO_INTEGER(offset); 392 if (intOffset < 0) throw %make_type_error(kTypedArraySetNegativeOffset); 393 394 if (intOffset > %_MaxSmi()) { 395 throw %make_range_error(kTypedArraySetSourceTooLarge); 396 } 397 switch (%TypedArraySetFastCases(this, obj, intOffset)) { 398 // These numbers should be synchronized with runtime.cc. 399 case 0: // TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE 400 return; 401 case 1: // TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING 402 TypedArraySetFromOverlappingTypedArray(this, obj, intOffset); 403 return; 404 case 2: // TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING 405 TypedArraySetFromArrayLike(this, 406 obj, %_TypedArrayGetLength(obj), intOffset); 407 return; 408 case 3: // TYPED_ARRAY_SET_NON_TYPED_ARRAY 409 var l = obj.length; 410 if (IS_UNDEFINED(l)) { 411 if (IS_NUMBER(obj)) { 412 // For number as a first argument, throw TypeError 413 // instead of silently ignoring the call, so that 414 // the user knows (s)he did something wrong. 415 // (Consistent with Firefox and Blink/WebKit) 416 throw %make_type_error(kInvalidArgument); 417 } 418 return; 419 } 420 l = TO_LENGTH(l); 421 if (intOffset + l > %_TypedArrayGetLength(this)) { 422 throw %make_range_error(kTypedArraySetSourceTooLarge); 423 } 424 TypedArraySetFromArrayLike(this, obj, l, intOffset); 425 return; 426 } 427} 428%FunctionSetLength(TypedArraySet, 1); 429 430function TypedArrayGetToStringTag() { 431 if (!IS_TYPEDARRAY(this)) return; 432 var name = %_ClassOf(this); 433 if (IS_UNDEFINED(name)) return; 434 return name; 435} 436 437 438// ES6 draft 05-05-15, section 22.2.3.7 439function TypedArrayEvery(f, receiver) { 440 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 441 442 var length = %_TypedArrayGetLength(this); 443 444 return InnerArrayEvery(f, receiver, this, length); 445} 446%FunctionSetLength(TypedArrayEvery, 1); 447 448 449// ES6 draft 08-24-14, section 22.2.3.12 450function TypedArrayForEach(f, receiver) { 451 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 452 453 var length = %_TypedArrayGetLength(this); 454 455 InnerArrayForEach(f, receiver, this, length); 456} 457%FunctionSetLength(TypedArrayForEach, 1); 458 459 460// ES6 draft 04-05-14 section 22.2.3.8 461function TypedArrayFill(value, start, end) { 462 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 463 464 var length = %_TypedArrayGetLength(this); 465 466 return InnerArrayFill(value, start, end, this, length); 467} 468%FunctionSetLength(TypedArrayFill, 1); 469 470 471// ES6 draft 07-15-13, section 22.2.3.9 472function TypedArrayFilter(f, thisArg) { 473 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 474 475 var length = %_TypedArrayGetLength(this); 476 if (!IS_CALLABLE(f)) throw %make_type_error(kCalledNonCallable, f); 477 var result = new InternalArray(); 478 InnerArrayFilter(f, thisArg, this, length, result); 479 var captured = result.length; 480 var output = TypedArraySpeciesCreate(this, captured); 481 for (var i = 0; i < captured; i++) { 482 output[i] = result[i]; 483 } 484 return output; 485} 486%FunctionSetLength(TypedArrayFilter, 1); 487 488 489// ES6 draft 07-15-13, section 22.2.3.10 490function TypedArrayFind(predicate, thisArg) { 491 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 492 493 var length = %_TypedArrayGetLength(this); 494 495 return InnerArrayFind(predicate, thisArg, this, length); 496} 497%FunctionSetLength(TypedArrayFind, 1); 498 499 500// ES6 draft 07-15-13, section 22.2.3.11 501function TypedArrayFindIndex(predicate, thisArg) { 502 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 503 504 var length = %_TypedArrayGetLength(this); 505 506 return InnerArrayFindIndex(predicate, thisArg, this, length); 507} 508%FunctionSetLength(TypedArrayFindIndex, 1); 509 510 511// ES6 draft 05-18-15, section 22.2.3.21 512function TypedArrayReverse() { 513 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 514 515 var length = %_TypedArrayGetLength(this); 516 517 return PackedArrayReverse(this, length); 518} 519 520// ES6 draft 05-18-15, section 22.2.3.25 521function TypedArraySort(comparefn) { 522 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 523 524 var length = %_TypedArrayGetLength(this); 525 526 if (IS_UNDEFINED(comparefn)) { 527 return %TypedArraySortFast(this); 528 } 529 530 return InnerArraySort(this, length, comparefn); 531} 532 533 534// ES6 section 22.2.3.13 535function TypedArrayIndexOf(element, index) { 536 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 537 538 var length = %_TypedArrayGetLength(this); 539 540 if (length === 0) return -1; 541 if (!IS_NUMBER(element)) return -1; 542 var n = TO_INTEGER(index); 543 544 var k; 545 if (n === 0) { 546 k = 0; 547 } else if (n > 0) { 548 k = n; 549 } else { 550 k = length + n; 551 if (k < 0) { 552 k = 0; 553 } 554 } 555 556 while (k < length) { 557 var elementK = this[k]; 558 if (element === elementK) { 559 return k; 560 } 561 ++k; 562 } 563 return -1; 564} 565%FunctionSetLength(TypedArrayIndexOf, 1); 566 567 568// ES6 section 22.2.3.16 569function TypedArrayLastIndexOf(element, index) { 570 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 571 572 var length = %_TypedArrayGetLength(this); 573 574 if (length === 0) return -1; 575 if (!IS_NUMBER(element)) return -1; 576 var n; 577 if (arguments.length < 2) { 578 n = length - 1; 579 } else { 580 n = TO_INTEGER(index); 581 } 582 583 var k; 584 if (n >= 0) { 585 if (length <= n) { 586 k = length - 1; 587 } else if (n === 0) { 588 k = 0; 589 } else { 590 k = n; 591 } 592 } else { 593 k = length + n; 594 } 595 596 while (k >= 0) { 597 var elementK = this[k]; 598 if (element === elementK) { 599 return k; 600 } 601 --k; 602 } 603 return -1; 604} 605%FunctionSetLength(TypedArrayLastIndexOf, 1); 606 607 608// ES6 draft 07-15-13, section 22.2.3.18 609function TypedArrayMap(f, thisArg) { 610 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 611 612 var length = %_TypedArrayGetLength(this); 613 var result = TypedArraySpeciesCreate(this, length); 614 if (!IS_CALLABLE(f)) throw %make_type_error(kCalledNonCallable, f); 615 for (var i = 0; i < length; i++) { 616 var element = this[i]; 617 result[i] = %_Call(f, thisArg, element, i, this); 618 } 619 return result; 620} 621%FunctionSetLength(TypedArrayMap, 1); 622 623 624// ES6 draft 05-05-15, section 22.2.3.24 625function TypedArraySome(f, receiver) { 626 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 627 628 var length = %_TypedArrayGetLength(this); 629 630 return InnerArraySome(f, receiver, this, length); 631} 632%FunctionSetLength(TypedArraySome, 1); 633 634 635// ES6 section 22.2.3.27 636function TypedArrayToLocaleString() { 637 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 638 639 var length = %_TypedArrayGetLength(this); 640 641 return InnerArrayToLocaleString(this, length); 642} 643 644 645// ES6 section 22.2.3.14 646function TypedArrayJoin(separator) { 647 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 648 649 var length = %_TypedArrayGetLength(this); 650 651 return InnerArrayJoin(separator, this, length); 652} 653 654 655// ES6 draft 07-15-13, section 22.2.3.19 656function TypedArrayReduce(callback, current) { 657 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 658 659 var length = %_TypedArrayGetLength(this); 660 return InnerArrayReduce(callback, current, this, length, 661 arguments.length); 662} 663%FunctionSetLength(TypedArrayReduce, 1); 664 665 666// ES6 draft 07-15-13, section 22.2.3.19 667function TypedArrayReduceRight(callback, current) { 668 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 669 670 var length = %_TypedArrayGetLength(this); 671 return InnerArrayReduceRight(callback, current, this, length, 672 arguments.length); 673} 674%FunctionSetLength(TypedArrayReduceRight, 1); 675 676 677function TypedArraySlice(start, end) { 678 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 679 var len = %_TypedArrayGetLength(this); 680 681 var relativeStart = TO_INTEGER(start); 682 683 var k; 684 if (relativeStart < 0) { 685 k = MaxSimple(len + relativeStart, 0); 686 } else { 687 k = MinSimple(relativeStart, len); 688 } 689 690 var relativeEnd; 691 if (IS_UNDEFINED(end)) { 692 relativeEnd = len; 693 } else { 694 relativeEnd = TO_INTEGER(end); 695 } 696 697 var final; 698 if (relativeEnd < 0) { 699 final = MaxSimple(len + relativeEnd, 0); 700 } else { 701 final = MinSimple(relativeEnd, len); 702 } 703 704 var count = MaxSimple(final - k, 0); 705 var array = TypedArraySpeciesCreate(this, count); 706 // The code below is the 'then' branch; the 'else' branch species 707 // a memcpy. Because V8 doesn't canonicalize NaN, the difference is 708 // unobservable. 709 var n = 0; 710 while (k < final) { 711 var kValue = this[k]; 712 array[n] = kValue; 713 k++; 714 n++; 715 } 716 return array; 717} 718 719 720// ES2016 draft, section 22.2.3.14 721function TypedArrayIncludes(searchElement, fromIndex) { 722 if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray); 723 724 var length = %_TypedArrayGetLength(this); 725 726 if (length === 0) return false; 727 var n = TO_INTEGER(fromIndex); 728 729 var k; 730 if (n >= 0) { 731 k = n; 732 } else { 733 k = length + n; 734 if (k < 0) { 735 k = 0; 736 } 737 } 738 739 while (k < length) { 740 var elementK = this[k]; 741 if (%SameValueZero(searchElement, elementK)) { 742 return true; 743 } 744 745 ++k; 746 } 747 748 return false; 749} 750%FunctionSetLength(TypedArrayIncludes, 1); 751 752 753// ES6 draft 08-24-14, section 22.2.2.2 754function TypedArrayOf() { 755 var length = arguments.length; 756 var array = TypedArrayCreate(this, length); 757 for (var i = 0; i < length; i++) { 758 array[i] = arguments[i]; 759 } 760 return array; 761} 762 763 764// 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 ] ] ) 785function TypedArrayFrom(source, mapfn, thisArg) { 786 if (!%IsConstructor(this)) throw %make_type_error(kNotConstructor, this); 787 var mapping; 788 if (!IS_UNDEFINED(mapfn)) { 789 if (!IS_CALLABLE(mapfn)) throw %make_type_error(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; 808} 809%FunctionSetLength(TypedArrayFrom, 1); 810 811// TODO(bmeurer): Migrate this to a proper builtin. 812function TypedArrayConstructor() { 813 throw %make_type_error(kConstructAbstractClass, "TypedArray"); 814} 815 816// ------------------------------------------------------------------- 817 818%SetCode(GlobalTypedArray, TypedArrayConstructor); 819utils.InstallFunctions(GlobalTypedArray, DONT_ENUM, [ 820 "from", TypedArrayFrom, 821 "of", TypedArrayOf 822]); 823utils.InstallGetter(GlobalTypedArray.prototype, toStringTagSymbol, 824 TypedArrayGetToStringTag); 825utils.InstallFunctions(GlobalTypedArray.prototype, DONT_ENUM, [ 826 "subarray", TypedArraySubArray, 827 "set", TypedArraySet, 828 "every", TypedArrayEvery, 829 "fill", TypedArrayFill, 830 "filter", TypedArrayFilter, 831 "find", TypedArrayFind, 832 "findIndex", TypedArrayFindIndex, 833 "includes", TypedArrayIncludes, 834 "indexOf", TypedArrayIndexOf, 835 "join", TypedArrayJoin, 836 "lastIndexOf", TypedArrayLastIndexOf, 837 "forEach", TypedArrayForEach, 838 "map", TypedArrayMap, 839 "reduce", TypedArrayReduce, 840 "reduceRight", TypedArrayReduceRight, 841 "reverse", TypedArrayReverse, 842 "slice", TypedArraySlice, 843 "some", TypedArraySome, 844 "sort", TypedArraySort, 845 "toLocaleString", TypedArrayToLocaleString 846]); 847 848%AddNamedProperty(GlobalTypedArray.prototype, "toString", ArrayToString, 849 DONT_ENUM); 850 851 852macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE) 853 %SetCode(GlobalNAME, NAMEConstructor); 854 %FunctionSetPrototype(GlobalNAME, new GlobalObject()); 855 %InternalSetPrototype(GlobalNAME, GlobalTypedArray); 856 %InternalSetPrototype(GlobalNAME.prototype, GlobalTypedArray.prototype); 857 858 %AddNamedProperty(GlobalNAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE, 859 READ_ONLY | DONT_ENUM | DONT_DELETE); 860 861 %AddNamedProperty(GlobalNAME.prototype, 862 "constructor", global.NAME, DONT_ENUM); 863 %AddNamedProperty(GlobalNAME.prototype, 864 "BYTES_PER_ELEMENT", ELEMENT_SIZE, 865 READ_ONLY | DONT_ENUM | DONT_DELETE); 866endmacro 867 868TYPED_ARRAYS(SETUP_TYPED_ARRAY) 869 870}) 871