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 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); |
| 721 Maybe<bool> result = |
| 722 delegate_->WriteHostObject(v8_isolate, Utils::ToLocal(object)); |
| 723 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>()); |
| 724 DCHECK(!result.IsNothing()); |
| 725 return result; |
| 726 } |
| 727 |
703 Maybe<uint32_t> ValueSerializer::WriteJSObjectPropertiesSlow( | 728 Maybe<uint32_t> ValueSerializer::WriteJSObjectPropertiesSlow( |
704 Handle<JSObject> object, Handle<FixedArray> keys) { | 729 Handle<JSObject> object, Handle<FixedArray> keys) { |
705 uint32_t properties_written = 0; | 730 uint32_t properties_written = 0; |
706 int length = keys->length(); | 731 int length = keys->length(); |
707 for (int i = 0; i < length; i++) { | 732 for (int i = 0; i < length; i++) { |
708 Handle<Object> key(keys->get(i), isolate_); | 733 Handle<Object> key(keys->get(i), isolate_); |
709 | 734 |
710 bool success; | 735 bool success; |
711 LookupIterator it = LookupIterator::PropertyOrElement( | 736 LookupIterator it = LookupIterator::PropertyOrElement( |
712 isolate_, object, key, &success, LookupIterator::OWN); | 737 isolate_, object, key, &success, LookupIterator::OWN); |
(...skipping 27 matching lines...) Expand all Loading... |
740 MessageTemplate::FormatMessage(isolate_, template_index, arg0); | 765 MessageTemplate::FormatMessage(isolate_, template_index, arg0); |
741 if (delegate_) { | 766 if (delegate_) { |
742 delegate_->ThrowDataCloneError(Utils::ToLocal(message)); | 767 delegate_->ThrowDataCloneError(Utils::ToLocal(message)); |
743 } else { | 768 } else { |
744 isolate_->Throw( | 769 isolate_->Throw( |
745 *isolate_->factory()->NewError(isolate_->error_function(), message)); | 770 *isolate_->factory()->NewError(isolate_->error_function(), message)); |
746 } | 771 } |
747 } | 772 } |
748 | 773 |
749 ValueDeserializer::ValueDeserializer(Isolate* isolate, | 774 ValueDeserializer::ValueDeserializer(Isolate* isolate, |
750 Vector<const uint8_t> data) | 775 Vector<const uint8_t> data, |
| 776 v8::ValueDeserializer::Delegate* delegate) |
751 : isolate_(isolate), | 777 : isolate_(isolate), |
| 778 delegate_(delegate), |
752 position_(data.start()), | 779 position_(data.start()), |
753 end_(data.start() + data.length()), | 780 end_(data.start() + data.length()), |
754 id_map_(Handle<SeededNumberDictionary>::cast( | 781 id_map_(Handle<SeededNumberDictionary>::cast( |
755 isolate->global_handles()->Create( | 782 isolate->global_handles()->Create( |
756 *SeededNumberDictionary::New(isolate, 0)))) {} | 783 *SeededNumberDictionary::New(isolate, 0)))) {} |
757 | 784 |
758 ValueDeserializer::~ValueDeserializer() { | 785 ValueDeserializer::~ValueDeserializer() { |
759 GlobalHandles::Destroy(Handle<Object>::cast(id_map_).location()); | 786 GlobalHandles::Destroy(Handle<Object>::cast(id_map_).location()); |
760 | 787 |
761 Handle<Object> transfer_map_handle; | 788 Handle<Object> transfer_map_handle; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 return Just(value); | 880 return Just(value); |
854 } | 881 } |
855 | 882 |
856 Maybe<Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(int size) { | 883 Maybe<Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(int size) { |
857 if (size > end_ - position_) return Nothing<Vector<const uint8_t>>(); | 884 if (size > end_ - position_) return Nothing<Vector<const uint8_t>>(); |
858 const uint8_t* start = position_; | 885 const uint8_t* start = position_; |
859 position_ += size; | 886 position_ += size; |
860 return Just(Vector<const uint8_t>(start, size)); | 887 return Just(Vector<const uint8_t>(start, size)); |
861 } | 888 } |
862 | 889 |
| 890 bool ValueDeserializer::ReadUint32(uint32_t* value) { |
| 891 return ReadVarint<uint32_t>().To(value); |
| 892 } |
| 893 |
| 894 bool ValueDeserializer::ReadUint64(uint64_t* value) { |
| 895 return ReadVarint<uint64_t>().To(value); |
| 896 } |
| 897 |
| 898 bool ValueDeserializer::ReadRawBytes(size_t length, const void** data) { |
| 899 if (length > static_cast<size_t>(end_ - position_)) return false; |
| 900 *data = position_; |
| 901 position_ += length; |
| 902 return true; |
| 903 } |
| 904 |
863 void ValueDeserializer::TransferArrayBuffer( | 905 void ValueDeserializer::TransferArrayBuffer( |
864 uint32_t transfer_id, Handle<JSArrayBuffer> array_buffer) { | 906 uint32_t transfer_id, Handle<JSArrayBuffer> array_buffer) { |
865 if (array_buffer_transfer_map_.is_null()) { | 907 if (array_buffer_transfer_map_.is_null()) { |
866 array_buffer_transfer_map_ = | 908 array_buffer_transfer_map_ = |
867 Handle<SeededNumberDictionary>::cast(isolate_->global_handles()->Create( | 909 Handle<SeededNumberDictionary>::cast(isolate_->global_handles()->Create( |
868 *SeededNumberDictionary::New(isolate_, 0))); | 910 *SeededNumberDictionary::New(isolate_, 0))); |
869 } | 911 } |
870 Handle<SeededNumberDictionary> dictionary = | 912 Handle<SeededNumberDictionary> dictionary = |
871 array_buffer_transfer_map_.ToHandleChecked(); | 913 array_buffer_transfer_map_.ToHandleChecked(); |
872 const bool used_as_prototype = false; | 914 const bool used_as_prototype = false; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 return ReadJSArrayBuffer(); | 1006 return ReadJSArrayBuffer(); |
965 case SerializationTag::kArrayBufferTransfer: { | 1007 case SerializationTag::kArrayBufferTransfer: { |
966 const bool is_shared = false; | 1008 const bool is_shared = false; |
967 return ReadTransferredJSArrayBuffer(is_shared); | 1009 return ReadTransferredJSArrayBuffer(is_shared); |
968 } | 1010 } |
969 case SerializationTag::kSharedArrayBufferTransfer: { | 1011 case SerializationTag::kSharedArrayBufferTransfer: { |
970 const bool is_shared = true; | 1012 const bool is_shared = true; |
971 return ReadTransferredJSArrayBuffer(is_shared); | 1013 return ReadTransferredJSArrayBuffer(is_shared); |
972 } | 1014 } |
973 default: | 1015 default: |
974 return MaybeHandle<Object>(); | 1016 // TODO(jbroman): Introduce an explicit tag for host objects to avoid |
| 1017 // having to treat every unknown tag as a potential host object. |
| 1018 position_--; |
| 1019 return ReadHostObject(); |
975 } | 1020 } |
976 } | 1021 } |
977 | 1022 |
978 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { | 1023 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { |
979 uint32_t utf8_length; | 1024 uint32_t utf8_length; |
980 Vector<const uint8_t> utf8_bytes; | 1025 Vector<const uint8_t> utf8_bytes; |
981 if (!ReadVarint<uint32_t>().To(&utf8_length) || | 1026 if (!ReadVarint<uint32_t>().To(&utf8_length) || |
982 utf8_length > | 1027 utf8_length > |
983 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || | 1028 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || |
984 !ReadRawBytes(utf8_length).To(&utf8_bytes)) | 1029 !ReadRawBytes(utf8_length).To(&utf8_bytes)) |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1309 } | 1354 } |
1310 if (byte_offset % element_size != 0 || byte_length % element_size != 0) { | 1355 if (byte_offset % element_size != 0 || byte_length % element_size != 0) { |
1311 return MaybeHandle<JSArrayBufferView>(); | 1356 return MaybeHandle<JSArrayBufferView>(); |
1312 } | 1357 } |
1313 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray( | 1358 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray( |
1314 external_array_type, buffer, byte_offset, byte_length / element_size); | 1359 external_array_type, buffer, byte_offset, byte_length / element_size); |
1315 AddObjectWithID(id, typed_array); | 1360 AddObjectWithID(id, typed_array); |
1316 return typed_array; | 1361 return typed_array; |
1317 } | 1362 } |
1318 | 1363 |
| 1364 MaybeHandle<JSObject> ValueDeserializer::ReadHostObject() { |
| 1365 if (!delegate_) return MaybeHandle<JSObject>(); |
| 1366 STACK_CHECK(isolate_, MaybeHandle<JSObject>()); |
| 1367 uint32_t id = next_id_++; |
| 1368 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); |
| 1369 v8::Local<v8::Object> object; |
| 1370 if (!delegate_->ReadHostObject(v8_isolate).ToLocal(&object)) { |
| 1371 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate_, JSObject); |
| 1372 return MaybeHandle<JSObject>(); |
| 1373 } |
| 1374 Handle<JSObject> js_object = |
| 1375 Handle<JSObject>::cast(Utils::OpenHandle(*object)); |
| 1376 AddObjectWithID(id, js_object); |
| 1377 return js_object; |
| 1378 } |
| 1379 |
1319 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( | 1380 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( |
1320 Handle<JSObject> object, SerializationTag end_tag) { | 1381 Handle<JSObject> object, SerializationTag end_tag) { |
1321 for (uint32_t num_properties = 0;; num_properties++) { | 1382 for (uint32_t num_properties = 0;; num_properties++) { |
1322 SerializationTag tag; | 1383 SerializationTag tag; |
1323 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); | 1384 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); |
1324 if (tag == end_tag) { | 1385 if (tag == end_tag) { |
1325 ConsumeTag(end_tag); | 1386 ConsumeTag(end_tag); |
1326 return Just(num_properties); | 1387 return Just(num_properties); |
1327 } | 1388 } |
1328 | 1389 |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1479 if (stack.size() != 1) { | 1540 if (stack.size() != 1) { |
1480 isolate_->Throw(*isolate_->factory()->NewError( | 1541 isolate_->Throw(*isolate_->factory()->NewError( |
1481 MessageTemplate::kDataCloneDeserializationError)); | 1542 MessageTemplate::kDataCloneDeserializationError)); |
1482 return MaybeHandle<Object>(); | 1543 return MaybeHandle<Object>(); |
1483 } | 1544 } |
1484 return scope.CloseAndEscape(stack[0]); | 1545 return scope.CloseAndEscape(stack[0]); |
1485 } | 1546 } |
1486 | 1547 |
1487 } // namespace internal | 1548 } // namespace internal |
1488 } // namespace v8 | 1549 } // namespace v8 |
OLD | NEW |