blob: 98232c2814ab6443ff9f679930567436a22801bc [file] [log] [blame]
// Copyright 2017 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
assertEquals(this.__proto__, Object.prototype);
function TestAddingPropertyToGlobalPrototype() {
let foo_func_called = 0;
let bar_func_called = 0;
function Foo() {}
Foo.prototype.func = function() { ++foo_func_called; }
delete this.func;
this.__proto__ = Foo.prototype;
function Bar() {}
Bar.prototype = this;
let o = new Bar();
for (let i = 0; i < 11; ++i) {
// First, the property is looked up from Foo.
o.func();
// Add the property to Bar which is a Global-mode prototype between o
// and Foo. In the next iteration, it's looked up from Bar.
if (i == 9) {
Bar.prototype.func = function() { ++bar_func_called; }
}
}
assertEquals(10, foo_func_called);
assertEquals(1, bar_func_called);
}
TestAddingPropertyToGlobalPrototype();
// Same as TestAddingPropertyToGlobalPrototype, but using o["foo"] access
// instead of o.foo.
function TestAddingPropertyToGlobalPrototype2() {
let foo_func_called = 0;
let bar_func_called = 0;
let name = "func";
function Foo() {}
Foo.prototype[name] = function() { ++foo_func_called; }
delete this[name];
this.__proto__ = Foo.prototype;
function Bar() {}
Bar.prototype = this;
let o = new Bar();
for (let i = 0; i < 11; ++i) {
// First, the property is looked up from Foo.
o[name]();
// Add the property to Bar which is a Global-mode prototype between o
// and Foo. In the next iteration, it's looked up from Bar.
if (i == 9) {
Bar.prototype[name] = function() { ++bar_func_called; }
}
}
assertEquals(10, foo_func_called);
assertEquals(1, bar_func_called);
}
TestAddingPropertyToGlobalPrototype2();
function TestAddingPropertyToGlobalPrototype_DefineProperty() {
let foo_func_called = 0;
let bar_func_called = 0;
function Foo() {}
Foo.prototype.func = function() { ++foo_func_called; }
delete this.func;
this.__proto__ = Foo.prototype;
function Bar() {}
Bar.prototype = this;
let o = new Bar();
for (let i = 0; i < 11; ++i) {
// First, the property is looked up from Foo.
o.func();
// Add the property to Bar which is a Global-mode prototype between o
// and Foo. In the next iteration, it's looked up from Bar.
if (i == 9) {
Object.defineProperty(Bar.prototype, "func",
{
value: function() { ++bar_func_called; },
configurable:true
});
}
}
assertEquals(10, foo_func_called);
assertEquals(1, bar_func_called);
}
TestAddingPropertyToGlobalPrototype_DefineProperty();
function TestAddingAccessorPropertyToGlobalPrototype() {
let foo_func_called = 0;
let bar_func_called = 0;
function Foo() {}
Foo.prototype.func = function() { ++foo_func_called; }
delete this.func;
this.__proto__ = Foo.prototype;
function Bar() {}
Bar.prototype = this;
let o = new Bar();
for (let i = 0; i < 11; ++i) {
// First, the property is looked up from Foo.
o.func();
// Add the property to Bar which is a Global-mode prototype between o
// and Foo. In the next iteration, it's looked up from Bar.
if (i == 9) {
Object.defineProperty(Bar.prototype, "func",
{
get: function() { return function() { ++bar_func_called; }},
configurable: true
});
}
}
assertEquals(10, foo_func_called);
assertEquals(1, bar_func_called);
}
TestAddingAccessorPropertyToGlobalPrototype();
function TestRemovingPropertyFromGlobalPrototype() {
let foo_func_called = 0;
let bar_func_called = 0;
function Foo() {}
Foo.prototype.func = function() { ++foo_func_called; }
delete this.func;
this.__proto__ = Foo.prototype;
function Bar() {}
Bar.prototype = this;
Bar.prototype.func = function() { ++bar_func_called; }
let o = new Bar();
for (let i = 0; i < 11; ++i) {
// First, the property is looked up from Bar.
o.func();
// Remove the property from Bar which is a Global-mode prototype between
// o and Foo. In the next iteration, it's looked up from Foo.
if (i == 9) {
delete Bar.prototype.func;
}
}
assertEquals(1, foo_func_called);
assertEquals(10, bar_func_called);
}
TestRemovingPropertyFromGlobalPrototype();
// Same as TestRemovingPropertyFromGlobalPrototype, but using o["foo"] access
// instead of o.foo.
function TestRemovingPropertyFromGlobalPrototype2() {
let foo_func_called = 0;
let bar_func_called = 0;
let name = "func";
function Foo() {}
Foo.prototype[name] = function() { ++foo_func_called; }
this.__proto__ = Foo.prototype;
function Bar() {}
Bar.prototype = this;
Bar.prototype[name] = function() { ++bar_func_called; }
let o = new Bar();
for (let i = 0; i < 11; ++i) {
// First, the property is looked up from Bar.
o[name]();
// Remove the property from Bar which is a Global-mode prototype between
// o and Foo. In the next iteration, it's looked up from Foo.
if (i == 9) {
delete Bar.prototype[name];
}
}
assertEquals(1, foo_func_called);
assertEquals(10, bar_func_called);
}
TestRemovingPropertyFromGlobalPrototype2();
function TestAddingPropertyToGlobalPrototype_MonomorphicDot() {
function DoMonomorphicStoreToPrototypeDot(p, f, do_delete=true) {
p.func = f;
if (do_delete) {
delete p.func;
}
}
let foo_func_called = 0;
let bar_func_called = 0;
function Foo() {}
Foo.prototype.func = function() { ++foo_func_called; }
delete this.func;
this.__proto__ = Foo.prototype;
function Bar() {}
Bar.prototype = this;
function bar_func() {
++bar_func_called;
}
DoMonomorphicStoreToPrototypeDot(Bar.prototype, bar_func);
DoMonomorphicStoreToPrototypeDot(Bar.prototype, bar_func);
DoMonomorphicStoreToPrototypeDot(Bar.prototype, bar_func);
let o = new Bar();
for (let i = 0; i < 11; ++i) {
// First, the property is looked up from Foo.
o.func();
// Add the property to Bar which is a Global-mode prototype between o
// and Foo. In the next iteration, it's looked up from Bar.
if (i == 9) {
DoMonomorphicStoreToPrototypeDot(Bar.prototype, bar_func, false);
}
}
assertEquals(10, foo_func_called);
assertEquals(1, bar_func_called);
}
TestAddingPropertyToGlobalPrototype_MonomorphicDot();
function TestAddingPropertyToGlobalPrototype_MonomorphicBrackets() {
function DoMonomorphicStoreToPrototypeBrackets(p, name, f, do_delete=true) {
p[name] = f;
if (do_delete) {
delete p[name];
}
}
let foo_func_called = 0;
let bar_func_called = 0;
let name = "func";
function Foo() {}
Foo.prototype[name] = function() { ++foo_func_called; }
delete this[name];
this.__proto__ = Foo.prototype;
function Bar() {}
Bar.prototype = this;
function bar_func() {
++bar_func_called;
}
DoMonomorphicStoreToPrototypeBrackets(Bar.prototype, name, bar_func);
DoMonomorphicStoreToPrototypeBrackets(Bar.prototype, name, bar_func);
DoMonomorphicStoreToPrototypeBrackets(Bar.prototype, name, bar_func);
let o = new Bar();
for (let i = 0; i < 11; ++i) {
// First, the property is looked up from Foo.
o.func();
// Add the property to Bar which is a Global-mode prototype between o
// and Foo. In the next iteration, it's looked up from Bar.
if (i == 9) {
DoMonomorphicStoreToPrototypeBrackets(Bar.prototype, name, bar_func, false);
}
}
assertEquals(10, foo_func_called);
assertEquals(1, bar_func_called);
}
TestAddingPropertyToGlobalPrototype_MonomorphicBrackets();
function TestReconfiguringDataToAccessor() {
let setter_called = 0;
let name = "prop";
delete this[name];
this.__proto__ = Object.prototype;
function Bar() {}
Bar.prototype = this;
Object.defineProperty(Bar.prototype, name, {value: 1000, writable: true, configurable: true});
for (let i = 0; i < 11; ++i) {
let obj1 = new Bar();
if (i < 10) {
assertEquals(1000, obj1.prop);
} else {
assertEquals(3000, obj1.prop);
}
// Add the property into the object.
obj1.prop = 2000;
if (i < 10) {
assertEquals(2000, obj1.prop);
} else {
assertEquals(3000, obj1.prop);
}
// Make "prop" an accessor property in the prototype.
if (i == 9) {
Object.defineProperty(Bar.prototype, name,
{get: () => 3000,
set: function(val) { ++setter_called; }});
}
}
assertEquals(1, setter_called);
}
TestReconfiguringDataToAccessor();