1 2 #ifndef SRC_NODE_SNAPSHOTABLE_H_ 3 #define SRC_NODE_SNAPSHOTABLE_H_ 4 5 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 6 7 #include "base_object.h" 8 #include "util.h" 9 10 namespace node { 11 12 class Environment; 13 struct RealmSerializeInfo; 14 struct SnapshotData; 15 class ExternalReferenceRegistry; 16 17 using SnapshotIndex = size_t; 18 19 struct PropInfo { 20 std::string name; // name for debugging 21 uint32_t id; // In the list - in case there are any empty entries 22 SnapshotIndex index; // In the snapshot 23 }; 24 25 typedef size_t SnapshotIndex; 26 27 // When serializing an embedder object, we'll serialize the native states 28 // into a chunk that can be mapped into a subclass of InternalFieldInfoBase, 29 // and pass it into the V8 callback as the payload of StartupData. 30 // The memory chunk looks like this: 31 // 32 // [ type ] - EmbedderObjectType (a uint8_t) 33 // [ length ] - a size_t 34 // [ ... ] - custom bytes of size |length - header size| 35 struct InternalFieldInfoBase { 36 public: 37 EmbedderObjectType type; 38 size_t length; 39 40 template <typename T> NewInternalFieldInfoBase41 static T* New(EmbedderObjectType type) { 42 static_assert(std::is_base_of_v<InternalFieldInfoBase, T> || 43 std::is_same_v<InternalFieldInfoBase, T>, 44 "Can only accept InternalFieldInfoBase subclasses"); 45 void* buf = ::operator new[](sizeof(T)); 46 T* result = new (buf) T; 47 result->type = type; 48 result->length = sizeof(T); 49 return result; 50 } 51 52 template <typename T> CopyInternalFieldInfoBase53 T* Copy() const { 54 static_assert(std::is_base_of_v<InternalFieldInfoBase, T> || 55 std::is_same_v<InternalFieldInfoBase, T>, 56 "Can only accept InternalFieldInfoBase subclasses"); 57 static_assert(std::is_trivially_copyable_v<T>, 58 "Can only memcpy trivially copyable class"); 59 void* buf = ::operator new[](sizeof(T)); 60 T* result = new (buf) T; 61 memcpy(result, this, sizeof(T)); 62 return result; 63 } 64 DeleteInternalFieldInfoBase65 void Delete() { ::operator delete[](this); } 66 67 InternalFieldInfoBase() = default; 68 }; 69 70 // An interface for snapshotable native objects to inherit from. 71 // Use the SERIALIZABLE_OBJECT_METHODS() macro in the class to define 72 // the following methods to implement: 73 // 74 // - PrepareForSerialization(): This would be run prior to context 75 // serialization. Use this method to e.g. release references that 76 // can be re-initialized, or perform property store operations 77 // that needs a V8 context. 78 // - Serialize(): This would be called during context serialization, 79 // once for each embedder field of the object. 80 // Allocate and construct an InternalFieldInfoBase object that contains 81 // data that can be used to deserialize native states. 82 // - Deserialize(): This would be called after the context is 83 // deserialized and the object graph is complete, once for each 84 // embedder field of the object. Use this to restore native states 85 // in the object. 86 class SnapshotableObject : public BaseObject { 87 public: 88 SnapshotableObject(Realm* realm, 89 v8::Local<v8::Object> wrap, 90 EmbedderObjectType type); 91 std::string GetTypeName() const; 92 93 // If returns false, the object will not be serialized. 94 virtual bool PrepareForSerialization(v8::Local<v8::Context> context, 95 v8::SnapshotCreator* creator) = 0; 96 virtual InternalFieldInfoBase* Serialize(int index) = 0; is_snapshotable()97 bool is_snapshotable() const override { return true; } 98 // We'll make sure that the type is set in the constructor type()99 EmbedderObjectType type() { return type_; } 100 101 private: 102 EmbedderObjectType type_; 103 }; 104 105 #define SERIALIZABLE_OBJECT_METHODS() \ 106 bool PrepareForSerialization(v8::Local<v8::Context> context, \ 107 v8::SnapshotCreator* creator) override; \ 108 InternalFieldInfoBase* Serialize(int index) override; \ 109 static void Deserialize(v8::Local<v8::Context> context, \ 110 v8::Local<v8::Object> holder, \ 111 int index, \ 112 InternalFieldInfoBase* info); 113 114 v8::StartupData SerializeNodeContextInternalFields(v8::Local<v8::Object> holder, 115 int index, 116 void* env); 117 void DeserializeNodeInternalFields(v8::Local<v8::Object> holder, 118 int index, 119 v8::StartupData payload, 120 void* env); 121 void SerializeSnapshotableObjects(Realm* realm, 122 v8::SnapshotCreator* creator, 123 RealmSerializeInfo* info); 124 } // namespace node 125 126 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 127 128 #endif // SRC_NODE_SNAPSHOTABLE_H_ 129