From 1f254bc0211038fe71e5e797807cd77675534a2b Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Wed, 22 Jan 2025 13:27:17 -0800 Subject: [PATCH] [Fix] `ES2024`+: `IsTypedArrayOutOfBounds`: properly handle resizable arrays --- 2024/IsTypedArrayOutOfBounds.js | 5 ++- test/tests.js | 73 +++++++++++++++++++++++++++------ 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/2024/IsTypedArrayOutOfBounds.js b/2024/IsTypedArrayOutOfBounds.js index 436e03d3..0fac92bd 100644 --- a/2024/IsTypedArrayOutOfBounds.js +++ b/2024/IsTypedArrayOutOfBounds.js @@ -3,6 +3,7 @@ var $TypeError = require('es-errors/type'); var IsDetachedBuffer = require('./IsDetachedBuffer'); +var IsFixedLengthArrayBuffer = require('./IsFixedLengthArrayBuffer'); var TypedArrayElementSize = require('./TypedArrayElementSize'); var isTypedArrayWithBufferWitnessRecord = require('../helpers/records/typed-array-with-buffer-witness-record'); @@ -32,8 +33,10 @@ module.exports = function IsTypedArrayOutOfBounds(taRecord) { var byteOffsetStart = typedArrayByteOffset(O); // step 5 + var isFixed = IsFixedLengthArrayBuffer(typedArrayBuffer(O)); + var byteOffsetEnd; - var length = typedArrayLength(O); + var length = isFixed ? typedArrayLength(O) : 'AUTO'; // TODO: probably use package for array length // seems to apply when TA is backed by a resizable/growable AB if (length === 'AUTO') { // step 6 diff --git a/test/tests.js b/test/tests.js index bb16d8ed..823638f6 100644 --- a/test/tests.js +++ b/test/tests.js @@ -16468,25 +16468,74 @@ var es2024 = function ES2024(ES, ops, expectedMissing, skips) { ); }); - t.test('detached buffer', { skip: !esV.canDetach }, function (st) { - var ab = new ArrayBuffer(8); + t.test('actual typed arrays', { skip: availableTypedArrays.length === 0 }, function (st) { + forEach(availableTypedArrays, function (TypedArray) { + st.test('detached buffer', { skip: !esV.canDetach }, function (s2t) { + var ab = new ArrayBuffer(8); - var ta = new Uint8Array(ab); + var ta = new Uint8Array(ab); - var preDetachedRecord = ES.MakeTypedArrayWithBufferWitnessRecord(ta, 'UNORDERED'); + var preDetachedRecord = ES.MakeTypedArrayWithBufferWitnessRecord(ta, 'UNORDERED'); - st.equal(ES.IsTypedArrayOutOfBounds(preDetachedRecord), false); + s2t.equal(ES.IsTypedArrayOutOfBounds(preDetachedRecord), false); - ES.DetachArrayBuffer(ab); + ES.DetachArrayBuffer(ab); - var postDetachedRecord = ES.MakeTypedArrayWithBufferWitnessRecord(ta, 'UNORDERED'); + var postDetachedRecord = ES.MakeTypedArrayWithBufferWitnessRecord(ta, 'UNORDERED'); - st['throws']( - function () { ES.IsTypedArrayOutOfBounds(preDetachedRecord); }, - TypeError - ); + s2t['throws']( + function () { ES.IsTypedArrayOutOfBounds(preDetachedRecord); }, + TypeError + ); + + s2t.equal(ES.IsTypedArrayOutOfBounds(postDetachedRecord), true); + + s2t.end(); + }); + + st.test('Typed Array: ' + TypedArray, function (tat) { + var TA = global[TypedArray]; + + tat.test('non-fixed length, return length * elementSize', { skip: !('resizable' in ArrayBuffer.prototype) }, function (tast) { + var ab = new ArrayBuffer(8, { maxByteLength: 64 }); + var rta = new TA(ab); + + tast.equal( + ES.IsTypedArrayOutOfBounds(ES.MakeTypedArrayWithBufferWitnessRecord(rta, 'UNORDERED')), + false, + 'resizable ArrayBuffer’s Typed Array (' + TypedArray + ') is not out of bounds' + ); + + tast.end(); + }); - st.equal(ES.IsTypedArrayOutOfBounds(postDetachedRecord), true); + tat.test('non-fixed length, detached returns zero', { skip: !esV.canDetach }, function (tast) { + var ab = new ArrayBuffer(8, { maxByteLength: 64 }); + var rta = new TA(ab); + + ES.DetachArrayBuffer(ab); + + tast.equal( + ES.IsTypedArrayOutOfBounds(ES.MakeTypedArrayWithBufferWitnessRecord(rta, 'UNORDERED')), + true, + 'resizable ArrayBuffer’s detached Typed Array (' + TypedArray + ') is out of bounds' + ); + + tast.end(); + }); + + // TODO true for byteOffsetStart > bufferByteLength || byteOffsetEnd > bufferByteLength + // not sure how to produce these TAs + + for (var i = 0; i < 8; i += 1) { + tat.equal( + ES.IsTypedArrayOutOfBounds(ES.MakeTypedArrayWithBufferWitnessRecord(new TA(new ArrayBuffer(640), i * 8), 'UNORDERED')), + false, + 'byteOffset ' + (i * 8) + ' is not out of bounds' + ); + } + }); + }); st.end(); });