5 #include "src/value-serializer.h" 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/objects/smi.h" 24 #include "src/snapshot/code-serializer.h" 25 #include "src/transitions.h" 26 #include "src/wasm/wasm-engine.h" 27 #include "src/wasm/wasm-objects-inl.h" 28 #include "src/wasm/wasm-result.h" 29 #include "src/wasm/wasm-serialization.h" 48 static const uint32_t kLatestVersion = 13;
49 static_assert(kLatestVersion == v8::CurrentValueSerializerFormatVersion(),
50 "Exported format version must match latest version.");
52 static const int kPretenureThreshold = 100 * KB;
55 static size_t BytesNeededForVarint(T value) {
56 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
57 "Only unsigned integer types can be written as varints.");
69 enum class SerializationTag : uint8_t {
75 kVerifyObjectCount =
'?',
98 kObjectReference =
'^',
100 kBeginJSObject =
'o',
105 kBeginSparseJSArray =
'a',
107 kEndSparseJSArray =
'@',
110 kBeginDenseJSArray =
'A',
112 kEndDenseJSArray =
'$',
138 kArrayBufferTransfer =
't',
146 kArrayBufferView =
'V',
148 kSharedArrayBuffer =
'u',
155 kWasmModuleTransfer =
'w',
161 kWasmMemoryTransfer =
'm',
166 enum class ArrayBufferViewTag : uint8_t {
169 kUint8ClampedArray =
'C',
176 kBigInt64Array =
'q',
177 kBigUint64Array =
'Q',
181 enum class WasmEncodingTag : uint8_t {
187 ValueSerializer::ValueSerializer(Isolate* isolate,
191 zone_(isolate->allocator(), ZONE_NAME),
192 id_map_(isolate->heap(), ZoneAllocationPolicy(&zone_)),
193 array_buffer_transfer_map_(isolate->heap(),
194 ZoneAllocationPolicy(&zone_)) {}
196 ValueSerializer::~ValueSerializer() {
206 void ValueSerializer::WriteHeader() {
207 WriteTag(SerializationTag::kVersion);
208 WriteVarint(kLatestVersion);
211 void ValueSerializer::SetTreatArrayBufferViewsAsHostObjects(
bool mode) {
212 treat_array_buffer_views_as_host_objects_ = mode;
215 void ValueSerializer::WriteTag(SerializationTag tag) {
216 uint8_t raw_tag =
static_cast<uint8_t
>(tag);
217 WriteRawBytes(&raw_tag,
sizeof(raw_tag));
220 template <
typename T>
221 void ValueSerializer::WriteVarint(T value) {
226 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
227 "Only unsigned integer types can be written as varints.");
228 uint8_t stack_buffer[
sizeof(T) * 8 / 7 + 1];
229 uint8_t* next_byte = &stack_buffer[0];
231 *next_byte = (value & 0x7F) | 0x80;
235 *(next_byte - 1) &= 0x7F;
236 WriteRawBytes(stack_buffer, next_byte - stack_buffer);
239 template <
typename T>
240 void ValueSerializer::WriteZigZag(T value) {
245 static_assert(std::is_integral<T>::value && std::is_signed<T>::value,
246 "Only signed integer types can be written as zigzag.");
247 using UnsignedT =
typename std::make_unsigned<T>::type;
248 WriteVarint((static_cast<UnsignedT>(value) << 1) ^
249 (value >> (8 *
sizeof(T) - 1)));
252 void ValueSerializer::WriteDouble(
double value) {
254 WriteRawBytes(&value,
sizeof(value));
257 void ValueSerializer::WriteOneByteString(Vector<const uint8_t> chars) {
258 WriteVarint<uint32_t>(chars.length());
259 WriteRawBytes(chars.begin(), chars.length() *
sizeof(uint8_t));
262 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) {
264 WriteVarint<uint32_t>(chars.length() *
sizeof(uc16));
265 WriteRawBytes(chars.begin(), chars.length() *
sizeof(uc16));
268 void ValueSerializer::WriteBigIntContents(BigInt* bigint) {
269 uint32_t bitfield = bigint->GetBitfieldForSerialization();
270 int bytelength = BigInt::DigitsByteLengthForBitfield(bitfield);
271 WriteVarint<uint32_t>(bitfield);
273 if (ReserveRawBytes(bytelength).To(&dest)) {
274 bigint->SerializeDigits(dest);
278 void ValueSerializer::WriteRawBytes(
const void* source,
size_t length) {
280 if (ReserveRawBytes(length).To(&dest)) {
281 memcpy(dest, source, length);
285 Maybe<uint8_t*> ValueSerializer::ReserveRawBytes(
size_t bytes) {
286 size_t old_size = buffer_size_;
287 size_t new_size = old_size + bytes;
288 if (V8_UNLIKELY(new_size > buffer_capacity_)) {
290 if (!ExpandBuffer(new_size).To(&ok)) {
291 return Nothing<uint8_t*>();
294 buffer_size_ = new_size;
295 return Just(&buffer_[old_size]);
298 Maybe<bool> ValueSerializer::ExpandBuffer(
size_t required_capacity) {
299 DCHECK_GT(required_capacity, buffer_capacity_);
300 size_t requested_capacity =
301 std::max(required_capacity, buffer_capacity_ * 2) + 64;
302 size_t provided_capacity = 0;
303 void* new_buffer =
nullptr;
308 new_buffer = realloc(buffer_, requested_capacity);
309 provided_capacity = requested_capacity;
312 DCHECK(provided_capacity >= requested_capacity);
313 buffer_ =
reinterpret_cast<uint8_t*
>(new_buffer);
314 buffer_capacity_ = provided_capacity;
317 out_of_memory_ =
true;
318 return Nothing<bool>();
322 void ValueSerializer::WriteUint32(
uint32_t value) {
323 WriteVarint<uint32_t>(value);
326 void ValueSerializer::WriteUint64(uint64_t value) {
327 WriteVarint<uint64_t>(value);
330 std::vector<uint8_t> ValueSerializer::ReleaseBuffer() {
331 return std::vector<uint8_t>(buffer_, buffer_ + buffer_size_);
334 std::pair<uint8_t*, size_t> ValueSerializer::Release() {
335 auto result = std::make_pair(buffer_, buffer_size_);
338 buffer_capacity_ = 0;
342 void ValueSerializer::TransferArrayBuffer(
uint32_t transfer_id,
343 Handle<JSArrayBuffer> array_buffer) {
344 DCHECK(!array_buffer_transfer_map_.Find(array_buffer));
345 DCHECK(!array_buffer->is_shared());
346 array_buffer_transfer_map_.Set(array_buffer, transfer_id);
349 Maybe<bool> ValueSerializer::WriteObject(Handle<Object>
object) {
350 out_of_memory_ =
false;
351 if (object->IsSmi()) {
352 WriteSmi(Smi::cast(*
object));
353 return ThrowIfOutOfMemory();
356 DCHECK(object->IsHeapObject());
357 switch (HeapObject::cast(*object)->map()->instance_type()) {
359 WriteOddball(Oddball::cast(*
object));
360 return ThrowIfOutOfMemory();
361 case HEAP_NUMBER_TYPE:
362 WriteHeapNumber(HeapNumber::cast(*
object));
363 return ThrowIfOutOfMemory();
364 case MUTABLE_HEAP_NUMBER_TYPE:
365 WriteMutableHeapNumber(MutableHeapNumber::cast(*
object));
366 return ThrowIfOutOfMemory();
368 WriteBigInt(BigInt::cast(*
object));
369 return ThrowIfOutOfMemory();
370 case JS_TYPED_ARRAY_TYPE:
371 case JS_DATA_VIEW_TYPE: {
377 Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(
object);
378 if (!id_map_.Find(view) && !treat_array_buffer_views_as_host_objects_) {
379 Handle<JSArrayBuffer> buffer(
380 view->IsJSTypedArray()
381 ? Handle<JSTypedArray>::cast(view)->GetBuffer()
382 : handle(JSArrayBuffer::cast(view->buffer()), isolate_));
383 if (!WriteJSReceiver(buffer).FromMaybe(
false))
return Nothing<bool>();
385 return WriteJSReceiver(view);
388 if (object->IsString()) {
389 WriteString(Handle<String>::cast(
object));
390 return ThrowIfOutOfMemory();
391 }
else if (object->IsJSReceiver()) {
392 return WriteJSReceiver(Handle<JSReceiver>::cast(
object));
394 ThrowDataCloneError(MessageTemplate::kDataCloneError,
object);
395 return Nothing<bool>();
400 void ValueSerializer::WriteOddball(Oddball* oddball) {
401 SerializationTag tag = SerializationTag::kUndefined;
402 switch (oddball->kind()) {
403 case Oddball::kUndefined:
404 tag = SerializationTag::kUndefined;
406 case Oddball::kFalse:
407 tag = SerializationTag::kFalse;
410 tag = SerializationTag::kTrue;
413 tag = SerializationTag::kNull;
422 void ValueSerializer::WriteSmi(Smi smi) {
423 static_assert(kSmiValueSize <= 32,
"Expected SMI <= 32 bits.");
424 WriteTag(SerializationTag::kInt32);
425 WriteZigZag<int32_t>(smi->value());
428 void ValueSerializer::WriteHeapNumber(HeapNumber* number) {
429 WriteTag(SerializationTag::kDouble);
430 WriteDouble(number->value());
433 void ValueSerializer::WriteMutableHeapNumber(MutableHeapNumber* number) {
434 WriteTag(SerializationTag::kDouble);
435 WriteDouble(number->value());
438 void ValueSerializer::WriteBigInt(BigInt* bigint) {
439 WriteTag(SerializationTag::kBigInt);
440 WriteBigIntContents(bigint);
443 void ValueSerializer::WriteString(Handle<String>
string) {
444 string = String::Flatten(isolate_,
string);
445 DisallowHeapAllocation no_gc;
446 String::FlatContent flat =
string->GetFlatContent();
447 DCHECK(flat.IsFlat());
448 if (flat.IsOneByte()) {
449 Vector<const uint8_t> chars = flat.ToOneByteVector();
450 WriteTag(SerializationTag::kOneByteString);
451 WriteOneByteString(chars);
452 }
else if (flat.IsTwoByte()) {
453 Vector<const uc16> chars = flat.ToUC16Vector();
454 uint32_t byte_length = chars.length() *
sizeof(uc16);
456 if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1)
457 WriteTag(SerializationTag::kPadding);
458 WriteTag(SerializationTag::kTwoByteString);
459 WriteTwoByteString(chars);
465 Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
467 uint32_t* id_map_entry = id_map_.Get(receiver);
469 WriteTag(SerializationTag::kObjectReference);
471 return ThrowIfOutOfMemory();
476 *id_map_entry =
id + 1;
479 InstanceType instance_type = receiver->map()->instance_type();
480 if (receiver->IsCallable() || (IsSpecialReceiverInstanceType(instance_type) &&
481 instance_type != JS_SPECIAL_API_OBJECT_TYPE)) {
482 ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
483 return Nothing<bool>();
487 STACK_CHECK(isolate_, Nothing<bool>());
489 HandleScope scope(isolate_);
490 switch (instance_type) {
492 return WriteJSArray(Handle<JSArray>::cast(receiver));
494 case JS_API_OBJECT_TYPE: {
495 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver);
496 if (JSObject::GetEmbedderFieldCount(js_object->map())) {
497 return WriteHostObject(js_object);
499 return WriteJSObject(js_object);
502 case JS_SPECIAL_API_OBJECT_TYPE:
503 return WriteHostObject(Handle<JSObject>::cast(receiver));
505 WriteJSDate(JSDate::cast(*receiver));
506 return ThrowIfOutOfMemory();
508 return WriteJSValue(Handle<JSValue>::cast(receiver));
510 WriteJSRegExp(JSRegExp::cast(*receiver));
511 return ThrowIfOutOfMemory();
513 return WriteJSMap(Handle<JSMap>::cast(receiver));
515 return WriteJSSet(Handle<JSSet>::cast(receiver));
516 case JS_ARRAY_BUFFER_TYPE:
517 return WriteJSArrayBuffer(Handle<JSArrayBuffer>::cast(receiver));
518 case JS_TYPED_ARRAY_TYPE:
519 case JS_DATA_VIEW_TYPE:
520 return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver));
521 case WASM_MODULE_TYPE: {
522 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
523 if (!FLAG_wasm_disable_structured_cloning || enabled_features.threads) {
525 return WriteWasmModule(Handle<WasmModuleObject>::cast(receiver));
529 case WASM_MEMORY_TYPE: {
530 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
531 if (enabled_features.threads) {
532 return WriteWasmMemory(Handle<WasmMemoryObject>::cast(receiver));
540 ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
541 return Nothing<bool>();
544 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject>
object) {
545 DCHECK(!object->map()->IsCustomElementsReceiverMap());
546 const bool can_serialize_fast =
547 object->HasFastProperties() &&
object->elements()->length() == 0;
548 if (!can_serialize_fast)
return WriteJSObjectSlow(
object);
550 Handle<Map> map(object->map(), isolate_);
551 WriteTag(SerializationTag::kBeginJSObject);
556 bool map_changed =
false;
557 for (
int i = 0;
i < map->NumberOfOwnDescriptors();
i++) {
558 Handle<Name> key(map->instance_descriptors()->GetKey(
i), isolate_);
559 if (!key->IsString())
continue;
560 PropertyDetails details = map->instance_descriptors()->GetDetails(
i);
561 if (details.IsDontEnum())
continue;
563 Handle<Object> value;
564 if (V8_LIKELY(!map_changed)) map_changed = *map == object->map();
565 if (V8_LIKELY(!map_changed && details.location() == kField)) {
566 DCHECK_EQ(kData, details.kind());
567 FieldIndex field_index = FieldIndex::ForDescriptor(*map,
i);
568 value = JSObject::FastPropertyAt(
object, details.representation(),
574 LookupIterator it(isolate_,
object, key, LookupIterator::OWN);
575 if (!it.IsFound())
continue;
576 if (!Object::GetProperty(&it).ToHandle(&value))
return Nothing<bool>();
579 if (!WriteObject(key).FromMaybe(
false) ||
580 !WriteObject(value).FromMaybe(
false)) {
581 return Nothing<bool>();
583 properties_written++;
586 WriteTag(SerializationTag::kEndJSObject);
587 WriteVarint<uint32_t>(properties_written);
588 return ThrowIfOutOfMemory();
591 Maybe<bool> ValueSerializer::WriteJSObjectSlow(Handle<JSObject>
object) {
592 WriteTag(SerializationTag::kBeginJSObject);
593 Handle<FixedArray> keys;
595 if (!KeyAccumulator::GetKeys(
object, KeyCollectionMode::kOwnOnly,
598 !WriteJSObjectPropertiesSlow(
object, keys).To(&properties_written)) {
599 return Nothing<bool>();
601 WriteTag(SerializationTag::kEndJSObject);
602 WriteVarint<uint32_t>(properties_written);
603 return ThrowIfOutOfMemory();
606 Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) {
608 bool valid_length = array->length()->ToArrayLength(&length);
609 DCHECK(valid_length);
617 const bool should_serialize_densely =
618 array->HasFastElements() && !array->HasHoleyElements();
620 if (should_serialize_densely) {
621 DCHECK_LE(length, static_cast<uint32_t>(FixedArray::kMaxLength));
622 WriteTag(SerializationTag::kBeginDenseJSArray);
623 WriteVarint<uint32_t>(length);
628 switch (array->GetElementsKind()) {
629 case PACKED_SMI_ELEMENTS: {
630 Handle<FixedArray> elements(FixedArray::cast(array->elements()),
632 for (;
i < length;
i++) WriteSmi(Smi::cast(elements->get(
i)));
635 case PACKED_DOUBLE_ELEMENTS: {
638 if (length == 0)
break;
639 Handle<FixedDoubleArray> elements(
640 FixedDoubleArray::cast(array->elements()), isolate_);
641 for (;
i < length;
i++) {
642 WriteTag(SerializationTag::kDouble);
643 WriteDouble(elements->get_scalar(
i));
647 case PACKED_ELEMENTS: {
648 Handle<Object> old_length(array->length(), isolate_);
649 for (;
i < length;
i++) {
650 if (array->length() != *old_length ||
651 array->GetElementsKind() != PACKED_ELEMENTS) {
655 Handle<Object> element(FixedArray::cast(array->elements())->
get(
i),
657 if (!WriteObject(element).FromMaybe(
false))
return Nothing<bool>();
666 for (;
i < length;
i++) {
670 Handle<Object> element;
671 LookupIterator it(isolate_, array,
i, array, LookupIterator::OWN);
676 WriteTag(SerializationTag::kTheHole);
679 if (!Object::GetProperty(&it).ToHandle(&element) ||
680 !WriteObject(element).FromMaybe(
false)) {
681 return Nothing<bool>();
685 KeyAccumulator accumulator(isolate_, KeyCollectionMode::kOwnOnly,
687 if (!accumulator.CollectOwnPropertyNames(array, array).FromMaybe(
false)) {
688 return Nothing<bool>();
690 Handle<FixedArray> keys =
691 accumulator.GetKeys(GetKeysConversion::kConvertToString);
693 if (!WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) {
694 return Nothing<bool>();
696 WriteTag(SerializationTag::kEndDenseJSArray);
697 WriteVarint<uint32_t>(properties_written);
698 WriteVarint<uint32_t>(length);
700 WriteTag(SerializationTag::kBeginSparseJSArray);
701 WriteVarint<uint32_t>(length);
702 Handle<FixedArray> keys;
704 if (!KeyAccumulator::GetKeys(array, KeyCollectionMode::kOwnOnly,
707 !WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) {
708 return Nothing<bool>();
710 WriteTag(SerializationTag::kEndSparseJSArray);
711 WriteVarint<uint32_t>(properties_written);
712 WriteVarint<uint32_t>(length);
714 return ThrowIfOutOfMemory();
717 void ValueSerializer::WriteJSDate(JSDate* date) {
718 WriteTag(SerializationTag::kDate);
719 WriteDouble(date->value()->Number());
722 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) {
723 Object* inner_value = value->value();
724 if (inner_value->IsTrue(isolate_)) {
725 WriteTag(SerializationTag::kTrueObject);
726 }
else if (inner_value->IsFalse(isolate_)) {
727 WriteTag(SerializationTag::kFalseObject);
728 }
else if (inner_value->IsNumber()) {
729 WriteTag(SerializationTag::kNumberObject);
730 WriteDouble(inner_value->Number());
731 }
else if (inner_value->IsBigInt()) {
732 WriteTag(SerializationTag::kBigIntObject);
733 WriteBigIntContents(BigInt::cast(inner_value));
734 }
else if (inner_value->IsString()) {
735 WriteTag(SerializationTag::kStringObject);
736 WriteString(handle(String::cast(inner_value), isolate_));
738 DCHECK(inner_value->IsSymbol());
739 ThrowDataCloneError(MessageTemplate::kDataCloneError, value);
740 return Nothing<bool>();
742 return ThrowIfOutOfMemory();
745 void ValueSerializer::WriteJSRegExp(JSRegExp* regexp) {
746 WriteTag(SerializationTag::kRegExp);
747 WriteString(handle(regexp->Pattern(), isolate_));
748 WriteVarint(static_cast<uint32_t>(regexp->GetFlags()));
751 Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) {
753 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()), isolate_);
754 int length = table->NumberOfElements() * 2;
755 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length);
757 DisallowHeapAllocation no_gc;
758 Oddball* the_hole = ReadOnlyRoots(isolate_).the_hole_value();
759 int capacity = table->UsedCapacity();
760 int result_index = 0;
761 for (
int i = 0;
i < capacity;
i++) {
762 Object* key = table->KeyAt(
i);
763 if (key == the_hole)
continue;
764 entries->set(result_index++, key);
765 entries->set(result_index++, table->ValueAt(
i));
767 DCHECK_EQ(result_index, length);
771 WriteTag(SerializationTag::kBeginJSMap);
772 for (
int i = 0;
i < length;
i++) {
773 if (!WriteObject(handle(entries->get(
i), isolate_)).FromMaybe(
false)) {
774 return Nothing<bool>();
777 WriteTag(SerializationTag::kEndJSMap);
778 WriteVarint<uint32_t>(length);
779 return ThrowIfOutOfMemory();
782 Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet>
set) {
784 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()), isolate_);
785 int length = table->NumberOfElements();
786 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length);
788 DisallowHeapAllocation no_gc;
789 Oddball* the_hole = ReadOnlyRoots(isolate_).the_hole_value();
790 int capacity = table->UsedCapacity();
791 int result_index = 0;
792 for (
int i = 0;
i < capacity;
i++) {
793 Object* key = table->KeyAt(
i);
794 if (key == the_hole)
continue;
795 entries->set(result_index++, key);
797 DCHECK_EQ(result_index, length);
801 WriteTag(SerializationTag::kBeginJSSet);
802 for (
int i = 0;
i < length;
i++) {
803 if (!WriteObject(handle(entries->get(
i), isolate_)).FromMaybe(
false)) {
804 return Nothing<bool>();
807 WriteTag(SerializationTag::kEndJSSet);
808 WriteVarint<uint32_t>(length);
809 return ThrowIfOutOfMemory();
812 Maybe<bool> ValueSerializer::WriteJSArrayBuffer(
813 Handle<JSArrayBuffer> array_buffer) {
814 if (array_buffer->is_shared()) {
816 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
817 return Nothing<bool>();
820 v8::Isolate* v8_isolate =
reinterpret_cast<v8::Isolate*
>(isolate_);
822 v8_isolate, Utils::ToLocalShared(array_buffer));
823 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
825 WriteTag(SerializationTag::kSharedArrayBuffer);
826 WriteVarint(index.FromJust());
827 return ThrowIfOutOfMemory();
830 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer);
831 if (transfer_entry) {
832 WriteTag(SerializationTag::kArrayBufferTransfer);
833 WriteVarint(*transfer_entry);
834 return ThrowIfOutOfMemory();
836 if (array_buffer->was_neutered()) {
837 ThrowDataCloneError(MessageTemplate::kDataCloneErrorNeuteredArrayBuffer);
838 return Nothing<bool>();
840 double byte_length = array_buffer->byte_length();
841 if (byte_length > std::numeric_limits<uint32_t>::max()) {
842 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
843 return Nothing<bool>();
845 WriteTag(SerializationTag::kArrayBuffer);
846 WriteVarint<uint32_t>(byte_length);
847 WriteRawBytes(array_buffer->backing_store(), byte_length);
848 return ThrowIfOutOfMemory();
851 Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) {
852 if (treat_array_buffer_views_as_host_objects_) {
853 return WriteHostObject(handle(view, isolate_));
855 WriteTag(SerializationTag::kArrayBufferView);
856 ArrayBufferViewTag tag = ArrayBufferViewTag::kInt8Array;
857 if (view->IsJSTypedArray()) {
858 switch (JSTypedArray::cast(view)->type()) {
859 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \ 860 case kExternal##Type##Array: \ 861 tag = ArrayBufferViewTag::k##Type##Array; \ 863 TYPED_ARRAYS(TYPED_ARRAY_CASE)
864 #undef TYPED_ARRAY_CASE 867 DCHECK(view->IsJSDataView());
868 tag = ArrayBufferViewTag::kDataView;
870 WriteVarint(static_cast<uint8_t>(tag));
871 WriteVarint(static_cast<uint32_t>(view->byte_offset()));
872 WriteVarint(static_cast<uint32_t>(view->byte_length()));
873 return ThrowIfOutOfMemory();
876 Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject>
object) {
877 if (delegate_ !=
nullptr) {
879 Maybe<uint32_t> transfer_id = delegate_->GetWasmModuleTransferId(
880 reinterpret_cast<v8::Isolate*>(isolate_),
882 Utils::ToLocal(Handle<JSObject>::cast(
object))));
883 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
885 if (transfer_id.To(&
id)) {
886 WriteTag(SerializationTag::kWasmModuleTransfer);
887 WriteVarint<uint32_t>(id);
892 WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes;
893 WriteTag(SerializationTag::kWasmModule);
894 WriteRawBytes(&encoding_tag,
sizeof(encoding_tag));
896 wasm::NativeModule* native_module =
object->native_module();
897 Vector<const uint8_t> wire_bytes = native_module->wire_bytes();
898 WriteVarint<uint32_t>(
static_cast<uint32_t>(wire_bytes.size()));
899 uint8_t* destination;
900 if (ReserveRawBytes(wire_bytes.size()).To(&destination)) {
901 memcpy(destination, wire_bytes.start(), wire_bytes.size());
904 wasm::WasmSerializer wasm_serializer(isolate_, native_module);
905 size_t module_size = wasm_serializer.GetSerializedNativeModuleSize();
906 CHECK_GE(std::numeric_limits<uint32_t>::max(), module_size);
907 WriteVarint<uint32_t>(
static_cast<uint32_t>(module_size));
908 uint8_t* module_buffer;
909 if (ReserveRawBytes(module_size).To(&module_buffer)) {
910 if (!wasm_serializer.SerializeNativeModule({module_buffer, module_size})) {
911 return Nothing<bool>();
914 return ThrowIfOutOfMemory();
917 Maybe<bool> ValueSerializer::WriteWasmMemory(Handle<WasmMemoryObject>
object) {
918 if (!object->array_buffer()->is_shared()) {
919 ThrowDataCloneError(MessageTemplate::kDataCloneError,
object);
920 return Nothing<bool>();
923 WriteTag(SerializationTag::kWasmMemoryTransfer);
924 WriteZigZag<int32_t>(
object->maximum_pages());
925 return WriteJSReceiver(Handle<JSReceiver>(object->array_buffer(), isolate_));
928 Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject>
object) {
929 WriteTag(SerializationTag::kHostObject);
931 isolate_->Throw(*isolate_->factory()->NewError(
932 isolate_->error_function(), MessageTemplate::kDataCloneError, object));
933 return Nothing<bool>();
935 v8::Isolate* v8_isolate =
reinterpret_cast<v8::Isolate*
>(isolate_);
938 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
939 DCHECK(!result.IsNothing());
943 Maybe<uint32_t> ValueSerializer::WriteJSObjectPropertiesSlow(
944 Handle<JSObject>
object, Handle<FixedArray> keys) {
946 int length = keys->length();
947 for (
int i = 0;
i < length;
i++) {
948 Handle<Object> key(keys->get(
i), isolate_);
951 LookupIterator it = LookupIterator::PropertyOrElement(
952 isolate_,
object, key, &success, LookupIterator::OWN);
954 Handle<Object> value;
955 if (!Object::GetProperty(&it).ToHandle(&value))
return Nothing<uint32_t>();
959 if (!it.IsFound())
continue;
961 if (!WriteObject(key).FromMaybe(
false) ||
962 !WriteObject(value).FromMaybe(
false)) {
963 return Nothing<uint32_t>();
966 properties_written++;
968 return Just(properties_written);
971 void ValueSerializer::ThrowDataCloneError(MessageTemplate template_index) {
972 return ThrowDataCloneError(template_index,
973 isolate_->factory()->empty_string());
976 Maybe<bool> ValueSerializer::ThrowIfOutOfMemory() {
977 if (out_of_memory_) {
978 ThrowDataCloneError(MessageTemplate::kDataCloneErrorOutOfMemory);
979 return Nothing<bool>();
984 void ValueSerializer::ThrowDataCloneError(MessageTemplate index,
985 Handle<Object> arg0) {
986 Handle<String> message =
987 MessageFormatter::FormatMessage(isolate_, index, arg0);
992 *isolate_->factory()->NewError(isolate_->error_function(), message));
994 if (isolate_->has_scheduled_exception()) {
995 isolate_->PromoteScheduledException();
999 ValueDeserializer::ValueDeserializer(Isolate* isolate,
1000 Vector<const uint8_t> data,
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_(Handle<FixedArray>::cast(isolate->global_handles()->Create(
1008 ReadOnlyRoots(isolate_).empty_fixed_array()))) {}
1010 ValueDeserializer::~ValueDeserializer() {
1011 GlobalHandles::Destroy(id_map_.location());
1013 Handle<Object> transfer_map_handle;
1014 if (array_buffer_transfer_map_.ToHandle(&transfer_map_handle)) {
1015 GlobalHandles::Destroy(transfer_map_handle.location());
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>();
1032 Maybe<SerializationTag> ValueDeserializer::PeekTag()
const {
1033 const uint8_t* peek_position = position_;
1034 SerializationTag tag;
1036 if (peek_position >= end_)
return Nothing<SerializationTag>();
1037 tag =
static_cast<SerializationTag
>(*peek_position);
1039 }
while (tag == SerializationTag::kPadding);
1043 void ValueDeserializer::ConsumeTag(SerializationTag peeked_tag) {
1044 SerializationTag actual_tag = ReadTag().ToChecked();
1045 DCHECK(actual_tag == peeked_tag);
1049 Maybe<SerializationTag> ValueDeserializer::ReadTag() {
1050 SerializationTag tag;
1052 if (position_ >= end_)
return Nothing<SerializationTag>();
1053 tag =
static_cast<SerializationTag
>(*position_);
1055 }
while (tag == SerializationTag::kPadding);
1059 template <
typename T>
1060 Maybe<T> ValueDeserializer::ReadVarint() {
1066 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
1067 "Only unsigned integer types can be read as varints.");
1070 bool has_another_byte;
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;
1078 has_another_byte = byte & 0x80;
1080 }
while (has_another_byte);
1084 template <
typename T>
1085 Maybe<T> ValueDeserializer::ReadZigZag() {
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)));
1098 Maybe<double> ValueDeserializer::ReadDouble() {
1100 if (position_ > end_ -
sizeof(
double))
return Nothing<double>();
1102 memcpy(&value, position_,
sizeof(
double));
1103 position_ +=
sizeof(double);
1104 if (std::isnan(value)) value = std::numeric_limits<double>::quiet_NaN();
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_;
1112 return Just(Vector<const uint8_t>(start, size));
1115 bool ValueDeserializer::ReadUint32(
uint32_t* value) {
1116 return ReadVarint<uint32_t>().To(value);
1119 bool ValueDeserializer::ReadUint64(uint64_t* value) {
1120 return ReadVarint<uint64_t>().To(value);
1123 bool ValueDeserializer::ReadDouble(
double* value) {
1124 return ReadDouble().To(value);
1127 bool ValueDeserializer::ReadRawBytes(
size_t length,
const void** data) {
1128 if (length > static_cast<size_t>(end_ - position_))
return false;
1130 position_ += length;
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_ =
1138 Handle<SimpleNumberDictionary>::cast(isolate_->global_handles()->Create(
1139 *SimpleNumberDictionary::New(isolate_, 0)));
1141 Handle<SimpleNumberDictionary> dictionary =
1142 array_buffer_transfer_map_.ToHandleChecked();
1143 Handle<SimpleNumberDictionary> new_dictionary = SimpleNumberDictionary::Set(
1144 isolate_, dictionary, transfer_id, array_buffer);
1145 if (!new_dictionary.is_identical_to(dictionary)) {
1146 GlobalHandles::Destroy(dictionary.location());
1147 array_buffer_transfer_map_ = Handle<SimpleNumberDictionary>::cast(
1148 isolate_->global_handles()->Create(*new_dictionary));
1152 MaybeHandle<Object> ValueDeserializer::ReadObject() {
1153 DisallowJavascriptExecution no_js(isolate_);
1154 MaybeHandle<Object> result = ReadObjectInternal();
1158 Handle<Object> object;
1159 SerializationTag tag;
1160 if (result.ToHandle(&
object) && V8_UNLIKELY(object->IsJSArrayBuffer()) &&
1161 PeekTag().To(&tag) && tag == SerializationTag::kArrayBufferView) {
1162 ConsumeTag(SerializationTag::kArrayBufferView);
1163 result = ReadJSArrayBufferView(Handle<JSArrayBuffer>::cast(
object));
1166 if (result.is_null() && !isolate_->has_pending_exception()) {
1167 isolate_->Throw(*isolate_->factory()->NewError(
1168 MessageTemplate::kDataCloneDeserializationError));
1174 MaybeHandle<Object> ValueDeserializer::ReadObjectInternal() {
1175 SerializationTag tag;
1176 if (!ReadTag().To(&tag))
return MaybeHandle<Object>();
1178 case SerializationTag::kVerifyObjectCount:
1180 if (ReadVarint<uint32_t>().IsNothing())
return MaybeHandle<Object>();
1181 return ReadObject();
1182 case SerializationTag::kUndefined:
1183 return isolate_->factory()->undefined_value();
1184 case SerializationTag::kNull:
1185 return isolate_->factory()->null_value();
1186 case SerializationTag::kTrue:
1187 return isolate_->factory()->true_value();
1188 case SerializationTag::kFalse:
1189 return isolate_->factory()->false_value();
1190 case SerializationTag::kInt32: {
1191 Maybe<int32_t> number = ReadZigZag<int32_t>();
1192 if (number.IsNothing())
return MaybeHandle<Object>();
1193 return isolate_->factory()->NewNumberFromInt(number.FromJust(),
1196 case SerializationTag::kUint32: {
1197 Maybe<uint32_t> number = ReadVarint<uint32_t>();
1198 if (number.IsNothing())
return MaybeHandle<Object>();
1199 return isolate_->factory()->NewNumberFromUint(number.FromJust(),
1202 case SerializationTag::kDouble: {
1203 Maybe<double> number = ReadDouble();
1204 if (number.IsNothing())
return MaybeHandle<Object>();
1205 return isolate_->factory()->NewNumber(number.FromJust(), pretenure_);
1207 case SerializationTag::kBigInt:
1208 return ReadBigInt();
1209 case SerializationTag::kUtf8String:
1210 return ReadUtf8String();
1211 case SerializationTag::kOneByteString:
1212 return ReadOneByteString();
1213 case SerializationTag::kTwoByteString:
1214 return ReadTwoByteString();
1215 case SerializationTag::kObjectReference: {
1217 if (!ReadVarint<uint32_t>().To(&
id))
return MaybeHandle<Object>();
1218 return GetObjectWithID(
id);
1220 case SerializationTag::kBeginJSObject:
1221 return ReadJSObject();
1222 case SerializationTag::kBeginSparseJSArray:
1223 return ReadSparseJSArray();
1224 case SerializationTag::kBeginDenseJSArray:
1225 return ReadDenseJSArray();
1226 case SerializationTag::kDate:
1227 return ReadJSDate();
1228 case SerializationTag::kTrueObject:
1229 case SerializationTag::kFalseObject:
1230 case SerializationTag::kNumberObject:
1231 case SerializationTag::kBigIntObject:
1232 case SerializationTag::kStringObject:
1233 return ReadJSValue(tag);
1234 case SerializationTag::kRegExp:
1235 return ReadJSRegExp();
1236 case SerializationTag::kBeginJSMap:
1238 case SerializationTag::kBeginJSSet:
1240 case SerializationTag::kArrayBuffer: {
1241 const bool is_shared =
false;
1242 return ReadJSArrayBuffer(is_shared);
1244 case SerializationTag::kArrayBufferTransfer: {
1245 return ReadTransferredJSArrayBuffer();
1247 case SerializationTag::kSharedArrayBuffer: {
1248 const bool is_shared =
true;
1249 return ReadJSArrayBuffer(is_shared);
1251 case SerializationTag::kWasmModule:
1252 return ReadWasmModule();
1253 case SerializationTag::kWasmModuleTransfer:
1254 return ReadWasmModuleTransfer();
1255 case SerializationTag::kWasmMemoryTransfer:
1256 return ReadWasmMemory();
1257 case SerializationTag::kHostObject:
1258 return ReadHostObject();
1262 if (version_ < 13) {
1264 return ReadHostObject();
1266 return MaybeHandle<Object>();
1270 MaybeHandle<String> ValueDeserializer::ReadString() {
1271 if (version_ < 12)
return ReadUtf8String();
1272 Handle<Object> object;
1273 if (!ReadObject().ToHandle(&
object) || !object->IsString()) {
1274 return MaybeHandle<String>();
1276 return Handle<String>::cast(
object);
1279 MaybeHandle<BigInt> ValueDeserializer::ReadBigInt() {
1281 if (!ReadVarint<uint32_t>().To(&bitfield))
return MaybeHandle<BigInt>();
1282 int bytelength = BigInt::DigitsByteLengthForBitfield(bitfield);
1283 Vector<const uint8_t> digits_storage;
1284 if (!ReadRawBytes(bytelength).To(&digits_storage)) {
1285 return MaybeHandle<BigInt>();
1287 return BigInt::FromSerializedDigits(isolate_, bitfield, digits_storage,
1291 MaybeHandle<String> ValueDeserializer::ReadUtf8String() {
1293 Vector<const uint8_t> utf8_bytes;
1294 if (!ReadVarint<uint32_t>().To(&utf8_length) ||
1296 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1297 !ReadRawBytes(utf8_length).To(&utf8_bytes)) {
1298 return MaybeHandle<String>();
1300 return isolate_->factory()->NewStringFromUtf8(
1301 Vector<const char>::cast(utf8_bytes), pretenure_);
1304 MaybeHandle<String> ValueDeserializer::ReadOneByteString() {
1306 Vector<const uint8_t> bytes;
1307 if (!ReadVarint<uint32_t>().To(&byte_length) ||
1309 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1310 !ReadRawBytes(byte_length).To(&bytes)) {
1311 return MaybeHandle<String>();
1313 return isolate_->factory()->NewStringFromOneByte(bytes, pretenure_);
1316 MaybeHandle<String> ValueDeserializer::ReadTwoByteString() {
1318 Vector<const uint8_t> bytes;
1319 if (!ReadVarint<uint32_t>().To(&byte_length) ||
1321 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1322 byte_length %
sizeof(uc16) != 0 ||
1323 !ReadRawBytes(byte_length).To(&bytes)) {
1324 return MaybeHandle<String>();
1329 if (byte_length == 0)
return isolate_->factory()->empty_string();
1330 Handle<SeqTwoByteString> string;
1331 if (!isolate_->factory()
1332 ->NewRawTwoByteString(byte_length /
sizeof(uc16), pretenure_)
1333 .ToHandle(&
string)) {
1334 return MaybeHandle<String>();
1339 DisallowHeapAllocation no_gc;
1340 memcpy(string->GetChars(), bytes.begin(), bytes.length());
1344 bool ValueDeserializer::ReadExpectedString(Handle<String> expected) {
1345 DisallowHeapAllocation no_gc;
1347 const uint8_t* original_position = position_;
1349 SerializationTag tag;
1351 Vector<const uint8_t> bytes;
1352 if (!ReadTag().To(&tag) || !ReadVarint<uint32_t>().To(&byte_length) ||
1354 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1355 !ReadRawBytes(byte_length).To(&bytes)) {
1356 position_ = original_position;
1360 String::FlatContent flat = expected->GetFlatContent();
1364 if (tag == SerializationTag::kOneByteString && flat.IsOneByte()) {
1365 Vector<const uint8_t> chars = flat.ToOneByteVector();
1366 if (byte_length == static_cast<size_t>(chars.length()) &&
1367 memcmp(bytes.begin(), chars.begin(), byte_length) == 0) {
1370 }
else if (tag == SerializationTag::kTwoByteString && flat.IsTwoByte()) {
1371 Vector<const uc16> chars = flat.ToUC16Vector();
1372 if (byte_length == static_cast<unsigned>(chars.length()) *
sizeof(uc16) &&
1373 memcmp(bytes.begin(), chars.begin(), byte_length) == 0) {
1376 }
else if (tag == SerializationTag::kUtf8String && flat.IsOneByte()) {
1377 Vector<const uint8_t> chars = flat.ToOneByteVector();
1378 if (byte_length == static_cast<size_t>(chars.length()) &&
1379 String::IsAscii(chars.begin(), chars.length()) &&
1380 memcmp(bytes.begin(), chars.begin(), byte_length) == 0) {
1385 position_ = original_position;
1389 MaybeHandle<JSObject> ValueDeserializer::ReadJSObject() {
1391 STACK_CHECK(isolate_, MaybeHandle<JSObject>());
1394 HandleScope scope(isolate_);
1395 Handle<JSObject>
object =
1396 isolate_->factory()->NewJSObject(isolate_->object_function(), pretenure_);
1397 AddObjectWithID(
id,
object);
1401 if (!ReadJSObjectProperties(
object, SerializationTag::kEndJSObject,
true)
1402 .To(&num_properties) ||
1403 !ReadVarint<uint32_t>().To(&expected_num_properties) ||
1404 num_properties != expected_num_properties) {
1405 return MaybeHandle<JSObject>();
1408 DCHECK(HasObjectWithID(
id));
1409 return scope.CloseAndEscape(
object);
1412 MaybeHandle<JSArray> ValueDeserializer::ReadSparseJSArray() {
1414 STACK_CHECK(isolate_, MaybeHandle<JSArray>());
1417 if (!ReadVarint<uint32_t>().To(&length))
return MaybeHandle<JSArray>();
1420 HandleScope scope(isolate_);
1421 Handle<JSArray> array = isolate_->factory()->NewJSArray(
1422 0, TERMINAL_FAST_ELEMENTS_KIND, pretenure_);
1423 JSArray::SetLength(array, length);
1424 AddObjectWithID(
id, array);
1429 if (!ReadJSObjectProperties(array, SerializationTag::kEndSparseJSArray,
false)
1430 .To(&num_properties) ||
1431 !ReadVarint<uint32_t>().To(&expected_num_properties) ||
1432 !ReadVarint<uint32_t>().To(&expected_length) ||
1433 num_properties != expected_num_properties || length != expected_length) {
1434 return MaybeHandle<JSArray>();
1437 DCHECK(HasObjectWithID(
id));
1438 return scope.CloseAndEscape(array);
1441 MaybeHandle<JSArray> ValueDeserializer::ReadDenseJSArray() {
1443 STACK_CHECK(isolate_, MaybeHandle<JSArray>());
1449 if (!ReadVarint<uint32_t>().To(&length) ||
1450 length > static_cast<uint32_t>(FixedArray::kMaxLength) ||
1451 length > static_cast<size_t>(end_ - position_)) {
1452 return MaybeHandle<JSArray>();
1456 HandleScope scope(isolate_);
1457 Handle<JSArray> array = isolate_->factory()->NewJSArray(
1458 HOLEY_ELEMENTS, length, length, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE,
1460 AddObjectWithID(
id, array);
1462 Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate_);
1464 SerializationTag tag;
1465 if (PeekTag().To(&tag) && tag == SerializationTag::kTheHole) {
1466 ConsumeTag(SerializationTag::kTheHole);
1470 Handle<Object> element;
1471 if (!ReadObject().ToHandle(&element))
return MaybeHandle<JSArray>();
1476 if (version_ < 11 && element->IsUndefined(isolate_))
continue;
1479 CHECK_LT(
i, static_cast<uint32_t>(elements->length()));
1481 elements->set(
i, *element);
1487 if (!ReadJSObjectProperties(array, SerializationTag::kEndDenseJSArray,
false)
1488 .To(&num_properties) ||
1489 !ReadVarint<uint32_t>().To(&expected_num_properties) ||
1490 !ReadVarint<uint32_t>().To(&expected_length) ||
1491 num_properties != expected_num_properties || length != expected_length) {
1492 return MaybeHandle<JSArray>();
1495 DCHECK(HasObjectWithID(
id));
1496 return scope.CloseAndEscape(array);
1499 MaybeHandle<JSDate> ValueDeserializer::ReadJSDate() {
1501 if (!ReadDouble().To(&value))
return MaybeHandle<JSDate>();
1503 Handle<JSDate> date;
1504 if (!JSDate::New(isolate_->date_function(), isolate_->date_function(), value)
1506 return MaybeHandle<JSDate>();
1508 AddObjectWithID(
id, date);
1512 MaybeHandle<JSValue> ValueDeserializer::ReadJSValue(SerializationTag tag) {
1514 Handle<JSValue> value;
1516 case SerializationTag::kTrueObject:
1517 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1518 isolate_->boolean_function(), pretenure_));
1519 value->set_value(ReadOnlyRoots(isolate_).true_value());
1521 case SerializationTag::kFalseObject:
1522 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1523 isolate_->boolean_function(), pretenure_));
1524 value->set_value(ReadOnlyRoots(isolate_).false_value());
1526 case SerializationTag::kNumberObject: {
1528 if (!ReadDouble().To(&number))
return MaybeHandle<JSValue>();
1529 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1530 isolate_->number_function(), pretenure_));
1531 Handle<Object> number_object =
1532 isolate_->factory()->NewNumber(number, pretenure_);
1533 value->set_value(*number_object);
1536 case SerializationTag::kBigIntObject: {
1537 Handle<BigInt> bigint;
1538 if (!ReadBigInt().ToHandle(&bigint))
return MaybeHandle<JSValue>();
1539 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1540 isolate_->bigint_function(), pretenure_));
1541 value->set_value(*bigint);
1544 case SerializationTag::kStringObject: {
1545 Handle<String> string;
1546 if (!ReadString().ToHandle(&
string))
return MaybeHandle<JSValue>();
1547 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject(
1548 isolate_->string_function(), pretenure_));
1549 value->set_value(*
string);
1555 AddObjectWithID(
id, value);
1559 MaybeHandle<JSRegExp> ValueDeserializer::ReadJSRegExp() {
1561 Handle<String> pattern;
1563 Handle<JSRegExp> regexp;
1564 if (!ReadString().ToHandle(&pattern) ||
1565 !ReadVarint<uint32_t>().To(&raw_flags)) {
1566 return MaybeHandle<JSRegExp>();
1572 if ((raw_flags & flags_mask) ||
1573 !JSRegExp::New(isolate_, pattern, static_cast<JSRegExp::Flags>(raw_flags))
1574 .ToHandle(®exp)) {
1575 return MaybeHandle<JSRegExp>();
1578 AddObjectWithID(
id, regexp);
1582 MaybeHandle<JSMap> ValueDeserializer::ReadJSMap() {
1584 STACK_CHECK(isolate_, MaybeHandle<JSMap>());
1586 HandleScope scope(isolate_);
1588 Handle<JSMap> map = isolate_->factory()->NewJSMap();
1589 AddObjectWithID(
id, map);
1591 Handle<JSFunction> map_set = isolate_->map_set();
1594 SerializationTag tag;
1595 if (!PeekTag().To(&tag))
return MaybeHandle<JSMap>();
1596 if (tag == SerializationTag::kEndJSMap) {
1597 ConsumeTag(SerializationTag::kEndJSMap);
1601 Handle<Object> argv[2];
1602 if (!ReadObject().ToHandle(&argv[0]) || !ReadObject().ToHandle(&argv[1])) {
1603 return MaybeHandle<JSMap>();
1606 AllowJavascriptExecution allow_js(isolate_);
1607 if (Execution::Call(isolate_, map_set, map, arraysize(argv), argv)
1609 return MaybeHandle<JSMap>();
1615 if (!ReadVarint<uint32_t>().To(&expected_length) ||
1616 length != expected_length) {
1617 return MaybeHandle<JSMap>();
1619 DCHECK(HasObjectWithID(
id));
1620 return scope.CloseAndEscape(map);
1623 MaybeHandle<JSSet> ValueDeserializer::ReadJSSet() {
1625 STACK_CHECK(isolate_, MaybeHandle<JSSet>());
1627 HandleScope scope(isolate_);
1629 Handle<JSSet>
set = isolate_->factory()->NewJSSet();
1630 AddObjectWithID(
id,
set);
1631 Handle<JSFunction> set_add = isolate_->set_add();
1634 SerializationTag tag;
1635 if (!PeekTag().To(&tag))
return MaybeHandle<JSSet>();
1636 if (tag == SerializationTag::kEndJSSet) {
1637 ConsumeTag(SerializationTag::kEndJSSet);
1641 Handle<Object> argv[1];
1642 if (!ReadObject().ToHandle(&argv[0]))
return MaybeHandle<JSSet>();
1644 AllowJavascriptExecution allow_js(isolate_);
1645 if (Execution::Call(isolate_, set_add,
set, arraysize(argv), argv)
1647 return MaybeHandle<JSSet>();
1653 if (!ReadVarint<uint32_t>().To(&expected_length) ||
1654 length != expected_length) {
1655 return MaybeHandle<JSSet>();
1657 DCHECK(HasObjectWithID(
id));
1658 return scope.CloseAndEscape(
set);
1661 MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadJSArrayBuffer(
1666 Local<SharedArrayBuffer> sab_value;
1667 if (!ReadVarint<uint32_t>().To(&clone_id) || delegate_ ==
nullptr ||
1669 ->GetSharedArrayBufferFromId(
1670 reinterpret_cast<v8::Isolate*>(isolate_), clone_id)
1671 .ToLocal(&sab_value)) {
1672 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSArrayBuffer);
1673 return MaybeHandle<JSArrayBuffer>();
1675 Handle<JSArrayBuffer> array_buffer = Utils::OpenHandle(*sab_value);
1676 DCHECK_EQ(is_shared, array_buffer->is_shared());
1677 AddObjectWithID(
id, array_buffer);
1678 return array_buffer;
1681 if (!ReadVarint<uint32_t>().To(&byte_length) ||
1682 byte_length > static_cast<size_t>(end_ - position_)) {
1683 return MaybeHandle<JSArrayBuffer>();
1685 const bool should_initialize =
false;
1686 Handle<JSArrayBuffer> array_buffer =
1687 isolate_->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, pretenure_);
1688 if (!JSArrayBuffer::SetupAllocatingData(array_buffer, isolate_, byte_length,
1689 should_initialize)) {
1690 return MaybeHandle<JSArrayBuffer>();
1692 memcpy(array_buffer->backing_store(), position_, byte_length);
1693 position_ += byte_length;
1694 AddObjectWithID(
id, array_buffer);
1695 return array_buffer;
1698 MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadTransferredJSArrayBuffer() {
1701 Handle<SimpleNumberDictionary> transfer_map;
1702 if (!ReadVarint<uint32_t>().To(&transfer_id) ||
1703 !array_buffer_transfer_map_.ToHandle(&transfer_map)) {
1704 return MaybeHandle<JSArrayBuffer>();
1706 int index = transfer_map->FindEntry(isolate_, transfer_id);
1707 if (index == SimpleNumberDictionary::kNotFound) {
1708 return MaybeHandle<JSArrayBuffer>();
1710 Handle<JSArrayBuffer> array_buffer(
1711 JSArrayBuffer::cast(transfer_map->ValueAt(index)), isolate_);
1712 AddObjectWithID(
id, array_buffer);
1713 return array_buffer;
1716 MaybeHandle<JSArrayBufferView> ValueDeserializer::ReadJSArrayBufferView(
1717 Handle<JSArrayBuffer> buffer) {
1718 uint32_t buffer_byte_length =
static_cast<uint32_t>(buffer->byte_length());
1722 if (!ReadVarint<uint8_t>().To(&tag) ||
1723 !ReadVarint<uint32_t>().To(&byte_offset) ||
1724 !ReadVarint<uint32_t>().To(&byte_length) ||
1725 byte_offset > buffer_byte_length ||
1726 byte_length > buffer_byte_length - byte_offset) {
1727 return MaybeHandle<JSArrayBufferView>();
1730 ExternalArrayType external_array_type = kExternalInt8Array;
1731 unsigned element_size = 0;
1733 switch (static_cast<ArrayBufferViewTag>(tag)) {
1734 case ArrayBufferViewTag::kDataView: {
1735 Handle<JSDataView> data_view =
1736 isolate_->factory()->NewJSDataView(buffer, byte_offset, byte_length);
1737 AddObjectWithID(
id, data_view);
1740 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \ 1741 case ArrayBufferViewTag::k##Type##Array: \ 1742 external_array_type = kExternal##Type##Array; \ 1743 element_size = sizeof(ctype); \ 1745 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1746 #undef TYPED_ARRAY_CASE 1748 if (element_size == 0 || byte_offset % element_size != 0 ||
1749 byte_length % element_size != 0) {
1750 return MaybeHandle<JSArrayBufferView>();
1752 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray(
1753 external_array_type, buffer, byte_offset, byte_length / element_size,
1755 AddObjectWithID(
id, typed_array);
1759 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModuleTransfer() {
1760 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1761 if ((FLAG_wasm_disable_structured_cloning && !enabled_features.threads) ||
1762 expect_inline_wasm()) {
1763 return MaybeHandle<JSObject>();
1767 Local<Value> module_value;
1768 if (!ReadVarint<uint32_t>().To(&transfer_id) || delegate_ ==
nullptr ||
1772 .ToLocal(&module_value)) {
1773 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject);
1774 return MaybeHandle<JSObject>();
1777 Handle<JSObject> module =
1778 Handle<JSObject>::cast(Utils::OpenHandle(*module_value));
1779 AddObjectWithID(
id, module);
1783 MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
1784 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1785 if ((FLAG_wasm_disable_structured_cloning && !enabled_features.threads) ||
1786 !expect_inline_wasm()) {
1787 return MaybeHandle<JSObject>();
1790 Vector<const uint8_t> encoding_tag;
1791 if (!ReadRawBytes(
sizeof(WasmEncodingTag)).To(&encoding_tag) ||
1792 encoding_tag[0] !=
static_cast<uint8_t
>(WasmEncodingTag::kRawBytes)) {
1793 return MaybeHandle<JSObject>();
1798 static_assert(
sizeof(
int) <=
sizeof(
uint32_t),
1799 "max int must fit in uint32_t");
1800 const uint32_t max_valid_size = std::numeric_limits<int>::max();
1802 Vector<const uint8_t> wire_bytes;
1803 uint32_t compiled_bytes_length = 0;
1804 Vector<const uint8_t> compiled_bytes;
1805 if (!ReadVarint<uint32_t>().To(&wire_bytes_length) ||
1806 wire_bytes_length > max_valid_size ||
1807 !ReadRawBytes(wire_bytes_length).To(&wire_bytes) ||
1808 !ReadVarint<uint32_t>().To(&compiled_bytes_length) ||
1809 compiled_bytes_length > max_valid_size ||
1810 !ReadRawBytes(compiled_bytes_length).To(&compiled_bytes)) {
1811 return MaybeHandle<JSObject>();
1815 MaybeHandle<WasmModuleObject> result =
1816 wasm::DeserializeNativeModule(isolate_, compiled_bytes, wire_bytes);
1817 if (result.is_null()) {
1818 wasm::ErrorThrower thrower(isolate_,
"ValueDeserializer::ReadWasmModule");
1820 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1821 result = isolate_->wasm_engine()->SyncCompile(
1822 isolate_, enabled_features, &thrower,
1823 wasm::ModuleWireBytes(wire_bytes));
1826 if (!result.is_null()) {
1827 AddObjectWithID(
id, result.ToHandleChecked());
1832 MaybeHandle<WasmMemoryObject> ValueDeserializer::ReadWasmMemory() {
1835 auto enabled_features = wasm::WasmFeaturesFromIsolate(isolate_);
1836 if (!enabled_features.threads) {
1837 return MaybeHandle<WasmMemoryObject>();
1840 int32_t maximum_pages;
1841 if (!ReadZigZag<int32_t>().To(&maximum_pages)) {
1842 return MaybeHandle<WasmMemoryObject>();
1845 SerializationTag tag;
1846 if (!ReadTag().To(&tag) || tag != SerializationTag::kSharedArrayBuffer) {
1847 return MaybeHandle<WasmMemoryObject>();
1850 const bool is_shared =
true;
1851 Handle<JSArrayBuffer> buffer;
1852 if (!ReadJSArrayBuffer(is_shared).ToHandle(&buffer)) {
1853 return MaybeHandle<WasmMemoryObject>();
1856 Handle<WasmMemoryObject> result =
1857 WasmMemoryObject::New(isolate_, buffer, maximum_pages);
1859 AddObjectWithID(
id, result);
1863 MaybeHandle<JSObject> ValueDeserializer::ReadHostObject() {
1864 if (!delegate_)
return MaybeHandle<JSObject>();
1865 STACK_CHECK(isolate_, MaybeHandle<JSObject>());
1867 v8::Isolate* v8_isolate =
reinterpret_cast<v8::Isolate*
>(isolate_);
1870 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject);
1871 return MaybeHandle<JSObject>();
1873 Handle<JSObject> js_object =
1874 Handle<JSObject>::cast(Utils::OpenHandle(*
object));
1875 AddObjectWithID(
id, js_object);
1881 static void CommitProperties(Handle<JSObject>
object, Handle<Map> map,
1882 const std::vector<Handle<Object>>& properties) {
1883 JSObject::AllocateStorageForMap(
object, map);
1884 DCHECK(!object->map()->is_dictionary_map());
1886 DisallowHeapAllocation no_gc;
1887 DescriptorArray* descriptors =
object->map()->instance_descriptors();
1888 for (
unsigned i = 0;
i < properties.size();
i++) {
1890 object->WriteToField(
i, descriptors->GetDetails(
i), *properties[
i]);
1894 static bool IsValidObjectKey(Handle<Object> value) {
1895 return value->IsName() || value->IsNumber();
1898 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties(
1899 Handle<JSObject>
object, SerializationTag end_tag,
1900 bool can_use_transitions) {
1904 if (can_use_transitions) {
1905 bool transitioning =
true;
1906 Handle<Map> map(object->map(), isolate_);
1907 DCHECK(!map->is_dictionary_map());
1908 DCHECK_EQ(0, map->instance_descriptors()->number_of_descriptors());
1909 std::vector<Handle<Object>> properties;
1910 properties.reserve(8);
1912 while (transitioning) {
1914 SerializationTag tag;
1915 if (!PeekTag().To(&tag))
return Nothing<uint32_t>();
1916 if (tag == end_tag) {
1917 ConsumeTag(end_tag);
1918 CommitProperties(
object, map, properties);
1919 CHECK_LT(properties.size(), std::numeric_limits<uint32_t>::max());
1920 return Just(static_cast<uint32_t>(properties.size()));
1928 TransitionsAccessor transitions(isolate_, map);
1929 Handle<String> expected_key = transitions.ExpectedTransitionKey();
1930 if (!expected_key.is_null() && ReadExpectedString(expected_key)) {
1932 target = transitions.ExpectedTransitionTarget();
1934 if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) {
1935 return Nothing<uint32_t>();
1937 if (key->IsString()) {
1939 isolate_->factory()->InternalizeString(Handle<String>::cast(key));
1941 transitioning = TransitionsAccessor(isolate_, map)
1942 .FindTransitionToField(Handle<String>::cast(key))
1945 transitioning =
false;
1950 Handle<Object> value;
1951 if (!ReadObject().ToHandle(&value))
return Nothing<uint32_t>();
1956 if (transitioning) {
1957 int descriptor =
static_cast<int>(properties.size());
1958 PropertyDetails details =
1959 target->instance_descriptors()->GetDetails(descriptor);
1960 Representation expected_representation = details.representation();
1961 if (value->FitsRepresentation(expected_representation)) {
1962 if (expected_representation.IsHeapObject() &&
1963 !target->instance_descriptors()
1964 ->GetFieldType(descriptor)
1965 ->NowContains(value)) {
1966 Handle<FieldType> value_type =
1967 value->OptimalType(isolate_, expected_representation);
1968 Map::GeneralizeField(isolate_, target, descriptor,
1969 details.constness(), expected_representation,
1972 DCHECK(target->instance_descriptors()
1973 ->GetFieldType(descriptor)
1974 ->NowContains(value));
1975 properties.push_back(value);
1979 transitioning =
false;
1985 DCHECK(!transitioning);
1986 CHECK_LT(properties.size(), std::numeric_limits<uint32_t>::max());
1987 CommitProperties(
object, map, properties);
1988 num_properties =
static_cast<uint32_t>(properties.size());
1991 LookupIterator it = LookupIterator::PropertyOrElement(
1992 isolate_,
object, key, &success, LookupIterator::OWN);
1993 CHECK_EQ(LookupIterator::NOT_FOUND, it.state());
1995 JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE)
1997 return Nothing<uint32_t>();
2005 DCHECK(!transitioning);
2006 DCHECK_GE(num_properties, 1u);
2010 for (;; num_properties++) {
2011 SerializationTag tag;
2012 if (!PeekTag().To(&tag))
return Nothing<uint32_t>();
2013 if (tag == end_tag) {
2014 ConsumeTag(end_tag);
2015 return Just(num_properties);
2019 if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) {
2020 return Nothing<uint32_t>();
2022 Handle<Object> value;
2023 if (!ReadObject().ToHandle(&value))
return Nothing<uint32_t>();
2026 LookupIterator it = LookupIterator::PropertyOrElement(
2027 isolate_,
object, key, &success, LookupIterator::OWN);
2028 CHECK_EQ(LookupIterator::NOT_FOUND, it.state());
2030 JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE)
2032 return Nothing<uint32_t>();
2037 bool ValueDeserializer::HasObjectWithID(
uint32_t id) {
2038 return id < static_cast<unsigned>(id_map_->length()) &&
2039 !id_map_->get(
id)->IsTheHole(isolate_);
2042 MaybeHandle<JSReceiver> ValueDeserializer::GetObjectWithID(
uint32_t id) {
2043 if (
id >= static_cast<unsigned>(id_map_->length())) {
2044 return MaybeHandle<JSReceiver>();
2046 Object* value = id_map_->get(
id);
2047 if (value->IsTheHole(isolate_))
return MaybeHandle<JSReceiver>();
2048 DCHECK(value->IsJSReceiver());
2049 return Handle<JSReceiver>(JSReceiver::cast(value), isolate_);
2052 void ValueDeserializer::AddObjectWithID(
uint32_t id,
2053 Handle<JSReceiver>
object) {
2054 DCHECK(!HasObjectWithID(
id));
2055 Handle<FixedArray> new_array =
2056 FixedArray::SetAndGrow(isolate_, id_map_,
id,
object);
2059 if (!new_array.is_identical_to(id_map_)) {
2060 GlobalHandles::Destroy(id_map_.location());
2061 id_map_ = Handle<FixedArray>::cast(
2062 isolate_->global_handles()->Create(*new_array));
2066 static Maybe<bool> SetPropertiesFromKeyValuePairs(Isolate* isolate,
2067 Handle<JSObject>
object,
2068 Handle<Object>* data,
2070 for (
unsigned i = 0;
i < 2 * num_properties;
i += 2) {
2071 Handle<Object> key = data[
i];
2072 if (!IsValidObjectKey(key))
return Nothing<bool>();
2073 Handle<Object> value = data[
i + 1];
2075 LookupIterator it = LookupIterator::PropertyOrElement(
2076 isolate,
object, key, &success, LookupIterator::OWN);
2077 CHECK_EQ(LookupIterator::NOT_FOUND, it.state());
2079 JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE)
2081 return Nothing<bool>();
2091 void ThrowDeserializationExceptionIfNonePending(Isolate* isolate) {
2092 if (!isolate->has_pending_exception()) {
2093 isolate->Throw(*isolate->factory()->NewError(
2094 MessageTemplate::kDataCloneDeserializationError));
2096 DCHECK(isolate->has_pending_exception());
2102 ValueDeserializer::ReadObjectUsingEntireBufferForLegacyFormat() {
2103 DCHECK_EQ(version_, 0u);
2104 HandleScope scope(isolate_);
2105 std::vector<Handle<Object>> stack;
2106 while (position_ < end_) {
2107 SerializationTag tag;
2108 if (!PeekTag().To(&tag))
break;
2110 Handle<Object> new_object;
2112 case SerializationTag::kEndJSObject: {
2113 ConsumeTag(SerializationTag::kEndJSObject);
2118 if (!ReadVarint<uint32_t>().To(&num_properties) ||
2119 stack.size() / 2 < num_properties) {
2120 isolate_->Throw(*isolate_->factory()->NewError(
2121 MessageTemplate::kDataCloneDeserializationError));
2122 return MaybeHandle<Object>();
2125 size_t begin_properties =
2126 stack.size() - 2 *
static_cast<size_t>(num_properties);
2127 Handle<JSObject> js_object = isolate_->factory()->NewJSObject(
2128 isolate_->object_function(), pretenure_);
2129 if (num_properties &&
2130 !SetPropertiesFromKeyValuePairs(
2131 isolate_, js_object, &stack[begin_properties], num_properties)
2132 .FromMaybe(
false)) {
2133 ThrowDeserializationExceptionIfNonePending(isolate_);
2134 return MaybeHandle<Object>();
2137 stack.resize(begin_properties);
2138 new_object = js_object;
2141 case SerializationTag::kEndSparseJSArray: {
2142 ConsumeTag(SerializationTag::kEndSparseJSArray);
2147 if (!ReadVarint<uint32_t>().To(&num_properties) ||
2148 !ReadVarint<uint32_t>().To(&length) ||
2149 stack.size() / 2 < num_properties) {
2150 isolate_->Throw(*isolate_->factory()->NewError(
2151 MessageTemplate::kDataCloneDeserializationError));
2152 return MaybeHandle<Object>();
2155 Handle<JSArray> js_array = isolate_->factory()->NewJSArray(
2156 0, TERMINAL_FAST_ELEMENTS_KIND, pretenure_);
2157 JSArray::SetLength(js_array, length);
2158 size_t begin_properties =
2159 stack.size() - 2 *
static_cast<size_t>(num_properties);
2160 if (num_properties &&
2161 !SetPropertiesFromKeyValuePairs(
2162 isolate_, js_array, &stack[begin_properties], num_properties)
2163 .FromMaybe(
false)) {
2164 ThrowDeserializationExceptionIfNonePending(isolate_);
2165 return MaybeHandle<Object>();
2168 stack.resize(begin_properties);
2169 new_object = js_array;
2172 case SerializationTag::kEndDenseJSArray: {
2174 isolate_->Throw(*isolate_->factory()->NewError(
2175 MessageTemplate::kDataCloneDeserializationError));
2176 return MaybeHandle<Object>();
2179 if (!ReadObject().ToHandle(&new_object))
return MaybeHandle<Object>();
2182 stack.push_back(new_object);
2187 while (position_ < end_) {
2188 DCHECK(*position_++ == static_cast<uint8_t>(SerializationTag::kPadding));
2193 if (stack.size() != 1) {
2194 isolate_->Throw(*isolate_->factory()->NewError(
2195 MessageTemplate::kDataCloneDeserializationError));
2196 return MaybeHandle<Object>();
2198 return scope.CloseAndEscape(stack[0]);
virtual Maybe< uint32_t > GetSharedArrayBufferId(Isolate *isolate, Local< SharedArrayBuffer > shared_array_buffer)
virtual void * ReallocateBufferMemory(void *old_buffer, size_t size, size_t *actual_size)
virtual void FreeBufferMemory(void *buffer)
virtual MaybeLocal< Object > ReadHostObject(Isolate *isolate)
virtual MaybeLocal< WasmCompiledModule > GetWasmModuleFromId(Isolate *isolate, uint32_t transfer_id)
virtual Maybe< bool > WriteHostObject(Isolate *isolate, Local< Object > object)
virtual void ThrowDataCloneError(Local< String > message)=0