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 #include "src/value-serializer.h"
6
7 #include <type_traits>
8
9 #include "include/v8-value-serializer-version.h"
10 #include "src/api-inl.h"
11 #include "src/base/logging.h"
12 #include "src/conversions.h"
13 #include "src/flags.h"
14 #include "src/handles-inl.h"
15 #include "src/heap/factory.h"
16 #include "src/isolate.h"
17 #include "src/maybe-handles-inl.h"
18 #include "src/objects-inl.h"
19 #include "src/objects/js-array-inl.h"
20 #include "src/objects/js-collection-inl.h"
21 #include "src/objects/js-regexp-inl.h"
22 #include "src/objects/ordered-hash-table-inl.h"
23 #include "src/snapshot/code-serializer.h"
24 #include "src/transitions.h"
25 #include "src/wasm/wasm-engine.h"
26 #include "src/wasm/wasm-objects-inl.h"
27 #include "src/wasm/wasm-result.h"
28 #include "src/wasm/wasm-serialization.h"
29
30 namespace v8 {
31 namespace internal {
32
33 // Version 9: (imported from Blink)
34 // Version 10: one-byte (Latin-1) strings
35 // Version 11: properly separate undefined from the hole in arrays
36 // Version 12: regexp and string objects share normal string encoding
37 // Version 13: host objects have an explicit tag (rather than handling all
38 // unknown tags)
39 //
40 // WARNING: Increasing this value is a change which cannot safely be rolled
41 // back without breaking compatibility with data stored on disk. It is
42 // strongly recommended that you do not make such changes near a release
43 // milestone branch point.
44 //
45 // Recent changes are routinely reverted in preparation for branch, and this
46 // has been the cause of at least one bug in the past.
47 static const uint32_t kLatestVersion = 13;
48 static_assert(kLatestVersion == v8::CurrentValueSerializerFormatVersion(),
49 "Exported format version must match latest version.");
50
51 static const int kPretenureThreshold = 100 * KB;
52
53 template <typename T>
BytesNeededForVarint(T value)54 static size_t BytesNeededForVarint(T value) {
55 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
56 "Only unsigned integer types can be written as varints.");
57 size_t result = 0;
58 do {
59 result++;
60 value >>= 7;
61 } while (value);
62 return result;
63 }
64
65 // Note that some additional tag values are defined in Blink's
66 // Source/bindings/core/v8/serialization/SerializationTag.h, which must
67 // not clash with values defined here.
68 enum class SerializationTag : uint8_t {
69 // version:uint32_t (if at beginning of data, sets version > 0)
70 kVersion = 0xFF,
71 // ignore
72 kPadding = '\0',
73 // refTableSize:uint32_t (previously used for sanity checks; safe to ignore)
74 kVerifyObjectCount = '?',
75 // Oddballs (no data).
76 kTheHole = '-',
77 kUndefined = '_',
78 kNull = '0',
79 kTrue = 'T',
80 kFalse = 'F',
81 // Number represented as 32-bit integer, ZigZag-encoded
82 // (like sint32 in protobuf)
83 kInt32 = 'I',
84 // Number represented as 32-bit unsigned integer, varint-encoded
85 // (like uint32 in protobuf)
86 kUint32 = 'U',
87 // Number represented as a 64-bit double.
88 // Host byte order is used (N.B. this makes the format non-portable).
89 kDouble = 'N',
90 // BigInt. Bitfield:uint32_t, then raw digits storage.
91 kBigInt = 'Z',
92 // byteLength:uint32_t, then raw data
93 kUtf8String = 'S',
94 kOneByteString = '"',
95 kTwoByteString = 'c',
96 // Reference to a serialized object. objectID:uint32_t
97 kObjectReference = '^',
98 // Beginning of a JS object.
99 kBeginJSObject = 'o',
100 // End of a JS object. numProperties:uint32_t
101 kEndJSObject = '{',
102 // Beginning of a sparse JS array. length:uint32_t
103 // Elements and properties are written as key/value pairs, like objects.
104 kBeginSparseJSArray = 'a',
105 // End of a sparse JS array. numProperties:uint32_t length:uint32_t
106 kEndSparseJSArray = '@',
107 // Beginning of a dense JS array. length:uint32_t
108 // |length| elements, followed by properties as key/value pairs
109 kBeginDenseJSArray = 'A',
110 // End of a dense JS array. numProperties:uint32_t length:uint32_t
111 kEndDenseJSArray = '$',
112 // Date. millisSinceEpoch:double
113 kDate = 'D',
114 // Boolean object. No data.
115 kTrueObject = 'y',
116 kFalseObject = 'x',
117 // Number object. value:double
118 kNumberObject = 'n',
119 // BigInt object. Bitfield:uint32_t, then raw digits storage.
120 kBigIntObject = 'z',
121 // String object, UTF-8 encoding. byteLength:uint32_t, then raw data.
122 kStringObject = 's',
123 // Regular expression, UTF-8 encoding. byteLength:uint32_t, raw data,
124 // flags:uint32_t.
125 kRegExp = 'R',
126 // Beginning of a JS map.
127 kBeginJSMap = ';',
128 // End of a JS map. length:uint32_t.
129 kEndJSMap = ':',
130 // Beginning of a JS set.
131 kBeginJSSet = '\'',
132 // End of a JS set. length:uint32_t.
133 kEndJSSet = ',',
134 // Array buffer. byteLength:uint32_t, then raw data.
135 kArrayBuffer = 'B',
136 // Array buffer (transferred). transferID:uint32_t
137 kArrayBufferTransfer = 't',
138 // View into an array buffer.
139 // subtag:ArrayBufferViewTag, byteOffset:uint32_t, byteLength:uint32_t
140 // For typed arrays, byteOffset and byteLength must be divisible by the size
141 // of the element.
142 // Note: kArrayBufferView is special, and should have an ArrayBuffer (or an
143 // ObjectReference to one) serialized just before it. This is a quirk arising
144 // from the previous stack-based implementation.
145 kArrayBufferView = 'V',
146 // Shared array buffer. transferID:uint32_t
147 kSharedArrayBuffer = 'u',
148 // Compiled WebAssembly module. encodingType:(one-byte tag).
149 // If encodingType == 'y' (raw bytes):
150 // wasmWireByteLength:uint32_t, then raw data
151 // compiledDataLength:uint32_t, then raw data
152 kWasmModule = 'W',
153 // A wasm module object transfer. next value is its index.
154 kWasmModuleTransfer = 'w',
155 // The delegate is responsible for processing all following data.
156 // This "escapes" to whatever wire format the delegate chooses.
157 kHostObject = '\\',
158 // A transferred WebAssembly.Memory object. maximumPages:int32_t, then by
159 // SharedArrayBuffer tag and its data.
160 kWasmMemoryTransfer = 'm',
161 };
162
163 namespace {
164
165 enum class ArrayBufferViewTag : uint8_t {
166 kInt8Array = 'b',
167 kUint8Array = 'B',
168 kUint8ClampedArray = 'C',
169 kInt16Array = 'w',
170 kUint16Array = 'W',
171 kInt32Array = 'd',
172 kUint32Array = 'D',
173 kFloat32Array = 'f',
174 kFloat64Array = 'F',
175 kBigInt64Array = 'q',
176 kBigUint64Array = 'Q',
177 kDataView = '?',
178 };
179
180 enum class WasmEncodingTag : uint8_t {
181 kRawBytes = 'y',
182 };
183
184 } // namespace
185
ValueSerializer(Isolate * isolate,v8::ValueSerializer::Delegate * delegate)186 ValueSerializer::ValueSerializer(Isolate* isolate,
187 v8::ValueSerializer::Delegate* delegate)
188 : isolate_(isolate),
189 delegate_(delegate),
190 zone_(isolate->allocator(), ZONE_NAME),
191 id_map_(isolate->heap(), ZoneAllocationPolicy(&zone_)),
192 array_buffer_transfer_map_(isolate->heap(),
193 ZoneAllocationPolicy(&zone_)) {}
194
~ValueSerializer()195 ValueSerializer::~ValueSerializer() {
196 if (buffer_) {
197 if (delegate_) {
198 delegate_->FreeBufferMemory(buffer_);
199 } else {
200 free(buffer_);
201 }
202 }
203 }
204
WriteHeader()205 void ValueSerializer::WriteHeader() {
206 WriteTag(SerializationTag::kVersion);
207 WriteVarint(kLatestVersion);
208 }
209
SetTreatArrayBufferViewsAsHostObjects(bool mode)210 void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(bool mode) {
211 treat_array_buffer_views_as_host_objects_ = mode;
212 }
213
WriteTag(SerializationTag tag)214 void ValueSerializer::WriteTag(SerializationTag tag) {
215 uint8_t raw_tag = static_cast<uint8_t>(tag);
216 WriteRawBytes(&raw_tag, sizeof(raw_tag));
217 }
218
219 template <typename T>
WriteVarint(T value)220 void ValueSerializer::WriteVarint(T value) {
221 // Writes an unsigned integer as a base-128 varint.
222 // The number is written, 7 bits at a time, from the least significant to the
223 // most significant 7 bits. Each byte, except the last, has the MSB set.
224 // See also https://developers.google.com/protocol-buffers/docs/encoding
225 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
226 "Only unsigned integer types can be written as varints.");
227 uint8_t stack_buffer[sizeof(T) * 8 / 7 + 1];
228 uint8_t* next_byte = &stack_buffer[0];
229 do {
230 *next_byte = (value & 0x7F) | 0x80;
231 next_byte++;
232 value >>= 7;
233 } while (value);
234 *(next_byte - 1) &= 0x7F;
235 WriteRawBytes(stack_buffer, next_byte - stack_buffer);
236 }
237
238 template <typename T>
WriteZigZag(T value)239 void ValueSerializer::WriteZigZag(T value) {
240 // Writes a signed integer as a varint using ZigZag encoding (i.e. 0 is
241 // encoded as 0, -1 as 1, 1 as 2, -2 as 3, and so on).
242 // See also https://developers.google.com/protocol-buffers/docs/encoding
243 // Note that this implementation relies on the right shift being arithmetic.
244 static_assert(std::is_integral<T>::value && std::is_signed<T>::value,
245 "Only signed integer types can be written as zigzag.");
246 using UnsignedT = typename std::make_unsigned<T>::type;
247 WriteVarint((static_cast<UnsignedT>(value) << 1) ^
248 (value >> (8 * sizeof(T) - 1)));
249 }
250
WriteDouble(double value)251 void ValueSerializer::WriteDouble(double value) {
252 // Warning: this uses host endianness.
253 WriteRawBytes(&value, sizeof(value));
254 }
255
WriteOneByteString(Vector<const uint8_t> chars)256 void ValueSerializer::WriteOneByteString(Vector<const uint8_t> chars) {
257 WriteVarint<uint32_t>(chars.length());
258 WriteRawBytes(chars.begin(), chars.length() * sizeof(uint8_t));
259 }
260
WriteTwoByteString(Vector<const uc16> chars)261 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) {
262 // Warning: this uses host endianness.
263 WriteVarint<uint32_t>(chars.length() * sizeof(uc16));
264 WriteRawBytes(chars.begin(), chars.length() * sizeof(uc16));
265 }
266
WriteBigIntContents(BigInt * bigint)267 void ValueSerializer::WriteBigIntContents(BigInt* bigint) {
268 uint32_t bitfield = bigint->GetBitfieldForSerialization();
269 int bytelength = BigInt::DigitsByteLengthForBitfield(bitfield);
270 WriteVarint<uint32_t>(bitfield);
271 uint8_t* dest;
272 if (ReserveRawBytes(bytelength).To(&dest)) {
273 bigint->SerializeDigits(dest);
274 }
275 }
276
WriteRawBytes(const void * source,size_t length)277 void ValueSerializer::WriteRawBytes(const void* source, size_t length) {
278 uint8_t* dest;
279 if (ReserveRawBytes(length).To(&dest)) {
280 memcpy(dest, source, length);
281 }
282 }
283
ReserveRawBytes(size_t bytes)284 Maybe<uint8_t*> ValueSerializer::ReserveRawBytes(size_t bytes) {
285 size_t old_size = buffer_size_;
286 size_t new_size = old_size + bytes;
287 if (V8_UNLIKELY(new_size > buffer_capacity_)) {
288 bool ok;
289 if (!ExpandBuffer(new_size).To(&ok)) {
290 return Nothing<uint8_t*>();
291 }
292 }
293 buffer_size_ = new_size;
294 return Just(&buffer_[old_size]);
295 }
296
ExpandBuffer(size_t required_capacity)297 Maybe<bool> ValueSerializer::ExpandBuffer(size_t required_capacity) {
298 DCHECK_GT(required_capacity, buffer_capacity_);
299 size_t requested_capacity =
300 std::max(required_capacity, buffer_capacity_ * 2) + 64;
301 size_t provided_capacity = 0;
302 void* new_buffer = nullptr;
303 if (delegate_) {
304 new_buffer = delegate_->ReallocateBufferMemory(buffer_, requested_capacity,
305 &provided_capacity);
306 } else {
307 new_buffer = realloc(buffer_, requested_capacity);
308 provided_capacity = requested_capacity;
309 }
310 if (new_buffer) {
311 DCHECK(provided_capacity >= requested_capacity);
312 buffer_ = reinterpret_cast<uint8_t*>(new_buffer);
313 buffer_capacity_ = provided_capacity;
314 return Just(true);
315 } else {
316 out_of_memory_ = true;
317 return Nothing<bool>();
318 }
319 }
320
WriteUint32(uint32_t value)321 void ValueSerializer::WriteUint32(uint32_t value) {
322 WriteVarint<uint32_t>(value);
323 }
324
WriteUint64(uint64_t value)325 void ValueSerializer::WriteUint64(uint64_t value) {
326 WriteVarint<uint64_t>(value);
327 }
328
ReleaseBuffer()329 std::vector<uint8_t> ValueSerializer::ReleaseBuffer() {
330 return std::vector<uint8_t>(buffer_, buffer_ + buffer_size_);
331 }
332
Release()333 std::pair<uint8_t*, size_t> ValueSerializer::Release() {
334 auto result = std::make_pair(buffer_, buffer_size_);
335 buffer_ = nullptr;
336 buffer_size_ = 0;
337 buffer_capacity_ = 0;
338 return result;
339 }
340
TransferArrayBuffer(uint32_t transfer_id,Handle<JSArrayBuffer> array_buffer)341 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id,
342 Handle<JSArrayBuffer> array_buffer) {
343 DCHECK(!array_buffer_transfer_map_.Find(array_buffer));
344 DCHECK(!array_buffer->is_shared());
345 array_buffer_transfer_map_.Set(array_buffer, transfer_id);
346 }
347
WriteObject(Handle<Object> object)348 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) {
349 out_of_memory_ = false;
350 if (object->IsSmi()) {
351 WriteSmi(Smi::cast(*object));
352 return ThrowIfOutOfMemory();
353 }
354
355 DCHECK(object->IsHeapObject());
356 switch (HeapObject::cast(*object)->map()->instance_type()) {
357 case ODDBALL_TYPE:
358 WriteOddball(Oddball::cast(*object));
359 return ThrowIfOutOfMemory();
360 case HEAP_NUMBER_TYPE:
361 WriteHeapNumber(HeapNumber::cast(*object));
362 return ThrowIfOutOfMemory();
363 case MUTABLE_HEAP_NUMBER_TYPE:
364 WriteMutableHeapNumber(MutableHeapNumber::cast(*object));
365 return ThrowIfOutOfMemory();
366 case BIGINT_TYPE:
367 WriteBigInt(BigInt::cast(*object));
368 return ThrowIfOutOfMemory();
369 case JS_TYPED_ARRAY_TYPE:
370 case JS_DATA_VIEW_TYPE: {
371 // Despite being JSReceivers, these have their wrapped buffer serialized
372 // first. That makes this logic a little quirky, because it needs to
373 // happen before we assign object IDs.
374 // TODO(jbroman): It may be possible to avoid materializing a typed
375 // array's buffer here.
376 Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(object);
377 if (!id_map_.Find(view) && !treat_array_buffer_views_as_host_objects_) {
378 Handle<JSArrayBuffer> buffer(
379 view->IsJSTypedArray()
380 ? Handle<JSTypedArray>::cast(view)->GetBuffer()
381 : handle(JSArrayBuffer::cast(view->buffer()), isolate_));
382 if (!WriteJSReceiver(buffer).FromMaybe(false)) return Nothing<bool>();
383 }
384 return WriteJSReceiver(view);
385 }
386 default:
387 if (object->IsString()) {
388 WriteString(Handle<String>::cast(object));
389 return ThrowIfOutOfMemory();
390 } else if (object->IsJSReceiver()) {
391 return WriteJSReceiver(Handle<JSReceiver>::cast(object));
392 } else {
393 ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
394 return Nothing<bool>();
395 }
396 }
397 }
398
WriteOddball(Oddball * oddball)399 void ValueSerializer::WriteOddball(Oddball* oddball) {
400 SerializationTag tag = SerializationTag::kUndefined;
401 switch (oddball->kind()) {
402 case Oddball::kUndefined:
403 tag = SerializationTag::kUndefined;
404 break;
405 case Oddball::kFalse:
406 tag = SerializationTag::kFalse;
407 break;
408 case Oddball::kTrue:
409 tag = SerializationTag::kTrue;
410 break;
411 case Oddball::kNull:
412 tag = SerializationTag::kNull;
413 break;
414 default:
415 UNREACHABLE();
416 break;
417 }
418 WriteTag(tag);
419 }
420
WriteSmi(Smi * smi)421 void ValueSerializer::WriteSmi(Smi* smi) {
422 static_assert(kSmiValueSize <= 32, "Expected SMI <= 32 bits.");
423 WriteTag(SerializationTag::kInt32);
424 WriteZigZag<int32_t>(smi->value());
425 }
426
WriteHeapNumber(HeapNumber * number)427 void ValueSerializer::WriteHeapNumber(HeapNumber* number) {
428 WriteTag(SerializationTag::kDouble);
429 WriteDouble(number->value());
430 }
431
WriteMutableHeapNumber(MutableHeapNumber * number)432 void ValueSerializer::WriteMutableHeapNumber(MutableHeapNumber* number) {
433 WriteTag(SerializationTag::kDouble);
434 WriteDouble(number->value());
435 }
436
WriteBigInt(BigInt * bigint)437 void ValueSerializer::WriteBigInt(BigInt* bigint) {
438 WriteTag(SerializationTag::kBigInt);
439 WriteBigIntContents(bigint);
440 }
441
WriteString(Handle<String> string)442 void ValueSerializer::WriteString(Handle<String> string) {
443 string = String::Flatten(isolate_, string);
444 DisallowHeapAllocation no_gc;
445 String::FlatContent flat = string->GetFlatContent();
446 DCHECK(flat.IsFlat());
447 if (flat.IsOneByte()) {
448 Vector<const uint8_t> chars = flat.ToOneByteVector();
449 WriteTag(SerializationTag::kOneByteString);
450 WriteOneByteString(chars);
451 } else if (flat.IsTwoByte()) {
452 Vector<const uc16> chars = flat.ToUC16Vector();
453 uint32_t byte_length = chars.length() * sizeof(uc16);
454 // The existing reading code expects 16-byte strings to be aligned.
455 if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1)
456 WriteTag(SerializationTag::kPadding);
457 WriteTag(SerializationTag::kTwoByteString);
458 WriteTwoByteString(chars);
459 } else {
460 UNREACHABLE();
461 }
462 }
463
WriteJSReceiver(Handle<JSReceiver> receiver)464 Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
465 // If the object has already been serialized, just write its ID.
466 uint32_t* id_map_entry = id_map_.Get(receiver);
467 if (uint32_t id = *id_map_entry) {
468 WriteTag(SerializationTag::kObjectReference);
469 WriteVarint(id - 1);
470 return ThrowIfOutOfMemory();
471 }
472
473 // Otherwise, allocate an ID for it.
474 uint32_t id = next_id_++;
475 *id_map_entry = id + 1;
476
477 // Eliminate callable and exotic objects, which should not be serialized.
478 InstanceType instance_type = receiver->map()->instance_type();
479 if (receiver->IsCallable() || (IsSpecialReceiverInstanceType(instance_type) &&
480 instance_type != JS_SPECIAL_API_OBJECT_TYPE)) {
481 ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
482 return Nothing<bool>();
483 }
484
485 // If we are at the end of the stack, abort. This function may recurse.
486 STACK_CHECK(isolate_, Nothing<bool>());
487
488 HandleScope scope(isolate_);
489 switch (instance_type) {
490 case JS_ARRAY_TYPE:
491 return WriteJSArray(Handle<JSArray>::cast(receiver));
492 case JS_OBJECT_TYPE:
493 case JS_API_OBJECT_TYPE: {
494 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver);
495 if (JSObject::GetEmbedderFieldCount(js_object->map())) {
496 return WriteHostObject(js_object);
497 } else {
498 return WriteJSObject(js_object);
499 }
500 }
501 case JS_SPECIAL_API_OBJECT_TYPE:
502 return WriteHostObject(Handle<JSObject>::cast(receiver));
503 case JS_DATE_TYPE:
504 WriteJSDate(JSDate::cast(*receiver));
505 return ThrowIfOutOfMemory();
506 case JS_VALUE_TYPE:
507 return WriteJSValue(Handle<JSValue>::cast(receiver));
508 case JS_REGEXP_TYPE:
509 WriteJSRegExp(JSRegExp::cast(*receiver));
510 return ThrowIfOutOfMemory();
511 case JS_MAP_TYPE:
512 return WriteJSMap(Handle<JSMap>::cast(receiver));
513 case JS_SET_TYPE:
514 return WriteJSSet(Handle<JSSet>::cast(receiver));
515 case JS_ARRAY_BUFFER_TYPE:
516 return WriteJSArrayBuffer(Handle<JSArrayBuffer>::cast(receiver));
517 case JS_TYPED_ARRAY_TYPE:
518 case JS_DATA_VIEW_TYPE:
519 return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver));
520 case WASM_MODULE_TYPE: {
521 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
522 if (!FLAG_wasm_disable_structured_cloning || enabled_features.threads) {
523 // Only write WebAssembly modules if not disabled by a flag.
524 return WriteWasmModule(Handle<WasmModuleObject>::cast(receiver));
525 }
526 break;
527 }
528 case WASM_MEMORY_TYPE: {
529 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
530 if (enabled_features.threads) {
531 return WriteWasmMemory(Handle<WasmMemoryObject>::cast(receiver));
532 }
533 break;
534 }
535 default:
536 break;
537 }
538
539 ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
540 return Nothing<bool>();
541 }
542
WriteJSObject(Handle<JSObject> object)543 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) {
544 DCHECK(!object->map()->IsCustomElementsReceiverMap());
545 const bool can_serialize_fast =
546 object->HasFastProperties() && object->elements()->length() == 0;
547 if (!can_serialize_fast) return WriteJSObjectSlow(object);
548
549 Handle<Map> map(object->map(), isolate_);
550 WriteTag(SerializationTag::kBeginJSObject);
551
552 // Write out fast properties as long as they are only data properties and the
553 // map doesn't change.
554 uint32_t properties_written = 0;
555 bool map_changed = false;
556 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
557 Handle<Name> key(map->instance_descriptors()->GetKey(i), isolate_);
558 if (!key->IsString()) continue;
559 PropertyDetails details = map->instance_descriptors()->GetDetails(i);
560 if (details.IsDontEnum()) continue;
561
562 Handle<Object> value;
563 if (V8_LIKELY(!map_changed)) map_changed = *map == object->map();
564 if (V8_LIKELY(!map_changed && details.location() == kField)) {
565 DCHECK_EQ(kData, details.kind());
566 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
567 value = JSObject::FastPropertyAt(object, details.representation(),
568 field_index);
569 } else {
570 // This logic should essentially match WriteJSObjectPropertiesSlow.
571 // If the property is no longer found, do not serialize it.
572 // This could happen if a getter deleted the property.
573 LookupIterator it(isolate_, object, key, LookupIterator::OWN);
574 if (!it.IsFound()) continue;
575 if (!Object::GetProperty(&it).ToHandle(&value)) return Nothing<bool>();
576 }
577
578 if (!WriteObject(key).FromMaybe(false) ||
579 !WriteObject(value).FromMaybe(false)) {
580 return Nothing<bool>();
581 }
582 properties_written++;
583 }
584
585 WriteTag(SerializationTag::kEndJSObject);
586 WriteVarint<uint32_t>(properties_written);
587 return ThrowIfOutOfMemory();
588 }
589
WriteJSObjectSlow(Handle<JSObject> object)590 Maybe<bool> ValueSerializer::WriteJSObjectSlow(Handle<JSObject> object) {
591 WriteTag(SerializationTag::kBeginJSObject);
592 Handle<FixedArray> keys;
593 uint32_t properties_written = 0;
594 if (!KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
595 ENUMERABLE_STRINGS)
596 .ToHandle(&keys) ||
597 !WriteJSObjectPropertiesSlow(object, keys).To(&properties_written)) {
598 return Nothing<bool>();
599 }
600 WriteTag(SerializationTag::kEndJSObject);
601 WriteVarint<uint32_t>(properties_written);
602 return ThrowIfOutOfMemory();
603 }
604
WriteJSArray(Handle<JSArray> array)605 Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) {
606 uint32_t length = 0;
607 bool valid_length = array->length()->ToArrayLength(&length);
608 DCHECK(valid_length);
609 USE(valid_length);
610
611 // To keep things simple, for now we decide between dense and sparse
612 // serialization based on elements kind. A more principled heuristic could
613 // count the elements, but would need to take care to note which indices
614 // existed (as only indices which were enumerable own properties at this point
615 // should be serialized).
616 const bool should_serialize_densely =
617 array->HasFastElements() && !array->HasHoleyElements();
618
619 if (should_serialize_densely) {
620 DCHECK_LE(length, static_cast<uint32_t>(FixedArray::kMaxLength));
621 WriteTag(SerializationTag::kBeginDenseJSArray);
622 WriteVarint<uint32_t>(length);
623 uint32_t i = 0;
624
625 // Fast paths. Note that PACKED_ELEMENTS in particular can bail due to the
626 // structure of the elements changing.
627 switch (array->GetElementsKind()) {
628 case PACKED_SMI_ELEMENTS: {
629 Handle<FixedArray> elements(FixedArray::cast(array->elements()),
630 isolate_);
631 for (; i < length; i++) WriteSmi(Smi::cast(elements->get(i)));
632 break;
633 }
634 case PACKED_DOUBLE_ELEMENTS: {
635 // Elements are empty_fixed_array, not a FixedDoubleArray, if the array
636 // is empty. No elements to encode in this case anyhow.
637 if (length == 0) break;
638 Handle<FixedDoubleArray> elements(
639 FixedDoubleArray::cast(array->elements()), isolate_);
640 for (; i < length; i++) {
641 WriteTag(SerializationTag::kDouble);
642 WriteDouble(elements->get_scalar(i));
643 }
644 break;
645 }
646 case PACKED_ELEMENTS: {
647 Handle<Object> old_length(array->length(), isolate_);
648 for (; i < length; i++) {
649 if (array->length() != *old_length ||
650 array->GetElementsKind() != PACKED_ELEMENTS) {
651 // Fall back to slow path.
652 break;
653 }
654 Handle<Object> element(FixedArray::cast(array->elements())->get(i),
655 isolate_);
656 if (!WriteObject(element).FromMaybe(false)) return Nothing<bool>();
657 }
658 break;
659 }
660 default:
661 break;
662 }
663
664 // If there are elements remaining, serialize them slowly.
665 for (; i < length; i++) {
666 // Serializing the array's elements can have arbitrary side effects, so we
667 // cannot rely on still having fast elements, even if it did to begin
668 // with.
669 Handle<Object> element;
670 LookupIterator it(isolate_, array, i, array, LookupIterator::OWN);
671 if (!it.IsFound()) {
672 // This can happen in the case where an array that was originally dense
673 // became sparse during serialization. It's too late to switch to the
674 // sparse format, but we can mark the elements as absent.
675 WriteTag(SerializationTag::kTheHole);
676 continue;
677 }
678 if (!Object::GetProperty(&it).ToHandle(&element) ||
679 !WriteObject(element).FromMaybe(false)) {
680 return Nothing<bool>();
681 }
682 }
683
684 KeyAccumulator accumulator(isolate_, KeyCollectionMode::kOwnOnly,
685 ENUMERABLE_STRINGS);
686 if (!accumulator.CollectOwnPropertyNames(array, array).FromMaybe(false)) {
687 return Nothing<bool>();
688 }
689 Handle<FixedArray> keys =
690 accumulator.GetKeys(GetKeysConversion::kConvertToString);
691 uint32_t properties_written;
692 if (!WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) {
693 return Nothing<bool>();
694 }
695 WriteTag(SerializationTag::kEndDenseJSArray);
696 WriteVarint<uint32_t>(properties_written);
697 WriteVarint<uint32_t>(length);
698 } else {
699 WriteTag(SerializationTag::kBeginSparseJSArray);
700 WriteVarint<uint32_t>(length);
701 Handle<FixedArray> keys;
702 uint32_t properties_written = 0;
703 if (!KeyAccumulator::GetKeys(array, KeyCollectionMode::kOwnOnly,
704 ENUMERABLE_STRINGS)
705 .ToHandle(&keys) ||
706 !WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) {
707 return Nothing<bool>();
708 }
709 WriteTag(SerializationTag::kEndSparseJSArray);
710 WriteVarint<uint32_t>(properties_written);
711 WriteVarint<uint32_t>(length);
712 }
713 return ThrowIfOutOfMemory();
714 }
715
WriteJSDate(JSDate * date)716 void ValueSerializer::WriteJSDate(JSDate* date) {
717 WriteTag(SerializationTag::kDate);
718 WriteDouble(date->value()->Number());
719 }
720
WriteJSValue(Handle<JSValue> value)721 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) {
722 Object* inner_value = value->value();
723 if (inner_value->IsTrue(isolate_)) {
724 WriteTag(SerializationTag::kTrueObject);
725 } else if (inner_value->IsFalse(isolate_)) {
726 WriteTag(SerializationTag::kFalseObject);
727 } else if (inner_value->IsNumber()) {
728 WriteTag(SerializationTag::kNumberObject);
729 WriteDouble(inner_value->Number());
730 } else if (inner_value->IsBigInt()) {
731 WriteTag(SerializationTag::kBigIntObject);
732 WriteBigIntContents(BigInt::cast(inner_value));
733 } else if (inner_value->IsString()) {
734 WriteTag(SerializationTag::kStringObject);
735 WriteString(handle(String::cast(inner_value), isolate_));
736 } else {
737 DCHECK(inner_value->IsSymbol());
738 ThrowDataCloneError(MessageTemplate::kDataCloneError, value);
739 return Nothing<bool>();
740 }
741 return ThrowIfOutOfMemory();
742 }
743
WriteJSRegExp(JSRegExp * regexp)744 void ValueSerializer::WriteJSRegExp(JSRegExp* regexp) {
745 WriteTag(SerializationTag::kRegExp);
746 WriteString(handle(regexp->Pattern(), isolate_));
747 WriteVarint(static_cast<uint32_t>(regexp->GetFlags()));
748 }
749
WriteJSMap(Handle<JSMap> map)750 Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) {
751 // First copy the key-value pairs, since getters could mutate them.
752 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()), isolate_);
753 int length = table->NumberOfElements() * 2;
754 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length);
755 {
756 DisallowHeapAllocation no_gc;
757 Oddball* the_hole = ReadOnlyRoots(isolate_).the_hole_value();
758 int capacity = table->UsedCapacity();
759 int result_index = 0;
760 for (int i = 0; i < capacity; i++) {
761 Object* key = table->KeyAt(i);
762 if (key == the_hole) continue;
763 entries->set(result_index++, key);
764 entries->set(result_index++, table->ValueAt(i));
765 }
766 DCHECK_EQ(result_index, length);
767 }
768
769 // Then write it out.
770 WriteTag(SerializationTag::kBeginJSMap);
771 for (int i = 0; i < length; i++) {
772 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) {
773 return Nothing<bool>();
774 }
775 }
776 WriteTag(SerializationTag::kEndJSMap);
777 WriteVarint<uint32_t>(length);
778 return ThrowIfOutOfMemory();
779 }
780
WriteJSSet(Handle<JSSet> set)781 Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> set) {
782 // First copy the element pointers, since getters could mutate them.
783 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()), isolate_);
784 int length = table->NumberOfElements();
785 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length);
786 {
787 DisallowHeapAllocation no_gc;
788 Oddball* the_hole = ReadOnlyRoots(isolate_).the_hole_value();
789 int capacity = table->UsedCapacity();
790 int result_index = 0;
791 for (int i = 0; i < capacity; i++) {
792 Object* key = table->KeyAt(i);
793 if (key == the_hole) continue;
794 entries->set(result_index++, key);
795 }
796 DCHECK_EQ(result_index, length);
797 }
798
799 // Then write it out.
800 WriteTag(SerializationTag::kBeginJSSet);
801 for (int i = 0; i < length; i++) {
802 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) {
803 return Nothing<bool>();
804 }
805 }
806 WriteTag(SerializationTag::kEndJSSet);
807 WriteVarint<uint32_t>(length);
808 return ThrowIfOutOfMemory();
809 }
810
WriteJSArrayBuffer(Handle<JSArrayBuffer> array_buffer)811 Maybe<bool> ValueSerializer::WriteJSArrayBuffer(
812 Handle<JSArrayBuffer> array_buffer) {
813 if (array_buffer->is_shared()) {
814 if (!delegate_) {
815 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
816 return Nothing<bool>();
817 }
818
819 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
820 Maybe<uint32_t> index = delegate_->GetSharedArrayBufferId(
821 v8_isolate, Utils::ToLocalShared(array_buffer));
822 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
823
824 WriteTag(SerializationTag::kSharedArrayBuffer);
825 WriteVarint(index.FromJust());
826 return ThrowIfOutOfMemory();
827 }
828
829 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer);
830 if (transfer_entry) {
831 WriteTag(SerializationTag::kArrayBufferTransfer);
832 WriteVarint(*transfer_entry);
833 return ThrowIfOutOfMemory();
834 }
835 if (array_buffer->was_neutered()) {
836 ThrowDataCloneError(MessageTemplate::kDataCloneErrorNeuteredArrayBuffer);
837 return Nothing<bool>();
838 }
839 double byte_length = array_buffer->byte_length()->Number();
840 if (byte_length > std::numeric_limits<uint32_t>::max()) {
841 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
842 return Nothing<bool>();
843 }
844 WriteTag(SerializationTag::kArrayBuffer);
845 WriteVarint<uint32_t>(byte_length);
846 WriteRawBytes(array_buffer->backing_store(), byte_length);
847 return ThrowIfOutOfMemory();
848 }
849
WriteJSArrayBufferView(JSArrayBufferView * view)850 Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) {
851 if (treat_array_buffer_views_as_host_objects_) {
852 return WriteHostObject(handle(view, isolate_));
853 }
854 WriteTag(SerializationTag::kArrayBufferView);
855 ArrayBufferViewTag tag = ArrayBufferViewTag::kInt8Array;
856 if (view->IsJSTypedArray()) {
857 switch (JSTypedArray::cast(view)->type()) {
858 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
859 case kExternal##Type##Array: \
860 tag = ArrayBufferViewTag::k##Type##Array; \
861 break;
862 TYPED_ARRAYS(TYPED_ARRAY_CASE)
863 #undef TYPED_ARRAY_CASE
864 }
865 } else {
866 DCHECK(view->IsJSDataView());
867 tag = ArrayBufferViewTag::kDataView;
868 }
869 WriteVarint(static_cast<uint8_t>(tag));
870 WriteVarint(NumberToUint32(view->byte_offset()));
871 WriteVarint(NumberToUint32(view->byte_length()));
872 return ThrowIfOutOfMemory();
873 }
874
WriteWasmModule(Handle<WasmModuleObject> object)875 Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject> object) {
876 if (delegate_ != nullptr) {
877 // TODO(titzer): introduce a Utils::ToLocal for WasmModuleObject.
878 Maybe<uint32_t> transfer_id = delegate_->GetWasmModuleTransferId(
879 reinterpret_cast<v8::Isolate*>(isolate_),
880 v8::Local<v8::WasmCompiledModule>::Cast(
881 Utils::ToLocal(Handle<JSObject>::cast(object))));
882 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
883 uint32_t id = 0;
884 if (transfer_id.To(&id)) {
885 WriteTag(SerializationTag::kWasmModuleTransfer);
886 WriteVarint<uint32_t>(id);
887 return Just(true);
888 }
889 }
890
891 WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes;
892 WriteTag(SerializationTag::kWasmModule);
893 WriteRawBytes(&encoding_tag, sizeof(encoding_tag));
894
895 wasm::NativeModule* native_module = object->native_module();
896 Vector<const uint8_t> wire_bytes = native_module->wire_bytes();
897 WriteVarint<uint32_t>(static_cast<uint32_t>(wire_bytes.size()));
898 uint8_t* destination;
899 if (ReserveRawBytes(wire_bytes.size()).To(&destination)) {
900 memcpy(destination, wire_bytes.start(), wire_bytes.size());
901 }
902
903 wasm::WasmSerializer wasm_serializer(isolate_, native_module);
904 size_t module_size = wasm_serializer.GetSerializedNativeModuleSize();
905 CHECK_GE(std::numeric_limits<uint32_t>::max(), module_size);
906 WriteVarint<uint32_t>(static_cast<uint32_t>(module_size));
907 uint8_t* module_buffer;
908 if (ReserveRawBytes(module_size).To(&module_buffer)) {
909 if (!wasm_serializer.SerializeNativeModule({module_buffer, module_size})) {
910 return Nothing<bool>();
911 }
912 }
913 return ThrowIfOutOfMemory();
914 }
915
WriteWasmMemory(Handle<WasmMemoryObject> object)916 Maybe<bool> ValueSerializer::WriteWasmMemory(Handle<WasmMemoryObject> object) {
917 if (!object->array_buffer()->is_shared()) {
918 ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
919 return Nothing<bool>();
920 }
921
922 WriteTag(SerializationTag::kWasmMemoryTransfer);
923 WriteZigZag<int32_t>(object->maximum_pages());
924 return WriteJSReceiver(Handle<JSReceiver>(object->array_buffer(), isolate_));
925 }
926
WriteHostObject(Handle<JSObject> object)927 Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) {
928 WriteTag(SerializationTag::kHostObject);
929 if (!delegate_) {
930 isolate_->Throw(*isolate_->factory()->NewError(
931 isolate_->error_function(), MessageTemplate::kDataCloneError, object));
932 return Nothing<bool>();
933 }
934 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
935 Maybe<bool> result =
936 delegate_->WriteHostObject(v8_isolate, Utils::ToLocal(object));
937 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
938 DCHECK(!result.IsNothing());
939 return result;
940 }
941
WriteJSObjectPropertiesSlow(Handle<JSObject> object,Handle<FixedArray> keys)942 Maybe<uint32_t> ValueSerializer::WriteJSObjectPropertiesSlow(
943 Handle<JSObject> object, Handle<FixedArray> keys) {
944 uint32_t properties_written = 0;
945 int length = keys->length();
946 for (int i = 0; i < length; i++) {
947 Handle<Object> key(keys->get(i), isolate_);
948
949 bool success;
950 LookupIterator it = LookupIterator::PropertyOrElement(
951 isolate_, object, key, &success, LookupIterator::OWN);
952 DCHECK(success);
953 Handle<Object> value;
954 if (!Object::GetProperty(&it).ToHandle(&value)) return Nothing<uint32_t>();
955
956 // If the property is no longer found, do not serialize it.
957 // This could happen if a getter deleted the property.
958 if (!it.IsFound()) continue;
959
960 if (!WriteObject(key).FromMaybe(false) ||
961 !WriteObject(value).FromMaybe(false)) {
962 return Nothing<uint32_t>();
963 }
964
965 properties_written++;
966 }
967 return Just(properties_written);
968 }
969
ThrowDataCloneError(MessageTemplate::Template template_index)970 void ValueSerializer::ThrowDataCloneError(
971 MessageTemplate::Template template_index) {
972 return ThrowDataCloneError(template_index,
973 isolate_->factory()->empty_string());
974 }
975
ThrowIfOutOfMemory()976 Maybe<bool> ValueSerializer::ThrowIfOutOfMemory() {
977 if (out_of_memory_) {
978 ThrowDataCloneError(MessageTemplate::kDataCloneErrorOutOfMemory);
979 return Nothing<bool>();
980 }
981 return Just(true);
982 }
983
ThrowDataCloneError(MessageTemplate::Template template_index,Handle<Object> arg0)984 void ValueSerializer::ThrowDataCloneError(
985 MessageTemplate::Template template_index, Handle<Object> arg0) {
986 Handle<String> message =
987 MessageTemplate::FormatMessage(isolate_, template_index, arg0);
988 if (delegate_) {
989 delegate_->ThrowDataCloneError(Utils::ToLocal(message));
990 } else {
991 isolate_->Throw(
992 *isolate_->factory()->NewError(isolate_->error_function(), message));
993 }
994 if (isolate_->has_scheduled_exception()) {
995 isolate_->PromoteScheduledException();
996 }
997 }
998
ValueDeserializer(Isolate * isolate,Vector<const uint8_t> data,v8::ValueDeserializer::Delegate * delegate)999 ValueDeserializer::ValueDeserializer(Isolate* isolate,
1000 Vector<const uint8_t> data,
1001 v8::ValueDeserializer::Delegate* delegate)
1002 : isolate_(isolate),
1003 delegate_(delegate),
1004 position_(data.start()),
1005 end_(data.start() + data.length()),
1006 pretenure_(data.length() > kPretenureThreshold ? TENURED : NOT_TENURED),
1007 id_map_(isolate->global_handles()->Create(
1008 ReadOnlyRoots(isolate_).empty_fixed_array())) {}
1009
~ValueDeserializer()1010 ValueDeserializer::~ValueDeserializer() {
1011 GlobalHandles::Destroy(Handle<Object>::cast(id_map_).location());
1012
1013 Handle<Object> transfer_map_handle;
1014 if (array_buffer_transfer_map_.ToHandle(&transfer_map_handle)) {
1015 GlobalHandles::Destroy(transfer_map_handle.location());
1016 }
1017 }
1018
ReadHeader()1019 Maybe<bool> ValueDeserializer::ReadHeader() {
1020 if (position_ < end_ &&
1021 *position_ == static_cast<uint8_t>(SerializationTag::kVersion)) {
1022 ReadTag().ToChecked();
1023 if (!ReadVarint<uint32_t>().To(&version_) || version_ > kLatestVersion) {
1024 isolate_->Throw(*isolate_->factory()->NewError(
1025 MessageTemplate::kDataCloneDeserializationVersionError));
1026 return Nothing<bool>();
1027 }
1028 }
1029 return Just(true);
1030 }
1031
PeekTag() const1032 Maybe<SerializationTag> ValueDeserializer::PeekTag() const {
1033 const uint8_t* peek_position = position_;
1034 SerializationTag tag;
1035 do {
1036 if (peek_position >= end_) return Nothing<SerializationTag>();
1037 tag = static_cast<SerializationTag>(*peek_position);
1038 peek_position++;
1039 } while (tag == SerializationTag::kPadding);
1040 return Just(tag);
1041 }
1042
ConsumeTag(SerializationTag peeked_tag)1043 void ValueDeserializer::ConsumeTag(SerializationTag peeked_tag) {
1044 SerializationTag actual_tag = ReadTag().ToChecked();
1045 DCHECK(actual_tag == peeked_tag);
1046 USE(actual_tag);
1047 }
1048
ReadTag()1049 Maybe<SerializationTag> ValueDeserializer::ReadTag() {
1050 SerializationTag tag;
1051 do {
1052 if (position_ >= end_) return Nothing<SerializationTag>();
1053 tag = static_cast<SerializationTag>(*position_);
1054 position_++;
1055 } while (tag == SerializationTag::kPadding);
1056 return Just(tag);
1057 }
1058
1059 template <typename T>
ReadVarint()1060 Maybe<T> ValueDeserializer::ReadVarint() {
1061 // Reads an unsigned integer as a base-128 varint.
1062 // The number is written, 7 bits at a time, from the least significant to the
1063 // most significant 7 bits. Each byte, except the last, has the MSB set.
1064 // If the varint is larger than T, any more significant bits are discarded.
1065 // See also https://developers.google.com/protocol-buffers/docs/encoding
1066 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
1067 "Only unsigned integer types can be read as varints.");
1068 T value = 0;
1069 unsigned shift = 0;
1070 bool has_another_byte;
1071 do {
1072 if (position_ >= end_) return Nothing<T>();
1073 uint8_t byte = *position_;
1074 if (V8_LIKELY(shift < sizeof(T) * 8)) {
1075 value |= static_cast<T>(byte & 0x7F) << shift;
1076 shift += 7;
1077 }
1078 has_another_byte = byte & 0x80;
1079 position_++;
1080 } while (has_another_byte);
1081 return Just(value);
1082 }
1083
1084 template <typename T>
ReadZigZag()1085 Maybe<T> ValueDeserializer::ReadZigZag() {
1086 // Writes a signed integer as a varint using ZigZag encoding (i.e. 0 is
1087 // encoded as 0, -1 as 1, 1 as 2, -2 as 3, and so on).
1088 // See also https://developers.google.com/protocol-buffers/docs/encoding
1089 static_assert(std::is_integral<T>::value && std::is_signed<T>::value,
1090 "Only signed integer types can be read as zigzag.");
1091 using UnsignedT = typename std::make_unsigned<T>::type;
1092 UnsignedT unsigned_value;
1093 if (!ReadVarint<UnsignedT>().To(&unsigned_value)) return Nothing<T>();
1094 return Just(static_cast<T>((unsigned_value >> 1) ^
1095 -static_cast<T>(unsigned_value & 1)));
1096 }
1097
ReadDouble()1098 Maybe<double> ValueDeserializer::ReadDouble() {
1099 // Warning: this uses host endianness.
1100 if (position_ > end_ - sizeof(double)) return Nothing<double>();
1101 double value;
1102 memcpy(&value, position_, sizeof(double));
1103 position_ += sizeof(double);
1104 if (std::isnan(value)) value = std::numeric_limits<double>::quiet_NaN();
1105 return Just(value);
1106 }
1107
ReadRawBytes(int size)1108 Maybe<Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(int size) {
1109 if (size > end_ - position_) return Nothing<Vector<const uint8_t>>();
1110 const uint8_t* start = position_;
1111 position_ += size;
1112 return Just(Vector<const uint8_t>(start, size));
1113 }
1114
ReadUint32(uint32_t * value)1115 bool ValueDeserializer::ReadUint32(uint32_t* value) {
1116 return ReadVarint<uint32_t>().To(value);
1117 }
1118
ReadUint64(uint64_t * value)1119 bool ValueDeserializer::ReadUint64(uint64_t* value) {
1120 return ReadVarint<uint64_t>().To(value);
1121 }
1122
ReadDouble(double * value)1123 bool ValueDeserializer::ReadDouble(double* value) {
1124 return ReadDouble().To(value);
1125 }
1126
ReadRawBytes(size_t length,const void ** data)1127 bool ValueDeserializer::ReadRawBytes(size_t length, const void** data) {
1128 if (length > static_cast<size_t>(end_ - position_)) return false;
1129 *data = position_;
1130 position_ += length;
1131 return true;
1132 }
1133
TransferArrayBuffer(uint32_t transfer_id,Handle<JSArrayBuffer> array_buffer)1134 void ValueDeserializer::TransferArrayBuffer(
1135 uint32_t transfer_id, Handle<JSArrayBuffer> array_buffer) {
1136 if (array_buffer_transfer_map_.is_null()) {
1137 array_buffer_transfer_map_ = isolate_->global_handles()->Create(
1138 *SimpleNumberDictionary::New(isolate_, 0));
1139 }
1140 Handle<SimpleNumberDictionary> dictionary =
1141 array_buffer_transfer_map_.ToHandleChecked();
1142 Handle<SimpleNumberDictionary> new_dictionary = SimpleNumberDictionary::Set(
1143 isolate_, dictionary, transfer_id, array_buffer);
1144 if (!new_dictionary.is_identical_to(dictionary)) {
1145 GlobalHandles::Destroy(Handle<Object>::cast(dictionary).location());
1146 array_buffer_transfer_map_ =
1147 isolate_->global_handles()->Create(*new_dictionary);
1148 }
1149 }
1150
ReadObject()1151 MaybeHandle<Object> ValueDeserializer::ReadObject() {
1152 MaybeHandle<Object> result = ReadObjectInternal();
1153
1154 // ArrayBufferView is special in that it consumes the value before it, even
1155 // after format version 0.
1156 Handle<Object> object;
1157 SerializationTag tag;
1158 if (result.ToHandle(&object) && V8_UNLIKELY(object->IsJSArrayBuffer()) &&
1159 PeekTag().To(&tag) && tag == SerializationTag::kArrayBufferView) {
1160 ConsumeTag(SerializationTag::kArrayBufferView);
1161 result = ReadJSArrayBufferView(Handle<JSArrayBuffer>::cast(object));
1162 }
1163
1164 if (result.is_null() && !isolate_->has_pending_exception()) {
1165 isolate_->Throw(*isolate_->factory()->NewError(
1166 MessageTemplate::kDataCloneDeserializationError));
1167 }
1168
1169 return result;
1170 }
1171
ReadObjectInternal()1172 MaybeHandle<Object> ValueDeserializer::ReadObjectInternal() {
1173 SerializationTag tag;
1174 if (!ReadTag().To(&tag)) return MaybeHandle<Object>();
1175 switch (tag) {
1176 case SerializationTag::kVerifyObjectCount:
1177 // Read the count and ignore it.
1178 if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>();
1179 return ReadObject();
1180 case SerializationTag::kUndefined:
1181 return isolate_->factory()->undefined_value();
1182 case SerializationTag::kNull:
1183 return isolate_->factory()->null_value();
1184 case SerializationTag::kTrue:
1185 return isolate_->factory()->true_value();
1186 case SerializationTag::kFalse:
1187 return isolate_->factory()->false_value();
1188 case SerializationTag::kInt32: {
1189 Maybe<int32_t> number = ReadZigZag<int32_t>();
1190 if (number.IsNothing()) return MaybeHandle<Object>();
1191 return isolate_->factory()->NewNumberFromInt(number.FromJust(),
1192 pretenure_);
1193 }
1194 case SerializationTag::kUint32: {
1195 Maybe<uint32_t> number = ReadVarint<uint32_t>();
1196 if (number.IsNothing()) return MaybeHandle<Object>();
1197 return isolate_->factory()->NewNumberFromUint(number.FromJust(),
1198 pretenure_);
1199 }
1200 case SerializationTag::kDouble: {
1201 Maybe<double> number = ReadDouble();
1202 if (number.IsNothing()) return MaybeHandle<Object>();
1203 return isolate_->factory()->NewNumber(number.FromJust(), pretenure_);
1204 }
1205 case SerializationTag::kBigInt:
1206 return ReadBigInt();
1207 case SerializationTag::kUtf8String:
1208 return ReadUtf8String();
1209 case SerializationTag::kOneByteString:
1210 return ReadOneByteString();
1211 case SerializationTag::kTwoByteString:
1212 return ReadTwoByteString();
1213 case SerializationTag::kObjectReference: {
1214 uint32_t id;
1215 if (!ReadVarint<uint32_t>().To(&id)) return MaybeHandle<Object>();
1216 return GetObjectWithID(id);
1217 }
1218 case SerializationTag::kBeginJSObject:
1219 return ReadJSObject();
1220 case SerializationTag::kBeginSparseJSArray:
1221 return ReadSparseJSArray();
1222 case SerializationTag::kBeginDenseJSArray:
1223 return ReadDenseJSArray();
1224 case SerializationTag::kDate:
1225 return ReadJSDate();
1226 case SerializationTag::kTrueObject:
1227 case SerializationTag::kFalseObject:
1228 case SerializationTag::kNumberObject:
1229 case SerializationTag::kBigIntObject:
1230 case SerializationTag::kStringObject:
1231 return ReadJSValue(tag);
1232 case SerializationTag::kRegExp:
1233 return ReadJSRegExp();
1234 case SerializationTag::kBeginJSMap:
1235 return ReadJSMap();
1236 case SerializationTag::kBeginJSSet:
1237 return ReadJSSet();
1238 case SerializationTag::kArrayBuffer: {
1239 const bool is_shared = false;
1240 return ReadJSArrayBuffer(is_shared);
1241 }
1242 case SerializationTag::kArrayBufferTransfer: {
1243 return ReadTransferredJSArrayBuffer();
1244 }
1245 case SerializationTag::kSharedArrayBuffer: {
1246 const bool is_shared = true;
1247 return ReadJSArrayBuffer(is_shared);
1248 }
1249 case SerializationTag::kWasmModule:
1250 return ReadWasmModule();
1251 case SerializationTag::kWasmModuleTransfer:
1252 return ReadWasmModuleTransfer();
1253 case SerializationTag::kWasmMemoryTransfer:
1254 return ReadWasmMemory();
1255 case SerializationTag::kHostObject:
1256 return ReadHostObject();
1257 default:
1258 // Before there was an explicit tag for host objects, all unknown tags
1259 // were delegated to the host.
1260 if (version_ < 13) {
1261 position_--;
1262 return ReadHostObject();
1263 }
1264 return MaybeHandle<Object>();
1265 }
1266 }
1267
ReadString()1268 MaybeHandle<String> ValueDeserializer::ReadString() {
1269 if (version_ < 12) return ReadUtf8String();
1270 Handle<Object> object;
1271 if (!ReadObject().ToHandle(&object) || !object->IsString()) {
1272 return MaybeHandle<String>();
1273 }
1274 return Handle<String>::cast(object);
1275 }
1276
ReadBigInt()1277 MaybeHandle<BigInt> ValueDeserializer::ReadBigInt() {
1278 if (!FLAG_harmony_bigint) return MaybeHandle<BigInt>();
1279 uint32_t bitfield;
1280 if (!ReadVarint<uint32_t>().To(&bitfield)) return MaybeHandle<BigInt>();
1281 int bytelength = BigInt::DigitsByteLengthForBitfield(bitfield);
1282 Vector<const uint8_t> digits_storage;
1283 if (!ReadRawBytes(bytelength).To(&digits_storage)) {
1284 return MaybeHandle<BigInt>();
1285 }
1286 return BigInt::FromSerializedDigits(isolate_, bitfield, digits_storage,
1287 pretenure_);
1288 }
1289
ReadUtf8String()1290 MaybeHandle<String> ValueDeserializer::ReadUtf8String() {
1291 uint32_t utf8_length;
1292 Vector<const uint8_t> utf8_bytes;
1293 if (!ReadVarint<uint32_t>().To(&utf8_length) ||
1294 utf8_length >
1295 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1296 !ReadRawBytes(utf8_length).To(&utf8_bytes)) {
1297 return MaybeHandle<String>();
1298 }
1299 return isolate_->factory()->NewStringFromUtf8(
1300 Vector<const char>::cast(utf8_bytes), pretenure_);
1301 }
1302
ReadOneByteString()1303 MaybeHandle<String> ValueDeserializer::ReadOneByteString() {
1304 uint32_t byte_length;
1305 Vector<const uint8_t> bytes;
1306 if (!ReadVarint<uint32_t>().To(&byte_length) ||
1307 byte_length >
1308 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1309 !ReadRawBytes(byte_length).To(&bytes)) {
1310 return MaybeHandle<String>();
1311 }
1312 return isolate_->factory()->NewStringFromOneByte(bytes, pretenure_);
1313 }
1314
ReadTwoByteString()1315 MaybeHandle<String> ValueDeserializer::ReadTwoByteString() {
1316 uint32_t byte_length;
1317 Vector<const uint8_t> bytes;
1318 if (!ReadVarint<uint32_t>().To(&byte_length) ||
1319 byte_length >
1320 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1321 byte_length % sizeof(uc16) != 0 ||
1322 !ReadRawBytes(byte_length).To(&bytes)) {
1323 return MaybeHandle<String>();
1324 }
1325
1326 // Allocate an uninitialized string so that we can do a raw memcpy into the
1327 // string on the heap (regardless of alignment).
1328 if (byte_length == 0) return isolate_->factory()->empty_string();
1329 Handle<SeqTwoByteString> string;
1330 if (!isolate_->factory()
1331 ->NewRawTwoByteString(byte_length / sizeof(uc16), pretenure_)
1332 .ToHandle(&string)) {
1333 return MaybeHandle<String>();
1334 }
1335
1336 // Copy the bytes directly into the new string.
1337 // Warning: this uses host endianness.
1338 memcpy(string->GetChars(), bytes.begin(), bytes.length());
1339 return string;
1340 }
1341
ReadExpectedString(Handle<String> expected)1342 bool ValueDeserializer::ReadExpectedString(Handle<String> expected) {
1343 DisallowHeapAllocation no_gc;
1344 // In the case of failure, the position in the stream is reset.
1345 const uint8_t* original_position = position_;
1346
1347 SerializationTag tag;
1348 uint32_t byte_length;
1349 Vector<const uint8_t> bytes;
1350 if (!ReadTag().To(&tag) || !ReadVarint<uint32_t>().To(&byte_length) ||
1351 byte_length >
1352 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1353 !ReadRawBytes(byte_length).To(&bytes)) {
1354 position_ = original_position;
1355 return false;
1356 }
1357
1358 String::FlatContent flat = expected->GetFlatContent();
1359
1360 // If the bytes are verbatim what is in the flattened string, then the string
1361 // is successfully consumed.
1362 if (tag == SerializationTag::kOneByteString && flat.IsOneByte()) {
1363 Vector<const uint8_t> chars = flat.ToOneByteVector();
1364 if (byte_length == static_cast<size_t>(chars.length()) &&
1365 memcmp(bytes.begin(), chars.begin(), byte_length) == 0) {
1366 return true;
1367 }
1368 } else if (tag == SerializationTag::kTwoByteString && flat.IsTwoByte()) {
1369 Vector<const uc16> chars = flat.ToUC16Vector();
1370 if (byte_length == static_cast<unsigned>(chars.length()) * sizeof(uc16) &&
1371 memcmp(bytes.begin(), chars.begin(), byte_length) == 0) {
1372 return true;
1373 }
1374 } else if (tag == SerializationTag::kUtf8String && flat.IsOneByte()) {
1375 Vector<const uint8_t> chars = flat.ToOneByteVector();
1376 if (byte_length == static_cast<size_t>(chars.length()) &&
1377 String::IsAscii(chars.begin(), chars.length()) &&
1378 memcmp(bytes.begin(), chars.begin(), byte_length) == 0) {
1379 return true;
1380 }
1381 }
1382
1383 position_ = original_position;
1384 return false;
1385 }
1386
ReadJSObject()1387 MaybeHandle<JSObject> ValueDeserializer::ReadJSObject() {
1388 // If we are at the end of the stack, abort. This function may recurse.
1389 STACK_CHECK(isolate_, MaybeHandle<JSObject>());
1390
1391 uint32_t id = next_id_++;
1392 HandleScope scope(isolate_);
1393 Handle<JSObject> object =
1394 isolate_->factory()->NewJSObject(isolate_->object_function(), pretenure_);
1395 AddObjectWithID(id, object);
1396
1397 uint32_t num_properties;
1398 uint32_t expected_num_properties;
1399 if (!ReadJSObjectProperties(object, SerializationTag::kEndJSObject, true)
1400 .To(&num_properties) ||
1401 !ReadVarint<uint32_t>().To(&expected_num_properties) ||
1402 num_properties != expected_num_properties) {
1403 return MaybeHandle<JSObject>();
1404 }
1405
1406 DCHECK(HasObjectWithID(id));
1407 return scope.CloseAndEscape(object);
1408 }
1409
ReadSparseJSArray()1410 MaybeHandle<JSArray> ValueDeserializer::ReadSparseJSArray() {
1411 // If we are at the end of the stack, abort. This function may recurse.
1412 STACK_CHECK(isolate_, MaybeHandle<JSArray>());
1413
1414 uint32_t length;
1415 if (!ReadVarint<uint32_t>().To(&length)) return MaybeHandle<JSArray>();
1416
1417 uint32_t id = next_id_++;
1418 HandleScope scope(isolate_);
1419 Handle<JSArray> array = isolate_->factory()->NewJSArray(
1420 0, TERMINAL_FAST_ELEMENTS_KIND, pretenure_);
1421 JSArray::SetLength(array, length);
1422 AddObjectWithID(id, array);
1423
1424 uint32_t num_properties;
1425 uint32_t expected_num_properties;
1426 uint32_t expected_length;
1427 if (!ReadJSObjectProperties(array, SerializationTag::kEndSparseJSArray, false)
1428 .To(&num_properties) ||
1429 !ReadVarint<uint32_t>().To(&expected_num_properties) ||
1430 !ReadVarint<uint32_t>().To(&expected_length) ||
1431 num_properties != expected_num_properties || length != expected_length) {
1432 return MaybeHandle<JSArray>();
1433 }
1434
1435 DCHECK(HasObjectWithID(id));
1436 return scope.CloseAndEscape(array);
1437 }
1438
ReadDenseJSArray()1439 MaybeHandle<JSArray> ValueDeserializer::ReadDenseJSArray() {
1440 // If we are at the end of the stack, abort. This function may recurse.
1441 STACK_CHECK(isolate_, MaybeHandle<JSArray>());
1442
1443 // We shouldn't permit an array larger than the biggest we can request from
1444 // V8. As an additional sanity check, since each entry will take at least one
1445 // byte to encode, if there are fewer bytes than that we can also fail fast.
1446 uint32_t length;
1447 if (!ReadVarint<uint32_t>().To(&length) ||
1448 length > static_cast<uint32_t>(FixedArray::kMaxLength) ||
1449 length > static_cast<size_t>(end_ - position_)) {
1450 return MaybeHandle<JSArray>();
1451 }
1452
1453 uint32_t id = next_id_++;
1454 HandleScope scope(isolate_);
1455 Handle<JSArray> array = isolate_->factory()->NewJSArray(
1456 HOLEY_ELEMENTS, length, length, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE,
1457 pretenure_);
1458 AddObjectWithID(id, array);
1459
1460 Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate_);
1461 for (uint32_t i = 0; i < length; i++) {
1462 SerializationTag tag;
1463 if (PeekTag().To(&tag) && tag == SerializationTag::kTheHole) {
1464 ConsumeTag(SerializationTag::kTheHole);
1465 continue;
1466 }
1467
1468 Handle<Object> element;
1469 if (!ReadObject().ToHandle(&element)) return MaybeHandle<JSArray>();
1470
1471 // Serialization versions less than 11 encode the hole the same as
1472 // undefined. For consistency with previous behavior, store these as the
1473 // hole. Past version 11, undefined means undefined.
1474 if (version_ < 11 && element->IsUndefined(isolate_)) continue;
1475
1476 elements->set(i, *element);
1477 }
1478
1479 uint32_t num_properties;
1480 uint32_t expected_num_properties;
1481 uint32_t expected_length;
1482 if (!ReadJSObjectProperties(array, SerializationTag::kEndDenseJSArray, false)
1483 .To(&num_properties) ||
1484 !ReadVarint<uint32_t>().To(&expected_num_properties) ||
1485 !ReadVarint<uint32_t>().To(&expected_length) ||
1486 num_properties != expected_num_properties || length != expected_length) {
1487 return MaybeHandle<JSArray>();
1488 }
1489
1490 DCHECK(HasObjectWithID(id));
1491 return scope.CloseAndEscape(array);
1492 }
1493
ReadJSDate()1494 MaybeHandle<JSDate> ValueDeserializer::ReadJSDate() {
1495 double value;
1496 if (!ReadDouble().To(&value)) return MaybeHandle<JSDate>();
1497 uint32_t id = next_id_++;
1498 Handle<JSDate> date;
1499 if (!JSDate::New(isolate_->date_function(), isolate_->date_function(), value)
1500 .ToHandle(&date)) {
1501 return MaybeHandle<JSDate>();
1502 }
1503 AddObjectWithID(id, date);
1504 return date;
1505 }
1506
ReadJSValue(SerializationTag tag)1507 MaybeHandle<JSValue> ValueDeserializer::ReadJSValue(SerializationTag tag) {
1508 uint32_t id = next_id_++;
1509 Handle<JSValue> value;
1510 switch (tag) {
1511 case SerializationTag::kTrueObject:
1512 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1513 isolate_->boolean_function(), pretenure_));
1514 value->set_value(ReadOnlyRoots(isolate_).true_value());
1515 break;
1516 case SerializationTag::kFalseObject:
1517 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1518 isolate_->boolean_function(), pretenure_));
1519 value->set_value(ReadOnlyRoots(isolate_).false_value());
1520 break;
1521 case SerializationTag::kNumberObject: {
1522 double number;
1523 if (!ReadDouble().To(&number)) return MaybeHandle<JSValue>();
1524 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1525 isolate_->number_function(), pretenure_));
1526 Handle<Object> number_object =
1527 isolate_->factory()->NewNumber(number, pretenure_);
1528 value->set_value(*number_object);
1529 break;
1530 }
1531 case SerializationTag::kBigIntObject: {
1532 Handle<BigInt> bigint;
1533 if (!ReadBigInt().ToHandle(&bigint)) return MaybeHandle<JSValue>();
1534 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1535 isolate_->bigint_function(), pretenure_));
1536 value->set_value(*bigint);
1537 break;
1538 }
1539 case SerializationTag::kStringObject: {
1540 Handle<String> string;
1541 if (!ReadString().ToHandle(&string)) return MaybeHandle<JSValue>();
1542 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1543 isolate_->string_function(), pretenure_));
1544 value->set_value(*string);
1545 break;
1546 }
1547 default:
1548 UNREACHABLE();
1549 }
1550 AddObjectWithID(id, value);
1551 return value;
1552 }
1553
ReadJSRegExp()1554 MaybeHandle<JSRegExp> ValueDeserializer::ReadJSRegExp() {
1555 uint32_t id = next_id_++;
1556 Handle<String> pattern;
1557 uint32_t raw_flags;
1558 Handle<JSRegExp> regexp;
1559 if (!ReadString().ToHandle(&pattern) ||
1560 !ReadVarint<uint32_t>().To(&raw_flags)) {
1561 return MaybeHandle<JSRegExp>();
1562 }
1563
1564 // Ensure the deserialized flags are valid.
1565 // TODO(adamk): Can we remove this check now that dotAll is always-on?
1566 uint32_t flags_mask = static_cast<uint32_t>(-1) << JSRegExp::FlagCount();
1567 if ((raw_flags & flags_mask) ||
1568 !JSRegExp::New(isolate_, pattern, static_cast<JSRegExp::Flags>(raw_flags))
1569 .ToHandle(®exp)) {
1570 return MaybeHandle<JSRegExp>();
1571 }
1572
1573 AddObjectWithID(id, regexp);
1574 return regexp;
1575 }
1576
ReadJSMap()1577 MaybeHandle<JSMap> ValueDeserializer::ReadJSMap() {
1578 // If we are at the end of the stack, abort. This function may recurse.
1579 STACK_CHECK(isolate_, MaybeHandle<JSMap>());
1580
1581 HandleScope scope(isolate_);
1582 uint32_t id = next_id_++;
1583 Handle<JSMap> map = isolate_->factory()->NewJSMap();
1584 AddObjectWithID(id, map);
1585
1586 Handle<JSFunction> map_set = isolate_->map_set();
1587 uint32_t length = 0;
1588 while (true) {
1589 SerializationTag tag;
1590 if (!PeekTag().To(&tag)) return MaybeHandle<JSMap>();
1591 if (tag == SerializationTag::kEndJSMap) {
1592 ConsumeTag(SerializationTag::kEndJSMap);
1593 break;
1594 }
1595
1596 Handle<Object> argv[2];
1597 if (!ReadObject().ToHandle(&argv[0]) || !ReadObject().ToHandle(&argv[1]) ||
1598 Execution::Call(isolate_, map_set, map, arraysize(argv), argv)
1599 .is_null()) {
1600 return MaybeHandle<JSMap>();
1601 }
1602 length += 2;
1603 }
1604
1605 uint32_t expected_length;
1606 if (!ReadVarint<uint32_t>().To(&expected_length) ||
1607 length != expected_length) {
1608 return MaybeHandle<JSMap>();
1609 }
1610 DCHECK(HasObjectWithID(id));
1611 return scope.CloseAndEscape(map);
1612 }
1613
ReadJSSet()1614 MaybeHandle<JSSet> ValueDeserializer::ReadJSSet() {
1615 // If we are at the end of the stack, abort. This function may recurse.
1616 STACK_CHECK(isolate_, MaybeHandle<JSSet>());
1617
1618 HandleScope scope(isolate_);
1619 uint32_t id = next_id_++;
1620 Handle<JSSet> set = isolate_->factory()->NewJSSet();
1621 AddObjectWithID(id, set);
1622 Handle<JSFunction> set_add = isolate_->set_add();
1623 uint32_t length = 0;
1624 while (true) {
1625 SerializationTag tag;
1626 if (!PeekTag().To(&tag)) return MaybeHandle<JSSet>();
1627 if (tag == SerializationTag::kEndJSSet) {
1628 ConsumeTag(SerializationTag::kEndJSSet);
1629 break;
1630 }
1631
1632 Handle<Object> argv[1];
1633 if (!ReadObject().ToHandle(&argv[0]) ||
1634 Execution::Call(isolate_, set_add, set, arraysize(argv), argv)
1635 .is_null()) {
1636 return MaybeHandle<JSSet>();
1637 }
1638 length++;
1639 }
1640
1641 uint32_t expected_length;
1642 if (!ReadVarint<uint32_t>().To(&expected_length) ||
1643 length != expected_length) {
1644 return MaybeHandle<JSSet>();
1645 }
1646 DCHECK(HasObjectWithID(id));
1647 return scope.CloseAndEscape(set);
1648 }
1649
ReadJSArrayBuffer(bool is_shared)1650 MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadJSArrayBuffer(
1651 bool is_shared) {
1652 uint32_t id = next_id_++;
1653 if (is_shared) {
1654 uint32_t clone_id;
1655 Local<SharedArrayBuffer> sab_value;
1656 if (!ReadVarint<uint32_t>().To(&clone_id) || delegate_ == nullptr ||
1657 !delegate_
1658 ->GetSharedArrayBufferFromId(
1659 reinterpret_cast<v8::Isolate*>(isolate_), clone_id)
1660 .ToLocal(&sab_value)) {
1661 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSArrayBuffer);
1662 return MaybeHandle<JSArrayBuffer>();
1663 }
1664 Handle<JSArrayBuffer> array_buffer = Utils::OpenHandle(*sab_value);
1665 DCHECK_EQ(is_shared, array_buffer->is_shared());
1666 AddObjectWithID(id, array_buffer);
1667 return array_buffer;
1668 }
1669 uint32_t byte_length;
1670 if (!ReadVarint<uint32_t>().To(&byte_length) ||
1671 byte_length > static_cast<size_t>(end_ - position_)) {
1672 return MaybeHandle<JSArrayBuffer>();
1673 }
1674 const bool should_initialize = false;
1675 Handle<JSArrayBuffer> array_buffer =
1676 isolate_->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, pretenure_);
1677 if (!JSArrayBuffer::SetupAllocatingData(array_buffer, isolate_, byte_length,
1678 should_initialize)) {
1679 return MaybeHandle<JSArrayBuffer>();
1680 }
1681 memcpy(array_buffer->backing_store(), position_, byte_length);
1682 position_ += byte_length;
1683 AddObjectWithID(id, array_buffer);
1684 return array_buffer;
1685 }
1686
ReadTransferredJSArrayBuffer()1687 MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadTransferredJSArrayBuffer() {
1688 uint32_t id = next_id_++;
1689 uint32_t transfer_id;
1690 Handle<SimpleNumberDictionary> transfer_map;
1691 if (!ReadVarint<uint32_t>().To(&transfer_id) ||
1692 !array_buffer_transfer_map_.ToHandle(&transfer_map)) {
1693 return MaybeHandle<JSArrayBuffer>();
1694 }
1695 int index = transfer_map->FindEntry(isolate_, transfer_id);
1696 if (index == SimpleNumberDictionary::kNotFound) {
1697 return MaybeHandle<JSArrayBuffer>();
1698 }
1699 Handle<JSArrayBuffer> array_buffer(
1700 JSArrayBuffer::cast(transfer_map->ValueAt(index)), isolate_);
1701 AddObjectWithID(id, array_buffer);
1702 return array_buffer;
1703 }
1704
ReadJSArrayBufferView(Handle<JSArrayBuffer> buffer)1705 MaybeHandle<JSArrayBufferView> ValueDeserializer::ReadJSArrayBufferView(
1706 Handle<JSArrayBuffer> buffer) {
1707 uint32_t buffer_byte_length = NumberToUint32(buffer->byte_length());
1708 uint8_t tag = 0;
1709 uint32_t byte_offset = 0;
1710 uint32_t byte_length = 0;
1711 if (!ReadVarint<uint8_t>().To(&tag) ||
1712 !ReadVarint<uint32_t>().To(&byte_offset) ||
1713 !ReadVarint<uint32_t>().To(&byte_length) ||
1714 byte_offset > buffer_byte_length ||
1715 byte_length > buffer_byte_length - byte_offset) {
1716 return MaybeHandle<JSArrayBufferView>();
1717 }
1718 uint32_t id = next_id_++;
1719 ExternalArrayType external_array_type = kExternalInt8Array;
1720 unsigned element_size = 0;
1721
1722 if (!FLAG_harmony_bigint) {
1723 // Refuse to construct BigInt64Arrays unless the flag is on.
1724 ArrayBufferViewTag cast_tag = static_cast<ArrayBufferViewTag>(tag);
1725 if (cast_tag == ArrayBufferViewTag::kBigInt64Array ||
1726 cast_tag == ArrayBufferViewTag::kBigUint64Array) {
1727 return MaybeHandle<JSArrayBufferView>();
1728 }
1729 }
1730
1731 switch (static_cast<ArrayBufferViewTag>(tag)) {
1732 case ArrayBufferViewTag::kDataView: {
1733 Handle<JSDataView> data_view =
1734 isolate_->factory()->NewJSDataView(buffer, byte_offset, byte_length);
1735 AddObjectWithID(id, data_view);
1736 return data_view;
1737 }
1738 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
1739 case ArrayBufferViewTag::k##Type##Array: \
1740 external_array_type = kExternal##Type##Array; \
1741 element_size = sizeof(ctype); \
1742 break;
1743 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1744 #undef TYPED_ARRAY_CASE
1745 }
1746 if (element_size == 0 || byte_offset % element_size != 0 ||
1747 byte_length % element_size != 0) {
1748 return MaybeHandle<JSArrayBufferView>();
1749 }
1750 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray(
1751 external_array_type, buffer, byte_offset, byte_length / element_size,
1752 pretenure_);
1753 AddObjectWithID(id, typed_array);
1754 return typed_array;
1755 }
1756
ReadWasmModuleTransfer()1757 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModuleTransfer() {
1758 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1759 if ((FLAG_wasm_disable_structured_cloning && !enabled_features.threads) ||
1760 expect_inline_wasm()) {
1761 return MaybeHandle<JSObject>();
1762 }
1763
1764 uint32_t transfer_id = 0;
1765 Local<Value> module_value;
1766 if (!ReadVarint<uint32_t>().To(&transfer_id) || delegate_ == nullptr ||
1767 !delegate_
1768 ->GetWasmModuleFromId(reinterpret_cast<v8::Isolate*>(isolate_),
1769 transfer_id)
1770 .ToLocal(&module_value)) {
1771 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject);
1772 return MaybeHandle<JSObject>();
1773 }
1774 uint32_t id = next_id_++;
1775 Handle<JSObject> module =
1776 Handle<JSObject>::cast(Utils::OpenHandle(*module_value));
1777 AddObjectWithID(id, module);
1778 return module;
1779 }
1780
ReadWasmModule()1781 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
1782 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1783 if ((FLAG_wasm_disable_structured_cloning && !enabled_features.threads) ||
1784 !expect_inline_wasm()) {
1785 return MaybeHandle<JSObject>();
1786 }
1787
1788 Vector<const uint8_t> encoding_tag;
1789 if (!ReadRawBytes(sizeof(WasmEncodingTag)).To(&encoding_tag) ||
1790 encoding_tag[0] != static_cast<uint8_t>(WasmEncodingTag::kRawBytes)) {
1791 return MaybeHandle<JSObject>();
1792 }
1793
1794 // Extract the data from the buffer: wasm wire bytes, followed by V8 compiled
1795 // script data.
1796 static_assert(sizeof(int) <= sizeof(uint32_t),
1797 "max int must fit in uint32_t");
1798 const uint32_t max_valid_size = std::numeric_limits<int>::max();
1799 uint32_t wire_bytes_length = 0;
1800 Vector<const uint8_t> wire_bytes;
1801 uint32_t compiled_bytes_length = 0;
1802 Vector<const uint8_t> compiled_bytes;
1803 if (!ReadVarint<uint32_t>().To(&wire_bytes_length) ||
1804 wire_bytes_length > max_valid_size ||
1805 !ReadRawBytes(wire_bytes_length).To(&wire_bytes) ||
1806 !ReadVarint<uint32_t>().To(&compiled_bytes_length) ||
1807 compiled_bytes_length > max_valid_size ||
1808 !ReadRawBytes(compiled_bytes_length).To(&compiled_bytes)) {
1809 return MaybeHandle<JSObject>();
1810 }
1811
1812 // Try to deserialize the compiled module first.
1813 MaybeHandle<WasmModuleObject> result =
1814 wasm::DeserializeNativeModule(isolate_, compiled_bytes, wire_bytes);
1815 if (result.is_null()) {
1816 wasm::ErrorThrower thrower(isolate_, "ValueDeserializer::ReadWasmModule");
1817 // TODO(titzer): are the current features appropriate for deserializing?
1818 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1819 result = isolate_->wasm_engine()->SyncCompile(
1820 isolate_, enabled_features, &thrower,
1821 wasm::ModuleWireBytes(wire_bytes));
1822 }
1823 uint32_t id = next_id_++;
1824 if (!result.is_null()) {
1825 AddObjectWithID(id, result.ToHandleChecked());
1826 }
1827 return result;
1828 }
1829
ReadWasmMemory()1830 MaybeHandle<WasmMemoryObject> ValueDeserializer::ReadWasmMemory() {
1831 uint32_t id = next_id_++;
1832
1833 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1834 if (!enabled_features.threads) {
1835 return MaybeHandle<WasmMemoryObject>();
1836 }
1837
1838 int32_t maximum_pages;
1839 if (!ReadZigZag<int32_t>().To(&maximum_pages)) {
1840 return MaybeHandle<WasmMemoryObject>();
1841 }
1842
1843 SerializationTag tag;
1844 if (!ReadTag().To(&tag) || tag != SerializationTag::kSharedArrayBuffer) {
1845 return MaybeHandle<WasmMemoryObject>();
1846 }
1847
1848 const bool is_shared = true;
1849 Handle<JSArrayBuffer> buffer;
1850 if (!ReadJSArrayBuffer(is_shared).ToHandle(&buffer)) {
1851 return MaybeHandle<WasmMemoryObject>();
1852 }
1853
1854 Handle<WasmMemoryObject> result =
1855 WasmMemoryObject::New(isolate_, buffer, maximum_pages);
1856
1857 AddObjectWithID(id, result);
1858 return result;
1859 }
1860
ReadHostObject()1861 MaybeHandle<JSObject> ValueDeserializer::ReadHostObject() {
1862 if (!delegate_) return MaybeHandle<JSObject>();
1863 STACK_CHECK(isolate_, MaybeHandle<JSObject>());
1864 uint32_t id = next_id_++;
1865 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
1866 v8::Local<v8::Object> object;
1867 if (!delegate_->ReadHostObject(v8_isolate).ToLocal(&object)) {
1868 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject);
1869 return MaybeHandle<JSObject>();
1870 }
1871 Handle<JSObject> js_object =
1872 Handle<JSObject>::cast(Utils::OpenHandle(*object));
1873 AddObjectWithID(id, js_object);
1874 return js_object;
1875 }
1876
1877 // Copies a vector of property values into an object, given the map that should
1878 // be used.
CommitProperties(Handle<JSObject> object,Handle<Map> map,const std::vector<Handle<Object>> & properties)1879 static void CommitProperties(Handle<JSObject> object, Handle<Map> map,
1880 const std::vector<Handle<Object>>& properties) {
1881 JSObject::AllocateStorageForMap(object, map);
1882 DCHECK(!object->map()->is_dictionary_map());
1883
1884 DisallowHeapAllocation no_gc;
1885 DescriptorArray* descriptors = object->map()->instance_descriptors();
1886 for (unsigned i = 0; i < properties.size(); i++) {
1887 // Initializing store.
1888 object->WriteToField(i, descriptors->GetDetails(i), *properties[i]);
1889 }
1890 }
1891
IsValidObjectKey(Handle<Object> value)1892 static bool IsValidObjectKey(Handle<Object> value) {
1893 return value->IsName() || value->IsNumber();
1894 }
1895
ReadJSObjectProperties(Handle<JSObject> object,SerializationTag end_tag,bool can_use_transitions)1896 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties(
1897 Handle<JSObject> object, SerializationTag end_tag,
1898 bool can_use_transitions) {
1899 uint32_t num_properties = 0;
1900
1901 // Fast path (following map transitions).
1902 if (can_use_transitions) {
1903 bool transitioning = true;
1904 Handle<Map> map(object->map(), isolate_);
1905 DCHECK(!map->is_dictionary_map());
1906 DCHECK_EQ(0, map->instance_descriptors()->number_of_descriptors());
1907 std::vector<Handle<Object>> properties;
1908 properties.reserve(8);
1909
1910 while (transitioning) {
1911 // If there are no more properties, finish.
1912 SerializationTag tag;
1913 if (!PeekTag().To(&tag)) return Nothing<uint32_t>();
1914 if (tag == end_tag) {
1915 ConsumeTag(end_tag);
1916 CommitProperties(object, map, properties);
1917 CHECK_LT(properties.size(), std::numeric_limits<uint32_t>::max());
1918 return Just(static_cast<uint32_t>(properties.size()));
1919 }
1920
1921 // Determine the key to be used and the target map to transition to, if
1922 // possible. Transitioning may abort if the key is not a string, or if no
1923 // transition was found.
1924 Handle<Object> key;
1925 Handle<Map> target;
1926 TransitionsAccessor transitions(isolate_, map);
1927 Handle<String> expected_key = transitions.ExpectedTransitionKey();
1928 if (!expected_key.is_null() && ReadExpectedString(expected_key)) {
1929 key = expected_key;
1930 target = transitions.ExpectedTransitionTarget();
1931 } else {
1932 if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) {
1933 return Nothing<uint32_t>();
1934 }
1935 if (key->IsString()) {
1936 key =
1937 isolate_->factory()->InternalizeString(Handle<String>::cast(key));
1938 // Don't reuse |transitions| because it could be stale.
1939 transitioning = TransitionsAccessor(isolate_, map)
1940 .FindTransitionToField(Handle<String>::cast(key))
1941 .ToHandle(&target);
1942 } else {
1943 transitioning = false;
1944 }
1945 }
1946
1947 // Read the value that corresponds to it.
1948 Handle<Object> value;
1949 if (!ReadObject().ToHandle(&value)) return Nothing<uint32_t>();
1950
1951 // If still transitioning and the value fits the field representation
1952 // (though generalization may be required), store the property value so
1953 // that we can copy them all at once. Otherwise, stop transitioning.
1954 if (transitioning) {
1955 int descriptor = static_cast<int>(properties.size());
1956 PropertyDetails details =
1957 target->instance_descriptors()->GetDetails(descriptor);
1958 Representation expected_representation = details.representation();
1959 if (value->FitsRepresentation(expected_representation)) {
1960 if (expected_representation.IsHeapObject() &&
1961 !target->instance_descriptors()
1962 ->GetFieldType(descriptor)
1963 ->NowContains(value)) {
1964 Handle<FieldType> value_type =
1965 value->OptimalType(isolate_, expected_representation);
1966 Map::GeneralizeField(isolate_, target, descriptor,
1967 details.constness(), expected_representation,
1968 value_type);
1969 }
1970 DCHECK(target->instance_descriptors()
1971 ->GetFieldType(descriptor)
1972 ->NowContains(value));
1973 properties.push_back(value);
1974 map = target;
1975 continue;
1976 } else {
1977 transitioning = false;
1978 }
1979 }
1980
1981 // Fell out of transitioning fast path. Commit the properties gathered so
1982 // far, and then start setting properties slowly instead.
1983 DCHECK(!transitioning);
1984 CHECK_LT(properties.size(), std::numeric_limits<uint32_t>::max());
1985 CommitProperties(object, map, properties);
1986 num_properties = static_cast<uint32_t>(properties.size());
1987
1988 bool success;
1989 LookupIterator it = LookupIterator::PropertyOrElement(
1990 isolate_, object, key, &success, LookupIterator::OWN);
1991 if (!success ||
1992 JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE)
1993 .is_null()) {
1994 return Nothing<uint32_t>();
1995 }
1996 num_properties++;
1997 }
1998
1999 // At this point, transitioning should be done, but at least one property
2000 // should have been written (in the zero-property case, there is an early
2001 // return).
2002 DCHECK(!transitioning);
2003 DCHECK_GE(num_properties, 1u);
2004 }
2005
2006 // Slow path.
2007 for (;; num_properties++) {
2008 SerializationTag tag;
2009 if (!PeekTag().To(&tag)) return Nothing<uint32_t>();
2010 if (tag == end_tag) {
2011 ConsumeTag(end_tag);
2012 return Just(num_properties);
2013 }
2014
2015 Handle<Object> key;
2016 if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) {
2017 return Nothing<uint32_t>();
2018 }
2019 Handle<Object> value;
2020 if (!ReadObject().ToHandle(&value)) return Nothing<uint32_t>();
2021
2022 bool success;
2023 LookupIterator it = LookupIterator::PropertyOrElement(
2024 isolate_, object, key, &success, LookupIterator::OWN);
2025 if (!success ||
2026 JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE)
2027 .is_null()) {
2028 return Nothing<uint32_t>();
2029 }
2030 }
2031 }
2032
HasObjectWithID(uint32_t id)2033 bool ValueDeserializer::HasObjectWithID(uint32_t id) {
2034 return id < static_cast<unsigned>(id_map_->length()) &&
2035 !id_map_->get(id)->IsTheHole(isolate_);
2036 }
2037
GetObjectWithID(uint32_t id)2038 MaybeHandle<JSReceiver> ValueDeserializer::GetObjectWithID(uint32_t id) {
2039 if (id >= static_cast<unsigned>(id_map_->length())) {
2040 return MaybeHandle<JSReceiver>();
2041 }
2042 Object* value = id_map_->get(id);
2043 if (value->IsTheHole(isolate_)) return MaybeHandle<JSReceiver>();
2044 DCHECK(value->IsJSReceiver());
2045 return Handle<JSReceiver>(JSReceiver::cast(value), isolate_);
2046 }
2047
AddObjectWithID(uint32_t id,Handle<JSReceiver> object)2048 void ValueDeserializer::AddObjectWithID(uint32_t id,
2049 Handle<JSReceiver> object) {
2050 DCHECK(!HasObjectWithID(id));
2051 Handle<FixedArray> new_array =
2052 FixedArray::SetAndGrow(isolate_, id_map_, id, object);
2053
2054 // If the dictionary was reallocated, update the global handle.
2055 if (!new_array.is_identical_to(id_map_)) {
2056 GlobalHandles::Destroy(Handle<Object>::cast(id_map_).location());
2057 id_map_ = isolate_->global_handles()->Create(*new_array);
2058 }
2059 }
2060
SetPropertiesFromKeyValuePairs(Isolate * isolate,Handle<JSObject> object,Handle<Object> * data,uint32_t num_properties)2061 static Maybe<bool> SetPropertiesFromKeyValuePairs(Isolate* isolate,
2062 Handle<JSObject> object,
2063 Handle<Object>* data,
2064 uint32_t num_properties) {
2065 for (unsigned i = 0; i < 2 * num_properties; i += 2) {
2066 Handle<Object> key = data[i];
2067 if (!IsValidObjectKey(key)) return Nothing<bool>();
2068 Handle<Object> value = data[i + 1];
2069 bool success;
2070 LookupIterator it = LookupIterator::PropertyOrElement(
2071 isolate, object, key, &success, LookupIterator::OWN);
2072 if (!success ||
2073 JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE)
2074 .is_null()) {
2075 return Nothing<bool>();
2076 }
2077 }
2078 return Just(true);
2079 }
2080
2081 namespace {
2082
2083 // Throws a generic "deserialization failed" exception by default, unless a more
2084 // specific exception has already been thrown.
ThrowDeserializationExceptionIfNonePending(Isolate * isolate)2085 void ThrowDeserializationExceptionIfNonePending(Isolate* isolate) {
2086 if (!isolate->has_pending_exception()) {
2087 isolate->Throw(*isolate->factory()->NewError(
2088 MessageTemplate::kDataCloneDeserializationError));
2089 }
2090 DCHECK(isolate->has_pending_exception());
2091 }
2092
2093 } // namespace
2094
2095 MaybeHandle<Object>
ReadObjectUsingEntireBufferForLegacyFormat()2096 ValueDeserializer::ReadObjectUsingEntireBufferForLegacyFormat() {
2097 DCHECK_EQ(version_, 0u);
2098 HandleScope scope(isolate_);
2099 std::vector<Handle<Object>> stack;
2100 while (position_ < end_) {
2101 SerializationTag tag;
2102 if (!PeekTag().To(&tag)) break;
2103
2104 Handle<Object> new_object;
2105 switch (tag) {
2106 case SerializationTag::kEndJSObject: {
2107 ConsumeTag(SerializationTag::kEndJSObject);
2108
2109 // JS Object: Read the last 2*n values from the stack and use them as
2110 // key-value pairs.
2111 uint32_t num_properties;
2112 if (!ReadVarint<uint32_t>().To(&num_properties) ||
2113 stack.size() / 2 < num_properties) {
2114 isolate_->Throw(*isolate_->factory()->NewError(
2115 MessageTemplate::kDataCloneDeserializationError));
2116 return MaybeHandle<Object>();
2117 }
2118
2119 size_t begin_properties =
2120 stack.size() - 2 * static_cast<size_t>(num_properties);
2121 Handle<JSObject> js_object = isolate_->factory()->NewJSObject(
2122 isolate_->object_function(), pretenure_);
2123 if (num_properties &&
2124 !SetPropertiesFromKeyValuePairs(
2125 isolate_, js_object, &stack[begin_properties], num_properties)
2126 .FromMaybe(false)) {
2127 ThrowDeserializationExceptionIfNonePending(isolate_);
2128 return MaybeHandle<Object>();
2129 }
2130
2131 stack.resize(begin_properties);
2132 new_object = js_object;
2133 break;
2134 }
2135 case SerializationTag::kEndSparseJSArray: {
2136 ConsumeTag(SerializationTag::kEndSparseJSArray);
2137
2138 // Sparse JS Array: Read the last 2*|num_properties| from the stack.
2139 uint32_t num_properties;
2140 uint32_t length;
2141 if (!ReadVarint<uint32_t>().To(&num_properties) ||
2142 !ReadVarint<uint32_t>().To(&length) ||
2143 stack.size() / 2 < num_properties) {
2144 isolate_->Throw(*isolate_->factory()->NewError(
2145 MessageTemplate::kDataCloneDeserializationError));
2146 return MaybeHandle<Object>();
2147 }
2148
2149 Handle<JSArray> js_array = isolate_->factory()->NewJSArray(
2150 0, TERMINAL_FAST_ELEMENTS_KIND, pretenure_);
2151 JSArray::SetLength(js_array, length);
2152 size_t begin_properties =
2153 stack.size() - 2 * static_cast<size_t>(num_properties);
2154 if (num_properties &&
2155 !SetPropertiesFromKeyValuePairs(
2156 isolate_, js_array, &stack[begin_properties], num_properties)
2157 .FromMaybe(false)) {
2158 ThrowDeserializationExceptionIfNonePending(isolate_);
2159 return MaybeHandle<Object>();
2160 }
2161
2162 stack.resize(begin_properties);
2163 new_object = js_array;
2164 break;
2165 }
2166 case SerializationTag::kEndDenseJSArray: {
2167 // This was already broken in Chromium, and apparently wasn't missed.
2168 isolate_->Throw(*isolate_->factory()->NewError(
2169 MessageTemplate::kDataCloneDeserializationError));
2170 return MaybeHandle<Object>();
2171 }
2172 default:
2173 if (!ReadObject().ToHandle(&new_object)) return MaybeHandle<Object>();
2174 break;
2175 }
2176 stack.push_back(new_object);
2177 }
2178
2179 // Nothing remains but padding.
2180 #ifdef DEBUG
2181 while (position_ < end_) {
2182 DCHECK(*position_++ == static_cast<uint8_t>(SerializationTag::kPadding));
2183 }
2184 #endif
2185 position_ = end_;
2186
2187 if (stack.size() != 1) {
2188 isolate_->Throw(*isolate_->factory()->NewError(
2189 MessageTemplate::kDataCloneDeserializationError));
2190 return MaybeHandle<Object>();
2191 }
2192 return scope.CloseAndEscape(stack[0]);
2193 }
2194
2195 } // namespace internal
2196 } // namespace v8
2197