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