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/json-stringifier.h" | 5 #include "src/json-stringifier.h" |
6 | 6 |
7 #include "src/conversions.h" | 7 #include "src/conversions.h" |
8 #include "src/lookup.h" | 8 #include "src/lookup.h" |
9 #include "src/messages.h" | 9 #include "src/messages.h" |
10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 if (!gap->IsUndefined(isolate_) && !InitializeGap(gap)) { | 94 if (!gap->IsUndefined(isolate_) && !InitializeGap(gap)) { |
95 return MaybeHandle<Object>(); | 95 return MaybeHandle<Object>(); |
96 } | 96 } |
97 Result result = SerializeObject(object); | 97 Result result = SerializeObject(object); |
98 if (result == UNCHANGED) return factory()->undefined_value(); | 98 if (result == UNCHANGED) return factory()->undefined_value(); |
99 if (result == SUCCESS) return builder_.Finish(); | 99 if (result == SUCCESS) return builder_.Finish(); |
100 DCHECK(result == EXCEPTION); | 100 DCHECK(result == EXCEPTION); |
101 return MaybeHandle<Object>(); | 101 return MaybeHandle<Object>(); |
102 } | 102 } |
103 | 103 |
104 bool IsInList(Handle<String> key, List<Handle<String> >* list) { | |
105 // TODO(yangguo): This is O(n^2) for n properties in the list. Deal with this | |
106 // if this becomes an issue. | |
107 for (const Handle<String>& existing : *list) { | |
108 if (String::Equals(existing, key)) return true; | |
109 } | |
110 return false; | |
111 } | |
112 | |
113 bool JsonStringifier::InitializeReplacer(Handle<Object> replacer) { | 104 bool JsonStringifier::InitializeReplacer(Handle<Object> replacer) { |
114 DCHECK(property_list_.is_null()); | 105 DCHECK(property_list_.is_null()); |
115 DCHECK(replacer_function_.is_null()); | 106 DCHECK(replacer_function_.is_null()); |
116 Maybe<bool> is_array = Object::IsArray(replacer); | 107 Maybe<bool> is_array = Object::IsArray(replacer); |
117 if (is_array.IsNothing()) return false; | 108 if (is_array.IsNothing()) return false; |
118 if (is_array.FromJust()) { | 109 if (is_array.FromJust()) { |
119 HandleScope handle_scope(isolate_); | 110 HandleScope handle_scope(isolate_); |
120 List<Handle<String> > list; | 111 Handle<OrderedHashSet> set = factory()->NewOrderedHashSet(); |
121 Handle<Object> length_obj; | 112 Handle<Object> length_obj; |
122 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 113 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
123 isolate_, length_obj, | 114 isolate_, length_obj, |
124 Object::GetLengthFromArrayLike(isolate_, replacer), false); | 115 Object::GetLengthFromArrayLike(isolate_, replacer), false); |
125 uint32_t length; | 116 uint32_t length; |
126 if (!length_obj->ToUint32(&length)) length = kMaxUInt32; | 117 if (!length_obj->ToUint32(&length)) length = kMaxUInt32; |
127 for (uint32_t i = 0; i < length; i++) { | 118 for (uint32_t i = 0; i < length; i++) { |
128 Handle<Object> element; | 119 Handle<Object> element; |
129 Handle<String> key; | 120 Handle<String> key; |
130 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 121 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
131 isolate_, element, Object::GetElement(isolate_, replacer, i), false); | 122 isolate_, element, Object::GetElement(isolate_, replacer, i), false); |
132 if (element->IsNumber() || element->IsString()) { | 123 if (element->IsNumber() || element->IsString()) { |
133 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 124 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
134 isolate_, key, Object::ToString(isolate_, element), false); | 125 isolate_, key, Object::ToString(isolate_, element), false); |
135 } else if (element->IsJSValue()) { | 126 } else if (element->IsJSValue()) { |
136 Handle<Object> value(Handle<JSValue>::cast(element)->value(), isolate_); | 127 Handle<Object> value(Handle<JSValue>::cast(element)->value(), isolate_); |
137 if (value->IsNumber() || value->IsString()) { | 128 if (value->IsNumber() || value->IsString()) { |
138 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 129 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
139 isolate_, key, Object::ToString(isolate_, element), false); | 130 isolate_, key, Object::ToString(isolate_, element), false); |
140 } | 131 } |
141 } | 132 } |
142 if (key.is_null()) continue; | 133 if (key.is_null()) continue; |
143 if (!IsInList(key, &list)) list.Add(key); | 134 // Object keys are internalized, so do it here. |
| 135 key = factory()->InternalizeString(key); |
| 136 set = OrderedHashSet::Add(set, key); |
144 } | 137 } |
145 property_list_ = factory()->NewUninitializedFixedArray(list.length()); | 138 property_list_ = OrderedHashSet::ConvertToKeysArray( |
146 for (int i = 0; i < list.length(); i++) { | 139 set, GetKeysConversion::kKeepNumbers); |
147 property_list_->set(i, *list[i]); | |
148 } | |
149 property_list_ = handle_scope.CloseAndEscape(property_list_); | 140 property_list_ = handle_scope.CloseAndEscape(property_list_); |
150 } else if (replacer->IsCallable()) { | 141 } else if (replacer->IsCallable()) { |
151 replacer_function_ = Handle<JSReceiver>::cast(replacer); | 142 replacer_function_ = Handle<JSReceiver>::cast(replacer); |
152 } | 143 } |
153 return true; | 144 return true; |
154 } | 145 } |
155 | 146 |
156 bool JsonStringifier::InitializeGap(Handle<Object> gap) { | 147 bool JsonStringifier::InitializeGap(Handle<Object> gap) { |
157 DCHECK_NULL(gap_); | 148 DCHECK_NULL(gap_); |
158 HandleScope scope(isolate_); | 149 HandleScope scope(isolate_); |
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 if (object->IsOneByteRepresentationUnderneath()) { | 704 if (object->IsOneByteRepresentationUnderneath()) { |
714 SerializeString_<uint8_t, uc16>(object); | 705 SerializeString_<uint8_t, uc16>(object); |
715 } else { | 706 } else { |
716 SerializeString_<uc16, uc16>(object); | 707 SerializeString_<uc16, uc16>(object); |
717 } | 708 } |
718 } | 709 } |
719 } | 710 } |
720 | 711 |
721 } // namespace internal | 712 } // namespace internal |
722 } // namespace v8 | 713 } // namespace v8 |
OLD | NEW |