Commit 3c4c25db authored by Shu-yu Guo's avatar Shu-yu Guo Committed by V8 LUCI CQ

[change-array-by-copy] Implement Array.prototype.toSpliced

Drive-by: add unscopable test for Array.prototype.toReversed.

Bug: v8:12764
Change-Id: I9d7dd8d4eae6d23811382b6795c2c6ff7f76be72
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3717552Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81364}
parent 902b2327
...@@ -785,6 +785,7 @@ filegroup( ...@@ -785,6 +785,7 @@ filegroup(
"src/builtins/array-some.tq", "src/builtins/array-some.tq",
"src/builtins/array-splice.tq", "src/builtins/array-splice.tq",
"src/builtins/array-to-reversed.tq", "src/builtins/array-to-reversed.tq",
"src/builtins/array-to-spliced.tq",
"src/builtins/array-unshift.tq", "src/builtins/array-unshift.tq",
"src/builtins/array-with.tq", "src/builtins/array-with.tq",
"src/builtins/array.tq", "src/builtins/array.tq",
......
...@@ -1686,6 +1686,7 @@ torque_files = [ ...@@ -1686,6 +1686,7 @@ torque_files = [
"src/builtins/array-some.tq", "src/builtins/array-some.tq",
"src/builtins/array-splice.tq", "src/builtins/array-splice.tq",
"src/builtins/array-to-reversed.tq", "src/builtins/array-to-reversed.tq",
"src/builtins/array-to-spliced.tq",
"src/builtins/array-unshift.tq", "src/builtins/array-unshift.tq",
"src/builtins/array-with.tq", "src/builtins/array-with.tq",
"src/builtins/array.tq", "src/builtins/array.tq",
......
...@@ -58,6 +58,26 @@ macro DoCopyElements<FixedArrayType : type extends FixedArrayBase>( ...@@ -58,6 +58,26 @@ macro DoCopyElements<FixedArrayType : type extends FixedArrayBase>(
Convert<intptr>(srcIndex), Convert<intptr>(count)); Convert<intptr>(srcIndex), Convert<intptr>(count));
} }
macro InsertArgumentsIntoFastPackedArray<
FixedArrayType : type extends FixedArrayBase, ElementType: type>(
dst: JSArray, dstStart: Smi, args: Arguments,
argsStart: constexpr IntegerLiteral, insertCount: Smi): void {
// Copy arguments.
let k: Smi = dstStart;
if (insertCount > 0) {
dcheck(Convert<intptr>(insertCount) == args.length - argsStart);
const typedNewElements: FixedArrayType =
UnsafeCast<FixedArrayType>(dst.elements);
for (let i: intptr = ConstexprIntegerLiteralToIntptr(argsStart);
i < args.length; ++i) {
const e: JSAny = args[i];
// The argument elements were already validated to be an appropriate
// {ElementType} to store in {FixedArrayType}.
typedNewElements[k++] = UnsafeCast<ElementType>(e);
}
}
}
macro macro
FastSplice<FixedArrayType : type extends FixedArrayBase, ElementType: type>( FastSplice<FixedArrayType : type extends FixedArrayBase, ElementType: type>(
implicit context: Context)( implicit context: Context)(
...@@ -97,22 +117,47 @@ FastSplice<FixedArrayType : type extends FixedArrayBase, ElementType: type>( ...@@ -97,22 +117,47 @@ FastSplice<FixedArrayType : type extends FixedArrayBase, ElementType: type>(
} }
// Copy arguments. // Copy arguments.
let k: Smi = actualStart; InsertArgumentsIntoFastPackedArray<FixedArrayType, ElementType>(
if (insertCount > 0) { a, actualStart, args, 2, insertCount);
const typedNewElements: FixedArrayType =
UnsafeCast<FixedArrayType>(a.elements);
for (let i: intptr = 2; i < args.length; ++i) {
const e: JSAny = args[i];
// The argument elements were already validated to be an appropriate
// {ElementType} to store in {FixedArrayType}.
typedNewElements[k++] = UnsafeCast<ElementType>(e);
}
}
// Update the array's length after all the FixedArray shuffling is done. // Update the array's length after all the FixedArray shuffling is done.
a.length = newLength; a.length = newLength;
} }
transitioning macro TransitionElementsKindForInsertionIfNeeded(
context: Context, a: JSArray, originalElementsKind: ElementsKind,
args: Arguments, argsStart: constexpr IntegerLiteral): ElementsKind {
dcheck(a.map.elements_kind == originalElementsKind);
let elementsKind = originalElementsKind;
for (let k: intptr = ConstexprIntegerLiteralToIntptr(argsStart);
k < args.length; ++k) {
const e = args[k];
if (IsFastSmiElementsKind(elementsKind)) {
if (TaggedIsNotSmi(e)) {
const heapObject: HeapObject = UnsafeCast<HeapObject>(e);
elementsKind = IsHeapNumber(heapObject) ?
AllowDoubleElements(elementsKind) :
AllowNonNumberElements(elementsKind);
}
} else if (IsDoubleElementsKind(elementsKind)) {
if (!IsNumber(e)) {
elementsKind = AllowNonNumberElements(elementsKind);
}
} else {
// Already generic.
break;
}
}
if (elementsKind != originalElementsKind) {
const smiElementsKind: Smi = Convert<Smi>(Convert<int32>(elementsKind));
TransitionElementsKindWithKind(context, a, smiElementsKind);
}
return elementsKind;
}
transitioning macro FastArraySplice( transitioning macro FastArraySplice(
context: Context, args: Arguments, o: JSReceiver, context: Context, args: Arguments, o: JSReceiver,
originalLengthNumber: Number, actualStartNumber: Number, insertCount: Smi, originalLengthNumber: Number, actualStartNumber: Number, insertCount: Smi,
...@@ -136,27 +181,8 @@ transitioning macro FastArraySplice( ...@@ -136,27 +181,8 @@ transitioning macro FastArraySplice(
let elementsKind: ElementsKind = EnsureArrayPushable(map) otherwise Bailout; let elementsKind: ElementsKind = EnsureArrayPushable(map) otherwise Bailout;
if (!IsFastElementsKind(elementsKind)) goto Bailout; if (!IsFastElementsKind(elementsKind)) goto Bailout;
const oldElementsKind: ElementsKind = elementsKind; elementsKind = TransitionElementsKindForInsertionIfNeeded(
for (let i: intptr = 2; i < args.length; ++i) { context, a, elementsKind, args, 2);
const e: JSAny = args[i];
if (IsFastSmiElementsKind(elementsKind)) {
if (TaggedIsNotSmi(e)) {
const heapObject: HeapObject = UnsafeCast<HeapObject>(e);
elementsKind = IsHeapNumber(heapObject) ?
AllowDoubleElements(elementsKind) :
AllowNonNumberElements(elementsKind);
}
} else if (IsDoubleElementsKind(elementsKind)) {
if (!IsNumber(e)) {
elementsKind = AllowNonNumberElements(elementsKind);
}
}
}
if (elementsKind != oldElementsKind) {
const smiElementsKind: Smi = Convert<Smi>(Convert<int32>(elementsKind));
TransitionElementsKindWithKind(context, a, smiElementsKind);
}
// Make sure that the length hasn't been changed by side-effect. // Make sure that the length hasn't been changed by side-effect.
const length: Smi = Cast<Smi>(a.length) otherwise Bailout; const length: Smi = Cast<Smi>(a.length) otherwise Bailout;
...@@ -403,7 +429,7 @@ ArrayPrototypeSplice( ...@@ -403,7 +429,7 @@ ArrayPrototypeSplice(
// Bailout exception. // Bailout exception.
const newLength: Number = len + insertCount - actualDeleteCount; const newLength: Number = len + insertCount - actualDeleteCount;
if (newLength > kMaxSafeInteger) { if (newLength > kMaxSafeInteger) {
ThrowTypeError(MessageTemplate::kInvalidArrayLength, start); ThrowTypeError(MessageTemplate::kInvalidArrayLength, newLength);
} }
try { try {
......
...@@ -56,8 +56,8 @@ macro TryFastPackedArrayToReversed(implicit context: Context)(receiver: JSAny): ...@@ -56,8 +56,8 @@ macro TryFastPackedArrayToReversed(implicit context: Context)(receiver: JSAny):
goto Slow; goto Slow;
} }
transitioning macro GenericArrayToReversed( transitioning macro GenericArrayToReversed(implicit context: Context)(
context: Context, receiver: JSAny): JSAny { receiver: JSAny): JSAny {
// 1. Let O be ? ToObject(this value). // 1. Let O be ? ToObject(this value).
const object: JSReceiver = ToObject_Inline(context, receiver); const object: JSReceiver = ToObject_Inline(context, receiver);
...@@ -96,7 +96,7 @@ transitioning javascript builtin ArrayPrototypeToReversed( ...@@ -96,7 +96,7 @@ transitioning javascript builtin ArrayPrototypeToReversed(
try { try {
return TryFastPackedArrayToReversed(receiver) otherwise Slow; return TryFastPackedArrayToReversed(receiver) otherwise Slow;
} label Slow { } label Slow {
return GenericArrayToReversed(context, receiver); return GenericArrayToReversed(receiver);
} }
} }
} }
// 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.
namespace array {
// Makes a copy of the source array for toSpliced without inserting the new
// items.
macro CopyFastPackedArrayForToSpliced(implicit context: Context)(
kind: constexpr ElementsKind, array: JSArray, newLenSmi: Smi,
actualStartSmi: Smi, insertCountSmi: Smi,
actualDeleteCountSmi: Smi): JSArray {
const newLen: intptr = Convert<intptr>(newLenSmi);
const actualStart: intptr = Convert<intptr>(actualStartSmi);
const insertCount: intptr = Convert<intptr>(insertCountSmi);
const actualDeleteCount: intptr = Convert<intptr>(actualDeleteCountSmi);
const copy: FixedArrayBase =
AllocateFixedArray(kind, newLen, AllocationFlag::kNone);
// Copy the part before the inserted items.
CopyElements(kind, copy, 0, array.elements, 0, actualStart);
// Leave the items to be inserted for later since it could transition the
// ElementsKind.
// Copy the part after the inserted items.
const secondPartStart: intptr = actualStart + insertCount;
const secondPartLen: intptr = newLen - secondPartStart;
const r: intptr = actualStart + actualDeleteCount;
dcheck(Convert<Smi>(r + secondPartLen) <= array.length);
CopyElements(kind, copy, secondPartStart, array.elements, r, secondPartLen);
const map: Map = LoadJSArrayElementsMap(kind, LoadNativeContext(context));
return NewJSArray(map, copy);
}
transitioning macro TryFastArrayToSpliced(implicit context: Context)(
args: Arguments, o: JSReceiver, originalLenNumber: Number,
newLenNumber: Number, actualStartNumber: Number, insertCount: Smi,
actualDeleteCountNumber: Number): JSArray labels Slow {
const newLen: Smi = Cast<Smi>(newLenNumber) otherwise Slow;
const actualStart: Smi = Cast<Smi>(actualStartNumber) otherwise Slow;
const actualDeleteCount: Smi =
Cast<Smi>(actualDeleteCountNumber) otherwise Slow;
const array: FastJSArray = Cast<FastJSArray>(o) otherwise Slow;
// If any argument coercion shrunk the source array, go to the slow case.
const originalLen: Smi = Cast<Smi>(originalLenNumber) otherwise Slow;
if (originalLen > array.length) goto Slow;
// Array#toSpliced does not preserve holes and always creates packed Arrays.
// Holes in the source array-like are treated like any other element and the
// value is computed with Get. So, there are only fast paths for packed
// elements.
let elementsKind: ElementsKind = array.map.elements_kind;
if (!IsFastPackedElementsKind(elementsKind)) goto Slow;
// Make a copy before inserting the new items, as doing so can transition the
// ElementsKind.
let copy: JSArray;
if (elementsKind == ElementsKind::PACKED_SMI_ELEMENTS) {
copy = CopyFastPackedArrayForToSpliced(
ElementsKind::PACKED_SMI_ELEMENTS, array, newLen, actualStart,
insertCount, actualDeleteCount);
} else if (elementsKind == ElementsKind::PACKED_ELEMENTS) {
copy = CopyFastPackedArrayForToSpliced(
ElementsKind::PACKED_ELEMENTS, array, newLen, actualStart, insertCount,
actualDeleteCount);
} else {
dcheck(elementsKind == ElementsKind::PACKED_DOUBLE_ELEMENTS);
copy = CopyFastPackedArrayForToSpliced(
ElementsKind::PACKED_DOUBLE_ELEMENTS, array, newLen, actualStart,
insertCount, actualDeleteCount);
}
// Array#toSpliced's parameters are (start, deleteCount, ...items), so the
// first item to insert is at index 2.
const kArgsStart = 2;
elementsKind = TransitionElementsKindForInsertionIfNeeded(
context, copy, elementsKind, args, kArgsStart);
// Insert the items.
dcheck(IsFastPackedElementsKind(elementsKind));
if (IsFastSmiOrTaggedElementsKind(elementsKind)) {
InsertArgumentsIntoFastPackedArray<FixedArray, JSAny>(
copy, actualStart, args, kArgsStart, insertCount);
} else {
InsertArgumentsIntoFastPackedArray<FixedDoubleArray, Number>(
copy, actualStart, args, kArgsStart, insertCount);
}
return copy;
}
transitioning macro GenericArrayToSpliced(implicit context: Context)(
args: Arguments, o: JSReceiver, newLen: Number, actualStart: Number,
actualDeleteCount: Number): JSArray {
// 13. Let A be ? ArrayCreate(𝔽(newLen)).
const copy = ArrayCreate(newLen);
// 14. Let i be 0.
let i: Number = 0;
// 15. Let r be actualStart + actualDeleteCount.
let r: Number = actualStart + actualDeleteCount;
// 16. Repeat, while i < actualStart,
while (i < actualStart) {
// a. Let Pi be ! ToString(𝔽(i)).
// b. Let iValue be ? Get(O, Pi).
const iValue = GetProperty(o, i);
// c. Perform ! CreateDataPropertyOrThrow(A, Pi, iValue).
FastCreateDataProperty(copy, i, iValue);
// d. Set i to i + 1.
++i;
}
if (args.length > 2) {
// 17. For each element E of items, do
for (let k: intptr = 2; k < args.length; ++k) {
const e = args[k];
// a. Let Pi be ! ToString(𝔽(i)).
// b. Perform ! CreateDataPropertyOrThrow(A, Pi, E).
FastCreateDataProperty(copy, i, e);
// c. Set i to i + 1.
++i;
}
}
// 18. Repeat, while i < newLen,
while (i < newLen) {
// a. Let Pi be ! ToString(𝔽(i)).
// b. Let from be ! ToString(𝔽(r)).
// c. Let fromValue be ? Get(O, from).
const fromValue = GetProperty(o, r);
// d. Perform ! CreateDataPropertyOrThrow(A, Pi, fromValue).
FastCreateDataProperty(copy, i, fromValue);
// e. Set i to i + 1.
++i;
// f. Set r to r + 1.
++r;
}
// 19. Return A.
return copy;
}
// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toSpliced
transitioning javascript builtin ArrayPrototypeToSpliced(
js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
const start = arguments[0];
const deleteCount = arguments[1];
// 1. Let O be ? ToObject(this value).
const o: JSReceiver = ToObject(context, receiver);
// 2. Let len be ? LengthOfArrayLike(O).
const len: Number = GetLengthProperty(o);
// 3. Let relativeStart be ? ToIntegerOrInfinity(start).
const relativeStart: Number = ToInteger_Inline(start);
// 4. If relativeStart is -∞, let actualStart be 0.
// 5. Else if relativeStart < 0, let actualStart be max(len + relativeStart,
// 0).
// 6. Else, let actualStart be min(relativeStart, len).
//
// TODO(syg): Support Number length values in ConvertAndClampRelativeIndex.
const actualStart = relativeStart < 0 ? Max((len + relativeStart), 0) :
Min(relativeStart, len);
let insertCount: Smi;
let actualDeleteCount: Number;
if (arguments.length == 0) {
// 7. Let insertCount be the number of elements in items.
insertCount = 0;
// 8. If start is not present, then
// a. Let actualDeleteCount be 0.
actualDeleteCount = 0;
} else if (arguments.length == 1) {
// 7. Let insertCount be the number of elements in items.
insertCount = 0;
// 9. Else if deleteCount is not present, then
// a. Let actualDeleteCount be len - actualStart.
actualDeleteCount = len - actualStart;
} else {
// 7. Let insertCount be the number of elements in items.
insertCount = Convert<Smi>(arguments.length) - 2;
// 10. Else,
// a. Let dc be ? ToIntegerOrInfinity(deleteCount).
// b. Let actualDeleteCount be the result of clamping dc between 0 and len
// - actualStart.
const dc = ToInteger_Inline(deleteCount);
actualDeleteCount = Min(Max(0, dc), len - actualStart);
}
// 11. Let newLen be len + insertCount - actualDeleteCount.
const newLen = len + insertCount - actualDeleteCount;
// 12. If newLen > 2^53 - 1, throw a TypeError exception.
if (newLen > kMaxSafeInteger) {
ThrowTypeError(MessageTemplate::kInvalidArrayLength, newLen);
}
if (newLen == 0) return ArrayCreate(0);
try {
return TryFastArrayToSpliced(
arguments, o, len, newLen, actualStart, insertCount, actualDeleteCount)
otherwise Slow;
} label Slow {
return GenericArrayToSpliced(
arguments, o, newLen, actualStart, actualDeleteCount);
}
}
}
...@@ -4524,6 +4524,8 @@ void Genesis::InitializeGlobal_harmony_change_array_by_copy() { ...@@ -4524,6 +4524,8 @@ void Genesis::InitializeGlobal_harmony_change_array_by_copy() {
SimpleInstallFunction(isolate_, array_prototype, "toReversed", SimpleInstallFunction(isolate_, array_prototype, "toReversed",
Builtin::kArrayPrototypeToReversed, 0, true); Builtin::kArrayPrototypeToReversed, 0, true);
SimpleInstallFunction(isolate_, array_prototype, "toSpliced",
Builtin::kArrayPrototypeToSpliced, 2, false);
SimpleInstallFunction(isolate_, array_prototype, "with", SimpleInstallFunction(isolate_, array_prototype, "with",
Builtin::kArrayPrototypeWith, 2, true); Builtin::kArrayPrototypeWith, 2, true);
...@@ -4533,6 +4535,7 @@ void Genesis::InitializeGlobal_harmony_change_array_by_copy() { ...@@ -4533,6 +4535,7 @@ void Genesis::InitializeGlobal_harmony_change_array_by_copy() {
.ToHandleChecked()); .ToHandleChecked());
InstallTrueValuedProperty(isolate_, unscopables, "toReversed"); InstallTrueValuedProperty(isolate_, unscopables, "toReversed");
InstallTrueValuedProperty(isolate_, unscopables, "toSpliced");
} }
{ {
......
...@@ -74,12 +74,11 @@ assertEquals("toReversed", Array.prototype.toReversed.name); ...@@ -74,12 +74,11 @@ assertEquals("toReversed", Array.prototype.toReversed.name);
let a = [,,,,]; let a = [,,,,];
Array.prototype[3] = "on proto"; Array.prototype[3] = "on proto";
let r = a.toReversed(); let r = a.toReversed();
assertEquals([,,,,], a);
assertEquals(["on proto",undefined,undefined,undefined], r); assertEquals(["on proto",undefined,undefined,undefined], r);
assertTrue(r.hasOwnProperty('0')); for (let i = 0; i < a.length; i++) {
assertTrue(r.hasOwnProperty('1')); assertFalse(a.hasOwnProperty(i));
assertTrue(r.hasOwnProperty('2')); assertTrue(r.hasOwnProperty(i));
assertTrue(r.hasOwnProperty('3')); }
})(); })();
(function TestMidIterationShenanigans() { (function TestMidIterationShenanigans() {
...@@ -105,3 +104,5 @@ assertEquals("toReversed", Array.prototype.toReversed.name); ...@@ -105,3 +104,5 @@ assertEquals("toReversed", Array.prototype.toReversed.name);
r = a.toReversed(); r = a.toReversed();
assertEquals([4,3,2,"poof"], r); assertEquals([4,3,2,"poof"], r);
})(); })();
assertEquals(Array.prototype[Symbol.unscopables].toReversed, true);
// 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);
...@@ -540,30 +540,30 @@ KNOWN_OBJECTS = { ...@@ -540,30 +540,30 @@ KNOWN_OBJECTS = {
("old_space", 0x04a25): "StringSplitCache", ("old_space", 0x04a25): "StringSplitCache",
("old_space", 0x04e2d): "RegExpMultipleCache", ("old_space", 0x04e2d): "RegExpMultipleCache",
("old_space", 0x05235): "BuiltinsConstantsTable", ("old_space", 0x05235): "BuiltinsConstantsTable",
("old_space", 0x05671): "AsyncFunctionAwaitRejectSharedFun", ("old_space", 0x05675): "AsyncFunctionAwaitRejectSharedFun",
("old_space", 0x05695): "AsyncFunctionAwaitResolveSharedFun", ("old_space", 0x05699): "AsyncFunctionAwaitResolveSharedFun",
("old_space", 0x056b9): "AsyncGeneratorAwaitRejectSharedFun", ("old_space", 0x056bd): "AsyncGeneratorAwaitRejectSharedFun",
("old_space", 0x056dd): "AsyncGeneratorAwaitResolveSharedFun", ("old_space", 0x056e1): "AsyncGeneratorAwaitResolveSharedFun",
("old_space", 0x05701): "AsyncGeneratorYieldResolveSharedFun", ("old_space", 0x05705): "AsyncGeneratorYieldResolveSharedFun",
("old_space", 0x05725): "AsyncGeneratorReturnResolveSharedFun", ("old_space", 0x05729): "AsyncGeneratorReturnResolveSharedFun",
("old_space", 0x05749): "AsyncGeneratorReturnClosedRejectSharedFun", ("old_space", 0x0574d): "AsyncGeneratorReturnClosedRejectSharedFun",
("old_space", 0x0576d): "AsyncGeneratorReturnClosedResolveSharedFun", ("old_space", 0x05771): "AsyncGeneratorReturnClosedResolveSharedFun",
("old_space", 0x05791): "AsyncIteratorValueUnwrapSharedFun", ("old_space", 0x05795): "AsyncIteratorValueUnwrapSharedFun",
("old_space", 0x057b5): "PromiseAllResolveElementSharedFun", ("old_space", 0x057b9): "PromiseAllResolveElementSharedFun",
("old_space", 0x057d9): "PromiseAllSettledResolveElementSharedFun", ("old_space", 0x057dd): "PromiseAllSettledResolveElementSharedFun",
("old_space", 0x057fd): "PromiseAllSettledRejectElementSharedFun", ("old_space", 0x05801): "PromiseAllSettledRejectElementSharedFun",
("old_space", 0x05821): "PromiseAnyRejectElementSharedFun", ("old_space", 0x05825): "PromiseAnyRejectElementSharedFun",
("old_space", 0x05845): "PromiseCapabilityDefaultRejectSharedFun", ("old_space", 0x05849): "PromiseCapabilityDefaultRejectSharedFun",
("old_space", 0x05869): "PromiseCapabilityDefaultResolveSharedFun", ("old_space", 0x0586d): "PromiseCapabilityDefaultResolveSharedFun",
("old_space", 0x0588d): "PromiseCatchFinallySharedFun", ("old_space", 0x05891): "PromiseCatchFinallySharedFun",
("old_space", 0x058b1): "PromiseGetCapabilitiesExecutorSharedFun", ("old_space", 0x058b5): "PromiseGetCapabilitiesExecutorSharedFun",
("old_space", 0x058d5): "PromiseThenFinallySharedFun", ("old_space", 0x058d9): "PromiseThenFinallySharedFun",
("old_space", 0x058f9): "PromiseThrowerFinallySharedFun", ("old_space", 0x058fd): "PromiseThrowerFinallySharedFun",
("old_space", 0x0591d): "PromiseValueThunkFinallySharedFun", ("old_space", 0x05921): "PromiseValueThunkFinallySharedFun",
("old_space", 0x05941): "ProxyRevokeSharedFun", ("old_space", 0x05945): "ProxyRevokeSharedFun",
("old_space", 0x05965): "ShadowRealmImportValueFulfilledSFI", ("old_space", 0x05969): "ShadowRealmImportValueFulfilledSFI",
("old_space", 0x05989): "SourceTextModuleExecuteAsyncModuleFulfilledSFI", ("old_space", 0x0598d): "SourceTextModuleExecuteAsyncModuleFulfilledSFI",
("old_space", 0x059ad): "SourceTextModuleExecuteAsyncModuleRejectedSFI", ("old_space", 0x059b1): "SourceTextModuleExecuteAsyncModuleRejectedSFI",
} }
# Lower 32 bits of first page addresses for various heap spaces. # Lower 32 bits of first page addresses for various heap spaces.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment