1
0
mirror of https://github.com/roytam1/UXP.git synced 2026-05-26 05:46:58 +00:00

Issue #2551 - implement TypedArray.prototype.with

This commit is contained in:
Basilisk-Dev
2026-03-23 08:50:01 -04:00
committed by roytam1
parent a704425358
commit 3d131186be
4 changed files with 148 additions and 0 deletions
+59
View File
@@ -37,6 +37,10 @@ function TypedArrayLengthMethod() {
return TypedArrayLength(this);
}
function TypedArrayContentTypeIsBigIntMethod() {
return IsBigInt64TypedArray(this) || IsBigUint64TypedArray(this);
}
function GetAttachedArrayBuffer(tarray) {
var buffer = ViewedArrayBufferIfReified(tarray);
if (IsDetachedBuffer(buffer))
@@ -895,6 +899,61 @@ function TypedArrayToReversed() {
return A;
}
// ES2023 23.2.3.36 %TypedArray%.prototype.with ( index, value )
function TypedArrayWith(index, value) {
// 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");
// Steps 4-6.
var relativeIndex = ToInteger(index);
var actualIndex = relativeIndex >= 0 ? relativeIndex : len + relativeIndex;
// Steps 7-8.
var isBigIntContentType;
if (isTypedArray) {
isBigIntContentType = callFunction(TypedArrayContentTypeIsBigIntMethod, O);
} else {
isBigIntContentType = callFunction(CallTypedArrayMethodIfWrapped, O,
"TypedArrayContentTypeIsBigIntMethod");
}
var numericValue = isBigIntContentType ? ToBigInt(value) : ToNumber(value);
// Step 9.
if (actualIndex < 0 || actualIndex >= len)
ThrowRangeError(JSMSG_BAD_INDEX);
// Step 10.
var A = TypedArrayCreateSameType(O, len);
// Steps 11-12.
for (var k = 0; k < len; k++) {
var fromValue;
if (k === actualIndex) {
fromValue = numericValue;
} else {
fromValue = O[k];
}
A[k] = fromValue;
}
// Step 13.
return A;
}
// ES6 draft 20150220 22.2.3.22.1 %TypedArray%.prototype.set(array [, offset])
function SetFromNonTypedArray(target, array, targetOffset, targetLength, targetBuffer) {
assert(!IsPossiblyWrappedTypedArray(array),
@@ -97,6 +97,10 @@ assertThrowsInstanceOf(() => {
array.values();
}, TypeError);
assertThrowsInstanceOf(() => {
array.with(POISON, POISON);
}, TypeError);
assertThrowsInstanceOf(() => {
array.every(POISON);
}, TypeError);
+84
View File
@@ -0,0 +1,84 @@
for (var constructor of anyTypedArrayConstructors) {
assertEq(constructor.prototype.with.length, 2);
var original = new constructor([1, 2, 3, 4]);
var updated = original.with(1, 9);
assertDeepEq(updated, new constructor([1, 9, 3, 4]));
assertDeepEq(original, new constructor([1, 2, 3, 4]));
assertEq(updated === original, false);
assertEq(updated.constructor, constructor);
assertDeepEq(new constructor([1, 2, 3]).with(-1, 7),
new constructor([1, 2, 7]));
assertDeepEq(new constructor([1, 2, 3]).with(-0, 7),
new constructor([7, 2, 3]));
assertThrowsInstanceOf(() => {
new constructor([1, 2, 3]).with(3, 9);
}, RangeError);
assertThrowsInstanceOf(() => {
new constructor([1, 2, 3]).with(-4, 9);
}, RangeError);
var valueOrder = [];
var value = {
valueOf() {
valueOrder.push("valueOf");
return 9;
}
};
assertThrowsInstanceOf(() => {
new constructor([1, 2, 3]).with(9, value);
}, RangeError);
assertEq(valueOrder.join(","), "valueOf");
var ctorIgnored = new constructor([5, 6, 7]);
Object.defineProperty(ctorIgnored, "constructor", {
get() {
throw new Error("constructor accessor called");
}
});
assertDeepEq(ctorIgnored.with(0, 4), new constructor([4, 6, 7]));
if (constructor === Uint8ClampedArray ||
(typeof isSharedConstructor === "function" && isSharedConstructor(constructor) &&
constructor.name === Uint8ClampedArray.name))
{
assertDeepEq(new constructor([0, 1, 2]).with(1, 2.6),
new constructor([0, 3, 2]));
}
var invalidReceivers = [undefined, null, 1, false, "", Symbol(), [], {}, /./,
new Proxy(new constructor(), {})];
invalidReceivers.forEach(invalidReceiver => {
assertThrowsInstanceOf(() => {
constructor.prototype.with.call(invalidReceiver, 0, 1);
}, TypeError,
"Assert that with fails if this value is not a TypedArray");
});
}
for (var constructor of typedArrayConstructors) {
if (typeof newGlobal === "function") {
var withFn = newGlobal()[constructor.name].prototype.with;
var original = new constructor([3, 2, 1]);
var updated = withFn.call(original, 1, 8);
assertDeepEq(updated, new constructor([3, 8, 1]));
assertDeepEq(original, new constructor([3, 2, 1]));
}
}
if (typeof BigInt64Array === "function" && typeof BigUint64Array === "function") {
var bigIntArray = new BigInt64Array([1n, 2n, 3n]);
assertEq(BigInt64Array.prototype.with.length, 2);
assertDeepEq(bigIntArray.with(1, 9n), new BigInt64Array([1n, 9n, 3n]));
assertThrowsInstanceOf(() => bigIntArray.with(1, 9), TypeError);
var bigUintArray = new BigUint64Array([1n, 2n, 3n]);
assertDeepEq(bigUintArray.with(2, 4n), new BigUint64Array([1n, 2n, 4n]));
assertThrowsInstanceOf(() => bigUintArray.with(9, 1), TypeError);
}
if (typeof reportCompare === "function")
reportCompare(true, true);
+1
View File
@@ -1629,6 +1629,7 @@ TypedArrayObject::protoFunctions[] = {
JS_SELF_HOSTED_FN("reduceRight", "TypedArrayReduceRight", 1, 0),
JS_SELF_HOSTED_FN("reverse", "TypedArrayReverse", 0, 0),
JS_SELF_HOSTED_FN("toReversed", "TypedArrayToReversed", 0, 0),
JS_SELF_HOSTED_FN("with", "TypedArrayWith", 2, 0),
JS_SELF_HOSTED_FN("slice", "TypedArraySlice", 2, 0),
JS_SELF_HOSTED_FN("some", "TypedArraySome", 1, 0),
JS_SELF_HOSTED_FN("sort", "TypedArraySort", 1, 0),