/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "TypedArrayConstants.h" function ViewedArrayBufferIfReified(tarray) { assert(IsTypedArray(tarray), "non-typed array asked for its buffer"); var buf = UnsafeGetReservedSlot(tarray, JS_TYPEDARRAYLAYOUT_BUFFER_SLOT); assert( buf === null || (IsObject(buf) && (GuardToArrayBuffer(buf) !== null || GuardToSharedArrayBuffer(buf) !== null)), "unexpected value in buffer slot" ); return buf; } function IsDetachedBuffer(buffer) { // A typed array with a null buffer has never had its buffer exposed to // become detached. if (buffer === null) { return false; } assert( GuardToArrayBuffer(buffer) !== null || GuardToSharedArrayBuffer(buffer) !== null, "non-ArrayBuffer passed to IsDetachedBuffer" ); // Shared array buffers are not detachable. // // This check is more expensive than desirable, but IsDetachedBuffer is // only hot for non-shared memory in SetFromNonTypedArray, so there is an // optimization in place there to avoid incurring the cost here. An // alternative is to give SharedArrayBuffer the same layout as ArrayBuffer. if ((buffer = GuardToArrayBuffer(buffer)) === null) { return false; } var flags = UnsafeGetInt32FromReservedSlot(buffer, JS_ARRAYBUFFER_FLAGS_SLOT); return (flags & JS_ARRAYBUFFER_DETACHED_FLAG) !== 0; } function TypedArrayLengthMethod() { return TypedArrayLength(this); } function GetAttachedArrayBuffer(tarray) { var buffer = ViewedArrayBufferIfReified(tarray); if (IsDetachedBuffer(buffer)) { ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); } return buffer; } function GetAttachedArrayBufferMethod() { return GetAttachedArrayBuffer(this); } // A function which ensures that the argument is either a typed array or a // cross-compartment wrapper for a typed array and that the typed array involved // has an attached array buffer. If one of those conditions doesn't hold (wrong // kind of argument, or detached array buffer), an exception is thrown. The // return value is `true` if the argument is a typed array, `false` if it's a // cross-compartment wrapper for a typed array. function IsTypedArrayEnsuringArrayBuffer(arg) { if (IsObject(arg) && IsTypedArray(arg)) { GetAttachedArrayBuffer(arg); return true; } callFunction( CallTypedArrayMethodIfWrapped, arg, "GetAttachedArrayBufferMethod" ); return false; } // ES2019 draft rev 85ce767c86a1a8ed719fe97e978028bff819d1f2 // 7.3.20 SpeciesConstructor ( O, defaultConstructor ) // // SpeciesConstructor function optimized for TypedArrays to avoid calling // ConstructorForTypedArray, a non-inlineable runtime function, in the normal // case. function TypedArraySpeciesConstructor(obj) { // Step 1. assert(IsObject(obj), "not passed an object"); // Step 2. var ctor = obj.constructor; // Step 3. if (ctor === undefined) { return ConstructorForTypedArray(obj); } // Step 4. if (!IsObject(ctor)) { ThrowTypeError(JSMSG_OBJECT_REQUIRED, "object's 'constructor' property"); } // Steps 5. var s = ctor[GetBuiltinSymbol("species")]; // Step 6. if (IsNullOrUndefined(s)) { return ConstructorForTypedArray(obj); } // Step 7. if (IsConstructor(s)) { return s; } // Step 8. ThrowTypeError( JSMSG_NOT_CONSTRUCTOR, "@@species property of object's constructor" ); } // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.3.5.1 Runtime Semantics: ValidateTypedArray ( O ) function ValidateTypedArray(obj) { if (IsObject(obj)) { /* Steps 3-5 (non-wrapped typed arrays). */ if (IsTypedArray(obj)) { // GetAttachedArrayBuffer throws for detached array buffers. GetAttachedArrayBuffer(obj); return true; } /* Steps 3-5 (wrapped typed arrays). */ if (IsPossiblyWrappedTypedArray(obj)) { if (PossiblyWrappedTypedArrayHasDetachedBuffer(obj)) { ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); } return false; } } /* Steps 1-2. */ ThrowTypeError(JSMSG_NON_TYPED_ARRAY_RETURNED); } // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.4.6 TypedArrayCreate ( constructor, argumentList ) function TypedArrayCreateWithLength(constructor, length) { // Step 1. var newTypedArray = constructContentFunction( constructor, constructor, length ); // Step 2. var isTypedArray = ValidateTypedArray(newTypedArray); // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(newTypedArray); } else { len = callFunction( CallTypedArrayMethodIfWrapped, newTypedArray, "TypedArrayLengthMethod" ); } if (len < length) { ThrowTypeError(JSMSG_SHORT_TYPED_ARRAY_RETURNED, length, len); } // Step 4. return newTypedArray; } // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.4.6 TypedArrayCreate ( constructor, argumentList ) function TypedArrayCreateWithBuffer(constructor, buffer, byteOffset, length) { // Step 1. var newTypedArray = constructContentFunction( constructor, constructor, buffer, byteOffset, length ); // Step 2. ValidateTypedArray(newTypedArray); // Step 3 (not applicable). // Step 4. return newTypedArray; } // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.4.7 TypedArraySpeciesCreate ( exemplar, argumentList ) function TypedArraySpeciesCreateWithLength(exemplar, length) { // Step 1 (omitted). // Steps 2-3. var C = TypedArraySpeciesConstructor(exemplar); // Step 4. return TypedArrayCreateWithLength(C, length); } // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.4.7 TypedArraySpeciesCreate ( exemplar, argumentList ) function TypedArraySpeciesCreateWithBuffer( exemplar, buffer, byteOffset, length ) { // Step 1 (omitted). // Steps 2-3. var C = TypedArraySpeciesConstructor(exemplar); // Step 4. return TypedArrayCreateWithBuffer(C, buffer, byteOffset, length); } // ES6 draft rev30 (2014/12/24) 22.2.3.6 %TypedArray%.prototype.entries() function TypedArrayEntries() { // Step 1. var O = this; // We need to be a bit careful here, because in the Xray case we want to // create the iterator in our current compartment. // // Before doing that, though, we want to check that we have a typed array // and it does not have a detached array buffer. We do the latter by just // calling GetAttachedArrayBuffer() and letting it throw if there isn't one. // In the case when we're not sure we have a typed array (e.g. we might have // a cross-compartment wrapper for one), we can go ahead and call // GetAttachedArrayBuffer via IsTypedArrayEnsuringArrayBuffer; that will // throw if we're not actually a wrapped typed array, or if we have a // detached array buffer. // Step 2-6. IsTypedArrayEnsuringArrayBuffer(O); // Step 7. return CreateArrayIterator(O, ITEM_KIND_KEY_AND_VALUE); } // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.7 %TypedArray%.prototype.every ( callbackfn [ , thisArg ] ) function TypedArrayEvery(callbackfn /*, thisArg*/) { // Step 1. var O = this; // Step 2. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Step 4. if (ArgumentsLength() === 0) { ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.every"); } if (!IsCallable(callbackfn)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); } var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Steps 5-6. for (var k = 0; k < len; k++) { // Steps 6.b-d. var kValue = O[k]; // Step 6.c. var testResult = callContentFunction(callbackfn, thisArg, kValue, k, O); // Step 6.d. if (!testResult) { return false; } } // Step 7. return true; } // Inlining this enables inlining of the callback function. SetIsInlinableLargeFunction(TypedArrayEvery); // ES2018 draft rev ad2d1c60c5dc42a806696d4b58b4dca42d1f7dd4 // 22.2.3.8 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] ) function TypedArrayFill(value, start = 0, end = undefined) { // This function is not generic. if (!IsObject(this) || !IsTypedArray(this)) { return callFunction( CallTypedArrayMethodIfWrapped, this, value, start, end, "TypedArrayFill" ); } // Step 1. var O = this; // Step 2. var buffer = GetAttachedArrayBuffer(this); // Step 3. var len = TypedArrayLength(O); // Step 4. var kind = GetTypedArrayKind(O); if (kind === TYPEDARRAY_KIND_BIGINT64 || kind === TYPEDARRAY_KIND_BIGUINT64) { value = ToBigInt(value); } else { value = ToNumber(value); } // Step 5. var relativeStart = ToInteger(start); // Step 6. var k = relativeStart < 0 ? std_Math_max(len + relativeStart, 0) : std_Math_min(relativeStart, len); // Step 7. var relativeEnd = end === undefined ? len : ToInteger(end); // Step 8. var final = relativeEnd < 0 ? std_Math_max(len + relativeEnd, 0) : std_Math_min(relativeEnd, len); // Step 9. if (buffer === null) { // A typed array previously using inline storage may acquire a // buffer, so we must check with the source. buffer = ViewedArrayBufferIfReified(O); } if (IsDetachedBuffer(buffer)) { ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); } // Step 10. for (; k < final; k++) { O[k] = value; } // Step 11. return O; } // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // %TypedArray%.prototype.filter ( callbackfn [ , thisArg ] ) function TypedArrayFilter(callbackfn /*, thisArg*/) { // Step 1. var O = this; // Step 2. // This function is not generic. // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Step 4. if (ArgumentsLength() === 0) { ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.filter"); } if (!IsCallable(callbackfn)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); } // Step 5. var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Step 6. var kept = new_List(); // Step 8. var captured = 0; // Steps 7 and 9.e. for (var k = 0; k < len; k++) { // Steps 9.a-b. var kValue = O[k]; // Steps 9.c-d. if (callContentFunction(callbackfn, T, kValue, k, O)) { // Steps 9.d.i-ii. kept[captured++] = kValue; } } // Step 10. var A = TypedArraySpeciesCreateWithLength(O, captured); // Steps 11 and 12.b. for (var n = 0; n < captured; n++) { // Step 12.a. A[n] = kept[n]; } // Step 13. return A; } // Inlining this enables inlining of the callback function. SetIsInlinableLargeFunction(TypedArrayFilter); // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.10 %TypedArray%.prototype.find ( predicate [ , thisArg ] ) function TypedArrayFind(predicate /*, thisArg*/) { // Step 1. var O = this; // Step 2. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Step 4. if (ArgumentsLength() === 0) { ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.find"); } if (!IsCallable(predicate)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate)); } var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Steps 5-6. for (var k = 0; k < len; k++) { // Steps 6.a-b. var kValue = O[k]; // Steps 6.c-d. if (callContentFunction(predicate, thisArg, kValue, k, O)) { return kValue; } } // Step 7. return undefined; } // Inlining this enables inlining of the callback function. SetIsInlinableLargeFunction(TypedArrayFind); // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.11 %TypedArray%.prototype.findIndex ( predicate [ , thisArg ] ) function TypedArrayFindIndex(predicate /*, thisArg*/) { // Step 1. var O = this; // Step 2. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Step 4. if (ArgumentsLength() === 0) { ThrowTypeError( JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.findIndex" ); } if (!IsCallable(predicate)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate)); } var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Steps 5-6. for (var k = 0; k < len; k++) { // Steps 6.a-f. if (callContentFunction(predicate, thisArg, O[k], k, O)) { return k; } } // Step 7. return -1; } // Inlining this enables inlining of the callback function. SetIsInlinableLargeFunction(TypedArrayFindIndex); // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.12 %TypedArray%.prototype.forEach ( callbackfn [ , thisArg ] ) function TypedArrayForEach(callbackfn /*, thisArg*/) { // Step 1. var O = this; // Step 2. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Step 4. if (ArgumentsLength() === 0) { ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "TypedArray.prototype.forEach"); } if (!IsCallable(callbackfn)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); } var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Steps 5-6. for (var k = 0; k < len; k++) { // Steps 6.a-c. callContentFunction(callbackfn, thisArg, O[k], k, O); } // Step 7. return undefined; } // Inlining this enables inlining of the callback function. SetIsInlinableLargeFunction(TypedArrayForEach); // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.14 %TypedArray%.prototype.indexOf ( searchElement [ , fromIndex ] ) function TypedArrayIndexOf(searchElement, fromIndex = 0) { // Step 2. if (!IsObject(this) || !IsTypedArray(this)) { return callFunction( CallTypedArrayMethodIfWrapped, this, searchElement, fromIndex, "TypedArrayIndexOf" ); } GetAttachedArrayBuffer(this); // Step 1. var O = this; // Step 3. var len = TypedArrayLength(O); // Step 4. if (len === 0) { return -1; } // Step 5. var n = ToInteger(fromIndex); // Step 6. assert(fromIndex !== undefined || n === 0, "ToInteger(undefined) is zero"); // Reload O.[[ArrayLength]] in case ToInteger() detached the ArrayBuffer. // This let's us avoid executing the HasProperty operation in step 11.a. len = TypedArrayLength(O); assert( len === 0 || !IsDetachedBuffer(ViewedArrayBufferIfReified(O)), "TypedArrays with detached buffers have a length of zero" ); // Step 7. if (n >= len) { return -1; } // Steps 7-10. // Steps 7-8 are handled implicitly. var k; if (n >= 0) { // Step 9.a. k = n; } else { // Step 10.a. k = len + n; // Step 10.b. if (k < 0) { k = 0; } } // Step 11. for (; k < len; k++) { // Step 11.a (not necessary in our implementation). assert(k in O, "unexpected missing element"); // Steps 11.b.i-iii. if (O[k] === searchElement) { return k; } } // Step 12. return -1; } // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.15 %TypedArray%.prototype.join ( separator ) function TypedArrayJoin(separator) { // Step 2. if (!IsObject(this) || !IsTypedArray(this)) { return callFunction( CallTypedArrayMethodIfWrapped, this, separator, "TypedArrayJoin" ); } GetAttachedArrayBuffer(this); // Step 1. var O = this; // Step 3. var len = TypedArrayLength(O); // Steps 4-5. var sep = separator === undefined ? "," : ToString(separator); // Steps 6 and 9. if (len === 0) { return ""; } // ToString() might have detached the underlying ArrayBuffer. To avoid // checking for this condition when looping in step 8.c, do it once here. if (TypedArrayLength(O) === 0) { assert( IsDetachedBuffer(ViewedArrayBufferIfReified(O)), "TypedArrays with detached buffers have a length of zero" ); return callFunction(String_repeat, ",", len - 1); } assert( !IsDetachedBuffer(ViewedArrayBufferIfReified(O)), "TypedArrays with detached buffers have a length of zero" ); var element0 = O[0]; // Omit the 'if' clause in step 8.c, since typed arrays can't have undefined or null elements. assert(element0 !== undefined, "unexpected undefined element"); // Step 6. var R = ToString(element0); // Steps 7-8. for (var k = 1; k < len; k++) { // Step 8.b. var element = O[k]; // Omit the 'if' clause in step 8.c, since typed arrays can't have undefined or null elements. assert(element !== undefined, "unexpected undefined element"); // Steps 8.a and 8.c-d. R += sep + ToString(element); } // Step 9. return R; } // ES6 draft (2016/1/11) 22.2.3.15 %TypedArray%.prototype.keys() function TypedArrayKeys() { // Step 1. var O = this; // See the big comment in TypedArrayEntries for what we're doing here. // Step 2. IsTypedArrayEnsuringArrayBuffer(O); // Step 3. return CreateArrayIterator(O, ITEM_KIND_KEY); } // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.17 %TypedArray%.prototype.lastIndexOf ( searchElement [ , fromIndex ] ) function TypedArrayLastIndexOf(searchElement /*, fromIndex*/) { // Step 2. if (!IsObject(this) || !IsTypedArray(this)) { if (ArgumentsLength() > 1) { return callFunction( CallTypedArrayMethodIfWrapped, this, searchElement, GetArgument(1), "TypedArrayLastIndexOf" ); } return callFunction( CallTypedArrayMethodIfWrapped, this, searchElement, "TypedArrayLastIndexOf" ); } GetAttachedArrayBuffer(this); // Step 1. var O = this; // Step 3. var len = TypedArrayLength(O); // Step 4. if (len === 0) { return -1; } // Step 5. var n = ArgumentsLength() > 1 ? ToInteger(GetArgument(1)) : len - 1; // Reload O.[[ArrayLength]] in case ToInteger() detached the ArrayBuffer. // This let's us avoid executing the HasProperty operation in step 9.a. len = TypedArrayLength(O); assert( len === 0 || !IsDetachedBuffer(ViewedArrayBufferIfReified(O)), "TypedArrays with detached buffers have a length of zero" ); // Steps 6-8. var k = n >= 0 ? std_Math_min(n, len - 1) : len + n; // Step 9. for (; k >= 0; k--) { // Step 9.a (not necessary in our implementation). assert(k in O, "unexpected missing element"); // Steps 9.b.i-iii. if (O[k] === searchElement) { return k; } } // Step 10. return -1; } // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.3.19 %TypedArray%.prototype.map ( callbackfn [ , thisArg ] ) function TypedArrayMap(callbackfn /*, thisArg*/) { // Step 1. var O = this; // Step 2. // This function is not generic. // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Step 4. if (ArgumentsLength() === 0) { ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.map"); } if (!IsCallable(callbackfn)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); } // Step 5. var T = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Step 6. var A = TypedArraySpeciesCreateWithLength(O, len); // Steps 7, 8.a (implicit) and 8.e. for (var k = 0; k < len; k++) { // Steps 8.b-c. var mappedValue = callContentFunction(callbackfn, T, O[k], k, O); // Steps 8.d. A[k] = mappedValue; } // Step 9. return A; } // Inlining this enables inlining of the callback function. SetIsInlinableLargeFunction(TypedArrayMap); // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.20 %TypedArray%.prototype.reduce ( callbackfn [ , initialValue ] ) function TypedArrayReduce(callbackfn /*, initialValue*/) { // Step 1. var O = this; // Step 2. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Step 4. if (ArgumentsLength() === 0) { ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.reduce"); } if (!IsCallable(callbackfn)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); } // Step 5. if (len === 0 && ArgumentsLength() === 1) { ThrowTypeError(JSMSG_EMPTY_ARRAY_REDUCE); } // Step 6. var k = 0; // Steps 7-9. var accumulator = ArgumentsLength() > 1 ? GetArgument(1) : O[k++]; // Step 10. for (; k < len; k++) { accumulator = callContentFunction( callbackfn, undefined, accumulator, O[k], k, O ); } // Step 11. return accumulator; } // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.21 %TypedArray%.prototype.reduceRight ( callbackfn [ , initialValue ] ) function TypedArrayReduceRight(callbackfn /*, initialValue*/) { // Step 1. var O = this; // Step 2. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Step 4. if (ArgumentsLength() === 0) { ThrowTypeError( JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.reduceRight" ); } if (!IsCallable(callbackfn)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); } // Step 5. if (len === 0 && ArgumentsLength() === 1) { ThrowTypeError(JSMSG_EMPTY_ARRAY_REDUCE); } // Step 6. var k = len - 1; // Steps 7-9. var accumulator = ArgumentsLength() > 1 ? GetArgument(1) : O[k--]; // Step 10. for (; k >= 0; k--) { accumulator = callContentFunction( callbackfn, undefined, accumulator, O[k], k, O ); } // Step 11. return accumulator; } // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.22 %TypedArray%.prototype.reverse ( ) function TypedArrayReverse() { // Step 2. if (!IsObject(this) || !IsTypedArray(this)) { return callFunction( CallTypedArrayMethodIfWrapped, this, "TypedArrayReverse" ); } GetAttachedArrayBuffer(this); // Step 1. var O = this; // Step 3. var len = TypedArrayLength(O); // Step 4. var middle = std_Math_floor(len / 2); // Steps 5-6. for (var lower = 0; lower !== middle; lower++) { // Step 6.a. var upper = len - lower - 1; // Step 6.d. var lowerValue = O[lower]; // Step 6.e. var upperValue = O[upper]; // Steps 6.f-g. O[lower] = upperValue; O[upper] = lowerValue; } // Step 7. return O; } // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.3.24 %TypedArray%.prototype.slice ( start, end ) function TypedArraySlice(start, end) { // Step 1. var O = this; // Step 2. if (!IsObject(O) || !IsTypedArray(O)) { return callFunction( CallTypedArrayMethodIfWrapped, O, start, end, "TypedArraySlice" ); } var buffer = GetAttachedArrayBuffer(O); // Step 3. var len = TypedArrayLength(O); // Step 4. var relativeStart = ToInteger(start); // Step 5. var k = relativeStart < 0 ? std_Math_max(len + relativeStart, 0) : std_Math_min(relativeStart, len); // Step 6. var relativeEnd = end === undefined ? len : ToInteger(end); // Step 7. var final = relativeEnd < 0 ? std_Math_max(len + relativeEnd, 0) : std_Math_min(relativeEnd, len); // Step 8. var count = std_Math_max(final - k, 0); // Step 9. var A = TypedArraySpeciesCreateWithLength(O, count); // Steps 14-15. if (count > 0) { // Steps 14.b.ii, 15.b. if (buffer === null) { // A typed array previously using inline storage may acquire a // buffer, so we must check with the source. buffer = ViewedArrayBufferIfReified(O); } if (IsDetachedBuffer(buffer)) { ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); } // Steps 10-13, 15. var sliced = TypedArrayBitwiseSlice(O, A, k, count); // Step 14. if (!sliced) { // Step 14.a. var n = 0; // Step 14.b. while (k < final) { // Steps 14.b.i-v. A[n++] = O[k++]; } } } // Step 16. return A; } // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.25 %TypedArray%.prototype.some ( callbackfn [ , thisArg ] ) function TypedArraySome(callbackfn /*, thisArg*/) { // Step 1. var O = this; // Step 2. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Step 4. if (ArgumentsLength() === 0) { ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.some"); } if (!IsCallable(callbackfn)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, callbackfn)); } var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Steps 5-6. for (var k = 0; k < len; k++) { // Steps 6.a-b. var kValue = O[k]; // Step 6.c. var testResult = callContentFunction(callbackfn, thisArg, kValue, k, O); // Step 6.d. if (testResult) { return true; } } // Step 7. return false; } // Inlining this enables inlining of the callback function. SetIsInlinableLargeFunction(TypedArraySome); // To satisfy step 6.b from TypedArray SortCompare described in 23.2.3.29 the // user supplied comparefn is wrapped. function TypedArraySortCompare(comparefn) { return function(x, y) { // Step 6.b.i. var v = +callContentFunction(comparefn, undefined, x, y); // Step 6.b.ii. if (v !== v) { return 0; } // Step 6.b.iii. return v; }; } // ES2019 draft rev 8a16cb8d18660a1106faae693f0f39b9f1a30748 // 22.2.3.26 %TypedArray%.prototype.sort ( comparefn ) function TypedArraySort(comparefn) { // This function is not generic. // Step 1. if (comparefn !== undefined) { if (!IsCallable(comparefn)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, comparefn)); } } // Step 2. var obj = this; // Step 3. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(obj); // Step 4. var len; if (isTypedArray) { len = TypedArrayLength(obj); } else { len = callFunction( CallTypedArrayMethodIfWrapped, obj, "TypedArrayLengthMethod" ); } // Arrays with less than two elements remain unchanged when sorted. if (len <= 1) { return obj; } if (comparefn === undefined) { return TypedArrayNativeSort(obj); } // Steps 5-6. var wrappedCompareFn = TypedArraySortCompare(comparefn); // Step 7. var sorted = MergeSortTypedArray(obj, len, wrappedCompareFn); // Move the sorted elements into the array. for (var i = 0; i < len; i++) { obj[i] = sorted[i]; } return obj; } // ES2017 draft rev f8a9be8ea4bd97237d176907a1e3080dce20c68f // 22.2.3.28 %TypedArray%.prototype.toLocaleString ([ reserved1 [ , reserved2 ] ]) // ES2017 Intl draft rev 78bbe7d1095f5ff3760ac4017ed366026e4cb276 // 13.4.1 Array.prototype.toLocaleString ([ locales [ , options ]]) function TypedArrayToLocaleString(locales = undefined, options = undefined) { // ValidateTypedArray, then step 1. var array = this; // This function is not generic. // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(array); // If we got here, `this` is either a typed array or a wrapper for one. // Step 2. var len; if (isTypedArray) { len = TypedArrayLength(array); } else { len = callFunction( CallTypedArrayMethodIfWrapped, array, "TypedArrayLengthMethod" ); } // Step 4. if (len === 0) { return ""; } // Step 5. var firstElement = array[0]; // Steps 6-7. // Omit the 'if' clause in step 6, since typed arrays can't have undefined // or null elements. #if JS_HAS_INTL_API var R = ToString( callContentFunction( firstElement.toLocaleString, firstElement, locales, options ) ); #else var R = ToString( callContentFunction(firstElement.toLocaleString, firstElement) ); #endif // Step 3 (reordered). // We don't (yet?) implement locale-dependent separators. var separator = ","; // Steps 8-9. for (var k = 1; k < len; k++) { // Step 9.a. var S = R + separator; // Step 9.b. var nextElement = array[k]; // Step 9.c *should* be unreachable: typed array elements are numbers. // But bug 1079853 means |nextElement| *could* be |undefined|, if the // previous iteration's step 9.d or step 7 detached |array|'s buffer. // Conveniently, if this happens, evaluating |nextElement.toLocaleString| // throws the required TypeError, and the only observable difference is // the error message. So despite bug 1079853, we can skip step 9.c. // Step 9.d. #if JS_HAS_INTL_API R = ToString( callContentFunction( nextElement.toLocaleString, nextElement, locales, options ) ); #else R = ToString(callContentFunction(nextElement.toLocaleString, nextElement)); #endif // Step 9.e. R = S + R; } // Step 10. return R; } // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9 // 22.2.3.27 %TypedArray%.prototype.subarray ( begin, end ) function TypedArraySubarray(begin, end) { // Step 1. var obj = this; // Steps 2-3. // This function is not generic. if (!IsObject(obj) || !IsTypedArray(obj)) { return callFunction( CallTypedArrayMethodIfWrapped, this, begin, end, "TypedArraySubarray" ); } // Step 4. var buffer = ViewedArrayBufferIfReified(obj); if (buffer === null) { buffer = TypedArrayBuffer(obj); } // Step 5. var srcLength = TypedArrayLength(obj); // Step 13 (Reordered because otherwise it'd be observable that we reset // the byteOffset to zero when the underlying array buffer gets detached). var srcByteOffset = TypedArrayByteOffset(obj); // Step 6. var relativeBegin = ToInteger(begin); // Step 7. var beginIndex = relativeBegin < 0 ? std_Math_max(srcLength + relativeBegin, 0) : std_Math_min(relativeBegin, srcLength); // Step 8. var relativeEnd = end === undefined ? srcLength : ToInteger(end); // Step 9. var endIndex = relativeEnd < 0 ? std_Math_max(srcLength + relativeEnd, 0) : std_Math_min(relativeEnd, srcLength); // Step 10. var newLength = std_Math_max(endIndex - beginIndex, 0); // Steps 11-12. var elementSize = TypedArrayElementSize(obj); // Step 14. var beginByteOffset = srcByteOffset + beginIndex * elementSize; // Steps 15-16. return TypedArraySpeciesCreateWithBuffer( obj, buffer, beginByteOffset, newLength ); } // https://tc39.es/proposal-relative-indexing-method // %TypedArray%.prototype.at ( index ) function TypedArrayAt(index) { // Step 1. var obj = this; // Step 2. // This function is not generic. if (!IsObject(obj) || !IsTypedArray(obj)) { return callFunction( CallTypedArrayMethodIfWrapped, obj, index, "TypedArrayAt" ); } GetAttachedArrayBuffer(obj); // Step 3. var len = TypedArrayLength(obj); // Step 4. var relativeIndex = ToInteger(index); // Steps 5-6. var k; if (relativeIndex >= 0) { k = relativeIndex; } else { k = len + relativeIndex; } // Step 7. if (k < 0 || k >= len) { return undefined; } // Step 8. return obj[k]; } // This function is only barely too long for normal inlining. SetIsInlinableLargeFunction(TypedArrayAt); // https://github.com/tc39/proposal-array-find-from-last // %TypedArray%.prototype.findLast ( predicate, thisArg ) function TypedArrayFindLast(predicate /*, thisArg*/) { // Step 1. var O = this; // Step 2. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Step 4. if (ArgumentsLength() === 0) { ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.findLast"); } if (!IsCallable(predicate)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate)); } var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Steps 5-6. for (var k = len - 1; k >= 0; k--) { // Steps 6.a-b. var kValue = O[k]; // Steps 6.c-d. if (callContentFunction(predicate, thisArg, kValue, k, O)) { return kValue; } } // Step 7. return undefined; } // Inlining this enables inlining of the callback function. SetIsInlinableLargeFunction(TypedArrayFindLast); // https://github.com/tc39/proposal-array-find-from-last // %TypedArray%.prototype.findLastIndex ( predicate, thisArg ) function TypedArrayFindLastIndex(predicate /*, thisArg*/) { // Step 1. var O = this; // Step 2. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Step 4. if (ArgumentsLength() === 0) { ThrowTypeError( JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.findLastIndex" ); } if (!IsCallable(predicate)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate)); } var thisArg = ArgumentsLength() > 1 ? GetArgument(1) : undefined; // Steps 5-6. for (var k = len - 1; k >= 0; k--) { // Steps 6.a-f. if (callContentFunction(predicate, thisArg, O[k], k, O)) { return k; } } // Step 7. return -1; } // Inlining this enables inlining of the callback function. SetIsInlinableLargeFunction(TypedArrayFindLastIndex); // ES6 draft rev30 (2014/12/24) 22.2.3.30 %TypedArray%.prototype.values() // // Uncloned functions with `$` prefix are allocated as extended function // to store the original name in `SetCanonicalName`. function $TypedArrayValues() { // Step 1. var O = this; // See the big comment in TypedArrayEntries for what we're doing here. IsTypedArrayEnsuringArrayBuffer(O); // Step 7. return CreateArrayIterator(O, ITEM_KIND_VALUE); } SetCanonicalName($TypedArrayValues, "values"); // ES2021 draft rev 190d474c3d8728653fbf8a5a37db1de34b9c1472 // Plus // 22.2.3.13 %TypedArray%.prototype.includes ( searchElement [ , fromIndex ] ) function TypedArrayIncludes(searchElement, fromIndex = 0) { // Step 2. if (!IsObject(this) || !IsTypedArray(this)) { return callFunction( CallTypedArrayMethodIfWrapped, this, searchElement, fromIndex, "TypedArrayIncludes" ); } GetAttachedArrayBuffer(this); // Step 1. var O = this; // Step 3. var len = TypedArrayLength(O); // Step 4. if (len === 0) { return false; } // Step 5. var n = ToInteger(fromIndex); // Step 6. assert(fromIndex !== undefined || n === 0, "ToInteger(undefined) is zero"); // Steps 7-10. // Steps 7-8 are handled implicitly. var k; if (n >= 0) { // Step 9.a k = n; } else { // Step 10.a. k = len + n; // Step 10.b. if (k < 0) { k = 0; } } // Step 11. while (k < len) { // Steps 11.a-b. if (SameValueZero(searchElement, O[k])) { return true; } // Step 11.c. k++; } // Step 12. return false; } // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.2.1 %TypedArray%.from ( source [ , mapfn [ , thisArg ] ] ) function TypedArrayStaticFrom(source, mapfn = undefined, thisArg = undefined) { // Step 1. var C = this; // Step 2. if (!IsConstructor(C)) { ThrowTypeError(JSMSG_NOT_CONSTRUCTOR, typeof C); } // Step 3. var mapping; if (mapfn !== undefined) { // Step 3.a. if (!IsCallable(mapfn)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(1, mapfn)); } // Step 3.b. mapping = true; } else { // Step 4. mapping = false; } // Step 5. var T = thisArg; // Step 6. // Inlined: GetMethod, steps 1-2. var usingIterator = source[GetBuiltinSymbol("iterator")]; // Step 7. // Inlined: GetMethod, step 3. if (usingIterator !== undefined && usingIterator !== null) { // Inlined: GetMethod, step 4. if (!IsCallable(usingIterator)) { ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, source)); } // Try to take a fast path when there's no mapper function and the // constructor is a built-in TypedArray constructor. if (!mapping && IsTypedArrayConstructor(C) && IsObject(source)) { // The source is a TypedArray using the default iterator. if ( usingIterator === $TypedArrayValues && IsTypedArray(source) && ArrayIteratorPrototypeOptimizable() ) { // Step 7.a. // Omitted but we still need to throw if |source| was detached. GetAttachedArrayBuffer(source); // Step 7.b. var len = TypedArrayLength(source); // Step 7.c. var targetObj = constructContentFunction(C, C, len); // Steps 7.d-f. for (var k = 0; k < len; k++) { targetObj[k] = source[k]; } // Step 7.g. return targetObj; } // The source is a packed array using the default iterator. if ( usingIterator === $ArrayValues && IsPackedArray(source) && ArrayIteratorPrototypeOptimizable() ) { // Steps 7.b-c. var targetObj = constructContentFunction(C, C, source.length); // Steps 7.a, 7.d-f. TypedArrayInitFromPackedArray(targetObj, source); // Step 7.g. return targetObj; } } // Step 7.a. var values = IterableToList(source, usingIterator); // Step 7.b. var len = values.length; // Step 7.c. var targetObj = TypedArrayCreateWithLength(C, len); // Steps 7.d-e. for (var k = 0; k < len; k++) { // Step 7.e.ii. var kValue = values[k]; // Steps 7.e.iii-iv. var mappedValue = mapping ? callContentFunction(mapfn, T, kValue, k) : kValue; // Step 7.e.v. targetObj[k] = mappedValue; } // Step 7.f. // Asserting that `values` is empty here would require removing them one by one from // the list's start in the loop above. That would introduce unacceptable overhead. // Additionally, the loop's logic is simple enough not to require the assert. // Step 7.g. return targetObj; } // Step 8 is an assertion: items is not an Iterator. Testing this is // literally the very last thing we did, so we don't assert here. // Step 9. var arrayLike = ToObject(source); // Step 10. var len = ToLength(arrayLike.length); // Step 11. var targetObj = TypedArrayCreateWithLength(C, len); // Steps 12-13. for (var k = 0; k < len; k++) { // Steps 13.a-b. var kValue = arrayLike[k]; // Steps 13.c-d. var mappedValue = mapping ? callContentFunction(mapfn, T, kValue, k) : kValue; // Step 13.e. targetObj[k] = mappedValue; } // Step 14. return targetObj; } // ES2017 draft rev 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e // 22.2.2.2 %TypedArray%.of ( ...items ) function TypedArrayStaticOf(/*...items*/) { // Step 1. var len = ArgumentsLength(); // Step 2 (implicit). // Step 3. var C = this; // Step 4. if (!IsConstructor(C)) { ThrowTypeError(JSMSG_NOT_CONSTRUCTOR, typeof C); } // Step 5. var newObj = TypedArrayCreateWithLength(C, len); // Steps 6-7. for (var k = 0; k < len; k++) { newObj[k] = GetArgument(k); } // Step 8. return newObj; } // ES 2016 draft Mar 25, 2016 22.2.2.4. function $TypedArraySpecies() { // Step 1. return this; } SetCanonicalName($TypedArraySpecies, "get [Symbol.species]"); // ES2018 draft rev 0525bb33861c7f4e9850f8a222c89642947c4b9c // 22.2.2.1.1 Runtime Semantics: IterableToList( items, method ) function IterableToList(items, method) { // Step 1 (Inlined GetIterator). // 7.4.1 GetIterator, step 1. assert(IsCallable(method), "method argument is a function"); // 7.4.1 GetIterator, step 2. var iterator = callContentFunction(method, items); // 7.4.1 GetIterator, step 3. if (!IsObject(iterator)) { ThrowTypeError(JSMSG_GET_ITER_RETURNED_PRIMITIVE); } // 7.4.1 GetIterator, step 4. var nextMethod = iterator.next; // Step 2. var values = []; // Steps 3-4. var i = 0; while (true) { // Step 4.a. var next = callContentFunction(nextMethod, iterator); if (!IsObject(next)) { ThrowTypeError(JSMSG_ITER_METHOD_RETURNED_PRIMITIVE, "next"); } // Step 4.b. if (next.done) { break; } DefineDataProperty(values, i++, next.value); } // Step 5. return values; } // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9 // 24.1.4.3 ArrayBuffer.prototype.slice ( start, end ) function ArrayBufferSlice(start, end) { // Step 1. var O = this; // Steps 2-3, // This function is not generic. if (!IsObject(O) || (O = GuardToArrayBuffer(O)) === null) { return callFunction( CallArrayBufferMethodIfWrapped, this, start, end, "ArrayBufferSlice" ); } // Step 4. if (IsDetachedBuffer(O)) { ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); } // Step 5. var len = ArrayBufferByteLength(O); // Step 6. var relativeStart = ToInteger(start); // Step 7. var first = relativeStart < 0 ? std_Math_max(len + relativeStart, 0) : std_Math_min(relativeStart, len); // Step 8. var relativeEnd = end === undefined ? len : ToInteger(end); // Step 9. var final = relativeEnd < 0 ? std_Math_max(len + relativeEnd, 0) : std_Math_min(relativeEnd, len); // Step 10. var newLen = std_Math_max(final - first, 0); // Step 11 var ctor = SpeciesConstructor(O, GetBuiltinConstructor("ArrayBuffer")); // Step 12. var new_ = constructContentFunction(ctor, ctor, newLen); // Steps 13-15. var isWrapped = false; var newBuffer; if ((newBuffer = GuardToArrayBuffer(new_)) !== null) { // Step 15. if (IsDetachedBuffer(newBuffer)) { ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); } } else { newBuffer = new_; // Steps 13-14. if (!IsWrappedArrayBuffer(newBuffer)) { ThrowTypeError(JSMSG_NON_ARRAY_BUFFER_RETURNED); } isWrapped = true; // Step 15. if ( callFunction( CallArrayBufferMethodIfWrapped, newBuffer, "IsDetachedBufferThis" ) ) { ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); } } // Step 16. if (newBuffer === O) { ThrowTypeError(JSMSG_SAME_ARRAY_BUFFER_RETURNED); } // Step 17. var actualLen = PossiblyWrappedArrayBufferByteLength(newBuffer); if (actualLen < newLen) { ThrowTypeError(JSMSG_SHORT_ARRAY_BUFFER_RETURNED, newLen, actualLen); } // Steps 18-19. if (IsDetachedBuffer(O)) { ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); } // Steps 20-22. ArrayBufferCopyData(newBuffer, 0, O, first, newLen, isWrapped); // Step 23. return newBuffer; } function IsDetachedBufferThis() { return IsDetachedBuffer(this); } // ES 2016 draft Mar 25, 2016 24.1.3.3. function $ArrayBufferSpecies() { // Step 1. return this; } SetCanonicalName($ArrayBufferSpecies, "get [Symbol.species]"); // Shared memory and atomics proposal (30 Oct 2016) function $SharedArrayBufferSpecies() { // Step 1. return this; } SetCanonicalName($SharedArrayBufferSpecies, "get [Symbol.species]"); // ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9 // 24.2.4.3 SharedArrayBuffer.prototype.slice ( start, end ) function SharedArrayBufferSlice(start, end) { // Step 1. var O = this; // Steps 2-3. // This function is not generic. if (!IsObject(O) || (O = GuardToSharedArrayBuffer(O)) === null) { return callFunction( CallSharedArrayBufferMethodIfWrapped, this, start, end, "SharedArrayBufferSlice" ); } // Step 4. var len = SharedArrayBufferByteLength(O); // Step 5. var relativeStart = ToInteger(start); // Step 6. var first = relativeStart < 0 ? std_Math_max(len + relativeStart, 0) : std_Math_min(relativeStart, len); // Step 7. var relativeEnd = end === undefined ? len : ToInteger(end); // Step 8. var final = relativeEnd < 0 ? std_Math_max(len + relativeEnd, 0) : std_Math_min(relativeEnd, len); // Step 9. var newLen = std_Math_max(final - first, 0); // Step 10 var ctor = SpeciesConstructor(O, GetBuiltinConstructor("SharedArrayBuffer")); // Step 11. var new_ = constructContentFunction(ctor, ctor, newLen); // Steps 12-13. var isWrapped = false; var newObj; if ((newObj = GuardToSharedArrayBuffer(new_)) === null) { if (!IsWrappedSharedArrayBuffer(new_)) { ThrowTypeError(JSMSG_NON_SHARED_ARRAY_BUFFER_RETURNED); } isWrapped = true; newObj = new_; } // Step 14. if (newObj === O || SharedArrayBuffersMemorySame(newObj, O)) { ThrowTypeError(JSMSG_SAME_SHARED_ARRAY_BUFFER_RETURNED); } // Step 15. var actualLen = PossiblyWrappedSharedArrayBufferByteLength(newObj); if (actualLen < newLen) { ThrowTypeError(JSMSG_SHORT_SHARED_ARRAY_BUFFER_RETURNED, newLen, actualLen); } // Steps 16-18. SharedArrayBufferCopyData(newObj, 0, O, first, newLen, isWrapped); // Step 19. return newObj; } // https://github.com/tc39/proposal-change-array-by-copy function TypedArrayCreateSameType(exemplar, length) { // Step 1. Assert: exemplar is an Object that has [[TypedArrayName]] and [[ContentType]] internal slots. assert( IsPossiblyWrappedTypedArray(exemplar), "in TypedArrayCreateSameType, exemplar does not have a [[ContentType]] internal slot" ); // Step 2. Let constructor be the intrinsic object listed in column one of Table 63 for exemplar.[[TypedArrayName]]. let constructor = ConstructorForTypedArray(exemplar); // Step 4 omitted. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots. - guaranteed by the TypedArray implementation // Step 5 omitted. Assert: result.[[ContentType]] is exemplar.[[ContentType]]. - guaranteed by the typed array implementation // Step 3. Let result be ? TypedArrayCreate(constructor, argumentList). // Step 6. Return result. return TypedArrayCreateWithLength(constructor, length); } // https://github.com/tc39/proposal-change-array-by-copy // TypedArray.prototype.toReversed() function TypedArrayToReversed() { // Step 2. Perform ? ValidateTypedArray(O). if (!IsObject(this) || !IsTypedArray(this)) { return callFunction( CallTypedArrayMethodIfWrapped, this, "TypedArrayToReversed" ); } GetAttachedArrayBuffer(this); // Step 1. Let O be the this value. var O = this; // Step 3. Let length be O.[[ArrayLength]]. var len = TypedArrayLength(O); // Step 4. Let A be ? TypedArrayCreateSameType(O, « 𝔽(length) »). var A = TypedArrayCreateSameType(O, len); // Step 5. Let k be 0. // Step 6. Repeat, while k < length, for (var k = 0; k < len; k++) { // Step 5.a. Let from be ! ToString(𝔽(length - k - 1)). var from = len - k - 1; // Step 5.b. omitted - Let Pk be ! ToString(𝔽(k)). // k coerced to String by property access // Step 5.c. Let fromValue be ! Get(O, from). var fromValue = O[from]; // Step 5.d. Perform ! Set(A, k, kValue, true). A[k] = fromValue; } // Step 7. Return A. return A; } // https://github.com/tc39/proposal-change-array-by-copy // TypedArray.prototype.with() function TypedArrayWith(index, value) { // Step 2. Perform ? ValidateTypedArray(O). if (!IsObject(this) || !IsTypedArray(this)) { return callFunction( CallTypedArrayMethodIfWrapped, this, index, value, "TypedArrayWith" ); } GetAttachedArrayBuffer(this); // Step 1. Let O be the this value. var O = this; // Step 3. Let len be O.[[ArrayLength]]. var len = TypedArrayLength(O); // Step 4. Let relativeIndex be ? ToIntegerOrInfinity(index). var relativeIndex = ToInteger(index); var actualIndex; if (relativeIndex >= 0) { // Step 5. If relativeIndex ≥ 0, let actualIndex be relativeIndex. actualIndex = relativeIndex; } else { // Step 6. Else, let actualIndex be len + relativeIndex. actualIndex = len + relativeIndex; } var kind = GetTypedArrayKind(O); if (kind === TYPEDARRAY_KIND_BIGINT64 || kind === TYPEDARRAY_KIND_BIGUINT64) { // Step 7. If O.[[ContentType]] is BigInt, set value to ? ToBigInt(value). value = ToBigInt(value); } else { // Step 8. Else, set value to ? ToNumber(value). value = ToNumber(value); } // Reload the array length in case the underlying buffer has been detached. len = TypedArrayLength(O); assert( !IsDetachedBuffer(ViewedArrayBufferIfReified(O)) || len === 0, "length is set to zero when the buffer has been detached" ); // Step 9. If ! IsValidIntegerIndex(O, 𝔽(actualIndex)) is false, throw a RangeError exception. // This check is an inlined version of the IsValidIntegerIndex abstract operation. if (actualIndex < 0 || actualIndex >= len) { ThrowRangeError(JSMSG_BAD_INDEX); } // Step 10. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »). var A = TypedArrayCreateSameType(O, len); // Step 11. Let k be 0. // Step 12. Repeat, while k < len, for (var k = 0; k < len; k++) { // Step 12.a. omitted - Let Pk be ! ToString(𝔽(k)). // k coerced to String by property access // Step 12.b. If k is actualIndex, let fromValue be value. // Step 12.c. Else, let fromValue be ! Get(O, Pk). var fromValue = k === actualIndex ? value : O[k]; // Step 12.d. Perform ! Set(A, Pk, fromValue, true). A[k] = fromValue; } // Step 13. return A; } // https://github.com/tc39/proposal-change-array-by-copy // TypedArray.prototype.toSorted() function TypedArrayToSorted(comparefn) { // Step 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception. if (comparefn !== undefined) { if (!IsCallable(comparefn)) { ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, comparefn)); } } // Step 2. Let O be the this value. var O = this; // Step 3. Perform ? ValidateTypedArray(this). var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); // Step 4. omitted. Let buffer be obj.[[ViewedArrayBuffer]]. // FIXME: Draft spec not synched with https://github.com/tc39/ecma262/pull/2723 // Step 5. Let len be O.[[ArrayLength]]. var len; if (isTypedArray) { len = TypedArrayLength(O); } else { len = callFunction( CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod" ); } // Arrays with less than two elements remain unchanged when sorted. if (len <= 1) { // Step 6. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »). var A = TypedArrayCreateSameType(O, len); // Steps 7-11. if (len > 0) { A[0] = O[0]; } // Step 12. return A; } if (comparefn === undefined) { // Step 6. Let A be ? TypedArrayCreateSameType(O, « 𝔽(len) »). var A = TypedArrayCreateSameType(O, len); // Steps 7-11 not followed exactly; this implementation copies the list and then // sorts the copy, rather than calling a sort method that copies the list and then // copying the result again. // Equivalent to steps 10-11. for (var k = 0; k < len; k++) { A[k] = O[k]; } // Equivalent to steps 7-9 and 12. return TypedArrayNativeSort(A); } // Steps 7-8. var wrappedCompareFn = TypedArraySortCompare(comparefn); // Steps 6 and 9-12. // // MergeSortTypedArray returns a sorted copy - exactly what we need to return. return MergeSortTypedArray(O, len, wrappedCompareFn); }