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(®exp)) { 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