Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: src/value-serializer.cc

Issue 2327653002: Support delegating serialization of host objects. (Closed)
Patch Set: Isolate* argument to delegate Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698