Index: src/json-stringifier.h |
diff --git a/src/json-stringifier.h b/src/json-stringifier.h |
index b40a78249ff2f3a192d5c27aa8312e1d4f74bd82..0b084e070d0aa43eeef090c92c4ff517ee1f3dbc 100644 |
--- a/src/json-stringifier.h |
+++ b/src/json-stringifier.h |
@@ -16,7 +16,9 @@ namespace internal { |
class BasicJsonStringifier BASE_EMBEDDED { |
public: |
- explicit BasicJsonStringifier(Isolate* isolate); |
+ BasicJsonStringifier(Isolate* isolate, Handle<String> gap); |
+ |
+ ~BasicJsonStringifier() { DeleteArray(gap_); } |
MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object); |
@@ -65,9 +67,10 @@ class BasicJsonStringifier BASE_EMBEDDED { |
Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key); |
void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) { |
- if (deferred_comma) builder_.AppendCharacter(','); |
+ Separator(!deferred_comma); |
SerializeString(Handle<String>::cast(deferred_key)); |
builder_.AppendCharacter(':'); |
+ if (gap_ != nullptr) builder_.AppendCharacter(' '); |
} |
Result SerializeSmi(Smi* object); |
@@ -98,6 +101,14 @@ class BasicJsonStringifier BASE_EMBEDDED { |
template <typename Char> |
INLINE(static bool DoNotEscape(Char c)); |
+ INLINE(void NewLine()); |
+ INLINE(void Indent() { indent_++; }); |
+ INLINE(void Unindent() { indent_--; }); |
+ INLINE(void Separator(bool first) { |
+ if (!first) builder_.AppendCharacter(','); |
+ NewLine(); |
+ }) |
+ |
Result StackPush(Handle<Object> object); |
void StackPop(); |
@@ -107,6 +118,9 @@ class BasicJsonStringifier BASE_EMBEDDED { |
IncrementalStringBuilder builder_; |
Handle<String> tojson_string_; |
Handle<JSArray> stack_; |
+ Handle<String> gap_string_; |
+ uc16* gap_; |
+ int indent_; |
static const int kJsonEscapeTableEntrySize = 8; |
static const char* const JsonEscapeTable; |
@@ -181,11 +195,26 @@ 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) |
- : isolate_(isolate), builder_(isolate) { |
+BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate, Handle<String> gap) |
+ : isolate_(isolate), builder_(isolate), gap_string_(gap), indent_(0) { |
tojson_string_ = factory()->toJSON_string(); |
stack_ = factory()->NewJSArray(8); |
+ int gap_length = gap->length(); |
+ if (gap_length != 0) { |
+ String::Flatten(gap); |
+ 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); |
+ builder_.ChangeEncoding(); |
+ } |
+ gap_[gap_length] = '\0'; |
+ } else { |
+ gap_ = nullptr; |
+ } |
} |
@@ -206,7 +235,8 @@ MaybeHandle<Object> BasicJsonStringifier::StringifyString( |
object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
if (worst_case_length > 32 * KB) { // Slow path if too large. |
- BasicJsonStringifier stringifier(isolate); |
+ BasicJsonStringifier stringifier(isolate, |
+ isolate->factory()->empty_string()); |
return stringifier.Stringify(object); |
} |
@@ -361,11 +391,12 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeGeneric( |
bool deferred_comma, |
bool deferred_key) { |
Handle<JSFunction> fun = isolate_->json_serialize_adapter(); |
- Handle<Object> argv[] = { key, object }; |
+ Handle<Object> indent(Smi::FromInt(indent_), isolate_); |
+ Handle<Object> argv[] = {key, object, indent, gap_string_}; |
Handle<Object> result; |
ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
- isolate_, result, Execution::Call(isolate_, fun, object, 2, argv), |
- EXCEPTION); |
+ isolate_, result, |
+ Execution::Call(isolate_, fun, object, arraysize(argv), argv), EXCEPTION); |
if (result->IsUndefined()) return UNCHANGED; |
if (deferred_key) { |
if (key->IsSmi()) key = factory()->NumberToString(key); |
@@ -436,12 +467,13 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
uint32_t length = 0; |
CHECK(object->length()->ToArrayLength(&length)); |
builder_.AppendCharacter('['); |
+ Indent(); |
switch (object->GetElementsKind()) { |
case FAST_SMI_ELEMENTS: { |
Handle<FixedArray> elements(FixedArray::cast(object->elements()), |
isolate_); |
for (uint32_t i = 0; i < length; i++) { |
- if (i > 0) builder_.AppendCharacter(','); |
+ Separator(i == 0); |
SerializeSmi(Smi::cast(elements->get(i))); |
} |
break; |
@@ -452,7 +484,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
Handle<FixedDoubleArray> elements( |
FixedDoubleArray::cast(object->elements()), isolate_); |
for (uint32_t i = 0; i < length; i++) { |
- if (i > 0) builder_.AppendCharacter(','); |
+ Separator(i == 0); |
SerializeDouble(elements->get_scalar(i)); |
} |
break; |
@@ -466,7 +498,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
if (result != SUCCESS) return result; |
break; |
} |
- if (i > 0) builder_.AppendCharacter(','); |
+ Separator(i == 0); |
Result result = SerializeElement( |
isolate_, |
Handle<Object>(FixedArray::cast(object->elements())->get(i), |
@@ -489,6 +521,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
break; |
} |
} |
+ Unindent(); |
+ if (length > 0) NewLine(); |
builder_.AppendCharacter(']'); |
StackPop(); |
return SUCCESS; |
@@ -498,7 +532,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow( |
Handle<JSArray> object, uint32_t start, uint32_t length) { |
for (uint32_t i = start; i < length; i++) { |
- if (i > 0) builder_.AppendCharacter(','); |
+ Separator(i == 0); |
Handle<Object> element; |
ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
isolate_, element, JSReceiver::GetElement(isolate_, object, i), |
@@ -527,6 +561,7 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
DCHECK(!object->IsJSGlobalProxy() && !object->IsJSGlobalObject()); |
builder_.AppendCharacter('{'); |
+ Indent(); |
bool comma = false; |
if (object->HasFastProperties() && |
@@ -593,7 +628,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( |
if (result == EXCEPTION) return result; |
} |
} |
- |
+ Unindent(); |
+ if (comma) NewLine(); |
builder_.AppendCharacter('}'); |
StackPop(); |
return SUCCESS; |
@@ -661,6 +697,11 @@ bool BasicJsonStringifier::DoNotEscape(uint16_t c) { |
return c >= '#' && c != '\\' && c != 0x7f; |
} |
+void BasicJsonStringifier::NewLine() { |
+ if (gap_ == nullptr) return; |
+ builder_.AppendCharacter('\n'); |
+ for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_); |
+} |
void BasicJsonStringifier::SerializeString(Handle<String> object) { |
object = String::Flatten(object); |