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