| 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 "\370\0 \371\0 \372\0 \373\0 " | 81 "\370\0 \371\0 \372\0 \373\0 " |
| 82 "\374\0 \375\0 \376\0 \377\0 "; | 82 "\374\0 \375\0 \376\0 \377\0 "; |
| 83 | 83 |
| 84 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) | 84 BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) |
| 85 : isolate_(isolate), builder_(isolate), gap_(nullptr), indent_(0) { | 85 : isolate_(isolate), builder_(isolate), gap_(nullptr), indent_(0) { |
| 86 tojson_string_ = factory()->toJSON_string(); | 86 tojson_string_ = factory()->toJSON_string(); |
| 87 stack_ = factory()->NewJSArray(8); | 87 stack_ = factory()->NewJSArray(8); |
| 88 } | 88 } |
| 89 | 89 |
| 90 MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object, | 90 MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object, |
| 91 Handle<Object> replacer, |
| 91 Handle<Object> gap) { | 92 Handle<Object> gap) { |
| 93 if (!InitializeReplacer(replacer)) return MaybeHandle<Object>(); |
| 92 if (!gap->IsUndefined() && !InitializeGap(gap)) return MaybeHandle<Object>(); | 94 if (!gap->IsUndefined() && !InitializeGap(gap)) return MaybeHandle<Object>(); |
| 93 Result result = SerializeObject(object); | 95 Result result = SerializeObject(object); |
| 94 if (result == UNCHANGED) return factory()->undefined_value(); | 96 if (result == UNCHANGED) return factory()->undefined_value(); |
| 95 if (result == SUCCESS) return builder_.Finish(); | 97 if (result == SUCCESS) return builder_.Finish(); |
| 96 DCHECK(result == EXCEPTION); | 98 DCHECK(result == EXCEPTION); |
| 97 return MaybeHandle<Object>(); | 99 return MaybeHandle<Object>(); |
| 98 } | 100 } |
| 99 | 101 |
| 102 bool IsInList(Handle<String> key, List<Handle<String> >* list) { |
| 103 // TODO(yangguo): This is O(n^2) for n properties in the list. Deal with this |
| 104 // if this becomes an issue. |
| 105 for (const Handle<String>& existing : *list) { |
| 106 if (String::Equals(existing, key)) return true; |
| 107 } |
| 108 return false; |
| 109 } |
| 110 |
| 111 bool BasicJsonStringifier::InitializeReplacer(Handle<Object> replacer) { |
| 112 DCHECK(property_list_.is_null()); |
| 113 Maybe<bool> is_array = Object::IsArray(replacer); |
| 114 if (is_array.IsNothing()) return false; |
| 115 if (is_array.FromJust()) { |
| 116 HandleScope handle_scope(isolate_); |
| 117 List<Handle<String> > list; |
| 118 Handle<Object> length_obj; |
| 119 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 120 isolate_, length_obj, |
| 121 Object::GetLengthFromArrayLike(isolate_, replacer), false); |
| 122 uint32_t length; |
| 123 if (!length_obj->ToUint32(&length)) length = kMaxUInt32; |
| 124 for (uint32_t i = 0; i < length; i++) { |
| 125 Handle<Object> element; |
| 126 Handle<String> key; |
| 127 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 128 isolate_, element, Object::GetElement(isolate_, replacer, i), false); |
| 129 if (element->IsNumber() || element->IsString()) { |
| 130 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 131 isolate_, key, Object::ToString(isolate_, element), false); |
| 132 } else if (element->IsJSValue()) { |
| 133 Handle<Object> value(Handle<JSValue>::cast(element)->value(), isolate_); |
| 134 if (value->IsNumber() || value->IsString()) { |
| 135 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 136 isolate_, key, Object::ToString(isolate_, element), false); |
| 137 } |
| 138 } |
| 139 if (key.is_null()) continue; |
| 140 if (!IsInList(key, &list)) list.Add(key); |
| 141 } |
| 142 property_list_ = factory()->NewUninitializedFixedArray(list.length()); |
| 143 for (int i = 0; i < list.length(); i++) { |
| 144 property_list_->set(i, *list[i]); |
| 145 } |
| 146 property_list_ = handle_scope.CloseAndEscape(property_list_); |
| 147 } |
| 148 return true; |
| 149 } |
| 150 |
| 100 bool BasicJsonStringifier::InitializeGap(Handle<Object> gap) { | 151 bool BasicJsonStringifier::InitializeGap(Handle<Object> gap) { |
| 101 DCHECK_NULL(gap_); | 152 DCHECK_NULL(gap_); |
| 102 HandleScope scope(isolate_); | 153 HandleScope scope(isolate_); |
| 103 if (gap->IsJSReceiver()) { | 154 if (gap->IsJSValue()) { |
| 104 Handle<String> class_name(Handle<JSReceiver>::cast(gap)->class_name()); | 155 Handle<Object> value(Handle<JSValue>::cast(gap)->value(), isolate_); |
| 105 if (class_name.is_identical_to(factory()->String_string())) { | 156 if (value->IsString()) { |
| 106 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, | 157 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, |
| 107 Object::ToString(isolate_, gap), false); | 158 Object::ToString(isolate_, gap), false); |
| 108 } else if (class_name.is_identical_to(factory()->number_string())) { | 159 } else if (value->IsNumber()) { |
| 109 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, Object::ToNumber(gap), | 160 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, Object::ToNumber(gap), |
| 110 false); | 161 false); |
| 111 } | 162 } |
| 112 } | 163 } |
| 113 | 164 |
| 114 if (gap->IsString()) { | 165 if (gap->IsString()) { |
| 115 Handle<String> gap_string = Handle<String>::cast(gap); | 166 Handle<String> gap_string = Handle<String>::cast(gap); |
| 116 if (gap_string->length() > 0) { | 167 if (gap_string->length() > 0) { |
| 117 int gap_length = std::min(gap_string->length(), 10); | 168 int gap_length = std::min(gap_string->length(), 10); |
| 118 gap_ = NewArray<uc16>(gap_length + 1); | 169 gap_ = NewArray<uc16>(gap_length + 1); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 139 | 190 |
| 140 MaybeHandle<Object> BasicJsonStringifier::StringifyString( | 191 MaybeHandle<Object> BasicJsonStringifier::StringifyString( |
| 141 Isolate* isolate, Handle<String> object) { | 192 Isolate* isolate, Handle<String> object) { |
| 142 static const int kJsonQuoteWorstCaseBlowup = 6; | 193 static const int kJsonQuoteWorstCaseBlowup = 6; |
| 143 static const int kSpaceForQuotes = 2; | 194 static const int kSpaceForQuotes = 2; |
| 144 int worst_case_length = | 195 int worst_case_length = |
| 145 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | 196 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
| 146 | 197 |
| 147 if (worst_case_length > 32 * KB) { // Slow path if too large. | 198 if (worst_case_length > 32 * KB) { // Slow path if too large. |
| 148 BasicJsonStringifier stringifier(isolate); | 199 BasicJsonStringifier stringifier(isolate); |
| 149 return stringifier.Stringify(object, isolate->factory()->undefined_value()); | 200 Handle<Object> undefined = isolate->factory()->undefined_value(); |
| 201 return stringifier.Stringify(object, undefined, undefined); |
| 150 } | 202 } |
| 151 | 203 |
| 152 object = String::Flatten(object); | 204 object = String::Flatten(object); |
| 153 DCHECK(object->IsFlat()); | 205 DCHECK(object->IsFlat()); |
| 154 Handle<SeqString> result; | 206 Handle<SeqString> result; |
| 155 if (object->IsOneByteRepresentationUnderneath()) { | 207 if (object->IsOneByteRepresentationUnderneath()) { |
| 156 result = isolate->factory() | 208 result = isolate->factory() |
| 157 ->NewRawOneByteString(worst_case_length) | 209 ->NewRawOneByteString(worst_case_length) |
| 158 .ToHandleChecked(); | 210 .ToHandleChecked(); |
| 159 IncrementalStringBuilder::NoExtendString<uint8_t> no_extend( | 211 IncrementalStringBuilder::NoExtendString<uint8_t> no_extend( |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 } | 482 } |
| 431 return SUCCESS; | 483 return SUCCESS; |
| 432 } | 484 } |
| 433 | 485 |
| 434 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( | 486 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
| 435 Handle<JSObject> object) { | 487 Handle<JSObject> object) { |
| 436 HandleScope handle_scope(isolate_); | 488 HandleScope handle_scope(isolate_); |
| 437 Result stack_push = StackPush(object); | 489 Result stack_push = StackPush(object); |
| 438 if (stack_push != SUCCESS) return stack_push; | 490 if (stack_push != SUCCESS) return stack_push; |
| 439 | 491 |
| 440 if (object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER && | 492 if (property_list_.is_null() && |
| 493 object->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER && |
| 441 object->HasFastProperties() && | 494 object->HasFastProperties() && |
| 442 Handle<JSObject>::cast(object)->elements()->length() == 0) { | 495 Handle<JSObject>::cast(object)->elements()->length() == 0) { |
| 443 DCHECK(object->IsJSObject()); | 496 DCHECK(object->IsJSObject()); |
| 444 DCHECK(!object->IsJSGlobalProxy()); | 497 DCHECK(!object->IsJSGlobalProxy()); |
| 445 Handle<JSObject> js_obj = Handle<JSObject>::cast(object); | 498 Handle<JSObject> js_obj = Handle<JSObject>::cast(object); |
| 446 DCHECK(!js_obj->HasIndexedInterceptor()); | 499 DCHECK(!js_obj->HasIndexedInterceptor()); |
| 447 DCHECK(!js_obj->HasNamedInterceptor()); | 500 DCHECK(!js_obj->HasNamedInterceptor()); |
| 448 Handle<Map> map(js_obj->map()); | 501 Handle<Map> map(js_obj->map()); |
| 449 builder_.AppendCharacter('{'); | 502 builder_.AppendCharacter('{'); |
| 450 Indent(); | 503 Indent(); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 480 } else { | 533 } else { |
| 481 Result result = SerializeJSReceiverSlow(object); | 534 Result result = SerializeJSReceiverSlow(object); |
| 482 if (result != SUCCESS) return result; | 535 if (result != SUCCESS) return result; |
| 483 } | 536 } |
| 484 StackPop(); | 537 StackPop(); |
| 485 return SUCCESS; | 538 return SUCCESS; |
| 486 } | 539 } |
| 487 | 540 |
| 488 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSReceiverSlow( | 541 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSReceiverSlow( |
| 489 Handle<JSReceiver> object) { | 542 Handle<JSReceiver> object) { |
| 490 Handle<FixedArray> contents; | 543 Handle<FixedArray> contents = property_list_; |
| 491 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 544 if (contents.is_null()) { |
| 492 isolate_, contents, | 545 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 493 JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION); | 546 isolate_, contents, |
| 547 JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION); |
| 548 } |
| 494 | 549 |
| 495 builder_.AppendCharacter('{'); | 550 builder_.AppendCharacter('{'); |
| 496 Indent(); | 551 Indent(); |
| 497 bool comma = false; | 552 bool comma = false; |
| 498 for (int i = 0; i < contents->length(); i++) { | 553 for (int i = 0; i < contents->length(); i++) { |
| 499 Object* key = contents->get(i); | 554 Object* key = contents->get(i); |
| 500 Handle<String> key_handle; | 555 Handle<String> key_handle; |
| 501 MaybeHandle<Object> maybe_property; | 556 MaybeHandle<Object> maybe_property; |
| 502 if (key->IsString()) { | 557 if (key->IsString()) { |
| 503 key_handle = Handle<String>(String::cast(key), isolate_); | 558 key_handle = Handle<String>(String::cast(key), isolate_); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 if (object->IsOneByteRepresentationUnderneath()) { | 704 if (object->IsOneByteRepresentationUnderneath()) { |
| 650 SerializeString_<uint8_t, uc16>(object); | 705 SerializeString_<uint8_t, uc16>(object); |
| 651 } else { | 706 } else { |
| 652 SerializeString_<uc16, uc16>(object); | 707 SerializeString_<uc16, uc16>(object); |
| 653 } | 708 } |
| 654 } | 709 } |
| 655 } | 710 } |
| 656 | 711 |
| 657 } // namespace internal | 712 } // namespace internal |
| 658 } // namespace v8 | 713 } // namespace v8 |
| OLD | NEW |