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