OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #ifndef V8_JSON_STRINGIFIER_H_ | 5 #ifndef V8_JSON_STRINGIFIER_H_ |
6 #define V8_JSON_STRINGIFIER_H_ | 6 #define V8_JSON_STRINGIFIER_H_ |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 false, | 88 false, |
89 Handle<Object>(Smi::FromInt(i), isolate)); | 89 Handle<Object>(Smi::FromInt(i), isolate)); |
90 } | 90 } |
91 | 91 |
92 // Serialize a object property. | 92 // Serialize a object property. |
93 // The key may or may not be serialized depending on the property. | 93 // The key may or may not be serialized depending on the property. |
94 // The key may also serve as argument for the toJSON function. | 94 // The key may also serve as argument for the toJSON function. |
95 INLINE(Result SerializeProperty(Handle<Object> object, | 95 INLINE(Result SerializeProperty(Handle<Object> object, |
96 bool deferred_comma, | 96 bool deferred_comma, |
97 Handle<String> deferred_key)) { | 97 Handle<String> deferred_key)) { |
98 ASSERT(!deferred_key.is_null()); | 98 DCHECK(!deferred_key.is_null()); |
99 return Serialize_<true>(object, deferred_comma, deferred_key); | 99 return Serialize_<true>(object, deferred_comma, deferred_key); |
100 } | 100 } |
101 | 101 |
102 template <bool deferred_string_key> | 102 template <bool deferred_string_key> |
103 Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key); | 103 Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key); |
104 | 104 |
105 void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) { | 105 void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) { |
106 if (deferred_comma) Append(','); | 106 if (deferred_comma) Append(','); |
107 SerializeString(Handle<String>::cast(deferred_key)); | 107 SerializeString(Handle<String>::cast(deferred_key)); |
108 Append(':'); | 108 Append(':'); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 if (result == UNCHANGED) return isolate_->factory()->undefined_value(); | 256 if (result == UNCHANGED) return isolate_->factory()->undefined_value(); |
257 if (result == SUCCESS) { | 257 if (result == SUCCESS) { |
258 ShrinkCurrentPart(); | 258 ShrinkCurrentPart(); |
259 Accumulate(); | 259 Accumulate(); |
260 if (overflowed_) { | 260 if (overflowed_) { |
261 return isolate_->Throw<Object>( | 261 return isolate_->Throw<Object>( |
262 isolate_->factory()->NewInvalidStringLengthError()); | 262 isolate_->factory()->NewInvalidStringLengthError()); |
263 } | 263 } |
264 return accumulator(); | 264 return accumulator(); |
265 } | 265 } |
266 ASSERT(result == EXCEPTION); | 266 DCHECK(result == EXCEPTION); |
267 return MaybeHandle<Object>(); | 267 return MaybeHandle<Object>(); |
268 } | 268 } |
269 | 269 |
270 | 270 |
271 MaybeHandle<Object> BasicJsonStringifier::StringifyString( | 271 MaybeHandle<Object> BasicJsonStringifier::StringifyString( |
272 Isolate* isolate, Handle<String> object) { | 272 Isolate* isolate, Handle<String> object) { |
273 static const int kJsonQuoteWorstCaseBlowup = 6; | 273 static const int kJsonQuoteWorstCaseBlowup = 6; |
274 static const int kSpaceForQuotes = 2; | 274 static const int kSpaceForQuotes = 2; |
275 int worst_case_length = | 275 int worst_case_length = |
276 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | 276 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
277 | 277 |
278 if (worst_case_length > 32 * KB) { // Slow path if too large. | 278 if (worst_case_length > 32 * KB) { // Slow path if too large. |
279 BasicJsonStringifier stringifier(isolate); | 279 BasicJsonStringifier stringifier(isolate); |
280 return stringifier.Stringify(object); | 280 return stringifier.Stringify(object); |
281 } | 281 } |
282 | 282 |
283 object = String::Flatten(object); | 283 object = String::Flatten(object); |
284 ASSERT(object->IsFlat()); | 284 DCHECK(object->IsFlat()); |
285 if (object->IsOneByteRepresentationUnderneath()) { | 285 if (object->IsOneByteRepresentationUnderneath()) { |
286 Handle<String> result = isolate->factory()->NewRawOneByteString( | 286 Handle<String> result = isolate->factory()->NewRawOneByteString( |
287 worst_case_length).ToHandleChecked(); | 287 worst_case_length).ToHandleChecked(); |
288 DisallowHeapAllocation no_gc; | 288 DisallowHeapAllocation no_gc; |
289 return StringifyString_<SeqOneByteString>( | 289 return StringifyString_<SeqOneByteString>( |
290 isolate, | 290 isolate, |
291 object->GetFlatContent().ToOneByteVector(), | 291 object->GetFlatContent().ToOneByteVector(), |
292 result); | 292 result); |
293 } else { | 293 } else { |
294 Handle<String> result = isolate->factory()->NewRawTwoByteString( | 294 Handle<String> result = isolate->factory()->NewRawTwoByteString( |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 499 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
500 isolate_, value, Execution::ToString(isolate_, object), EXCEPTION); | 500 isolate_, value, Execution::ToString(isolate_, object), EXCEPTION); |
501 SerializeString(Handle<String>::cast(value)); | 501 SerializeString(Handle<String>::cast(value)); |
502 } else if (class_name == isolate_->heap()->Number_string()) { | 502 } else if (class_name == isolate_->heap()->Number_string()) { |
503 Handle<Object> value; | 503 Handle<Object> value; |
504 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 504 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
505 isolate_, value, Execution::ToNumber(isolate_, object), EXCEPTION); | 505 isolate_, value, Execution::ToNumber(isolate_, object), EXCEPTION); |
506 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); | 506 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); |
507 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); | 507 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); |
508 } else { | 508 } else { |
509 ASSERT(class_name == isolate_->heap()->Boolean_string()); | 509 DCHECK(class_name == isolate_->heap()->Boolean_string()); |
510 Object* value = JSValue::cast(*object)->value(); | 510 Object* value = JSValue::cast(*object)->value(); |
511 ASSERT(value->IsBoolean()); | 511 DCHECK(value->IsBoolean()); |
512 AppendAscii(value->IsTrue() ? "true" : "false"); | 512 AppendAscii(value->IsTrue() ? "true" : "false"); |
513 } | 513 } |
514 return SUCCESS; | 514 return SUCCESS; |
515 } | 515 } |
516 | 516 |
517 | 517 |
518 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { | 518 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { |
519 static const int kBufferSize = 100; | 519 static const int kBufferSize = 100; |
520 char chars[kBufferSize]; | 520 char chars[kBufferSize]; |
521 Vector<char> buffer(chars, kBufferSize); | 521 Vector<char> buffer(chars, kBufferSize); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
624 } | 624 } |
625 return SUCCESS; | 625 return SUCCESS; |
626 } | 626 } |
627 | 627 |
628 | 628 |
629 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( | 629 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
630 Handle<JSObject> object) { | 630 Handle<JSObject> object) { |
631 HandleScope handle_scope(isolate_); | 631 HandleScope handle_scope(isolate_); |
632 Result stack_push = StackPush(object); | 632 Result stack_push = StackPush(object); |
633 if (stack_push != SUCCESS) return stack_push; | 633 if (stack_push != SUCCESS) return stack_push; |
634 ASSERT(!object->IsJSGlobalProxy() && !object->IsGlobalObject()); | 634 DCHECK(!object->IsJSGlobalProxy() && !object->IsGlobalObject()); |
635 | 635 |
636 Append('{'); | 636 Append('{'); |
637 bool comma = false; | 637 bool comma = false; |
638 | 638 |
639 if (object->HasFastProperties() && | 639 if (object->HasFastProperties() && |
640 !object->HasIndexedInterceptor() && | 640 !object->HasIndexedInterceptor() && |
641 !object->HasNamedInterceptor() && | 641 !object->HasNamedInterceptor() && |
642 object->elements()->length() == 0) { | 642 object->elements()->length() == 0) { |
643 Handle<Map> map(object->map()); | 643 Handle<Map> map(object->map()); |
644 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { | 644 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { |
(...skipping 25 matching lines...) Expand all Loading... |
670 EXCEPTION); | 670 EXCEPTION); |
671 | 671 |
672 for (int i = 0; i < contents->length(); i++) { | 672 for (int i = 0; i < contents->length(); i++) { |
673 Object* key = contents->get(i); | 673 Object* key = contents->get(i); |
674 Handle<String> key_handle; | 674 Handle<String> key_handle; |
675 MaybeHandle<Object> maybe_property; | 675 MaybeHandle<Object> maybe_property; |
676 if (key->IsString()) { | 676 if (key->IsString()) { |
677 key_handle = Handle<String>(String::cast(key), isolate_); | 677 key_handle = Handle<String>(String::cast(key), isolate_); |
678 maybe_property = Object::GetPropertyOrElement(object, key_handle); | 678 maybe_property = Object::GetPropertyOrElement(object, key_handle); |
679 } else { | 679 } else { |
680 ASSERT(key->IsNumber()); | 680 DCHECK(key->IsNumber()); |
681 key_handle = factory_->NumberToString(Handle<Object>(key, isolate_)); | 681 key_handle = factory_->NumberToString(Handle<Object>(key, isolate_)); |
682 uint32_t index; | 682 uint32_t index; |
683 if (key->IsSmi()) { | 683 if (key->IsSmi()) { |
684 maybe_property = Object::GetElement( | 684 maybe_property = Object::GetElement( |
685 isolate_, object, Smi::cast(key)->value()); | 685 isolate_, object, Smi::cast(key)->value()); |
686 } else if (key_handle->AsArrayIndex(&index)) { | 686 } else if (key_handle->AsArrayIndex(&index)) { |
687 maybe_property = Object::GetElement(isolate_, object, index); | 687 maybe_property = Object::GetElement(isolate_, object, index); |
688 } else { | 688 } else { |
689 maybe_property = Object::GetPropertyOrElement(object, key_handle); | 689 maybe_property = Object::GetPropertyOrElement(object, key_handle); |
690 } | 690 } |
691 } | 691 } |
692 Handle<Object> property; | 692 Handle<Object> property; |
693 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 693 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
694 isolate_, property, maybe_property, EXCEPTION); | 694 isolate_, property, maybe_property, EXCEPTION); |
695 Result result = SerializeProperty(property, comma, key_handle); | 695 Result result = SerializeProperty(property, comma, key_handle); |
696 if (!comma && result == SUCCESS) comma = true; | 696 if (!comma && result == SUCCESS) comma = true; |
697 if (result == EXCEPTION) return result; | 697 if (result == EXCEPTION) return result; |
698 } | 698 } |
699 } | 699 } |
700 | 700 |
701 Append('}'); | 701 Append('}'); |
702 StackPop(); | 702 StackPop(); |
703 current_part_ = handle_scope.CloseAndEscape(current_part_); | 703 current_part_ = handle_scope.CloseAndEscape(current_part_); |
704 return SUCCESS; | 704 return SUCCESS; |
705 } | 705 } |
706 | 706 |
707 | 707 |
708 void BasicJsonStringifier::ShrinkCurrentPart() { | 708 void BasicJsonStringifier::ShrinkCurrentPart() { |
709 ASSERT(current_index_ < part_length_); | 709 DCHECK(current_index_ < part_length_); |
710 current_part_ = SeqString::Truncate(Handle<SeqString>::cast(current_part_), | 710 current_part_ = SeqString::Truncate(Handle<SeqString>::cast(current_part_), |
711 current_index_); | 711 current_index_); |
712 } | 712 } |
713 | 713 |
714 | 714 |
715 void BasicJsonStringifier::Accumulate() { | 715 void BasicJsonStringifier::Accumulate() { |
716 if (accumulator()->length() + current_part_->length() > String::kMaxLength) { | 716 if (accumulator()->length() + current_part_->length() > String::kMaxLength) { |
717 // Screw it. Simply set the flag and carry on. Throw exception at the end. | 717 // Screw it. Simply set the flag and carry on. Throw exception at the end. |
718 set_accumulator(factory_->empty_string()); | 718 set_accumulator(factory_->empty_string()); |
719 overflowed_ = true; | 719 overflowed_ = true; |
720 } else { | 720 } else { |
721 set_accumulator(factory_->NewConsString(accumulator(), | 721 set_accumulator(factory_->NewConsString(accumulator(), |
722 current_part_).ToHandleChecked()); | 722 current_part_).ToHandleChecked()); |
723 } | 723 } |
724 } | 724 } |
725 | 725 |
726 | 726 |
727 void BasicJsonStringifier::Extend() { | 727 void BasicJsonStringifier::Extend() { |
728 Accumulate(); | 728 Accumulate(); |
729 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { | 729 if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) { |
730 part_length_ *= kPartLengthGrowthFactor; | 730 part_length_ *= kPartLengthGrowthFactor; |
731 } | 731 } |
732 if (is_ascii_) { | 732 if (is_ascii_) { |
733 current_part_ = | 733 current_part_ = |
734 factory_->NewRawOneByteString(part_length_).ToHandleChecked(); | 734 factory_->NewRawOneByteString(part_length_).ToHandleChecked(); |
735 } else { | 735 } else { |
736 current_part_ = | 736 current_part_ = |
737 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); | 737 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); |
738 } | 738 } |
739 ASSERT(!current_part_.is_null()); | 739 DCHECK(!current_part_.is_null()); |
740 current_index_ = 0; | 740 current_index_ = 0; |
741 } | 741 } |
742 | 742 |
743 | 743 |
744 void BasicJsonStringifier::ChangeEncoding() { | 744 void BasicJsonStringifier::ChangeEncoding() { |
745 ShrinkCurrentPart(); | 745 ShrinkCurrentPart(); |
746 Accumulate(); | 746 Accumulate(); |
747 current_part_ = | 747 current_part_ = |
748 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); | 748 factory_->NewRawTwoByteString(part_length_).ToHandleChecked(); |
749 ASSERT(!current_part_.is_null()); | 749 DCHECK(!current_part_.is_null()); |
750 current_index_ = 0; | 750 current_index_ = 0; |
751 is_ascii_ = false; | 751 is_ascii_ = false; |
752 } | 752 } |
753 | 753 |
754 | 754 |
755 template <typename SrcChar, typename DestChar> | 755 template <typename SrcChar, typename DestChar> |
756 int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, | 756 int BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src, |
757 DestChar* dest, | 757 DestChar* dest, |
758 int length) { | 758 int length) { |
759 DestChar* dest_start = dest; | 759 DestChar* dest_start = dest; |
760 | 760 |
761 // Assert that uc16 character is not truncated down to 8 bit. | 761 // Assert that uc16 character is not truncated down to 8 bit. |
762 // The <uc16, char> version of this method must not be called. | 762 // The <uc16, char> version of this method must not be called. |
763 ASSERT(sizeof(*dest) >= sizeof(*src)); | 763 DCHECK(sizeof(*dest) >= sizeof(*src)); |
764 | 764 |
765 for (int i = 0; i < length; i++) { | 765 for (int i = 0; i < length; i++) { |
766 SrcChar c = src[i]; | 766 SrcChar c = src[i]; |
767 if (DoNotEscape(c)) { | 767 if (DoNotEscape(c)) { |
768 *(dest++) = static_cast<DestChar>(c); | 768 *(dest++) = static_cast<DestChar>(c); |
769 } else { | 769 } else { |
770 const uint8_t* chars = reinterpret_cast<const uint8_t*>( | 770 const uint8_t* chars = reinterpret_cast<const uint8_t*>( |
771 &JsonEscapeTable[c * kJsonEscapeTableEntrySize]); | 771 &JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
772 while (*chars != '\0') *(dest++) = *(chars++); | 772 while (*chars != '\0') *(dest++) = *(chars++); |
773 } | 773 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 template <> | 834 template <> |
835 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { | 835 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { |
836 return c >= '#' && c != '\\' && c != 0x7f; | 836 return c >= '#' && c != '\\' && c != 0x7f; |
837 } | 837 } |
838 | 838 |
839 | 839 |
840 template <> | 840 template <> |
841 Vector<const uint8_t> BasicJsonStringifier::GetCharVector( | 841 Vector<const uint8_t> BasicJsonStringifier::GetCharVector( |
842 Handle<String> string) { | 842 Handle<String> string) { |
843 String::FlatContent flat = string->GetFlatContent(); | 843 String::FlatContent flat = string->GetFlatContent(); |
844 ASSERT(flat.IsAscii()); | 844 DCHECK(flat.IsAscii()); |
845 return flat.ToOneByteVector(); | 845 return flat.ToOneByteVector(); |
846 } | 846 } |
847 | 847 |
848 | 848 |
849 template <> | 849 template <> |
850 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { | 850 Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String> string) { |
851 String::FlatContent flat = string->GetFlatContent(); | 851 String::FlatContent flat = string->GetFlatContent(); |
852 ASSERT(flat.IsTwoByte()); | 852 DCHECK(flat.IsTwoByte()); |
853 return flat.ToUC16Vector(); | 853 return flat.ToUC16Vector(); |
854 } | 854 } |
855 | 855 |
856 | 856 |
857 void BasicJsonStringifier::SerializeString(Handle<String> object) { | 857 void BasicJsonStringifier::SerializeString(Handle<String> object) { |
858 object = String::Flatten(object); | 858 object = String::Flatten(object); |
859 if (is_ascii_) { | 859 if (is_ascii_) { |
860 if (object->IsOneByteRepresentationUnderneath()) { | 860 if (object->IsOneByteRepresentationUnderneath()) { |
861 SerializeString_<true, uint8_t>(object); | 861 SerializeString_<true, uint8_t>(object); |
862 } else { | 862 } else { |
863 ChangeEncoding(); | 863 ChangeEncoding(); |
864 SerializeString(object); | 864 SerializeString(object); |
865 } | 865 } |
866 } else { | 866 } else { |
867 if (object->IsOneByteRepresentationUnderneath()) { | 867 if (object->IsOneByteRepresentationUnderneath()) { |
868 SerializeString_<false, uint8_t>(object); | 868 SerializeString_<false, uint8_t>(object); |
869 } else { | 869 } else { |
870 SerializeString_<false, uc16>(object); | 870 SerializeString_<false, uc16>(object); |
871 } | 871 } |
872 } | 872 } |
873 } | 873 } |
874 | 874 |
875 } } // namespace v8::internal | 875 } } // namespace v8::internal |
876 | 876 |
877 #endif // V8_JSON_STRINGIFIER_H_ | 877 #endif // V8_JSON_STRINGIFIER_H_ |
OLD | NEW |