@@ -1107,25 +1107,33 @@ std::string SnapshotableObject::GetTypeName() const {
11071107void DeserializeNodeInternalFields (Local<Object> holder,
11081108 int index,
11091109 StartupData payload,
1110- void * env ) {
1110+ void * callback_data ) {
11111111 if (payload.raw_size == 0 ) {
1112- holder->SetAlignedPointerInInternalField (index, nullptr );
11131112 return ;
11141113 }
1114+
11151115 per_process::Debug (DebugCategory::MKSNAPSHOT,
11161116 " Deserialize internal field %d of %p, size=%d\n " ,
11171117 static_cast <int >(index),
11181118 (*holder),
11191119 static_cast <int >(payload.raw_size ));
11201120
1121- if (payload.raw_size == 0 ) {
1122- holder->SetAlignedPointerInInternalField (index, nullptr );
1121+ Environment* env = static_cast <Environment*>(callback_data);
1122+
1123+ // To deserialize the first field, check the type and re-tag the object.
1124+ if (index == BaseObject::kEmbedderType ) {
1125+ int size = sizeof (EmbedderTypeInfo);
1126+ DCHECK_EQ (payload.raw_size , size);
1127+ EmbedderTypeInfo read_data;
1128+ memcpy (&read_data, payload.data , size);
1129+ // For now we only support non-cppgc objects.
1130+ CHECK_EQ (read_data.mode , EmbedderTypeInfo::MemoryMode::kBaseObject );
1131+ BaseObject::TagBaseObject (env->isolate_data (), holder);
11231132 return ;
11241133 }
11251134
1126- DCHECK_EQ (index, BaseObject::kEmbedderType );
1127-
1128- Environment* env_ptr = static_cast <Environment*>(env);
1135+ // To deserialize the second field, enqueue a deserialize request.
1136+ DCHECK_IS_SNAPSHOT_SLOT (index);
11291137 const InternalFieldInfoBase* info =
11301138 reinterpret_cast <const InternalFieldInfoBase*>(payload.data );
11311139 // TODO(joyeecheung): we can add a constant kNodeEmbedderId to the
@@ -1138,7 +1146,7 @@ void DeserializeNodeInternalFields(Local<Object> holder,
11381146 " Object %p is %s\n " , \
11391147 (*holder), \
11401148 #NativeTypeName); \
1141- env_ptr ->EnqueueDeserializeRequest ( \
1149+ env ->EnqueueDeserializeRequest ( \
11421150 NativeTypeName::Deserialize, \
11431151 holder, \
11441152 index, \
@@ -1164,28 +1172,52 @@ void DeserializeNodeInternalFields(Local<Object> holder,
11641172StartupData SerializeNodeContextInternalFields (Local<Object> holder,
11651173 int index,
11661174 void * callback_data) {
1167- // We only do one serialization for the kEmbedderType slot, the result
1168- // contains everything necessary for deserializing the entire object,
1169- // including the fields whose index is bigger than kEmbedderType
1170- // (most importantly, BaseObject::kSlot).
1171- // For Node.js this design is enough for all the native binding that are
1172- // serializable.
1175+ // For the moment we do not set any internal fields in ArrayBuffer
1176+ // or ArrayBufferViews, so just return nullptr.
1177+ if (holder->IsArrayBuffer () || holder->IsArrayBufferView ()) {
1178+ CHECK_NULL (holder->GetAlignedPointerFromInternalField (index));
1179+ return StartupData{nullptr , 0 };
1180+ }
1181+
1182+ // Use the V8 convention and serialize unknown objects verbatim.
11731183 Environment* env = static_cast <Environment*>(callback_data);
1174- if (index != BaseObject::kEmbedderType ||
1175- !BaseObject::IsBaseObject (env->isolate_data (), holder)) {
1184+ if (!BaseObject::IsBaseObject (env->isolate_data (), holder)) {
1185+ per_process::Debug (DebugCategory::MKSNAPSHOT,
1186+ " Serialize unknown object, index=%d, holder=%p\n " ,
1187+ static_cast <int >(index),
1188+ *holder);
11761189 return StartupData{nullptr , 0 };
11771190 }
11781191
11791192 per_process::Debug (DebugCategory::MKSNAPSHOT,
1180- " Serialize internal field , index=%d, holder=%p\n " ,
1193+ " Serialize BaseObject , index=%d, holder=%p\n " ,
11811194 static_cast <int >(index),
11821195 *holder);
11831196
1184- void * native_ptr =
1185- holder->GetAlignedPointerFromInternalField (BaseObject::kSlot );
1186- per_process::Debug (DebugCategory::MKSNAPSHOT, " native = %p\n " , native_ptr);
1187- DCHECK (static_cast <BaseObject*>(native_ptr)->is_snapshotable ());
1188- SnapshotableObject* obj = static_cast <SnapshotableObject*>(native_ptr);
1197+ BaseObject* object_ptr = static_cast <BaseObject*>(
1198+ holder->GetAlignedPointerFromInternalField (BaseObject::kSlot ));
1199+ // If the native object is already set to null, ignore it.
1200+ if (object_ptr == nullptr ) {
1201+ return StartupData{nullptr , 0 };
1202+ }
1203+
1204+ DCHECK (object_ptr->is_snapshotable ());
1205+ SnapshotableObject* obj = static_cast <SnapshotableObject*>(object_ptr);
1206+
1207+ // To serialize the type field, save data in a EmbedderTypeInfo.
1208+ if (index == BaseObject::kEmbedderType ) {
1209+ int size = sizeof (EmbedderTypeInfo);
1210+ char * data = new char [size];
1211+ // We need to use placement new because V8 calls delete[] on the returned
1212+ // data.
1213+ // TODO(joyeecheung): support cppgc objects.
1214+ new (data) EmbedderTypeInfo (obj->type (),
1215+ EmbedderTypeInfo::MemoryMode::kBaseObject );
1216+ return StartupData{data, size};
1217+ }
1218+
1219+ // To serialize the slot field, invoke Serialize() method on the object.
1220+ DCHECK_IS_SNAPSHOT_SLOT (index);
11891221
11901222 per_process::Debug (DebugCategory::MKSNAPSHOT,
11911223 " Object %p is %s, " ,
@@ -1341,7 +1373,7 @@ bool BindingData::PrepareForSerialization(Local<Context> context,
13411373}
13421374
13431375InternalFieldInfoBase* BindingData::Serialize (int index) {
1344- DCHECK_EQ (index, BaseObject:: kEmbedderType );
1376+ DCHECK_IS_SNAPSHOT_SLOT (index);
13451377 InternalFieldInfo* info = internal_field_info_;
13461378 internal_field_info_ = nullptr ;
13471379 return info;
@@ -1351,7 +1383,7 @@ void BindingData::Deserialize(Local<Context> context,
13511383 Local<Object> holder,
13521384 int index,
13531385 InternalFieldInfoBase* info) {
1354- DCHECK_EQ (index, BaseObject:: kEmbedderType );
1386+ DCHECK_IS_SNAPSHOT_SLOT (index);
13551387 v8::HandleScope scope (context->GetIsolate ());
13561388 Realm* realm = Realm::GetCurrent (context);
13571389 // Recreate the buffer in the constructor.
0 commit comments