GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_snapshotable.h Lines: 14 14 100.0 %
Date: 2022-08-16 04:20:39 Branches: 0 0 - %

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