GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_snapshotable.h Lines: 13 14 92.9 %
Date: 2021-10-06 04:12:32 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
16
#define SERIALIZABLE_OBJECT_TYPES(V)                                           \
17
  V(fs_binding_data, fs::BindingData)                                          \
18
  V(v8_binding_data, v8_utils::BindingData)                                    \
19
  V(blob_binding_data, BlobBindingData)
20
21
enum class EmbedderObjectType : uint8_t {
22
  k_default = 0,
23
#define V(PropertyName, NativeType) k_##PropertyName,
24
  SERIALIZABLE_OBJECT_TYPES(V)
25
#undef V
26
};
27
28
// When serializing an embedder object, we'll serialize the native states
29
// into a chunk that can be mapped into a subclass of InternalFieldInfo,
30
// and pass it into the V8 callback as the payload of StartupData.
31
// TODO(joyeecheung): the classification of types seem to be wrong.
32
// We'd need a type for each field of each class of native object.
33
// Maybe it's fine - we'll just use the type to invoke BaseObject constructors
34
// and specify that the BaseObject has only one field for us to serialize.
35
// And for non-BaseObject embedder objects, we'll use field-wise types.
36
// The memory chunk looks like this:
37
//
38
// [   type   ] - EmbedderObjectType (a uint8_t)
39
// [  length  ] - a size_t
40
// [    ...   ] - custom bytes of size |length - header size|
41
struct InternalFieldInfo {
42
  EmbedderObjectType type;
43
  size_t length;
44
45
  InternalFieldInfo() = delete;
46
47
18
  static InternalFieldInfo* New(EmbedderObjectType type) {
48
18
    return New(type, sizeof(InternalFieldInfo));
49
  }
50
51
18
  static InternalFieldInfo* New(EmbedderObjectType type, size_t length) {
52
    InternalFieldInfo* result =
53
18
        reinterpret_cast<InternalFieldInfo*>(::operator new[](length));
54
18
    result->type = type;
55
18
    result->length = length;
56
18
    return result;
57
  }
58
59
14541
  InternalFieldInfo* Copy() const {
60
    InternalFieldInfo* result =
61
14541
        reinterpret_cast<InternalFieldInfo*>(::operator new[](length));
62
14541
    memcpy(result, this, length);
63
14541
    return result;
64
  }
65
66
14541
  void Delete() { ::operator delete[](this); }
67
};
68
69
// An interface for snapshotable native objects to inherit from.
70
// Use the SERIALIZABLE_OBJECT_METHODS() macro in the class to define
71
// the following methods to implement:
72
//
73
// - PrepareForSerialization(): This would be run prior to context
74
//   serialization. Use this method to e.g. release references that
75
//   can be re-initialized, or perform property store operations
76
//   that needs a V8 context.
77
// - Serialize(): This would be called during context serialization,
78
//   once for each embedder field of the object.
79
//   Allocate and construct an InternalFieldInfo object that contains
80
//   data that can be used to deserialize native states.
81
// - Deserialize(): This would be called after the context is
82
//   deserialized and the object graph is complete, once for each
83
//   embedder field of the object. Use this to restore native states
84
//   in the object.
85
class SnapshotableObject : public BaseObject {
86
 public:
87
  SnapshotableObject(Environment* env,
88
                     v8::Local<v8::Object> wrap,
89
                     EmbedderObjectType type = EmbedderObjectType::k_default);
90
  const char* GetTypeNameChars() const;
91
92
  virtual void PrepareForSerialization(v8::Local<v8::Context> context,
93
                                       v8::SnapshotCreator* creator) = 0;
94
  virtual InternalFieldInfo* Serialize(int index) = 0;
95
  bool is_snapshotable() const override { return true; }
96
  // We'll make sure that the type is set in the constructor
97
18
  EmbedderObjectType type() { return type_; }
98
99
 private:
100
  EmbedderObjectType type_;
101
};
102
103
#define SERIALIZABLE_OBJECT_METHODS()                                          \
104
  void PrepareForSerialization(v8::Local<v8::Context> context,                 \
105
                               v8::SnapshotCreator* creator) override;         \
106
  InternalFieldInfo* Serialize(int index) override;                            \
107
  static void Deserialize(v8::Local<v8::Context> context,                      \
108
                          v8::Local<v8::Object> holder,                        \
109
                          int index,                                           \
110
                          InternalFieldInfo* info);
111
112
v8::StartupData SerializeNodeContextInternalFields(v8::Local<v8::Object> holder,
113
                                                   int index,
114
                                                   void* env);
115
void DeserializeNodeInternalFields(v8::Local<v8::Object> holder,
116
                                   int index,
117
                                   v8::StartupData payload,
118
                                   void* env);
119
void SerializeBindingData(Environment* env,
120
                          v8::SnapshotCreator* creator,
121
                          EnvSerializeInfo* info);
122
123
bool IsSnapshotableType(FastStringKey key);
124
125
class SnapshotBuilder {
126
 public:
127
  static std::string Generate(const std::vector<std::string> args,
128
                              const std::vector<std::string> exec_args);
129
  static void Generate(SnapshotData* out,
130
                       const std::vector<std::string> args,
131
                       const std::vector<std::string> exec_args);
132
};
133
}  // namespace node
134
135
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
136
137
#endif  // SRC_NODE_SNAPSHOTABLE_H_