From 05c199ce70245b4059608575db6f0d9beb8afba3 Mon Sep 17 00:00:00 2001 From: jameslahm Date: Mon, 14 Feb 2022 16:58:10 +0800 Subject: [PATCH] [bootstrapper] copy accessors in deserialized global into global object created using global proxy template Originally, the accessors wont be copied into global object from deserialized global. And the accessors in serialized global object will be lost. Fix to copy accessors in deserialized global into global object when recreating new global object using passed global proxy template. Tests credited to xiangyangemail@gmail.com https://chromium-review.googlesource.com/c/v8/v8/+/3405405 Bug: v8:12564 Change-Id: Iefb3a6dbfa5445b227d87c26eb423cf1b924dbb4 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3459937 Reviewed-by: Jakob Kummerow Reviewed-by: Toon Verwaest Commit-Queue: Jakob Gruber Cr-Commit-Position: refs/heads/main@{#79087} --- src/init/bootstrapper.cc | 15 +++++++++++---- test/cctest/test-serialize.cc | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc index 602e8083a4..318afc569e 100644 --- a/src/init/bootstrapper.cc +++ b/src/init/bootstrapper.cc @@ -6011,8 +6011,15 @@ void Genesis::TransferNamedProperties(Handle from, Handle value(cell->value(), isolate()); if (value->IsTheHole(isolate())) continue; PropertyDetails details = cell->property_details(); - if (details.kind() != PropertyKind::kData) continue; - JSObject::AddProperty(isolate(), to, key, value, details.attributes()); + if (details.kind() == PropertyKind::kData) { + JSObject::AddProperty(isolate(), to, key, value, details.attributes()); + } else { + DCHECK_EQ(PropertyKind::kAccessor, details.kind()); + DCHECK(!to->HasFastProperties()); + PropertyDetails d(PropertyKind::kAccessor, details.attributes(), + PropertyCellType::kMutable); + JSObject::SetNormalizedProperty(to, key, value, d); + } } } else if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) { @@ -6186,8 +6193,8 @@ Genesis::Genesis( // If no global proxy template was passed in, simply use the global in the // snapshot. If a global proxy template was passed in it's used to recreate - // the global object and its protype chain, and the data properties from the - // deserialized global are copied onto it. + // the global object and its prototype chain, and the data and the accessor + // properties from the deserialized global are copied onto it. if (context_snapshot_index == 0 && !global_proxy_template.IsEmpty()) { Handle global_object = CreateNewGlobals(global_proxy_template, global_proxy); diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc index e187d8da7b..3b66af0727 100644 --- a/test/cctest/test-serialize.cc +++ b/test/cctest/test-serialize.cc @@ -3835,6 +3835,39 @@ UNINITIALIZED_TEST(SnapshotAccessorDescriptors) { delete[] data1.data; } +UNINITIALIZED_TEST(SnapshotObjectDefinePropertyWhenNewGlobalTemplate) { + const char* source1 = + "Object.defineProperty(this, 'property1', {\n" + " value: 42,\n" + " writable: false\n" + "});\n" + "var bValue = 38;\n" + "Object.defineProperty(this, 'property2', {\n" + " get() { return bValue; },\n" + " set(newValue) { bValue = newValue; }\n" + "});"; + v8::StartupData data1 = CreateSnapshotDataBlob(source1); + + v8::Isolate::CreateParams params1; + params1.snapshot_blob = &data1; + params1.array_buffer_allocator = CcTest::array_buffer_allocator(); + + v8::Isolate* isolate1 = v8::Isolate::New(params1); + { + v8::Isolate::Scope i_scope(isolate1); + v8::HandleScope h_scope(isolate1); + v8::Local global_template = + v8::ObjectTemplate::New(isolate1); + v8::Local context = + v8::Context::New(isolate1, nullptr, global_template); + v8::Context::Scope c_scope(context); + ExpectInt32("this.property1", 42); + ExpectInt32("this.property2", 38); + } + isolate1->Dispose(); + delete[] data1.data; +} + UNINITIALIZED_TEST(SnapshotCreatorIncludeGlobalProxy) { DisableAlwaysOpt(); DisableEmbeddedBlobRefcounting();