Index: test/cctest/test-serialize.cc |
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc |
index 95b8ddebf3e857bba3af09053494c16e7551397a..628f0fbdbe25633f7df194e86e25ded5e5401224 100644 |
--- a/test/cctest/test-serialize.cc |
+++ b/test/cctest/test-serialize.cc |
@@ -287,7 +287,7 @@ static void PartiallySerializeObject(Vector<const byte>* startup_blob_out, |
isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear); |
startup_serializer.SerializeStrongReferences(); |
- PartialSerializer partial_serializer(isolate, &startup_serializer); |
+ PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); |
partial_serializer.Serialize(&raw_foo); |
startup_serializer.SerializeWeakReferencesAndDeferred(); |
@@ -387,7 +387,7 @@ static void PartiallySerializeContext(Vector<const byte>* startup_blob_out, |
startup_serializer.SerializeStrongReferences(); |
SnapshotByteSink partial_sink; |
- PartialSerializer partial_serializer(isolate, &startup_serializer); |
+ PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); |
partial_serializer.Serialize(&raw_context); |
startup_serializer.SerializeWeakReferencesAndDeferred(); |
@@ -506,7 +506,7 @@ static void PartiallySerializeCustomContext( |
startup_serializer.SerializeStrongReferences(); |
SnapshotByteSink partial_sink; |
- PartialSerializer partial_serializer(isolate, &startup_serializer); |
+ PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); |
partial_serializer.Serialize(&raw_context); |
startup_serializer.SerializeWeakReferencesAndDeferred(); |
@@ -2109,10 +2109,38 @@ TEST(SnapshotCreatorUnknownExternalReferences) { |
delete[] blob.data; |
} |
+struct InternalFieldData { |
+ uint32_t data; |
+}; |
+ |
+v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, |
+ int index) { |
+ InternalFieldData* data = static_cast<InternalFieldData*>( |
+ holder->GetAlignedPointerFromInternalField(index)); |
+ int size = sizeof(*data); |
+ char* payload = new char[size]; |
+ // We simply use memcpy to serialize the content. |
+ memcpy(payload, data, size); |
+ return {payload, size}; |
+} |
+ |
+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); |
+} |
+ |
TEST(SnapshotCreatorTemplates) { |
DisableTurbofan(); |
v8::StartupData blob; |
+ |
{ |
+ InternalFieldData* a1 = new InternalFieldData{11}; |
+ InternalFieldData* b0 = new InternalFieldData{20}; |
+ InternalFieldData* c0 = new InternalFieldData{30}; |
+ InternalFieldData* c1 = new InternalFieldData{31}; |
+ |
v8::SnapshotCreator creator(original_external_references); |
v8::Isolate* isolate = creator.GetIsolate(); |
{ |
@@ -2125,14 +2153,38 @@ TEST(SnapshotCreatorTemplates) { |
global_template->Set(v8_str("f"), callback); |
v8::Local<v8::Context> context = |
v8::Context::New(isolate, no_extension, global_template); |
+ v8::Local<v8::ObjectTemplate> object_template = |
+ v8::ObjectTemplate::New(isolate); |
+ object_template->SetInternalFieldCount(2); |
+ |
v8::Context::Scope context_scope(context); |
ExpectInt32("f()", 42); |
+ |
+ v8::Local<v8::Object> a = |
+ object_template->NewInstance(context).ToLocalChecked(); |
+ v8::Local<v8::Object> b = |
+ object_template->NewInstance(context).ToLocalChecked(); |
+ v8::Local<v8::Object> c = |
+ object_template->NewInstance(context).ToLocalChecked(); |
+ a->SetInternalField(0, b); |
+ a->SetAlignedPointerInInternalField(1, a1); |
+ b->SetAlignedPointerInInternalField(0, b0); |
+ b->SetInternalField(1, c); |
+ c->SetAlignedPointerInInternalField(0, c0); |
+ c->SetAlignedPointerInInternalField(1, c1); |
+ CHECK(context->Global()->Set(context, v8_str("a"), a).FromJust()); |
+ |
CHECK_EQ(0, creator.AddContext(context)); |
CHECK_EQ(0, creator.AddTemplate(callback)); |
CHECK_EQ(1, creator.AddTemplate(global_template)); |
} |
- blob = |
- creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); |
+ blob = creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear, |
+ SerializeInternalFields); |
+ |
+ delete a1; |
+ delete b0; |
+ delete c1; |
+ delete c0; |
} |
{ |
@@ -2140,6 +2192,7 @@ 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); |
@@ -2173,10 +2226,39 @@ TEST(SnapshotCreatorTemplates) { |
// Check that it instantiates to the same prototype. |
ExpectTrue("g.prototype === f.prototype"); |
+ // Retrieve internal fields. |
+ v8::Local<v8::Object> a = context->Global() |
+ ->Get(context, v8_str("a")) |
+ .ToLocalChecked() |
+ ->ToObject(context) |
+ .ToLocalChecked(); |
+ v8::Local<v8::Object> b = |
+ a->GetInternalField(0)->ToObject(context).ToLocalChecked(); |
+ InternalFieldData* a1 = reinterpret_cast<InternalFieldData*>( |
+ a->GetAlignedPointerFromInternalField(1)); |
+ InternalFieldData* b0 = reinterpret_cast<InternalFieldData*>( |
+ b->GetAlignedPointerFromInternalField(0)); |
+ v8::Local<v8::Object> c = |
+ b->GetInternalField(1)->ToObject(context).ToLocalChecked(); |
+ InternalFieldData* c0 = reinterpret_cast<InternalFieldData*>( |
+ c->GetAlignedPointerFromInternalField(0)); |
+ InternalFieldData* c1 = reinterpret_cast<InternalFieldData*>( |
+ c->GetAlignedPointerFromInternalField(1)); |
+ |
+ CHECK_EQ(11, a1->data); |
+ CHECK_EQ(20, b0->data); |
+ CHECK_EQ(30, c0->data); |
+ CHECK_EQ(31, c1->data); |
+ |
// 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()); |
+ |
+ delete a1; |
+ delete b0; |
+ delete c1; |
+ delete c0; |
} |
{ |