/src/node/deps/v8/include/v8-value-serializer.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2021 the V8 project authors. All rights reserved. |
2 | | // Use of this source code is governed by a BSD-style license that can be |
3 | | // found in the LICENSE file. |
4 | | |
5 | | #ifndef INCLUDE_V8_VALUE_SERIALIZER_H_ |
6 | | #define INCLUDE_V8_VALUE_SERIALIZER_H_ |
7 | | |
8 | | #include <stddef.h> |
9 | | #include <stdint.h> |
10 | | |
11 | | #include <memory> |
12 | | #include <utility> |
13 | | |
14 | | #include "v8-local-handle.h" // NOLINT(build/include_directory) |
15 | | #include "v8-maybe.h" // NOLINT(build/include_directory) |
16 | | #include "v8config.h" // NOLINT(build/include_directory) |
17 | | |
18 | | namespace v8 { |
19 | | |
20 | | class ArrayBuffer; |
21 | | class Isolate; |
22 | | class Object; |
23 | | class SharedArrayBuffer; |
24 | | class String; |
25 | | class WasmModuleObject; |
26 | | class Value; |
27 | | |
28 | | namespace internal { |
29 | | struct ScriptStreamingData; |
30 | | class SharedObjectConveyorHandles; |
31 | | class ValueDeserializer; |
32 | | class ValueSerializer; |
33 | | } // namespace internal |
34 | | |
35 | | /** |
36 | | * A move-only class for managing the lifetime of shared value conveyors used |
37 | | * by V8 to keep JS shared values alive in transit when serialized. |
38 | | * |
39 | | * This class is not directly constructible and is always passed to a |
40 | | * ValueSerializer::Delegate via ValueSerializer::SetSharedValueConveyor. |
41 | | * |
42 | | * The embedder must not destruct the SharedValueConveyor until the associated |
43 | | * serialized data will no longer be deserialized. |
44 | | */ |
45 | | class V8_EXPORT SharedValueConveyor final { |
46 | | public: |
47 | | SharedValueConveyor(SharedValueConveyor&&) noexcept; |
48 | | ~SharedValueConveyor(); |
49 | | |
50 | | SharedValueConveyor& operator=(SharedValueConveyor&&) noexcept; |
51 | | |
52 | | private: |
53 | | friend class internal::ValueSerializer; |
54 | | friend class internal::ValueDeserializer; |
55 | | |
56 | | explicit SharedValueConveyor(Isolate* isolate); |
57 | | |
58 | | std::unique_ptr<internal::SharedObjectConveyorHandles> private_; |
59 | | }; |
60 | | |
61 | | /** |
62 | | * Value serialization compatible with the HTML structured clone algorithm. |
63 | | * The format is backward-compatible (i.e. safe to store to disk). |
64 | | */ |
65 | | class V8_EXPORT ValueSerializer { |
66 | | public: |
67 | | class V8_EXPORT Delegate { |
68 | | public: |
69 | 2 | virtual ~Delegate() = default; |
70 | | |
71 | | /** |
72 | | * Handles the case where a DataCloneError would be thrown in the structured |
73 | | * clone spec. Other V8 embedders may throw some other appropriate exception |
74 | | * type. |
75 | | */ |
76 | | virtual void ThrowDataCloneError(Local<String> message) = 0; |
77 | | |
78 | | /** |
79 | | * The embedder overrides this method to enable custom host object filter |
80 | | * with Delegate::IsHostObject. |
81 | | * |
82 | | * This method is called at most once per serializer. |
83 | | */ |
84 | | virtual bool HasCustomHostObject(Isolate* isolate); |
85 | | |
86 | | /** |
87 | | * The embedder overrides this method to determine if an JS object is a |
88 | | * host object and needs to be serialized by the host. |
89 | | */ |
90 | | virtual Maybe<bool> IsHostObject(Isolate* isolate, Local<Object> object); |
91 | | |
92 | | /** |
93 | | * The embedder overrides this method to write some kind of host object, if |
94 | | * possible. If not, a suitable exception should be thrown and |
95 | | * Nothing<bool>() returned. |
96 | | */ |
97 | | virtual Maybe<bool> WriteHostObject(Isolate* isolate, Local<Object> object); |
98 | | |
99 | | /** |
100 | | * Called when the ValueSerializer is going to serialize a |
101 | | * SharedArrayBuffer object. The embedder must return an ID for the |
102 | | * object, using the same ID if this SharedArrayBuffer has already been |
103 | | * serialized in this buffer. When deserializing, this ID will be passed to |
104 | | * ValueDeserializer::GetSharedArrayBufferFromId as |clone_id|. |
105 | | * |
106 | | * If the object cannot be serialized, an |
107 | | * exception should be thrown and Nothing<uint32_t>() returned. |
108 | | */ |
109 | | virtual Maybe<uint32_t> GetSharedArrayBufferId( |
110 | | Isolate* isolate, Local<SharedArrayBuffer> shared_array_buffer); |
111 | | |
112 | | virtual Maybe<uint32_t> GetWasmModuleTransferId( |
113 | | Isolate* isolate, Local<WasmModuleObject> module); |
114 | | |
115 | | /** |
116 | | * Called when the first shared value is serialized. All subsequent shared |
117 | | * values will use the same conveyor. |
118 | | * |
119 | | * The embedder must ensure the lifetime of the conveyor matches the |
120 | | * lifetime of the serialized data. |
121 | | * |
122 | | * If the embedder supports serializing shared values, this method should |
123 | | * return true. Otherwise the embedder should throw an exception and return |
124 | | * false. |
125 | | * |
126 | | * This method is called at most once per serializer. |
127 | | */ |
128 | | virtual bool AdoptSharedValueConveyor(Isolate* isolate, |
129 | | SharedValueConveyor&& conveyor); |
130 | | |
131 | | /** |
132 | | * Allocates memory for the buffer of at least the size provided. The actual |
133 | | * size (which may be greater or equal) is written to |actual_size|. If no |
134 | | * buffer has been allocated yet, nullptr will be provided. |
135 | | * |
136 | | * If the memory cannot be allocated, nullptr should be returned. |
137 | | * |actual_size| will be ignored. It is assumed that |old_buffer| is still |
138 | | * valid in this case and has not been modified. |
139 | | * |
140 | | * The default implementation uses the stdlib's `realloc()` function. |
141 | | */ |
142 | | virtual void* ReallocateBufferMemory(void* old_buffer, size_t size, |
143 | | size_t* actual_size); |
144 | | |
145 | | /** |
146 | | * Frees a buffer allocated with |ReallocateBufferMemory|. |
147 | | * |
148 | | * The default implementation uses the stdlib's `free()` function. |
149 | | */ |
150 | | virtual void FreeBufferMemory(void* buffer); |
151 | | }; |
152 | | |
153 | | explicit ValueSerializer(Isolate* isolate); |
154 | | ValueSerializer(Isolate* isolate, Delegate* delegate); |
155 | | ~ValueSerializer(); |
156 | | |
157 | | /** |
158 | | * Writes out a header, which includes the format version. |
159 | | */ |
160 | | void WriteHeader(); |
161 | | |
162 | | /** |
163 | | * Serializes a JavaScript value into the buffer. |
164 | | */ |
165 | | V8_WARN_UNUSED_RESULT Maybe<bool> WriteValue(Local<Context> context, |
166 | | Local<Value> value); |
167 | | |
168 | | /** |
169 | | * Returns the stored data (allocated using the delegate's |
170 | | * ReallocateBufferMemory) and its size. This serializer should not be used |
171 | | * once the buffer is released. The contents are undefined if a previous write |
172 | | * has failed. Ownership of the buffer is transferred to the caller. |
173 | | */ |
174 | | V8_WARN_UNUSED_RESULT std::pair<uint8_t*, size_t> Release(); |
175 | | |
176 | | /** |
177 | | * Marks an ArrayBuffer as havings its contents transferred out of band. |
178 | | * Pass the corresponding ArrayBuffer in the deserializing context to |
179 | | * ValueDeserializer::TransferArrayBuffer. |
180 | | */ |
181 | | void TransferArrayBuffer(uint32_t transfer_id, |
182 | | Local<ArrayBuffer> array_buffer); |
183 | | |
184 | | /** |
185 | | * Indicate whether to treat ArrayBufferView objects as host objects, |
186 | | * i.e. pass them to Delegate::WriteHostObject. This should not be |
187 | | * called when no Delegate was passed. |
188 | | * |
189 | | * The default is not to treat ArrayBufferViews as host objects. |
190 | | */ |
191 | | void SetTreatArrayBufferViewsAsHostObjects(bool mode); |
192 | | |
193 | | /** |
194 | | * Write raw data in various common formats to the buffer. |
195 | | * Note that integer types are written in base-128 varint format, not with a |
196 | | * binary copy. For use during an override of Delegate::WriteHostObject. |
197 | | */ |
198 | | void WriteUint32(uint32_t value); |
199 | | void WriteUint64(uint64_t value); |
200 | | void WriteDouble(double value); |
201 | | void WriteRawBytes(const void* source, size_t length); |
202 | | |
203 | | ValueSerializer(const ValueSerializer&) = delete; |
204 | | void operator=(const ValueSerializer&) = delete; |
205 | | |
206 | | private: |
207 | | struct PrivateData; |
208 | | PrivateData* private_; |
209 | | }; |
210 | | |
211 | | /** |
212 | | * Deserializes values from data written with ValueSerializer, or a compatible |
213 | | * implementation. |
214 | | */ |
215 | | class V8_EXPORT ValueDeserializer { |
216 | | public: |
217 | | class V8_EXPORT Delegate { |
218 | | public: |
219 | 0 | virtual ~Delegate() = default; |
220 | | |
221 | | /** |
222 | | * The embedder overrides this method to read some kind of host object, if |
223 | | * possible. If not, a suitable exception should be thrown and |
224 | | * MaybeLocal<Object>() returned. |
225 | | */ |
226 | | virtual MaybeLocal<Object> ReadHostObject(Isolate* isolate); |
227 | | |
228 | | /** |
229 | | * Get a WasmModuleObject given a transfer_id previously provided |
230 | | * by ValueSerializer::Delegate::GetWasmModuleTransferId |
231 | | */ |
232 | | virtual MaybeLocal<WasmModuleObject> GetWasmModuleFromId( |
233 | | Isolate* isolate, uint32_t transfer_id); |
234 | | |
235 | | /** |
236 | | * Get a SharedArrayBuffer given a clone_id previously provided |
237 | | * by ValueSerializer::Delegate::GetSharedArrayBufferId |
238 | | */ |
239 | | virtual MaybeLocal<SharedArrayBuffer> GetSharedArrayBufferFromId( |
240 | | Isolate* isolate, uint32_t clone_id); |
241 | | |
242 | | /** |
243 | | * Get the SharedValueConveyor previously provided by |
244 | | * ValueSerializer::Delegate::AdoptSharedValueConveyor. |
245 | | */ |
246 | | virtual const SharedValueConveyor* GetSharedValueConveyor(Isolate* isolate); |
247 | | }; |
248 | | |
249 | | ValueDeserializer(Isolate* isolate, const uint8_t* data, size_t size); |
250 | | ValueDeserializer(Isolate* isolate, const uint8_t* data, size_t size, |
251 | | Delegate* delegate); |
252 | | ~ValueDeserializer(); |
253 | | |
254 | | /** |
255 | | * Reads and validates a header (including the format version). |
256 | | * May, for example, reject an invalid or unsupported wire format. |
257 | | */ |
258 | | V8_WARN_UNUSED_RESULT Maybe<bool> ReadHeader(Local<Context> context); |
259 | | |
260 | | /** |
261 | | * Deserializes a JavaScript value from the buffer. |
262 | | */ |
263 | | V8_WARN_UNUSED_RESULT MaybeLocal<Value> ReadValue(Local<Context> context); |
264 | | |
265 | | /** |
266 | | * Accepts the array buffer corresponding to the one passed previously to |
267 | | * ValueSerializer::TransferArrayBuffer. |
268 | | */ |
269 | | void TransferArrayBuffer(uint32_t transfer_id, |
270 | | Local<ArrayBuffer> array_buffer); |
271 | | |
272 | | /** |
273 | | * Similar to TransferArrayBuffer, but for SharedArrayBuffer. |
274 | | * The id is not necessarily in the same namespace as unshared ArrayBuffer |
275 | | * objects. |
276 | | */ |
277 | | void TransferSharedArrayBuffer(uint32_t id, |
278 | | Local<SharedArrayBuffer> shared_array_buffer); |
279 | | |
280 | | /** |
281 | | * Must be called before ReadHeader to enable support for reading the legacy |
282 | | * wire format (i.e., which predates this being shipped). |
283 | | * |
284 | | * Don't use this unless you need to read data written by previous versions of |
285 | | * blink::ScriptValueSerializer. |
286 | | */ |
287 | | void SetSupportsLegacyWireFormat(bool supports_legacy_wire_format); |
288 | | |
289 | | /** |
290 | | * Reads the underlying wire format version. Likely mostly to be useful to |
291 | | * legacy code reading old wire format versions. Must be called after |
292 | | * ReadHeader. |
293 | | */ |
294 | | uint32_t GetWireFormatVersion() const; |
295 | | |
296 | | /** |
297 | | * Reads raw data in various common formats to the buffer. |
298 | | * Note that integer types are read in base-128 varint format, not with a |
299 | | * binary copy. For use during an override of Delegate::ReadHostObject. |
300 | | */ |
301 | | V8_WARN_UNUSED_RESULT bool ReadUint32(uint32_t* value); |
302 | | V8_WARN_UNUSED_RESULT bool ReadUint64(uint64_t* value); |
303 | | V8_WARN_UNUSED_RESULT bool ReadDouble(double* value); |
304 | | V8_WARN_UNUSED_RESULT bool ReadRawBytes(size_t length, const void** data); |
305 | | |
306 | | ValueDeserializer(const ValueDeserializer&) = delete; |
307 | | void operator=(const ValueDeserializer&) = delete; |
308 | | |
309 | | private: |
310 | | struct PrivateData; |
311 | | PrivateData* private_; |
312 | | }; |
313 | | |
314 | | } // namespace v8 |
315 | | |
316 | | #endif // INCLUDE_V8_VALUE_SERIALIZER_H_ |