From 3e05786b77ebb9e3ef12e4ced1b55fb2bf072e23 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Fri, 15 May 2026 21:26:56 -0400 Subject: [PATCH] Fix ArrayBuffer slice after resizable source shrink --- js/src/builtin/TypedArray.js | 5 +++- .../non262/ArrayBuffer/resizable-transfer.js | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/js/src/builtin/TypedArray.js b/js/src/builtin/TypedArray.js index b5a3b2a011..4311f27079 100644 --- a/js/src/builtin/TypedArray.js +++ b/js/src/builtin/TypedArray.js @@ -1877,7 +1877,10 @@ function ArrayBufferSlice(start, end) { ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED); // Steps 19-21. - ArrayBufferCopyData(new_, 0, O, first | 0, newLen | 0, isWrapped); + var currentLen = ArrayBufferByteLength(O); + var copyLen = first >= currentLen ? 0 : std_Math_min(newLen, currentLen - first); + if (copyLen > 0) + ArrayBufferCopyData(new_, 0, O, first | 0, copyLen | 0, isWrapped); // Step 22. return new_; diff --git a/js/src/tests/non262/ArrayBuffer/resizable-transfer.js b/js/src/tests/non262/ArrayBuffer/resizable-transfer.js index b9f9dbb13a..b05a0deffa 100644 --- a/js/src/tests/non262/ArrayBuffer/resizable-transfer.js +++ b/js/src/tests/non262/ArrayBuffer/resizable-transfer.js @@ -62,6 +62,33 @@ assertEq(fixedMoved.maxByteLength, 10); assertEq(fixedMoved.resizable, false); assertEq(new Uint8Array(fixedMoved)[0], 7); +var sliceSource = new ArrayBuffer(8, { maxByteLength: 8 }); +var sliceSourceBytes = new Uint8Array(sliceSource); +for (var i = 0; i < sliceSourceBytes.length; i++) + sliceSourceBytes[i] = i + 1; + +sliceSource.constructor = { + [Symbol.species]: function(byteLength) { + sliceSource.resize(4); + return new ArrayBuffer(byteLength); + } +}; + +var sliced = sliceSource.slice(2, 8); +var slicedBytes = new Uint8Array(sliced); +assertEq(sliced.byteLength, 6); +assertEq(slicedBytes[0], 3); +assertEq(slicedBytes[1], 4); +assertEq(slicedBytes[2], 0); +assertEq(slicedBytes[5], 0); + +sliceSource.resize(8); +for (var i = 0; i < sliceSourceBytes.length; i++) + sliceSourceBytes[i] = i + 1; +var zeroCopied = sliceSource.slice(6, 8); +assertEq(zeroCopied.byteLength, 2); +assertEq(new Uint8Array(zeroCopied)[0], 0); + assertThrowsInstanceOf(() => new ArrayBuffer(4, { maxByteLength: 3 }), RangeError); if (typeof reportCompare === "function")