summaryrefslogtreecommitdiff
path: root/deps/v8/test/mjsunit/typedarray-growablesharedarraybuffer.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/mjsunit/typedarray-growablesharedarraybuffer.js')
-rw-r--r--deps/v8/test/mjsunit/typedarray-growablesharedarraybuffer.js1345
1 files changed, 1340 insertions, 5 deletions
diff --git a/deps/v8/test/mjsunit/typedarray-growablesharedarraybuffer.js b/deps/v8/test/mjsunit/typedarray-growablesharedarraybuffer.js
index b4703dd841..28a9d42bb0 100644
--- a/deps/v8/test/mjsunit/typedarray-growablesharedarraybuffer.js
+++ b/deps/v8/test/mjsunit/typedarray-growablesharedarraybuffer.js
@@ -93,6 +93,93 @@ d8.file.execute('test/mjsunit/typedarray-helpers.js');
/Invalid typed array length: 2/);
})();
+(function ConstructFromTypedArray() {
+ AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
+ const gsab = CreateGrowableSharedArrayBuffer(
+ 4 * sourceCtor.BYTES_PER_ELEMENT,
+ 8 * sourceCtor.BYTES_PER_ELEMENT);
+ const fixedLength = new sourceCtor(gsab, 0, 4);
+ const fixedLengthWithOffset = new sourceCtor(
+ gsab, 2 * sourceCtor.BYTES_PER_ELEMENT, 2);
+ const lengthTracking = new sourceCtor(gsab, 0);
+ const lengthTrackingWithOffset = new sourceCtor(
+ gsab, 2 * sourceCtor.BYTES_PER_ELEMENT);
+
+ // Write some data into the array.
+ const taFull = new sourceCtor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(taFull, i, i + 1);
+ }
+
+ // Orig. array: [1, 2, 3, 4]
+ // [1, 2, 3, 4] << fixedLength
+ // [3, 4] << fixedLengthWithOffset
+ // [1, 2, 3, 4, ...] << lengthTracking
+ // [3, 4, ...] << lengthTrackingWithOffset
+
+ assertEquals([1, 2, 3, 4], ToNumbers(new targetCtor(fixedLength)));
+ assertEquals([3, 4], ToNumbers(new targetCtor(fixedLengthWithOffset)));
+ assertEquals([1, 2, 3, 4], ToNumbers(new targetCtor(lengthTracking)));
+ assertEquals([3, 4], ToNumbers(new targetCtor(lengthTrackingWithOffset)));
+
+ // Grow.
+ gsab.grow(6 * sourceCtor.BYTES_PER_ELEMENT);
+
+ for (let i = 0; i < 6; ++i) {
+ WriteToTypedArray(taFull, i, i + 1);
+ }
+
+ // Orig. array: [1, 2, 3, 4, 5, 6]
+ // [1, 2, 3, 4] << fixedLength
+ // [3, 4] << fixedLengthWithOffset
+ // [1, 2, 3, 4, 5, 6, ...] << lengthTracking
+ // [3, 4, 5, 6, ...] << lengthTrackingWithOffset
+
+ assertEquals([1, 2, 3, 4], ToNumbers(new targetCtor(fixedLength)));
+ assertEquals([3, 4], ToNumbers(new targetCtor(fixedLengthWithOffset)));
+ assertEquals([1, 2, 3, 4, 5, 6],
+ ToNumbers(new targetCtor(lengthTracking)));
+ assertEquals([3, 4, 5, 6],
+ ToNumbers(new targetCtor(lengthTrackingWithOffset)));
+ });
+})();
+
+(function ConstructFromTypedArraySpeciesConstructorNotCalled() {
+ class MySharedArrayBuffer extends SharedArrayBuffer {
+ constructor(...params) {
+ super(...params);
+ }
+ static get [Symbol.species]() {
+ throw new Error('This should not be called!');
+ }
+ };
+
+ AllBigIntMatchedCtorCombinations((targetCtor, sourceCtor) => {
+ const gsab = new MySharedArrayBuffer(
+ 4 * sourceCtor.BYTES_PER_ELEMENT,
+ {maxByteLength: 8 * sourceCtor.BYTES_PER_ELEMENT});
+ // Write some data into the array.
+ const taWrite = new sourceCtor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(taWrite, i, 2 * i);
+ }
+
+ const fixedLength = new sourceCtor(gsab, 0, 4);
+ assertEquals([0, 2, 4, 6], ToNumbers(new targetCtor(fixedLength)));
+
+ const fixedLengthWithOffset = new sourceCtor(
+ gsab, 2 * sourceCtor.BYTES_PER_ELEMENT, 2);
+ assertEquals([4, 6], ToNumbers(new targetCtor(fixedLengthWithOffset)));
+
+ const lengthTracking = new sourceCtor(gsab, 0);
+ assertEquals([0, 2, 4, 6], ToNumbers(new targetCtor(lengthTracking)));
+
+ const lengthTrackingWithOffset = new sourceCtor(
+ gsab, 2 * sourceCtor.BYTES_PER_ELEMENT);
+ assertEquals([4, 6], ToNumbers(new targetCtor(lengthTrackingWithOffset)));
+ });
+})();
+
(function TypedArrayLengthWhenGrown1() {
const gsab = CreateGrowableSharedArrayBuffer(16, 40);
@@ -2213,11 +2300,6 @@ function TestIterationAndGrow(ta, expected, gsab, grow_after,
})();
(function IncludesSpecialValues() {
- const floatCtors = [
- Float32Array,
- Float64Array,
- MyFloat32Array
- ];
for (let ctor of floatCtors) {
const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
8 * ctor.BYTES_PER_ELEMENT);
@@ -2230,3 +2312,1256 @@ function TestIterationAndGrow(ta, expected, gsab, grow_after,
assertTrue(lengthTracking.includes(NaN));
}
})();
+
+(function IndexOfLastIndexOf() {
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const fixedLength = new ctor(gsab, 0, 4);
+ const fixedLengthWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT, 2);
+ const lengthTracking = new ctor(gsab, 0);
+ const lengthTrackingWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT);
+
+ // Write some data into the array.
+ const taWrite = new ctor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(taWrite, i, Math.floor(i / 2));
+ }
+
+ // Orig. array: [0, 0, 1, 1]
+ // [0, 0, 1, 1] << fixedLength
+ // [1, 1] << fixedLengthWithOffset
+ // [0, 0, 1, 1, ...] << lengthTracking
+ // [1, 1, ...] << lengthTrackingWithOffset
+
+ assertEquals(0, IndexOfHelper(fixedLength, 0));
+ assertEquals(1, IndexOfHelper(fixedLength, 0, 1));
+ assertEquals(-1, IndexOfHelper(fixedLength, 0, 2));
+ assertEquals(-1, IndexOfHelper(fixedLength, 0, -2));
+ assertEquals(1, IndexOfHelper(fixedLength, 0, -3));
+ assertEquals(2, IndexOfHelper(fixedLength, 1, 1));
+ assertEquals(2, IndexOfHelper(fixedLength, 1, -3));
+ assertEquals(2, IndexOfHelper(fixedLength, 1, -2));
+ assertEquals(-1, IndexOfHelper(fixedLength, undefined));
+
+ assertEquals(1, LastIndexOfHelper(fixedLength, 0));
+ assertEquals(1, LastIndexOfHelper(fixedLength, 0, 1));
+ assertEquals(1, LastIndexOfHelper(fixedLength, 0, 2));
+ assertEquals(1, LastIndexOfHelper(fixedLength, 0, -2));
+ assertEquals(1, LastIndexOfHelper(fixedLength, 0, -3));
+ assertEquals(-1, LastIndexOfHelper(fixedLength, 1, 1));
+ assertEquals(2, LastIndexOfHelper(fixedLength, 1, -2));
+ assertEquals(-1, LastIndexOfHelper(fixedLength, 1, -3));
+ assertEquals(-1, LastIndexOfHelper(fixedLength, undefined));
+
+ assertEquals(-1, IndexOfHelper(fixedLengthWithOffset, 0));
+ assertEquals(0, IndexOfHelper(fixedLengthWithOffset, 1));
+ assertEquals(0, IndexOfHelper(fixedLengthWithOffset, 1, -2));
+ assertEquals(1, IndexOfHelper(fixedLengthWithOffset, 1, -1));
+ assertEquals(-1, IndexOfHelper(fixedLengthWithOffset, undefined));
+
+ assertEquals(-1, LastIndexOfHelper(fixedLengthWithOffset, 0));
+ assertEquals(1, LastIndexOfHelper(fixedLengthWithOffset, 1));
+ assertEquals(0, LastIndexOfHelper(fixedLengthWithOffset, 1, -2));
+ assertEquals(1, LastIndexOfHelper(fixedLengthWithOffset, 1, -1));
+ assertEquals(-1, LastIndexOfHelper(fixedLengthWithOffset, undefined));
+
+ assertEquals(0, IndexOfHelper(lengthTracking, 0));
+ assertEquals(-1, IndexOfHelper(lengthTracking, 0, 2));
+ assertEquals(2, IndexOfHelper(lengthTracking, 1, -3));
+ assertEquals(-1, IndexOfHelper(lengthTracking, undefined));
+
+ assertEquals(1, LastIndexOfHelper(lengthTracking, 0));
+ assertEquals(1, LastIndexOfHelper(lengthTracking, 0, 2));
+ assertEquals(1, LastIndexOfHelper(lengthTracking, 0, -3));
+ assertEquals(-1, LastIndexOfHelper(lengthTracking, 1, 1));
+ assertEquals(2, LastIndexOfHelper(lengthTracking, 1, 2));
+ assertEquals(-1, LastIndexOfHelper(lengthTracking, 1, -3));
+ assertEquals(-1, LastIndexOfHelper(lengthTracking, undefined));
+
+ assertEquals(-1, IndexOfHelper(lengthTrackingWithOffset, 0));
+ assertEquals(0, IndexOfHelper(lengthTrackingWithOffset, 1));
+ assertEquals(1, IndexOfHelper(lengthTrackingWithOffset, 1, 1));
+ assertEquals(0, IndexOfHelper(lengthTrackingWithOffset, 1, -2));
+ assertEquals(-1, IndexOfHelper(lengthTrackingWithOffset, undefined));
+
+ assertEquals(-1, LastIndexOfHelper(lengthTrackingWithOffset, 0));
+ assertEquals(1, LastIndexOfHelper(lengthTrackingWithOffset, 1));
+ assertEquals(1, LastIndexOfHelper(lengthTrackingWithOffset, 1, 1));
+ assertEquals(0, LastIndexOfHelper(lengthTrackingWithOffset, 1, -2));
+ assertEquals(1, LastIndexOfHelper(lengthTrackingWithOffset, 1, -1));
+ assertEquals(-1, LastIndexOfHelper(lengthTrackingWithOffset, undefined));
+
+ // Grow.
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ for (let i = 0; i < 6; ++i) {
+ WriteToTypedArray(taWrite, i, Math.floor(i / 2));
+ }
+
+ // Orig. array: [0, 0, 1, 1, 2, 2]
+ // [0, 0, 1, 1] << fixedLength
+ // [1, 1] << fixedLengthWithOffset
+ // [0, 0, 1, 1, 2, 2, ...] << lengthTracking
+ // [1, 1, 2, 2, ...] << lengthTrackingWithOffset
+
+ assertEquals(2, IndexOfHelper(fixedLength, 1));
+ assertEquals(-1, IndexOfHelper(fixedLength, 2));
+ assertEquals(-1, IndexOfHelper(fixedLength, undefined));
+
+ assertEquals(3, LastIndexOfHelper(fixedLength, 1));
+ assertEquals(-1, LastIndexOfHelper(fixedLength, 2));
+ assertEquals(-1, LastIndexOfHelper(fixedLength, undefined));
+
+ assertEquals(-1, IndexOfHelper(fixedLengthWithOffset, 0));
+ assertEquals(0, IndexOfHelper(fixedLengthWithOffset, 1));
+ assertEquals(-1, IndexOfHelper(fixedLengthWithOffset, 2));
+ assertEquals(-1, IndexOfHelper(fixedLengthWithOffset, undefined));
+
+ assertEquals(-1, LastIndexOfHelper(fixedLengthWithOffset, 0));
+ assertEquals(1, LastIndexOfHelper(fixedLengthWithOffset, 1));
+ assertEquals(-1, LastIndexOfHelper(fixedLengthWithOffset, 2));
+ assertEquals(-1, LastIndexOfHelper(fixedLengthWithOffset, undefined));
+
+ assertEquals(2, IndexOfHelper(lengthTracking, 1));
+ assertEquals(4, IndexOfHelper(lengthTracking, 2));
+ assertEquals(-1, IndexOfHelper(lengthTracking, undefined));
+
+ assertEquals(3, LastIndexOfHelper(lengthTracking, 1));
+ assertEquals(5, LastIndexOfHelper(lengthTracking, 2));
+ assertEquals(-1, LastIndexOfHelper(lengthTracking, undefined));
+
+ assertEquals(-1, IndexOfHelper(lengthTrackingWithOffset, 0));
+ assertEquals(0, IndexOfHelper(lengthTrackingWithOffset, 1));
+ assertEquals(2, IndexOfHelper(lengthTrackingWithOffset, 2));
+ assertEquals(-1, IndexOfHelper(lengthTrackingWithOffset, undefined));
+
+ assertEquals(-1, LastIndexOfHelper(lengthTrackingWithOffset, 0));
+ assertEquals(1, LastIndexOfHelper(lengthTrackingWithOffset, 1));
+ assertEquals(3, LastIndexOfHelper(lengthTrackingWithOffset, 2));
+ assertEquals(-1, LastIndexOfHelper(lengthTrackingWithOffset, undefined));
+ }
+})();
+
+(function IndexOfParameterConversionGrows() {
+ // Growing + length-tracking TA.
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const lengthTracking = new ctor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(lengthTracking, i, 1);
+ }
+
+ let evil = { valueOf: () => {
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ return 0;
+ }};
+ assertEquals(-1, IndexOfHelper(lengthTracking, 0));
+ // The TA grew but we only look at the data until the original length.
+ assertEquals(-1, IndexOfHelper(lengthTracking, 0, evil));
+ }
+
+ // Growing + length-tracking TA, index conversion.
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const lengthTracking = new ctor(gsab);
+ WriteToTypedArray(lengthTracking, 0, 1);
+
+ let evil = { valueOf: () => {
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ return -4;
+ }};
+ assertEquals(0, IndexOfHelper(lengthTracking, 1, -4));
+ // The TA grew but the start index conversion is done based on the original
+ // length.
+ assertEquals(0, IndexOfHelper(lengthTracking, 1, evil));
+ }
+})();
+
+(function LastIndexOfParameterConversionGrows() {
+ // Growing + length-tracking TA.
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const lengthTracking = new ctor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(lengthTracking, i, 1);
+ }
+
+ let evil = { valueOf: () => {
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ return -1;
+ }};
+ assertEquals(-1, LastIndexOfHelper(lengthTracking, 0));
+ // Because lastIndexOf iterates from the given index downwards, it's not
+ // possible to test that "we only look at the data until the original
+ // length" without also testing that the index conversion happening with the
+ // original length.
+ assertEquals(-1, LastIndexOfHelper(lengthTracking, 0, evil));
+ }
+
+ // Growing + length-tracking TA, index conversion.
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const lengthTracking = new ctor(gsab);
+
+ let evil = { valueOf: () => {
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ return -4;
+ }};
+ assertEquals(0, LastIndexOfHelper(lengthTracking, 0, -4));
+ // The TA grew but the start index conversion is done based on the original
+ // length.
+ assertEquals(0, LastIndexOfHelper(lengthTracking, 0, evil));
+ }
+})();
+
+(function IndexOfLastIndexOfSpecialValues() {
+ for (let ctor of floatCtors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const lengthTracking = new ctor(gsab);
+ lengthTracking[0] = -Infinity;
+ lengthTracking[1] = -Infinity;
+ lengthTracking[2] = Infinity;
+ lengthTracking[3] = Infinity;
+ lengthTracking[4] = NaN;
+ lengthTracking[5] = NaN;
+ assertEquals(0, lengthTracking.indexOf(-Infinity));
+ assertEquals(1, lengthTracking.lastIndexOf(-Infinity));
+ assertEquals(2, lengthTracking.indexOf(Infinity));
+ assertEquals(3, lengthTracking.lastIndexOf(Infinity));
+ // NaN is never found.
+ assertEquals(-1, lengthTracking.indexOf(NaN));
+ assertEquals(-1, lengthTracking.lastIndexOf(NaN));
+ }
+})();
+
+(function JoinToLocaleString() {
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const fixedLength = new ctor(gsab, 0, 4);
+ const fixedLengthWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT, 2);
+ const lengthTracking = new ctor(gsab, 0);
+ const lengthTrackingWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT);
+
+ // Write some data into the array.
+ const taWrite = new ctor(gsab);
+ 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
+
+ assertEquals('0,2,4,6', fixedLength.join());
+ assertEquals('0,2,4,6', fixedLength.toLocaleString());
+ assertEquals('4,6', fixedLengthWithOffset.join());
+ assertEquals('4,6', fixedLengthWithOffset.toLocaleString());
+ assertEquals('0,2,4,6', lengthTracking.join());
+ assertEquals('0,2,4,6', lengthTracking.toLocaleString());
+ assertEquals('4,6', lengthTrackingWithOffset.join());
+ assertEquals('4,6', lengthTrackingWithOffset.toLocaleString());
+
+ // Grow.
+ gsab.grow(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
+
+ assertEquals('0,2,4,6', fixedLength.join());
+ assertEquals('0,2,4,6', fixedLength.toLocaleString());
+ assertEquals('4,6', fixedLengthWithOffset.join());
+ assertEquals('4,6', fixedLengthWithOffset.toLocaleString());
+ assertEquals('0,2,4,6,8,10', lengthTracking.join());
+ assertEquals('0,2,4,6,8,10', lengthTracking.toLocaleString());
+ assertEquals('4,6,8,10', lengthTrackingWithOffset.join());
+ assertEquals('4,6,8,10', lengthTrackingWithOffset.toLocaleString());
+ }
+})();
+
+(function JoinParameterConversionGrows() {
+ // Growing + fixed-length TA.
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const fixedLength = new ctor(gsab, 0, 4);
+
+ let evil = { toString: () => {
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ return '.';
+ }};
+ assertEquals('0.0.0.0', fixedLength.join(evil));
+ }
+
+ // Growing + length-tracking TA.
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const lengthTracking = new ctor(gsab);
+
+ let evil = { toString: () => {
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ return '.';
+ }};
+ // We iterate 4 elements, since it was the starting length.
+ assertEquals('0.0.0.0', lengthTracking.join(evil));
+ }
+})();
+
+(function ToLocaleStringNumberPrototypeToLocaleStringGrows() {
+ const oldNumberPrototypeToLocaleString = Number.prototype.toLocaleString;
+ const oldBigIntPrototypeToLocaleString = BigInt.prototype.toLocaleString;
+
+ // Growing + fixed-length TA.
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const fixedLength = new ctor(gsab, 0, 4);
+
+ let growAfter = 2;
+ Number.prototype.toLocaleString = function() {
+ --growAfter;
+ if (growAfter == 0) {
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ }
+ return oldNumberPrototypeToLocaleString.call(this);
+ }
+ BigInt.prototype.toLocaleString = function() {
+ --growAfter;
+ if (growAfter == 0) {
+ gsab.grow(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.
+ assertEquals('0,0,0,0', fixedLength.toLocaleString());
+ }
+
+ // Growing + length-tracking TA.
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const lengthTracking = new ctor(gsab);
+
+ let growAfter = 2;
+ Number.prototype.toLocaleString = function() {
+ --growAfter;
+ if (growAfter == 0) {
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ }
+ return oldNumberPrototypeToLocaleString.call(this);
+ }
+ BigInt.prototype.toLocaleString = function() {
+ --growAfter;
+ if (growAfter == 0) {
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ }
+ return oldBigIntPrototypeToLocaleString.call(this);
+ }
+
+ // We iterate 4 elements since it was the starting length.
+ assertEquals('0,0,0,0', lengthTracking.toLocaleString());
+ }
+
+ Number.prototype.toLocaleString = oldNumberPrototypeToLocaleString;
+ BigInt.prototype.toLocaleString = oldBigIntPrototypeToLocaleString;
+})();
+
+(function TestMap() {
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const fixedLength = new ctor(gsab, 0, 4);
+ const fixedLengthWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT, 2);
+ const lengthTracking = new ctor(gsab, 0);
+ const lengthTrackingWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT);
+
+ // Write some data into the array.
+ const taWrite = new ctor(gsab);
+ 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
+
+ function Helper(array) {
+ const values = [];
+ function GatherValues(n, ix) {
+ assertEquals(values.length, ix);
+ values.push(n);
+ if (typeof n == 'bigint') {
+ return n + 1n;
+ }
+ return n + 1;
+ }
+ const newValues = array.map(GatherValues);
+ for (let i = 0; i < values.length; ++i) {
+ if (typeof values[i] == 'bigint') {
+ assertEquals(newValues[i], values[i] + 1n);
+ } else {
+ assertEquals(newValues[i], values[i] + 1);
+ }
+ }
+ return ToNumbers(values);
+ }
+
+ assertEquals([0, 2, 4, 6], Helper(fixedLength));
+ assertEquals([4, 6], Helper(fixedLengthWithOffset));
+ assertEquals([0, 2, 4, 6], Helper(lengthTracking));
+ assertEquals([4, 6], Helper(lengthTrackingWithOffset));
+
+ // Grow.
+ gsab.grow(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
+
+ assertEquals([0, 2, 4, 6], Helper(fixedLength));
+ assertEquals([4, 6], Helper(fixedLengthWithOffset));
+ assertEquals([0, 2, 4, 6, 8, 10], Helper(lengthTracking));
+ assertEquals([4, 6, 8, 10], Helper(lengthTrackingWithOffset));
+ }
+})();
+
+(function MapGrowMidIteration() {
+ // Orig. array: [0, 2, 4, 6]
+ // [0, 2, 4, 6] << fixedLength
+ // [4, 6] << fixedLengthWithOffset
+ // [0, 2, 4, 6, ...] << lengthTracking
+ // [4, 6, ...] << lengthTrackingWithOffset
+ function CreateGsabForTest(ctor) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ // Write some data into the array.
+ const taWrite = new ctor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(taWrite, i, 2 * i);
+ }
+ return gsab;
+ }
+
+ let values;
+ let gsab;
+ let growAfter;
+ let growTo;
+ function CollectValuesAndResize(n) {
+ if (typeof n == 'bigint') {
+ values.push(Number(n));
+ } else {
+ values.push(n);
+ }
+ if (values.length == growAfter) {
+ gsab.grow(growTo);
+ }
+ return n;
+ }
+
+ function Helper(array) {
+ values = [];
+ array.map(CollectValuesAndResize);
+ return values;
+ }
+
+ for (let ctor of ctors) {
+ gsab = CreateGsabForTest(ctor);
+ const fixedLength = new ctor(gsab, 0, 4);
+ growAfter = 2;
+ growTo = 5 * ctor.BYTES_PER_ELEMENT;
+ assertEquals([0, 2, 4, 6], Helper(fixedLength));
+ }
+
+ for (let ctor of ctors) {
+ gsab = CreateGsabForTest(ctor);
+ const fixedLengthWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT, 2);
+ growAfter = 1;
+ growTo = 5 * ctor.BYTES_PER_ELEMENT;
+ assertEquals([4, 6], Helper(fixedLengthWithOffset));
+ }
+
+ for (let ctor of ctors) {
+ gsab = CreateGsabForTest(ctor);
+ const lengthTracking = new ctor(gsab, 0);
+ growAfter = 2;
+ growTo = 5 * ctor.BYTES_PER_ELEMENT;
+ assertEquals([0, 2, 4, 6], Helper(lengthTracking));
+ }
+
+ for (let ctor of ctors) {
+ gsab = CreateGsabForTest(ctor);
+ const lengthTrackingWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT);
+ growAfter = 1;
+ growTo = 5 * ctor.BYTES_PER_ELEMENT;
+ assertEquals([4, 6], Helper(lengthTrackingWithOffset));
+ }
+})();
+
+(function MapSpeciesCreateGrows() {
+ let values;
+ let gsab;
+ function CollectValues(n, ix, ta) {
+ if (typeof n == 'bigint') {
+ values.push(Number(n));
+ } else {
+ values.push(n);
+ }
+ // We still need to return a valid BigInt / non-BigInt, even if
+ // n is `undefined`.
+ if (IsBigIntTypedArray(ta)) {
+ return 0n;
+ }
+ return 0;
+ }
+
+ function Helper(array) {
+ values = [];
+ array.map(CollectValues);
+ return values;
+ }
+
+ for (let ctor of ctors) {
+ gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const taWrite = new ctor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(taWrite, i, i);
+ }
+
+ let resizeWhenConstructorCalled = false;
+ class MyArray extends ctor {
+ constructor(...params) {
+ super(...params);
+ if (resizeWhenConstructorCalled) {
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ }
+ }
+ };
+
+ const fixedLength = new MyArray(gsab, 0, 4);
+ resizeWhenConstructorCalled = true;
+ assertEquals([0, 1, 2, 3], Helper(fixedLength));
+ assertEquals(6 * ctor.BYTES_PER_ELEMENT, gsab.byteLength);
+ }
+
+ for (let ctor of ctors) {
+ gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+
+ const taWrite = new ctor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(taWrite, i, i);
+ }
+
+ let resizeWhenConstructorCalled = false;
+ class MyArray extends ctor {
+ constructor(...params) {
+ super(...params);
+ if (resizeWhenConstructorCalled) {
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ }
+ }
+ };
+
+ const lengthTracking = new MyArray(gsab);
+ resizeWhenConstructorCalled = true;
+ assertEquals([0, 1, 2, 3], Helper(lengthTracking));
+ assertEquals(6 * ctor.BYTES_PER_ELEMENT, gsab.byteLength);
+ }
+})();
+
+(function Reverse() {
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const fixedLength = new ctor(gsab, 0, 4);
+ const fixedLengthWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT, 2);
+ const lengthTracking = new ctor(gsab, 0);
+ const lengthTrackingWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT);
+
+ const wholeArrayView = new ctor(gsab);
+ function WriteData() {
+ // Write some data into the array.
+ for (let i = 0; i < wholeArrayView.length; ++i) {
+ WriteToTypedArray(wholeArrayView, i, 2 * i);
+ }
+ }
+ WriteData();
+
+ // Orig. array: [0, 2, 4, 6]
+ // [0, 2, 4, 6] << fixedLength
+ // [4, 6] << fixedLengthWithOffset
+ // [0, 2, 4, 6, ...] << lengthTracking
+ // [4, 6, ...] << lengthTrackingWithOffset
+
+ fixedLength.reverse();
+ assertEquals([6, 4, 2, 0], ToNumbers(wholeArrayView));
+ fixedLengthWithOffset.reverse();
+ assertEquals([6, 4, 0, 2], ToNumbers(wholeArrayView));
+ lengthTracking.reverse();
+ assertEquals([2, 0, 4, 6], ToNumbers(wholeArrayView));
+ lengthTrackingWithOffset.reverse();
+ assertEquals([2, 0, 6, 4], ToNumbers(wholeArrayView));
+
+ // Grow.
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ WriteData();
+
+ // 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
+
+ fixedLength.reverse();
+ assertEquals([6, 4, 2, 0, 8, 10], ToNumbers(wholeArrayView));
+ fixedLengthWithOffset.reverse();
+ assertEquals([6, 4, 0, 2, 8, 10], ToNumbers(wholeArrayView));
+ lengthTracking.reverse();
+ assertEquals([10, 8, 2, 0, 4, 6], ToNumbers(wholeArrayView));
+ lengthTrackingWithOffset.reverse();
+ assertEquals([10, 8, 6, 4, 0, 2], ToNumbers(wholeArrayView));
+ }
+})();
+
+(function SetWithGrowableTarget() {
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const fixedLength = new ctor(gsab, 0, 4);
+ const fixedLengthWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT, 2);
+ const lengthTracking = new ctor(gsab, 0);
+ const lengthTrackingWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT);
+
+ // Write some data into the array.
+ const taFull = new ctor(gsab);
+
+ // Orig. array: [0, 0, 0, 0]
+ // [0, 0, 0, 0] << fixedLength
+ // [0, 0] << fixedLengthWithOffset
+ // [0, 0, 0, 0, ...] << lengthTracking
+ // [0, 0, ...] << lengthTrackingWithOffset
+
+ SetHelper(fixedLength, [1, 2]);
+ assertEquals([1, 2, 0, 0], ToNumbers(taFull));
+ SetHelper(fixedLength, [3, 4], 1);
+ assertEquals([1, 3, 4, 0], ToNumbers(taFull));
+ assertThrows(() => { SetHelper(fixedLength, [0, 0, 0, 0, 0])}, RangeError);
+ assertThrows(() => { SetHelper(fixedLength, [0, 0, 0, 0], 1)}, RangeError);
+ assertEquals([1, 3, 4, 0], ToNumbers(taFull));
+
+ SetHelper(fixedLengthWithOffset, [5, 6]);
+ assertEquals([1, 3, 5, 6], ToNumbers(taFull));
+ SetHelper(fixedLengthWithOffset, [7], 1);
+ assertEquals([1, 3, 5, 7], ToNumbers(taFull));
+ assertThrows(() => { SetHelper(fixedLengthWithOffset, [0, 0, 0])},
+ RangeError);
+ assertThrows(() => { SetHelper(fixedLengthWithOffset, [0, 0], 1)},
+ RangeError);
+ assertEquals([1, 3, 5, 7], ToNumbers(taFull));
+
+ SetHelper(lengthTracking, [8, 9]);
+ assertEquals([8, 9, 5, 7], ToNumbers(taFull));
+ SetHelper(lengthTracking, [10, 11], 1);
+ assertEquals([8, 10, 11, 7], ToNumbers(taFull));
+ assertThrows(() => { SetHelper(lengthTracking, [0, 0, 0, 0, 0])},
+ RangeError);
+ assertThrows(() => { SetHelper(lengthTracking, [0, 0, 0, 0], 1)},
+ RangeError);
+ assertEquals([8, 10, 11, 7], ToNumbers(taFull));
+
+ SetHelper(lengthTrackingWithOffset, [12, 13]);
+ assertEquals([8, 10, 12, 13], ToNumbers(taFull));
+ SetHelper(lengthTrackingWithOffset, [14], 1);
+ assertEquals([8, 10, 12, 14], ToNumbers(taFull));
+ assertThrows(() => { SetHelper(lengthTrackingWithOffset, [0, 0, 0])},
+ RangeError);
+ assertThrows(() => { SetHelper(lengthTrackingWithOffset, [0, 0], 1)},
+ RangeError);
+ assertEquals([8, 10, 12, 14], ToNumbers(taFull));
+
+ // Grow.
+ gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+
+ // Orig. array: [8, 10, 12, 14, 0, 0]
+ // [8, 10, 12, 14] << fixedLength
+ // [12, 14] << fixedLengthWithOffset
+ // [8, 10, 12, 14, 0, 0, ...] << lengthTracking
+ // [12, 14, 0, 0, ...] << lengthTrackingWithOffset
+ SetHelper(fixedLength, [21, 22]);
+ assertEquals([21, 22, 12, 14, 0, 0], ToNumbers(taFull));
+ SetHelper(fixedLength, [23, 24], 1);
+ assertEquals([21, 23, 24, 14, 0, 0], ToNumbers(taFull));
+ assertThrows(() => { SetHelper(fixedLength, [0, 0, 0, 0, 0])}, RangeError);
+ assertThrows(() => { SetHelper(fixedLength, [0, 0, 0, 0], 1)}, RangeError);
+ assertEquals([21, 23, 24, 14, 0, 0], ToNumbers(taFull));
+
+ SetHelper(fixedLengthWithOffset, [25, 26]);
+ assertEquals([21, 23, 25, 26, 0, 0], ToNumbers(taFull));
+ SetHelper(fixedLengthWithOffset, [27], 1);
+ assertEquals([21, 23, 25, 27, 0, 0], ToNumbers(taFull));
+ assertThrows(() => { SetHelper(fixedLengthWithOffset, [0, 0, 0])},
+ RangeError);
+ assertThrows(() => { SetHelper(fixedLengthWithOffset, [0, 0], 1)},
+ RangeError);
+ assertEquals([21, 23, 25, 27, 0, 0], ToNumbers(taFull));
+
+ SetHelper(lengthTracking, [28, 29, 30, 31, 32, 33]);
+ assertEquals([28, 29, 30, 31, 32, 33], ToNumbers(taFull));
+ SetHelper(lengthTracking, [34, 35, 36, 37, 38], 1);
+ assertEquals([28, 34, 35, 36, 37, 38], ToNumbers(taFull));
+ assertThrows(() => { SetHelper(lengthTracking, [0, 0, 0, 0, 0, 0, 0])},
+ RangeError);
+ assertThrows(() => { SetHelper(lengthTracking, [0, 0, 0, 0, 0, 0], 1)},
+ RangeError);
+ assertEquals([28, 34, 35, 36, 37, 38], ToNumbers(taFull));
+
+ SetHelper(lengthTrackingWithOffset, [39, 40, 41, 42]);
+ assertEquals([28, 34, 39, 40, 41, 42], ToNumbers(taFull));
+ SetHelper(lengthTrackingWithOffset, [43, 44, 45], 1);
+ assertEquals([28, 34, 39, 43, 44, 45], ToNumbers(taFull));
+ assertThrows(() => { SetHelper(lengthTrackingWithOffset, [0, 0, 0, 0, 0])},
+ RangeError);
+ assertThrows(() => { SetHelper(lengthTrackingWithOffset, [0, 0, 0, 0], 1)},
+ RangeError);
+ assertEquals([28, 34, 39, 43, 44, 45], ToNumbers(taFull));
+ }
+})();
+
+(function SetSourceLengthGetterGrowsTarget() {
+ // Orig. array: [0, 2, 4, 6]
+ // [0, 2, 4, 6] << fixedLength
+ // [4, 6] << fixedLengthWithOffset
+ // [0, 2, 4, 6, ...] << lengthTracking
+ // [4, 6, ...] << lengthTrackingWithOffset
+ function CreateGsabForTest(ctor) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ // Write some data into the array.
+ const taWrite = new ctor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(taWrite, i, 2 * i);
+ }
+ return gsab;
+ }
+
+ let gsab;
+ let growTo;
+ function CreateSourceProxy(length) {
+ return new Proxy({}, {
+ get(target, prop, receiver) {
+ if (prop == 'length') {
+ gsab.grow(growTo);
+ return length;
+ }
+ return true; // Can be converted to both BigInt and Number.
+ }
+ });
+ }
+
+ // Test that we still throw for lengthTracking TAs if the source length is
+ // too large, even though we resized in the length getter (we check against
+ // the original length).
+ for (let ctor of ctors) {
+ gsab = CreateGsabForTest(ctor);
+ const lengthTracking = new ctor(gsab, 0);
+ growTo = 6 * ctor.BYTES_PER_ELEMENT;
+ assertThrows(() => { lengthTracking.set(CreateSourceProxy(6)); },
+ RangeError);
+ assertEquals([0, 2, 4, 6, 0, 0], ToNumbers(new ctor(gsab)));
+ }
+
+ for (let ctor of ctors) {
+ gsab = CreateGsabForTest(ctor);
+ const lengthTrackingWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT);
+ growTo = 6 * ctor.BYTES_PER_ELEMENT;
+ assertThrows(() => { lengthTrackingWithOffset.set(CreateSourceProxy(6)); },
+ RangeError);
+ assertEquals([0, 2, 4, 6, 0, 0], ToNumbers(new ctor(gsab)));
+ }
+})();
+
+(function SetGrowTargetMidIteration() {
+ // Orig. array: [0, 2, 4, 6]
+ // [0, 2, 4, 6] << fixedLength
+ // [4, 6] << fixedLengthWithOffset
+ // [0, 2, 4, 6, ...] << lengthTracking
+ // [4, 6, ...] << lengthTrackingWithOffset
+ function CreateGsabForTest(ctor) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ // Write some data into the array.
+ const taWrite = new ctor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(taWrite, i, 2 * i);
+ }
+ return gsab;
+ }
+
+ let gsab;
+ // Growing will happen when we're calling Get for the `growAt`:th data
+ // element, but we haven't yet written it to the target.
+ let growAt;
+ let growTo;
+ function CreateSourceProxy(length) {
+ let requestedIndices = [];
+ return new Proxy({}, {
+ get(target, prop, receiver) {
+ if (prop == 'length') {
+ return length;
+ }
+ requestedIndices.push(prop);
+ if (requestedIndices.length == growAt) {
+ gsab.grow(growTo);
+ }
+ return true; // Can be converted to both BigInt and Number.
+ }
+ });
+ }
+
+ for (let ctor of ctors) {
+ gsab = CreateGsabForTest(ctor);
+ const fixedLength = new ctor(gsab, 0, 4);
+ growAt = 2;
+ growTo = 6 * ctor.BYTES_PER_ELEMENT;
+ fixedLength.set(CreateSourceProxy(4));
+ assertEquals([1, 1, 1, 1], ToNumbers(fixedLength));
+ assertEquals([1, 1, 1, 1, 0, 0], ToNumbers(new ctor(gsab)));
+ }
+
+ for (let ctor of ctors) {
+ gsab = CreateGsabForTest(ctor);
+ const fixedLengthWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT, 2);
+ growAt = 1;
+ growTo = 6 * ctor.BYTES_PER_ELEMENT;
+ fixedLengthWithOffset.set(CreateSourceProxy(2));
+ assertEquals([1, 1], ToNumbers(fixedLengthWithOffset));
+ assertEquals([0, 2, 1, 1, 0, 0], ToNumbers(new ctor(gsab)));
+ }
+
+ for (let ctor of ctors) {
+ gsab = CreateGsabForTest(ctor);
+ const lengthTracking = new ctor(gsab, 0);
+ growAt = 2;
+ growTo = 6 * ctor.BYTES_PER_ELEMENT;
+ lengthTracking.set(CreateSourceProxy(2));
+ assertEquals([1, 1, 4, 6, 0, 0], ToNumbers(lengthTracking));
+ assertEquals([1, 1, 4, 6, 0, 0], ToNumbers(new ctor(gsab)));
+ }
+
+ for (let ctor of ctors) {
+ gsab = CreateGsabForTest(ctor);
+ const lengthTrackingWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT);
+ growAt = 1;
+ growTo = 6 * ctor.BYTES_PER_ELEMENT;
+ lengthTrackingWithOffset.set(CreateSourceProxy(2));
+ assertEquals([1, 1, 0, 0], ToNumbers(lengthTrackingWithOffset));
+ assertEquals([0, 2, 1, 1, 0, 0], ToNumbers(new ctor(gsab)));
+ }
+})();
+
+(function SetWithGrowableSource() {
+ for (let targetIsGrowable of [false, true]) {
+ for (let targetCtor of ctors) {
+ for (let sourceCtor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(
+ 4 * sourceCtor.BYTES_PER_ELEMENT,
+ 8 * sourceCtor.BYTES_PER_ELEMENT);
+ const fixedLength = new sourceCtor(gsab, 0, 4);
+ const fixedLengthWithOffset = new sourceCtor(
+ gsab, 2 * sourceCtor.BYTES_PER_ELEMENT, 2);
+ const lengthTracking = new sourceCtor(gsab, 0);
+ const lengthTrackingWithOffset = new sourceCtor(
+ gsab, 2 * sourceCtor.BYTES_PER_ELEMENT);
+
+ // Write some data into the array.
+ const taFull = new sourceCtor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(taFull, i, i + 1);
+ }
+
+ // Orig. array: [1, 2, 3, 4]
+ // [1, 2, 3, 4] << fixedLength
+ // [3, 4] << fixedLengthWithOffset
+ // [1, 2, 3, 4, ...] << lengthTracking
+ // [3, 4, ...] << lengthTrackingWithOffset
+
+ const targetAb = targetIsGrowable ?
+ new ArrayBuffer(6 * targetCtor.BYTES_PER_ELEMENT) :
+ new ArrayBuffer(6 * targetCtor.BYTES_PER_ELEMENT,
+ {maxByteLength: 8 * targetCtor.BYTES_PER_ELEMENT});
+ const target = new targetCtor(targetAb);
+
+ if (IsBigIntTypedArray(target) != IsBigIntTypedArray(taFull)) {
+ // Can't mix BigInt and non-BigInt types.
+ continue;
+ }
+
+ SetHelper(target, fixedLength);
+ assertEquals([1, 2, 3, 4, 0, 0], ToNumbers(target));
+
+ SetHelper(target, fixedLengthWithOffset);
+ assertEquals([3, 4, 3, 4, 0, 0], ToNumbers(target));
+
+ SetHelper(target, lengthTracking, 1);
+ assertEquals([3, 1, 2, 3, 4, 0], ToNumbers(target));
+
+ SetHelper(target, lengthTrackingWithOffset, 1);
+ assertEquals([3, 3, 4, 3, 4, 0], ToNumbers(target));
+
+ // Grow.
+ gsab.grow(6 * sourceCtor.BYTES_PER_ELEMENT);
+
+ for (let i = 0; i < 6; ++i) {
+ WriteToTypedArray(taFull, i, i + 1);
+ }
+
+ // Orig. array: [1, 2, 3, 4, 5, 6]
+ // [1, 2, 3, 4] << fixedLength
+ // [3, 4] << fixedLengthWithOffset
+ // [1, 2, 3, 4, 5, 6, ...] << lengthTracking
+ // [3, 4, 5, 6, ...] << lengthTrackingWithOffset
+
+ SetHelper(target, fixedLength);
+ assertEquals([1, 2, 3, 4, 4, 0], ToNumbers(target));
+
+ SetHelper(target, fixedLengthWithOffset);
+ assertEquals([3, 4, 3, 4, 4, 0], ToNumbers(target));
+
+ SetHelper(target, lengthTracking, 0);
+ assertEquals([1, 2, 3, 4, 5, 6], ToNumbers(target));
+
+ SetHelper(target, lengthTrackingWithOffset, 1);
+ assertEquals([1, 3, 4, 5, 6, 6], ToNumbers(target));
+ }
+ }
+ }
+})();
+
+(function Subarray() {
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const fixedLength = new ctor(gsab, 0, 4);
+ const fixedLengthWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT, 2);
+ const lengthTracking = new ctor(gsab, 0);
+ const lengthTrackingWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT);
+
+ // Write some data into the array.
+ const taWrite = new ctor(gsab);
+ 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
+
+ const fixedLengthSubFull = fixedLength.subarray(0);
+ assertEquals([0, 2, 4, 6], ToNumbers(fixedLengthSubFull));
+ const fixedLengthWithOffsetSubFull = fixedLengthWithOffset.subarray(0);
+ assertEquals([4, 6], ToNumbers(fixedLengthWithOffsetSubFull));
+ const lengthTrackingSubFull = lengthTracking.subarray(0);
+ assertEquals([0, 2, 4, 6], ToNumbers(lengthTrackingSubFull));
+ const lengthTrackingWithOffsetSubFull =
+ lengthTrackingWithOffset.subarray(0);
+ assertEquals([4, 6], ToNumbers(lengthTrackingWithOffsetSubFull));
+
+ // Relative offsets
+ assertEquals([4, 6], ToNumbers(fixedLength.subarray(-2)));
+ assertEquals([6], ToNumbers(fixedLengthWithOffset.subarray(-1)));
+ assertEquals([4, 6], ToNumbers(lengthTracking.subarray(-2)));
+ assertEquals([6], ToNumbers(lengthTrackingWithOffset.subarray(-1)));
+
+ // Grow.
+ gsab.grow(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
+
+ assertEquals([0, 2, 4, 6], ToNumbers(fixedLength.subarray(0)));
+ assertEquals([4, 6], ToNumbers(fixedLengthWithOffset.subarray(0)));
+ assertEquals([0, 2, 4, 6, 8, 10], ToNumbers(lengthTracking.subarray(0)));
+ assertEquals([4, 6, 8, 10],
+ ToNumbers(lengthTrackingWithOffset.subarray(0)));
+
+ assertEquals(4, fixedLengthSubFull.length);
+ assertEquals(2, fixedLengthWithOffsetSubFull.length);
+
+ // TODO(v8:11111): Are subarrays of length-tracking TAs also
+ // length-tracking? See
+ // https://github.com/tc39/proposal-resizablearraybuffer/issues/91
+ assertEquals(4, lengthTrackingSubFull.length);
+ assertEquals(2, lengthTrackingWithOffsetSubFull.length);
+ }
+})();
+
+(function SubarrayParameterConversionGrows() {
+ // Orig. array: [0, 2, 4, 6]
+ // [0, 2, 4, 6] << fixedLength
+ // [0, 2, 4, 6, ...] << lengthTracking
+ function CreateGsabForTest(ctor) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ // Write some data into the array.
+ const taWrite = new ctor(gsab);
+ for (let i = 0; i < 4; ++i) {
+ WriteToTypedArray(taWrite, i, 2 * i);
+ }
+ return gsab;
+ }
+
+ // Growing + fixed-length TA. Growing won't affect anything.
+ for (let ctor of ctors) {
+ const gsab = CreateGsabForTest(ctor);
+ const fixedLength = new ctor(gsab, 0, 4);
+
+ const evil = { valueOf: () => { gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ return 0;}};
+ assertEquals([0, 2, 4, 6], ToNumbers(fixedLength.subarray(evil)));
+ }
+
+ // Growing + length-tracking TA. The length computation is done with the
+ // original length.
+ for (let ctor of ctors) {
+ const gsab = CreateGsabForTest(ctor);
+ const lengthTracking = new ctor(gsab, 0);
+
+ const evil = { valueOf: () => { gsab.grow(6 * ctor.BYTES_PER_ELEMENT);
+ return 0;}};
+
+ assertEquals([0, 2, 4, 6], ToNumbers(lengthTracking.subarray(evil)));
+ }
+})();
+
+(function SortWithDefaultComparison() {
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const fixedLength = new ctor(gsab, 0, 4);
+ const fixedLengthWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT, 2);
+ const lengthTracking = new ctor(gsab, 0);
+ const lengthTrackingWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT);
+
+ const taFull = new ctor(gsab, 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();
+ assertEquals([4, 6, 8, 10], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ fixedLengthWithOffset.sort();
+ assertEquals([10, 8, 4, 6], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ lengthTracking.sort();
+ assertEquals([4, 6, 8, 10], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ lengthTrackingWithOffset.sort();
+ assertEquals([10, 8, 4, 6], ToNumbers(taFull));
+
+ // Grow.
+ gsab.grow(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();
+ assertEquals([4, 6, 8, 10, 2, 0], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ fixedLengthWithOffset.sort();
+ assertEquals([10, 8, 4, 6, 2, 0], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ lengthTracking.sort();
+ assertEquals([0, 2, 4, 6, 8, 10], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ lengthTrackingWithOffset.sort();
+ assertEquals([10, 8, 0, 2, 4, 6], ToNumbers(taFull));
+ }
+})();
+
+(function SortWithCustomComparison() {
+ for (let ctor of ctors) {
+ const gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ const fixedLength = new ctor(gsab, 0, 4);
+ const fixedLengthWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT, 2);
+ const lengthTracking = new ctor(gsab, 0);
+ const lengthTrackingWithOffset = new ctor(gsab, 2 * ctor.BYTES_PER_ELEMENT);
+
+ const taFull = new ctor(gsab, 0);
+ function WriteUnsortedData() {
+ // Write some data into the array.
+ for (let i = 0; i < taFull.length; ++i) {
+ WriteToTypedArray(taFull, i, 10 - i);
+ }
+ }
+ function CustomComparison(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(CustomComparison);
+ assertEquals([7, 9, 8, 10], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ fixedLengthWithOffset.sort(CustomComparison);
+ assertEquals([10, 9, 7, 8], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ lengthTracking.sort(CustomComparison);
+ assertEquals([7, 9, 8, 10], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ lengthTrackingWithOffset.sort(CustomComparison);
+ assertEquals([10, 9, 7, 8], ToNumbers(taFull));
+
+ // Grow.
+ gsab.grow(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(CustomComparison);
+ assertEquals([7, 9, 8, 10, 6, 5], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ fixedLengthWithOffset.sort(CustomComparison);
+ assertEquals([10, 9, 7, 8, 6, 5], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ lengthTracking.sort(CustomComparison);
+ assertEquals([5, 7, 9, 6, 8, 10], ToNumbers(taFull));
+
+ WriteUnsortedData();
+ lengthTrackingWithOffset.sort(CustomComparison);
+ assertEquals([10, 9, 5, 7, 6, 8], ToNumbers(taFull));
+ }
+})();
+
+(function SortCallbackGrows() {
+ function WriteUnsortedData(taFull) {
+ for (let i = 0; i < taFull.length; ++i) {
+ WriteToTypedArray(taFull, i, 10 - i);
+ }
+ }
+
+ let gsab;
+ let growTo;
+ function CustomComparison(a, b) {
+ gsab.grow(growTo);
+ if (a < b) {
+ return -1;
+ }
+ if (a > b) {
+ return 1;
+ }
+ return 0;
+ }
+
+ // Fixed length TA.
+ for (let ctor of ctors) {
+ gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ growTo = 6 * ctor.BYTES_PER_ELEMENT;
+ const fixedLength = new ctor(gsab, 0, 4);
+ const taFull = new ctor(gsab, 0);
+ WriteUnsortedData(taFull);
+
+ fixedLength.sort(CustomComparison);
+
+ // Growing doesn't affect the sorting.
+ assertEquals([7, 8, 9, 10, 0, 0], ToNumbers(taFull));
+ }
+
+ // Length-tracking TA.
+ for (let ctor of ctors) {
+ gsab = CreateGrowableSharedArrayBuffer(4 * ctor.BYTES_PER_ELEMENT,
+ 8 * ctor.BYTES_PER_ELEMENT);
+ growTo = 6 * ctor.BYTES_PER_ELEMENT;
+ const lengthTracking = new ctor(gsab, 0);
+ const taFull = new ctor(gsab, 0);
+ WriteUnsortedData(taFull);
+
+ lengthTracking.sort(CustomComparison);
+
+ // Growing doesn't affect the sorting. Only the elements that were part of
+ // the original TA are sorted.
+ assertEquals([7, 8, 9, 10, 0, 0], ToNumbers(taFull));
+ }
+})();