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