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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 kBeginSparseJSArray = 'a', | 65 kBeginSparseJSArray = 'a', |
66 // End of a sparse JS array. numProperties:uint32_t length:uint32_t | 66 // End of a sparse JS array. numProperties:uint32_t length:uint32_t |
67 kEndSparseJSArray = '@', | 67 kEndSparseJSArray = '@', |
68 // Beginning of a dense JS array. length:uint32_t | 68 // Beginning of a dense JS array. length:uint32_t |
69 // |length| elements, followed by properties as key/value pairs | 69 // |length| elements, followed by properties as key/value pairs |
70 kBeginDenseJSArray = 'A', | 70 kBeginDenseJSArray = 'A', |
71 // End of a dense JS array. numProperties:uint32_t length:uint32_t | 71 // End of a dense JS array. numProperties:uint32_t length:uint32_t |
72 kEndDenseJSArray = '$', | 72 kEndDenseJSArray = '$', |
73 // Date. millisSinceEpoch:double | 73 // Date. millisSinceEpoch:double |
74 kDate = 'D', | 74 kDate = 'D', |
| 75 // Boolean object. No data. |
| 76 kTrueObject = 'y', |
| 77 kFalseObject = 'x', |
| 78 // Number object. value:double |
| 79 kNumberObject = 'n', |
| 80 // String object, UTF-8 encoding. byteLength:uint32_t, then raw data. |
| 81 kStringObject = 's', |
75 }; | 82 }; |
76 | 83 |
77 ValueSerializer::ValueSerializer(Isolate* isolate) | 84 ValueSerializer::ValueSerializer(Isolate* isolate) |
78 : isolate_(isolate), | 85 : isolate_(isolate), |
79 zone_(isolate->allocator()), | 86 zone_(isolate->allocator()), |
80 id_map_(isolate->heap(), &zone_) {} | 87 id_map_(isolate->heap(), &zone_) {} |
81 | 88 |
82 ValueSerializer::~ValueSerializer() {} | 89 ValueSerializer::~ValueSerializer() {} |
83 | 90 |
84 void ValueSerializer::WriteHeader() { | 91 void ValueSerializer::WriteHeader() { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 } | 141 } |
135 | 142 |
136 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) { | 143 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) { |
137 // Warning: this uses host endianness. | 144 // Warning: this uses host endianness. |
138 WriteVarint<uint32_t>(chars.length() * sizeof(uc16)); | 145 WriteVarint<uint32_t>(chars.length() * sizeof(uc16)); |
139 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(chars.begin()), | 146 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(chars.begin()), |
140 reinterpret_cast<const uint8_t*>(chars.end())); | 147 reinterpret_cast<const uint8_t*>(chars.end())); |
141 } | 148 } |
142 | 149 |
143 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { | 150 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { |
| 151 if (!bytes) return nullptr; |
144 auto old_size = buffer_.size(); | 152 auto old_size = buffer_.size(); |
145 buffer_.resize(buffer_.size() + bytes); | 153 buffer_.resize(buffer_.size() + bytes); |
146 return &buffer_[old_size]; | 154 return &buffer_[old_size]; |
147 } | 155 } |
148 | 156 |
149 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 157 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { |
150 if (object->IsSmi()) { | 158 if (object->IsSmi()) { |
151 WriteSmi(Smi::cast(*object)); | 159 WriteSmi(Smi::cast(*object)); |
152 return Just(true); | 160 return Just(true); |
153 } | 161 } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 HandleScope scope(isolate_); | 274 HandleScope scope(isolate_); |
267 switch (instance_type) { | 275 switch (instance_type) { |
268 case JS_ARRAY_TYPE: | 276 case JS_ARRAY_TYPE: |
269 return WriteJSArray(Handle<JSArray>::cast(receiver)); | 277 return WriteJSArray(Handle<JSArray>::cast(receiver)); |
270 case JS_OBJECT_TYPE: | 278 case JS_OBJECT_TYPE: |
271 case JS_API_OBJECT_TYPE: | 279 case JS_API_OBJECT_TYPE: |
272 return WriteJSObject(Handle<JSObject>::cast(receiver)); | 280 return WriteJSObject(Handle<JSObject>::cast(receiver)); |
273 case JS_DATE_TYPE: | 281 case JS_DATE_TYPE: |
274 WriteJSDate(JSDate::cast(*receiver)); | 282 WriteJSDate(JSDate::cast(*receiver)); |
275 return Just(true); | 283 return Just(true); |
| 284 case JS_VALUE_TYPE: |
| 285 return WriteJSValue(Handle<JSValue>::cast(receiver)); |
276 default: | 286 default: |
277 UNIMPLEMENTED(); | 287 UNIMPLEMENTED(); |
278 break; | 288 break; |
279 } | 289 } |
280 return Nothing<bool>(); | 290 return Nothing<bool>(); |
281 } | 291 } |
282 | 292 |
283 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) { | 293 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) { |
284 WriteTag(SerializationTag::kBeginJSObject); | 294 WriteTag(SerializationTag::kBeginJSObject); |
285 Handle<FixedArray> keys; | 295 Handle<FixedArray> keys; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 WriteVarint<uint32_t>(length); | 366 WriteVarint<uint32_t>(length); |
357 } | 367 } |
358 return Just(true); | 368 return Just(true); |
359 } | 369 } |
360 | 370 |
361 void ValueSerializer::WriteJSDate(JSDate* date) { | 371 void ValueSerializer::WriteJSDate(JSDate* date) { |
362 WriteTag(SerializationTag::kDate); | 372 WriteTag(SerializationTag::kDate); |
363 WriteDouble(date->value()->Number()); | 373 WriteDouble(date->value()->Number()); |
364 } | 374 } |
365 | 375 |
| 376 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) { |
| 377 Object* inner_value = value->value(); |
| 378 if (inner_value->IsTrue(isolate_)) { |
| 379 WriteTag(SerializationTag::kTrueObject); |
| 380 } else if (inner_value->IsFalse(isolate_)) { |
| 381 WriteTag(SerializationTag::kFalseObject); |
| 382 } else if (inner_value->IsNumber()) { |
| 383 WriteTag(SerializationTag::kNumberObject); |
| 384 WriteDouble(inner_value->Number()); |
| 385 } else if (inner_value->IsString()) { |
| 386 // TODO(jbroman): Replace UTF-8 encoding with the same options available for |
| 387 // ordinary strings. |
| 388 WriteTag(SerializationTag::kStringObject); |
| 389 v8::Local<v8::String> api_string = |
| 390 Utils::ToLocal(handle(String::cast(inner_value), isolate_)); |
| 391 uint32_t utf8_length = api_string->Utf8Length(); |
| 392 WriteVarint(utf8_length); |
| 393 api_string->WriteUtf8(reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), |
| 394 utf8_length, nullptr, |
| 395 v8::String::NO_NULL_TERMINATION); |
| 396 } else { |
| 397 DCHECK(inner_value->IsSymbol()); |
| 398 return Nothing<bool>(); |
| 399 } |
| 400 return Just(true); |
| 401 } |
| 402 |
366 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( | 403 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( |
367 Handle<JSObject> object, Handle<FixedArray> keys) { | 404 Handle<JSObject> object, Handle<FixedArray> keys) { |
368 uint32_t properties_written = 0; | 405 uint32_t properties_written = 0; |
369 int length = keys->length(); | 406 int length = keys->length(); |
370 for (int i = 0; i < length; i++) { | 407 for (int i = 0; i < length; i++) { |
371 Handle<Object> key(keys->get(i), isolate_); | 408 Handle<Object> key(keys->get(i), isolate_); |
372 | 409 |
373 bool success; | 410 bool success; |
374 LookupIterator it = LookupIterator::PropertyOrElement( | 411 LookupIterator it = LookupIterator::PropertyOrElement( |
375 isolate_, object, key, &success, LookupIterator::OWN); | 412 isolate_, object, key, &success, LookupIterator::OWN); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 return GetObjectWithID(id); | 575 return GetObjectWithID(id); |
539 } | 576 } |
540 case SerializationTag::kBeginJSObject: | 577 case SerializationTag::kBeginJSObject: |
541 return ReadJSObject(); | 578 return ReadJSObject(); |
542 case SerializationTag::kBeginSparseJSArray: | 579 case SerializationTag::kBeginSparseJSArray: |
543 return ReadSparseJSArray(); | 580 return ReadSparseJSArray(); |
544 case SerializationTag::kBeginDenseJSArray: | 581 case SerializationTag::kBeginDenseJSArray: |
545 return ReadDenseJSArray(); | 582 return ReadDenseJSArray(); |
546 case SerializationTag::kDate: | 583 case SerializationTag::kDate: |
547 return ReadJSDate(); | 584 return ReadJSDate(); |
| 585 case SerializationTag::kTrueObject: |
| 586 case SerializationTag::kFalseObject: |
| 587 case SerializationTag::kNumberObject: |
| 588 case SerializationTag::kStringObject: |
| 589 return ReadJSValue(tag); |
548 default: | 590 default: |
549 return MaybeHandle<Object>(); | 591 return MaybeHandle<Object>(); |
550 } | 592 } |
551 } | 593 } |
552 | 594 |
553 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { | 595 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { |
554 uint32_t utf8_length; | 596 uint32_t utf8_length; |
555 Vector<const uint8_t> utf8_bytes; | 597 Vector<const uint8_t> utf8_bytes; |
556 if (!ReadVarint<uint32_t>().To(&utf8_length) || | 598 if (!ReadVarint<uint32_t>().To(&utf8_length) || |
557 utf8_length > | 599 utf8_length > |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 uint32_t id = next_id_++; | 721 uint32_t id = next_id_++; |
680 Handle<JSDate> date; | 722 Handle<JSDate> date; |
681 if (!JSDate::New(isolate_->date_function(), isolate_->date_function(), value) | 723 if (!JSDate::New(isolate_->date_function(), isolate_->date_function(), value) |
682 .ToHandle(&date)) { | 724 .ToHandle(&date)) { |
683 return MaybeHandle<JSDate>(); | 725 return MaybeHandle<JSDate>(); |
684 } | 726 } |
685 AddObjectWithID(id, date); | 727 AddObjectWithID(id, date); |
686 return date; | 728 return date; |
687 } | 729 } |
688 | 730 |
| 731 MaybeHandle<JSValue> ValueDeserializer::ReadJSValue(SerializationTag tag) { |
| 732 uint32_t id = next_id_++; |
| 733 Handle<JSValue> value; |
| 734 switch (tag) { |
| 735 case SerializationTag::kTrueObject: |
| 736 value = Handle<JSValue>::cast( |
| 737 isolate_->factory()->NewJSObject(isolate_->boolean_function())); |
| 738 value->set_value(isolate_->heap()->true_value()); |
| 739 break; |
| 740 case SerializationTag::kFalseObject: |
| 741 value = Handle<JSValue>::cast( |
| 742 isolate_->factory()->NewJSObject(isolate_->boolean_function())); |
| 743 value->set_value(isolate_->heap()->false_value()); |
| 744 break; |
| 745 case SerializationTag::kNumberObject: { |
| 746 double number; |
| 747 if (!ReadDouble().To(&number)) return MaybeHandle<JSValue>(); |
| 748 value = Handle<JSValue>::cast( |
| 749 isolate_->factory()->NewJSObject(isolate_->number_function())); |
| 750 Handle<Object> number_object = isolate_->factory()->NewNumber(number); |
| 751 value->set_value(*number_object); |
| 752 break; |
| 753 } |
| 754 case SerializationTag::kStringObject: { |
| 755 Handle<String> string; |
| 756 if (!ReadUtf8String().ToHandle(&string)) return MaybeHandle<JSValue>(); |
| 757 value = Handle<JSValue>::cast( |
| 758 isolate_->factory()->NewJSObject(isolate_->string_function())); |
| 759 value->set_value(*string); |
| 760 break; |
| 761 } |
| 762 default: |
| 763 UNREACHABLE(); |
| 764 return MaybeHandle<JSValue>(); |
| 765 } |
| 766 AddObjectWithID(id, value); |
| 767 return value; |
| 768 } |
| 769 |
689 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( | 770 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( |
690 Handle<JSObject> object, SerializationTag end_tag) { | 771 Handle<JSObject> object, SerializationTag end_tag) { |
691 for (uint32_t num_properties = 0;; num_properties++) { | 772 for (uint32_t num_properties = 0;; num_properties++) { |
692 SerializationTag tag; | 773 SerializationTag tag; |
693 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); | 774 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); |
694 if (tag == end_tag) { | 775 if (tag == end_tag) { |
695 ConsumeTag(end_tag); | 776 ConsumeTag(end_tag); |
696 return Just(num_properties); | 777 return Just(num_properties); |
697 } | 778 } |
698 | 779 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 } | 924 } |
844 #endif | 925 #endif |
845 position_ = end_; | 926 position_ = end_; |
846 | 927 |
847 if (stack.size() != 1) return MaybeHandle<Object>(); | 928 if (stack.size() != 1) return MaybeHandle<Object>(); |
848 return scope.CloseAndEscape(stack[0]); | 929 return scope.CloseAndEscape(stack[0]); |
849 } | 930 } |
850 | 931 |
851 } // namespace internal | 932 } // namespace internal |
852 } // namespace v8 | 933 } // namespace v8 |
OLD | NEW |