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