blob: 7cd08b12588af62b92d3eba8b59c20104ac6fda6 [file] [log] [blame]
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var typedArrayConstructors = [
Uint8Array,
Int8Array,
Uint16Array,
Int16Array,
Uint32Array,
Int32Array,
Uint8ClampedArray,
Float32Array,
Float64Array
];
function assertArrayLikeEquals(value, expected, type) {
assertEquals(value.__proto__, type.prototype);
// Don't test value.length because we mess with that;
// instead in certain callsites we check that length
// is set appropriately.
for (var i = 0; i < expected.length; ++i) {
// Use Object.is to differentiate between +-0
assertSame(expected[i], value[i]);
}
}
for (var constructor of typedArrayConstructors) {
// Test default numerical sorting order
var a = new constructor([100, 7, 45])
assertEquals(a.sort(), a);
assertArrayLikeEquals(a, [7, 45, 100], constructor);
assertEquals(a.length, 3);
// For arrays of floats, certain handling of +-0/NaN
if (constructor === Float32Array || constructor === Float64Array) {
var b = new constructor([+0, -0, NaN, -0, NaN, +0])
b.sort();
assertArrayLikeEquals(b, [-0, -0, +0, +0, NaN, NaN], constructor);
assertEquals(b.length, 6);
}
// Custom sort--backwards
a.sort(function(x, y) { return y - x; });
assertArrayLikeEquals(a, [100, 45, 7], constructor);
// Basic TypedArray method properties:
// Length field is ignored
Object.defineProperty(a, 'length', {value: 1});
assertEquals(a.sort(), a);
assertArrayLikeEquals(a, [7, 45, 100], constructor);
assertEquals(a.length, 1);
// Method doesn't work on other objects
assertThrows(function() { a.sort.call([]); }, TypeError);
// Do not touch elements out of byte offset
var buf = new ArrayBuffer(constructor.BYTES_PER_ELEMENT * 3);
var a = new constructor(buf, constructor.BYTES_PER_ELEMENT);
var b = new constructor(buf);
b[0] = 3; b[1] = 2; b[2] = 1;
a.sort();
assertArrayLikeEquals(a, [1, 2], constructor);
// Detached Operation
var array = new constructor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
%ArrayBufferDetach(array.buffer);
assertThrows(() => array.sort(), TypeError);
}
// Check that TypedArray.p.sort is stable.
for (let constructor of typedArrayConstructors) {
// Sort an array [0..kSize-1] modulo 4. If the sort is stable, the array
// will be partitioned into 4 parts, where each part has only increasing
// elements.
const kSize = 128;
const kModulo = 4;
const kRunSize = kSize / kModulo;
const template = Array.from({ length: kSize }, (_, i) => i);
const array = new constructor(template);
const compare = (a, b) => (b % kModulo) - (a % kModulo);
array.sort(compare);
function assertIncreasing(from) {
for (let i = from + 1; i < from + kRunSize; ++i) {
assertTrue(array[i - 1] < array[i]);
assertEquals(array[i - 1] % kModulo, array[i] % kModulo);
}
}
for (let i = 0; i < kModulo; ++i) assertIncreasing(i * kRunSize);
}
// The following creates a test for each typed element kind, where the array
// to sort consists of some max/min/zero elements.
//
// When providing a custom compare function, the torque version of
// TypedArray.p.sort needs to convert array elements to "Number"/"BigInt"
// and back. The following test checks the edge cases for that conversion.
let constructorsWithArrays = [
{ctor: Uint8Array, array: [255, 254, 4, 3, 2, 1, 0]},
{ctor: Int8Array, array: [127, 126, 1, 0, -1, -127, -128]},
{ctor: Uint16Array, array: [2 ** 16 - 1, 2 ** 16 - 2, 4, 3, 2, 1, 0]},
{
ctor: Int16Array,
array: [2 ** 15 - 1, 2 ** 15 - 2, 1, 0, -1, -(2 ** 15 - 1), -(2 ** 15)]
},
{ctor: Uint32Array, array: [2 ** 32 - 1, 2 ** 32 - 2, 4, 3, 2, 1, 0]},
{
ctor: Int32Array,
array: [2 ** 31 - 1, 2 ** 31 - 2, 1, 0, -1, -(2 ** 31 - 1), -(2 ** 31)]
},
{
ctor: Float32Array,
array: [2 ** 24, 2 ** 24 - 1, 1, 0,-1, -(2 ** 24 - 1), -(2 ** 24)]
},
{
ctor: Float64Array,
array: [2 ** 53, 2 ** 53 - 1, 1, 0, -1, -(2 ** 53 - 1), -(2 ** 53)]
},
{ctor: Uint8ClampedArray, array: [255, 254, 4, 3, 2, 1, 0]},
{
ctor: BigUint64Array,
array: [2n ** 64n - 1n, 2n ** 64n - 2n, 4n, 3n, 2n, 1n, 0n]
},
{
ctor: BigInt64Array,
array: [2n ** 63n - 1n, 2n ** 63n - 2n, 1n, 0n,
-1n, -(2n ** 63n - 1n), -(2n ** 63n)]
}
];
// Compare function needs to return a Number in all cases, and not a BigInt.
// Hence we can not simply return "a - b".
function cmpfn(a, b) {
if (a < b) return -1;
if (b < a) return 1;
return 0;
}
for (let constructor of constructorsWithArrays) {
let array = new constructor.ctor(constructor.array);
assertEquals(array.sort(cmpfn), array);
assertArrayLikeEquals(array, constructor.array.reverse(), constructor.ctor);
assertEquals(array.length, constructor.array.length);
}