• 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 #define SERIALIZABLE_OBJECT_TYPES(V)                                           \
26   V(fs_binding_data, fs::BindingData)                                          \
27   V(v8_binding_data, v8_utils::BindingData)                                    \
28   V(blob_binding_data, BlobBindingData)                                        \
29   V(process_binding_data, process::BindingData)                                \
30   V(url_binding_data, url::BindingData)                                        \
31   V(util_weak_reference, util::WeakReference)
32 
33 enum class EmbedderObjectType : uint8_t {
34 #define V(PropertyName, NativeType) k_##PropertyName,
35   SERIALIZABLE_OBJECT_TYPES(V)
36 #undef V
37 };
38 
39 typedef size_t SnapshotIndex;
40 
41 // When serializing an embedder object, we'll serialize the native states
42 // into a chunk that can be mapped into a subclass of InternalFieldInfoBase,
43 // and pass it into the V8 callback as the payload of StartupData.
44 // The memory chunk looks like this:
45 //
46 // [   type   ] - EmbedderObjectType (a uint8_t)
47 // [  length  ] - a size_t
48 // [    ...   ] - custom bytes of size |length - header size|
49 struct InternalFieldInfoBase {
50  public:
51   EmbedderObjectType type;
52   size_t length;
53 
54   template <typename T>
NewInternalFieldInfoBase55   static T* New(EmbedderObjectType type) {
56     static_assert(std::is_base_of_v<InternalFieldInfoBase, T> ||
57                       std::is_same_v<InternalFieldInfoBase, T>,
58                   "Can only accept InternalFieldInfoBase subclasses");
59     void* buf = ::operator new[](sizeof(T));
60     T* result = new (buf) T;
61     result->type = type;
62     result->length = sizeof(T);
63     return result;
64   }
65 
66   template <typename T>
CopyInternalFieldInfoBase67   T* Copy() const {
68     static_assert(std::is_base_of_v<InternalFieldInfoBase, T> ||
69                       std::is_same_v<InternalFieldInfoBase, T>,
70                   "Can only accept InternalFieldInfoBase subclasses");
71     static_assert(std::is_trivially_copyable_v<T>,
72                   "Can only memcpy trivially copyable class");
73     void* buf = ::operator new[](sizeof(T));
74     T* result = new (buf) T;
75     memcpy(result, this, sizeof(T));
76     return result;
77   }
78 
DeleteInternalFieldInfoBase79   void Delete() { ::operator delete[](this); }
80 
81   InternalFieldInfoBase() = default;
82 };
83 
84 // An interface for snapshotable native objects to inherit from.
85 // Use the SERIALIZABLE_OBJECT_METHODS() macro in the class to define
86 // the following methods to implement:
87 //
88 // - PrepareForSerialization(): This would be run prior to context
89 //   serialization. Use this method to e.g. release references that
90 //   can be re-initialized, or perform property store operations
91 //   that needs a V8 context.
92 // - Serialize(): This would be called during context serialization,
93 //   once for each embedder field of the object.
94 //   Allocate and construct an InternalFieldInfoBase object that contains
95 //   data that can be used to deserialize native states.
96 // - Deserialize(): This would be called after the context is
97 //   deserialized and the object graph is complete, once for each
98 //   embedder field of the object. Use this to restore native states
99 //   in the object.
100 class SnapshotableObject : public BaseObject {
101  public:
102   SnapshotableObject(Realm* realm,
103                      v8::Local<v8::Object> wrap,
104                      EmbedderObjectType type);
105   std::string_view GetTypeName() const;
106 
107   // If returns false, the object will not be serialized.
108   virtual bool PrepareForSerialization(v8::Local<v8::Context> context,
109                                        v8::SnapshotCreator* creator) = 0;
110   virtual InternalFieldInfoBase* Serialize(int index) = 0;
is_snapshotable()111   bool is_snapshotable() const override { return true; }
112   // We'll make sure that the type is set in the constructor
type()113   EmbedderObjectType type() { return type_; }
114 
115  private:
116   EmbedderObjectType type_;
117 };
118 
119 #define SERIALIZABLE_OBJECT_METHODS()                                          \
120   bool PrepareForSerialization(v8::Local<v8::Context> context,                 \
121                                v8::SnapshotCreator* creator) override;         \
122   InternalFieldInfoBase* Serialize(int index) override;                        \
123   static void Deserialize(v8::Local<v8::Context> context,                      \
124                           v8::Local<v8::Object> holder,                        \
125                           int index,                                           \
126                           InternalFieldInfoBase* info);
127 
128 v8::StartupData SerializeNodeContextInternalFields(v8::Local<v8::Object> holder,
129                                                    int index,
130                                                    void* env);
131 void DeserializeNodeInternalFields(v8::Local<v8::Object> holder,
132                                    int index,
133                                    v8::StartupData payload,
134                                    void* env);
135 void SerializeSnapshotableObjects(Realm* realm,
136                                   v8::SnapshotCreator* creator,
137                                   RealmSerializeInfo* info);
138 }  // namespace node
139 
140 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
141 
142 #endif  // SRC_NODE_SNAPSHOTABLE_H_
143