RAB: Integrate staging tests for the .sort method (#4176)

* Import relevant files from #3888

* Removing parts in resizableArrayBufferUtils.js and adding it in includes,
while applying review changes from PRs for previously tested methods.

* Renamed test files

* Some minor documentation fixes and removing onlyStrict flag
This commit is contained in:
Ioanna M Dimitriou H 2024-08-06 02:22:10 +02:00 committed by GitHub
parent c0942e0883
commit ef72bd1c44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 1036 additions and 0 deletions

View File

@ -0,0 +1,69 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.sort
description: >
Array.p.sort behaves correctly on TypedArrays backed by resizable buffers which
are grown by the comparison callback.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
function ResizeAndCompare(rab, resizeTo) {
return (a, b) => {
rab.resize(resizeTo);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
}
function WriteUnsortedData(taFull) {
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - i);
}
}
// Fixed length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 6 * ctor.BYTES_PER_ELEMENT;
const fixedLength = new ctor(rab, 0, 4);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
Array.prototype.sort.call(fixedLength, ResizeAndCompare(rab, resizeTo));
// Growing doesn't affect the sorting.
assert.compareArray(ToNumbers(taFull), [
7,
8,
9,
10,
0,
0
]);
}
// Length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 6 * ctor.BYTES_PER_ELEMENT;
const lengthTracking = new ctor(rab, 0);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
Array.prototype.sort.call(lengthTracking, ResizeAndCompare(rab, resizeTo));
// Growing doesn't affect the sorting. Only the elements that were part of
// the original TA are sorted.
assert.compareArray(ToNumbers(taFull), [
7,
8,
9,
10,
0,
0
]);
}

View File

@ -0,0 +1,191 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.sort
description: >
Array.p.sort behaves correctly on TypedArrays backed by resizable buffers and
is passed a user-provided comparison callback.
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 taFull = new ctor(rab, 0);
function WriteUnsortedData() {
// Write some data into the array.
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - i);
}
}
function OddBeforeEvenComparison(a, b) {
// Sort all odd numbers before even numbers.
a = Number(a);
b = Number(b);
if (a % 2 == 1 && b % 2 == 0) {
return -1;
}
if (a % 2 == 0 && b % 2 == 1) {
return 1;
}
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
// Orig. array: [10, 9, 8, 7]
// [10, 9, 8, 7] << fixedLength
// [8, 7] << fixedLengthWithOffset
// [10, 9, 8, 7, ...] << lengthTracking
// [8, 7, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
7,
9,
8,
10
]);
WriteUnsortedData();
Array.prototype.sort.call(fixedLengthWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
7,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
7,
9,
8,
10
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
7,
8
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 9, 8]
// [10, 9, 8, ...] << lengthTracking
// [8, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
8
]);
Array.prototype.sort.call(fixedLengthWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
9,
8,
10
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
8
]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
WriteUnsortedData();
Array.prototype.sort.call(fixedLength, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [10]);
Array.prototype.sort.call(fixedLengthWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [10]);
Array.prototype.sort.call(lengthTrackingWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [10]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [10]);
// Shrink to zero.
rab.resize(0);
Array.prototype.sort.call(fixedLength, OddBeforeEvenComparison);
Array.prototype.sort.call(fixedLengthWithOffset, OddBeforeEvenComparison);
Array.prototype.sort.call(lengthTrackingWithOffset, OddBeforeEvenComparison);
Array.prototype.sort.call(lengthTracking, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 9, 8, 7, 6, 5]
// [10, 9, 8, 7] << fixedLength
// [8, 7] << fixedLengthWithOffset
// [10, 9, 8, 7, 6, 5, ...] << lengthTracking
// [8, 7, 6, 5, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
7,
9,
8,
10,
6,
5
]);
WriteUnsortedData();
Array.prototype.sort.call(fixedLengthWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
7,
8,
6,
5
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
5,
7,
9,
6,
8,
10
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset, OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
5,
7,
6,
8
]);
}

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-array.prototype.sort
description: >
Array.p.sort behaves correctly on TypedArrays backed by resizable buffers and
is shrunk by the comparison callback.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer, Array.prototype.includes]
---*/
function ResizeAndCompare(rab, resizeTo) {
return (a, b) => {
rab.resize(resizeTo);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
}
function WriteUnsortedData(taFull) {
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - i);
}
}
// Fixed length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 2 * ctor.BYTES_PER_ELEMENT;
const fixedLength = new ctor(rab, 0, 4);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
Array.prototype.sort.call(fixedLength, ResizeAndCompare(rab, resizeTo));
// The data is unchanged.
assert.compareArray(ToNumbers(taFull), [
10,
9
]);
}
// Length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 2 * ctor.BYTES_PER_ELEMENT;
const lengthTracking = new ctor(rab, 0);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
Array.prototype.sort.call(lengthTracking, ResizeAndCompare(rab, resizeTo));
// The sort result is implementation defined, but it contains 2 elements out
// of the 4 original ones.
const newData = ToNumbers(taFull);
assert.sameValue(newData.length, 2);
assert([
10,
9,
8,
7
].includes(newData[0]));
assert([
10,
9,
8,
7
].includes(newData[1]));
}

View File

@ -0,0 +1,173 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-array.prototype.sort
description: >
Array.p.sort behaves correctly on TypedArrays backed by resizable buffers.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
// The default comparison function for Array.prototype.sort is the string sort.
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);
function WriteUnsortedData() {
// Write some data into the array.
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - 2 * i);
}
}
// Orig. array: [10, 8, 6, 4]
// [10, 8, 6, 4] << fixedLength
// [6, 4] << fixedLengthWithOffset
// [10, 8, 6, 4, ...] << lengthTracking
// [6, 4, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength);
assert.compareArray(ToNumbers(taFull), [
10,
4,
6,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(fixedLengthWithOffset);
assert.compareArray(ToNumbers(taFull), [
10,
8,
4,
6
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking);
assert.compareArray(ToNumbers(taFull), [
10,
4,
6,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(taFull), [
10,
8,
4,
6
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 8, 6]
// [10, 8, 6, ...] << lengthTracking
// [6, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), [
10,
8,
6
]);
Array.prototype.sort.call(fixedLengthWithOffset); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), [
10,
8,
6
]);
Array.prototype.sort.call(lengthTracking);
assert.compareArray(ToNumbers(taFull), [
10,
6,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(taFull), [
10,
8,
6
]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
WriteUnsortedData();
Array.prototype.sort.call(fixedLength); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), [10]);
Array.prototype.sort.call(fixedLengthWithOffset); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), [10]);
Array.prototype.sort.call(lengthTrackingWithOffset); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), [10]);
Array.prototype.sort.call(lengthTracking);
assert.compareArray(ToNumbers(taFull), [10]);
// Shrink to zero.
rab.resize(0);
Array.prototype.sort.call(fixedLength); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), []);
Array.prototype.sort.call(fixedLengthWithOffset); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), []);
Array.prototype.sort.call(lengthTrackingWithOffset); // OOB -> NOOP
assert.compareArray(ToNumbers(taFull), []);
Array.prototype.sort.call(lengthTracking);
assert.compareArray(ToNumbers(taFull), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 8, 6, 4, 2, 0]
// [10, 8, 6, 4] << fixedLength
// [6, 4] << fixedLengthWithOffset
// [10, 8, 6, 4, 2, 0, ...] << lengthTracking
// [6, 4, 2, 0, ...] << lengthTrackingWithOffset
WriteUnsortedData();
Array.prototype.sort.call(fixedLength);
assert.compareArray(ToNumbers(taFull), [
10,
4,
6,
8,
2,
0
]);
WriteUnsortedData();
Array.prototype.sort.call(fixedLengthWithOffset);
assert.compareArray(ToNumbers(taFull), [
10,
8,
4,
6,
2,
0
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTracking);
assert.compareArray(ToNumbers(taFull), [
0,
10,
2,
4,
6,
8
]);
WriteUnsortedData();
Array.prototype.sort.call(lengthTrackingWithOffset);
assert.compareArray(ToNumbers(taFull), [
10,
8,
0,
2,
4,
6
]);
}

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-%typedarray%.prototype.sort
description: >
TypedArray.p.sort behaves correctly on TypedArrays backed by resizable buffers
which are grown by the comparison callback.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
// Returns a function that resizes rab to size resizeTo and then compares its
// arguments. Such a result function is to be used as an argument to .sort.
function ResizeAndCompare(rab, resizeTo) {
return (a, b) => {
rab.resize(resizeTo);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
}
function WriteUnsortedData(taFull) {
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - i);
}
}
// Fixed length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 6 * ctor.BYTES_PER_ELEMENT;
const fixedLength = new ctor(rab, 0, 4);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
fixedLength.sort(ResizeAndCompare(rab, resizeTo));
// Growing doesn't affect the sorting.
assert.compareArray(ToNumbers(taFull), [
7,
8,
9,
10,
0,
0
]);
}
// Length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 6 * ctor.BYTES_PER_ELEMENT;
const lengthTracking = new ctor(rab, 0);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
lengthTracking.sort(ResizeAndCompare(rab, resizeTo));
// Growing doesn't affect the sorting. Only the elements that were part of
// the original TA are sorted.
assert.compareArray(ToNumbers(taFull), [
7,
8,
9,
10,
0,
0
]);
}

View File

@ -0,0 +1,206 @@
// 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.sort
description: >
TypedArray.p.sort behaves correctly on TypedArrays backed by resizable buffers
and passed a user-provided comparison callback.
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 taFull = new ctor(rab, 0);
function WriteUnsortedData() {
// Write some data into the array.
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - i);
}
}
function OddBeforeEvenComparison(a, b) {
// Sort all odd numbers before even numbers.
a = Number(a);
b = Number(b);
if (a % 2 == 1 && b % 2 == 0) {
return -1;
}
if (a % 2 == 0 && b % 2 == 1) {
return 1;
}
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
// Orig. array: [10, 9, 8, 7]
// [10, 9, 8, 7] << fixedLength
// [8, 7] << fixedLengthWithOffset
// [10, 9, 8, 7, ...] << lengthTracking
// [8, 7, ...] << lengthTrackingWithOffset
WriteUnsortedData();
fixedLength.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
7,
9,
8,
10
]);
WriteUnsortedData();
fixedLengthWithOffset.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
7,
8
]);
WriteUnsortedData();
lengthTracking.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
7,
9,
8,
10
]);
WriteUnsortedData();
lengthTrackingWithOffset.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
7,
8
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 9, 8]
// [10, 9, 8, ...] << lengthTracking
// [8, ...] << lengthTrackingWithOffset
WriteUnsortedData();
assert.throws(TypeError, () => {
fixedLength.sort(OddBeforeEvenComparison);
});
assert.compareArray(ToNumbers(taFull), [
10,
9,
8
]);
assert.throws(TypeError, () => {
fixedLengthWithOffset.sort(OddBeforeEvenComparison);
});
assert.compareArray(ToNumbers(taFull), [
10,
9,
8
]);
WriteUnsortedData();
lengthTracking.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
9,
8,
10
]);
WriteUnsortedData();
lengthTrackingWithOffset.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
8
]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
WriteUnsortedData();
assert.throws(TypeError, () => {
fixedLength.sort(OddBeforeEvenComparison);
});
assert.compareArray(ToNumbers(taFull), [10]);
assert.throws(TypeError, () => {
fixedLengthWithOffset.sort(OddBeforeEvenComparison);
});
assert.compareArray(ToNumbers(taFull), [10]);
assert.throws(TypeError, () => {
lengthTrackingWithOffset.sort(OddBeforeEvenComparison);
});
assert.compareArray(ToNumbers(taFull), [10]);
WriteUnsortedData();
lengthTracking.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [10]);
// Shrink to zero.
rab.resize(0);
assert.throws(TypeError, () => {
fixedLength.sort(OddBeforeEvenComparison);
});
assert.throws(TypeError, () => {
fixedLengthWithOffset.sort(OddBeforeEvenComparison);
});
assert.throws(TypeError, () => {
lengthTrackingWithOffset.sort(OddBeforeEvenComparison);
});
lengthTracking.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), []);
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 9, 8, 7, 6, 5]
// [10, 9, 8, 7] << fixedLength
// [8, 7] << fixedLengthWithOffset
// [10, 9, 8, 7, 6, 5, ...] << lengthTracking
// [8, 7, 6, 5, ...] << lengthTrackingWithOffset
WriteUnsortedData();
fixedLength.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
7,
9,
8,
10,
6,
5
]);
WriteUnsortedData();
fixedLengthWithOffset.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
7,
8,
6,
5
]);
WriteUnsortedData();
lengthTracking.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
5,
7,
9,
6,
8,
10
]);
WriteUnsortedData();
lengthTrackingWithOffset.sort(OddBeforeEvenComparison);
assert.compareArray(ToNumbers(taFull), [
10,
9,
5,
7,
6,
8
]);
}

View File

@ -0,0 +1,73 @@
// 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.sort
description: >
TypedArray.p.sort behaves correctly on TypedArrays backed by a
resizable buffer and is shrunk by the comparison callback
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer, Array.prototype.includes]
---*/
// Returns a function that resizes rab to size resizeTo and then compares its
// arguments. Such a result function is to be used as an argument to .sort.
function ResizeAndCompare(rab, resizeTo) {
return (a, b) => {
rab.resize(resizeTo);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
}
function WriteUnsortedData(taFull) {
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - i);
}
}
// Fixed length TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 2 * ctor.BYTES_PER_ELEMENT;
const fixedLength = new ctor(rab, 0, 4);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
fixedLength.sort(ResizeAndCompare(rab, resizeTo));
// The data is unchanged.
assert.compareArray(ToNumbers(taFull), [
10,
9
]);
}
// Length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const resizeTo = 2 * ctor.BYTES_PER_ELEMENT;
const lengthTracking = new ctor(rab, 0);
const taFull = new ctor(rab, 0);
WriteUnsortedData(taFull);
lengthTracking.sort(ResizeAndCompare(rab, resizeTo));
// The sort result is implementation defined, but it contains 2 elements out
// of the 4 original ones.
const newData = ToNumbers(taFull);
assert.sameValue(newData.length, 2);
assert([
10,
9,
8,
7
].includes(newData[0]));
assert([
10,
9,
8,
7
].includes(newData[1]));
}

View File

@ -0,0 +1,182 @@
// 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.sort
description: >
TypedArray.p.sort behaves correctly on TypedArrays backed by resizable buffers.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
// This test cannot be reused between TypedArray.protoype.sort and
// Array.prototype.sort, since the default sorting functions differ.
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);
function WriteUnsortedData() {
// Write some data into the array.
for (let i = 0; i < taFull.length; ++i) {
WriteToTypedArray(taFull, i, 10 - 2 * i);
}
}
// Orig. array: [10, 8, 6, 4]
// [10, 8, 6, 4] << fixedLength
// [6, 4] << fixedLengthWithOffset
// [10, 8, 6, 4, ...] << lengthTracking
// [6, 4, ...] << lengthTrackingWithOffset
WriteUnsortedData();
fixedLength.sort();
assert.compareArray(ToNumbers(taFull), [
4,
6,
8,
10
]);
WriteUnsortedData();
fixedLengthWithOffset.sort();
assert.compareArray(ToNumbers(taFull), [
10,
8,
4,
6
]);
WriteUnsortedData();
lengthTracking.sort();
assert.compareArray(ToNumbers(taFull), [
4,
6,
8,
10
]);
WriteUnsortedData();
lengthTrackingWithOffset.sort();
assert.compareArray(ToNumbers(taFull), [
10,
8,
4,
6
]);
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 8, 6]
// [10, 8, 6, ...] << lengthTracking
// [6, ...] << lengthTrackingWithOffset
WriteUnsortedData();
assert.throws(TypeError, () => {
fixedLength.sort();
});
WriteUnsortedData();
assert.throws(TypeError, () => {
fixedLengthWithOffset.sort();
});
WriteUnsortedData();
lengthTracking.sort();
assert.compareArray(ToNumbers(taFull), [
6,
8,
10
]);
WriteUnsortedData();
lengthTrackingWithOffset.sort();
assert.compareArray(ToNumbers(taFull), [
10,
8,
6
]);
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
WriteUnsortedData();
assert.throws(TypeError, () => {
fixedLength.sort();
});
WriteUnsortedData();
assert.throws(TypeError, () => {
fixedLengthWithOffset.sort();
});
WriteUnsortedData();
lengthTracking.sort();
assert.compareArray(ToNumbers(taFull), [10]);
WriteUnsortedData();
assert.throws(TypeError, () => {
lengthTrackingWithOffset.sort();
});
// Shrink to zero.
rab.resize(0);
WriteUnsortedData();
assert.throws(TypeError, () => {
fixedLength.sort();
});
WriteUnsortedData();
assert.throws(TypeError, () => {
fixedLengthWithOffset.sort();
});
WriteUnsortedData();
lengthTracking.sort();
assert.compareArray(ToNumbers(taFull), []);
WriteUnsortedData();
assert.throws(TypeError, () => {
lengthTrackingWithOffset.sort();
});
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [10, 8, 6, 4, 2, 0]
// [10, 8, 6, 4] << fixedLength
// [6, 4] << fixedLengthWithOffset
// [10, 8, 6, 4, 2, 0, ...] << lengthTracking
// [6, 4, 2, 0, ...] << lengthTrackingWithOffset
WriteUnsortedData();
fixedLength.sort();
assert.compareArray(ToNumbers(taFull), [
4,
6,
8,
10,
2,
0
]);
WriteUnsortedData();
fixedLengthWithOffset.sort();
assert.compareArray(ToNumbers(taFull), [
10,
8,
4,
6,
2,
0
]);
WriteUnsortedData();
lengthTracking.sort();
assert.compareArray(ToNumbers(taFull), [
0,
2,
4,
6,
8,
10
]);
WriteUnsortedData();
lengthTrackingWithOffset.sort();
assert.compareArray(ToNumbers(taFull), [
10,
8,
0,
2,
4,
6
]);
}