import { Array } from "array"; import { COMPARATOR } from "util/sort"; // Obtains the internal capacity of an array from its backing buffer. function internalCapacity(array: Array): i32 { // the memory region used by the backing buffer might still be larger in that the ArrayBuffer // pre-allocates a power of 2 sized buffer itself and reuses it as long as it isn't exceeded. var buffer: ArrayBuffer = array.data; return buffer.byteLength >> alignof(); } // Checks if two arrays are equal function isArraysEqual(a: Array, b: Array, len: i32 = 0): bool { if (!len) { len = a.length; if (len != b.length) return false; if (a === b) return true; } for (let i = 0; i < len; i++) { if (isFloat()) { if (isNaN(a[i]) == isNaN(b[i])) continue; } if (a[i] != b[i]) return false; } return true; } var arr = new Array(); // Array.isArray /////////////////////////////////////////////////////////////////////////////////// class P {} { assert(Array.isArray(null) == false); assert(Array.isArray(arr) == true); assert(Array.isArray(new P()) == false); assert(Array.isArray(new Uint8Array(1)) == false); assert(Array.isArray(1) == false); assert(Array.isArray("abc") == false); } // Array#fill ////////////////////////////////////////////////////////////////////////////////////// { let arr8: u8[] = [1, 2, 3, 4, 5]; arr8.fill(1, 1, 3); assert(isArraysEqual(arr8, [1, 1, 1, 4, 5])); arr8.fill(0); assert(isArraysEqual(arr8, [0, 0, 0, 0, 0])); arr8.fill(1, 0, -3); assert(isArraysEqual(arr8, [1, 1, 0, 0, 0])); arr8.fill(2, -2); assert(isArraysEqual(arr8, [1, 1, 0, 2, 2])); arr8.fill(0, 1, 0); assert(isArraysEqual(arr8, [1, 1, 0, 2, 2])); } { let arr32: u32[] = [1, 2, 3, 4, 5]; arr32.fill(1, 1, 3); assert(isArraysEqual(arr32, [1, 1, 1, 4, 5])); arr32.fill(0); assert(isArraysEqual(arr32, [0, 0, 0, 0, 0])); arr32.fill(1, 0, -3); assert(isArraysEqual(arr32, [1, 1, 0, 0, 0])); arr32.fill(2, -2); assert(isArraysEqual(arr32, [1, 1, 0, 2, 2])); arr32.fill(0, 1, 0); assert(isArraysEqual(arr32, [1, 1, 0, 2, 2])); } // Array#push/pop ////////////////////////////////////////////////////////////////////////////////// { assert(arr.length == 0); assert(internalCapacity(arr) == 0); arr.push(42); assert(arr[0] == 42); assert(arr.length == 1); assert(internalCapacity(arr) == 1); let i = arr.pop(); assert(i == 42); assert(arr.length == 0); assert(internalCapacity(arr) == 1); arr.push(43); assert(arr.length == 1); assert(internalCapacity(arr) == 1); assert(arr[0] == 43); arr.push(44); assert(arr.length == 2); assert(internalCapacity(arr) == 2); assert(arr[0] == 43); assert(arr[1] == 44); arr.push(45); assert(arr.length == 3); assert(internalCapacity(arr) == 3); assert(arr[0] == 43); assert(arr[1] == 44); assert(arr[2] == 45); } // Array#concat /////////////////////////////////////////////////////////////////////////////////// { let other = new Array(); let out = arr.concat(other); assert(internalCapacity(arr) == 3); assert(arr.length == 3); assert(out.length == 3); out.concat([]); assert(internalCapacity(arr) == 3); assert(out[0] == 43); assert(out[1] == 44); assert(out[2] == 45); other.push(46); other.push(47); out = arr.concat(other); assert(internalCapacity(arr) == 3); assert(other.length == 2); assert(out.length == 5); assert(out[0] == 43); assert(out[1] == 44); assert(out[2] == 45); assert(out[3] == 46); assert(out[4] == 47); out.pop(); assert(out.length == 4); out = arr.concat(null); assert(out.length == 3); assert(out[2] == 45); let source: i32[] = []; assert(source.length == 0); out = source.concat(arr); assert(out.length == 3); assert(source.length == 0); } // Array#copyWithin //////////////////////////////////////////////////////////////////////////////// { let cwArr: i32[]; cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(0, 3), [4, 5, 3, 4, 5])); cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(1, 3), [1, 4, 5, 4, 5])); cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(1, 2), [1, 3, 4, 5, 5])); cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(2, 2), [1, 2, 3, 4, 5])); cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(0, 3, 4), [4, 2, 3, 4, 5])); cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(1, 3, 4), [1, 4, 3, 4, 5])); cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(1, 2, 4), [1, 3, 4, 4, 5])); cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(0, -2), [4, 5, 3, 4, 5])); cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(0, -2, -1), [4, 2, 3, 4, 5])); cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(-4, -3, -2), [1, 3, 3, 4, 5])); cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(-4, -3, -1), [1, 3, 4, 4, 5])); cwArr = [1, 2, 3, 4, 5]; assert(isArraysEqual(cwArr.copyWithin(-4, -3), [1, 3, 4, 5, 5])); } // Array#unshift /////////////////////////////////////////////////////////////////////////////////// { arr.unshift(42); assert(arr.length == 4); assert(internalCapacity(arr) == 4); assert(arr[0] == 42); assert(arr[1] == 43); assert(arr[2] == 44); assert(arr[3] == 45); arr.unshift(41); assert(arr.length == 5); assert(internalCapacity(arr) == 5); assert(arr[0] == 41); assert(arr[1] == 42); assert(arr[2] == 43); assert(arr[3] == 44); assert(arr[4] == 45); } // Array#shift ///////////////////////////////////////////////////////////////////////////////////// var i: i32; { i = arr.shift(); assert(i == 41); assert(arr.length == 4); assert(internalCapacity(arr) == 5); assert(arr[0] == 42); assert(arr[1] == 43); assert(arr[2] == 44); assert(arr[3] == 45); i = arr.pop(); assert(i == 45); assert(arr.length == 3); assert(internalCapacity(arr) == 5); assert(arr[0] == 42); assert(arr[1] == 43); assert(arr[2] == 44); } // Array#reverse /////////////////////////////////////////////////////////////////////////////////// { arr.reverse(); assert(arr.length == 3); assert(internalCapacity(arr) == 5); assert(arr[0] == 44); assert(arr[1] == 43); assert(arr[2] == 42); arr.push(43); arr.push(44); } // Array#indexOf /////////////////////////////////////////////////////////////////////////////////// { i = arr.indexOf(44); assert(i == 0); i = arr.indexOf(42); assert(i == 2); i = arr.indexOf(45); assert(i == - 1); i = arr.indexOf(43, 100); assert(i == - 1); i = arr.indexOf(43, -100); assert(i == 1); i = arr.indexOf(43, -2); assert(i == 3); i = arr.indexOf(43, -4); assert(i == 1); i = arr.indexOf(43, 0); assert(i == 1); i = arr.indexOf(43, 1); assert(i == 1); i = arr.indexOf(43, 2); assert(i == 3); } // Array#includes ////////////////////////////////////////////////////////////////////////////////// { let includes = arr.includes(44); assert(includes == true); includes = arr.includes(42); assert(includes == true); includes = arr.includes(45); assert(includes == false); includes = arr.includes(43, 100); assert(includes == false); includes = arr.includes(43, -100); assert(includes == true); includes = arr.includes(43, -2); assert(includes == true); includes = arr.includes(43, -4); assert(includes == true); includes = arr.includes(43, 0); assert(includes == true); includes = arr.includes(43, 1); assert(includes == true); includes = arr.includes(43, 2); assert(includes == true); arr.splice(1, 1); assert(arr.length == 4); assert(internalCapacity(arr) == 5); assert(arr[0] == 44); assert(arr[1] == 42); } // Array#splice //////////////////////////////////////////////////////////////////////////////////// { let sarr: i32[] = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(0), [1, 2, 3, 4, 5])); assert(isArraysEqual(sarr, [])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(2), [3, 4, 5])); assert(isArraysEqual(sarr, [1, 2])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(2, 2), [3, 4])); assert(isArraysEqual(sarr, [1, 2, 5])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(0, 1), [1])); assert(isArraysEqual(sarr, [2, 3, 4, 5])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(-1), [5])); assert(isArraysEqual(sarr, [1, 2, 3, 4])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(-2), [4, 5])); assert(isArraysEqual(sarr, [1, 2, 3])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(-2, 1), [4])); assert(isArraysEqual(sarr, [1, 2, 3, 5])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(-7, 1), [1])); assert(isArraysEqual(sarr, [2, 3, 4, 5])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(-2, -1), [])); assert(isArraysEqual(sarr, [1, 2, 3, 4, 5])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(1, -2), [])); assert(isArraysEqual(sarr, [1, 2, 3, 4, 5])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(4, 0), [])); assert(isArraysEqual(sarr, [1, 2, 3, 4, 5])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(7, 0), [])); assert(isArraysEqual(sarr, [1, 2, 3, 4, 5])); sarr = [1, 2, 3, 4, 5]; assert(isArraysEqual(sarr.splice(7, 5), [])); assert(isArraysEqual(sarr, [1, 2, 3, 4, 5])); } // Array#findIndex ///////////////////////////////////////////////////////////////////////////////// { arr[0] = 0; arr[1] = 1; arr[2] = 2; arr[3] = 3; i = arr.findIndex((value: i32, index: i32, array: Array): bool => value == 0); assert(i == 0); i = arr.findIndex((value: i32, index: i32, array: Array): bool => value == 1); assert(i == 1); i = arr.findIndex((value: i32, index: i32, array: Array): bool => value == 100); assert(i == -1); // Test side effect push i = arr.findIndex((value: i32, index: i32, array: Array): bool => { array.push(100); // push side effect should not affect this method by spec return value == 100; }); // array should be changed, but this method result should be calculated for old array length assert(i == -1); assert(arr.length == 8); i = arr.findIndex((value: i32, index: i32, array: Array): bool => value == 100); assert(i != -1); arr.pop(); arr.pop(); arr.pop(); arr.pop(); // Test side effect pop i = arr.findIndex((value: i32, index: i32, array: Array): bool => { array.pop(); // popped items shouldn't be looked up, and we shouldn't go out of bounds return value == 100; }); // only 2 first items was looked up, since last 2 was removed by .pop() assert(i == -1); assert(arr.length == 2); arr.push(2); arr.push(3); } // Array#every ///////////////////////////////////////////////////////////////////////////////////// { let every = arr.every((value: i32, index: i32, array: Array): bool => value >= 0); assert(every == true); every = arr.every((value: i32, index: i32, array: Array): bool => value <= 0); assert(every == false); // Test side effect push every = arr.every((value: i32, index: i32, array: Array): bool => { array.push(100); // push side effect should not affect this method by spec return value < 10; }); // array should be changed, but this method result should be calculated for old array length assert(every == true); assert(arr.length == 8); every = arr.every((value: i32, index: i32, array: Array): bool => value < 10); assert(every == false); arr.pop(); arr.pop(); arr.pop(); arr.pop(); // Test side effect pop every = arr.every((value: i32, index: i32, array: Array): bool => { array.pop(); //poped items shouldn't be looked up, and we shouldn't go out of bounds return value < 3; }); // only 2 first items was looked up, since last 2 was removed by .pop() assert(every == true); assert(arr.length == 2); arr.push(2); arr.push(3); } // Array#some ////////////////////////////////////////////////////////////////////////////////////// { let some = arr.some((value: i32, index: i32, array: Array): bool => value >= 3); assert(some == true); some = arr.some((value: i32, index: i32, array: Array): bool => value <= -1); assert(some == false); // Test side effect push some = arr.some((value: i32, index: i32, array: Array): bool => { array.push(100); // push side effect should not affect this method by spec return value > 10; }); // array should be changed, but this method result should be calculated for old array length assert(some == false); assert(arr.length == 8); some = arr.some((value: i32, index: i32, array: Array): bool => value > 10); assert(some == true); arr.pop(); arr.pop(); arr.pop(); arr.pop(); // Test side effect pop some = arr.some((value: i32, index: i32, array: Array): bool => { array.pop(); // poped items shouldn't be looked up, and we shouldn't go out of bounds return value > 3; }); // only 2 first items was looked up, since last 2 was removed by .pop() assert(some == false); assert(arr.length == 2); arr.push(2); arr.push(3); } // Array#forEach /////////////////////////////////////////////////////////////////////////////////// { i = 0; arr.forEach((value: i32, index: i32, array: Array): void => { i += value; }); assert(i == 6); // Test side effect push i = 0; arr.forEach((value: i32, index: i32, array: Array): void => { array.push(100); //push side effect should not affect this method by spec i += value; }); // array should be changed, but this method result should be calculated for old array length assert(i == 6); assert(arr.length == 8); i = 0; arr.forEach((value: i32, index: i32, array: Array): void => { i += value; }); assert(i == 406); arr.pop(); arr.pop(); arr.pop(); arr.pop(); // Test side effect pop i = 0; arr.forEach((value: i32, index: i32, array: Array): void => { array.pop(); //poped items shouldn't be looked up, and we shouldn't go out of bounds i += value; }); // only 2 first items was looked up, since last 2 was removed by .pop() assert(i == 1); assert(arr.length == 2); arr.push(2); arr.push(3); // Test rehash action effec arr.forEach((value: i32, index: i32, array: Array): void => { if (index == 0) { for (let i = 0; i < 4; i++) { array.pop(); } for (let i = 0; i < 100; i++) { array.push(100 + i); } for (let i = 0; i < 100; i++) { array.pop(); } for (let i = 0; i < 100; i++) { array.push(i + 200); } } if (index == 2) { assert(value == 202); } }); assert(arr.length == 100); for (let i = 0; i < 100; i++) { arr.pop(); } arr.push(0); arr.push(1); arr.push(2); arr.push(3); } // Array#map /////////////////////////////////////////////////////////////////////////////////////// { let newArr: f32[] = arr.map((value: i32, index: i32, array: Array): f32 => value); assert(newArr.length == 4); assert(newArr[0] == arr[0]); // Test side effect push i = 0; arr.map((value: i32, index: i32, array: Array): i32 => { array.push(100); //push side effect should not affect this method by spec i += value; return value; }); assert(i == 6); assert(arr.length == 8); i = 0; arr.map((value: i32, index: i32, array: Array): i32 => { i += value; return value; }); assert(i == 406); arr.pop(); arr.pop(); arr.pop(); arr.pop(); // Test side effect pop i = 0; arr.map((value: i32, index: i32, array: Array): i32 => { array.pop(); //poped items shouldn't be looked up, and we shouldn't go out of bounds i += value; return value; }); // only 2 first items was looked up, since last 2 was removed by .pop() assert(i == 1); assert(arr.length == 2); arr.push(2); arr.push(3); } // Array#filter //////////////////////////////////////////////////////////////////////////////////// { let filteredArr: i32[] = arr.filter((value: i32, index: i32, array: Array): bool => value >= 2); assert(filteredArr.length == 2); // Test side effect push i = 0; arr.filter((value: i32, index: i32, array: Array): bool => { array.push(100); //push side effect should not affect this method by spec i += value; return value >= 2; }); assert(i == 6); assert(arr.length == 8); i = 0; arr.filter((value: i32, index: i32, array: Array): bool => { i += value; return value >= 2; }); assert(i == 406); arr.pop(); arr.pop(); arr.pop(); arr.pop(); // Test side effect pop i = 0; arr.filter((value: i32, index: i32, array: Array): bool => { array.pop(); //poped items shouldn't be looked up, and we shouldn't go out of bounds i += value; return value >= 2; }); // only 2 first items was looked up, since last 2 was removed by .pop() assert(i == 1); assert(arr.length == 2); arr.push(2); arr.push(3); } // Array#reduce //////////////////////////////////////////////////////////////////////////////////// { i = arr.reduce(((prev: i32, current: i32, index: i32, array: Array): i32 => prev + current), 0); assert(i == 6); // init value i = arr.reduce(((prev: i32, current: i32, index: i32, array: Array): i32 => prev + current), 4); assert(i == 10); let boolVal = arr.reduce(((prev: bool, current: i32, index: i32, array: Array): bool => prev || current > 2), false); assert(boolVal == true); boolVal = arr.reduce(((prev: bool, current: i32, index: i32, array: Array): bool => prev || current > 100), false); assert(boolVal == false); // Test side effect push i = arr.reduce(((prev: i32, current: i32, index: i32, array: Array): i32 => { array.push(1); // push side effect should not affect this method by spec return prev + current; }), 0); // array should be changed, but this method result should be calculated for old array length assert(i == 6); assert(arr.length == 8); i = arr.reduce(((prev: i32, current: i32, index: i32, array: Array): i32 => prev + current), 0); assert(i == 10); arr.pop(); arr.pop(); arr.pop(); arr.pop(); // Test side effect pop i = arr.reduce(((prev: i32, current: i32, index: i32, array: Array): i32 => { array.pop(); //poped items shouldn't be reduced, and we shouldn't go out of bounds return prev + current; }), 0); // only 2 first items was reduced, since last 2 was removed by .pop() assert(i == 1); assert(arr.length == 2); arr.push(2); arr.push(3); } // Array#reduceRight /////////////////////////////////////////////////////////////////////////////// { i = arr.reduceRight(((prev: i32, current: i32, index: i32, array: Array): i32 => prev + current), 0); assert(i == 6); // init value i = arr.reduceRight(((prev: i32, current: i32, index: i32, array: Array): i32 => prev + current), 4); assert(i == 10); let boolVal = arr.reduceRight(((prev: bool, current: i32, index: i32, array: Array): bool => prev || current > 2), false); assert(boolVal == true); boolVal = arr.reduceRight(((prev: bool, current: i32, index: i32, array: Array): bool => prev || current > 100), false); assert(boolVal == false); // Test side effect push i = arr.reduceRight(((prev: i32, current: i32, index: i32, array: Array): i32 => { array.push(1); // push side effect should not affect this method by spec return prev + current; }), 0); // array should be changed, but this method result should be calculated for old array length assert(i == 6); assert(arr.length == 8); i = arr.reduceRight(((prev: i32, current: i32, index: i32, array: Array): i32 => prev + current), 0); assert(i == 10); arr.pop(); arr.pop(); arr.pop(); arr.pop(); // Test side effect pop i = arr.reduceRight(((prev: i32, current: i32, index: i32, array: Array): i32 => { array.pop(); // poped items should be reduced return prev + current; }), 0); assert(i == 6); assert(arr.length == 0); arr.push(0); arr.push(1); arr.push(2); arr.push(3); } // Array#sort ////////////////////////////////////////////////////////////////////////////////////// // Checks if an array is properly sorted function isSorted(data: Array, comparator: (a: T, b: T) => i32 = COMPARATOR()): bool { for (let i: i32 = 1, len: i32 = data.length; i < len; i++) { if (comparator(data[i - 1], data[i]) > 0) return false; } return true; } function createReverseOrderedArray(size: i32): Array { var arr = Array.create(size); for (let i = 0; i < size; i++) { arr[i] = size - 1 - i; } return arr; } NativeMath.seedRandom(reinterpret(JSMath.random())); function createRandomOrderedArray(size: i32): Array { var arr = Array.create(size); for (let i = 0; i < size; i++) { arr[i] = (NativeMath.random() * size); } return arr; } function createReverseOrderedNestedArray(size: i32): Array> { var arr = Array.create>(size); for (let i: i32 = 0; i < size; i++) { let inner = Array.create(1); inner[0] = size - 1 - i; arr[i] = inner; } return arr; } class Proxy { constructor(public x: T) {} } function createReverseOrderedElementsArray(size: i32): Proxy[] { var arr = Array.create>(size); for (let i: i32 = 0; i < size; i++) { arr[i] = new Proxy(size - 1 - i); } return arr; } const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-,.+/\\[]{}()<>*&$%^@#!?"; function createRandomString(len: i32): string { var result = ""; for (let i = 0; i < len; i++) { result += charset.charAt((NativeMath.floor(NativeMath.random() * charset.length))); } return result; } function createRandomStringArray(size: i32): string[] { var arr = Array.create(size); for (let i: i32 = 0; i < size; i++) { arr[i] = createRandomString((NativeMath.random() * 32)); } return arr; } function assertSorted(arr: Array, comparator: (a: T, b: T) => i32 = COMPARATOR()): void { assert(isSorted(arr.sort(comparator), comparator)); } function assertSortedDefault(arr: Array): void { assertSorted(arr, COMPARATOR()); } // Tests for default comparator { let f32ArrayTyped: f32[] = [1.0, NaN, -Infinity, 1.00000001, 0.0, -1.0, -2.0, +Infinity]; f32ArrayTyped.sort(); assert(isArraysEqual(f32ArrayTyped, [-Infinity, -2.0, -1.0, 0.0, 1.0, 1.00000001, Infinity, NaN])); let f64ArrayTyped: f64[] = [1.0, NaN, -Infinity, 1.000000000000001, 0.0, -1.0, -2.0, +Infinity]; f64ArrayTyped.sort(); assert(isArraysEqual(f64ArrayTyped, [-Infinity, -2.0, -1.0, 0.0, 1.0, 1.000000000000001, Infinity, NaN])); let i32ArrayTyped: i32[] = [1, -2, -1, 0, 2]; i32ArrayTyped.sort(); assert(isArraysEqual(i32ArrayTyped, [-2, -1, 0, 1, 2])); let u32ArrayTyped: u32[] = [1, 4294967295, 4294967294, 0, 2]; u32ArrayTyped.sort(); assert(isArraysEqual(u32ArrayTyped, [0, 1, 2, 4294967294, 4294967295])); let reversed0: i32[] = []; let reversed1: i32[] = [1]; let reversed2: i32[] = [2, 1]; let reversed4: i32[] = [3, 2, 1, 0]; let expected4: i32[] = [0, 1, 2, 3]; let reversed64 = createReverseOrderedArray(64); let reversed128 = createReverseOrderedArray(128); let reversed1024 = createReverseOrderedArray(1024); let reversed10000 = createReverseOrderedArray(10000); let randomized512 = createRandomOrderedArray(512); // Test sorting with with default comparator assertSortedDefault(reversed0); assertSortedDefault(reversed1); assert(isArraysEqual(reversed1, [1])); assertSortedDefault(reversed2); assert(isArraysEqual(reversed2, [1, 2])); assertSortedDefault(reversed4); assert(isArraysEqual(reversed4, expected4)); assertSortedDefault(reversed64); assert(isArraysEqual(reversed64, expected4, 4)); assertSortedDefault(reversed128); assert(isArraysEqual(reversed128, expected4, 4)); assertSortedDefault(reversed1024); assert(isArraysEqual(reversed1024, expected4, 4)); assertSortedDefault(reversed10000); assert(isArraysEqual(reversed10000, expected4, 4)); assertSortedDefault(randomized512); } // Test sorting with custom comparator { let randomized64 = createRandomOrderedArray(64); let randomized257 = createRandomOrderedArray(257); assertSorted(randomized64, (a: i32, b: i32): i32 => a - b); assertSorted(randomized64, (a: i32, b: i32): i32 => b - a); assertSorted(randomized257, (a: i32, b: i32): i32 => a - b); assertSorted(randomized257, (a: i32, b: i32): i32 => b - a); } // Test sorting complex objects { let reversedNested512 = createReverseOrderedNestedArray(2); assertSorted(reversedNested512, (a: i32[], b: i32[]): i32 => a[0] - b[0]); } // Test sorting reference elements { let reversedElements512 = createReverseOrderedElementsArray(512); assertSorted>(reversedElements512, (a: Proxy, b: Proxy): i32 => a.x - b.x); } // Test sorting strings { let randomStringsActual: (string | null)[] = ["a", "b", "a", "ab", "ba", "", null]; let randomStringsExpected: (string | null)[] = ["", "a", "a", "ab", "b", "ba", null]; assertSorted(randomStringsActual); assert(isArraysEqual(randomStringsActual, randomStringsExpected)); let randomStrings400 = createRandomStringArray(400); assertSorted(randomStrings400); } // Array#join ////////////////////////////////////////////////////////////////////////////////////// class Ref { constructor() {} } { assert(([true, false]).join() == "true,false"); assert(([1,-2,-3]).join("") == "1-2-3"); assert(([1, 2, 3]).join("-") == "1-2-3"); assert(([i32.MIN_VALUE, i32.MIN_VALUE]).join("__") == "-2147483648__-2147483648"); assert(([0.0, 1.0, -2.0, NaN, -Infinity, Infinity]).join(", ") == "0.0, 1.0, -2.0, NaN, -Infinity, Infinity"); assert((["", "1", null]).join("") == "1"); let refArr: (Ref | null)[] = [new Ref(), null, new Ref()]; assert(refArr.join() == "[object Object],,[object Object]"); } // Array#toString ////////////////////////////////////////////////////////////////////////////////// { let arr0: i32[] = []; let arr1: i32[] = [1]; let arr2: i32[] = [1,2]; let arr3: i32[] = [0,1,2,3]; assert(arr0.toString() == ""); assert(arr1.toString() == "1"); assert(arr2.toString() == "1,2"); assert(arr3.toString() == "0,1,2,3"); assert(([1, -1, 0]).toString() == "1,-1,0"); assert(([1, 0xFFFF, 0]).toString() == "1,65535,0"); assert(([1, 0xFFFFFFFFFFFFFFFF, 0]).toString() == "1,18446744073709551615,0"); assert(([-1, -1234567890123456, 0, i64.MAX_VALUE]).toString() == "-1,-1234567890123456,0,9223372036854775807"); let arrStr: (string | null)[] = ["", "a", "a", "ab", "b", "ba", null] assert(arrStr.toString() == ",a,a,ab,b,ba,"); assert((["1", "2", null, "4"]).toString() == "1,2,,4"); var subarr32: i32[][] = [[1,2], [3,4]]; assert(subarr32.toString() == "1,2,3,4"); var subarr8: u8[][] = [[1,2], [3,4]]; assert(subarr8.toString() == "1,2,3,4"); var subarrU32: u32[][][] = [[[1]]]; assert(subarrU32.toString() == "1"); } // Unleak globals __release(changetype(arr));