v8/test/mjsunit/harmony/array-to-reversed.js
Choongwoo Han 2dcb0a1a1e Fix Array.toReversed to create properties for holes
Array.toReversed always creates properties even for holes, but the
optimization paths for HOLEY_* arrays did not respect the spec. This CL
fixes the fast paths to set `undefined` value instead of the hole.

Bug: chromium:1395672
Change-Id: I51584829caf312a1864f93928315782bb120ee14
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4081689
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Choongwoo Han <choongwoo.han@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#84766}
2022-12-09 18:00:55 +00:00

143 lines
4.0 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(0, Array.prototype.toReversed.length);
assertEquals("toReversed", Array.prototype.toReversed.name);
(function TestSmiPacked() {
let a = [1,2,3,4];
let r = a.toReversed();
assertEquals([1,2,3,4], a);
assertEquals([4,3,2,1], r);
assertFalse(a === r);
})();
(function TestDoublePacked() {
let a = [1.1,2.2,3.3,4.4];
let r = a.toReversed();
assertEquals([1.1,2.2,3.3,4.4], a);
assertEquals([4.4,3.3,2.2,1.1], r);
assertFalse(a === r);
})();
(function TestPacked() {
let a = [true,false,1,42.42];
let r = a.toReversed();
assertEquals([true,false,1,42.42], a);
assertEquals([42.42,1,false,true], r);
assertFalse(a === r);
})();
(function TestSmiHoley() {
let a = [1,,3,4];
let r = a.toReversed();
assertEquals([1,,3,4], a);
assertEquals([4,3,undefined,1], r);
assertFalse(a.hasOwnProperty(1));
assertTrue(r.hasOwnProperty(2));
assertFalse(a === r);
})();
(function TestDoubleHoley() {
let a = [1.1,,3.3,4.4];
let r = a.toReversed();
assertEquals([1.1,,3.3,4.4], a);
assertEquals([4.4,3.3,undefined,1.1], r);
assertFalse(a.hasOwnProperty(1));
assertTrue(r.hasOwnProperty(2));
assertFalse(a === r);
})();
(function TestHoley() {
let a = [true,false,,1,42.42];
let r = a.toReversed();
assertEquals([true,false,,1,42.42], a);
assertEquals([42.42,1,undefined,false,true], r);
assertFalse(a.hasOwnProperty(2));
assertTrue(r.hasOwnProperty(2));
assertFalse(a === r);
})();
(function TestGeneric() {
let a = { length: 4,
get "0"() { return "hello"; },
get "1"() { return "cursed"; },
get "2"() { return "java"; },
get "3"() { return "script" } };
let r = Array.prototype.toReversed.call(a);
assertEquals("hello", a[0]);
assertEquals(["script","java","cursed","hello"], r);
assertFalse(a === r);
assertTrue(Array.isArray(r));
assertEquals(Array, r.constructor);
})();
(function TestReadOrder() {
let order = [];
let a = { length: 4,
get "0"() { order.push("4th"); return "4th"; },
get "1"() { order.push("3rd"); return "3rd"; },
get "2"() { order.push("2nd"); return "2nd"; },
get "3"() { order.push("1st"); return "1st"; } };
let r = Array.prototype.toReversed.call(a);
assertEquals(["1st","2nd","3rd","4th"], r);
assertEquals(["1st","2nd","3rd","4th"], order);
})();
(function TestEmpty() {
assertEquals([], [].toReversed());
})();
(function TestTooBig() {
let a = { length: Math.pow(2, 32) };
assertThrows(() => Array.prototype.toReversed.call(a), RangeError);
})();
(function TestNoSpecies() {
class MyArray extends Array {
static get [Symbol.species]() { return MyArray; }
}
assertEquals(Array, (new MyArray()).toReversed().constructor);
})();
// All tests after this have an invalidated elements-on-prototype protector.
(function TestNoHoles() {
let a = [,,,,];
Array.prototype[3] = "on proto";
let r = a.toReversed();
assertEquals(["on proto",undefined,undefined,undefined], r);
for (let i = 0; i < a.length; i++) {
assertFalse(a.hasOwnProperty(i));
assertTrue(r.hasOwnProperty(i));
}
})();
(function TestMidIterationShenanigans() {
let 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.
let r = a.toReversed();
assertEquals(1, a.length);
assertEquals([4,3,2,1], r);
// Values can be changed mid-iteration.
a = { length: 4,
"0": 1,
get "1"() { a[0] = "poof"; return 2; },
"2": 3,
"3": 4,
__proto__: Array.prototype };
r = a.toReversed();
assertEquals([4,3,2,"poof"], r);
})();
assertEquals(Array.prototype[Symbol.unscopables].toReversed, true);