Allow immutable prototype templates to inherit

To enable the global object prototype chain to be frozen, all objects
in the chain need to be marked as immutable prototype exotic objects.
However, a bug in the previous implementation of immutable prototype
exotic objects left the check in place when initially setting up the
object, which made it impossible to allow inheritance chains. This
patch removes that mistaken check.

BUG=v8:5149

Review-Url: https://codereview.chromium.org/2449163004
Cr-Commit-Position: refs/heads/master@{#40702}
This commit is contained in:
littledan 2016-11-02 06:59:05 -07:00 committed by Commit bot
parent 5ce9760672
commit baf0ec31ec
2 changed files with 39 additions and 3 deletions

View File

@ -437,9 +437,7 @@ MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
JSObject::GetProperty(parent_instance, JSObject::GetProperty(parent_instance,
isolate->factory()->prototype_string()), isolate->factory()->prototype_string()),
JSFunction); JSFunction);
MAYBE_RETURN(JSObject::SetPrototype(prototype, parent_prototype, false, JSObject::ForceSetPrototype(prototype, parent_prototype);
Object::THROW_ON_ERROR),
MaybeHandle<JSFunction>());
} }
} }
Handle<JSFunction> function = ApiNatives::CreateApiFunction( Handle<JSFunction> function = ApiNatives::CreateApiFunction(

View File

@ -25939,3 +25939,41 @@ TEST(EvalInAccessCheckedContext) {
CHECK_EQ(42, x_value->Int32Value(context1).FromJust()); CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
context1->Exit(); context1->Exit();
} }
THREADED_TEST(ImmutableProtoWithParent) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
v8::HandleScope handle_scope(isolate);
Local<v8::FunctionTemplate> parent = v8::FunctionTemplate::New(isolate);
Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
templ->Inherit(parent);
templ->PrototypeTemplate()->SetImmutableProto();
Local<v8::Function> function =
templ->GetFunction(context.local()).ToLocalChecked();
Local<v8::Object> instance =
function->NewInstance(context.local()).ToLocalChecked();
Local<v8::Object> prototype =
instance->Get(context.local(), v8_str("__proto__"))
.ToLocalChecked()
->ToObject(context.local())
.ToLocalChecked();
// Look up the prototype
Local<v8::Value> original_proto =
prototype->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
// Setting the prototype (e.g., to null) throws
CHECK(
prototype->SetPrototype(context.local(), v8::Null(isolate)).IsNothing());
// The original prototype is still there
Local<Value> new_proto =
prototype->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
CHECK(new_proto->IsObject());
CHECK(new_proto.As<v8::Object>()
->Equals(context.local(), original_proto)
.FromJust());
}