Index: src/json-stringifier.cc |
diff --git a/src/json-stringifier.cc b/src/json-stringifier.cc |
index cc859929d79db46a6114f705ebe4df7f94c2e1c1..ac206822e9abc5b704c3aad1d8f09e18603c984a 100644 |
--- a/src/json-stringifier.cc |
+++ b/src/json-stringifier.cc |
@@ -81,29 +81,15 @@ const char* const BasicJsonStringifier::JsonEscapeTable = |
"\370\0 \371\0 \372\0 \373\0 " |
"\374\0 \375\0 \376\0 \377\0 "; |
-BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate, Handle<String> gap) |
- : isolate_(isolate), builder_(isolate), gap_string_(gap), indent_(0) { |
+BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate) |
+ : isolate_(isolate), builder_(isolate), gap_(nullptr), indent_(0) { |
tojson_string_ = factory()->toJSON_string(); |
stack_ = factory()->NewJSArray(8); |
- int gap_length = gap->length(); |
- if (gap_length != 0) { |
- gap = String::Flatten(gap); |
- if (gap->IsTwoByteRepresentation()) builder_.ChangeEncoding(); |
- DisallowHeapAllocation no_gc; |
- String::FlatContent flat = gap->GetFlatContent(); |
- gap_ = NewArray<uc16>(gap_length + 1); |
- if (flat.IsOneByte()) { |
- CopyChars(gap_, flat.ToOneByteVector().start(), gap_length); |
- } else { |
- CopyChars(gap_, flat.ToUC16Vector().start(), gap_length); |
- } |
- gap_[gap_length] = '\0'; |
- } else { |
- gap_ = nullptr; |
- } |
} |
-MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) { |
+MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object, |
+ Handle<Object> gap) { |
+ if (!gap->IsUndefined() && !InitializeGap(gap)) return MaybeHandle<Object>(); |
Result result = SerializeObject(object); |
if (result == UNCHANGED) return factory()->undefined_value(); |
if (result == SUCCESS) return builder_.Finish(); |
@@ -111,6 +97,46 @@ MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) { |
return MaybeHandle<Object>(); |
} |
+bool BasicJsonStringifier::InitializeGap(Handle<Object> gap) { |
+ DCHECK_NULL(gap_); |
+ HandleScope scope(isolate_); |
+ if (gap->IsJSReceiver()) { |
+ Handle<String> class_name(Handle<JSReceiver>::cast(gap)->class_name()); |
+ if (class_name.is_identical_to(factory()->String_string())) { |
Camillo Bruni
2016/05/23 14:08:25
argh :D we should have a IsNumberLike() somewhere
Yang
2016/05/23 18:19:07
Actually, the string case and the number case are
|
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, |
+ Object::ToString(isolate_, gap), false); |
+ } else if (class_name.is_identical_to(factory()->number_string())) { |
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap, Object::ToNumber(gap), |
+ false); |
+ } |
+ } |
+ |
+ if (gap->IsString()) { |
+ Handle<String> gap_string = Handle<String>::cast(gap); |
+ if (gap_string->length() > 0) { |
+ int gap_length = std::min(gap_string->length(), 10); |
+ gap_ = NewArray<uc16>(gap_length + 1); |
+ String::WriteToFlat(*gap_string, gap_, 0, gap_length); |
+ for (int i = 0; i < gap_length; i++) { |
+ if (gap_[i] > String::kMaxOneByteCharCode) { |
+ builder_.ChangeEncoding(); |
+ break; |
+ } |
+ } |
+ gap_[gap_length] = '\0'; |
+ } |
+ } else if (gap->IsNumber()) { |
+ int num_value = DoubleToInt32(gap->Number()); |
+ if (num_value > 0) { |
+ int gap_length = std::min(num_value, 10); |
Camillo Bruni
2016/05/23 14:08:25
just read the spec, wut? :D
Yang
2016/05/23 18:19:07
Yeah. Magic numbers ftw.
|
+ gap_ = NewArray<uc16>(gap_length + 1); |
+ for (int i = 0; i < gap_length; i++) gap_[i] = ' '; |
+ gap_[gap_length] = '\0'; |
+ } |
+ } |
+ return true; |
+} |
+ |
MaybeHandle<Object> BasicJsonStringifier::StringifyString( |
Isolate* isolate, Handle<String> object) { |
static const int kJsonQuoteWorstCaseBlowup = 6; |
@@ -119,9 +145,8 @@ MaybeHandle<Object> BasicJsonStringifier::StringifyString( |
object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
if (worst_case_length > 32 * KB) { // Slow path if too large. |
- BasicJsonStringifier stringifier(isolate, |
- isolate->factory()->empty_string()); |
- return stringifier.Stringify(object); |
+ BasicJsonStringifier stringifier(isolate); |
+ return stringifier.Stringify(object, isolate->factory()->undefined_value()); |
} |
object = String::Flatten(object); |