@@ -1146,25 +1146,33 @@ std::string SnapshotableObject::GetTypeName() const {
1146
1146
void DeserializeNodeInternalFields (Local<Object> holder,
1147
1147
int index,
1148
1148
StartupData payload,
1149
- void * env ) {
1149
+ void * callback_data ) {
1150
1150
if (payload.raw_size == 0 ) {
1151
- holder->SetAlignedPointerInInternalField (index , nullptr );
1152
1151
return ;
1153
1152
}
1153
+
1154
1154
per_process::Debug (DebugCategory::MKSNAPSHOT,
1155
1155
" Deserialize internal field %d of %p, size=%d\n " ,
1156
1156
static_cast <int >(index ),
1157
1157
(*holder),
1158
1158
static_cast <int >(payload.raw_size ));
1159
1159
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);
1162
1171
return ;
1163
1172
}
1164
1173
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 );
1168
1176
const InternalFieldInfoBase* info =
1169
1177
reinterpret_cast <const InternalFieldInfoBase*>(payload.data );
1170
1178
// TODO(joyeecheung): we can add a constant kNodeEmbedderId to the
@@ -1177,7 +1185,7 @@ void DeserializeNodeInternalFields(Local<Object> holder,
1177
1185
" Object %p is %s\n " , \
1178
1186
(*holder), \
1179
1187
#NativeTypeName); \
1180
- env_ptr ->EnqueueDeserializeRequest ( \
1188
+ env ->EnqueueDeserializeRequest ( \
1181
1189
NativeTypeName::Deserialize, \
1182
1190
holder, \
1183
1191
index , \
@@ -1203,28 +1211,52 @@ void DeserializeNodeInternalFields(Local<Object> holder,
1203
1211
StartupData SerializeNodeContextInternalFields (Local<Object> holder,
1204
1212
int index,
1205
1213
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.
1212
1222
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);
1215
1228
return StartupData{nullptr , 0 };
1216
1229
}
1217
1230
1218
1231
per_process::Debug (DebugCategory::MKSNAPSHOT,
1219
- " Serialize internal field , index=%d, holder=%p\n " ,
1232
+ " Serialize BaseObject , index=%d, holder=%p\n " ,
1220
1233
static_cast <int >(index ),
1221
1234
*holder);
1222
1235
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 );
1228
1260
1229
1261
per_process::Debug (DebugCategory::MKSNAPSHOT,
1230
1262
" Object %p is %s, " ,
@@ -1380,7 +1412,7 @@ bool BindingData::PrepareForSerialization(Local<Context> context,
1380
1412
}
1381
1413
1382
1414
InternalFieldInfoBase* BindingData::Serialize (int index) {
1383
- DCHECK_EQ (index , BaseObject:: kEmbedderType );
1415
+ DCHECK_IS_SNAPSHOT_SLOT (index );
1384
1416
InternalFieldInfo* info = internal_field_info_;
1385
1417
internal_field_info_ = nullptr ;
1386
1418
return info;
@@ -1390,7 +1422,7 @@ void BindingData::Deserialize(Local<Context> context,
1390
1422
Local<Object> holder,
1391
1423
int index,
1392
1424
InternalFieldInfoBase* info) {
1393
- DCHECK_EQ (index , BaseObject:: kEmbedderType );
1425
+ DCHECK_IS_SNAPSHOT_SLOT (index );
1394
1426
v8::HandleScope scope (context->GetIsolate ());
1395
1427
Realm* realm = Realm::GetCurrent (context);
1396
1428
// Recreate the buffer in the constructor.
0 commit comments