mirror of https://github.com/tc39/test262.git
RAB: Integrate staging tests for the .subarray method (#4177)
* Import relevant files from #3888 * Adds resizableArrayBufferUtils.js to includes and removes its content from each test * renamed tests to indicate the end argument is tested too * Adds more tests for the 'end' argument of .subarray
This commit is contained in:
parent
cb4a6c8074
commit
224c5c3cb9
|
@ -0,0 +1,106 @@
|
|||
// Copyright 2023 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-%typedarray%.prototype.subarray
|
||||
description: >
|
||||
TypedArray.p.subarray behaves correctly on TypedArrays backed by resizable
|
||||
buffers that are grown by argument coercion.
|
||||
includes: [compareArray.js, resizableArrayBufferUtils.js]
|
||||
features: [resizable-arraybuffer]
|
||||
---*/
|
||||
|
||||
// Orig. array: [0, 2, 4, 6]
|
||||
// [0, 2, 4, 6] << fixedLength
|
||||
// [0, 2, 4, 6, ...] << lengthTracking
|
||||
|
||||
// Growing a fixed length TA back in bounds.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
// Make `fixedLength` OOB.
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
const evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(4 * ctor.BYTES_PER_ELEMENT);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
// The length computation is done before parameter conversion. At that
|
||||
// point, the length is 0, since the TA is OOB.
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(evil, 1)), []);
|
||||
}
|
||||
|
||||
// As above but with the second parameter conversion growing the buffer.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
// Make `fixedLength` OOB.
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
const evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(4 * ctor.BYTES_PER_ELEMENT);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
// The length computation is done before parameter conversion. At that
|
||||
// point, the length is 0, since the TA is OOB.
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(0, evil)), []);
|
||||
}
|
||||
|
||||
|
||||
// Growing + fixed-length TA. Growing won't affect anything.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
const evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(evil)), [
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
6
|
||||
]);
|
||||
}
|
||||
|
||||
// As above but with the second parameter conversion growing the buffer.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
const evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
|
||||
return 4;
|
||||
}
|
||||
};
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(0, evil)), [
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
6
|
||||
]);
|
||||
}
|
||||
|
||||
// Growing + length-tracking TA. The length computation is done with the
|
||||
// original length.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const lengthTracking = new ctor(rab, 0);
|
||||
const evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
assert.compareArray(
|
||||
ToNumbers(lengthTracking.subarray(evil, lengthTracking.length)), [
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
6
|
||||
]);
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
// Copyright 2023 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-%typedarray%.prototype.subarray
|
||||
description: >
|
||||
TypedArray.p.subarray behaves correctly on TypedArrays backed by resizable
|
||||
buffers that are shrunk by argument coercion.
|
||||
includes: [compareArray.js, resizableArrayBufferUtils.js]
|
||||
features: [resizable-arraybuffer]
|
||||
---*/
|
||||
|
||||
// Orig. array: [0, 2, 4, 6]
|
||||
// [0, 2, 4, 6] << fixedLength
|
||||
// [0, 2, 4, 6, ...] << lengthTracking
|
||||
|
||||
|
||||
// Fixed-length TA + first parameter conversion shrinks. The old length is
|
||||
// used in the length computation, and the subarray construction fails.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
let evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
assert.throws(RangeError, () => {
|
||||
fixedLength.subarray(evil);
|
||||
});
|
||||
}
|
||||
|
||||
// Like the previous test, but now we construct a smaller subarray and it
|
||||
// succeeds.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
let evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(evil, 1)), [0]);
|
||||
}
|
||||
|
||||
// As above but with the second parameter conversion shrinking the buffer.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
let evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(0,evil)), [0]);
|
||||
}
|
||||
|
||||
// Fixed-length TA + second parameter conversion shrinks. The old length is
|
||||
// used in the length computation, and the subarray construction fails.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
let evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 3;
|
||||
}
|
||||
};
|
||||
assert.throws(RangeError, () => {
|
||||
fixedLength.subarray(0, evil);
|
||||
});
|
||||
}
|
||||
|
||||
// Like the previous test, but now we construct a smaller subarray and it
|
||||
// succeeds.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
let evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(0, evil)), [0]);
|
||||
}
|
||||
|
||||
// Shrinking + fixed-length TA, subarray construction succeeds even though the
|
||||
// TA goes OOB.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
const evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(evil, 1)), [0]);
|
||||
}
|
||||
|
||||
// As above but with the second parameter conversion shrinking the buffer.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
const evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(0,evil)), [0]);
|
||||
}
|
||||
|
||||
// Length-tracking TA + first parameter conversion shrinks. The old length is
|
||||
// used in the length computation, and the subarray construction fails.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const lengthTracking = new ctor(rab);
|
||||
let evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
assert.throws(RangeError, () => {
|
||||
lengthTracking.subarray(evil, lengthTracking.length);
|
||||
});
|
||||
}
|
||||
|
||||
// Like the previous test, but now we construct a smaller subarray and it
|
||||
// succeeds.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const lengthTracking = new ctor(rab);
|
||||
let evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
assert.compareArray(ToNumbers(lengthTracking.subarray(evil, 1)), [0]);
|
||||
}
|
||||
|
||||
// As above but with the second parameter conversion shrinking the buffer.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const lengthTracking = new ctor(rab);
|
||||
let evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
assert.compareArray(ToNumbers(lengthTracking.subarray(0,evil)), [0]);
|
||||
}
|
||||
|
||||
// Length-tracking TA + first parameter conversion shrinks. The second
|
||||
// parameter is negative -> the relative index is not recomputed, and the
|
||||
// subarray construction fails.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const lengthTracking = new ctor(rab);
|
||||
let evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
assert.throws(RangeError, () => {
|
||||
lengthTracking.subarray(evil, -1);
|
||||
});
|
||||
}
|
||||
|
||||
// Length-tracking TA + second parameter conversion shrinks. The second
|
||||
// parameter is too large -> the subarray construction fails.
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateRabForTest(ctor);
|
||||
const lengthTracking = new ctor(rab);
|
||||
let evil = {
|
||||
valueOf: () => {
|
||||
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
|
||||
return 3;
|
||||
}
|
||||
};
|
||||
assert.throws(RangeError, () => {
|
||||
lengthTracking.subarray(0, evil);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
// Copyright 2023 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-%typedarray%.prototype.subarray
|
||||
description: >
|
||||
TypedArray.p.subarray behaves correctly on TypedArrays backed by resizable
|
||||
buffers.
|
||||
includes: [compareArray.js, resizableArrayBufferUtils.js]
|
||||
features: [resizable-arraybuffer]
|
||||
---*/
|
||||
|
||||
for (let ctor of ctors) {
|
||||
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
|
||||
const fixedLength = new ctor(rab, 0, 4);
|
||||
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 2);
|
||||
const lengthTracking = new ctor(rab, 0);
|
||||
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
|
||||
// Write some data into the array.
|
||||
const taWrite = new ctor(rab);
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
WriteToTypedArray(taWrite, i, 2 * i);
|
||||
}
|
||||
|
||||
// Orig. array: [0, 2, 4, 6]
|
||||
// [0, 2, 4, 6] << fixedLength
|
||||
// [4, 6] << fixedLengthWithOffset
|
||||
// [0, 2, 4, 6, ...] << lengthTracking
|
||||
// [4, 6, ...] << lengthTrackingWithOffset
|
||||
|
||||
const fixedLengthSubFull = fixedLength.subarray(0);
|
||||
assert.compareArray(ToNumbers(fixedLengthSubFull), [
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
6
|
||||
]);
|
||||
const fixedLengthWithOffsetSubFull = fixedLengthWithOffset.subarray(0);
|
||||
assert.compareArray(ToNumbers(fixedLengthWithOffsetSubFull), [
|
||||
4,
|
||||
6
|
||||
]);
|
||||
const lengthTrackingSubFull = lengthTracking.subarray(0);
|
||||
assert.compareArray(ToNumbers(lengthTrackingSubFull), [
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
6
|
||||
]);
|
||||
const lengthTrackingWithOffsetSubFull = lengthTrackingWithOffset.subarray(0);
|
||||
assert.compareArray(ToNumbers(lengthTrackingWithOffsetSubFull), [
|
||||
4,
|
||||
6
|
||||
]);
|
||||
|
||||
// Relative offsets
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(-2)), [
|
||||
4,
|
||||
6
|
||||
]);
|
||||
assert.compareArray(ToNumbers(fixedLengthWithOffset.subarray(-1)), [6]);
|
||||
assert.compareArray(ToNumbers(lengthTracking.subarray(-2)), [
|
||||
4,
|
||||
6
|
||||
]);
|
||||
assert.compareArray(ToNumbers(lengthTrackingWithOffset.subarray(-1)), [6]);
|
||||
|
||||
// Shrink so that fixed length TAs go out of bounds.
|
||||
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
|
||||
|
||||
// Orig. array: [0, 2, 4]
|
||||
// [0, 2, 4, ...] << lengthTracking
|
||||
// [4, ...] << lengthTrackingWithOffset
|
||||
|
||||
// We can create subarrays of OOB arrays (which have length 0), as long as
|
||||
// the new arrays are not OOB.
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(0)), []);
|
||||
assert.compareArray(ToNumbers(fixedLengthWithOffset.subarray(0)), []);
|
||||
assert.compareArray(ToNumbers(lengthTracking.subarray(0)), [
|
||||
0,
|
||||
2,
|
||||
4
|
||||
]);
|
||||
assert.compareArray(ToNumbers(lengthTrackingWithOffset.subarray(0)), [4]);
|
||||
|
||||
// Also the previously created subarrays are OOB.
|
||||
assert.sameValue(fixedLengthSubFull.length, 0);
|
||||
assert.sameValue(fixedLengthWithOffsetSubFull.length, 0);
|
||||
|
||||
// Relative offsets
|
||||
assert.compareArray(ToNumbers(lengthTracking.subarray(-2)), [
|
||||
2,
|
||||
4
|
||||
]);
|
||||
assert.compareArray(ToNumbers(lengthTrackingWithOffset.subarray(-1)), [4]);
|
||||
|
||||
// Shrink so that the TAs with offset go out of bounds.
|
||||
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(0)), []);
|
||||
assert.compareArray(ToNumbers(lengthTracking.subarray(0)), [0]);
|
||||
|
||||
// Even the 0-length subarray of fixedLengthWithOffset would be OOB ->
|
||||
// this throws.
|
||||
assert.throws(RangeError, () => {
|
||||
fixedLengthWithOffset.subarray(0);
|
||||
});
|
||||
|
||||
// Also the previously created subarrays are OOB.
|
||||
assert.sameValue(fixedLengthSubFull.length, 0);
|
||||
assert.sameValue(fixedLengthWithOffsetSubFull.length, 0);
|
||||
assert.sameValue(lengthTrackingWithOffsetSubFull.length, 0);
|
||||
|
||||
// Shrink to zero.
|
||||
rab.resize(0);
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(0)), []);
|
||||
assert.compareArray(ToNumbers(lengthTracking.subarray(0)), []);
|
||||
assert.throws(RangeError, () => {
|
||||
fixedLengthWithOffset.subarray(0);
|
||||
});
|
||||
assert.throws(RangeError, () => {
|
||||
lengthTrackingWithOffset.subarray(0);
|
||||
});
|
||||
|
||||
// Also the previously created subarrays are OOB.
|
||||
assert.sameValue(fixedLengthSubFull.length, 0);
|
||||
assert.sameValue(fixedLengthWithOffsetSubFull.length, 0);
|
||||
assert.sameValue(lengthTrackingWithOffsetSubFull.length, 0);
|
||||
|
||||
// Grow so that all TAs are back in-bounds.
|
||||
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
|
||||
for (let i = 0; i < 6; ++i) {
|
||||
WriteToTypedArray(taWrite, i, 2 * i);
|
||||
}
|
||||
|
||||
// Orig. array: [0, 2, 4, 6, 8, 10]
|
||||
// [0, 2, 4, 6] << fixedLength
|
||||
// [4, 6] << fixedLengthWithOffset
|
||||
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
|
||||
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
|
||||
|
||||
assert.compareArray(ToNumbers(fixedLength.subarray(0)), [
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
6
|
||||
]);
|
||||
assert.compareArray(ToNumbers(fixedLengthWithOffset.subarray(0)), [
|
||||
4,
|
||||
6
|
||||
]);
|
||||
assert.compareArray(ToNumbers(lengthTracking.subarray(0)), [
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
6,
|
||||
8,
|
||||
10
|
||||
]);
|
||||
assert.compareArray(ToNumbers(lengthTrackingWithOffset.subarray(0)), [
|
||||
4,
|
||||
6,
|
||||
8,
|
||||
10
|
||||
]);
|
||||
|
||||
// Also the previously created subarrays are no longer OOB.
|
||||
assert.sameValue(fixedLengthSubFull.length, 4);
|
||||
assert.sameValue(fixedLengthWithOffsetSubFull.length, 2);
|
||||
// Subarrays of length-tracking TAs are also length-tracking.
|
||||
assert.sameValue(lengthTrackingSubFull.length, 6);
|
||||
assert.sameValue(lengthTrackingWithOffsetSubFull.length, 4);
|
||||
}
|
Loading…
Reference in New Issue