Skip to content

Add coverage for some implementation bugs in Array and TypedArray methods #4477

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
27 changes: 27 additions & 0 deletions test/built-ins/Array/prototype/with/index-throw-completion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.prototype.with
description: >
Index coercion returns a throw completion.
info: |
Array.prototype.with ( index, value )

...
4. Let relativeIndex be ? ToIntegerOrInfinity(index).
...
features: [change-array-by-copy]
---*/

function MyError() {}

var index = {
valueOf() {
throw new MyError();
}
};

assert.throws(MyError, function() {
[].with(index, null);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-array.prototype.with
description: >
Negative fractional index which is truncated to zero.
info: |
Array.prototype.with ( index, value )

...
3. Let relativeIndex be ? ToIntegerOrInfinity(index).
...

ToIntegerOrInfinity ( argument )

1. Let number be ? ToNumber(argument).
2. If number is one of NaN, +0𝔽, or -0𝔽, return 0.
3. If number is +∞𝔽, return +∞.
4. If number is -∞𝔽, return -∞.
5. Return truncate(ℝ(number)).
features: [change-array-by-copy]
---*/

var result = [0].with(-0.5, 123);
assert.sameValue(result[0], 123);
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-%typedarray%.prototype.lastIndexOf
description: >
Negative index is relative to the original typed array length.
info: |
%TypedArray%.prototype.lastIndexOf ( searchElement [ , fromIndex ] )

...
5. If fromIndex is present, let n be ? ToIntegerOrInfinity(fromIndex); else let n be len - 1.
6. If n = -∞, return -1𝔽.
7. If n ≥ 0, then
a. Let k be min(n, len - 1).
8. Else,
a. Let k be len + n.
...
features: [TypedArray, resizable-arraybuffer]
includes: [testTypedArray.js]
---*/

testWithTypedArrayConstructors(function(TA) {
var byteLength = 4 * TA.BYTES_PER_ELEMENT;
var rab = new ArrayBuffer(0, {maxByteLength: byteLength});
var ta = new TA(rab);

var indices = [
[-1, 2],
[-2, 2],
[-3, 1],
[-4, 0],
[-5, -1],
];

for (var i = 0; i < indices.length; ++i) {
var index = indices[i][0];
var expected = indices[i][1];
var searchElement = 123;

rab.resize(byteLength);
ta.fill(searchElement);

var indexValue = {
valueOf() {
rab.resize(3 * TA.BYTES_PER_ELEMENT);
return index;
}
};

assert.sameValue(
ta.lastIndexOf(searchElement, indexValue),
expected,
"For index " + index
);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-%typedarray%.prototype.slice
description: >
When species constructs a typed array using the same buffer but with a
different byte offset, slice output reflects element-by-element copying into
that buffer.
info: |
%TypedArray%.prototype.slice ( start, end )

...
14. If countBytes > 0, then
g. If srcType is targetType, then
ix. Repeat, while targetByteIndex < endByteIndex,
1. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered).
2. Perform SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered).
...
features: [TypedArray]
includes: [testTypedArray.js, compareArray.js]
---*/

testWithTypedArrayConstructors(function(TA) {
var ta = new TA([
10,
20,
30,
40,
50,
60,
]);

ta.constructor = {
[Symbol.species]: function() {
return new TA(ta.buffer, 2 * TA.BYTES_PER_ELEMENT);
}
};

var result = ta.slice(1, 4);

assert.compareArray(result, [
20, 20, 20, 60,
]);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-%typedarray%.prototype.subarray
description: >
Species constructor is called with the correct byte-offset value
info: |
%TypedArray%.prototype.subarray ( start, end )

...
13. Let srcByteOffset be O.[[ByteOffset]].
14. Let beginByteOffset be srcByteOffset + (startIndex × elementSize).
...
16. Else,
...
f. Let argumentsList be « buffer, 𝔽(beginByteOffset), 𝔽(newLength) ».
17. Return ? TypedArraySpeciesCreate(O, argumentsList).
features: [TypedArray]
includes: [testTypedArray.js, detachArrayBuffer.js]
---*/

testWithTypedArrayConstructors(function(TA) {
var ab = new ArrayBuffer(2 * TA.BYTES_PER_ELEMENT);
var ta = new TA(ab, TA.BYTES_PER_ELEMENT, 1);
var result = new TA(0);

ta.constructor = {
[Symbol.species]: function(buffer, byteOffset, length) {
assert.sameValue(buffer, ab);
assert.sameValue(byteOffset, 2 * TA.BYTES_PER_ELEMENT);
assert.sameValue(length, 0);
return result;
}
};

var end = {
valueOf() {
$DETACHBUFFER(ab);
return 0;
}
};

assert.sameValue(ta.subarray(1, end), result);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-%typedarray%.prototype.with
description: >
Index coercion returns a throw completion.
info: |
%TypedArray%.prototype.with ( index, value )

...
4. Let relativeIndex be ? ToIntegerOrInfinity(index).
...
features: [TypedArray, change-array-by-copy]
includes: [testTypedArray.js]
---*/

function MyError() {}

testWithTypedArrayConstructors(function(TA) {
var ta = new TA(1);

var index = {
valueOf() {
throw new MyError();
}
};

var value = {
valueOf() {
throw new Test262Error("Unexpected value coercion");
}
};

assert.throws(MyError, function() {
ta.with(index, value);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-%typedarray%.prototype.with
description: >
Negative fractional index which is truncated to zero.
info: |
%TypedArray%.prototype.with ( index, value )

...
4. Let relativeIndex be ? ToIntegerOrInfinity(index).
...

ToIntegerOrInfinity ( argument )

1. Let number be ? ToNumber(argument).
2. If number is one of NaN, +0𝔽, or -0𝔽, return 0.
3. If number is +∞𝔽, return +∞.
4. If number is -∞𝔽, return -∞.
5. Return truncate(ℝ(number)).
features: [TypedArray, change-array-by-copy]
includes: [testTypedArray.js]
---*/

testWithTypedArrayConstructors(function(TA) {
var ta = new TA(1);
var result = ta.with(-0.5, 123);
assert.sameValue(result[0], 123);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-%typedarray%.prototype.with
description: >
Negative index is relative to the original typed array length.
info: |
%TypedArray%.prototype.with ( index, value )

...
4. Let relativeIndex be ? ToIntegerOrInfinity(index).
5. If relativeIndex ≥ 0, let actualIndex be relativeIndex.
6. Else, let actualIndex be len + relativeIndex.
...
9. If IsValidIntegerIndex(O, 𝔽(actualIndex)) is false, throw a RangeError exception.
...
features: [TypedArray, change-array-by-copy, resizable-arraybuffer]
includes: [testTypedArray.js]
---*/

testWithTypedArrayConstructors(function(TA) {
var byteLength = 4 * TA.BYTES_PER_ELEMENT;
var rab = new ArrayBuffer(0, {maxByteLength: byteLength});
var ta = new TA(rab);

var value = {
valueOf() {
rab.resize(byteLength);
return 123;
}
};

assert.throws(RangeError, function() {
ta.with(-1, value);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-%typedarray%.prototype.with
description: >
Negative index is relative to the original typed array length.
info: |
%TypedArray%.prototype.with ( index, value )

...
4. Let relativeIndex be ? ToIntegerOrInfinity(index).
5. If relativeIndex ≥ 0, let actualIndex be relativeIndex.
6. Else, let actualIndex be len + relativeIndex.
...
9. If IsValidIntegerIndex(O, 𝔽(actualIndex)) is false, throw a RangeError exception.
...
features: [TypedArray, change-array-by-copy, resizable-arraybuffer]
includes: [testTypedArray.js]
---*/

testWithTypedArrayConstructors(function(TA) {
var byteLength = 4 * TA.BYTES_PER_ELEMENT;
var rab = new ArrayBuffer(byteLength, {maxByteLength: byteLength});
var ta = new TA(rab);

var value = {
valueOf() {
rab.resize(TA.BYTES_PER_ELEMENT);
return 123;
}
};

assert.throws(RangeError, function() {
ta.with(-1, value);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-%typedarray%.prototype.with
description: >
Value coercion returns a throw completion.
info: |
%TypedArray%.prototype.with ( index, value )

...
7. If O.[[ContentType]] is bigint, let numericValue be ? ToBigInt(value).
8. Else, let numericValue be ? ToNumber(value).
...
features: [TypedArray, change-array-by-copy]
includes: [testTypedArray.js]
---*/

function MyError() {}

testWithTypedArrayConstructors(function(TA) {
var ta = new TA(1);

var value = {
valueOf() {
throw new MyError();
}
};

assert.throws(MyError, function() {
ta.with(100, value);
}, "Positive too large index");

assert.throws(MyError, function() {
ta.with(-100, value);
}, "Negative too large index");
});
Loading