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; | |
jbroman
2016/08/19 19:11:16
This sometimes triggered the debug std::vector che
| |
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 (value->HasSpecificClassOf(isolate_->heap()->Boolean_string())) { | |
379 if (inner_value->IsTrue(isolate_)) { | |
380 WriteTag(SerializationTag::kTrueObject); | |
381 } else { | |
382 DCHECK(inner_value->IsFalse(isolate_)); | |
383 WriteTag(SerializationTag::kFalseObject); | |
384 } | |
385 } else if (value->HasSpecificClassOf(isolate_->heap()->Number_string())) { | |
386 DCHECK(inner_value->IsNumber()); | |
387 WriteTag(SerializationTag::kNumberObject); | |
388 WriteDouble(inner_value->Number()); | |
389 } else if (value->HasSpecificClassOf(isolate_->heap()->String_string())) { | |
390 DCHECK(inner_value->IsString()); | |
391 // TODO(jbroman): Replace UTF-8 encoding with the same options available for | |
392 // ordinary strings. | |
393 WriteTag(SerializationTag::kStringObject); | |
394 v8::Local<v8::String> api_string = | |
395 Utils::ToLocal(handle(String::cast(inner_value), isolate_)); | |
396 uint32_t utf8_length = api_string->Utf8Length(); | |
397 WriteVarint(utf8_length); | |
398 api_string->WriteUtf8(reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), | |
399 utf8_length, nullptr, | |
400 v8::String::NO_NULL_TERMINATION); | |
401 } else { | |
402 return Nothing<bool>(); | |
403 } | |
404 return Just(true); | |
405 } | |
406 | |
366 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( | 407 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( |
367 Handle<JSObject> object, Handle<FixedArray> keys) { | 408 Handle<JSObject> object, Handle<FixedArray> keys) { |
368 uint32_t properties_written = 0; | 409 uint32_t properties_written = 0; |
369 int length = keys->length(); | 410 int length = keys->length(); |
370 for (int i = 0; i < length; i++) { | 411 for (int i = 0; i < length; i++) { |
371 Handle<Object> key(keys->get(i), isolate_); | 412 Handle<Object> key(keys->get(i), isolate_); |
372 | 413 |
373 bool success; | 414 bool success; |
374 LookupIterator it = LookupIterator::PropertyOrElement( | 415 LookupIterator it = LookupIterator::PropertyOrElement( |
375 isolate_, object, key, &success, LookupIterator::OWN); | 416 isolate_, object, key, &success, LookupIterator::OWN); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
538 return GetObjectWithID(id); | 579 return GetObjectWithID(id); |
539 } | 580 } |
540 case SerializationTag::kBeginJSObject: | 581 case SerializationTag::kBeginJSObject: |
541 return ReadJSObject(); | 582 return ReadJSObject(); |
542 case SerializationTag::kBeginSparseJSArray: | 583 case SerializationTag::kBeginSparseJSArray: |
543 return ReadSparseJSArray(); | 584 return ReadSparseJSArray(); |
544 case SerializationTag::kBeginDenseJSArray: | 585 case SerializationTag::kBeginDenseJSArray: |
545 return ReadDenseJSArray(); | 586 return ReadDenseJSArray(); |
546 case SerializationTag::kDate: | 587 case SerializationTag::kDate: |
547 return ReadJSDate(); | 588 return ReadJSDate(); |
589 case SerializationTag::kTrueObject: | |
590 case SerializationTag::kFalseObject: | |
591 case SerializationTag::kNumberObject: | |
592 case SerializationTag::kStringObject: | |
593 return ReadJSValue(tag); | |
548 default: | 594 default: |
549 return MaybeHandle<Object>(); | 595 return MaybeHandle<Object>(); |
550 } | 596 } |
551 } | 597 } |
552 | 598 |
553 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { | 599 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { |
554 uint32_t utf8_length; | 600 uint32_t utf8_length; |
555 Vector<const uint8_t> utf8_bytes; | 601 Vector<const uint8_t> utf8_bytes; |
556 if (!ReadVarint<uint32_t>().To(&utf8_length) || | 602 if (!ReadVarint<uint32_t>().To(&utf8_length) || |
557 utf8_length > | 603 utf8_length > |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
679 uint32_t id = next_id_++; | 725 uint32_t id = next_id_++; |
680 Handle<JSDate> date; | 726 Handle<JSDate> date; |
681 if (!JSDate::New(isolate_->date_function(), isolate_->date_function(), value) | 727 if (!JSDate::New(isolate_->date_function(), isolate_->date_function(), value) |
682 .ToHandle(&date)) { | 728 .ToHandle(&date)) { |
683 return MaybeHandle<JSDate>(); | 729 return MaybeHandle<JSDate>(); |
684 } | 730 } |
685 AddObjectWithID(id, date); | 731 AddObjectWithID(id, date); |
686 return date; | 732 return date; |
687 } | 733 } |
688 | 734 |
735 MaybeHandle<JSValue> ValueDeserializer::ReadJSValue(SerializationTag tag) { | |
736 uint32_t id = next_id_++; | |
737 Handle<JSValue> value; | |
738 switch (tag) { | |
739 case SerializationTag::kTrueObject: | |
740 value = Handle<JSValue>::cast( | |
741 isolate_->factory()->NewJSObject(isolate_->boolean_function())); | |
742 value->set_value(isolate_->heap()->true_value()); | |
743 break; | |
744 case SerializationTag::kFalseObject: | |
745 value = Handle<JSValue>::cast( | |
746 isolate_->factory()->NewJSObject(isolate_->boolean_function())); | |
747 value->set_value(isolate_->heap()->false_value()); | |
748 break; | |
749 case SerializationTag::kNumberObject: { | |
750 double number; | |
751 if (!ReadDouble().To(&number)) return MaybeHandle<JSValue>(); | |
752 value = Handle<JSValue>::cast( | |
753 isolate_->factory()->NewJSObject(isolate_->number_function())); | |
754 value->set_value(*isolate_->factory()->NewNumber(number)); | |
755 break; | |
756 } | |
757 case SerializationTag::kStringObject: { | |
758 Handle<String> string; | |
759 if (!ReadUtf8String().ToHandle(&string)) return MaybeHandle<JSValue>(); | |
760 value = Handle<JSValue>::cast( | |
761 isolate_->factory()->NewJSObject(isolate_->string_function())); | |
762 value->set_value(*string); | |
763 break; | |
764 } | |
765 default: | |
766 return MaybeHandle<JSValue>(); | |
767 } | |
768 AddObjectWithID(id, value); | |
769 return value; | |
770 } | |
771 | |
689 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( | 772 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( |
690 Handle<JSObject> object, SerializationTag end_tag) { | 773 Handle<JSObject> object, SerializationTag end_tag) { |
691 for (uint32_t num_properties = 0;; num_properties++) { | 774 for (uint32_t num_properties = 0;; num_properties++) { |
692 SerializationTag tag; | 775 SerializationTag tag; |
693 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); | 776 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); |
694 if (tag == end_tag) { | 777 if (tag == end_tag) { |
695 ConsumeTag(end_tag); | 778 ConsumeTag(end_tag); |
696 return Just(num_properties); | 779 return Just(num_properties); |
697 } | 780 } |
698 | 781 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
843 } | 926 } |
844 #endif | 927 #endif |
845 position_ = end_; | 928 position_ = end_; |
846 | 929 |
847 if (stack.size() != 1) return MaybeHandle<Object>(); | 930 if (stack.size() != 1) return MaybeHandle<Object>(); |
848 return scope.CloseAndEscape(stack[0]); | 931 return scope.CloseAndEscape(stack[0]); |
849 } | 932 } |
850 | 933 |
851 } // namespace internal | 934 } // namespace internal |
852 } // namespace v8 | 935 } // namespace v8 |
OLD | NEW |