• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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