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