From baf0ec31ec8c16156f3808cc31fd980ac05b109a Mon Sep 17 00:00:00 2001 From: littledan Date: Wed, 2 Nov 2016 06:59:05 -0700 Subject: [PATCH] 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} --- src/api-natives.cc | 4 +--- test/cctest/test-api.cc | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/api-natives.cc b/src/api-natives.cc index a620b210a4..ab1b06256e 100644 --- a/src/api-natives.cc +++ b/src/api-natives.cc @@ -437,9 +437,7 @@ MaybeHandle InstantiateFunction(Isolate* isolate, JSObject::GetProperty(parent_instance, isolate->factory()->prototype_string()), JSFunction); - MAYBE_RETURN(JSObject::SetPrototype(prototype, parent_prototype, false, - Object::THROW_ON_ERROR), - MaybeHandle()); + JSObject::ForceSetPrototype(prototype, parent_prototype); } } Handle function = ApiNatives::CreateApiFunction( diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 72a32a5c9d..7abfa99de6 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -25939,3 +25939,41 @@ TEST(EvalInAccessCheckedContext) { CHECK_EQ(42, x_value->Int32Value(context1).FromJust()); context1->Exit(); } + +THREADED_TEST(ImmutableProtoWithParent) { + LocalContext context; + v8::Isolate* isolate = context->GetIsolate(); + v8::HandleScope handle_scope(isolate); + + Local parent = v8::FunctionTemplate::New(isolate); + + Local templ = v8::FunctionTemplate::New(isolate); + templ->Inherit(parent); + templ->PrototypeTemplate()->SetImmutableProto(); + + Local function = + templ->GetFunction(context.local()).ToLocalChecked(); + Local instance = + function->NewInstance(context.local()).ToLocalChecked(); + Local prototype = + instance->Get(context.local(), v8_str("__proto__")) + .ToLocalChecked() + ->ToObject(context.local()) + .ToLocalChecked(); + + // Look up the prototype + Local 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 new_proto = + prototype->Get(context.local(), v8_str("__proto__")).ToLocalChecked(); + CHECK(new_proto->IsObject()); + CHECK(new_proto.As() + ->Equals(context.local(), original_proto) + .FromJust()); +}