@@ -1146,25 +1146,33 @@ std::string SnapshotableObject::GetTypeName() const {
11461146void DeserializeNodeInternalFields (Local<Object> holder,
11471147 int index,
11481148 StartupData payload,
1149- void * env ) {
1149+ void * callback_data ) {
11501150 if (payload.raw_size == 0 ) {
1151- holder->SetAlignedPointerInInternalField (index, nullptr );
11521151 return ;
11531152 }
1153+
11541154 per_process::Debug (DebugCategory::MKSNAPSHOT,
11551155 " Deserialize internal field %d of %p, size=%d\n " ,
11561156 static_cast <int >(index),
11571157 (*holder),
11581158 static_cast <int >(payload.raw_size ));
11591159
1160- if (payload.raw_size == 0 ) {
1161- holder->SetAlignedPointerInInternalField (index, nullptr );
1160+ Environment* env = static_cast <Environment*>(callback_data);
1161+
1162+ // To deserialize the first field, check the type and re-tag the object.
1163+ if (index == BaseObject::kEmbedderType ) {
1164+ int size = sizeof (EmbedderTypeInfo);
1165+ DCHECK_EQ (payload.raw_size , size);
1166+ EmbedderTypeInfo read_data;
1167+ memcpy (&read_data, payload.data , size);
1168+ // For now we only support non-cppgc objects.
1169+ CHECK_EQ (read_data.mode , EmbedderTypeInfo::MemoryMode::kBaseObject );
1170+ BaseObject::TagBaseObject (env->isolate_data (), holder);
11621171 return ;
11631172 }
11641173
1165- DCHECK_EQ (index, BaseObject::kEmbedderType );
1166-
1167- Environment* env_ptr = static_cast <Environment*>(env);
1174+ // To deserialize the second field, enqueue a deserialize request.
1175+ DCHECK_IS_SNAPSHOT_SLOT (index);
11681176 const InternalFieldInfoBase* info =
11691177 reinterpret_cast <const InternalFieldInfoBase*>(payload.data );
11701178 // TODO(joyeecheung): we can add a constant kNodeEmbedderId to the
@@ -1177,7 +1185,7 @@ void DeserializeNodeInternalFields(Local<Object> holder,
11771185 " Object %p is %s\n " , \
11781186 (*holder), \
11791187 #NativeTypeName); \
1180- env_ptr ->EnqueueDeserializeRequest ( \
1188+ env ->EnqueueDeserializeRequest ( \
11811189 NativeTypeName::Deserialize, \
11821190 holder, \
11831191 index, \
@@ -1203,28 +1211,52 @@ void DeserializeNodeInternalFields(Local<Object> holder,
12031211StartupData SerializeNodeContextInternalFields (Local<Object> holder,
12041212 int index,
12051213 void * callback_data) {
1206- // We only do one serialization for the kEmbedderType slot, the result
1207- // contains everything necessary for deserializing the entire object,
1208- // including the fields whose index is bigger than kEmbedderType
1209- // (most importantly, BaseObject::kSlot).
1210- // For Node.js this design is enough for all the native binding that are
1211- // serializable.
1214+ // For the moment we do not set any internal fields in ArrayBuffer
1215+ // or ArrayBufferViews, so just return nullptr.
1216+ if (holder->IsArrayBuffer () || holder->IsArrayBufferView ()) {
1217+ CHECK_NULL (holder->GetAlignedPointerFromInternalField (index));
1218+ return StartupData{nullptr , 0 };
1219+ }
1220+
1221+ // Use the V8 convention and serialize unknown objects verbatim.
12121222 Environment* env = static_cast <Environment*>(callback_data);
1213- if (index != BaseObject::kEmbedderType ||
1214- !BaseObject::IsBaseObject (env->isolate_data (), holder)) {
1223+ if (!BaseObject::IsBaseObject (env->isolate_data (), holder)) {
1224+ per_process::Debug (DebugCategory::MKSNAPSHOT,
1225+ " Serialize unknown object, index=%d, holder=%p\n " ,
1226+ static_cast <int >(index),
1227+ *holder);
12151228 return StartupData{nullptr , 0 };
12161229 }
12171230
12181231 per_process::Debug (DebugCategory::MKSNAPSHOT,
1219- " Serialize internal field , index=%d, holder=%p\n " ,
1232+ " Serialize BaseObject , index=%d, holder=%p\n " ,
12201233 static_cast <int >(index),
12211234 *holder);
12221235
1223- void * native_ptr =
1224- holder->GetAlignedPointerFromInternalField (BaseObject::kSlot );
1225- per_process::Debug (DebugCategory::MKSNAPSHOT, " native = %p\n " , native_ptr);
1226- DCHECK (static_cast <BaseObject*>(native_ptr)->is_snapshotable ());
1227- SnapshotableObject* obj = static_cast <SnapshotableObject*>(native_ptr);
1236+ BaseObject* object_ptr = static_cast <BaseObject*>(
1237+ holder->GetAlignedPointerFromInternalField (BaseObject::kSlot ));
1238+ // If the native object is already set to null, ignore it.
1239+ if (object_ptr == nullptr ) {
1240+ return StartupData{nullptr , 0 };
1241+ }
1242+
1243+ DCHECK (object_ptr->is_snapshotable ());
1244+ SnapshotableObject* obj = static_cast <SnapshotableObject*>(object_ptr);
1245+
1246+ // To serialize the type field, save data in a EmbedderTypeInfo.
1247+ if (index == BaseObject::kEmbedderType ) {
1248+ int size = sizeof (EmbedderTypeInfo);
1249+ char * data = new char [size];
1250+ // We need to use placement new because V8 calls delete[] on the returned
1251+ // data.
1252+ // TODO(joyeecheung): support cppgc objects.
1253+ new (data) EmbedderTypeInfo (obj->type (),
1254+ EmbedderTypeInfo::MemoryMode::kBaseObject );
1255+ return StartupData{data, size};
1256+ }
1257+
1258+ // To serialize the slot field, invoke Serialize() method on the object.
1259+ DCHECK_IS_SNAPSHOT_SLOT (index);
12281260
12291261 per_process::Debug (DebugCategory::MKSNAPSHOT,
12301262 " Object %p is %s, " ,
@@ -1380,7 +1412,7 @@ bool BindingData::PrepareForSerialization(Local<Context> context,
13801412}
13811413
13821414InternalFieldInfoBase* BindingData::Serialize (int index) {
1383- DCHECK_EQ (index, BaseObject:: kEmbedderType );
1415+ DCHECK_IS_SNAPSHOT_SLOT (index);
13841416 InternalFieldInfo* info = internal_field_info_;
13851417 internal_field_info_ = nullptr ;
13861418 return info;
@@ -1390,7 +1422,7 @@ void BindingData::Deserialize(Local<Context> context,
13901422 Local<Object> holder,
13911423 int index,
13921424 InternalFieldInfoBase* info) {
1393- DCHECK_EQ (index, BaseObject:: kEmbedderType );
1425+ DCHECK_IS_SNAPSHOT_SLOT (index);
13941426 v8::HandleScope scope (context->GetIsolate ());
13951427 Realm* realm = Realm::GetCurrent (context);
13961428 // Recreate the buffer in the constructor.
0 commit comments