diff --git a/src/env.cc b/src/env.cc index b9d25b1996c3eb..a0d087dd7922d6 100644 --- a/src/env.cc +++ b/src/env.cc @@ -1835,6 +1835,7 @@ void Environment::EnqueueDeserializeRequest(DeserializeRequestCallback cb, Local holder, int index, InternalFieldInfo* info) { + DCHECK_EQ(index, BaseObject::kEmbedderType); DeserializeRequest request{cb, {isolate(), holder}, index, info}; deserialize_requests_.push_back(std::move(request)); } diff --git a/src/node_blob.cc b/src/node_blob.cc index e1bf3be2b07b9e..0f3e0a28748e15 100644 --- a/src/node_blob.cc +++ b/src/node_blob.cc @@ -479,7 +479,7 @@ void BlobBindingData::PrepareForSerialization( } InternalFieldInfo* BlobBindingData::Serialize(int index) { - DCHECK_EQ(index, BaseObject::kSlot); + DCHECK_EQ(index, BaseObject::kEmbedderType); InternalFieldInfo* info = InternalFieldInfo::New(type()); return info; } diff --git a/src/node_file.cc b/src/node_file.cc index 5a3e54669049fb..1b6a4c97e52941 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -2433,7 +2433,7 @@ void BindingData::Deserialize(Local context, Local holder, int index, InternalFieldInfo* info) { - DCHECK_EQ(index, BaseObject::kSlot); + DCHECK_EQ(index, BaseObject::kEmbedderType); HandleScope scope(context->GetIsolate()); Environment* env = Environment::GetCurrent(context); BindingData* binding = env->AddBindingData(context, holder); @@ -2450,7 +2450,7 @@ void BindingData::PrepareForSerialization(Local context, } InternalFieldInfo* BindingData::Serialize(int index) { - DCHECK_EQ(index, BaseObject::kSlot); + DCHECK_EQ(index, BaseObject::kEmbedderType); InternalFieldInfo* info = InternalFieldInfo::New(type()); return info; } diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc index 350a7094baad59..b88ef11ded9e8e 100644 --- a/src/node_process_methods.cc +++ b/src/node_process_methods.cc @@ -531,7 +531,7 @@ void BindingData::PrepareForSerialization(Local context, } InternalFieldInfo* BindingData::Serialize(int index) { - DCHECK_EQ(index, BaseObject::kSlot); + DCHECK_EQ(index, BaseObject::kEmbedderType); InternalFieldInfo* info = InternalFieldInfo::New(type()); return info; } @@ -540,7 +540,7 @@ void BindingData::Deserialize(Local context, Local holder, int index, InternalFieldInfo* info) { - DCHECK_EQ(index, BaseObject::kSlot); + DCHECK_EQ(index, BaseObject::kEmbedderType); v8::HandleScope scope(context->GetIsolate()); Environment* env = Environment::GetCurrent(context); // Recreate the buffer in the constructor. diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index b71c46acabed72..c76a3fb382b299 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -380,10 +380,13 @@ void DeserializeNodeInternalFields(Local holder, return; } + DCHECK_EQ(index, BaseObject::kEmbedderType); Environment* env_ptr = static_cast(env); const InternalFieldInfo* info = reinterpret_cast(payload.data); - + // TODO(joyeecheung): we can add a constant kNodeEmbedderId to the + // beginning of every InternalFieldInfo to ensure that we don't + // step on payloads that were not serialized by Node.js. switch (info->type) { #define V(PropertyName, NativeTypeName) \ case EmbedderObjectType::k_##PropertyName: { \ @@ -408,13 +411,32 @@ StartupData SerializeNodeContextInternalFields(Local holder, "Serialize internal field, index=%d, holder=%p\n", static_cast(index), *holder); - void* ptr = holder->GetAlignedPointerFromInternalField(BaseObject::kSlot); - if (ptr == nullptr) { + // We only do one serialization for the kEmbedderType slot, the result + // contains everything necessary for deserializing the entire object, + // including the fields whose index is bigger than kEmbedderType + // (most importantly, BaseObject::kSlot). + // For Node.js this design is enough for all the native binding that are + // serializable. + if (index != BaseObject::kEmbedderType) { + return StartupData{nullptr, 0}; + } + + void* type_ptr = holder->GetAlignedPointerFromInternalField(index); + if (type_ptr == nullptr) { + return StartupData{nullptr, 0}; + } + + uint16_t type = *(static_cast(type_ptr)); + per_process::Debug(DebugCategory::MKSNAPSHOT, "type = 0x%x\n", type); + if (type != kNodeEmbedderId) { return StartupData{nullptr, 0}; } - DCHECK(static_cast(ptr)->is_snapshotable()); - SnapshotableObject* obj = static_cast(ptr); + void* binding_ptr = + holder->GetAlignedPointerFromInternalField(BaseObject::kSlot); + per_process::Debug(DebugCategory::MKSNAPSHOT, "binding = %p\n", binding_ptr); + DCHECK(static_cast(binding_ptr)->is_snapshotable()); + SnapshotableObject* obj = static_cast(binding_ptr); per_process::Debug(DebugCategory::MKSNAPSHOT, "Object %p is %s, ", *holder, @@ -434,8 +456,9 @@ void SerializeBindingData(Environment* env, env->ForEachBindingData([&](FastStringKey key, BaseObjectPtr binding) { per_process::Debug(DebugCategory::MKSNAPSHOT, - "Serialize binding %i, %p, type=%s\n", + "Serialize binding %i (%p), object=%p, type=%s\n", static_cast(i), + binding.get(), *(binding->object()), key.c_str()); diff --git a/src/node_snapshotable.h b/src/node_snapshotable.h index f0a8bce215e027..ec560b6d4fc633 100644 --- a/src/node_snapshotable.h +++ b/src/node_snapshotable.h @@ -30,11 +30,6 @@ enum class EmbedderObjectType : uint8_t { // When serializing an embedder object, we'll serialize the native states // into a chunk that can be mapped into a subclass of InternalFieldInfo, // and pass it into the V8 callback as the payload of StartupData. -// TODO(joyeecheung): the classification of types seem to be wrong. -// We'd need a type for each field of each class of native object. -// Maybe it's fine - we'll just use the type to invoke BaseObject constructors -// and specify that the BaseObject has only one field for us to serialize. -// And for non-BaseObject embedder objects, we'll use field-wise types. // The memory chunk looks like this: // // [ type ] - EmbedderObjectType (a uint8_t) diff --git a/src/node_v8.cc b/src/node_v8.cc index cf7a494b7c7230..f37fb09bf9f017 100644 --- a/src/node_v8.cc +++ b/src/node_v8.cc @@ -124,7 +124,7 @@ void BindingData::Deserialize(Local context, Local holder, int index, InternalFieldInfo* info) { - DCHECK_EQ(index, BaseObject::kSlot); + DCHECK_EQ(index, BaseObject::kEmbedderType); HandleScope scope(context->GetIsolate()); Environment* env = Environment::GetCurrent(context); BindingData* binding = env->AddBindingData(context, holder); @@ -132,7 +132,7 @@ void BindingData::Deserialize(Local context, } InternalFieldInfo* BindingData::Serialize(int index) { - DCHECK_EQ(index, BaseObject::kSlot); + DCHECK_EQ(index, BaseObject::kEmbedderType); InternalFieldInfo* info = InternalFieldInfo::New(type()); return info; }