Source code

Revision control

Copy as Markdown

Other Tools

// 22.2.4.5 TypedArray ( buffer [ , byteOffset [ , length ] ] )
// Ensure the various error conditions are tested in the correct order.
const otherGlobal = newGlobal();
function* createBuffers(lengths = [0, 8]) {
for (let length of lengths) {
let buffer = new ArrayBuffer(length);
yield {buffer, detach: () => detachArrayBuffer(buffer)};
}
for (let length of lengths) {
let buffer = new otherGlobal.ArrayBuffer(length);
yield {buffer, detach: () => otherGlobal.detachArrayBuffer(buffer)};
}
}
const poisonedValue = new Proxy({}, new Proxy({}, {
get() {
// Throws an exception when any proxy trap is invoked.
throw new Error("Poisoned Value");
}
}));
class ExpectedError extends Error { }
function ConstructorWithThrowingPrototype(detach) {
return Object.defineProperty(function(){}.bind(null), "prototype", {
get() {
if (detach)
detach();
throw new ExpectedError();
}
});
}
function ValueThrowing(detach) {
return {
valueOf() {
if (detach)
detach();
throw new ExpectedError();
}
};
}
function ValueReturning(value, detach) {
return {
valueOf() {
if (detach)
detach();
return value;
}
};
}
// Ensure step 4 |AllocateTypedArray| is executed before step 6 |ToIndex(byteOffset)|.
for (let {buffer} of createBuffers()) {
let constructor = ConstructorWithThrowingPrototype();
assertThrowsInstanceOf(() =>
Reflect.construct(Int32Array, [buffer, poisonedValue, 0], constructor), ExpectedError);
}
// Ensure step 4 |AllocateTypedArray| is executed before step 9 |IsDetachedBuffer(buffer)|.
for (let {buffer, detach} of createBuffers()) {
let constructor = ConstructorWithThrowingPrototype();
detach();
assertThrowsInstanceOf(() =>
Reflect.construct(Int32Array, [buffer, 0, 0], constructor), ExpectedError);
}
// Ensure step 4 |AllocateTypedArray| is executed before step 9 |IsDetachedBuffer(buffer)|.
// - Variant: Detach buffer dynamically.
for (let {buffer, detach} of createBuffers()) {
let constructor = ConstructorWithThrowingPrototype(detach);
assertThrowsInstanceOf(() =>
Reflect.construct(Int32Array, [buffer, 0, 0], constructor), ExpectedError);
}
// Ensure step 4 |AllocateTypedArray| is executed before step 8.a |ToIndex(length)|.
for (let {buffer} of createBuffers()) {
let constructor = ConstructorWithThrowingPrototype();
assertThrowsInstanceOf(() =>
Reflect.construct(Int32Array, [buffer, 0, poisonedValue], constructor), ExpectedError);
}
// Ensure step 6 |ToIndex(byteOffset)| is executed before step 9 |IsDetachedBuffer(buffer)|.
for (let {buffer, detach} of createBuffers()) {
let byteOffset = ValueThrowing();
detach();
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, 0), ExpectedError);
}
// Ensure step 6 |ToIndex(byteOffset)| is executed before step 9 |IsDetachedBuffer(buffer)|.
// - Variant: Detach buffer dynamically.
for (let {buffer, detach} of createBuffers()) {
let byteOffset = ValueThrowing(detach);
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, 0), ExpectedError);
}
// Ensure step 6 |ToIndex(byteOffset)| is executed before step 8.a |ToIndex(length)|.
for (let {buffer} of createBuffers()) {
let byteOffset = ValueThrowing();
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, poisonedValue), ExpectedError);
}
// Ensure step 7 |offset modulo elementSize ≠ 0| is executed before step 9 |IsDetachedBuffer(buffer)|.
for (let {buffer, detach} of createBuffers()) {
let byteOffset = 1;
detach();
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, 0), RangeError);
}
// Ensure step 7 |offset modulo elementSize ≠ 0| is executed before step 9 |IsDetachedBuffer(buffer)|.
// - Variant: Detach buffer dynamically.
for (let {buffer, detach} of createBuffers()) {
let byteOffset = ValueReturning(1, detach);
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, 0), RangeError);
}
// Ensure step 7 |offset modulo elementSize ≠ 0| is executed before step 8.a |ToIndex(length)|.
for (let {buffer} of createBuffers()) {
assertThrowsInstanceOf(() => new Int32Array(buffer, 1, poisonedValue), RangeError);
}
// Ensure step 8.a |ToIndex(length)| is executed before step 9 |IsDetachedBuffer(buffer)|.
for (let {buffer, detach} of createBuffers()) {
let byteOffset = 0;
let length = ValueThrowing();
detach();
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, length), ExpectedError);
}
// Ensure step 8.a |ToIndex(length)| is executed before step 9 |IsDetachedBuffer(buffer)|.
// - Variant: Detach buffer dynamically (1).
for (let {buffer, detach} of createBuffers()) {
let byteOffset = ValueReturning(0, detach);
let length = ValueThrowing();
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, length), ExpectedError);
}
// Ensure step 8.a |ToIndex(length)| is executed before step 9 |IsDetachedBuffer(buffer)|.
// - Variant: Detach buffer dynamically (2).
for (let {buffer, detach} of createBuffers()) {
let byteOffset = 0;
let length = ValueThrowing(detach);
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, length), ExpectedError);
}
// Ensure step 9 |IsDetachedBuffer(buffer)| is executed before step 11.a |bufferByteLength modulo elementSize ≠ 0|.
for (let {buffer, detach} of createBuffers([1, 9])) {
let byteOffset = 0;
detach();
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset), TypeError);
}
// Ensure step 9 |IsDetachedBuffer(buffer)| is executed before step 11.a |bufferByteLength modulo elementSize ≠ 0|.
// - Variant: Detach buffer dynamically.
for (let {buffer, detach} of createBuffers([1, 9])) {
let byteOffset = ValueReturning(0, detach);
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset), TypeError);
}
// Ensure step 9 |IsDetachedBuffer(buffer)| is executed before step 11.c |newByteLength < 0|.
for (let {buffer, detach} of createBuffers()) {
let byteOffset = 64;
detach();
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset), TypeError);
}
// Ensure step 9 |IsDetachedBuffer(buffer)| is executed before step 11.c |newByteLength < 0|.
// - Variant: Detach buffer dynamically.
for (let {buffer, detach} of createBuffers()) {
let byteOffset = ValueReturning(64, detach);
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset), TypeError);
}
// Ensure step 9 |IsDetachedBuffer(buffer)| is executed before step 12.b |offset+newByteLength > bufferByteLength|.
// - Case A: The given byteOffset is too large.
for (let {buffer, detach} of createBuffers()) {
let byteOffset = 64;
let length = ValueReturning(0, detach);
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, length), TypeError);
}
// Ensure step 9 |IsDetachedBuffer(buffer)| is executed before step 12.b |offset+newByteLength > bufferByteLength|.
// - Case B: The given length is too large.
for (let {buffer, detach} of createBuffers()) {
let byteOffset = 0;
let length = ValueReturning(64, detach);
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, length), TypeError);
}
// Ensure we handle the case when ToIndex(byteOffset) detaches the array buffer.
for (let {buffer, detach} of createBuffers()) {
let byteOffset = ValueReturning(0, detach);
let length = 0;
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, length), TypeError);
}
// Ensure we handle the case when ToIndex(length) detaches the array buffer.
for (let {buffer, detach} of createBuffers()) {
let byteOffset = 0;
let length = ValueReturning(0, detach);
assertThrowsInstanceOf(() => new Int32Array(buffer, byteOffset, length), TypeError);
}
if (typeof reportCompare === "function")
reportCompare(true, true);