| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/value-serializer.h" | 5 #include "src/value-serializer.h" |
| 6 | 6 |
| 7 #include <type_traits> | 7 #include <type_traits> |
| 8 | 8 |
| 9 #include "src/base/logging.h" | 9 #include "src/base/logging.h" |
| 10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 buffer_.insert(buffer_.end(), begin, begin + length); | 198 buffer_.insert(buffer_.end(), begin, begin + length); |
| 199 } | 199 } |
| 200 | 200 |
| 201 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { | 201 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { |
| 202 if (!bytes) return nullptr; | 202 if (!bytes) return nullptr; |
| 203 auto old_size = buffer_.size(); | 203 auto old_size = buffer_.size(); |
| 204 buffer_.resize(buffer_.size() + bytes); | 204 buffer_.resize(buffer_.size() + bytes); |
| 205 return &buffer_[old_size]; | 205 return &buffer_[old_size]; |
| 206 } | 206 } |
| 207 | 207 |
| 208 void ValueSerializer::WriteUint32(uint32_t value) { |
| 209 WriteVarint<uint32_t>(value); |
| 210 } |
| 211 |
| 212 void ValueSerializer::WriteUint64(uint64_t value) { |
| 213 WriteVarint<uint64_t>(value); |
| 214 } |
| 215 |
| 208 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, | 216 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, |
| 209 Handle<JSArrayBuffer> array_buffer) { | 217 Handle<JSArrayBuffer> array_buffer) { |
| 210 DCHECK(!array_buffer_transfer_map_.Find(array_buffer)); | 218 DCHECK(!array_buffer_transfer_map_.Find(array_buffer)); |
| 211 array_buffer_transfer_map_.Set(array_buffer, transfer_id); | 219 array_buffer_transfer_map_.Set(array_buffer, transfer_id); |
| 212 } | 220 } |
| 213 | 221 |
| 214 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 222 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { |
| 215 if (object->IsSmi()) { | 223 if (object->IsSmi()) { |
| 216 WriteSmi(Smi::cast(*object)); | 224 WriteSmi(Smi::cast(*object)); |
| 217 return Just(true); | 225 return Just(true); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 } | 353 } |
| 346 | 354 |
| 347 // If we are at the end of the stack, abort. This function may recurse. | 355 // If we are at the end of the stack, abort. This function may recurse. |
| 348 STACK_CHECK(isolate_, Nothing<bool>()); | 356 STACK_CHECK(isolate_, Nothing<bool>()); |
| 349 | 357 |
| 350 HandleScope scope(isolate_); | 358 HandleScope scope(isolate_); |
| 351 switch (instance_type) { | 359 switch (instance_type) { |
| 352 case JS_ARRAY_TYPE: | 360 case JS_ARRAY_TYPE: |
| 353 return WriteJSArray(Handle<JSArray>::cast(receiver)); | 361 return WriteJSArray(Handle<JSArray>::cast(receiver)); |
| 354 case JS_OBJECT_TYPE: | 362 case JS_OBJECT_TYPE: |
| 355 case JS_API_OBJECT_TYPE: | 363 case JS_API_OBJECT_TYPE: { |
| 356 return WriteJSObject(Handle<JSObject>::cast(receiver)); | 364 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver); |
| 365 return js_object->GetInternalFieldCount() ? WriteHostObject(js_object) |
| 366 : WriteJSObject(js_object); |
| 367 } |
| 357 case JS_DATE_TYPE: | 368 case JS_DATE_TYPE: |
| 358 WriteJSDate(JSDate::cast(*receiver)); | 369 WriteJSDate(JSDate::cast(*receiver)); |
| 359 return Just(true); | 370 return Just(true); |
| 360 case JS_VALUE_TYPE: | 371 case JS_VALUE_TYPE: |
| 361 return WriteJSValue(Handle<JSValue>::cast(receiver)); | 372 return WriteJSValue(Handle<JSValue>::cast(receiver)); |
| 362 case JS_REGEXP_TYPE: | 373 case JS_REGEXP_TYPE: |
| 363 WriteJSRegExp(JSRegExp::cast(*receiver)); | 374 WriteJSRegExp(JSRegExp::cast(*receiver)); |
| 364 return Just(true); | 375 return Just(true); |
| 365 case JS_MAP_TYPE: | 376 case JS_MAP_TYPE: |
| 366 return WriteJSMap(Handle<JSMap>::cast(receiver)); | 377 return WriteJSMap(Handle<JSMap>::cast(receiver)); |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 } else { | 704 } else { |
| 694 DCHECK(view->IsJSDataView()); | 705 DCHECK(view->IsJSDataView()); |
| 695 tag = ArrayBufferViewTag::kDataView; | 706 tag = ArrayBufferViewTag::kDataView; |
| 696 } | 707 } |
| 697 WriteVarint(static_cast<uint8_t>(tag)); | 708 WriteVarint(static_cast<uint8_t>(tag)); |
| 698 WriteVarint(NumberToUint32(view->byte_offset())); | 709 WriteVarint(NumberToUint32(view->byte_offset())); |
| 699 WriteVarint(NumberToUint32(view->byte_length())); | 710 WriteVarint(NumberToUint32(view->byte_length())); |
| 700 return Just(true); | 711 return Just(true); |
| 701 } | 712 } |
| 702 | 713 |
| 714 Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) { |
| 715 if (!delegate_) { |
| 716 isolate_->Throw(*isolate_->factory()->NewError( |
| 717 isolate_->error_function(), MessageTemplate::kDataCloneError, object)); |
| 718 return Nothing<bool>(); |
| 719 } |
| 720 Maybe<bool> result = delegate_->WriteHostObject(Utils::ToLocal(object)); |
| 721 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>()); |
| 722 DCHECK(!result.IsNothing()); |
| 723 return result; |
| 724 } |
| 725 |
| 703 Maybe<uint32_t> ValueSerializer::WriteJSObjectPropertiesSlow( | 726 Maybe<uint32_t> ValueSerializer::WriteJSObjectPropertiesSlow( |
| 704 Handle<JSObject> object, Handle<FixedArray> keys) { | 727 Handle<JSObject> object, Handle<FixedArray> keys) { |
| 705 uint32_t properties_written = 0; | 728 uint32_t properties_written = 0; |
| 706 int length = keys->length(); | 729 int length = keys->length(); |
| 707 for (int i = 0; i < length; i++) { | 730 for (int i = 0; i < length; i++) { |
| 708 Handle<Object> key(keys->get(i), isolate_); | 731 Handle<Object> key(keys->get(i), isolate_); |
| 709 | 732 |
| 710 bool success; | 733 bool success; |
| 711 LookupIterator it = LookupIterator::PropertyOrElement( | 734 LookupIterator it = LookupIterator::PropertyOrElement( |
| 712 isolate_, object, key, &success, LookupIterator::OWN); | 735 isolate_, object, key, &success, LookupIterator::OWN); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 740 MessageTemplate::FormatMessage(isolate_, template_index, arg0); | 763 MessageTemplate::FormatMessage(isolate_, template_index, arg0); |
| 741 if (delegate_) { | 764 if (delegate_) { |
| 742 delegate_->ThrowDataCloneError(Utils::ToLocal(message)); | 765 delegate_->ThrowDataCloneError(Utils::ToLocal(message)); |
| 743 } else { | 766 } else { |
| 744 isolate_->Throw( | 767 isolate_->Throw( |
| 745 *isolate_->factory()->NewError(isolate_->error_function(), message)); | 768 *isolate_->factory()->NewError(isolate_->error_function(), message)); |
| 746 } | 769 } |
| 747 } | 770 } |
| 748 | 771 |
| 749 ValueDeserializer::ValueDeserializer(Isolate* isolate, | 772 ValueDeserializer::ValueDeserializer(Isolate* isolate, |
| 750 Vector<const uint8_t> data) | 773 Vector<const uint8_t> data, |
| 774 v8::ValueDeserializer::Delegate* delegate) |
| 751 : isolate_(isolate), | 775 : isolate_(isolate), |
| 776 delegate_(delegate), |
| 752 position_(data.start()), | 777 position_(data.start()), |
| 753 end_(data.start() + data.length()), | 778 end_(data.start() + data.length()), |
| 754 id_map_(Handle<SeededNumberDictionary>::cast( | 779 id_map_(Handle<SeededNumberDictionary>::cast( |
| 755 isolate->global_handles()->Create( | 780 isolate->global_handles()->Create( |
| 756 *SeededNumberDictionary::New(isolate, 0)))) {} | 781 *SeededNumberDictionary::New(isolate, 0)))) {} |
| 757 | 782 |
| 758 ValueDeserializer::~ValueDeserializer() { | 783 ValueDeserializer::~ValueDeserializer() { |
| 759 GlobalHandles::Destroy(Handle<Object>::cast(id_map_).location()); | 784 GlobalHandles::Destroy(Handle<Object>::cast(id_map_).location()); |
| 760 | 785 |
| 761 Handle<Object> transfer_map_handle; | 786 Handle<Object> transfer_map_handle; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 853 return Just(value); | 878 return Just(value); |
| 854 } | 879 } |
| 855 | 880 |
| 856 Maybe<Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(int size) { | 881 Maybe<Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(int size) { |
| 857 if (size > end_ - position_) return Nothing<Vector<const uint8_t>>(); | 882 if (size > end_ - position_) return Nothing<Vector<const uint8_t>>(); |
| 858 const uint8_t* start = position_; | 883 const uint8_t* start = position_; |
| 859 position_ += size; | 884 position_ += size; |
| 860 return Just(Vector<const uint8_t>(start, size)); | 885 return Just(Vector<const uint8_t>(start, size)); |
| 861 } | 886 } |
| 862 | 887 |
| 888 bool ValueDeserializer::ReadUint32(uint32_t* value) { |
| 889 return ReadVarint<uint32_t>().To(value); |
| 890 } |
| 891 |
| 892 bool ValueDeserializer::ReadUint64(uint64_t* value) { |
| 893 return ReadVarint<uint64_t>().To(value); |
| 894 } |
| 895 |
| 896 bool ValueDeserializer::ReadRawBytes(size_t length, const void** data) { |
| 897 if (length > static_cast<size_t>(end_ - position_)) return false; |
| 898 *data = position_; |
| 899 position_ += length; |
| 900 return true; |
| 901 } |
| 902 |
| 863 void ValueDeserializer::TransferArrayBuffer( | 903 void ValueDeserializer::TransferArrayBuffer( |
| 864 uint32_t transfer_id, Handle<JSArrayBuffer> array_buffer) { | 904 uint32_t transfer_id, Handle<JSArrayBuffer> array_buffer) { |
| 865 if (array_buffer_transfer_map_.is_null()) { | 905 if (array_buffer_transfer_map_.is_null()) { |
| 866 array_buffer_transfer_map_ = | 906 array_buffer_transfer_map_ = |
| 867 Handle<SeededNumberDictionary>::cast(isolate_->global_handles()->Create( | 907 Handle<SeededNumberDictionary>::cast(isolate_->global_handles()->Create( |
| 868 *SeededNumberDictionary::New(isolate_, 0))); | 908 *SeededNumberDictionary::New(isolate_, 0))); |
| 869 } | 909 } |
| 870 Handle<SeededNumberDictionary> dictionary = | 910 Handle<SeededNumberDictionary> dictionary = |
| 871 array_buffer_transfer_map_.ToHandleChecked(); | 911 array_buffer_transfer_map_.ToHandleChecked(); |
| 872 const bool used_as_prototype = false; | 912 const bool used_as_prototype = false; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 964 return ReadJSArrayBuffer(); | 1004 return ReadJSArrayBuffer(); |
| 965 case SerializationTag::kArrayBufferTransfer: { | 1005 case SerializationTag::kArrayBufferTransfer: { |
| 966 const bool is_shared = false; | 1006 const bool is_shared = false; |
| 967 return ReadTransferredJSArrayBuffer(is_shared); | 1007 return ReadTransferredJSArrayBuffer(is_shared); |
| 968 } | 1008 } |
| 969 case SerializationTag::kSharedArrayBufferTransfer: { | 1009 case SerializationTag::kSharedArrayBufferTransfer: { |
| 970 const bool is_shared = true; | 1010 const bool is_shared = true; |
| 971 return ReadTransferredJSArrayBuffer(is_shared); | 1011 return ReadTransferredJSArrayBuffer(is_shared); |
| 972 } | 1012 } |
| 973 default: | 1013 default: |
| 974 return MaybeHandle<Object>(); | 1014 // TODO(jbroman): Introduce an explicit tag for host objects to avoid |
| 1015 // having to treat every unknown tag as a potential host object. |
| 1016 position_--; |
| 1017 return ReadHostObject(); |
| 975 } | 1018 } |
| 976 } | 1019 } |
| 977 | 1020 |
| 978 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { | 1021 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { |
| 979 uint32_t utf8_length; | 1022 uint32_t utf8_length; |
| 980 Vector<const uint8_t> utf8_bytes; | 1023 Vector<const uint8_t> utf8_bytes; |
| 981 if (!ReadVarint<uint32_t>().To(&utf8_length) || | 1024 if (!ReadVarint<uint32_t>().To(&utf8_length) || |
| 982 utf8_length > | 1025 utf8_length > |
| 983 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || | 1026 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || |
| 984 !ReadRawBytes(utf8_length).To(&utf8_bytes)) | 1027 !ReadRawBytes(utf8_length).To(&utf8_bytes)) |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1309 } | 1352 } |
| 1310 if (byte_offset % element_size != 0 || byte_length % element_size != 0) { | 1353 if (byte_offset % element_size != 0 || byte_length % element_size != 0) { |
| 1311 return MaybeHandle<JSArrayBufferView>(); | 1354 return MaybeHandle<JSArrayBufferView>(); |
| 1312 } | 1355 } |
| 1313 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray( | 1356 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray( |
| 1314 external_array_type, buffer, byte_offset, byte_length / element_size); | 1357 external_array_type, buffer, byte_offset, byte_length / element_size); |
| 1315 AddObjectWithID(id, typed_array); | 1358 AddObjectWithID(id, typed_array); |
| 1316 return typed_array; | 1359 return typed_array; |
| 1317 } | 1360 } |
| 1318 | 1361 |
| 1362 MaybeHandle<JSObject> ValueDeserializer::ReadHostObject() { |
| 1363 if (!delegate_) return MaybeHandle<JSObject>(); |
| 1364 STACK_CHECK(isolate_, MaybeHandle<JSObject>()); |
| 1365 uint32_t id = next_id_++; |
| 1366 v8::Local<v8::Object> object; |
| 1367 if (!delegate_->ReadHostObject().ToLocal(&object)) { |
| 1368 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject); |
| 1369 return MaybeHandle<JSObject>(); |
| 1370 } |
| 1371 Handle<JSObject> js_object = |
| 1372 Handle<JSObject>::cast(Utils::OpenHandle(*object)); |
| 1373 AddObjectWithID(id, js_object); |
| 1374 return js_object; |
| 1375 } |
| 1376 |
| 1319 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( | 1377 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( |
| 1320 Handle<JSObject> object, SerializationTag end_tag) { | 1378 Handle<JSObject> object, SerializationTag end_tag) { |
| 1321 for (uint32_t num_properties = 0;; num_properties++) { | 1379 for (uint32_t num_properties = 0;; num_properties++) { |
| 1322 SerializationTag tag; | 1380 SerializationTag tag; |
| 1323 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); | 1381 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); |
| 1324 if (tag == end_tag) { | 1382 if (tag == end_tag) { |
| 1325 ConsumeTag(end_tag); | 1383 ConsumeTag(end_tag); |
| 1326 return Just(num_properties); | 1384 return Just(num_properties); |
| 1327 } | 1385 } |
| 1328 | 1386 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1479 if (stack.size() != 1) { | 1537 if (stack.size() != 1) { |
| 1480 isolate_->Throw(*isolate_->factory()->NewError( | 1538 isolate_->Throw(*isolate_->factory()->NewError( |
| 1481 MessageTemplate::kDataCloneDeserializationError)); | 1539 MessageTemplate::kDataCloneDeserializationError)); |
| 1482 return MaybeHandle<Object>(); | 1540 return MaybeHandle<Object>(); |
| 1483 } | 1541 } |
| 1484 return scope.CloseAndEscape(stack[0]); | 1542 return scope.CloseAndEscape(stack[0]); |
| 1485 } | 1543 } |
| 1486 | 1544 |
| 1487 } // namespace internal | 1545 } // namespace internal |
| 1488 } // namespace v8 | 1546 } // namespace v8 |
| OLD | NEW |