Line data Source code
1 : // Copyright 2016 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 V8_VALUE_SERIALIZER_H_
6 : #define V8_VALUE_SERIALIZER_H_
7 :
8 : #include <cstdint>
9 : #include <vector>
10 :
11 : #include "include/v8.h"
12 : #include "src/base/compiler-specific.h"
13 : #include "src/base/macros.h"
14 : #include "src/identity-map.h"
15 : #include "src/maybe-handles.h"
16 : #include "src/message-template.h"
17 : #include "src/vector.h"
18 : #include "src/zone/zone.h"
19 :
20 : namespace v8 {
21 : namespace internal {
22 :
23 : class BigInt;
24 : class HeapNumber;
25 : class Isolate;
26 : class JSArrayBuffer;
27 : class JSArrayBufferView;
28 : class JSDate;
29 : class JSMap;
30 : class JSRegExp;
31 : class JSSet;
32 : class JSValue;
33 : class MutableHeapNumber;
34 : class Object;
35 : class Oddball;
36 : class Smi;
37 : class WasmMemoryObject;
38 : class WasmModuleObject;
39 :
40 : enum class SerializationTag : uint8_t;
41 :
42 : /**
43 : * Writes V8 objects in a binary format that allows the objects to be cloned
44 : * according to the HTML structured clone algorithm.
45 : *
46 : * Format is based on Blink's previous serialization logic.
47 : */
48 : class ValueSerializer {
49 : public:
50 : ValueSerializer(Isolate* isolate, v8::ValueSerializer::Delegate* delegate);
51 : ~ValueSerializer();
52 :
53 : /*
54 : * Writes out a header, which includes the format version.
55 : */
56 : void WriteHeader();
57 :
58 : /*
59 : * Serializes a V8 object into the buffer.
60 : */
61 : Maybe<bool> WriteObject(Handle<Object> object) V8_WARN_UNUSED_RESULT;
62 :
63 : /*
64 : * Returns the buffer, allocated via the delegate, and its size.
65 : * Caller assumes ownership of the buffer.
66 : */
67 : std::pair<uint8_t*, size_t> Release();
68 :
69 : /*
70 : * Marks an ArrayBuffer as havings its contents transferred out of band.
71 : * Pass the corresponding JSArrayBuffer in the deserializing context to
72 : * ValueDeserializer::TransferArrayBuffer.
73 : */
74 : void TransferArrayBuffer(uint32_t transfer_id,
75 : Handle<JSArrayBuffer> array_buffer);
76 :
77 : /*
78 : * Publicly exposed wire format writing methods.
79 : * These are intended for use within the delegate's WriteHostObject method.
80 : */
81 : void WriteUint32(uint32_t value);
82 : void WriteUint64(uint64_t value);
83 : void WriteRawBytes(const void* source, size_t length);
84 : void WriteDouble(double value);
85 :
86 : /*
87 : * Indicate whether to treat ArrayBufferView objects as host objects,
88 : * i.e. pass them to Delegate::WriteHostObject. This should not be
89 : * called when no Delegate was passed.
90 : *
91 : * The default is not to treat ArrayBufferViews as host objects.
92 : */
93 : void SetTreatArrayBufferViewsAsHostObjects(bool mode);
94 :
95 : private:
96 : // Managing allocations of the internal buffer.
97 : Maybe<bool> ExpandBuffer(size_t required_capacity);
98 :
99 : // Writing the wire format.
100 : void WriteTag(SerializationTag tag);
101 : template <typename T>
102 : void WriteVarint(T value);
103 : template <typename T>
104 : void WriteZigZag(T value);
105 : void WriteOneByteString(Vector<const uint8_t> chars);
106 : void WriteTwoByteString(Vector<const uc16> chars);
107 : void WriteBigIntContents(BigInt bigint);
108 : Maybe<uint8_t*> ReserveRawBytes(size_t bytes);
109 :
110 : // Writing V8 objects of various kinds.
111 : void WriteOddball(Oddball oddball);
112 : void WriteSmi(Smi smi);
113 : void WriteHeapNumber(HeapNumber number);
114 : void WriteMutableHeapNumber(MutableHeapNumber number);
115 : void WriteBigInt(BigInt bigint);
116 : void WriteString(Handle<String> string);
117 : Maybe<bool> WriteJSReceiver(Handle<JSReceiver> receiver)
118 : V8_WARN_UNUSED_RESULT;
119 : Maybe<bool> WriteJSObject(Handle<JSObject> object) V8_WARN_UNUSED_RESULT;
120 : Maybe<bool> WriteJSObjectSlow(Handle<JSObject> object) V8_WARN_UNUSED_RESULT;
121 : Maybe<bool> WriteJSArray(Handle<JSArray> array) V8_WARN_UNUSED_RESULT;
122 : void WriteJSDate(JSDate date);
123 : Maybe<bool> WriteJSValue(Handle<JSValue> value) V8_WARN_UNUSED_RESULT;
124 : void WriteJSRegExp(JSRegExp regexp);
125 : Maybe<bool> WriteJSMap(Handle<JSMap> map) V8_WARN_UNUSED_RESULT;
126 : Maybe<bool> WriteJSSet(Handle<JSSet> map) V8_WARN_UNUSED_RESULT;
127 : Maybe<bool> WriteJSArrayBuffer(Handle<JSArrayBuffer> array_buffer)
128 : V8_WARN_UNUSED_RESULT;
129 : Maybe<bool> WriteJSArrayBufferView(JSArrayBufferView array_buffer);
130 : Maybe<bool> WriteWasmModule(Handle<WasmModuleObject> object)
131 : V8_WARN_UNUSED_RESULT;
132 : Maybe<bool> WriteWasmMemory(Handle<WasmMemoryObject> object)
133 : V8_WARN_UNUSED_RESULT;
134 : Maybe<bool> WriteHostObject(Handle<JSObject> object) V8_WARN_UNUSED_RESULT;
135 :
136 : /*
137 : * Reads the specified keys from the object and writes key-value pairs to the
138 : * buffer. Returns the number of keys actually written, which may be smaller
139 : * if some keys are not own properties when accessed.
140 : */
141 : Maybe<uint32_t> WriteJSObjectPropertiesSlow(
142 : Handle<JSObject> object, Handle<FixedArray> keys) V8_WARN_UNUSED_RESULT;
143 :
144 : /*
145 : * Asks the delegate to handle an error that occurred during data cloning, by
146 : * throwing an exception appropriate for the host.
147 : */
148 : void ThrowDataCloneError(MessageTemplate template_index);
149 : V8_NOINLINE void ThrowDataCloneError(MessageTemplate template_index,
150 : Handle<Object> arg0);
151 :
152 : Maybe<bool> ThrowIfOutOfMemory();
153 :
154 : Isolate* const isolate_;
155 : v8::ValueSerializer::Delegate* const delegate_;
156 : uint8_t* buffer_ = nullptr;
157 : size_t buffer_size_ = 0;
158 : size_t buffer_capacity_ = 0;
159 : bool treat_array_buffer_views_as_host_objects_ = false;
160 : bool out_of_memory_ = false;
161 : Zone zone_;
162 :
163 : // To avoid extra lookups in the identity map, ID+1 is actually stored in the
164 : // map (checking if the used identity is zero is the fast way of checking if
165 : // the entry is new).
166 : IdentityMap<uint32_t, ZoneAllocationPolicy> id_map_;
167 : uint32_t next_id_ = 0;
168 :
169 : // A similar map, for transferred array buffers.
170 : IdentityMap<uint32_t, ZoneAllocationPolicy> array_buffer_transfer_map_;
171 :
172 : DISALLOW_COPY_AND_ASSIGN(ValueSerializer);
173 : };
174 :
175 : /*
176 : * Deserializes values from data written with ValueSerializer, or a compatible
177 : * implementation.
178 : */
179 : class ValueDeserializer {
180 : public:
181 : ValueDeserializer(Isolate* isolate, Vector<const uint8_t> data,
182 : v8::ValueDeserializer::Delegate* delegate);
183 : ~ValueDeserializer();
184 :
185 : /*
186 : * Runs version detection logic, which may fail if the format is invalid.
187 : */
188 : Maybe<bool> ReadHeader() V8_WARN_UNUSED_RESULT;
189 :
190 : /*
191 : * Reads the underlying wire format version. Likely mostly to be useful to
192 : * legacy code reading old wire format versions. Must be called after
193 : * ReadHeader.
194 : */
195 : uint32_t GetWireFormatVersion() const { return version_; }
196 :
197 : /*
198 : * Deserializes a V8 object from the buffer.
199 : */
200 : MaybeHandle<Object> ReadObject() V8_WARN_UNUSED_RESULT;
201 :
202 : /*
203 : * Reads an object, consuming the entire buffer.
204 : *
205 : * This is required for the legacy "version 0" format, which did not allow
206 : * reference deduplication, and instead relied on a "stack" model for
207 : * deserializing, with the contents of objects and arrays provided first.
208 : */
209 : MaybeHandle<Object> ReadObjectUsingEntireBufferForLegacyFormat()
210 : V8_WARN_UNUSED_RESULT;
211 :
212 : /*
213 : * Accepts the array buffer corresponding to the one passed previously to
214 : * ValueSerializer::TransferArrayBuffer.
215 : */
216 : void TransferArrayBuffer(uint32_t transfer_id,
217 : Handle<JSArrayBuffer> array_buffer);
218 :
219 : /*
220 : * Publicly exposed wire format writing methods.
221 : * These are intended for use within the delegate's WriteHostObject method.
222 : */
223 : bool ReadUint32(uint32_t* value) V8_WARN_UNUSED_RESULT;
224 : bool ReadUint64(uint64_t* value) V8_WARN_UNUSED_RESULT;
225 : bool ReadDouble(double* value) V8_WARN_UNUSED_RESULT;
226 : bool ReadRawBytes(size_t length, const void** data) V8_WARN_UNUSED_RESULT;
227 : void set_expect_inline_wasm(bool expect_inline_wasm) {
228 262 : expect_inline_wasm_ = expect_inline_wasm;
229 : }
230 :
231 : private:
232 : // Reading the wire format.
233 : Maybe<SerializationTag> PeekTag() const V8_WARN_UNUSED_RESULT;
234 : void ConsumeTag(SerializationTag peeked_tag);
235 : Maybe<SerializationTag> ReadTag() V8_WARN_UNUSED_RESULT;
236 : template <typename T>
237 : Maybe<T> ReadVarint() V8_WARN_UNUSED_RESULT;
238 : template <typename T>
239 : Maybe<T> ReadZigZag() V8_WARN_UNUSED_RESULT;
240 : Maybe<double> ReadDouble() V8_WARN_UNUSED_RESULT;
241 : Maybe<Vector<const uint8_t>> ReadRawBytes(int size) V8_WARN_UNUSED_RESULT;
242 : bool expect_inline_wasm() const { return expect_inline_wasm_; }
243 :
244 : // Reads a string if it matches the one provided.
245 : // Returns true if this was the case. Otherwise, nothing is consumed.
246 : bool ReadExpectedString(Handle<String> expected) V8_WARN_UNUSED_RESULT;
247 :
248 : // Like ReadObject, but skips logic for special cases in simulating the
249 : // "stack machine".
250 : MaybeHandle<Object> ReadObjectInternal() V8_WARN_UNUSED_RESULT;
251 :
252 : // Reads a string intended to be part of a more complicated object.
253 : // Before v12, these are UTF-8 strings. After, they can be any encoding
254 : // permissible for a string (with the relevant tag).
255 : MaybeHandle<String> ReadString() V8_WARN_UNUSED_RESULT;
256 :
257 : // Reading V8 objects of specific kinds.
258 : // The tag is assumed to have already been read.
259 : MaybeHandle<BigInt> ReadBigInt() V8_WARN_UNUSED_RESULT;
260 : MaybeHandle<String> ReadUtf8String() V8_WARN_UNUSED_RESULT;
261 : MaybeHandle<String> ReadOneByteString() V8_WARN_UNUSED_RESULT;
262 : MaybeHandle<String> ReadTwoByteString() V8_WARN_UNUSED_RESULT;
263 : MaybeHandle<JSObject> ReadJSObject() V8_WARN_UNUSED_RESULT;
264 : MaybeHandle<JSArray> ReadSparseJSArray() V8_WARN_UNUSED_RESULT;
265 : MaybeHandle<JSArray> ReadDenseJSArray() V8_WARN_UNUSED_RESULT;
266 : MaybeHandle<JSDate> ReadJSDate() V8_WARN_UNUSED_RESULT;
267 : MaybeHandle<JSValue> ReadJSValue(SerializationTag tag) V8_WARN_UNUSED_RESULT;
268 : MaybeHandle<JSRegExp> ReadJSRegExp() V8_WARN_UNUSED_RESULT;
269 : MaybeHandle<JSMap> ReadJSMap() V8_WARN_UNUSED_RESULT;
270 : MaybeHandle<JSSet> ReadJSSet() V8_WARN_UNUSED_RESULT;
271 : MaybeHandle<JSArrayBuffer> ReadJSArrayBuffer(bool is_shared)
272 : V8_WARN_UNUSED_RESULT;
273 : MaybeHandle<JSArrayBuffer> ReadTransferredJSArrayBuffer()
274 : V8_WARN_UNUSED_RESULT;
275 : MaybeHandle<JSArrayBufferView> ReadJSArrayBufferView(
276 : Handle<JSArrayBuffer> buffer) V8_WARN_UNUSED_RESULT;
277 : MaybeHandle<JSObject> ReadWasmModule() V8_WARN_UNUSED_RESULT;
278 : MaybeHandle<JSObject> ReadWasmModuleTransfer() V8_WARN_UNUSED_RESULT;
279 : MaybeHandle<WasmMemoryObject> ReadWasmMemory() V8_WARN_UNUSED_RESULT;
280 : MaybeHandle<JSObject> ReadHostObject() V8_WARN_UNUSED_RESULT;
281 :
282 : /*
283 : * Reads key-value pairs into the object until the specified end tag is
284 : * encountered. If successful, returns the number of properties read.
285 : */
286 : Maybe<uint32_t> ReadJSObjectProperties(Handle<JSObject> object,
287 : SerializationTag end_tag,
288 : bool can_use_transitions);
289 :
290 : // Manipulating the map from IDs to reified objects.
291 : bool HasObjectWithID(uint32_t id);
292 : MaybeHandle<JSReceiver> GetObjectWithID(uint32_t id);
293 : void AddObjectWithID(uint32_t id, Handle<JSReceiver> object);
294 :
295 : Isolate* const isolate_;
296 : v8::ValueDeserializer::Delegate* const delegate_;
297 : const uint8_t* position_;
298 : const uint8_t* const end_;
299 : AllocationType allocation_;
300 : uint32_t version_ = 0;
301 : uint32_t next_id_ = 0;
302 : bool expect_inline_wasm_ = false;
303 :
304 : // Always global handles.
305 : Handle<FixedArray> id_map_;
306 : MaybeHandle<SimpleNumberDictionary> array_buffer_transfer_map_;
307 :
308 : DISALLOW_COPY_AND_ASSIGN(ValueDeserializer);
309 : };
310 :
311 : } // namespace internal
312 : } // namespace v8
313 :
314 : #endif // V8_VALUE_SERIALIZER_H_
|