Commit 629d2750 authored by conradw's avatar conradw Committed by Commit bot

[strong] Implement per-object restrictions behaviour for prototype setting

Implements the strong mode proposal's restrictions on the ability of user code
to modify the prototype of strong objects.

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/1143623002

Cr-Commit-Position: refs/heads/master@{#28664}
parent a814516a
......@@ -227,6 +227,8 @@ 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(StrongSetProto, \
"On strong object %, redefining the internal prototype is deprecated") \
T(SymbolKeyFor, "% is not a symbol") \
T(SymbolToPrimitive, \
"Cannot convert a Symbol wrapper object to a primitive value") \
......
......@@ -12618,6 +12618,13 @@ MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object,
#endif
Isolate* isolate = object->GetIsolate();
// Strong objects may not have their prototype set via __proto__ or
// setPrototypeOf.
if (from_javascript && object->map()->is_strong()) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongSetProto, object),
Object);
}
Heap* heap = isolate->heap();
// Silently ignore the change if value is not a JSObject or null.
// SpiderMonkey behaves this way.
......
// 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";
return [(function(){}), ({})];
}
function declareObjectLiteralWithProtoSloppy() {
return {__proto__: {}};
}
function declareObjectLiteralWithProtoStrong() {
"use strong";
return {__proto__: {}};
}
function testStrongObjectSetProto() {
"use strict";
let sloppyObjects = getSloppyObjects();
let strictObjects = getStrictObjects();
let strongObjects = getStrongObjects();
let weakObjects = sloppyObjects.concat(strictObjects);
for (let o of weakObjects) {
let setProtoBuiltin = function(o){Object.setPrototypeOf(o, {})};
let setProtoProperty = function(o){o.__proto__ = {}};
for (let setProtoFunc of [setProtoBuiltin, setProtoProperty]) {
assertDoesNotThrow(function(){setProtoFunc(o)});
assertDoesNotThrow(function(){setProtoFunc(o)});
assertDoesNotThrow(function(){setProtoFunc(o)});
%OptimizeFunctionOnNextCall(setProtoFunc);
assertDoesNotThrow(function(){setProtoFunc(o)});
%DeoptimizeFunction(setProtoFunc);
assertDoesNotThrow(function(){setProtoFunc(o)});
}
}
for (let o of strongObjects) {
let setProtoBuiltin = function(o){Object.setPrototypeOf(o, {})};
let setProtoProperty = function(o){o.__proto__ = {}};
for (let setProtoFunc of [setProtoBuiltin, setProtoProperty]) {
assertThrows(function(){setProtoFunc(o)}, TypeError);
assertThrows(function(){setProtoFunc(o)}, TypeError);
assertThrows(function(){setProtoFunc(o)}, TypeError);
%OptimizeFunctionOnNextCall(setProtoFunc);
assertThrows(function(){setProtoFunc(o)}, TypeError);
%DeoptimizeFunction(setProtoFunc);
assertThrows(function(){setProtoFunc(o)}, TypeError);
}
}
assertDoesNotThrow(declareObjectLiteralWithProtoSloppy);
assertDoesNotThrow(declareObjectLiteralWithProtoSloppy);
assertDoesNotThrow(declareObjectLiteralWithProtoSloppy);
%OptimizeFunctionOnNextCall(declareObjectLiteralWithProtoSloppy);
assertDoesNotThrow(declareObjectLiteralWithProtoSloppy);
%DeoptimizeFunction(declareObjectLiteralWithProtoSloppy);
assertDoesNotThrow(declareObjectLiteralWithProtoSloppy);
assertDoesNotThrow(declareObjectLiteralWithProtoStrong);
assertDoesNotThrow(declareObjectLiteralWithProtoStrong);
assertDoesNotThrow(declareObjectLiteralWithProtoStrong);
%OptimizeFunctionOnNextCall(declareObjectLiteralWithProtoStrong);
assertDoesNotThrow(declareObjectLiteralWithProtoStrong);
%DeoptimizeFunction(declareObjectLiteralWithProtoStrong);
assertDoesNotThrow(declareObjectLiteralWithProtoStrong);
}
testStrongObjectSetProto();
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