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