summaryrefslogtreecommitdiffstats
path: root/js/src/builtin/TypedArray.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin/TypedArray.js')
-rw-r--r--js/src/builtin/TypedArray.js2268
1 files changed, 2268 insertions, 0 deletions
diff --git a/js/src/builtin/TypedArray.js b/js/src/builtin/TypedArray.js
new file mode 100644
index 0000000000..6f0e713abf
--- /dev/null
+++ b/js/src/builtin/TypedArray.js
@@ -0,0 +1,2268 @@
+/* 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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 <https://github.com/tc39/ecma262/pull/2221>
+// 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);
+}