[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}
This commit is contained in:
parent
a814516a08
commit
629d275073
@ -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.
|
||||
|
83
test/mjsunit/strong/object-set-prototype.js
Normal file
83
test/mjsunit/strong/object-set-prototype.js
Normal file
@ -0,0 +1,83 @@
|
||||
// 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();
|
Loading…
Reference in New Issue
Block a user