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/factory.h" | 10 #include "src/factory.h" |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 // flags:uint32_t. | 83 // flags:uint32_t. |
84 kRegExp = 'R', | 84 kRegExp = 'R', |
85 // Beginning of a JS map. | 85 // Beginning of a JS map. |
86 kBeginJSMap = ';', | 86 kBeginJSMap = ';', |
87 // End of a JS map. length:uint32_t. | 87 // End of a JS map. length:uint32_t. |
88 kEndJSMap = ':', | 88 kEndJSMap = ':', |
89 // Beginning of a JS set. | 89 // Beginning of a JS set. |
90 kBeginJSSet = '\'', | 90 kBeginJSSet = '\'', |
91 // End of a JS set. length:uint32_t. | 91 // End of a JS set. length:uint32_t. |
92 kEndJSSet = ',', | 92 kEndJSSet = ',', |
| 93 // Array buffer. byteLength:uint32_t, then raw data. |
| 94 kArrayBuffer = 'B', |
93 }; | 95 }; |
94 | 96 |
95 ValueSerializer::ValueSerializer(Isolate* isolate) | 97 ValueSerializer::ValueSerializer(Isolate* isolate) |
96 : isolate_(isolate), | 98 : isolate_(isolate), |
97 zone_(isolate->allocator()), | 99 zone_(isolate->allocator()), |
98 id_map_(isolate->heap(), &zone_) {} | 100 id_map_(isolate->heap(), &zone_) {} |
99 | 101 |
100 ValueSerializer::~ValueSerializer() {} | 102 ValueSerializer::~ValueSerializer() {} |
101 | 103 |
102 void ValueSerializer::WriteHeader() { | 104 void ValueSerializer::WriteHeader() { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 buffer_.insert(buffer_.end(), chars.begin(), chars.end()); | 153 buffer_.insert(buffer_.end(), chars.begin(), chars.end()); |
152 } | 154 } |
153 | 155 |
154 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) { | 156 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) { |
155 // Warning: this uses host endianness. | 157 // Warning: this uses host endianness. |
156 WriteVarint<uint32_t>(chars.length() * sizeof(uc16)); | 158 WriteVarint<uint32_t>(chars.length() * sizeof(uc16)); |
157 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(chars.begin()), | 159 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(chars.begin()), |
158 reinterpret_cast<const uint8_t*>(chars.end())); | 160 reinterpret_cast<const uint8_t*>(chars.end())); |
159 } | 161 } |
160 | 162 |
| 163 void ValueSerializer::WriteRawBytes(const void* source, size_t length) { |
| 164 const uint8_t* begin = reinterpret_cast<const uint8_t*>(source); |
| 165 buffer_.insert(buffer_.end(), begin, begin + length); |
| 166 } |
| 167 |
161 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { | 168 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { |
162 if (!bytes) return nullptr; | 169 if (!bytes) return nullptr; |
163 auto old_size = buffer_.size(); | 170 auto old_size = buffer_.size(); |
164 buffer_.resize(buffer_.size() + bytes); | 171 buffer_.resize(buffer_.size() + bytes); |
165 return &buffer_[old_size]; | 172 return &buffer_[old_size]; |
166 } | 173 } |
167 | 174 |
168 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 175 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { |
169 if (object->IsSmi()) { | 176 if (object->IsSmi()) { |
170 WriteSmi(Smi::cast(*object)); | 177 WriteSmi(Smi::cast(*object)); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 return Just(true); | 301 return Just(true); |
295 case JS_VALUE_TYPE: | 302 case JS_VALUE_TYPE: |
296 return WriteJSValue(Handle<JSValue>::cast(receiver)); | 303 return WriteJSValue(Handle<JSValue>::cast(receiver)); |
297 case JS_REGEXP_TYPE: | 304 case JS_REGEXP_TYPE: |
298 WriteJSRegExp(JSRegExp::cast(*receiver)); | 305 WriteJSRegExp(JSRegExp::cast(*receiver)); |
299 return Just(true); | 306 return Just(true); |
300 case JS_MAP_TYPE: | 307 case JS_MAP_TYPE: |
301 return WriteJSMap(Handle<JSMap>::cast(receiver)); | 308 return WriteJSMap(Handle<JSMap>::cast(receiver)); |
302 case JS_SET_TYPE: | 309 case JS_SET_TYPE: |
303 return WriteJSSet(Handle<JSSet>::cast(receiver)); | 310 return WriteJSSet(Handle<JSSet>::cast(receiver)); |
| 311 case JS_ARRAY_BUFFER_TYPE: |
| 312 return WriteJSArrayBuffer(JSArrayBuffer::cast(*receiver)); |
304 default: | 313 default: |
305 UNIMPLEMENTED(); | 314 UNIMPLEMENTED(); |
306 break; | 315 break; |
307 } | 316 } |
308 return Nothing<bool>(); | 317 return Nothing<bool>(); |
309 } | 318 } |
310 | 319 |
311 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) { | 320 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) { |
312 WriteTag(SerializationTag::kBeginJSObject); | 321 WriteTag(SerializationTag::kBeginJSObject); |
313 Handle<FixedArray> keys; | 322 Handle<FixedArray> keys; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 for (int i = 0; i < length; i++) { | 492 for (int i = 0; i < length; i++) { |
484 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { | 493 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { |
485 return Nothing<bool>(); | 494 return Nothing<bool>(); |
486 } | 495 } |
487 } | 496 } |
488 WriteTag(SerializationTag::kEndJSSet); | 497 WriteTag(SerializationTag::kEndJSSet); |
489 WriteVarint<uint32_t>(length); | 498 WriteVarint<uint32_t>(length); |
490 return Just(true); | 499 return Just(true); |
491 } | 500 } |
492 | 501 |
| 502 Maybe<bool> ValueSerializer::WriteJSArrayBuffer(JSArrayBuffer* array_buffer) { |
| 503 if (array_buffer->was_neutered()) return Nothing<bool>(); |
| 504 double byte_length = array_buffer->byte_length()->Number(); |
| 505 if (byte_length > std::numeric_limits<uint32_t>::max()) { |
| 506 return Nothing<bool>(); |
| 507 } |
| 508 WriteTag(SerializationTag::kArrayBuffer); |
| 509 WriteVarint<uint32_t>(byte_length); |
| 510 WriteRawBytes(array_buffer->backing_store(), byte_length); |
| 511 return Just(true); |
| 512 } |
| 513 |
493 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( | 514 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( |
494 Handle<JSObject> object, Handle<FixedArray> keys) { | 515 Handle<JSObject> object, Handle<FixedArray> keys) { |
495 uint32_t properties_written = 0; | 516 uint32_t properties_written = 0; |
496 int length = keys->length(); | 517 int length = keys->length(); |
497 for (int i = 0; i < length; i++) { | 518 for (int i = 0; i < length; i++) { |
498 Handle<Object> key(keys->get(i), isolate_); | 519 Handle<Object> key(keys->get(i), isolate_); |
499 | 520 |
500 bool success; | 521 bool success; |
501 LookupIterator it = LookupIterator::PropertyOrElement( | 522 LookupIterator it = LookupIterator::PropertyOrElement( |
502 isolate_, object, key, &success, LookupIterator::OWN); | 523 isolate_, object, key, &success, LookupIterator::OWN); |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 case SerializationTag::kFalseObject: | 697 case SerializationTag::kFalseObject: |
677 case SerializationTag::kNumberObject: | 698 case SerializationTag::kNumberObject: |
678 case SerializationTag::kStringObject: | 699 case SerializationTag::kStringObject: |
679 return ReadJSValue(tag); | 700 return ReadJSValue(tag); |
680 case SerializationTag::kRegExp: | 701 case SerializationTag::kRegExp: |
681 return ReadJSRegExp(); | 702 return ReadJSRegExp(); |
682 case SerializationTag::kBeginJSMap: | 703 case SerializationTag::kBeginJSMap: |
683 return ReadJSMap(); | 704 return ReadJSMap(); |
684 case SerializationTag::kBeginJSSet: | 705 case SerializationTag::kBeginJSSet: |
685 return ReadJSSet(); | 706 return ReadJSSet(); |
| 707 case SerializationTag::kArrayBuffer: |
| 708 return ReadJSArrayBuffer(); |
686 default: | 709 default: |
687 return MaybeHandle<Object>(); | 710 return MaybeHandle<Object>(); |
688 } | 711 } |
689 } | 712 } |
690 | 713 |
691 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { | 714 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { |
692 uint32_t utf8_length; | 715 uint32_t utf8_length; |
693 Vector<const uint8_t> utf8_bytes; | 716 Vector<const uint8_t> utf8_bytes; |
694 if (!ReadVarint<uint32_t>().To(&utf8_length) || | 717 if (!ReadVarint<uint32_t>().To(&utf8_length) || |
695 utf8_length > | 718 utf8_length > |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
944 | 967 |
945 uint32_t expected_length; | 968 uint32_t expected_length; |
946 if (!ReadVarint<uint32_t>().To(&expected_length) || | 969 if (!ReadVarint<uint32_t>().To(&expected_length) || |
947 length != expected_length) { | 970 length != expected_length) { |
948 return MaybeHandle<JSSet>(); | 971 return MaybeHandle<JSSet>(); |
949 } | 972 } |
950 DCHECK(HasObjectWithID(id)); | 973 DCHECK(HasObjectWithID(id)); |
951 return scope.CloseAndEscape(set); | 974 return scope.CloseAndEscape(set); |
952 } | 975 } |
953 | 976 |
| 977 MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadJSArrayBuffer() { |
| 978 uint32_t id = next_id_++; |
| 979 uint32_t byte_length; |
| 980 Vector<const uint8_t> bytes; |
| 981 if (!ReadVarint<uint32_t>().To(&byte_length) || |
| 982 byte_length > static_cast<size_t>(end_ - position_)) { |
| 983 return MaybeHandle<JSArrayBuffer>(); |
| 984 } |
| 985 const bool should_initialize = false; |
| 986 Handle<JSArrayBuffer> array_buffer = isolate_->factory()->NewJSArrayBuffer(); |
| 987 JSArrayBuffer::SetupAllocatingData(array_buffer, isolate_, byte_length, |
| 988 should_initialize); |
| 989 memcpy(array_buffer->backing_store(), position_, byte_length); |
| 990 position_ += byte_length; |
| 991 AddObjectWithID(id, array_buffer); |
| 992 return array_buffer; |
| 993 } |
| 994 |
954 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( | 995 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( |
955 Handle<JSObject> object, SerializationTag end_tag) { | 996 Handle<JSObject> object, SerializationTag end_tag) { |
956 for (uint32_t num_properties = 0;; num_properties++) { | 997 for (uint32_t num_properties = 0;; num_properties++) { |
957 SerializationTag tag; | 998 SerializationTag tag; |
958 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); | 999 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); |
959 if (tag == end_tag) { | 1000 if (tag == end_tag) { |
960 ConsumeTag(end_tag); | 1001 ConsumeTag(end_tag); |
961 return Just(num_properties); | 1002 return Just(num_properties); |
962 } | 1003 } |
963 | 1004 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1108 } | 1149 } |
1109 #endif | 1150 #endif |
1110 position_ = end_; | 1151 position_ = end_; |
1111 | 1152 |
1112 if (stack.size() != 1) return MaybeHandle<Object>(); | 1153 if (stack.size() != 1) return MaybeHandle<Object>(); |
1113 return scope.CloseAndEscape(stack[0]); | 1154 return scope.CloseAndEscape(stack[0]); |
1114 } | 1155 } |
1115 | 1156 |
1116 } // namespace internal | 1157 } // namespace internal |
1117 } // namespace v8 | 1158 } // namespace v8 |
OLD | NEW |