TypedArray.js (30968B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "TypedArrayConstants.h" 6 7 function ViewedArrayBufferIfReified(tarray) { 8 assert(IsTypedArray(tarray), "non-typed array asked for its buffer"); 9 10 var buf = UnsafeGetReservedSlot(tarray, JS_TYPEDARRAYLAYOUT_BUFFER_SLOT); 11 assert( 12 buf === false || 13 buf === true || 14 (IsObject(buf) && 15 (GuardToArrayBuffer(buf) !== null || 16 GuardToSharedArrayBuffer(buf) !== null)), 17 "unexpected value in buffer slot" 18 ); 19 return IsObject(buf) ? buf : null; 20 } 21 22 function GetArrayBufferFlagsOrZero(buffer) { 23 // A typed array with a null buffer has never had its buffer exposed. Return 24 // the default flags, which is zero. 25 if (buffer === null) { 26 return 0; 27 } 28 29 assert( 30 GuardToArrayBuffer(buffer) !== null || 31 GuardToSharedArrayBuffer(buffer) !== null, 32 "non-ArrayBuffer passed to IsDetachedBuffer" 33 ); 34 35 // Return zero for shared array buffers. 36 if ((buffer = GuardToArrayBuffer(buffer)) === null) { 37 return 0; 38 } 39 40 return UnsafeGetInt32FromReservedSlot(buffer, JS_ARRAYBUFFER_FLAGS_SLOT); 41 } 42 43 function EnsureAttachedArrayBuffer(tarray) { 44 var buffer = ViewedArrayBufferIfReified(tarray); 45 var flags = GetArrayBufferFlagsOrZero(buffer); 46 if ((flags & JS_ARRAYBUFFER_DETACHED_FLAG) !== 0) { 47 ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); 48 } 49 } 50 51 function EnsureAttachedMutableArrayBuffer(tarray) { 52 var buffer = ViewedArrayBufferIfReified(tarray); 53 var flags = GetArrayBufferFlagsOrZero(buffer); 54 if ((flags & JS_ARRAYBUFFER_DETACHED_FLAG) !== 0) { 55 ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); 56 } 57 58 // Additional step from Immutable ArrayBuffer proposal. 59 if ((flags & JS_ARRAYBUFFER_IMMUTABLE_FLAG) !== 0) { 60 ThrowTypeError(JSMSG_ARRAYBUFFER_IMMUTABLE); 61 } 62 } 63 64 function EnsureAttachedArrayBufferMethod() { 65 EnsureAttachedArrayBuffer(this); 66 } 67 68 // A function which ensures that the argument is either a typed array or a 69 // cross-compartment wrapper for a typed array and that the typed array involved 70 // has an attached array buffer. If one of those conditions doesn't hold (wrong 71 // kind of argument, or detached array buffer), an exception is thrown. 72 function EnsureTypedArrayWithArrayBuffer(arg) { 73 if (IsObject(arg) && IsTypedArray(arg)) { 74 EnsureAttachedArrayBuffer(arg); 75 return; 76 } 77 78 callFunction( 79 CallTypedArrayMethodIfWrapped, 80 arg, 81 "EnsureAttachedArrayBufferMethod" 82 ); 83 } 84 85 // ES2019 draft rev 85ce767c86a1a8ed719fe97e978028bff819d1f2 86 // 7.3.20 SpeciesConstructor ( O, defaultConstructor ) 87 // 88 // SpeciesConstructor function optimized for TypedArrays to avoid calling 89 // ConstructorForTypedArray, a non-inlineable runtime function, in the normal 90 // case. 91 function TypedArraySpeciesConstructor(obj) { 92 // Step 1. 93 assert(IsObject(obj), "not passed an object"); 94 95 // Step 2. 96 var ctor = obj.constructor; 97 98 // Step 3. 99 if (ctor === undefined) { 100 return ConstructorForTypedArray(obj); 101 } 102 103 // Step 4. 104 if (!IsObject(ctor)) { 105 ThrowTypeError(JSMSG_OBJECT_REQUIRED, "object's 'constructor' property"); 106 } 107 108 // Steps 5. 109 var s = ctor[GetBuiltinSymbol("species")]; 110 111 // Step 6. 112 if (IsNullOrUndefined(s)) { 113 return ConstructorForTypedArray(obj); 114 } 115 116 // Step 7. 117 if (IsConstructor(s)) { 118 return s; 119 } 120 121 // Step 8. 122 ThrowTypeError( 123 JSMSG_NOT_CONSTRUCTOR, 124 "@@species property of object's constructor" 125 ); 126 } 127 128 // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 129 // 22.2.3.5.1 Runtime Semantics: ValidateTypedArray ( O ) 130 function ValidateWritableTypedArray(obj) { 131 if (IsObject(obj)) { 132 /* Steps 3-5 (non-wrapped typed arrays). */ 133 if (IsTypedArray(obj)) { 134 // EnsureAttachedMutableArrayBuffer throws for detached or immutable 135 // array buffers. 136 EnsureAttachedMutableArrayBuffer(obj); 137 return; 138 } 139 140 /* Steps 3-5 (wrapped typed arrays). */ 141 if (IsPossiblyWrappedTypedArray(obj)) { 142 if (PossiblyWrappedTypedArrayHasDetachedBuffer(obj)) { 143 ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); 144 } 145 if (PossiblyWrappedTypedArrayHasImmutableBuffer(obj)) { 146 ThrowTypeError(JSMSG_ARRAYBUFFER_IMMUTABLE); 147 } 148 return; 149 } 150 } 151 152 /* Steps 1-2. */ 153 ThrowTypeError(JSMSG_NON_TYPED_ARRAY_RETURNED); 154 } 155 156 // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 157 // 22.2.4.6 TypedArrayCreate ( constructor, argumentList ) 158 function TypedArrayCreateWithLength(constructor, length) { 159 // Step 1. 160 var newTypedArray = constructContentFunction( 161 constructor, 162 constructor, 163 length 164 ); 165 166 // Step 2. 167 ValidateWritableTypedArray(newTypedArray); 168 169 // Step 3. 170 var len = PossiblyWrappedTypedArrayLength(newTypedArray); 171 172 if (len < length) { 173 ThrowTypeError(JSMSG_SHORT_TYPED_ARRAY_RETURNED, length, len); 174 } 175 176 // Step 4. 177 return newTypedArray; 178 } 179 180 // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 181 // 22.2.4.7 TypedArraySpeciesCreate ( exemplar, argumentList ) 182 function TypedArraySpeciesCreateWithLength(exemplar, length) { 183 // Step 1 (omitted). 184 185 // Steps 2-3. 186 var C = TypedArraySpeciesConstructor(exemplar); 187 188 // Step 4. 189 return TypedArrayCreateWithLength(C, length); 190 } 191 192 // ES6 draft rev30 (2014/12/24) 22.2.3.6 %TypedArray%.prototype.entries() 193 function TypedArrayEntries() { 194 // Step 1. 195 var O = this; 196 197 // We need to be a bit careful here, because in the Xray case we want to 198 // create the iterator in our current compartment. 199 // 200 // Before doing that, though, we want to check that we have a typed array 201 // and it does not have a detached array buffer. We do the latter by just 202 // calling EnsureAttachedArrayBuffer() and letting it throw if there isn't one. 203 // In the case when we're not sure we have a typed array (e.g. we might have 204 // a cross-compartment wrapper for one), we can go ahead and call 205 // EnsureAttachedArrayBuffer via EnsureTypedArrayWithArrayBuffer; that will 206 // throw if we're not actually a wrapped typed array, or if we have a 207 // detached array buffer. 208 209 // Step 2-6. 210 EnsureTypedArrayWithArrayBuffer(O); 211 212 // We also need to make sure the length is in-bounds. This is checked by 213 // calling PossiblyWrappedTypedArrayLength, which throws for out-of-bounds. 214 PossiblyWrappedTypedArrayLength(O); 215 216 // Step 7. 217 RETURN_ARRAY_ITERATOR(O, ITEM_KIND_KEY_AND_VALUE); 218 } 219 220 // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 221 // Plus <https://github.com/tc39/ecma262/pull/2221> 222 // 22.2.3.7 %TypedArray%.prototype.every ( callbackfn [ , thisArg ] ) 223 function TypedArrayEvery(callbackfn /*, thisArg*/) { 224 // Step 1. 225 var O = this; 226 227 // Step 2. 228 EnsureTypedArrayWithArrayBuffer(O); 229 230 // If we got here, `this` is either a typed array or a wrapper for one. 231 232 // Step 3. 233 var len = PossiblyWrappedTypedArrayLength(O); 234 235 // Step 4. 236 if (ArgumentsLength() === 0) { 237 ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.every"); 238 } 239 if (!IsCallable(callbackfn)) { 240 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 241 } 242 243 var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; 244 245 // Steps 5-6. 246 for (var k = 0; k < len; k++) { 247 // Steps 6.b-d. 248 var kValue = O[k]; 249 250 // Step 6.c. 251 var testResult = callContentFunction(callbackfn, thisArg, kValue, k, O); 252 253 // Step 6.d. 254 if (!testResult) { 255 return false; 256 } 257 } 258 259 // Step 7. 260 return true; 261 } 262 // Inlining this enables inlining of the callback function. 263 SetIsInlinableLargeFunction(TypedArrayEvery); 264 265 // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 266 // %TypedArray%.prototype.filter ( callbackfn [ , thisArg ] ) 267 function TypedArrayFilter(callbackfn /*, thisArg*/) { 268 // Step 1. 269 var O = this; 270 271 // Step 2. 272 // This function is not generic. 273 // We want to make sure that we have an attached buffer, per spec prose. 274 EnsureTypedArrayWithArrayBuffer(O); 275 276 // If we got here, `this` is either a typed array or a wrapper for one. 277 278 // Step 3. 279 var len = PossiblyWrappedTypedArrayLength(O); 280 281 // Step 4. 282 if (ArgumentsLength() === 0) { 283 ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.filter"); 284 } 285 if (!IsCallable(callbackfn)) { 286 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 287 } 288 289 // Step 5. 290 var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined; 291 292 // Step 6. 293 var kept = new_List(); 294 295 // Step 8. 296 var captured = 0; 297 298 // Steps 7 and 9.e. 299 for (var k = 0; k < len; k++) { 300 // Steps 9.a-b. 301 var kValue = O[k]; 302 303 // Steps 9.c-d. 304 if (callContentFunction(callbackfn, T, kValue, k, O)) { 305 // Steps 9.d.i-ii. 306 kept[captured++] = kValue; 307 } 308 } 309 310 // Step 10. 311 var A = TypedArraySpeciesCreateWithLength(O, captured); 312 313 // Steps 11 and 12.b. 314 for (var n = 0; n < captured; n++) { 315 // Step 12.a. 316 A[n] = kept[n]; 317 } 318 319 // Step 13. 320 return A; 321 } 322 // Inlining this enables inlining of the callback function. 323 SetIsInlinableLargeFunction(TypedArrayFilter); 324 325 // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 326 // Plus <https://github.com/tc39/ecma262/pull/2221> 327 // 22.2.3.10 %TypedArray%.prototype.find ( predicate [ , thisArg ] ) 328 function TypedArrayFind(predicate /*, thisArg*/) { 329 // Step 1. 330 var O = this; 331 332 // Step 2. 333 EnsureTypedArrayWithArrayBuffer(O); 334 335 // If we got here, `this` is either a typed array or a wrapper for one. 336 337 // Step 3. 338 var len = PossiblyWrappedTypedArrayLength(O); 339 340 // Step 4. 341 if (ArgumentsLength() === 0) { 342 ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.find"); 343 } 344 if (!IsCallable(predicate)) { 345 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate)); 346 } 347 348 var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; 349 350 // Steps 5-6. 351 for (var k = 0; k < len; k++) { 352 // Steps 6.a-b. 353 var kValue = O[k]; 354 355 // Steps 6.c-d. 356 if (callContentFunction(predicate, thisArg, kValue, k, O)) { 357 return kValue; 358 } 359 } 360 361 // Step 7. 362 return undefined; 363 } 364 // Inlining this enables inlining of the callback function. 365 SetIsInlinableLargeFunction(TypedArrayFind); 366 367 // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 368 // Plus <https://github.com/tc39/ecma262/pull/2221> 369 // 22.2.3.11 %TypedArray%.prototype.findIndex ( predicate [ , thisArg ] ) 370 function TypedArrayFindIndex(predicate /*, thisArg*/) { 371 // Step 1. 372 var O = this; 373 374 // Step 2. 375 EnsureTypedArrayWithArrayBuffer(O); 376 377 // If we got here, `this` is either a typed array or a wrapper for one. 378 379 // Step 3. 380 var len = PossiblyWrappedTypedArrayLength(O); 381 382 // Step 4. 383 if (ArgumentsLength() === 0) { 384 ThrowTypeError( 385 JSMSG_MISSING_FUN_ARG, 386 0, 387 "%TypedArray%.prototype.findIndex" 388 ); 389 } 390 if (!IsCallable(predicate)) { 391 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate)); 392 } 393 394 var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; 395 396 // Steps 5-6. 397 for (var k = 0; k < len; k++) { 398 // Steps 6.a-f. 399 if (callContentFunction(predicate, thisArg, O[k], k, O)) { 400 return k; 401 } 402 } 403 404 // Step 7. 405 return -1; 406 } 407 // Inlining this enables inlining of the callback function. 408 SetIsInlinableLargeFunction(TypedArrayFindIndex); 409 410 // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 411 // Plus <https://github.com/tc39/ecma262/pull/2221> 412 // 22.2.3.12 %TypedArray%.prototype.forEach ( callbackfn [ , thisArg ] ) 413 function TypedArrayForEach(callbackfn /*, thisArg*/) { 414 // Step 1. 415 var O = this; 416 417 // Step 2. 418 EnsureTypedArrayWithArrayBuffer(O); 419 420 // If we got here, `this` is either a typed array or a wrapper for one. 421 422 // Step 3. 423 var len = PossiblyWrappedTypedArrayLength(O); 424 425 // Step 4. 426 if (ArgumentsLength() === 0) { 427 ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "TypedArray.prototype.forEach"); 428 } 429 if (!IsCallable(callbackfn)) { 430 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 431 } 432 433 var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; 434 435 // Steps 5-6. 436 for (var k = 0; k < len; k++) { 437 // Steps 6.a-c. 438 callContentFunction(callbackfn, thisArg, O[k], k, O); 439 } 440 441 // Step 7. 442 return undefined; 443 } 444 // Inlining this enables inlining of the callback function. 445 SetIsInlinableLargeFunction(TypedArrayForEach); 446 447 // ES6 draft (2016/1/11) 22.2.3.15 %TypedArray%.prototype.keys() 448 function TypedArrayKeys() { 449 // Step 1. 450 var O = this; 451 452 // See the big comment in TypedArrayEntries for what we're doing here. 453 454 // Step 2. 455 EnsureTypedArrayWithArrayBuffer(O); 456 PossiblyWrappedTypedArrayLength(O); 457 458 // Step 3. 459 RETURN_ARRAY_ITERATOR(O, ITEM_KIND_KEY); 460 } 461 462 // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 463 // 22.2.3.19 %TypedArray%.prototype.map ( callbackfn [ , thisArg ] ) 464 function TypedArrayMap(callbackfn /*, thisArg*/) { 465 // Step 1. 466 var O = this; 467 468 // Step 2. 469 // This function is not generic. 470 // We want to make sure that we have an attached buffer, per spec prose. 471 EnsureTypedArrayWithArrayBuffer(O); 472 473 // If we got here, `this` is either a typed array or a wrapper for one. 474 475 // Step 3. 476 var len = PossiblyWrappedTypedArrayLength(O); 477 478 // Step 4. 479 if (ArgumentsLength() === 0) { 480 ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.map"); 481 } 482 if (!IsCallable(callbackfn)) { 483 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 484 } 485 486 // Step 5. 487 var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined; 488 489 // Step 6. 490 var A = TypedArraySpeciesCreateWithLength(O, len); 491 492 // Steps 7, 8.a (implicit) and 8.e. 493 for (var k = 0; k < len; k++) { 494 // Steps 8.b-c. 495 var mappedValue = callContentFunction(callbackfn, T, O[k], k, O); 496 497 // Steps 8.d. 498 A[k] = mappedValue; 499 } 500 501 // Step 9. 502 return A; 503 } 504 // Inlining this enables inlining of the callback function. 505 SetIsInlinableLargeFunction(TypedArrayMap); 506 507 // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 508 // Plus <https://github.com/tc39/ecma262/pull/2221> 509 // 22.2.3.20 %TypedArray%.prototype.reduce ( callbackfn [ , initialValue ] ) 510 function TypedArrayReduce(callbackfn /*, initialValue*/) { 511 // Step 1. 512 var O = this; 513 514 // Step 2. 515 EnsureTypedArrayWithArrayBuffer(O); 516 517 // If we got here, `this` is either a typed array or a wrapper for one. 518 519 // Step 3. 520 var len = PossiblyWrappedTypedArrayLength(O); 521 522 // Step 4. 523 if (ArgumentsLength() === 0) { 524 ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.reduce"); 525 } 526 if (!IsCallable(callbackfn)) { 527 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 528 } 529 530 // Step 5. 531 if (len === 0 && ArgumentsLength() === 1) { 532 ThrowTypeError(JSMSG_EMPTY_ARRAY_REDUCE); 533 } 534 535 // Step 6. 536 var k = 0; 537 538 // Steps 7-9. 539 var accumulator = ArgumentsLength() > 1 ? GetArgument(1) : O[k++]; 540 541 // Step 10. 542 for (; k < len; k++) { 543 accumulator = callContentFunction( 544 callbackfn, 545 undefined, 546 accumulator, 547 O[k], 548 k, 549 O 550 ); 551 } 552 553 // Step 11. 554 return accumulator; 555 } 556 557 // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 558 // Plus <https://github.com/tc39/ecma262/pull/2221> 559 // 22.2.3.21 %TypedArray%.prototype.reduceRight ( callbackfn [ , initialValue ] ) 560 function TypedArrayReduceRight(callbackfn /*, initialValue*/) { 561 // Step 1. 562 var O = this; 563 564 // Step 2. 565 EnsureTypedArrayWithArrayBuffer(O); 566 567 // If we got here, `this` is either a typed array or a wrapper for one. 568 569 // Step 3. 570 var len = PossiblyWrappedTypedArrayLength(O); 571 572 // Step 4. 573 if (ArgumentsLength() === 0) { 574 ThrowTypeError( 575 JSMSG_MISSING_FUN_ARG, 576 0, 577 "%TypedArray%.prototype.reduceRight" 578 ); 579 } 580 if (!IsCallable(callbackfn)) { 581 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 582 } 583 584 // Step 5. 585 if (len === 0 && ArgumentsLength() === 1) { 586 ThrowTypeError(JSMSG_EMPTY_ARRAY_REDUCE); 587 } 588 589 // Step 6. 590 var k = len - 1; 591 592 // Steps 7-9. 593 var accumulator = ArgumentsLength() > 1 ? GetArgument(1) : O[k--]; 594 595 // Step 10. 596 for (; k >= 0; k--) { 597 accumulator = callContentFunction( 598 callbackfn, 599 undefined, 600 accumulator, 601 O[k], 602 k, 603 O 604 ); 605 } 606 607 // Step 11. 608 return accumulator; 609 } 610 611 // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 612 // Plus <https://github.com/tc39/ecma262/pull/2221> 613 // 22.2.3.25 %TypedArray%.prototype.some ( callbackfn [ , thisArg ] ) 614 function TypedArraySome(callbackfn /*, thisArg*/) { 615 // Step 1. 616 var O = this; 617 618 // Step 2. 619 EnsureTypedArrayWithArrayBuffer(O); 620 621 // If we got here, `this` is either a typed array or a wrapper for one. 622 623 // Step 3. 624 var len = PossiblyWrappedTypedArrayLength(O); 625 626 // Step 4. 627 if (ArgumentsLength() === 0) { 628 ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.some"); 629 } 630 if (!IsCallable(callbackfn)) { 631 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); 632 } 633 634 var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; 635 636 // Steps 5-6. 637 for (var k = 0; k < len; k++) { 638 // Steps 6.a-b. 639 var kValue = O[k]; 640 641 // Step 6.c. 642 var testResult = callContentFunction(callbackfn, thisArg, kValue, k, O); 643 644 // Step 6.d. 645 if (testResult) { 646 return true; 647 } 648 } 649 650 // Step 7. 651 return false; 652 } 653 // Inlining this enables inlining of the callback function. 654 SetIsInlinableLargeFunction(TypedArraySome); 655 656 // ES2017 draft rev f8a9be8ea4bd97237d176907a1e3080dce20c68f 657 // 22.2.3.28 %TypedArray%.prototype.toLocaleString ([ reserved1 [ , reserved2 ] ]) 658 // ES2017 Intl draft rev 78bbe7d1095f5ff3760ac4017ed366026e4cb276 659 // 13.4.1 Array.prototype.toLocaleString ([ locales [ , options ]]) 660 function TypedArrayToLocaleString(locales = undefined, options = undefined) { 661 // ValidateTypedArray, then step 1. 662 var array = this; 663 664 // This function is not generic. 665 // We want to make sure that we have an attached buffer, per spec prose. 666 EnsureTypedArrayWithArrayBuffer(array); 667 668 // If we got here, `this` is either a typed array or a wrapper for one. 669 670 // Step 2. 671 var len = PossiblyWrappedTypedArrayLength(array); 672 673 // Step 4. 674 if (len === 0) { 675 return ""; 676 } 677 678 // Step 5. 679 var firstElement = array[0]; 680 assert( 681 typeof firstElement === "number" || typeof firstElement === "bigint", 682 "TypedArray elements are either Numbers or BigInts" 683 ); 684 685 // Steps 6-7. 686 // Omit the 'if' clause in step 6, since non-empty typed arrays can't have 687 // undefined or null elements. 688 #if JS_HAS_INTL_API 689 var R = ToString( 690 callContentFunction( 691 firstElement.toLocaleString, 692 firstElement, 693 locales, 694 options 695 ) 696 ); 697 #else 698 var R = ToString( 699 callContentFunction(firstElement.toLocaleString, firstElement) 700 ); 701 #endif 702 703 // Step 3 (reordered). 704 // We don't (yet?) implement locale-dependent separators. 705 var separator = ","; 706 707 // Steps 8-9. 708 for (var k = 1; k < len; k++) { 709 // Step 9.a. 710 R += separator; 711 712 // Step 9.b. 713 var nextElement = array[k]; 714 715 // Step 9.c. 716 if (nextElement === undefined) { 717 continue; 718 } 719 assert( 720 typeof nextElement === "number" || typeof nextElement === "bigint", 721 "TypedArray elements are either Numbers or BigInts" 722 ); 723 724 // Steps 9.d-e. 725 #if JS_HAS_INTL_API 726 R += ToString( 727 callContentFunction( 728 nextElement.toLocaleString, 729 nextElement, 730 locales, 731 options 732 ) 733 ); 734 #else 735 R += ToString(callContentFunction(nextElement.toLocaleString, nextElement)); 736 #endif 737 } 738 739 // Step 10. 740 return R; 741 } 742 743 // https://tc39.es/proposal-relative-indexing-method 744 // %TypedArray%.prototype.at ( index ) 745 function TypedArrayAt(index) { 746 // Step 1. 747 var obj = this; 748 749 // Step 2. 750 // This function is not generic. 751 if (!IsObject(obj) || !IsTypedArray(obj)) { 752 return callFunction( 753 CallTypedArrayMethodIfWrapped, 754 obj, 755 index, 756 "TypedArrayAt" 757 ); 758 } 759 EnsureAttachedArrayBuffer(obj); 760 761 // Step 3. 762 var len = TypedArrayLength(obj); 763 764 // Step 4. 765 var relativeIndex = ToInteger(index); 766 767 // Steps 5-6. 768 var k; 769 if (relativeIndex >= 0) { 770 k = relativeIndex; 771 } else { 772 k = len + relativeIndex; 773 } 774 775 // Step 7. 776 if (k < 0 || k >= len) { 777 return undefined; 778 } 779 780 // Step 8. 781 return obj[k]; 782 } 783 // This function is only barely too long for normal inlining. 784 SetIsInlinableLargeFunction(TypedArrayAt); 785 786 // https://github.com/tc39/proposal-array-find-from-last 787 // %TypedArray%.prototype.findLast ( predicate, thisArg ) 788 function TypedArrayFindLast(predicate /*, thisArg*/) { 789 // Step 1. 790 var O = this; 791 792 // Step 2. 793 EnsureTypedArrayWithArrayBuffer(O); 794 795 // If we got here, `this` is either a typed array or a wrapper for one. 796 797 // Step 3. 798 var len = PossiblyWrappedTypedArrayLength(O); 799 800 // Step 4. 801 if (ArgumentsLength() === 0) { 802 ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.findLast"); 803 } 804 if (!IsCallable(predicate)) { 805 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate)); 806 } 807 808 var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; 809 810 // Steps 5-6. 811 for (var k = len - 1; k >= 0; k--) { 812 // Steps 6.a-b. 813 var kValue = O[k]; 814 815 // Steps 6.c-d. 816 if (callContentFunction(predicate, thisArg, kValue, k, O)) { 817 return kValue; 818 } 819 } 820 821 // Step 7. 822 return undefined; 823 } 824 // Inlining this enables inlining of the callback function. 825 SetIsInlinableLargeFunction(TypedArrayFindLast); 826 827 // https://github.com/tc39/proposal-array-find-from-last 828 // %TypedArray%.prototype.findLastIndex ( predicate, thisArg ) 829 function TypedArrayFindLastIndex(predicate /*, thisArg*/) { 830 // Step 1. 831 var O = this; 832 833 // Step 2. 834 EnsureTypedArrayWithArrayBuffer(O); 835 836 // If we got here, `this` is either a typed array or a wrapper for one. 837 838 // Step 3. 839 var len = PossiblyWrappedTypedArrayLength(O); 840 841 // Step 4. 842 if (ArgumentsLength() === 0) { 843 ThrowTypeError( 844 JSMSG_MISSING_FUN_ARG, 845 0, 846 "%TypedArray%.prototype.findLastIndex" 847 ); 848 } 849 if (!IsCallable(predicate)) { 850 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate)); 851 } 852 853 var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; 854 855 // Steps 5-6. 856 for (var k = len - 1; k >= 0; k--) { 857 // Steps 6.a-f. 858 if (callContentFunction(predicate, thisArg, O[k], k, O)) { 859 return k; 860 } 861 } 862 863 // Step 7. 864 return -1; 865 } 866 // Inlining this enables inlining of the callback function. 867 SetIsInlinableLargeFunction(TypedArrayFindLastIndex); 868 869 // ES6 draft rev30 (2014/12/24) 22.2.3.30 %TypedArray%.prototype.values() 870 // 871 // Uncloned functions with `$` prefix are allocated as extended function 872 // to store the original name in `SetCanonicalName`. 873 function $TypedArrayValues() { 874 // Step 1. 875 var O = this; 876 877 // See the big comment in TypedArrayEntries for what we're doing here. 878 EnsureTypedArrayWithArrayBuffer(O); 879 PossiblyWrappedTypedArrayLength(O); 880 881 // Step 7. 882 RETURN_ARRAY_ITERATOR(O, ITEM_KIND_VALUE); 883 } 884 SetCanonicalName($TypedArrayValues, "values"); 885 886 // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 887 // 22.2.2.1 %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] ) 888 function TypedArrayStaticFrom(source, mapfn = undefined, thisArg = undefined) { 889 // Step 1. 890 var C = this; 891 892 // Step 2. 893 if (!IsConstructor(C)) { 894 ThrowTypeError(JSMSG_NOT_CONSTRUCTOR, typeof C); 895 } 896 897 // Step 3. 898 var mapping; 899 if (mapfn !== undefined) { 900 // Step 3.a. 901 if (!IsCallable(mapfn)) { 902 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, mapfn)); 903 } 904 905 // Step 3.b. 906 mapping = true; 907 } else { 908 // Step 4. 909 mapping = false; 910 } 911 912 // Step 5. 913 var T = thisArg; 914 915 // Step 6. 916 // Inlined: GetMethod, steps 1-2. 917 var usingIterator = source[GetBuiltinSymbol("iterator")]; 918 919 // Step 7. 920 // Inlined: GetMethod, step 3. 921 if (usingIterator !== undefined && usingIterator !== null) { 922 // Inlined: GetMethod, step 4. 923 if (!IsCallable(usingIterator)) { 924 ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, source)); 925 } 926 927 // Try to take a fast path when there's no mapper function and the 928 // constructor is a built-in TypedArray constructor. 929 if (!mapping && IsTypedArrayConstructor(C) && IsObject(source)) { 930 // The source is a TypedArray using the default iterator. 931 if ( 932 usingIterator === $TypedArrayValues && 933 IsTypedArray(source) && 934 ArrayIteratorPrototypeOptimizable() 935 ) { 936 // Step 7.a. 937 // Omitted but we still need to throw if |source| was detached. 938 EnsureAttachedArrayBuffer(source); 939 940 // Step 7.b. 941 var len = TypedArrayLength(source); 942 943 // Step 7.c. 944 var targetObj = constructContentFunction(C, C, len); 945 946 // Steps 7.d-f. 947 for (var k = 0; k < len; k++) { 948 targetObj[k] = source[k]; 949 } 950 951 // Step 7.g. 952 return targetObj; 953 } 954 955 // The source is a packed array using the default iterator. 956 if ( 957 usingIterator === $ArrayValues && 958 IsPackedArray(source) && 959 ArrayIteratorPrototypeOptimizable() 960 ) { 961 // Steps 7.b-c. 962 var targetObj = constructContentFunction(C, C, source.length); 963 964 // Steps 7.a, 7.d-f. 965 TypedArrayInitFromPackedArray(targetObj, source); 966 967 // Step 7.g. 968 return targetObj; 969 } 970 } 971 972 // Step 7.a. 973 var values = IterableToList(source, usingIterator); 974 975 // Step 7.b. 976 var len = values.length; 977 978 // Step 7.c. 979 var targetObj = TypedArrayCreateWithLength(C, len); 980 981 // Steps 7.d-e. 982 for (var k = 0; k < len; k++) { 983 // Step 7.e.ii. 984 var kValue = values[k]; 985 986 // Steps 7.e.iii-iv. 987 var mappedValue = mapping 988 ? callContentFunction(mapfn, T, kValue, k) 989 : kValue; 990 991 // Step 7.e.v. 992 targetObj[k] = mappedValue; 993 } 994 995 // Step 7.f. 996 // Asserting that `values` is empty here would require removing them one by one from 997 // the list's start in the loop above. That would introduce unacceptable overhead. 998 // Additionally, the loop's logic is simple enough not to require the assert. 999 1000 // Step 7.g. 1001 return targetObj; 1002 } 1003 1004 // Step 8 is an assertion: items is not an Iterator. Testing this is 1005 // literally the very last thing we did, so we don't assert here. 1006 1007 // Step 9. 1008 var arrayLike = ToObject(source); 1009 1010 // Step 10. 1011 var len = ToLength(arrayLike.length); 1012 1013 // Step 11. 1014 var targetObj = TypedArrayCreateWithLength(C, len); 1015 1016 // Steps 12-13. 1017 for (var k = 0; k < len; k++) { 1018 // Steps 13.a-b. 1019 var kValue = arrayLike[k]; 1020 1021 // Steps 13.c-d. 1022 var mappedValue = mapping 1023 ? callContentFunction(mapfn, T, kValue, k) 1024 : kValue; 1025 1026 // Step 13.e. 1027 targetObj[k] = mappedValue; 1028 } 1029 1030 // Step 14. 1031 return targetObj; 1032 } 1033 1034 // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 1035 // 22.2.2.2 %TypedArray%.of ( ...items ) 1036 function TypedArrayStaticOf(/*...items*/) { 1037 // Step 1. 1038 var len = ArgumentsLength(); 1039 1040 // Step 2 (implicit). 1041 1042 // Step 3. 1043 var C = this; 1044 1045 // Step 4. 1046 if (!IsConstructor(C)) { 1047 ThrowTypeError(JSMSG_NOT_CONSTRUCTOR, typeof C); 1048 } 1049 1050 // Step 5. 1051 var newObj = TypedArrayCreateWithLength(C, len); 1052 1053 // Steps 6-7. 1054 for (var k = 0; k < len; k++) { 1055 newObj[k] = GetArgument(k); 1056 } 1057 1058 // Step 8. 1059 return newObj; 1060 } 1061 1062 // ES 2016 draft Mar 25, 2016 22.2.2.4. 1063 function $TypedArraySpecies() { 1064 // Step 1. 1065 return this; 1066 } 1067 SetCanonicalName($TypedArraySpecies, "get [Symbol.species]"); 1068 1069 // ES2018 draft rev 0525bb33861c7f4e9850f8a222c89642947c4b9c 1070 // 22.2.2.1.1 Runtime Semantics: IterableToList( items, method ) 1071 function IterableToList(items, method) { 1072 // Step 1 (Inlined GetIterator). 1073 1074 // 7.4.1 GetIterator, step 1. 1075 assert(IsCallable(method), "method argument is a function"); 1076 1077 // 7.4.1 GetIterator, step 2. 1078 var iterator = callContentFunction(method, items); 1079 1080 // 7.4.1 GetIterator, step 3. 1081 if (!IsObject(iterator)) { 1082 ThrowTypeError(JSMSG_GET_ITER_RETURNED_PRIMITIVE); 1083 } 1084 1085 // 7.4.1 GetIterator, step 4. 1086 var nextMethod = iterator.next; 1087 1088 // Step 2. 1089 var values = []; 1090 1091 // Steps 3-4. 1092 var i = 0; 1093 while (true) { 1094 // Step 4.a. 1095 var next = callContentFunction(nextMethod, iterator); 1096 if (!IsObject(next)) { 1097 ThrowTypeError(JSMSG_ITER_METHOD_RETURNED_PRIMITIVE, "next"); 1098 } 1099 1100 // Step 4.b. 1101 if (next.done) { 1102 break; 1103 } 1104 DefineDataProperty(values, i++, next.value); 1105 } 1106 1107 // Step 5. 1108 return values; 1109 } 1110 1111 // ES 2016 draft Mar 25, 2016 24.1.3.3. 1112 function $ArrayBufferSpecies() { 1113 // Step 1. 1114 return this; 1115 } 1116 SetCanonicalName($ArrayBufferSpecies, "get [Symbol.species]"); 1117 1118 // Shared memory and atomics proposal (30 Oct 2016) 1119 function $SharedArrayBufferSpecies() { 1120 // Step 1. 1121 return this; 1122 } 1123 SetCanonicalName($SharedArrayBufferSpecies, "get [Symbol.species]"); 1124 1125 // https://github.com/tc39/proposal-change-array-by-copy 1126 function TypedArrayCreateSameType(exemplar, length) { 1127 // Step 1. Assert: exemplar is an Object that has [[TypedArrayName]] and [[ContentType]] internal slots. 1128 assert( 1129 IsPossiblyWrappedTypedArray(exemplar), 1130 "in TypedArrayCreateSameType, exemplar does not have a [[ContentType]] internal slot" 1131 ); 1132 1133 // Step 2. Let constructor be the intrinsic object listed in column one of Table 63 for exemplar.[[TypedArrayName]]. 1134 var constructor = ConstructorForTypedArray(exemplar); 1135 1136 // Step 4 omitted. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots. - guaranteed by the TypedArray implementation 1137 // Step 5 omitted. Assert: result.[[ContentType]] is exemplar.[[ContentType]]. - guaranteed by the typed array implementation 1138 1139 // Step 3. Let result be ? TypedArrayCreate(constructor, argumentList). 1140 // Step 6. Return result. 1141 return TypedArrayCreateWithLength(constructor, length); 1142 } 1143 1144 // https://tc39.es/ecma262/#sec-%typedarray%.prototype.tosorted 1145 // 23.2.3.33 %TypedArray%.prototype.toSorted ( comparefn ) 1146 function TypedArrayToSorted(comparefn) { 1147 // Step 1. If comparefn is not undefined and IsCallable(comparefn) is false, 1148 // throw a TypeError exception. 1149 if (comparefn !== undefined) { 1150 if (!IsCallable(comparefn)) { 1151 ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, comparefn)); 1152 } 1153 } 1154 1155 // Step 2. Let O be the this value. 1156 var O = this; 1157 1158 // Step 3. Perform ? ValidateTypedArray(this). 1159 EnsureTypedArrayWithArrayBuffer(O); 1160 1161 // Step 4. Let len be TypedArrayLength(taRecord). 1162 var len = PossiblyWrappedTypedArrayLength(O); 1163 1164 // Step 5. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »). 1165 var A = TypedArrayCreateSameType(O, len); 1166 1167 // Steps 6-10 not followed exactly; this implementation copies the list and then 1168 // sorts the copy, rather than calling a sort method that copies the list and then 1169 // copying the result again. 1170 1171 // Equivalent to steps 9-10. 1172 for (var k = 0; k < len; k++) { 1173 A[k] = O[k]; 1174 } 1175 1176 // Arrays with less than two elements remain unchanged when sorted. 1177 if (len > 1) { 1178 // Equivalent to steps 6-8. 1179 callFunction(std_TypedArray_sort, A, comparefn); 1180 } 1181 1182 // Step 11. 1183 return A; 1184 }