Remove unnecessary tests if $262.detachArrayBuffer is defined

This commit is contained in:
André Bargull 2025-04-30 14:16:12 +02:00 committed by Philip Chimento
parent 11c8fe0a99
commit 61286de40c
9 changed files with 475 additions and 493 deletions

View File

@ -8,6 +8,7 @@ description: |
pending
esid: pending
---*/
var buffer = new ArrayBuffer(2);
var view = new DataView(buffer);
@ -30,16 +31,13 @@ for (let fun of ['getInt8', 'getInt16']) {
assert.sameValue(view[fun](NaN), 0);
}
if ('$262.detachArrayBuffer' in this) {
// ToIndex is called before detachment check, so we can tell the difference
// between a ToIndex failure and a real out of bounds failure.
$262.detachArrayBuffer(buffer);
// ToIndex is called before detachment check, so we can tell the difference
// between a ToIndex failure and a real out of bounds failure.
$262.detachArrayBuffer(buffer);
check(view);
assert.throws(TypeError, () => view.getInt8(0));
assert.throws(TypeError, () => view.setInt8(0, 0));
assert.throws(TypeError, () => view.getInt8(Math.pow(2, 53) - 1));
assert.throws(TypeError, () => view.setInt8(Math.pow(2, 53) - 1, 0));
}
check(view);
assert.throws(TypeError, () => view.getInt8(0));
assert.throws(TypeError, () => view.setInt8(0, 0));
assert.throws(TypeError, () => view.getInt8(Math.pow(2, 53) - 1));
assert.throws(TypeError, () => view.setInt8(Math.pow(2, 53) - 1, 0));

View File

@ -9,74 +9,70 @@ description: |
pending
esid: pending
---*/
function checkResult(actual, expected)
{
assert.sameValue(actual.value, expected.value);
assert.sameValue(actual.done, expected.done);
}
if (typeof $262.detachArrayBuffer === "function")
var iteratorFunction = Uint8Array.prototype[Symbol.iterator];
var thisGlobal = this;
var otherGlobal = $262.createRealm().global;
var thisNext = new Uint8Array()[Symbol.iterator]().next
for (const constructor of typedArrayConstructors)
{
var iteratorFunction = Uint8Array.prototype[Symbol.iterator];
assert.sameValue(new constructor()[Symbol.iterator]().next, thisNext);
var globals =
[
[thisGlobal, thisGlobal],
[thisGlobal, otherGlobal],
[otherGlobal, otherGlobal],
[otherGlobal, thisGlobal],
];
var thisGlobal = this;
var otherGlobal = $262.createRealm().global;
var thisNext = new Uint8Array()[Symbol.iterator]().next
for (const constructor of typedArrayConstructors)
for (const [arrayGlobal, bufferGlobal] of globals)
{
assert.sameValue(new constructor()[Symbol.iterator]().next, thisNext);
var arr, buffer, iterator;
var globals =
[
[thisGlobal, thisGlobal],
[thisGlobal, otherGlobal],
[otherGlobal, otherGlobal],
[otherGlobal, thisGlobal],
];
for (const [arrayGlobal, bufferGlobal] of globals)
function arrayBufferIterator()
{
var arr, buffer, iterator;
var byteLength = 2 * constructor.BYTES_PER_ELEMENT;
var buf = new bufferGlobal.ArrayBuffer(byteLength);
var tarray = new arrayGlobal[constructor.name](buf);
function arrayBufferIterator()
{
var byteLength = 2 * constructor.BYTES_PER_ELEMENT;
var buf = new bufferGlobal.ArrayBuffer(byteLength);
var tarray = new arrayGlobal[constructor.name](buf);
tarray[0] = 1;
tarray[1] = 2;
tarray[0] = 1;
tarray[1] = 2;
return [tarray, buf, Reflect.apply(iteratorFunction, tarray, [])];
}
[arr, buffer, iterator] = arrayBufferIterator();
checkResult(thisNext.call(iterator), {value: 1, done: false});
checkResult(thisNext.call(iterator), {value: 2, done: false});
checkResult(thisNext.call(iterator), {value: undefined, done: true});
// Test an exhausted iterator.
bufferGlobal.$262.detachArrayBuffer(buffer);
checkResult(thisNext.call(iterator), {value: undefined, done: true});
// Test an all-but-exhausted iterator.
[arr, buffer, iterator] = arrayBufferIterator();
checkResult(thisNext.call(iterator), {value: 1, done: false});
checkResult(thisNext.call(iterator), {value: 2, done: false});
bufferGlobal.$262.detachArrayBuffer(buffer);
assert.throws(TypeError, () => thisNext.call(iterator));
// Test an unexhausted iterator.
[arr, buffer, iterator] = arrayBufferIterator();
checkResult(thisNext.call(iterator), {value: 1, done: false});
bufferGlobal.$262.detachArrayBuffer(buffer);
assert.throws(TypeError, () => thisNext.call(iterator));
return [tarray, buf, Reflect.apply(iteratorFunction, tarray, [])];
}
[arr, buffer, iterator] = arrayBufferIterator();
checkResult(thisNext.call(iterator), {value: 1, done: false});
checkResult(thisNext.call(iterator), {value: 2, done: false});
checkResult(thisNext.call(iterator), {value: undefined, done: true});
// Test an exhausted iterator.
bufferGlobal.$262.detachArrayBuffer(buffer);
checkResult(thisNext.call(iterator), {value: undefined, done: true});
// Test an all-but-exhausted iterator.
[arr, buffer, iterator] = arrayBufferIterator();
checkResult(thisNext.call(iterator), {value: 1, done: false});
checkResult(thisNext.call(iterator), {value: 2, done: false});
bufferGlobal.$262.detachArrayBuffer(buffer);
assert.throws(TypeError, () => thisNext.call(iterator));
// Test an unexhausted iterator.
[arr, buffer, iterator] = arrayBufferIterator();
checkResult(thisNext.call(iterator), {value: 1, done: false});
bufferGlobal.$262.detachArrayBuffer(buffer);
assert.throws(TypeError, () => thisNext.call(iterator));
}
}

View File

@ -8,6 +8,7 @@ description: |
pending
esid: pending
---*/
// Tests for detached ArrayBuffer checks in %TypedArray%.prototype.set(array|typedArray, offset).
function* createTypedArrays(lengths = [0, 1, 4, 4096]) {
@ -19,255 +20,252 @@ function* createTypedArrays(lengths = [0, 1, 4, 4096]) {
}
}
if (typeof $262.detachArrayBuffer === "function") {
class ExpectedError extends Error {}
class ExpectedError extends Error {}
// No detached check on function entry.
for (let {typedArray, buffer} of createTypedArrays()) {
$262.detachArrayBuffer(buffer);
// No detached check on function entry.
for (let {typedArray, buffer} of createTypedArrays()) {
$262.detachArrayBuffer(buffer);
assert.throws(ExpectedError, () => typedArray.set(null, {
assert.throws(ExpectedError, () => typedArray.set(null, {
valueOf() {
throw new ExpectedError();
}
}));
}
// Check for detached buffer after calling ToInteger(offset). Test with:
// - valid offset,
// - too large offset,
// - and negative offset.
for (let [offset, error] of [[0, TypeError], [1000000, TypeError], [-1, RangeError]]) {
for (let source of [[], [0], new Int32Array(0), new Int32Array(1)]) {
for (let {typedArray, buffer} of createTypedArrays()) {
assert.throws(error, () => typedArray.set(source, {
valueOf() {
$262.detachArrayBuffer(buffer);
return offset;
}
}));
}
}
}
// Tests when called with detached typed array as source.
for (let {typedArray} of createTypedArrays()) {
for (let {typedArray: source, buffer: sourceBuffer} of createTypedArrays()) {
$262.detachArrayBuffer(sourceBuffer);
assert.throws(ExpectedError, () => typedArray.set(source, {
valueOf() {
throw new ExpectedError();
}
}));
}
}
// Check for detached buffer after calling ToInteger(offset). Test with:
// - valid offset,
// - too large offset,
// - and negative offset.
for (let [offset, error] of [[0, TypeError], [1000000, TypeError], [-1, RangeError]]) {
for (let source of [[], [0], new Int32Array(0), new Int32Array(1)]) {
for (let {typedArray, buffer} of createTypedArrays()) {
assert.throws(error, () => typedArray.set(source, {
valueOf() {
$262.detachArrayBuffer(buffer);
return offset;
}
}));
}
}
}
// Tests when called with detached typed array as source.
// Check when detaching source buffer in ToInteger(offset). Test with:
// - valid offset,
// - too large offset,
// - and negative offset.
for (let [offset, error] of [[0, TypeError], [1000000, TypeError], [-1, RangeError]]) {
for (let {typedArray} of createTypedArrays()) {
for (let {typedArray: source, buffer: sourceBuffer} of createTypedArrays()) {
$262.detachArrayBuffer(sourceBuffer);
assert.throws(ExpectedError, () => typedArray.set(source, {
assert.throws(error, () => typedArray.set(source, {
valueOf() {
throw new ExpectedError();
$262.detachArrayBuffer(sourceBuffer);
return offset;
}
}));
}
}
// Check when detaching source buffer in ToInteger(offset). Test with:
// - valid offset,
// - too large offset,
// - and negative offset.
for (let [offset, error] of [[0, TypeError], [1000000, TypeError], [-1, RangeError]]) {
for (let {typedArray} of createTypedArrays()) {
for (let {typedArray: source, buffer: sourceBuffer} of createTypedArrays()) {
assert.throws(error, () => typedArray.set(source, {
valueOf() {
$262.detachArrayBuffer(sourceBuffer);
return offset;
}
}));
}
}
}
// Test when target and source use the same underlying buffer and
// ToInteger(offset) detaches the buffer. Test with:
// - same typed array,
// - different typed array, but same element type,
// - and different element type.
for (let src of [ta => ta, ta => new Int32Array(ta.buffer), ta => new Float32Array(ta.buffer)]) {
for (let {typedArray, buffer} of createTypedArrays()) {
let source = src(typedArray);
assert.throws(TypeError, () => typedArray.set(source, {
valueOf() {
$262.detachArrayBuffer(buffer);
return 0;
}
}));
}
}
// Test when Get(src, "length") detaches the buffer, but srcLength is 0.
// Also use different offsets to ensure bounds checks use the typed array's
// length value from before detaching the buffer.
for (let offset of [() => 0, ta => Math.min(1, ta.length), ta => Math.max(0, ta.length - 1)]) {
for (let {typedArray, buffer} of createTypedArrays()) {
let source = {
get length() {
$262.detachArrayBuffer(buffer);
return 0;
}
};
typedArray.set(source, offset(typedArray));
}
}
// Test when ToLength(Get(src, "length")) detaches the buffer, but
// srcLength is 0. Also use different offsets to ensure bounds checks use
// the typed array's length value from before detaching the buffer.
for (let offset of [() => 0, ta => Math.min(1, ta.length), ta => Math.max(0, ta.length - 1)]) {
for (let {typedArray, buffer} of createTypedArrays()) {
let source = {
length: {
valueOf() {
$262.detachArrayBuffer(buffer);
return 0;
}
}
};
typedArray.set(source, offset(typedArray));
}
}
// Test no TypeError is thrown when the typed array is detached and
// srcLength > 0.
for (let {typedArray, buffer} of createTypedArrays()) {
let source = {
length: {
valueOf() {
$262.detachArrayBuffer(buffer);
return 1;
}
}
};
if (typedArray.length === 0) {
assert.throws(RangeError, () => typedArray.set(source));
} else {
typedArray.set(source);
}
}
// Same as above, but with side-effect when executing Get(src, "0").
for (let {typedArray, buffer} of createTypedArrays()) {
let source = {
get 0() {
throw new ExpectedError();
},
length: {
valueOf() {
$262.detachArrayBuffer(buffer);
return 1;
}
}
};
let err = typedArray.length === 0 ? RangeError : ExpectedError;
assert.throws(err, () => typedArray.set(source));
}
// Same as above, but with side-effect when executing ToNumber(Get(src, "0")).
for (let {typedArray, buffer} of createTypedArrays()) {
let source = {
get 0() {
return {
valueOf() {
throw new ExpectedError();
}
};
},
length: {
valueOf() {
$262.detachArrayBuffer(buffer);
return 1;
}
}
};
let err = typedArray.length === 0 ? RangeError : ExpectedError;
assert.throws(err, () => typedArray.set(source));
}
// Side-effects when getting the source elements detach the buffer.
for (let {typedArray, buffer} of createTypedArrays()) {
let source = Object.defineProperties([], {
0: {
get() {
$262.detachArrayBuffer(buffer);
return 1;
}
}
});
if (typedArray.length === 0) {
assert.throws(RangeError, () => typedArray.set(source));
} else {
typedArray.set(source);
}
}
// Side-effects when getting the source elements detach the buffer. Also
// ensure other elements are accessed.
for (let {typedArray, buffer} of createTypedArrays()) {
let accessed = false;
let source = Object.defineProperties([], {
0: {
get() {
$262.detachArrayBuffer(buffer);
return 1;
}
},
1: {
get() {
assert.sameValue(accessed, false);
accessed = true;
return 2;
}
}
});
if (typedArray.length <= 1) {
assert.throws(RangeError, () => typedArray.set(source));
} else {
assert.sameValue(accessed, false);
typedArray.set(source);
assert.sameValue(accessed, true);
}
}
// Side-effects when converting the source elements detach the buffer.
for (let {typedArray, buffer} of createTypedArrays()) {
let source = [{
valueOf() {
$262.detachArrayBuffer(buffer);
return 1;
}
}];
if (typedArray.length === 0) {
assert.throws(RangeError, () => typedArray.set(source));
} else {
typedArray.set(source);
}
}
// Side-effects when converting the source elements detach the buffer. Also
// ensure other elements are accessed.
for (let {typedArray, buffer} of createTypedArrays()) {
let accessed = false;
let source = [{
valueOf() {
$262.detachArrayBuffer(buffer);
return 1;
}
}, {
valueOf() {
assert.sameValue(accessed, false);
accessed = true;
return 2;
}
}];
if (typedArray.length <= 1) {
assert.throws(RangeError, () => typedArray.set(source));
} else {
assert.sameValue(accessed, false);
typedArray.set(source);
assert.sameValue(accessed, true);
}
}
}
// Test when target and source use the same underlying buffer and
// ToInteger(offset) detaches the buffer. Test with:
// - same typed array,
// - different typed array, but same element type,
// - and different element type.
for (let src of [ta => ta, ta => new Int32Array(ta.buffer), ta => new Float32Array(ta.buffer)]) {
for (let {typedArray, buffer} of createTypedArrays()) {
let source = src(typedArray);
assert.throws(TypeError, () => typedArray.set(source, {
valueOf() {
$262.detachArrayBuffer(buffer);
return 0;
}
}));
}
}
// Test when Get(src, "length") detaches the buffer, but srcLength is 0.
// Also use different offsets to ensure bounds checks use the typed array's
// length value from before detaching the buffer.
for (let offset of [() => 0, ta => Math.min(1, ta.length), ta => Math.max(0, ta.length - 1)]) {
for (let {typedArray, buffer} of createTypedArrays()) {
let source = {
get length() {
$262.detachArrayBuffer(buffer);
return 0;
}
};
typedArray.set(source, offset(typedArray));
}
}
// Test when ToLength(Get(src, "length")) detaches the buffer, but
// srcLength is 0. Also use different offsets to ensure bounds checks use
// the typed array's length value from before detaching the buffer.
for (let offset of [() => 0, ta => Math.min(1, ta.length), ta => Math.max(0, ta.length - 1)]) {
for (let {typedArray, buffer} of createTypedArrays()) {
let source = {
length: {
valueOf() {
$262.detachArrayBuffer(buffer);
return 0;
}
}
};
typedArray.set(source, offset(typedArray));
}
}
// Test no TypeError is thrown when the typed array is detached and
// srcLength > 0.
for (let {typedArray, buffer} of createTypedArrays()) {
let source = {
length: {
valueOf() {
$262.detachArrayBuffer(buffer);
return 1;
}
}
};
if (typedArray.length === 0) {
assert.throws(RangeError, () => typedArray.set(source));
} else {
typedArray.set(source);
}
}
// Same as above, but with side-effect when executing Get(src, "0").
for (let {typedArray, buffer} of createTypedArrays()) {
let source = {
get 0() {
throw new ExpectedError();
},
length: {
valueOf() {
$262.detachArrayBuffer(buffer);
return 1;
}
}
};
let err = typedArray.length === 0 ? RangeError : ExpectedError;
assert.throws(err, () => typedArray.set(source));
}
// Same as above, but with side-effect when executing ToNumber(Get(src, "0")).
for (let {typedArray, buffer} of createTypedArrays()) {
let source = {
get 0() {
return {
valueOf() {
throw new ExpectedError();
}
};
},
length: {
valueOf() {
$262.detachArrayBuffer(buffer);
return 1;
}
}
};
let err = typedArray.length === 0 ? RangeError : ExpectedError;
assert.throws(err, () => typedArray.set(source));
}
// Side-effects when getting the source elements detach the buffer.
for (let {typedArray, buffer} of createTypedArrays()) {
let source = Object.defineProperties([], {
0: {
get() {
$262.detachArrayBuffer(buffer);
return 1;
}
}
});
if (typedArray.length === 0) {
assert.throws(RangeError, () => typedArray.set(source));
} else {
typedArray.set(source);
}
}
// Side-effects when getting the source elements detach the buffer. Also
// ensure other elements are accessed.
for (let {typedArray, buffer} of createTypedArrays()) {
let accessed = false;
let source = Object.defineProperties([], {
0: {
get() {
$262.detachArrayBuffer(buffer);
return 1;
}
},
1: {
get() {
assert.sameValue(accessed, false);
accessed = true;
return 2;
}
}
});
if (typedArray.length <= 1) {
assert.throws(RangeError, () => typedArray.set(source));
} else {
assert.sameValue(accessed, false);
typedArray.set(source);
assert.sameValue(accessed, true);
}
}
// Side-effects when converting the source elements detach the buffer.
for (let {typedArray, buffer} of createTypedArrays()) {
let source = [{
valueOf() {
$262.detachArrayBuffer(buffer);
return 1;
}
}];
if (typedArray.length === 0) {
assert.throws(RangeError, () => typedArray.set(source));
} else {
typedArray.set(source);
}
}
// Side-effects when converting the source elements detach the buffer. Also
// ensure other elements are accessed.
for (let {typedArray, buffer} of createTypedArrays()) {
let accessed = false;
let source = [{
valueOf() {
$262.detachArrayBuffer(buffer);
return 1;
}
}, {
valueOf() {
assert.sameValue(accessed, false);
accessed = true;
return 2;
}
}];
if (typedArray.length <= 1) {
assert.throws(RangeError, () => typedArray.set(source));
} else {
assert.sameValue(accessed, false);
typedArray.set(source);
assert.sameValue(accessed, true);
}
}

View File

@ -24,9 +24,7 @@ for (var constructor of anyTypedArrayConstructors) {
assert.sameValue(Object.hasOwn(receiver, 10), false);
// Detached
if (typeof $262.detachArrayBuffer === "function" &&
!isSharedConstructor(constructor))
{
if (!isSharedConstructor(constructor)) {
$262.detachArrayBuffer(ta.buffer)
assert.sameValue(ta[0], undefined);

View File

@ -9,6 +9,7 @@ description: |
pending
esid: pending
---*/
// Test %TypedArray%.prototype.set(typedArray, offset) when called with wrapped
// typed array.
@ -35,53 +36,52 @@ for (var TA of anyTypedArrayConstructors) {
}
// Detachment checks are also applied correctly for wrapped typed arrays.
if (typeof $262.detachArrayBuffer === "function") {
// Create typed array from different global (explicit constructor call).
for (var TA of typedArrayConstructors) {
var target = new TA(4);
var source = new otherGlobal[TA.name](1);
taintLengthProperty(source);
// Called with wrapped typed array, array buffer already detached.
otherGlobal.$262.detachArrayBuffer(source.buffer);
assert.throws(TypeError, () => target.set(source));
// Create typed array from different global (explicit constructor call).
for (var TA of typedArrayConstructors) {
var target = new TA(4);
var source = new otherGlobal[TA.name](1);
taintLengthProperty(source);
var source = new otherGlobal[TA.name](1);
taintLengthProperty(source);
// Called with wrapped typed array, array buffer already detached.
otherGlobal.$262.detachArrayBuffer(source.buffer);
assert.throws(TypeError, () => target.set(source));
// Called with wrapped typed array, array buffer detached when
// processing offset parameter.
var offset = {
valueOf() {
otherGlobal.$262.detachArrayBuffer(source.buffer);
return 0;
}
};
assert.throws(TypeError, () => target.set(source, offset));
}
var source = new otherGlobal[TA.name](1);
taintLengthProperty(source);
// Create typed array from different global (implictly created when
// ArrayBuffer is a CCW).
for (var TA of typedArrayConstructors) {
var target = new TA(4);
var source = new TA(new otherGlobal.ArrayBuffer(1 * TA.BYTES_PER_ELEMENT));
taintLengthProperty(source);
// Called with wrapped typed array, array buffer already detached.
otherGlobal.$262.detachArrayBuffer(source.buffer);
assert.throws(TypeError, () => target.set(source));
var source = new TA(new otherGlobal.ArrayBuffer(1 * TA.BYTES_PER_ELEMENT));
taintLengthProperty(source);
// Called with wrapped typed array, array buffer detached when
// processing offset parameter.
var offset = {
valueOf() {
otherGlobal.$262.detachArrayBuffer(source.buffer);
return 0;
}
};
assert.throws(TypeError, () => target.set(source, offset));
}
// Called with wrapped typed array, array buffer detached when
// processing offset parameter.
var offset = {
valueOf() {
otherGlobal.$262.detachArrayBuffer(source.buffer);
return 0;
}
};
assert.throws(TypeError, () => target.set(source, offset));
}
// Create typed array from different global (implictly created when
// ArrayBuffer is a CCW).
for (var TA of typedArrayConstructors) {
var target = new TA(4);
var source = new TA(new otherGlobal.ArrayBuffer(1 * TA.BYTES_PER_ELEMENT));
taintLengthProperty(source);
// Called with wrapped typed array, array buffer already detached.
otherGlobal.$262.detachArrayBuffer(source.buffer);
assert.throws(TypeError, () => target.set(source));
var source = new TA(new otherGlobal.ArrayBuffer(1 * TA.BYTES_PER_ELEMENT));
taintLengthProperty(source);
// Called with wrapped typed array, array buffer detached when
// processing offset parameter.
var offset = {
valueOf() {
otherGlobal.$262.detachArrayBuffer(source.buffer);
return 0;
}
};
assert.throws(TypeError, () => target.set(source, offset));
}

View File

@ -8,6 +8,7 @@ description: |
pending
esid: pending
---*/
// Tests for detached ArrayBuffer checks in %TypedArray%.prototype.slice ( start, end ).
function* createTypedArrays(lengths = [0, 1, 4, 4096]) {
@ -27,85 +28,82 @@ function* createTypedArrays(lengths = [0, 1, 4, 4096]) {
}
}
if (typeof $262.detachArrayBuffer === "function") {
// ArrayBuffer is detached when entering slice().
for (let {typedArray, buffer} of createTypedArrays()) {
$262.detachArrayBuffer(buffer());
assert.throws(TypeError, () => {
typedArray.slice(0);
}, "ArrayBuffer is detached on function entry");
}
// ArrayBuffer is detached when computing ToInteger(start).
for (let {typedArray, length, buffer} of createTypedArrays()) {
let detached = false;
let start = {
valueOf() {
assert.sameValue(detached, false);
$262.detachArrayBuffer(buffer());
assert.sameValue(detached, false);
detached = true;
return 0;
}
};
// Doesn't throw an error when no bytes are copied.
if (length === 0) {
typedArray.slice(start);
} else {
assert.throws(TypeError, () => {
typedArray.slice(start);
}, "ArrayBuffer is detached in ToInteger(start)");
}
assert.sameValue(detached, true, "$262.detachArrayBuffer was called");
}
// ArrayBuffer is detached when computing ToInteger(end).
for (let {typedArray, length, buffer} of createTypedArrays()) {
let detached = false;
let end = {
valueOf() {
assert.sameValue(detached, false);
$262.detachArrayBuffer(buffer());
assert.sameValue(detached, false);
detached = true;
return length;
}
};
// Doesn't throw an error when no bytes are copied.
if (length === 0) {
typedArray.slice(0, end);
} else {
assert.throws(TypeError, () => {
typedArray.slice(0, end);
}, "ArrayBuffer is detached in ToInteger(end)");
}
assert.sameValue(detached, true, "$262.detachArrayBuffer was called");
}
// ArrayBuffer is detached in species constructor.
for (let {typedArray, length, buffer} of createTypedArrays()) {
let detached = false;
typedArray.constructor = {
[Symbol.species]: function(...args) {
assert.sameValue(detached, false);
$262.detachArrayBuffer(buffer());
assert.sameValue(detached, false);
detached = true;
return new Int32Array(...args);
}
};
// Doesn't throw an error when no bytes are copied.
if (length === 0) {
typedArray.slice(0);
} else {
assert.throws(TypeError, () => {
typedArray.slice(0);
}, "ArrayBuffer is detached in TypedArraySpeciesCreate(...)");
}
assert.sameValue(detached, true, "$262.detachArrayBuffer was called");
}
// ArrayBuffer is detached when entering slice().
for (let {typedArray, buffer} of createTypedArrays()) {
$262.detachArrayBuffer(buffer());
assert.throws(TypeError, () => {
typedArray.slice(0);
}, "ArrayBuffer is detached on function entry");
}
// ArrayBuffer is detached when computing ToInteger(start).
for (let {typedArray, length, buffer} of createTypedArrays()) {
let detached = false;
let start = {
valueOf() {
assert.sameValue(detached, false);
$262.detachArrayBuffer(buffer());
assert.sameValue(detached, false);
detached = true;
return 0;
}
};
// Doesn't throw an error when no bytes are copied.
if (length === 0) {
typedArray.slice(start);
} else {
assert.throws(TypeError, () => {
typedArray.slice(start);
}, "ArrayBuffer is detached in ToInteger(start)");
}
assert.sameValue(detached, true, "$262.detachArrayBuffer was called");
}
// ArrayBuffer is detached when computing ToInteger(end).
for (let {typedArray, length, buffer} of createTypedArrays()) {
let detached = false;
let end = {
valueOf() {
assert.sameValue(detached, false);
$262.detachArrayBuffer(buffer());
assert.sameValue(detached, false);
detached = true;
return length;
}
};
// Doesn't throw an error when no bytes are copied.
if (length === 0) {
typedArray.slice(0, end);
} else {
assert.throws(TypeError, () => {
typedArray.slice(0, end);
}, "ArrayBuffer is detached in ToInteger(end)");
}
assert.sameValue(detached, true, "$262.detachArrayBuffer was called");
}
// ArrayBuffer is detached in species constructor.
for (let {typedArray, length, buffer} of createTypedArrays()) {
let detached = false;
typedArray.constructor = {
[Symbol.species]: function(...args) {
assert.sameValue(detached, false);
$262.detachArrayBuffer(buffer());
assert.sameValue(detached, false);
detached = true;
return new Int32Array(...args);
}
};
// Doesn't throw an error when no bytes are copied.
if (length === 0) {
typedArray.slice(0);
} else {
assert.throws(TypeError, () => {
typedArray.slice(0);
}, "ArrayBuffer is detached in TypedArraySpeciesCreate(...)");
}
assert.sameValue(detached, true, "$262.detachArrayBuffer was called");
}

View File

@ -8,18 +8,17 @@ description: |
pending
esid: pending
---*/
// Ensure that TypedArrays throw when attempting to sort a detached ArrayBuffer
if (typeof $262.detachArrayBuffer === "function") {
assert.throws(TypeError, () => {
let buffer = new ArrayBuffer(32);
let array = new Int32Array(buffer);
$262.detachArrayBuffer(buffer);
array.sort();
});
}
assert.throws(TypeError, () => {
let buffer = new ArrayBuffer(32);
let array = new Int32Array(buffer);
$262.detachArrayBuffer(buffer);
array.sort();
});
// Ensure detaching buffer in comparator doesn't throw an error.
if (typeof $262.detachArrayBuffer === "function") {
{
let detached = false;
let ta = new Int32Array(3);
ta.sort(function(a, b) {
@ -43,7 +42,7 @@ let otherGlobal = $262.createRealm().global;
}
// Ensure detaching buffer in comparator doesn't throw an error when the typed array is wrapped.
if (typeof $262.detachArrayBuffer === "function") {
{
let detached = false;
let ta = new Int32Array(3);
otherGlobal.Int32Array.prototype.sort.call(ta, function(a,b) {

View File

@ -9,30 +9,27 @@ description: |
pending
esid: pending
---*/
// Bug 1291003
if (typeof $262.detachArrayBuffer === "function") {
for (let constructor of typedArrayConstructors) {
const elementSize = constructor.BYTES_PER_ELEMENT;
let targetOffset;
let buffer = new ArrayBuffer(2 * elementSize);
let typedArray = new constructor(buffer, 1 * elementSize, 1);
typedArray.constructor = {
[Symbol.species]: function(ab, offset, length) {
targetOffset = offset;
return new constructor(1);
}
};
for (let constructor of typedArrayConstructors) {
const elementSize = constructor.BYTES_PER_ELEMENT;
let beginIndex = {
valueOf() {
$262.detachArrayBuffer(buffer);
return 0;
}
};
typedArray.subarray(beginIndex);
let targetOffset;
let buffer = new ArrayBuffer(2 * elementSize);
let typedArray = new constructor(buffer, 1 * elementSize, 1);
typedArray.constructor = {
[Symbol.species]: function(ab, offset, length) {
targetOffset = offset;
return new constructor(1);
}
};
assert.sameValue(targetOffset, 1 * elementSize);
}
let beginIndex = {
valueOf() {
$262.detachArrayBuffer(buffer);
return 0;
}
};
typedArray.subarray(beginIndex);
assert.sameValue(targetOffset, 1 * elementSize);
}

View File

@ -9,39 +9,37 @@ description: |
pending
esid: pending
---*/
if (typeof $262.detachArrayBuffer === "function") {
const originalNumberToLocaleString = Number.prototype.toLocaleString;
// Throws if array buffer is detached.
for (let constructor of typedArrayConstructors) {
let typedArray = new constructor(42);
$262.detachArrayBuffer(typedArray.buffer);
assert.throws(TypeError, () => typedArray.toLocaleString());
}
const originalNumberToLocaleString = Number.prototype.toLocaleString;
// Doesn't throw a TypeError if detached in Number.prototype.toLocaleString.
for (let constructor of typedArrayConstructors) {
Number.prototype.toLocaleString = function() {
"use strict";
if (!detached) {
$262.detachArrayBuffer(typedArray.buffer);
detached = true;
}
return this;
};
// No error for single element arrays.
let detached = false;
let typedArray = new constructor(1);
assert.sameValue(typedArray.toLocaleString(), "0");
assert.sameValue(detached, true);
// And no error if more than one element is present.
detached = false;
typedArray = new constructor(2);
assert.sameValue(typedArray.toLocaleString(), "0,");
assert.sameValue(detached, true);
}
Number.prototype.toLocaleString = originalNumberToLocaleString;
// Throws if array buffer is detached.
for (let constructor of typedArrayConstructors) {
let typedArray = new constructor(42);
$262.detachArrayBuffer(typedArray.buffer);
assert.throws(TypeError, () => typedArray.toLocaleString());
}
// Doesn't throw a TypeError if detached in Number.prototype.toLocaleString.
for (let constructor of typedArrayConstructors) {
Number.prototype.toLocaleString = function() {
"use strict";
if (!detached) {
$262.detachArrayBuffer(typedArray.buffer);
detached = true;
}
return this;
};
// No error for single element arrays.
let detached = false;
let typedArray = new constructor(1);
assert.sameValue(typedArray.toLocaleString(), "0");
assert.sameValue(detached, true);
// And no error if more than one element is present.
detached = false;
typedArray = new constructor(2);
assert.sameValue(typedArray.toLocaleString(), "0,");
assert.sameValue(detached, true);
}
Number.prototype.toLocaleString = originalNumberToLocaleString;