145 lines
4.4 KiB
JavaScript
145 lines
4.4 KiB
JavaScript
|
// Copyright 2022 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: --harmony-change-array-by-copy
|
||
|
|
||
|
assertEquals(2, Array.prototype.toSpliced.length);
|
||
|
assertEquals("toSpliced", Array.prototype.toSpliced.name);
|
||
|
|
||
|
function TerribleCopy(input) {
|
||
|
let copy;
|
||
|
if (Array.isArray(input)) {
|
||
|
copy = [...input];
|
||
|
} else {
|
||
|
copy = { length: input.length };
|
||
|
for (let i = 0; i < input.length; i++) {
|
||
|
copy[i] = input[i];
|
||
|
}
|
||
|
}
|
||
|
return copy;
|
||
|
}
|
||
|
|
||
|
function AssertToSplicedAndSpliceSameResult(input, ...args) {
|
||
|
const orig = TerribleCopy(input);
|
||
|
const s = Array.prototype.toSpliced.apply(input, args);
|
||
|
const copy = TerribleCopy(input);
|
||
|
Array.prototype.splice.apply(copy, args);
|
||
|
|
||
|
// The in-place spliced version should be pairwise equal to the toSpliced,
|
||
|
// modulo being an actual Array if the input is generic.
|
||
|
if (Array.isArray(input)) {
|
||
|
assertEquals(copy, s);
|
||
|
} else {
|
||
|
assertEquals(copy.length, s.length);
|
||
|
for (let i = 0; i < copy.length; i++) {
|
||
|
assertEquals(copy[i], s[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// The original input should be unchanged.
|
||
|
assertEquals(orig, input);
|
||
|
|
||
|
// The result of toSpliced() is a copy.
|
||
|
assertFalse(s === input);
|
||
|
}
|
||
|
|
||
|
function TestToSplicedBasicBehaviorHelper(input, itemsToInsert) {
|
||
|
const startIndices = [0, 1, -1, -100, Infinity, -Infinity];
|
||
|
const deleteCounts = [0, 1, 2, 3];
|
||
|
|
||
|
AssertToSplicedAndSpliceSameResult(input);
|
||
|
|
||
|
for (let startIndex of startIndices) {
|
||
|
AssertToSplicedAndSpliceSameResult(input, startIndex);
|
||
|
for (let deleteCount of deleteCounts) {
|
||
|
AssertToSplicedAndSpliceSameResult(input, startIndex, deleteCount);
|
||
|
AssertToSplicedAndSpliceSameResult(input, startIndex, deleteCount,
|
||
|
...itemsToInsert);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Smi packed
|
||
|
TestToSplicedBasicBehaviorHelper([1,2,3,4], [5,6]);
|
||
|
|
||
|
// Double packed
|
||
|
TestToSplicedBasicBehaviorHelper([1.1,2.2,3.3,4.4], [5.5,6.6]);
|
||
|
|
||
|
// Packed
|
||
|
TestToSplicedBasicBehaviorHelper([true,false,1,42.42], [null,"foo"]);
|
||
|
|
||
|
// Generic
|
||
|
TestToSplicedBasicBehaviorHelper({ length: 4,
|
||
|
get "0"() { return "hello"; },
|
||
|
get "1"() { return "cursed"; },
|
||
|
get "2"() { return "java"; },
|
||
|
get "3"() { return "script" } },
|
||
|
["foo","bar"]);
|
||
|
|
||
|
(function TestReadOrder() {
|
||
|
const order = [];
|
||
|
const a = { length: 4,
|
||
|
get "0"() { order.push("1st"); return "1st"; },
|
||
|
get "1"() { order.push("2nd"); return "2nd"; },
|
||
|
get "2"() { order.push("3rd"); return "3rd"; },
|
||
|
get "3"() { order.push("4th"); return "4th"; } };
|
||
|
const s = Array.prototype.toSpliced.call(a);
|
||
|
assertEquals(["1st","2nd","3rd","4th"], s);
|
||
|
assertEquals(["1st","2nd","3rd","4th"], order);
|
||
|
})();
|
||
|
|
||
|
(function TestTooBig() {
|
||
|
const a = { length: Math.pow(2, 32) };
|
||
|
assertThrows(() => Array.prototype.toSpliced.call(a), RangeError);
|
||
|
})();
|
||
|
|
||
|
(function TestNoSpecies() {
|
||
|
class MyArray extends Array {
|
||
|
static get [Symbol.species]() { return MyArray; }
|
||
|
}
|
||
|
assertEquals(Array, (new MyArray()).toSpliced().constructor);
|
||
|
})();
|
||
|
|
||
|
// All tests after this have an invalidated elements-on-prototype protector.
|
||
|
(function TestNoHoles() {
|
||
|
const a = [,,,,];
|
||
|
Array.prototype[3] = "on proto";
|
||
|
const s = a.toSpliced();
|
||
|
assertEquals([undefined,undefined,undefined,"on proto"], s);
|
||
|
for (let i = 0; i < a.length; i++) {
|
||
|
assertFalse(a.hasOwnProperty(i));
|
||
|
assertTrue(s.hasOwnProperty(i));
|
||
|
}
|
||
|
})();
|
||
|
|
||
|
(function TestMidIterationShenanigans() {
|
||
|
{
|
||
|
const a = { length: 4,
|
||
|
"0": 1,
|
||
|
get "1"() { a.length = 1; return 2; },
|
||
|
"2": 3,
|
||
|
"3": 4,
|
||
|
__proto__: Array.prototype };
|
||
|
// The length is cached before iteration, so mid-iteration resizing does not
|
||
|
// affect the copied array length.
|
||
|
const s = a.toSpliced();
|
||
|
assertEquals(1, a.length);
|
||
|
assertEquals([1,2,3,4], s);
|
||
|
}
|
||
|
|
||
|
{
|
||
|
// Values can be changed mid-iteration.
|
||
|
const a = { length: 4,
|
||
|
"0": 1,
|
||
|
get "1"() { a[3] = "poof"; return 2; },
|
||
|
"2": 3,
|
||
|
"3": 4,
|
||
|
__proto__: Array.prototype };
|
||
|
const s = a.toSpliced();
|
||
|
assertEquals([1,2,3,"poof"], s);
|
||
|
}
|
||
|
})();
|
||
|
|
||
|
assertEquals(Array.prototype[Symbol.unscopables].toSpliced, true);
|