diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-03-21 10:16:54 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-03-25 09:44:10 +0100 |
commit | c459d8ea5d402c702948c860d9497b2230ff7e8a (patch) | |
tree | 56c282fc4d40e5cb613b47cf7be3ea0526ed5b6f /deps/v8/test/cctest/test-serialize.cc | |
parent | e0bc5a7361b1d29c3ed034155fd779ce6f44fb13 (diff) | |
download | android-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.tar.gz android-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.tar.bz2 android-node-v8-c459d8ea5d402c702948c860d9497b2230ff7e8a.zip |
deps: update V8 to 5.7.492.69
PR-URL: https://github.com/nodejs/node/pull/11752
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Diffstat (limited to 'deps/v8/test/cctest/test-serialize.cc')
-rw-r--r-- | deps/v8/test/cctest/test-serialize.cc | 370 |
1 files changed, 308 insertions, 62 deletions
diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc index 1b5497f772..9644d09624 100644 --- a/deps/v8/test/cctest/test-serialize.cc +++ b/deps/v8/test/cctest/test-serialize.cc @@ -285,8 +285,9 @@ static void PartiallySerializeObject(Vector<const byte>* startup_blob_out, isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear); startup_serializer.SerializeStrongReferences(); - PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); - partial_serializer.Serialize(&raw_foo); + PartialSerializer partial_serializer(isolate, &startup_serializer, + v8::SerializeInternalFieldsCallback()); + partial_serializer.Serialize(&raw_foo, false); startup_serializer.SerializeWeakReferencesAndDeferred(); @@ -321,7 +322,9 @@ UNINITIALIZED_TEST(PartialSerializerObject) { { SnapshotData snapshot_data(partial_blob); Deserializer deserializer(&snapshot_data); - root = deserializer.DeserializePartial(isolate, global_proxy) + root = deserializer + .DeserializePartial(isolate, global_proxy, + v8::DeserializeInternalFieldsCallback()) .ToHandleChecked(); CHECK(root->IsString()); } @@ -330,7 +333,9 @@ UNINITIALIZED_TEST(PartialSerializerObject) { { SnapshotData snapshot_data(partial_blob); Deserializer deserializer(&snapshot_data); - root2 = deserializer.DeserializePartial(isolate, global_proxy) + root2 = deserializer + .DeserializePartial(isolate, global_proxy, + v8::DeserializeInternalFieldsCallback()) .ToHandleChecked(); CHECK(root2->IsString()); CHECK(root.is_identical_to(root2)); @@ -385,8 +390,9 @@ static void PartiallySerializeContext(Vector<const byte>* startup_blob_out, startup_serializer.SerializeStrongReferences(); SnapshotByteSink partial_sink; - PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); - partial_serializer.Serialize(&raw_context); + PartialSerializer partial_serializer(isolate, &startup_serializer, + v8::SerializeInternalFieldsCallback()); + partial_serializer.Serialize(&raw_context, false); startup_serializer.SerializeWeakReferencesAndDeferred(); SnapshotData startup_snapshot(&startup_serializer); @@ -419,7 +425,9 @@ UNINITIALIZED_TEST(PartialSerializerContext) { { SnapshotData snapshot_data(partial_blob); Deserializer deserializer(&snapshot_data); - root = deserializer.DeserializePartial(isolate, global_proxy) + root = deserializer + .DeserializePartial(isolate, global_proxy, + v8::DeserializeInternalFieldsCallback()) .ToHandleChecked(); CHECK(root->IsContext()); CHECK(Handle<Context>::cast(root)->global_proxy() == *global_proxy); @@ -429,7 +437,9 @@ UNINITIALIZED_TEST(PartialSerializerContext) { { SnapshotData snapshot_data(partial_blob); Deserializer deserializer(&snapshot_data); - root2 = deserializer.DeserializePartial(isolate, global_proxy) + root2 = deserializer + .DeserializePartial(isolate, global_proxy, + v8::DeserializeInternalFieldsCallback()) .ToHandleChecked(); CHECK(root2->IsContext()); CHECK(!root.is_identical_to(root2)); @@ -505,8 +515,9 @@ static void PartiallySerializeCustomContext( startup_serializer.SerializeStrongReferences(); SnapshotByteSink partial_sink; - PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); - partial_serializer.Serialize(&raw_context); + PartialSerializer partial_serializer(isolate, &startup_serializer, + v8::SerializeInternalFieldsCallback()); + partial_serializer.Serialize(&raw_context, false); startup_serializer.SerializeWeakReferencesAndDeferred(); SnapshotData startup_snapshot(&startup_serializer); @@ -539,7 +550,9 @@ UNINITIALIZED_TEST(PartialSerializerCustomContext) { { SnapshotData snapshot_data(partial_blob); Deserializer deserializer(&snapshot_data); - root = deserializer.DeserializePartial(isolate, global_proxy) + root = deserializer + .DeserializePartial(isolate, global_proxy, + v8::DeserializeInternalFieldsCallback()) .ToHandleChecked(); CHECK(root->IsContext()); Handle<Context> context = Handle<Context>::cast(root); @@ -1075,7 +1088,7 @@ TEST(CodeSerializerLargeCodeObject) { Vector<const uint8_t> source = ConstructSource(STATIC_CHAR_VECTOR("var j=1; if (j == 0) {"), STATIC_CHAR_VECTOR("for (let i of Object.prototype);"), - STATIC_CHAR_VECTOR("} j=7; j"), 1000); + STATIC_CHAR_VECTOR("} j=7; j"), 1050); Handle<String> source_str = isolate->factory()->NewStringFromOneByte(source).ToHandleChecked(); @@ -1771,7 +1784,6 @@ TEST(CodeSerializerEagerCompilationAndPreAge) { FLAG_serialize_toplevel = true; FLAG_serialize_age_code = true; FLAG_serialize_eager = true; - FLAG_min_preparse_length = 1; static const char* source = "function f() {" @@ -1807,10 +1819,10 @@ TEST(CodeSerializerEagerCompilationAndPreAge) { HandleScope i_scope(i_isolate); Handle<SharedFunctionInfo> toplevel = v8::Utils::OpenHandle(*unbound); Handle<Script> script(Script::cast(toplevel->script())); - WeakFixedArray::Iterator iterator(script->shared_function_infos()); // Every function has been pre-compiled from the code cache. int count = 0; - while (SharedFunctionInfo* shared = iterator.Next<SharedFunctionInfo>()) { + SharedFunctionInfo::ScriptIterator iterator(script); + while (SharedFunctionInfo* shared = iterator.Next()) { CHECK(shared->is_compiled()); CHECK_EQ(Code::kPreAgedCodeAge, shared->code()->GetAge()); count++; @@ -1821,6 +1833,7 @@ TEST(CodeSerializerEagerCompilationAndPreAge) { } TEST(Regress503552) { + if (!FLAG_incremental_marking) return; // Test that the code serializer can deal with weak cells that form a linked // list during incremental marking. CcTest::InitializeVM(); @@ -1962,19 +1975,19 @@ TEST(SnapshotCreatorMultipleContexts) { v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); CompileRun("var f = function() { return 1; }"); - CHECK_EQ(0u, creator.AddContext(context)); + creator.SetDefaultContext(context); } { v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); CompileRun("var f = function() { return 2; }"); - CHECK_EQ(1u, creator.AddContext(context)); + CHECK_EQ(0u, creator.AddContext(context)); } { v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate); - CHECK_EQ(2u, creator.AddContext(context)); + CHECK_EQ(1u, creator.AddContext(context)); } blob = creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); @@ -1988,22 +2001,21 @@ TEST(SnapshotCreatorMultipleContexts) { v8::Isolate::Scope isolate_scope(isolate); { v8::HandleScope handle_scope(isolate); - v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); + v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); ExpectInt32("f()", 1); } { v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 1).ToLocalChecked(); + v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); v8::Context::Scope context_scope(context); ExpectInt32("f()", 2); } { v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 2).ToLocalChecked(); + v8::Context::FromSnapshot(isolate, 1).ToLocalChecked(); v8::Context::Scope context_scope(context); ExpectUndefined("this.f"); } @@ -2013,24 +2025,68 @@ TEST(SnapshotCreatorMultipleContexts) { delete[] blob.data; } -void SerializedCallback(const v8::FunctionCallbackInfo<v8::Value>& args) { +static void SerializedCallback( + const v8::FunctionCallbackInfo<v8::Value>& args) { args.GetReturnValue().Set(v8_num(42)); } -void SerializedCallbackReplacement( +static void SerializedCallbackReplacement( const v8::FunctionCallbackInfo<v8::Value>& args) { args.GetReturnValue().Set(v8_num(1337)); } +static void NamedPropertyGetterForSerialization( + v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { + if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x")) + .FromJust()) { + info.GetReturnValue().Set(v8_num(2016)); + } +} + +static void AccessorForSerialization( + v8::Local<v8::String> property, + const v8::PropertyCallbackInfo<v8::Value>& info) { + info.GetReturnValue().Set(v8_num(2017)); +} + static int serialized_static_field = 314; +class SerializedExtension : public v8::Extension { + public: + SerializedExtension() + : v8::Extension("serialized extension", + "native function g();" + "function h() { return 13; };" + "function i() { return 14; };" + "var o = { p: 7 };") {} + + virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate( + v8::Isolate* isolate, v8::Local<v8::String> name) { + CHECK(name->Equals(isolate->GetCurrentContext(), v8_str("g")).FromJust()); + return v8::FunctionTemplate::New(isolate, FunctionCallback); + } + + static void FunctionCallback( + const v8::FunctionCallbackInfo<v8::Value>& args) { + args.GetReturnValue().Set(v8_num(12)); + } +}; + intptr_t original_external_references[] = { reinterpret_cast<intptr_t>(SerializedCallback), - reinterpret_cast<intptr_t>(&serialized_static_field), 0}; + reinterpret_cast<intptr_t>(&serialized_static_field), + reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization), + reinterpret_cast<intptr_t>(&AccessorForSerialization), + reinterpret_cast<intptr_t>(&SerializedExtension::FunctionCallback), + 0}; intptr_t replaced_external_references[] = { reinterpret_cast<intptr_t>(SerializedCallbackReplacement), - reinterpret_cast<intptr_t>(&serialized_static_field), 0}; + reinterpret_cast<intptr_t>(&serialized_static_field), + reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization), + reinterpret_cast<intptr_t>(&AccessorForSerialization), + reinterpret_cast<intptr_t>(&SerializedExtension::FunctionCallback), + 0}; TEST(SnapshotCreatorExternalReferences) { DisableAlwaysOpt(); @@ -2048,7 +2104,7 @@ TEST(SnapshotCreatorExternalReferences) { callback->GetFunction(context).ToLocalChecked(); CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust()); ExpectInt32("f()", 42); - CHECK_EQ(0u, creator.AddContext(context)); + creator.SetDefaultContext(context); } blob = creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); @@ -2064,8 +2120,7 @@ TEST(SnapshotCreatorExternalReferences) { { v8::Isolate::Scope isolate_scope(isolate); v8::HandleScope handle_scope(isolate); - v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); + v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); ExpectInt32("f()", 42); } @@ -2082,8 +2137,7 @@ TEST(SnapshotCreatorExternalReferences) { { v8::Isolate::Scope isolate_scope(isolate); v8::HandleScope handle_scope(isolate); - v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); + v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); ExpectInt32("f()", 1337); } @@ -2108,7 +2162,7 @@ TEST(SnapshotCreatorUnknownExternalReferences) { CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust()); ExpectInt32("f()", 42); - CHECK_EQ(0u, creator.AddContext(context)); + creator.SetDefaultContext(context); } v8::StartupData blob = creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); @@ -2120,22 +2174,27 @@ struct InternalFieldData { uint32_t data; }; -v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, - int index) { - InternalFieldData* data = static_cast<InternalFieldData*>( +v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index, + void* data) { + CHECK_EQ(reinterpret_cast<void*>(2016), data); + InternalFieldData* internal_field = static_cast<InternalFieldData*>( holder->GetAlignedPointerFromInternalField(index)); - int size = sizeof(*data); + int size = sizeof(*internal_field); char* payload = new char[size]; // We simply use memcpy to serialize the content. - memcpy(payload, data, size); + memcpy(payload, internal_field, size); return {payload, size}; } +std::vector<InternalFieldData*> deserialized_data; + void DeserializeInternalFields(v8::Local<v8::Object> holder, int index, - v8::StartupData payload) { - InternalFieldData* data = new InternalFieldData{0}; - memcpy(data, payload.data, payload.raw_size); - holder->SetAlignedPointerInInternalField(index, data); + v8::StartupData payload, void* data) { + CHECK_EQ(reinterpret_cast<void*>(2017), data); + InternalFieldData* internal_field = new InternalFieldData{0}; + memcpy(internal_field, payload.data, payload.raw_size); + holder->SetAlignedPointerInInternalField(index, internal_field); + deserialized_data.push_back(internal_field); } TEST(SnapshotCreatorTemplates) { @@ -2159,6 +2218,8 @@ TEST(SnapshotCreatorTemplates) { global_template->Set(v8_str("f"), callback); v8::Local<v8::Context> context = v8::Context::New(isolate, no_extension, global_template); + creator.SetDefaultContext(context); + context = v8::Context::New(isolate, no_extension, global_template); v8::Local<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate); object_template->SetInternalFieldCount(3); @@ -2185,12 +2246,15 @@ TEST(SnapshotCreatorTemplates) { c->SetInternalField(2, field_external); CHECK(context->Global()->Set(context, v8_str("a"), a).FromJust()); - CHECK_EQ(0u, creator.AddContext(context)); + CHECK_EQ(0u, + creator.AddContext(context, v8::SerializeInternalFieldsCallback( + SerializeInternalFields, + reinterpret_cast<void*>(2016)))); CHECK_EQ(0u, creator.AddTemplate(callback)); CHECK_EQ(1u, creator.AddTemplate(global_template)); } - blob = creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear, - SerializeInternalFields); + blob = + creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); delete a1; delete b0; @@ -2202,7 +2266,6 @@ TEST(SnapshotCreatorTemplates) { params.snapshot_blob = &blob; params.array_buffer_allocator = CcTest::array_buffer_allocator(); params.external_references = original_external_references; - params.deserialize_internal_fields_callback = DeserializeInternalFields; v8::Isolate* isolate = v8::Isolate::New(params); { v8::Isolate::Scope isolate_scope(isolate); @@ -2210,7 +2273,11 @@ TEST(SnapshotCreatorTemplates) { // Create a new context without a new object template. v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); + v8::Context::FromSnapshot( + isolate, 0, + v8::DeserializeInternalFieldsCallback( + DeserializeInternalFields, reinterpret_cast<void*>(2017))) + .ToLocalChecked(); v8::Context::Scope context_scope(context); ExpectInt32("f()", 42); @@ -2272,29 +2339,208 @@ TEST(SnapshotCreatorTemplates) { // Accessing out of bound returns empty MaybeHandle. CHECK(v8::ObjectTemplate::FromSnapshot(isolate, 2).IsEmpty()); CHECK(v8::FunctionTemplate::FromSnapshot(isolate, 2).IsEmpty()); - CHECK(v8::Context::FromSnapshot(isolate, 2).IsEmpty()); + CHECK(v8::Context::FromSnapshot(isolate, 1).IsEmpty()); - delete a1; - delete b0; - delete c0; + for (auto data : deserialized_data) delete data; + deserialized_data.clear(); } + } + isolate->Dispose(); + } + delete[] blob.data; +} + +TEST(SnapshotCreatorIncludeGlobalProxy) { + DisableAlwaysOpt(); + v8::StartupData blob; + + { + v8::SnapshotCreator creator(original_external_references); + v8::Isolate* isolate = creator.GetIsolate(); + v8::RegisterExtension(new SerializedExtension); + const char* extension_names[] = {"serialized extension"}; + v8::ExtensionConfiguration extensions(1, extension_names); + { + // Set default context. This context implicitly does *not* serialize + // the global proxy, and upon deserialization one has to be created + // in the bootstrapper from the global object template. + // Side effects from extensions are persisted though. + v8::HandleScope handle_scope(isolate); + v8::Local<v8::ObjectTemplate> global_template = + v8::ObjectTemplate::New(isolate); + v8::Local<v8::FunctionTemplate> callback = + v8::FunctionTemplate::New(isolate, SerializedCallback); + global_template->Set(v8_str("f"), callback); + global_template->SetHandler(v8::NamedPropertyHandlerConfiguration( + NamedPropertyGetterForSerialization)); + v8::Local<v8::Context> context = + v8::Context::New(isolate, &extensions, global_template); + v8::Context::Scope context_scope(context); + ExpectInt32("f()", 42); + ExpectInt32("g()", 12); + ExpectInt32("h()", 13); + ExpectInt32("o.p", 7); + ExpectInt32("x", 2016); + creator.SetDefaultContext(context); + } + { + // Add additional context. This context implicitly *does* serialize + // the global proxy, and upon deserialization one has to be created + // in the bootstrapper from the global object template. + // Side effects from extensions are persisted. + v8::HandleScope handle_scope(isolate); + v8::Local<v8::ObjectTemplate> global_template = + v8::ObjectTemplate::New(isolate); + v8::Local<v8::FunctionTemplate> callback = + v8::FunctionTemplate::New(isolate, SerializedCallback); + global_template->SetInternalFieldCount(3); + global_template->Set(v8_str("f"), callback); + global_template->SetHandler(v8::NamedPropertyHandlerConfiguration( + NamedPropertyGetterForSerialization)); + global_template->SetAccessor(v8_str("y"), AccessorForSerialization); + v8::Local<v8::Private> priv = + v8::Private::ForApi(isolate, v8_str("cached")); + global_template->SetAccessorProperty( + v8_str("cached"), + v8::FunctionTemplate::NewWithCache(isolate, SerializedCallback, priv, + v8::Local<v8::Value>())); + v8::Local<v8::Context> context = + v8::Context::New(isolate, &extensions, global_template); + v8::Context::Scope context_scope(context); + + CHECK(context->Global() + ->SetPrivate(context, priv, v8_str("cached string")) + .FromJust()); + v8::Local<v8::Private> hidden = + v8::Private::ForApi(isolate, v8_str("hidden")); + CHECK(context->Global() + ->SetPrivate(context, hidden, v8_str("hidden string")) + .FromJust()); + ExpectInt32("f()", 42); + ExpectInt32("g()", 12); + ExpectInt32("h()", 13); + ExpectInt32("o.p", 7); + ExpectInt32("x", 2016); + ExpectInt32("y", 2017); + CHECK(v8_str("hidden string") + ->Equals(context, context->Global() + ->GetPrivate(context, hidden) + .ToLocalChecked()) + .FromJust()); + + CHECK_EQ(0u, + creator.AddContext(context, v8::SerializeInternalFieldsCallback( + SerializeInternalFields, + reinterpret_cast<void*>(2016)))); + } + blob = + creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); + } + + { + v8::Isolate::CreateParams params; + params.snapshot_blob = &blob; + params.array_buffer_allocator = CcTest::array_buffer_allocator(); + params.external_references = original_external_references; + v8::Isolate* isolate = v8::Isolate::New(params); + { + v8::Isolate::Scope isolate_scope(isolate); + // We can introduce new extensions, which could override the already + // snapshotted extension. + v8::Extension* extension = new v8::Extension("new extension", + "function i() { return 24; }" + "function j() { return 25; }" + "if (o.p == 7) o.p++;"); + extension->set_auto_enable(true); + v8::RegisterExtension(extension); { - // Create a context with a new object template. It is merged into the - // deserialized global object. + // Create a new context from default context snapshot. This will + // create a new global object from a new global object template + // without the interceptor. v8::HandleScope handle_scope(isolate); - v8::ExtensionConfiguration* no_extension = nullptr; - v8::Local<v8::ObjectTemplate> global_template = - v8::ObjectTemplate::New(isolate); - global_template->Set( - v8_str("g"), - v8::FunctionTemplate::New(isolate, SerializedCallbackReplacement)); - v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 0, no_extension, global_template) - .ToLocalChecked(); + v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); - ExpectInt32("g()", 1337); ExpectInt32("f()", 42); + ExpectInt32("g()", 12); + ExpectInt32("h()", 13); + ExpectInt32("i()", 24); + ExpectInt32("j()", 25); + ExpectInt32("o.p", 8); + v8::TryCatch try_catch(isolate); + CHECK(CompileRun("x").IsEmpty()); + CHECK(try_catch.HasCaught()); + } + { + // Create a new context from first additional context snapshot. This + // will use the global object from the snapshot, including interceptor. + v8::HandleScope handle_scope(isolate); + v8::Local<v8::Context> context = + v8::Context::FromSnapshot( + isolate, 0, + v8::DeserializeInternalFieldsCallback( + DeserializeInternalFields, reinterpret_cast<void*>(2017))) + .ToLocalChecked(); + + { + v8::Context::Scope context_scope(context); + ExpectInt32("f()", 42); + ExpectInt32("g()", 12); + ExpectInt32("h()", 13); + ExpectInt32("i()", 24); + ExpectInt32("j()", 25); + ExpectInt32("o.p", 8); + ExpectInt32("x", 2016); + v8::Local<v8::Private> hidden = + v8::Private::ForApi(isolate, v8_str("hidden")); + CHECK(v8_str("hidden string") + ->Equals(context, context->Global() + ->GetPrivate(context, hidden) + .ToLocalChecked()) + .FromJust()); + ExpectString("cached", "cached string"); + } + + v8::Local<v8::Object> global = context->Global(); + CHECK_EQ(3, global->InternalFieldCount()); + context->DetachGlobal(); + + // New context, but reuse global proxy. + v8::ExtensionConfiguration* no_extensions = nullptr; + v8::Local<v8::Context> context2 = + v8::Context::FromSnapshot( + isolate, 0, + v8::DeserializeInternalFieldsCallback( + DeserializeInternalFields, reinterpret_cast<void*>(2017)), + no_extensions, global) + .ToLocalChecked(); + { + v8::Context::Scope context_scope(context2); + ExpectInt32("f()", 42); + ExpectInt32("g()", 12); + ExpectInt32("h()", 13); + ExpectInt32("i()", 24); + ExpectInt32("j()", 25); + ExpectInt32("o.p", 8); + ExpectInt32("x", 2016); + v8::Local<v8::Private> hidden = + v8::Private::ForApi(isolate, v8_str("hidden")); + CHECK(v8_str("hidden string") + ->Equals(context2, context2->Global() + ->GetPrivate(context2, hidden) + .ToLocalChecked()) + .FromJust()); + + // Set cached accessor property again. + v8::Local<v8::Private> priv = + v8::Private::ForApi(isolate, v8_str("cached")); + CHECK(context2->Global() + ->SetPrivate(context2, priv, v8_str("cached string 1")) + .FromJust()); + ExpectString("cached", "cached string 1"); + } + + CHECK(context2->Global()->Equals(context2, global).FromJust()); } } isolate->Dispose(); |