RAB: Integrate staging tests for the .toLocaleString method (#4178)

* 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.

* Apply suggestions from code review

* Address review: get implementation dependent toLocaleString separator.

* Apply suggestions from code review
This commit is contained in:
Ioanna M Dimitriou H 2024-08-14 21:30:54 +02:00 committed by GitHub
parent 984df1f3db
commit b1d0933df5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 530 additions and 0 deletions

View File

@ -0,0 +1,88 @@
// 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.tolocalestring
description: >
Array.p.toLocaleString behaves correctly on TypedArrays backed by resizable
buffers.
includes: [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);
// toLocaleString separator is implementation dependent.
function listToString(list) {
const comma = ['',''].toLocaleString();
return list.join(comma);
}
// Write some data into the array.
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([0,2,4,6]));
assert.sameValue(Array.prototype.toLocaleString.call(fixedLengthWithOffset), listToString([4,6]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([0,2,4,6]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTrackingWithOffset), listToString([4,6]));
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(fixedLengthWithOffset), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([0,2,4]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTrackingWithOffset), listToString([4]));
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(fixedLengthWithOffset), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTrackingWithOffset), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([0]));
// Shrink to zero.
rab.resize(0);
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(fixedLengthWithOffset), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTrackingWithOffset), listToString([]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([]));
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([0,2,4,6]));
assert.sameValue(Array.prototype.toLocaleString.call(fixedLengthWithOffset), listToString([4,6]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([0,2,4,6,8,10]));
assert.sameValue(Array.prototype.toLocaleString.call(lengthTrackingWithOffset), listToString([4,6,8,10]));
}

View File

@ -0,0 +1,81 @@
// 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.tolocalestring
description: >
Array.p.toLocaleString behaves correctly when {Number,BigInt}.prototype.toLocaleString
is replaced with a user-provided function that grows the array.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
const oldNumberPrototypeToLocaleString = Number.prototype.toLocaleString;
const oldBigIntPrototypeToLocaleString = BigInt.prototype.toLocaleString;
// toLocaleString separator is implementation dependent.
function listToString(list) {
const comma = ['',''].toLocaleString();
const len = list.length;
let result = '';
if (len > 1) {
for (let i=0; i < len - 1 ; i++) {
result += list[i] + comma;
}
}
if (len > 0) {
result += list[len-1];
}
return result;
}
// Growing + fixed-length TA.
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);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements since it was the starting length. Resizing doesn't
// affect the TA.
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength), listToString([0,0,0,0]));
}
// Growing + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements since it was the starting length.
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking), listToString([0,0,0,0]));
}
Number.prototype.toLocaleString = oldNumberPrototypeToLocaleString;
BigInt.prototype.toLocaleString = oldBigIntPrototypeToLocaleString;

View File

@ -0,0 +1,82 @@
// 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.tolocalestring
description: >
Array.p.toLocaleString behaves correctly when {Number,BigInt}.prototype.toLocaleString
is replaced with a user-provided function that shrinks the array.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
const oldNumberPrototypeToLocaleString = Number.prototype.toLocaleString;
const oldBigIntPrototypeToLocaleString = BigInt.prototype.toLocaleString;
// toLocaleString separator is implementation dependent.
function listToString(list) {
const comma = ['',''].toLocaleString();
const len = list.length;
let result = '';
if (len > 1) {
for (let i=0; i < len - 1 ; i++) {
result += list[i] + comma;
}
}
if (len > 0) {
result += list[len-1];
}
return result;
}
// Shrinking + fixed-length TA.
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);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements, since it was the starting length. The TA goes
// OOB after 2 elements.
assert.sameValue(Array.prototype.toLocaleString.call(fixedLength),listToString([0,0,'','']));
}
// Shrinking + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements, since it was the starting length. Elements beyond
// the new length are converted to the empty string.
assert.sameValue(Array.prototype.toLocaleString.call(lengthTracking),listToString([0,0,'','']));
}
Number.prototype.toLocaleString = oldNumberPrototypeToLocaleString;
BigInt.prototype.toLocaleString = oldBigIntPrototypeToLocaleString;

View File

@ -0,0 +1,114 @@
// 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.tolocalestring
description: >
TypedArray.p.toLocaleString behaves correctly on TypedArrays backed by
resizable buffers.
includes: [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);
// toLocaleString separator is implementation dependent.
function listToString(list) {
const comma = ['',''].toLocaleString();
const len = list.length;
let result = '';
if (len > 1) {
for (let i=0; i < len - 1 ; i++) {
result += list[i] + comma;
}
}
if (len > 0) {
result += list[len-1];
}
return result;
}
// Write some data into the array.
for (let i = 0; i < 4; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, ...] << lengthTracking
// [4, 6, ...] << lengthTrackingWithOffset
assert.sameValue(fixedLength.toLocaleString(),listToString([0,2,4,6]));
assert.sameValue(fixedLengthWithOffset.toLocaleString(),listToString([4,6]));
assert.sameValue(lengthTracking.toLocaleString(),listToString([0,2,4,6]));
assert.sameValue(lengthTrackingWithOffset.toLocaleString(),listToString([4,6]));
// Shrink so that fixed length TAs go out of bounds.
rab.resize(3 * ctor.BYTES_PER_ELEMENT);
// Orig. array: [0, 2, 4]
// [0, 2, 4, ...] << lengthTracking
// [4, ...] << lengthTrackingWithOffset
assert.throws(TypeError, () => {
fixedLength.toLocaleString();
});
assert.throws(TypeError, () => {
fixedLengthWithOffset.toLocaleString();
});
assert.sameValue(lengthTracking.toLocaleString(),listToString([0,2,4]));
assert.sameValue(lengthTrackingWithOffset.toLocaleString(),listToString([4]));
// Shrink so that the TAs with offset go out of bounds.
rab.resize(1 * ctor.BYTES_PER_ELEMENT);
assert.throws(TypeError, () => {
fixedLength.toLocaleString();
});
assert.throws(TypeError, () => {
fixedLengthWithOffset.toLocaleString();
});
assert.throws(TypeError, () => {
lengthTrackingWithOffset.toLocaleString();
});
assert.sameValue(lengthTracking.toLocaleString(),listToString([0]));
// Shrink to zero.
rab.resize(0);
assert.throws(TypeError, () => {
fixedLength.toLocaleString();
});
assert.throws(TypeError, () => {
fixedLengthWithOffset.toLocaleString();
});
assert.throws(TypeError, () => {
lengthTrackingWithOffset.toLocaleString();
});
assert.sameValue(lengthTracking.toLocaleString(),listToString([]));
// Grow so that all TAs are back in-bounds.
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
for (let i = 0; i < 6; ++i) {
WriteToTypedArray(taWrite, i, 2 * i);
}
// Orig. array: [0, 2, 4, 6, 8, 10]
// [0, 2, 4, 6] << fixedLength
// [4, 6] << fixedLengthWithOffset
// [0, 2, 4, 6, 8, 10, ...] << lengthTracking
// [4, 6, 8, 10, ...] << lengthTrackingWithOffset
assert.sameValue(fixedLength.toLocaleString(),listToString([0,2,4,6]));
assert.sameValue(fixedLengthWithOffset.toLocaleString(),listToString([4,6]));
assert.sameValue(lengthTracking.toLocaleString(),listToString([0,2,4,6,8,10]));
assert.sameValue(lengthTrackingWithOffset.toLocaleString(),listToString([4,6,8,10]));
}

View File

@ -0,0 +1,82 @@
// 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.tolocalestring
description: >
TypedArray.p.toLocaleString behaves correctly when {Number,BigInt}.
prototype.toLocaleString is replaced with a user-provided function
that grows the underlying resizable buffer.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
const oldNumberPrototypeToLocaleString = Number.prototype.toLocaleString;
const oldBigIntPrototypeToLocaleString = BigInt.prototype.toLocaleString;
// toLocaleString separator is implementation dependent.
function listToString(list) {
const comma = ['',''].toLocaleString();
const len = list.length;
let result = '';
if (len > 1) {
for (let i=0; i < len - 1 ; i++) {
result += list[i] + comma;
}
}
if (len > 0) {
result += list[len-1];
}
return result;
}
// Growing + fixed-length TA.
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);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements since it was the starting length. Resizing doesn't
// affect the TA.
assert.sameValue(fixedLength.toLocaleString(), listToString([0,0,0,0]));
}
// Growing + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements since it was the starting length.
assert.sameValue(lengthTracking.toLocaleString(), listToString([0,0,0,0]));
}
Number.prototype.toLocaleString = oldNumberPrototypeToLocaleString;
BigInt.prototype.toLocaleString = oldBigIntPrototypeToLocaleString;

View File

@ -0,0 +1,83 @@
// 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.tolocalestring
description: >
TypedArray.p.toLocaleString behaves correctly when {Number,BigInt}.
prototype.toLocaleString is replaced with a user-provided function
that shrinks the underlying resizable buffer.
includes: [resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/
const oldNumberPrototypeToLocaleString = Number.prototype.toLocaleString;
const oldBigIntPrototypeToLocaleString = BigInt.prototype.toLocaleString;
// toLocaleString separator is implementation dependent.
function listToString(list) {
const comma = ['',''].toLocaleString();
const len = list.length;
let result = '';
if (len > 1) {
for (let i=0; i < len - 1 ; i++) {
result += list[i] + comma;
}
}
if (len > 0) {
result += list[len-1];
}
return result;
}
// Shrinking + fixed-length TA.
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);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements, since it was the starting length. The TA goes
// OOB after 2 elements.
assert.sameValue(fixedLength.toLocaleString(), listToString([0,0,'','']));
}
// Shrinking + length-tracking TA.
for (let ctor of ctors) {
const rab = CreateResizableArrayBuffer(4 * ctor.BYTES_PER_ELEMENT, 8 * ctor.BYTES_PER_ELEMENT);
const lengthTracking = new ctor(rab);
let resizeAfter = 2;
Number.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldNumberPrototypeToLocaleString.call(this);
};
BigInt.prototype.toLocaleString = function () {
--resizeAfter;
if (resizeAfter == 0) {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
}
return oldBigIntPrototypeToLocaleString.call(this);
};
// We iterate 4 elements, since it was the starting length. Elements beyond
// the new length are converted to the empty string.
assert.sameValue(lengthTracking.toLocaleString(), listToString([0,0,'','']));
}
Number.prototype.toLocaleString = oldNumberPrototypeToLocaleString;
BigInt.prototype.toLocaleString = oldBigIntPrototypeToLocaleString;