0ff7b4830c
This patch implements "immutable prototype exotic objects" from the ECMAScript spec, which are objects whose __proto__ cannot be changed, but are not otherwise frozen. They are introduced in order to prevent a Proxy from being introduced to the prototype chain of the global object. The API is extended by a SetImmutablePrototype() call in ObjectTemplate, which can be used to vend new immutable prototype objects. Additionally, Object.prototype is an immutable prototype object. In the implementation, a new bit is added to Maps to say whether the prototype is immutable, which is read by SetPrototype. Map transitions to the immutable prototype state are not saved in the transition tree because the main use case is just for the prototype chain of the global object, which there will be only one of per Context, so no need to take up the extra word for a pointer in each full transition tree. BUG=v8:5149 Review-Url: https://codereview.chromium.org/2108203002 Cr-Commit-Position: refs/heads/master@{#37482}
40 lines
1.1 KiB
JavaScript
40 lines
1.1 KiB
JavaScript
// Copyright 2015 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.
|
|
|
|
function Receiver() { this.receiver = "receiver"; }
|
|
function Proto() { this.proto = "proto"; }
|
|
|
|
function f(a) {
|
|
return a.foo;
|
|
}
|
|
|
|
var rec = new Receiver();
|
|
|
|
// Formerly, this mutated rec.__proto__.__proto__, but
|
|
// the global object prototype chain is now immutable;
|
|
// not sure if this test now hits the original hazard case.
|
|
var proto = rec.__proto__;
|
|
|
|
// Initialize prototype chain dependent IC (nonexistent load).
|
|
assertEquals(undefined, f(rec));
|
|
assertEquals(undefined, f(rec));
|
|
|
|
// Add a new prototype to the end of the chain.
|
|
var p2 = new Proto();
|
|
p2.__proto__ = null;
|
|
proto.__proto__ = p2;
|
|
|
|
// Update the IC.
|
|
assertEquals(undefined, f(rec));
|
|
|
|
// Now modify the most recently added prototype by adding a property...
|
|
p2.foo = "bar";
|
|
assertEquals("bar", f(rec));
|
|
|
|
// ...and removing it again. Due to missing prototype user registrations,
|
|
// this fails to invalidate the IC.
|
|
delete p2.foo;
|
|
p2.secret = "GAME OVER";
|
|
assertEquals(undefined, f(rec));
|