[strong] Implement per-object restrictions behaviour of property freezing
Implements the strong mode proposal's restrictions on changing a strong object's writable, non-configurable property to non-writable. Setting the strong bit is still wip, so this change will only affect those objects that have the bit correctly set. The tests reflect this, and will be expanded as more objects can be marked as strong. BUG=v8:3956 LOG=N Review URL: https://codereview.chromium.org/1142393003 Cr-Commit-Position: refs/heads/master@{#28698}
This commit is contained in:
parent
9058ac3be1
commit
6edc3e3179
@ -227,8 +227,12 @@ class CallSite {
|
||||
T(StrongArity, \
|
||||
"In strong mode, calling a function with too few arguments is deprecated") \
|
||||
T(StrongImplicitCast, "In strong mode, implicit conversions are deprecated") \
|
||||
T(StrongRedefineDisallowed, \
|
||||
"Cannot redefine non-configurable property '%' of strong object % to be " \
|
||||
"non-writable") \
|
||||
T(StrongSetProto, \
|
||||
"On strong object %, redefining the internal prototype is deprecated") \
|
||||
"On strong object %, redefining writable, non-configurable property '%' " \
|
||||
"to be non-writable is deprecated") \
|
||||
T(SymbolKeyFor, "% is not a symbol") \
|
||||
T(SymbolToPrimitive, \
|
||||
"Cannot convert a Symbol wrapper object to a primitive value") \
|
||||
|
@ -682,14 +682,19 @@ function DefineObjectProperty(obj, p, desc, should_throw) {
|
||||
}
|
||||
// Step 10a
|
||||
if (IsDataDescriptor(current) && IsDataDescriptor(desc)) {
|
||||
if (!current.isWritable() && desc.isWritable()) {
|
||||
if (should_throw) {
|
||||
throw MakeTypeError(kRedefineDisallowed, p);
|
||||
} else {
|
||||
return false;
|
||||
var currentIsWritable = current.isWritable();
|
||||
if (currentIsWritable != desc.isWritable()) {
|
||||
if (!currentIsWritable || IS_STRONG(obj)) {
|
||||
if (should_throw) {
|
||||
throw currentIsWritable
|
||||
? MakeTypeError(kStrongRedefineDisallowed, obj, p)
|
||||
: MakeTypeError(kRedefineDisallowed, p);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!current.isWritable() && desc.hasValue() &&
|
||||
if (!currentIsWritable && desc.hasValue() &&
|
||||
!$sameValue(desc.getValue(), current.getValue())) {
|
||||
if (should_throw) {
|
||||
throw MakeTypeError(kRedefineDisallowed, p);
|
||||
@ -1223,7 +1228,10 @@ function ObjectSealJS(obj) {
|
||||
function ObjectFreezeJS(obj) {
|
||||
if (!IS_SPEC_OBJECT(obj)) return obj;
|
||||
var isProxy = %_IsJSProxy(obj);
|
||||
if (isProxy || %HasSloppyArgumentsElements(obj) || %IsObserved(obj)) {
|
||||
// TODO(conradw): Investigate modifying the fast path to accommodate strong
|
||||
// objects.
|
||||
if (isProxy || %HasSloppyArgumentsElements(obj) || %IsObserved(obj) ||
|
||||
IS_STRONG(obj)) {
|
||||
if (isProxy) {
|
||||
ProxyFix(obj);
|
||||
}
|
||||
|
75
test/mjsunit/strong/object-freeze-property.js
Normal file
75
test/mjsunit/strong/object-freeze-property.js
Normal file
@ -0,0 +1,75 @@
|
||||
// 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.
|
||||
|
||||
// Flags: --strong-mode --allow-natives-syntax
|
||||
|
||||
// TODO(conradw): Track implementation of strong bit for other objects, add
|
||||
// tests.
|
||||
|
||||
function getSloppyObjects() {
|
||||
return [(function(){}), ({})];
|
||||
}
|
||||
|
||||
function getStrictObjects() {
|
||||
"use strict";
|
||||
return [(function(){}), ({})];
|
||||
}
|
||||
|
||||
function getStrongObjects() {
|
||||
"use strong";
|
||||
// Strong functions can't have properties added to them.
|
||||
return [{}];
|
||||
}
|
||||
|
||||
(function testStrongObjectFreezePropValid() {
|
||||
"use strict";
|
||||
let strongObjects = getStrongObjects();
|
||||
|
||||
for (let o of strongObjects) {
|
||||
Object.defineProperty(o, "foo", { configurable: true, writable: true });
|
||||
assertDoesNotThrow(
|
||||
function() {
|
||||
"use strong";
|
||||
Object.defineProperty(o, "foo", {configurable: true, writable: false });
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
(function testStrongObjectFreezePropInvalid() {
|
||||
"use strict";
|
||||
let sloppyObjects = getSloppyObjects();
|
||||
let strictObjects = getStrictObjects();
|
||||
let strongObjects = getStrongObjects();
|
||||
let weakObjects = sloppyObjects.concat(strictObjects);
|
||||
|
||||
for (let o of weakObjects) {
|
||||
Object.defineProperty(o, "foo", { writable: true });
|
||||
assertDoesNotThrow(
|
||||
function() {
|
||||
"use strong";
|
||||
Object.defineProperty(o, "foo", { writable: false });
|
||||
});
|
||||
}
|
||||
for (let o of strongObjects) {
|
||||
function defProp(o) {
|
||||
Object.defineProperty(o, "foo", { writable: false });
|
||||
}
|
||||
function defProps(o) {
|
||||
Object.defineProperties(o, { "foo": { writable: false } });
|
||||
}
|
||||
function freezeProp(o) {
|
||||
Object.freeze(o);
|
||||
}
|
||||
Object.defineProperty(o, "foo", { writable: true });
|
||||
for (let func of [defProp, defProps, freezeProp]) {
|
||||
assertThrows(function(){func(o)}, TypeError);
|
||||
assertThrows(function(){func(o)}, TypeError);
|
||||
assertThrows(function(){func(o)}, TypeError);
|
||||
%OptimizeFunctionOnNextCall(func);
|
||||
assertThrows(function(){func(o)}, TypeError);
|
||||
%DeoptimizeFunction(func);
|
||||
assertThrows(function(){func(o)}, TypeError);
|
||||
}
|
||||
}
|
||||
})();
|
Loading…
Reference in New Issue
Block a user