node/deps/v8/test/mjsunit/clone-ic-regressions.js
Michaël Zasso 9d7cd9b864
deps: update V8 to 12.8.374.13
PR-URL: https://github.com/nodejs/node/pull/54077
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
2024-08-16 16:03:01 +02:00

343 lines
6.8 KiB
JavaScript

// Copyright 2023 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
// Tests megamorphic case
function clone1(o) {
return {...o};
}
// Tests monomorphic case
function clone2(o) {
return {...o};
}
// Tests null proto
function clone3(o) {
return {...o, __proto__: null};
}
%PrepareFunctionForOptimization(clone1);
%PrepareFunctionForOptimization(clone2);
%PrepareFunctionForOptimization(clone3);
function test(a, b) {
%ClearFunctionFeedback(clone2);
assertEquals({...b}, a);
assertEquals(clone1(b), a);
assertEquals(clone1(b), a);
assertEquals(clone2(b), a);
assertEquals(clone2(b), a);
assertEquals(clone1(b).constructor, a.constructor);
assertEquals(clone2(b).constructor, a.constructor);
%ClearFunctionFeedback(clone2);
assertEquals(clone2(b).constructor, a.constructor);
var a2 = {...a};
// Provoke some transitions
%ClearFunctionFeedback(clone2);
Object.assign(a, {xx: 42})
assertEquals({...b, xx: 42}, a);
assertEquals({...clone1(b), xx: 42}, a);
assertEquals({...clone1(b), xx: 42}, a);
assertEquals({...clone2(b), xx: 42}, a);
assertEquals({...clone2(b), xx: 42}, a);
%ClearFunctionFeedback(clone2);
Object.assign(a, {xx: 42.2})
assertEquals({...b, xx: 42.2}, a);
assertEquals({...clone1(b), xx: 42.2}, a);
assertEquals({...clone1(b), xx: 42.2}, a);
assertEquals({...clone2(b), xx: 42.2}, a);
assertEquals({...clone2(b), xx: 42.2}, a);
%ClearFunctionFeedback(clone3);
a2.__proto__ = null;
assertEquals(clone3(b), a2);
assertEquals(clone3(b), a2);
assertEquals(clone3(b).__proto__, undefined);
}
test({});
test({}, false);
test({}, 1.1);
test({}, NaN);
test({}, 2);
test({}, new function(){});
test({}, test);
test({}, {}.__proto__);
test({}, new Proxy({}, function(){}));
test({a: "a"}, new Proxy({a: "a"}, function(){}));
test({}, BigInt(2));
test({}, Symbol("ab"));
test({0: "a", 1: "b"}, "ab");
// non-enumerable
var obj = {a: 1}
Object.defineProperty(obj, 'b', {
value: 42,
});
test({a: 1}, obj);
assertFalse(%HaveSameMap({...obj},obj));
// some not writable
var obj = {}
Object.defineProperty(obj, 'a', {
value: 42,
writable: false,
enumerable: true
});
obj.b = 1;
test({a: 42, b: 1}, obj);
assertFalse(%HaveSameMap({...obj},obj));
// non-enumerable after non-writable
var obj = {}
Object.defineProperty(obj, 'a', {
value: 1,
writable: false,
enumerable: true,
});
Object.defineProperty(obj, 'b', {
value: 2,
});
test({a: 1}, obj);
var c = {...obj, a: 4};
test({0:1,1:2}, [1,2]);
var buffer = new ArrayBuffer(24);
var idView = new Uint32Array(buffer, 0, 2);
test({}, buffer);
test({0:0,1:0}, idView);
// with prototypes
{
__v_0 = Object.create(null);
__v_1 = Object.create(__v_0);
test({}, __v_0);
test({}, __v_1);
function F0() {}
const v2 = new F0();
test({}, v2);
}
// null prototype
{
function F0() {
this.b = 4294967297;
}
const v3 = new F0();
const o4 = {
__proto__: v3,
};
const o7 = {
...o4,
__proto__: null,
};
const o6 = {
...v3,
__proto__: null,
};
assertEquals(o6, {b: 4294967297});
assertEquals(o7, {});
test({}, o7);
test({b: 4294967297}, o6);
}
// Dictionary mode objects
{
let v0 = "";
for (let v1 = 0; v1 < 250; v1++) {
v0 += `this.a${v1} = 0;\n`;
}
const v4 = Function(v0);
const v5 = new v4();
const o6 = {
...v5,
};
test(o6, v5);
}
// Null proto with non data props
{
const v0 = [1];
const o3 = {
...v0,
get g() {
},
};
const o4 = {
...o3,
__proto__: null,
};
test({0: 1, g: undefined}, o4);
}
// Ensure the IC without feedback vector supports the fast-case
(function() {
var o = {};
o.x = "1";
var o2 = {...o};
assertTrue(%HaveSameMap(o, o2));
})();
// Cloning sealed and frozen objects
(function(){
function testFrozen1(x) {
"use strict"
if (x.x) {
assertThrows(function() { x.x = 42 }, TypeError);
}
if (x[2]) {
assertThrows(function() { x[2] = 42 }, TypeError);
}
}
function testFrozen2(x) {
if (x.x) {
x.x = 42;
assertFalse(x.x == 42);
}
if (x[2]) {
x[10] = 42;
assertFalse(x[10] == 42);
}
}
function testUnfrozen(x) {
x.x = 42;
assertTrue(x.x == 42);
x[2] = 42;
assertTrue(x[2] == 42);
}
function testSealed(x) {
x.asdf = 42;
assertFalse(x.asdf == 42);
x[10] = 42;
assertFalse(x[10] == 42);
}
function testUnsealed(x) {
x.asdf = 42;
assertTrue(x.asdf == 42);
x[10] = 42;
assertTrue(x[10] == 42);
}
function testFreeze(x) {
Object.freeze(x);
testFrozen1(x);
testFrozen2(x);
var y = {...x};
assertFalse(%HaveSameMap(x,y));
if (x.__proto__ == Object.prototype) {
assertEquals(x, y);
}
testUnfrozen(y);
y = Object.assign({}, x);
if (x.__proto__ == Object.prototype) {
assertEquals(x, y);
}
testUnfrozen(y);
}
function testSeal(x) {
Object.seal(x);
testSealed(x);
var y = {...x};
assertFalse(%HaveSameMap(x,y));
if (x.__proto__ == Object.prototype) {
assertEquals(x, y);
}
testUnsealed(y);
y = Object.assign({}, x);
if (x.__proto__ == Object.prototype) {
assertEquals(x, y);
}
testUnsealed(y);
}
function testNonExtend(x) {
Object.preventExtensions(x);
testSealed(x);
var y = {...x};
assertFalse(%HaveSameMap(x,y));
if (x.__proto__ == Object.prototype) {
assertEquals(x, y);
}
testUnsealed(y);
y = Object.assign({}, x);
if (x.__proto__ == Object.prototype) {
assertEquals(x, y);
}
testUnsealed(y);
}
var tests = [testFreeze, testSeal, testNonExtend];
for (var i = 0; i < 20; ++i) {
tests.forEach(test => {
if (i < 10) { %ClearFunctionFeedback(test); }
var x = {};
x.x = 3;
test(x);
if (i < 10) { %ClearFunctionFeedback(test); }
x = [];
x[2]= 3;
test(x);
if (i < 10) { %ClearFunctionFeedback(test); }
x = {};
x[2]= 3;
test(x);
if (i < 10) { %ClearFunctionFeedback(test); }
var x = {};
x.x = 3;
x[10000] = 3
test(x);
});
}
})();
// A case not supported by the clone IC.
(function () {
function F0() {}
const v6 = new F0();
o9 = {
...v6,
};
})();
// A case where the clone IC adds a transition to an existing transition array.
(function () {
function f1() {}
function F2(a4) {
function f5() {}
a4.toString = f5;
}
const v7 = new F2(WeakSet);
const v8 = new F2(f1);
new F2(v8);
const o10 = {
...v7,
};
})();
// A case where we copy from a smaller into a bigger object.
(function() {
function F0() {
}
function F3() {
const v9 = new F0();
const o10 = {
...v9,
};
}
new F3();
new F3();
new F3();
})();