RAB: Integrate helper to rest of the tests (#4198)

Co-authored-by: Philip Chimento <philip.chimento@gmail.com>
This commit is contained in:
Ioanna M Dimitriou H 2024-08-27 17:18:44 +02:00 committed by GitHub
parent a4443793b9
commit 3acb672d11
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 1722 additions and 0 deletions

View File

@ -0,0 +1,99 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-function.prototype.apply
description: >
Function.p.apply behaves correctly when the argument array is a
TypedArray backed by resizable buffer
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);
const taWrite = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, i);
}
function func(...args) {
return [...args];
}
assert.compareArray(ToNumbers(func.apply(null, fixedLength)), [
0,
1,
2,
3
]);
assert.compareArray(ToNumbers(func.apply(null, fixedLengthWithOffset)), [
2,
3
]);
assert.compareArray(ToNumbers(func.apply(null, lengthTracking)), [
0,
1,
2,
3
]);
assert.compareArray(ToNumbers(func.apply(null, lengthTrackingWithOffset)), [
2,
3
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
assert.compareArray(ToNumbers(func.apply(null, fixedLength)), []);
assert.compareArray(ToNumbers(func.apply(null, fixedLengthWithOffset)), []);
assert.compareArray(ToNumbers(func.apply(null, lengthTracking)), [
0,
1,
2
]);
assert.compareArray(ToNumbers(func.apply(null, lengthTrackingWithOffset)), [2]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.compareArray(ToNumbers(func.apply(null, fixedLength)), []);
assert.compareArray(ToNumbers(func.apply(null, fixedLengthWithOffset)), []);
assert.compareArray(ToNumbers(func.apply(null, lengthTracking)), [0]);
assert.compareArray(ToNumbers(func.apply(null, lengthTrackingWithOffset)), []);
// Shrink to zero.
rab.resize(0);
assert.compareArray(ToNumbers(func.apply(null, fixedLength)), []);
assert.compareArray(ToNumbers(func.apply(null, fixedLengthWithOffset)), []);
assert.compareArray(ToNumbers(func.apply(null, lengthTracking)), []);
assert.compareArray(ToNumbers(func.apply(null, lengthTrackingWithOffset)), []);
// Grow so that all TAs are back in-bounds. New memory is zeroed.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
assert.compareArray(ToNumbers(func.apply(null, fixedLength)), [
0,
0,
0,
0
]);
assert.compareArray(ToNumbers(func.apply(null, fixedLengthWithOffset)), [
0,
0
]);
assert.compareArray(ToNumbers(func.apply(null, lengthTracking)), [
0,
0,
0,
0,
0,
0
]);
assert.compareArray(ToNumbers(func.apply(null, lengthTrackingWithOffset)), [
0,
0,
0,
0
]);
}

View File

@ -0,0 +1,216 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-object.defineproperties
description: >
Object.defineProperties behaves correctly on TypedArrays backed by
resizable buffers
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function MayNeedBigInt(ta, value) {
if (ta instanceof BigInt64Array || ta instanceof BigUint64Array) {
return BigInt(value);
} else {
return value;
}
}
function DefinePropertiesMayNeedBigInt(ta, index, value) {
const values = {};
values[index] = { value: MayNeedBigInt(ta, value) };
Object.defineProperties(ta, values);
}
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);
const taFull = new ctor(rab, 0);
// Orig. array: [0, 0, 0, 0]
// [0, 0, 0, 0] << fixedLength
// [0, 0] << fixedLengthWithOffset
// [0, 0, 0, 0, ...] << lengthTracking
// [0, 0, ...] << lengthTrackingWithOffset
DefinePropertiesMayNeedBigInt(fixedLength, 0, 1);
assert.compareArray(ToNumbers(taFull), [
1,
0,
0,
0
]);
DefinePropertiesMayNeedBigInt(fixedLengthWithOffset, 0, 2);
assert.compareArray(ToNumbers(taFull), [
1,
0,
2,
0
]);
DefinePropertiesMayNeedBigInt(lengthTracking, 1, 3);
assert.compareArray(ToNumbers(taFull), [
1,
3,
2,
0
]);
DefinePropertiesMayNeedBigInt(lengthTrackingWithOffset, 1, 4);
assert.compareArray(ToNumbers(taFull), [
1,
3,
2,
4
]);
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(fixedLength, 4, 8);
});
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(fixedLengthWithOffset, 2, 8);
});
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(lengthTracking, 4, 8);
});
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(lengthTrackingWithOffset, 2, 8);
});
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [1, 3, 2]
// [1, 3, 2, ...] << lengthTracking
// [2, ...] << lengthTrackingWithOffset
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(fixedLength, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(fixedLengthWithOffset, 0, 8);
});
assert.compareArray(ToNumbers(taFull), [
1,
3,
2
]);
DefinePropertiesMayNeedBigInt(lengthTracking, 0, 5);
assert.compareArray(ToNumbers(taFull), [
5,
3,
2
]);
DefinePropertiesMayNeedBigInt(lengthTrackingWithOffset, 0, 6);
assert.compareArray(ToNumbers(taFull), [
5,
3,
6
]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(fixedLength, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(fixedLengthWithOffset, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(lengthTrackingWithOffset, 0, 8);
});
assert.compareArray(ToNumbers(taFull), [5]);
DefinePropertiesMayNeedBigInt(lengthTracking, 0, 7);
assert.compareArray(ToNumbers(taFull), [7]);
// Shrink to zero.
rab.resize(0);
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(fixedLength, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(fixedLengthWithOffset, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(lengthTracking, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(lengthTrackingWithOffset, 0, 8);
});
assert.compareArray(ToNumbers(taFull), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
DefinePropertiesMayNeedBigInt(fixedLength, 0, 9);
assert.compareArray(ToNumbers(taFull), [
9,
0,
0,
0,
0,
0
]);
DefinePropertiesMayNeedBigInt(fixedLengthWithOffset, 0, 10);
assert.compareArray(ToNumbers(taFull), [
9,
0,
10,
0,
0,
0
]);
DefinePropertiesMayNeedBigInt(lengthTracking, 1, 11);
assert.compareArray(ToNumbers(taFull), [
9,
11,
10,
0,
0,
0
]);
DefinePropertiesMayNeedBigInt(lengthTrackingWithOffset, 2, 12);
assert.compareArray(ToNumbers(taFull), [
9,
11,
10,
0,
12,
0
]);
// Trying to define properties out of the fixed-length bounds throws.
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(fixedLength, 5, 13);
});
assert.throws(TypeError, () => {
DefinePropertiesMayNeedBigInt(fixedLengthWithOffset, 3, 13);
});
assert.compareArray(ToNumbers(taFull), [
9,
11,
10,
0,
12,
0
]);
DefinePropertiesMayNeedBigInt(lengthTracking, 4, 14);
assert.compareArray(ToNumbers(taFull), [
9,
11,
10,
0,
14,
0
]);
DefinePropertiesMayNeedBigInt(lengthTrackingWithOffset, 3, 15);
assert.compareArray(ToNumbers(taFull), [
9,
11,
10,
0,
14,
15
]);
}

View File

@ -0,0 +1,62 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-object.defineproperty
description: >
Object.defineProperty behaves correctly when the object is a
TypedArray backed by a resizable buffer that's grown during argument
coercion
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function MayNeedBigInt(ta, value) {
if (ta instanceof BigInt64Array || ta instanceof BigUint64Array) {
return BigInt(value);
} else {
return value;
}
}
// Fixed length.
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);
// Make fixedLength go OOB.
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
const evil = {
toString: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
Object.defineProperty(fixedLength, evil, { value: MayNeedBigInt(fixedLength, 8) });
assert.compareArray(ToNumbers(fixedLength), [
8,
0,
0,
0
]);
}
// Length tracking.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab, 0);
const evil = {
toString: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return 4; // Index valid after resize.
}
};
Object.defineProperty(lengthTracking, evil, { value: MayNeedBigInt(lengthTracking, 8) });
assert.compareArray(ToNumbers(lengthTracking), [
0,
0,
0,
0,
8,
0
]);
}

View File

@ -0,0 +1,50 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-object.defineproperty
description: >
Object.defineProperty behaves correctly when the object is a
TypedArray backed by a resizable buffer that's shrunk during argument
coercion
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function MayNeedBigInt(ta, value) {
if (ta instanceof BigInt64Array || ta instanceof BigUint64Array) {
return BigInt(value);
} else {
return value;
}
}
// Fixed length.
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 evil = {
toString: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.throws(TypeError, () => {
Object.defineProperty(fixedLength, evil, { value: MayNeedBigInt(fixedLength, 8) });
});
}
// Length tracking.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab, 0);
const evil = {
toString: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 3; // Index too large after resize.
}
};
assert.throws(TypeError, () => {
Object.defineProperty(lengthTracking, evil, { value: MayNeedBigInt(lengthTracking, 8) });
});
}

View File

@ -0,0 +1,214 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-object.defineproperty
description: >
Object.defineProperty behaves correctly on TypedArrays backed by
resizable buffers
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function MayNeedBigInt(ta, value) {
if (ta instanceof BigInt64Array || ta instanceof BigUint64Array) {
return BigInt(value);
} else {
return value;
}
}
function DefinePropertyMayNeedBigInt(ta, index, value) {
Object.defineProperty(ta, index, { value: MayNeedBigInt(ta, value) });
}
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);
const taFull = new ctor(rab, 0);
// Orig. array: [0, 0, 0, 0]
// [0, 0, 0, 0] << fixedLength
// [0, 0] << fixedLengthWithOffset
// [0, 0, 0, 0, ...] << lengthTracking
// [0, 0, ...] << lengthTrackingWithOffset
DefinePropertyMayNeedBigInt(fixedLength, 0, 1);
assert.compareArray(ToNumbers(taFull), [
1,
0,
0,
0
]);
DefinePropertyMayNeedBigInt(fixedLengthWithOffset, 0, 2);
assert.compareArray(ToNumbers(taFull), [
1,
0,
2,
0
]);
DefinePropertyMayNeedBigInt(lengthTracking, 1, 3);
assert.compareArray(ToNumbers(taFull), [
1,
3,
2,
0
]);
DefinePropertyMayNeedBigInt(lengthTrackingWithOffset, 1, 4);
assert.compareArray(ToNumbers(taFull), [
1,
3,
2,
4
]);
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(fixedLength, 4, 8);
});
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(fixedLengthWithOffset, 2, 8);
});
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(lengthTracking, 4, 8);
});
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(lengthTrackingWithOffset, 2, 8);
});
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [1, 3, 2]
// [1, 3, 2, ...] << lengthTracking
// [2, ...] << lengthTrackingWithOffset
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(fixedLength, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(fixedLengthWithOffset, 0, 8);
});
assert.compareArray(ToNumbers(taFull), [
1,
3,
2
]);
DefinePropertyMayNeedBigInt(lengthTracking, 0, 5);
assert.compareArray(ToNumbers(taFull), [
5,
3,
2
]);
DefinePropertyMayNeedBigInt(lengthTrackingWithOffset, 0, 6);
assert.compareArray(ToNumbers(taFull), [
5,
3,
6
]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(fixedLength, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(fixedLengthWithOffset, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(lengthTrackingWithOffset, 0, 8);
});
assert.compareArray(ToNumbers(taFull), [5]);
DefinePropertyMayNeedBigInt(lengthTracking, 0, 7);
assert.compareArray(ToNumbers(taFull), [7]);
// Shrink to zero.
rab.resize(0);
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(fixedLength, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(fixedLengthWithOffset, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(lengthTracking, 0, 8);
});
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(lengthTrackingWithOffset, 0, 8);
});
assert.compareArray(ToNumbers(taFull), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
DefinePropertyMayNeedBigInt(fixedLength, 0, 9);
assert.compareArray(ToNumbers(taFull), [
9,
0,
0,
0,
0,
0
]);
DefinePropertyMayNeedBigInt(fixedLengthWithOffset, 0, 10);
assert.compareArray(ToNumbers(taFull), [
9,
0,
10,
0,
0,
0
]);
DefinePropertyMayNeedBigInt(lengthTracking, 1, 11);
assert.compareArray(ToNumbers(taFull), [
9,
11,
10,
0,
0,
0
]);
DefinePropertyMayNeedBigInt(lengthTrackingWithOffset, 2, 12);
assert.compareArray(ToNumbers(taFull), [
9,
11,
10,
0,
12,
0
]);
// Trying to define properties out of the fixed-length bounds throws.
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(fixedLength, 5, 13);
});
assert.throws(TypeError, () => {
DefinePropertyMayNeedBigInt(fixedLengthWithOffset, 3, 13);
});
assert.compareArray(ToNumbers(taFull), [
9,
11,
10,
0,
12,
0
]);
DefinePropertyMayNeedBigInt(lengthTracking, 4, 14);
assert.compareArray(ToNumbers(taFull), [
9,
11,
10,
0,
14,
0
]);
DefinePropertyMayNeedBigInt(lengthTrackingWithOffset, 3, 15);
assert.compareArray(ToNumbers(taFull), [
9,
11,
10,
0,
14,
15
]);
}

View File

@ -0,0 +1,53 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-object.freeze
description: >
Object.freeze throws on non-0-length TypedArrays backed by resizable
buffers but do not throw on 0-length ones
features: [resizable-arraybuffer]
includes: [resizableArrayBufferUtils.js]
---*/
// Freezing non-OOB non-zero-length TAs throws.
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);
assert.throws(TypeError, () => {
Object.freeze(fixedLength);
});
assert.throws(TypeError, () => {
Object.freeze(fixedLengthWithOffset);
});
assert.throws(TypeError, () => {
Object.freeze(lengthTracking);
});
assert.throws(TypeError, () => {
Object.freeze(lengthTrackingWithOffset);
});
}
// Freezing zero-length TAs doesn't throw.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const fixedLength = new ctor(rab, 0, 0);
const fixedLengthWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT, 0);
const lengthTrackingWithOffset = new ctor(rab, 4 * ctor.BYTES_PER_ELEMENT);
Object.freeze(fixedLength);
Object.freeze(fixedLengthWithOffset);
Object.freeze(lengthTrackingWithOffset);
}
// If the buffer has been resized to make length-tracking TAs zero-length,
// freezing them also doesn't throw.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
const lengthTrackingWithOffset = new ctor(rab, 2 * ctor.BYTES_PER_ELEMENT);
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
Object.freeze(lengthTrackingWithOffset);
rab.resize(0 * ctor.BYTES_PER_ELEMENT);
Object.freeze(lengthTracking);
}

View File

@ -0,0 +1,21 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-isvalidintegerindex
description: >
TypedArrays backed by resizable buffers that are out-of-bounds behave
as if they were detached
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
const rab = CreateResizableArrayBuffer(16, 40);
const i8a = new Int8Array(rab, 0, 4);
i8a.__proto__ = { 2: 'wrong value' };
i8a[2] = 10;
assert.sameValue(i8a[2], 10);
assert(2 in i8a);
rab.resize(0);
assert.sameValue(i8a[2], undefined);
assert(!(2 in i8a));

View File

@ -0,0 +1,63 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-isvalidintegerindex
description: >
Getting and setting in-bounds and out-of-bounds indices on TypedArrays backed
by resizable buffers.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function MayNeedBigInt(ta, num) {
if (ta instanceof BigInt64Array || ta instanceof BigUint64Array) {
return BigInt(num);
} else {
return num;
}
}
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 40 * ctor.BYTES_PER_ELEMENT);
const array = new ctor(rab, 0, 4);
// Initial values
for (let i = 0; i < 4; ++i) {
assert.sameValue(Convert(array[i]), 0);
}
// Within-bounds write
for (let i = 0; i < 4; ++i) {
array[i] = MayNeedBigInt(array, i);
}
// Within-bounds read
for (let i = 0; i < 4; ++i) {
assert.sameValue(Convert(array[i]), i, `${ctor} array fails within-bounds read`);
}
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
// OOB read. If the RAB isn't large enough to fit the entire TypedArray,
// the length of the TypedArray is treated as 0.
for (let i = 0; i < 4; ++i) {
assert.sameValue(array[i], undefined);
}
// OOB write (has no effect)
for (let i = 0; i < 4; ++i) {
array[i] = MayNeedBigInt(array, 10);
}
rab.resize(4 * ctor.BYTES_PER_ELEMENT);
// Within-bounds read
for (let i = 0; i < 2; ++i) {
assert.sameValue(array[i], MayNeedBigInt(array, i));
}
// The shrunk-and-regrown part got zeroed.
for (let i = 2; i < 4; ++i) {
assert.sameValue(array[i], MayNeedBigInt(array, 0));
}
rab.resize(40 * ctor.BYTES_PER_ELEMENT);
// Within-bounds read
for (let i = 0; i < 2; ++i) {
assert.sameValue(array[i], MayNeedBigInt(array, i));
}
for (let i = 2; i < 4; ++i) {
assert.sameValue(array[i], MayNeedBigInt(array, 0));
}
}

View File

@ -0,0 +1,41 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-isvalidintegerindex
description: >
In-bound indices are testable with `in` on TypedArrays backed by resizable buffers.
info: |
IsValidIntegerIndex ( O, index )
...
6. Let length be IntegerIndexedObjectLength(O, getBufferByteLength).
7. If length is out-of-bounds or (index) < 0 or (index) length, return false.
...
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 40 * ctor.BYTES_PER_ELEMENT);
const array = new ctor(rab, 0, 4);
// Within-bounds read
for (let i = 0; i < 4; ++i) {
assert(i in array);
}
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
// OOB read. If the RAB isn't large enough to fit the entire TypedArray,
// the length of the TypedArray is treated as 0.
for (let i = 0; i < 4; ++i) {
assert(!(i in array));
}
rab.resize(4 * ctor.BYTES_PER_ELEMENT);
// Within-bounds read
for (let i = 0; i < 4; ++i) {
assert(i in array);
}
rab.resize(40 * ctor.BYTES_PER_ELEMENT);
// Within-bounds read
for (let i = 0; i < 4; ++i) {
assert(i in array);
}
}

View File

@ -0,0 +1,19 @@
// 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
description: >
TypedArrays that are backed by resizable buffers have the same prototypes
as those backed by fixed-length buffers
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
const rab = CreateResizableArrayBuffer(40, 80);
const ab = new ArrayBuffer(80);
for (let ctor of ctors) {
const ta_rab = new ctor(rab, 0, 3);
const ta_ab = new ctor(ab, 0, 3);
assert.sameValue(ta_ab.__proto__, ta_rab.__proto__);
}

View File

@ -0,0 +1,58 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-arraybuffer-length
description: >
Basic functionality of length-tracking TypedArrays backed by resizable
buffers
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
const rab = CreateResizableArrayBuffer(16, 40);
let tas = [];
for (let ctor of ctors) {
tas.push(new ctor(rab));
}
for (let ta of tas) {
assert.sameValue(ta.length, 16 / ta.BYTES_PER_ELEMENT);
assert.sameValue(ta.byteLength, 16);
}
rab.resize(40);
for (let ta of tas) {
assert.sameValue(ta.length, 40 / ta.BYTES_PER_ELEMENT);
assert.sameValue(ta.byteLength, 40);
}
// Resize to a number which is not a multiple of all byte_lengths.
rab.resize(19);
for (let ta of tas) {
const expected_length = Math.floor(19 / ta.BYTES_PER_ELEMENT);
assert.sameValue(ta.length, expected_length);
assert.sameValue(ta.byteLength, expected_length * ta.BYTES_PER_ELEMENT);
}
rab.resize(1);
for (let ta of tas) {
if (ta.BYTES_PER_ELEMENT == 1) {
assert.sameValue(ta.length, 1);
assert.sameValue(ta.byteLength, 1);
} else {
assert.sameValue(ta.length, 0);
assert.sameValue(ta.byteLength, 0);
}
}
rab.resize(0);
for (let ta of tas) {
assert.sameValue(ta.length, 0);
assert.sameValue(ta.byteLength, 0);
}
rab.resize(8);
for (let ta of tas) {
assert.sameValue(ta.length, 8 / ta.BYTES_PER_ELEMENT);
assert.sameValue(ta.byteLength, 8);
}
rab.resize(40);
for (let ta of tas) {
assert.sameValue(ta.length, 40 / ta.BYTES_PER_ELEMENT);
assert.sameValue(ta.byteLength, 40);
}

View File

@ -0,0 +1,78 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-arraybuffer-length
description: >
Length-tracking TypedArrays backed by resizable buffers with offsets
behave correctly
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
// length-tracking-1 but with offsets.
const rab = CreateResizableArrayBuffer(16, 40);
const offset = 8;
let tas = [];
for (let ctor of ctors) {
tas.push(new ctor(rab, offset));
}
for (let ta of tas) {
assert.sameValue(ta.length, (16 - offset) / ta.BYTES_PER_ELEMENT);
assert.sameValue(ta.byteLength, 16 - offset);
assert.sameValue(ta.byteOffset, offset);
}
rab.resize(40);
for (let ta of tas) {
assert.sameValue(ta.length, (40 - offset) / ta.BYTES_PER_ELEMENT);
assert.sameValue(ta.byteLength, 40 - offset);
assert.sameValue(ta.byteOffset, offset);
}
// Resize to a number which is not a multiple of all byte_lengths.
rab.resize(20);
for (let ta of tas) {
const expected_length = Math.floor((20 - offset) / ta.BYTES_PER_ELEMENT);
assert.sameValue(ta.length, expected_length);
assert.sameValue(ta.byteLength, expected_length * ta.BYTES_PER_ELEMENT);
assert.sameValue(ta.byteOffset, offset);
}
// Resize so that all TypedArrays go out of bounds (because of the offset).
rab.resize(7);
for (let ta of tas) {
assert.sameValue(ta.length, 0);
assert.sameValue(ta.byteLength, 0);
assert.sameValue(ta.byteOffset, 0);
}
rab.resize(0);
for (let ta of tas) {
assert.sameValue(ta.length, 0);
assert.sameValue(ta.byteLength, 0);
assert.sameValue(ta.byteOffset, 0);
}
rab.resize(8);
for (let ta of tas) {
assert.sameValue(ta.length, 0);
assert.sameValue(ta.byteLength, 0);
assert.sameValue(ta.byteOffset, offset);
}
// Resize so that the TypedArrays which have element size > 1 go out of bounds
// (because less than 1 full element would fit).
rab.resize(offset + 1);
for (let ta of tas) {
if (ta.BYTES_PER_ELEMENT == 1) {
assert.sameValue(ta.length, 1);
assert.sameValue(ta.byteLength, 1);
assert.sameValue(ta.byteOffset, offset);
} else {
assert.sameValue(ta.length, 0);
assert.sameValue(ta.byteLength, 0);
assert.sameValue(ta.byteOffset, offset);
}
}
rab.resize(40);
for (let ta of tas) {
assert.sameValue(ta.length, (40 - offset) / ta.BYTES_PER_ELEMENT);
assert.sameValue(ta.byteLength, 40 - offset);
assert.sameValue(ta.byteOffset, offset);
}

View File

@ -0,0 +1,36 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-initializetypedarrayfromarraybuffer
description: >
Creating a TypedArray from a resizable buffer with invalid bounds
throw RangedError
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
const rab = CreateResizableArrayBuffer(40, 80);
for (let ctor of ctors) {
// Length too big.
assert.throws(RangeError, () => {
new ctor(rab, 0, 40 / ctor.BYTES_PER_ELEMENT + 1);
});
// Offset too close to the end.
assert.throws(RangeError, () => {
new ctor(rab, 40 - ctor.BYTES_PER_ELEMENT, 2);
});
// Offset beyond end.
assert.throws(RangeError, () => {
new ctor(rab, 40, 1);
});
if (ctor.BYTES_PER_ELEMENT > 1) {
// Offset not a multiple of the byte size.
assert.throws(RangeError, () => {
new ctor(rab, 1, 1);
});
assert.throws(RangeError, () => {
new ctor(rab, 1);
});
}
}

View File

@ -0,0 +1,150 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-initializetypedarrayfromtypedarray
description: >
Initializing a TypedArray from another TypedArray that is backed by a
resizable buffer
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function IsBigIntTypedArray(ta) {
return ta instanceof BigInt64Array || ta instanceof BigUint64Array;
}
function AllBigIntMatchedCtorCombinations(test) {
for (let targetCtor of ctors) {
for (let sourceCtor of ctors) {
if (IsBigIntTypedArray(new targetCtor()) != IsBigIntTypedArray(new sourceCtor())) {
continue;
}
test(targetCtor, sourceCtor);
}
}
}
AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
const rab = CreateResizableArrayBuffer(4 * sourceCtor.BYTES_PER_ELEMENT, 8 * sourceCtor.BYTES_PER_ELEMENT);
const fixedLength = new sourceCtor(rab, 0, 4);
const fixedLengthWithOffset = new sourceCtor(rab, 2 * sourceCtor.BYTES_PER_ELEMENT, 2);
const lengthTracking = new sourceCtor(rab, 0);
const lengthTrackingWithOffset = new sourceCtor(rab, 2 * sourceCtor.BYTES_PER_ELEMENT);
// Write some data into the array.
const taFull = new sourceCtor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taFull, i, i + 1);
}
// Orig. array: [1, 2, 3, 4]
// [1, 2, 3, 4] << fixedLength
// [3, 4] << fixedLengthWithOffset
// [1, 2, 3, 4, ...] << lengthTracking
// [3, 4, ...] << lengthTrackingWithOffset
assert.compareArray(ToNumbers(new targetCtor(fixedLength)), [
1,
2,
3,
4
]);
assert.compareArray(ToNumbers(new targetCtor(fixedLengthWithOffset)), [
3,
4
]);
assert.compareArray(ToNumbers(new targetCtor(lengthTracking)), [
1,
2,
3,
4
]);
assert.compareArray(ToNumbers(new targetCtor(lengthTrackingWithOffset)), [
3,
4
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * sourceCtor.BYTES_PER_ELEMENT);
// Orig. array: [1, 2, 3]
// [1, 2, 3, ...] << lengthTracking
// [3, ...] << lengthTrackingWithOffset
assert.throws(TypeError, () => {
new targetCtor(fixedLength);
});
assert.throws(TypeError, () => {
new targetCtor(fixedLengthWithOffset);
});
assert.compareArray(ToNumbers(new targetCtor(lengthTracking)), [
1,
2,
3
]);
assert.compareArray(ToNumbers(new targetCtor(lengthTrackingWithOffset)), [3]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * sourceCtor.BYTES_PER_ELEMENT);
assert.throws(TypeError, () => {
new targetCtor(fixedLength);
});
assert.throws(TypeError, () => {
new targetCtor(fixedLengthWithOffset);
});
assert.compareArray(ToNumbers(new targetCtor(lengthTracking)), [1]);
assert.throws(TypeError, () => {
new targetCtor(lengthTrackingWithOffset);
});
// Shrink to zero.
rab.resize(0);
assert.throws(TypeError, () => {
new targetCtor(fixedLength);
});
assert.throws(TypeError, () => {
new targetCtor(fixedLengthWithOffset);
});
assert.compareArray(ToNumbers(new targetCtor(lengthTracking)), []);
assert.throws(TypeError, () => {
new targetCtor(lengthTrackingWithOffset);
});
// Grow so that all TAs are back in-bounds.
rab.resize(6 * sourceCtor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taFull, i, i + 1);
}
// Orig. array: [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4] << fixedLength
// [3, 4] << fixedLengthWithOffset
// [1, 2, 3, 4, 5, 6, ...] << lengthTracking
// [3, 4, 5, 6, ...] << lengthTrackingWithOffset
assert.compareArray(ToNumbers(new targetCtor(fixedLength)), [
1,
2,
3,
4
]);
assert.compareArray(ToNumbers(new targetCtor(fixedLengthWithOffset)), [
3,
4
]);
assert.compareArray(ToNumbers(new targetCtor(lengthTracking)), [
1,
2,
3,
4,
5,
6
]);
assert.compareArray(ToNumbers(new targetCtor(lengthTrackingWithOffset)), [
3,
4,
5,
6
]);
});

View File

@ -0,0 +1,199 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-arraybuffer-length
description: >
Destructuring assignment on TypedArrays backed by resizable buffer
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.
let ta_write = new ctor(rab);
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(ta_write, i, i);
}
{
let [a, b, c, d, e] = fixedLength;
assert.compareArray(ToNumbers([
a,
b,
c,
d
]), [
0,
1,
2,
3
]);
assert.sameValue(e, undefined);
}
{
let [a, b, c] = fixedLengthWithOffset;
assert.compareArray(ToNumbers([
a,
b
]), [
2,
3
]);
assert.sameValue(c, undefined);
}
{
let [a, b, c, d, e] = lengthTracking;
assert.compareArray(ToNumbers([
a,
b,
c,
d
]), [
0,
1,
2,
3
]);
assert.sameValue(e, undefined);
}
{
let [a, b, c] = lengthTrackingWithOffset;
assert.compareArray(ToNumbers([
a,
b
]), [
2,
3
]);
assert.sameValue(c, undefined);
}
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
assert.throws(TypeError, () => {
let [a, b, c] = fixedLength;
});
assert.throws(TypeError, () => {
let [a, b, c] = fixedLengthWithOffset;
});
{
let [a, b, c, d] = lengthTracking;
assert.compareArray(ToNumbers([
a,
b,
c
]), [
0,
1,
2
]);
assert.sameValue(d, undefined);
}
{
let [a, b] = lengthTrackingWithOffset;
assert.compareArray(ToNumbers([a]), [2]);
assert.sameValue(b, undefined);
}
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.throws(TypeError, () => {
let [a, b, c] = fixedLength;
});
assert.throws(TypeError, () => {
let [a, b, c] = fixedLengthWithOffset;
});
assert.throws(TypeError, () => {
let [a, b, c] = lengthTrackingWithOffset;
});
{
let [a, b] = lengthTracking;
assert.compareArray(ToNumbers([a]), [0]);
assert.sameValue(b, undefined);
}
// Shrink to 0.
rab.resize(0);
assert.throws(TypeError, () => {
let [a, b, c] = fixedLength;
});
assert.throws(TypeError, () => {
let [a, b, c] = fixedLengthWithOffset;
});
assert.throws(TypeError, () => {
let [a, b, c] = lengthTrackingWithOffset;
});
{
let [a] = lengthTracking;
assert.sameValue(a, undefined);
}
// Grow so that all TAs are back in-bounds. The new memory is zeroed.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
{
let [a, b, c, d, e] = fixedLength;
assert.compareArray(ToNumbers([
a,
b,
c,
d
]), [
0,
0,
0,
0
]);
assert.sameValue(e, undefined);
}
{
let [a, b, c] = fixedLengthWithOffset;
assert.compareArray(ToNumbers([
a,
b
]), [
0,
0
]);
assert.sameValue(c, undefined);
}
{
let [a, b, c, d, e, f, g] = lengthTracking;
assert.compareArray(ToNumbers([
a,
b,
c,
d,
e,
f
]), [
0,
0,
0,
0,
0,
0
]);
assert.sameValue(g, undefined);
}
{
let [a, b, c, d, e] = lengthTrackingWithOffset;
assert.compareArray(ToNumbers([
a,
b,
c,
d
]), [
0,
0,
0,
0
]);
assert.sameValue(e, undefined);
}
}

View File

@ -0,0 +1,21 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-arraybuffer-length
description: >
Indices of TypedArrays backed by resizable buffers are enumerable with
for-in
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
let rab = CreateResizableArrayBuffer(100, 200);
for (let ctor of ctors) {
const ta = new ctor(rab, 0, 3);
let keys = '';
for (const key in ta) {
keys += key;
}
assert.sameValue(keys, '012');
}

View File

@ -0,0 +1,57 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-arraybuffer-length
description: >
TypedArrays backed by resizable buffers are iterable with for-of and behave
correctly when the buffer is grown during iteration
features: [resizable-arraybuffer]
includes: [compareArray.js, resizableArrayBufferUtils.js]
---*/
function CreateRab(buffer_byte_length, ctor) {
const rab = CreateResizableArrayBuffer(buffer_byte_length, 2 * buffer_byte_length);
let ta_write = new ctor(rab);
for (let i = 0; i < buffer_byte_length / ctor.BYTES_PER_ELEMENT; ++i) {
WriteToTypedArray(ta_write, i, i % 128);
}
return rab;
}
// We need to recreate the RAB between all TA tests, since we grow it.
for (let ctor of ctors) {
const no_elements = 10;
const offset = 2;
const buffer_byte_length = no_elements * ctor.BYTES_PER_ELEMENT;
const byte_offset = offset * ctor.BYTES_PER_ELEMENT;
// Create various different styles of TypedArrays with the RAB as the
// backing store and iterate them.
let rab = CreateRab(buffer_byte_length, ctor);
const length_tracking_ta = new ctor(rab);
{
let expected = [];
for (let i = 0; i < no_elements; ++i) {
expected.push(i % 128);
}
// After resizing, the new memory contains zeros.
for (let i = 0; i < no_elements; ++i) {
expected.push(0);
}
TestIterationAndResize(length_tracking_ta, expected, rab, no_elements, buffer_byte_length * 2);
}
rab = CreateRab(buffer_byte_length, ctor);
const length_tracking_ta_with_offset = new ctor(rab, byte_offset);
{
let expected = [];
for (let i = offset; i < no_elements; ++i) {
expected.push(i % 128);
}
for (let i = 0; i < no_elements; ++i) {
expected.push(0);
}
TestIterationAndResize(length_tracking_ta_with_offset, expected, rab, no_elements - offset, buffer_byte_length * 2);
}
}

View File

@ -0,0 +1,71 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-arraybuffer-length
description: >
TypedArrays backed by resizable buffers are iterable with for-of and behave
correctly when the buffer is grown during iteration
features: [resizable-arraybuffer]
includes: [compareArray.js, resizableArrayBufferUtils.js]
---*/
function CreateRab(buffer_byte_length, ctor) {
const rab = CreateResizableArrayBuffer(buffer_byte_length, 2 * buffer_byte_length);
let ta_write = new ctor(rab);
for (let i = 0; i < buffer_byte_length / ctor.BYTES_PER_ELEMENT; ++i) {
WriteToTypedArray(ta_write, i, i % 128);
}
return rab;
}
for (let ctor of ctors) {
const no_elements = 10;
const offset = 2;
const buffer_byte_length = no_elements * ctor.BYTES_PER_ELEMENT;
const byte_offset = offset * ctor.BYTES_PER_ELEMENT;
// Create various different styles of TypedArrays with the RAB as the
// backing store and iterate them.
// Fixed-length TAs aren't affected by resizing.
let rab = CreateRab(buffer_byte_length, ctor);
const ta = new ctor(rab, 0, 3);
TestIterationAndResize(ta, [
0,
1,
2
], rab, 2, buffer_byte_length * 2);
rab = CreateRab(buffer_byte_length, ctor);
const ta_with_offset = new ctor(rab, byte_offset, 3);
TestIterationAndResize(ta_with_offset, [
2,
3,
4
], rab, 2, buffer_byte_length * 2);
rab = CreateRab(buffer_byte_length, ctor);
const length_tracking_ta = new ctor(rab);
{
let expected = [];
for (let i = 0; i < no_elements; ++i) {
expected.push(i % 128);
}
for (let i = 0; i < no_elements; ++i) {
// After resizing, the new memory contains zeros.
expected.push(0);
}
TestIterationAndResize(length_tracking_ta, expected, rab, 2, buffer_byte_length * 2);
}
rab = CreateRab(buffer_byte_length, ctor);
const length_tracking_ta_with_offset = new ctor(rab, byte_offset);
{
let expected = [];
for (let i = offset; i < no_elements; ++i) {
expected.push(i % 128);
}
for (let i = 0; i < no_elements; ++i) {
expected.push(0);
}
TestIterationAndResize(length_tracking_ta_with_offset, expected, rab, 2, buffer_byte_length * 2);
}
}

View File

@ -0,0 +1,86 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-arraybuffer-length
description: >
TypedArrays backed by resizable buffers are iterable with for-of and behave
correctly when the buffer is shrunk during iteration
features: [resizable-arraybuffer]
includes: [compareArray.js, resizableArrayBufferUtils.js]
---*/
function CreateRab(buffer_byte_length, ctor) {
const rab = CreateResizableArrayBuffer(buffer_byte_length, 2 * buffer_byte_length);
let ta_write = new ctor(rab);
for (let i = 0; i < buffer_byte_length / ctor.BYTES_PER_ELEMENT; ++i) {
WriteToTypedArray(ta_write, i, i % 128);
}
return rab;
}
for (let ctor of ctors) {
const no_elements = 10;
const offset = 2;
const buffer_byte_length = no_elements * ctor.BYTES_PER_ELEMENT;
const byte_offset = offset * ctor.BYTES_PER_ELEMENT;
// Create various different styles of TypedArrays with the RAB as the
// backing store and iterate them.
// Fixed-length TAs aren't affected by shrinking if they stay in-bounds.
// They appear detached after shrinking out of bounds.
let rab = CreateRab(buffer_byte_length, ctor);
const ta1 = new ctor(rab, 0, 3);
TestIterationAndResize(ta1, [
0,
1,
2
], rab, 2, buffer_byte_length / 2);
rab = CreateRab(buffer_byte_length, ctor);
const ta2 = new ctor(rab, 0, 3);
assert.throws(TypeError, () => {
TestIterationAndResize(ta2, null, rab, 2, 1);
});
rab = CreateRab(buffer_byte_length, ctor);
const ta_with_offset1 = new ctor(rab, byte_offset, 3);
TestIterationAndResize(ta_with_offset1, [
2,
3,
4
], rab, 2, buffer_byte_length / 2);
rab = CreateRab(buffer_byte_length, ctor);
const ta_with_offset2 = new ctor(rab, byte_offset, 3);
assert.throws(TypeError, () => {
TestIterationAndResize(ta_with_offset2, null, rab, 2, 0);
});
// Length-tracking TA with offset 0 doesn't throw, but its length gracefully
// reduces too.
rab = CreateRab(buffer_byte_length, ctor);
const length_tracking_ta = new ctor(rab);
TestIterationAndResize(length_tracking_ta, [
0,
1,
2,
3,
4
], rab, 2, buffer_byte_length / 2);
// Length-tracking TA appears detached when the buffer is resized beyond the
// offset.
rab = CreateRab(buffer_byte_length, ctor);
const length_tracking_ta_with_offset = new ctor(rab, byte_offset);
assert.throws(TypeError, () => {
TestIterationAndResize(length_tracking_ta_with_offset, null, rab, 2, byte_offset / 2);
});
// Length-tracking TA reduces its length gracefully when the buffer is
// resized to barely cover the offset.
rab = CreateRab(buffer_byte_length, ctor);
const length_tracking_ta_with_offset2 = new ctor(rab, byte_offset);
TestIterationAndResize(length_tracking_ta_with_offset2, [
2,
3
], rab, 2, byte_offset);
}

View File

@ -0,0 +1,58 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-arraybuffer-length
description: >
TypedArrays backed by resizable buffers are iterable with for-of and behave
correctly when the buffer is shrunk during iteration
features: [resizable-arraybuffer]
includes: [compareArray.js, resizableArrayBufferUtils.js]
---*/
function CreateRab(buffer_byte_length, ctor) {
const rab = CreateResizableArrayBuffer(buffer_byte_length, 2 * buffer_byte_length);
let ta_write = new ctor(rab);
for (let i = 0; i < buffer_byte_length / ctor.BYTES_PER_ELEMENT; ++i) {
WriteToTypedArray(ta_write, i, i % 128);
}
return rab;
}
for (let ctor of ctors) {
const no_elements = 10;
const offset = 2;
const buffer_byte_length = no_elements * ctor.BYTES_PER_ELEMENT;
const byte_offset = offset * ctor.BYTES_PER_ELEMENT;
// Create various different styles of TypedArrays with the RAB as the
// backing store and iterate them.
// Fixed-length TAs appear detached after shrinking out of bounds.
let rab = CreateRab(buffer_byte_length, ctor);
const ta = new ctor(rab, 0, 3);
assert.throws(TypeError, () => {
TestIterationAndResize(ta, null, rab, 2, 0);
});
rab = CreateRab(buffer_byte_length, ctor);
const ta_with_offset = new ctor(rab, byte_offset, 3);
assert.throws(TypeError, () => {
TestIterationAndResize(ta_with_offset, null, rab, 2, 0);
});
// Length-tracking TA with offset 0 doesn't throw, but its length gracefully
// goes to zero too.
rab = CreateRab(buffer_byte_length, ctor);
const length_tracking_ta = new ctor(rab);
TestIterationAndResize(length_tracking_ta, [
0,
1
], rab, 2, 0);
// Length-tracking TA which is resized beyond the offset appars detached.
rab = CreateRab(buffer_byte_length, ctor);
const length_tracking_ta_with_offset = new ctor(rab, byte_offset);
assert.throws(TypeError, () => {
TestIterationAndResize(length_tracking_ta_with_offset, null, rab, 2, 0);
});
}

View File

@ -0,0 +1,70 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-arraybuffer-length
description: >
TypedArrays backed by resizable buffers are iterable with for-of
features: [resizable-arraybuffer]
includes: [compareArray.js, resizableArrayBufferUtils.js]
---*/
function CollectValues(ta) {
let values = [];
for (const value of ta) {
values.push(Number(value));
}
return values;
}
for (let ctor of ctors) {
const no_elements = 10;
const offset = 2;
const buffer_byte_length = no_elements * ctor.BYTES_PER_ELEMENT;
// We can use the same RAB for all the TAs below, since we won't modify it
// after writing the initial values.
const rab = CreateResizableArrayBuffer(buffer_byte_length, 2 * buffer_byte_length);
const byte_offset = offset * ctor.BYTES_PER_ELEMENT;
// Write some data into the array.
let ta_write = new ctor(rab);
for (let i = 0; i < no_elements; ++i) {
WriteToTypedArray(ta_write, i, i % 128);
}
// Create various different styles of TypedArrays with the RAB as the
// backing store and iterate them.
const ta = new ctor(rab, 0, 3);
assert.compareArray(CollectValues(ta), [
0,
1,
2
]);
const empty_ta = new ctor(rab, 0, 0);
assert.compareArray(CollectValues(empty_ta), []);
const ta_with_offset = new ctor(rab, byte_offset, 3);
assert.compareArray(CollectValues(ta_with_offset), [
2,
3,
4
]);
const empty_ta_with_offset = new ctor(rab, byte_offset, 0);
assert.compareArray(CollectValues(empty_ta_with_offset), []);
const length_tracking_ta = new ctor(rab);
{
let expected = [];
for (let i = 0; i < no_elements; ++i) {
expected.push(i % 128);
}
assert.compareArray(CollectValues(length_tracking_ta), expected);
}
const length_tracking_ta_with_offset = new ctor(rab, byte_offset);
{
let expected = [];
for (let i = offset; i < no_elements; ++i) {
expected.push(i % 128);
}
assert.compareArray(CollectValues(length_tracking_ta_with_offset), expected);
}
const empty_length_tracking_ta_with_offset = new ctor(rab, buffer_byte_length);
assert.compareArray(CollectValues(empty_length_tracking_ta_with_offset), []);
}