| OLD | NEW |
| 1 // Copyright 2012 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 #ifndef V8_JSON_STRINGIFIER_H_ | 5 #include "src/json-stringifier.h" |
| 6 #define V8_JSON_STRINGIFIER_H_ | |
| 7 | 6 |
| 8 #include "src/conversions.h" | 7 #include "src/conversions.h" |
| 9 #include "src/lookup.h" | 8 #include "src/lookup.h" |
| 10 #include "src/messages.h" | 9 #include "src/messages.h" |
| 11 #include "src/string-builder.h" | 10 #include "src/objects-inl.h" |
| 12 #include "src/utils.h" | 11 #include "src/utils.h" |
| 13 | 12 |
| 14 namespace v8 { | 13 namespace v8 { |
| 15 namespace internal { | 14 namespace internal { |
| 16 | 15 |
| 17 class BasicJsonStringifier BASE_EMBEDDED { | |
| 18 public: | |
| 19 BasicJsonStringifier(Isolate* isolate, Handle<String> gap); | |
| 20 | |
| 21 ~BasicJsonStringifier() { DeleteArray(gap_); } | |
| 22 | |
| 23 MUST_USE_RESULT MaybeHandle<Object> Stringify(Handle<Object> object); | |
| 24 | |
| 25 MUST_USE_RESULT INLINE(static MaybeHandle<Object> StringifyString( | |
| 26 Isolate* isolate, | |
| 27 Handle<String> object)); | |
| 28 | |
| 29 private: | |
| 30 enum Result { UNCHANGED, SUCCESS, EXCEPTION }; | |
| 31 | |
| 32 MUST_USE_RESULT MaybeHandle<Object> ApplyToJsonFunction( | |
| 33 Handle<Object> object, | |
| 34 Handle<Object> key); | |
| 35 | |
| 36 // Entry point to serialize the object. | |
| 37 INLINE(Result SerializeObject(Handle<Object> obj)) { | |
| 38 return Serialize_<false>(obj, false, factory()->empty_string()); | |
| 39 } | |
| 40 | |
| 41 // Serialize an array element. | |
| 42 // The index may serve as argument for the toJSON function. | |
| 43 INLINE(Result SerializeElement(Isolate* isolate, | |
| 44 Handle<Object> object, | |
| 45 int i)) { | |
| 46 return Serialize_<false>(object, | |
| 47 false, | |
| 48 Handle<Object>(Smi::FromInt(i), isolate)); | |
| 49 } | |
| 50 | |
| 51 // Serialize a object property. | |
| 52 // The key may or may not be serialized depending on the property. | |
| 53 // The key may also serve as argument for the toJSON function. | |
| 54 INLINE(Result SerializeProperty(Handle<Object> object, | |
| 55 bool deferred_comma, | |
| 56 Handle<String> deferred_key)) { | |
| 57 DCHECK(!deferred_key.is_null()); | |
| 58 return Serialize_<true>(object, deferred_comma, deferred_key); | |
| 59 } | |
| 60 | |
| 61 template <bool deferred_string_key> | |
| 62 Result Serialize_(Handle<Object> object, bool comma, Handle<Object> key); | |
| 63 | |
| 64 void SerializeDeferredKey(bool deferred_comma, Handle<Object> deferred_key) { | |
| 65 Separator(!deferred_comma); | |
| 66 SerializeString(Handle<String>::cast(deferred_key)); | |
| 67 builder_.AppendCharacter(':'); | |
| 68 if (gap_ != nullptr) builder_.AppendCharacter(' '); | |
| 69 } | |
| 70 | |
| 71 Result SerializeSmi(Smi* object); | |
| 72 | |
| 73 Result SerializeDouble(double number); | |
| 74 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) { | |
| 75 return SerializeDouble(object->value()); | |
| 76 } | |
| 77 | |
| 78 Result SerializeJSValue(Handle<JSValue> object); | |
| 79 | |
| 80 INLINE(Result SerializeJSArray(Handle<JSArray> object)); | |
| 81 INLINE(Result SerializeJSObject(Handle<JSObject> object)); | |
| 82 | |
| 83 Result SerializeJSProxy(Handle<JSProxy> object); | |
| 84 Result SerializeJSReceiverSlow(Handle<JSReceiver> object); | |
| 85 Result SerializeArrayLikeSlow(Handle<JSReceiver> object, uint32_t start, | |
| 86 uint32_t length); | |
| 87 | |
| 88 void SerializeString(Handle<String> object); | |
| 89 | |
| 90 template <typename SrcChar, typename DestChar> | |
| 91 INLINE(static void SerializeStringUnchecked_( | |
| 92 Vector<const SrcChar> src, | |
| 93 IncrementalStringBuilder::NoExtend<DestChar>* dest)); | |
| 94 | |
| 95 template <typename SrcChar, typename DestChar> | |
| 96 INLINE(void SerializeString_(Handle<String> string)); | |
| 97 | |
| 98 template <typename Char> | |
| 99 INLINE(static bool DoNotEscape(Char c)); | |
| 100 | |
| 101 INLINE(void NewLine()); | |
| 102 INLINE(void Indent() { indent_++; }); | |
| 103 INLINE(void Unindent() { indent_--; }); | |
| 104 INLINE(void Separator(bool first) { | |
| 105 if (!first) builder_.AppendCharacter(','); | |
| 106 NewLine(); | |
| 107 }) | |
| 108 | |
| 109 Result StackPush(Handle<Object> object); | |
| 110 void StackPop(); | |
| 111 | |
| 112 Factory* factory() { return isolate_->factory(); } | |
| 113 | |
| 114 Isolate* isolate_; | |
| 115 IncrementalStringBuilder builder_; | |
| 116 Handle<String> tojson_string_; | |
| 117 Handle<JSArray> stack_; | |
| 118 Handle<String> gap_string_; | |
| 119 uc16* gap_; | |
| 120 int indent_; | |
| 121 | |
| 122 static const int kJsonEscapeTableEntrySize = 8; | |
| 123 static const char* const JsonEscapeTable; | |
| 124 }; | |
| 125 | |
| 126 | |
| 127 // Translation table to escape Latin1 characters. | 16 // Translation table to escape Latin1 characters. |
| 128 // Table entries start at a multiple of 8 and are null-terminated. | 17 // Table entries start at a multiple of 8 and are null-terminated. |
| 129 const char* const BasicJsonStringifier::JsonEscapeTable = | 18 const char* const BasicJsonStringifier::JsonEscapeTable = |
| 130 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " | 19 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " |
| 131 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 " | 20 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 " |
| 132 "\\b\0 \\t\0 \\n\0 \\u000b\0 " | 21 "\\b\0 \\t\0 \\n\0 \\u000b\0 " |
| 133 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 " | 22 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 " |
| 134 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 " | 23 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 " |
| 135 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 " | 24 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 " |
| 136 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 " | 25 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 " |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 CopyChars(gap_, flat.ToOneByteVector().start(), gap_length); | 96 CopyChars(gap_, flat.ToOneByteVector().start(), gap_length); |
| 208 } else { | 97 } else { |
| 209 CopyChars(gap_, flat.ToUC16Vector().start(), gap_length); | 98 CopyChars(gap_, flat.ToUC16Vector().start(), gap_length); |
| 210 } | 99 } |
| 211 gap_[gap_length] = '\0'; | 100 gap_[gap_length] = '\0'; |
| 212 } else { | 101 } else { |
| 213 gap_ = nullptr; | 102 gap_ = nullptr; |
| 214 } | 103 } |
| 215 } | 104 } |
| 216 | 105 |
| 217 | |
| 218 MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) { | 106 MaybeHandle<Object> BasicJsonStringifier::Stringify(Handle<Object> object) { |
| 219 Result result = SerializeObject(object); | 107 Result result = SerializeObject(object); |
| 220 if (result == UNCHANGED) return factory()->undefined_value(); | 108 if (result == UNCHANGED) return factory()->undefined_value(); |
| 221 if (result == SUCCESS) return builder_.Finish(); | 109 if (result == SUCCESS) return builder_.Finish(); |
| 222 DCHECK(result == EXCEPTION); | 110 DCHECK(result == EXCEPTION); |
| 223 return MaybeHandle<Object>(); | 111 return MaybeHandle<Object>(); |
| 224 } | 112 } |
| 225 | 113 |
| 226 | |
| 227 MaybeHandle<Object> BasicJsonStringifier::StringifyString( | 114 MaybeHandle<Object> BasicJsonStringifier::StringifyString( |
| 228 Isolate* isolate, Handle<String> object) { | 115 Isolate* isolate, Handle<String> object) { |
| 229 static const int kJsonQuoteWorstCaseBlowup = 6; | 116 static const int kJsonQuoteWorstCaseBlowup = 6; |
| 230 static const int kSpaceForQuotes = 2; | 117 static const int kSpaceForQuotes = 2; |
| 231 int worst_case_length = | 118 int worst_case_length = |
| 232 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | 119 object->length() * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; |
| 233 | 120 |
| 234 if (worst_case_length > 32 * KB) { // Slow path if too large. | 121 if (worst_case_length > 32 * KB) { // Slow path if too large. |
| 235 BasicJsonStringifier stringifier(isolate, | 122 BasicJsonStringifier stringifier(isolate, |
| 236 isolate->factory()->empty_string()); | 123 isolate->factory()->empty_string()); |
| 237 return stringifier.Stringify(object); | 124 return stringifier.Stringify(object); |
| 238 } | 125 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 258 IncrementalStringBuilder::NoExtendString<uc16> no_extend(result, | 145 IncrementalStringBuilder::NoExtendString<uc16> no_extend(result, |
| 259 worst_case_length); | 146 worst_case_length); |
| 260 no_extend.Append('\"'); | 147 no_extend.Append('\"'); |
| 261 SerializeStringUnchecked_(object->GetFlatContent().ToUC16Vector(), | 148 SerializeStringUnchecked_(object->GetFlatContent().ToUC16Vector(), |
| 262 &no_extend); | 149 &no_extend); |
| 263 no_extend.Append('\"'); | 150 no_extend.Append('\"'); |
| 264 return no_extend.Finalize(); | 151 return no_extend.Finalize(); |
| 265 } | 152 } |
| 266 } | 153 } |
| 267 | 154 |
| 268 | |
| 269 MaybeHandle<Object> BasicJsonStringifier::ApplyToJsonFunction( | 155 MaybeHandle<Object> BasicJsonStringifier::ApplyToJsonFunction( |
| 270 Handle<Object> object, Handle<Object> key) { | 156 Handle<Object> object, Handle<Object> key) { |
| 271 LookupIterator it(object, tojson_string_, | 157 LookupIterator it(object, tojson_string_, |
| 272 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); | 158 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); |
| 273 Handle<Object> fun; | 159 Handle<Object> fun; |
| 274 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object); | 160 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object); |
| 275 if (!fun->IsCallable()) return object; | 161 if (!fun->IsCallable()) return object; |
| 276 | 162 |
| 277 // Call toJSON function. | 163 // Call toJSON function. |
| 278 if (key->IsSmi()) key = factory()->NumberToString(key); | 164 if (key->IsSmi()) key = factory()->NumberToString(key); |
| 279 Handle<Object> argv[] = { key }; | 165 Handle<Object> argv[] = {key}; |
| 280 HandleScope scope(isolate_); | 166 HandleScope scope(isolate_); |
| 281 ASSIGN_RETURN_ON_EXCEPTION( | 167 ASSIGN_RETURN_ON_EXCEPTION(isolate_, object, |
| 282 isolate_, object, | 168 Execution::Call(isolate_, fun, object, 1, argv), |
| 283 Execution::Call(isolate_, fun, object, 1, argv), | 169 Object); |
| 284 Object); | |
| 285 return scope.CloseAndEscape(object); | 170 return scope.CloseAndEscape(object); |
| 286 } | 171 } |
| 287 | 172 |
| 288 | |
| 289 BasicJsonStringifier::Result BasicJsonStringifier::StackPush( | 173 BasicJsonStringifier::Result BasicJsonStringifier::StackPush( |
| 290 Handle<Object> object) { | 174 Handle<Object> object) { |
| 291 StackLimitCheck check(isolate_); | 175 StackLimitCheck check(isolate_); |
| 292 if (check.HasOverflowed()) { | 176 if (check.HasOverflowed()) { |
| 293 isolate_->StackOverflow(); | 177 isolate_->StackOverflow(); |
| 294 return EXCEPTION; | 178 return EXCEPTION; |
| 295 } | 179 } |
| 296 | 180 |
| 297 int length = Smi::cast(stack_->length())->value(); | 181 int length = Smi::cast(stack_->length())->value(); |
| 298 { | 182 { |
| 299 DisallowHeapAllocation no_allocation; | 183 DisallowHeapAllocation no_allocation; |
| 300 FixedArray* elements = FixedArray::cast(stack_->elements()); | 184 FixedArray* elements = FixedArray::cast(stack_->elements()); |
| 301 for (int i = 0; i < length; i++) { | 185 for (int i = 0; i < length; i++) { |
| 302 if (elements->get(i) == *object) { | 186 if (elements->get(i) == *object) { |
| 303 AllowHeapAllocation allow_to_return_error; | 187 AllowHeapAllocation allow_to_return_error; |
| 304 Handle<Object> error = | 188 Handle<Object> error = |
| 305 factory()->NewTypeError(MessageTemplate::kCircularStructure); | 189 factory()->NewTypeError(MessageTemplate::kCircularStructure); |
| 306 isolate_->Throw(*error); | 190 isolate_->Throw(*error); |
| 307 return EXCEPTION; | 191 return EXCEPTION; |
| 308 } | 192 } |
| 309 } | 193 } |
| 310 } | 194 } |
| 311 JSArray::SetLength(stack_, length + 1); | 195 JSArray::SetLength(stack_, length + 1); |
| 312 FixedArray::cast(stack_->elements())->set(length, *object); | 196 FixedArray::cast(stack_->elements())->set(length, *object); |
| 313 return SUCCESS; | 197 return SUCCESS; |
| 314 } | 198 } |
| 315 | 199 |
| 316 | |
| 317 void BasicJsonStringifier::StackPop() { | 200 void BasicJsonStringifier::StackPop() { |
| 318 int length = Smi::cast(stack_->length())->value(); | 201 int length = Smi::cast(stack_->length())->value(); |
| 319 stack_->set_length(Smi::FromInt(length - 1)); | 202 stack_->set_length(Smi::FromInt(length - 1)); |
| 320 } | 203 } |
| 321 | 204 |
| 322 | |
| 323 template <bool deferred_string_key> | 205 template <bool deferred_string_key> |
| 324 BasicJsonStringifier::Result BasicJsonStringifier::Serialize_( | 206 BasicJsonStringifier::Result BasicJsonStringifier::Serialize_( |
| 325 Handle<Object> object, bool comma, Handle<Object> key) { | 207 Handle<Object> object, bool comma, Handle<Object> key) { |
| 326 if (object->IsJSReceiver()) { | 208 if (object->IsJSReceiver()) { |
| 327 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 209 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 328 isolate_, object, | 210 isolate_, object, ApplyToJsonFunction(object, key), EXCEPTION); |
| 329 ApplyToJsonFunction(object, key), | |
| 330 EXCEPTION); | |
| 331 } | 211 } |
| 332 | 212 |
| 333 if (object->IsSmi()) { | 213 if (object->IsSmi()) { |
| 334 if (deferred_string_key) SerializeDeferredKey(comma, key); | 214 if (deferred_string_key) SerializeDeferredKey(comma, key); |
| 335 return SerializeSmi(Smi::cast(*object)); | 215 return SerializeSmi(Smi::cast(*object)); |
| 336 } | 216 } |
| 337 | 217 |
| 338 switch (HeapObject::cast(*object)->map()->instance_type()) { | 218 switch (HeapObject::cast(*object)->map()->instance_type()) { |
| 339 case HEAP_NUMBER_TYPE: | 219 case HEAP_NUMBER_TYPE: |
| 340 case MUTABLE_HEAP_NUMBER_TYPE: | 220 case MUTABLE_HEAP_NUMBER_TYPE: |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 return SerializeJSProxy(Handle<JSProxy>::cast(object)); | 260 return SerializeJSProxy(Handle<JSProxy>::cast(object)); |
| 381 } | 261 } |
| 382 return SerializeJSObject(Handle<JSObject>::cast(object)); | 262 return SerializeJSObject(Handle<JSObject>::cast(object)); |
| 383 } | 263 } |
| 384 } | 264 } |
| 385 | 265 |
| 386 UNREACHABLE(); | 266 UNREACHABLE(); |
| 387 return UNCHANGED; | 267 return UNCHANGED; |
| 388 } | 268 } |
| 389 | 269 |
| 390 | |
| 391 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue( | 270 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue( |
| 392 Handle<JSValue> object) { | 271 Handle<JSValue> object) { |
| 393 String* class_name = object->class_name(); | 272 String* class_name = object->class_name(); |
| 394 if (class_name == isolate_->heap()->String_string()) { | 273 if (class_name == isolate_->heap()->String_string()) { |
| 395 Handle<Object> value; | 274 Handle<Object> value; |
| 396 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 275 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 397 isolate_, value, Object::ToString(isolate_, object), EXCEPTION); | 276 isolate_, value, Object::ToString(isolate_, object), EXCEPTION); |
| 398 SerializeString(Handle<String>::cast(value)); | 277 SerializeString(Handle<String>::cast(value)); |
| 399 } else if (class_name == isolate_->heap()->Number_string()) { | 278 } else if (class_name == isolate_->heap()->Number_string()) { |
| 400 Handle<Object> value; | 279 Handle<Object> value; |
| 401 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object), | 280 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object), |
| 402 EXCEPTION); | 281 EXCEPTION); |
| 403 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); | 282 if (value->IsSmi()) return SerializeSmi(Smi::cast(*value)); |
| 404 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); | 283 SerializeHeapNumber(Handle<HeapNumber>::cast(value)); |
| 405 } else if (class_name == isolate_->heap()->Boolean_string()) { | 284 } else if (class_name == isolate_->heap()->Boolean_string()) { |
| 406 Object* value = JSValue::cast(*object)->value(); | 285 Object* value = JSValue::cast(*object)->value(); |
| 407 DCHECK(value->IsBoolean()); | 286 DCHECK(value->IsBoolean()); |
| 408 builder_.AppendCString(value->IsTrue() ? "true" : "false"); | 287 builder_.AppendCString(value->IsTrue() ? "true" : "false"); |
| 409 } else { | 288 } else { |
| 410 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject. | 289 // ES6 24.3.2.1 step 10.c, serialize as an ordinary JSObject. |
| 411 return SerializeJSObject(object); | 290 return SerializeJSObject(object); |
| 412 } | 291 } |
| 413 return SUCCESS; | 292 return SUCCESS; |
| 414 } | 293 } |
| 415 | 294 |
| 416 | |
| 417 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { | 295 BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi* object) { |
| 418 static const int kBufferSize = 100; | 296 static const int kBufferSize = 100; |
| 419 char chars[kBufferSize]; | 297 char chars[kBufferSize]; |
| 420 Vector<char> buffer(chars, kBufferSize); | 298 Vector<char> buffer(chars, kBufferSize); |
| 421 builder_.AppendCString(IntToCString(object->value(), buffer)); | 299 builder_.AppendCString(IntToCString(object->value(), buffer)); |
| 422 return SUCCESS; | 300 return SUCCESS; |
| 423 } | 301 } |
| 424 | 302 |
| 425 | |
| 426 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( | 303 BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble( |
| 427 double number) { | 304 double number) { |
| 428 if (std::isinf(number) || std::isnan(number)) { | 305 if (std::isinf(number) || std::isnan(number)) { |
| 429 builder_.AppendCString("null"); | 306 builder_.AppendCString("null"); |
| 430 return SUCCESS; | 307 return SUCCESS; |
| 431 } | 308 } |
| 432 static const int kBufferSize = 100; | 309 static const int kBufferSize = 100; |
| 433 char chars[kBufferSize]; | 310 char chars[kBufferSize]; |
| 434 Vector<char> buffer(chars, kBufferSize); | 311 Vector<char> buffer(chars, kBufferSize); |
| 435 builder_.AppendCString(DoubleToCString(number, buffer)); | 312 builder_.AppendCString(DoubleToCString(number, buffer)); |
| 436 return SUCCESS; | 313 return SUCCESS; |
| 437 } | 314 } |
| 438 | 315 |
| 439 | |
| 440 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( | 316 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArray( |
| 441 Handle<JSArray> object) { | 317 Handle<JSArray> object) { |
| 442 HandleScope handle_scope(isolate_); | 318 HandleScope handle_scope(isolate_); |
| 443 Result stack_push = StackPush(object); | 319 Result stack_push = StackPush(object); |
| 444 if (stack_push != SUCCESS) return stack_push; | 320 if (stack_push != SUCCESS) return stack_push; |
| 445 uint32_t length = 0; | 321 uint32_t length = 0; |
| 446 CHECK(object->length()->ToArrayLength(&length)); | 322 CHECK(object->length()->ToArrayLength(&length)); |
| 447 DCHECK(!object->IsAccessCheckNeeded()); | 323 DCHECK(!object->IsAccessCheckNeeded()); |
| 448 builder_.AppendCharacter('['); | 324 builder_.AppendCharacter('['); |
| 449 Indent(); | 325 Indent(); |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 if (length > 0) NewLine(); | 527 if (length > 0) NewLine(); |
| 652 builder_.AppendCharacter(']'); | 528 builder_.AppendCharacter(']'); |
| 653 } else { | 529 } else { |
| 654 Result result = SerializeJSReceiverSlow(object); | 530 Result result = SerializeJSReceiverSlow(object); |
| 655 if (result != SUCCESS) return result; | 531 if (result != SUCCESS) return result; |
| 656 } | 532 } |
| 657 StackPop(); | 533 StackPop(); |
| 658 return SUCCESS; | 534 return SUCCESS; |
| 659 } | 535 } |
| 660 | 536 |
| 661 | |
| 662 template <typename SrcChar, typename DestChar> | 537 template <typename SrcChar, typename DestChar> |
| 663 void BasicJsonStringifier::SerializeStringUnchecked_( | 538 void BasicJsonStringifier::SerializeStringUnchecked_( |
| 664 Vector<const SrcChar> src, | 539 Vector<const SrcChar> src, |
| 665 IncrementalStringBuilder::NoExtend<DestChar>* dest) { | 540 IncrementalStringBuilder::NoExtend<DestChar>* dest) { |
| 666 // Assert that uc16 character is not truncated down to 8 bit. | 541 // Assert that uc16 character is not truncated down to 8 bit. |
| 667 // The <uc16, char> version of this method must not be called. | 542 // The <uc16, char> version of this method must not be called. |
| 668 DCHECK(sizeof(DestChar) >= sizeof(SrcChar)); | 543 DCHECK(sizeof(DestChar) >= sizeof(SrcChar)); |
| 669 | 544 |
| 670 for (int i = 0; i < src.length(); i++) { | 545 for (int i = 0; i < src.length(); i++) { |
| 671 SrcChar c = src[i]; | 546 SrcChar c = src[i]; |
| 672 if (DoNotEscape(c)) { | 547 if (DoNotEscape(c)) { |
| 673 dest->Append(c); | 548 dest->Append(c); |
| 674 } else { | 549 } else { |
| 675 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); | 550 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
| 676 } | 551 } |
| 677 } | 552 } |
| 678 } | 553 } |
| 679 | 554 |
| 680 | |
| 681 template <typename SrcChar, typename DestChar> | 555 template <typename SrcChar, typename DestChar> |
| 682 void BasicJsonStringifier::SerializeString_(Handle<String> string) { | 556 void BasicJsonStringifier::SerializeString_(Handle<String> string) { |
| 683 int length = string->length(); | 557 int length = string->length(); |
| 684 builder_.Append<uint8_t, DestChar>('"'); | 558 builder_.Append<uint8_t, DestChar>('"'); |
| 685 // We make a rough estimate to find out if the current string can be | 559 // We make a rough estimate to find out if the current string can be |
| 686 // serialized without allocating a new string part. The worst case length of | 560 // serialized without allocating a new string part. The worst case length of |
| 687 // an escaped character is 6. Shifting the remainin string length right by 3 | 561 // an escaped character is 6. Shifting the remainin string length right by 3 |
| 688 // is a more pessimistic estimate, but faster to calculate. | 562 // is a more pessimistic estimate, but faster to calculate. |
| 689 int worst_case_length = length << 3; | 563 int worst_case_length = length << 3; |
| 690 if (builder_.CurrentPartCanFit(worst_case_length)) { | 564 if (builder_.CurrentPartCanFit(worst_case_length)) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 701 builder_.Append<SrcChar, DestChar>(c); | 575 builder_.Append<SrcChar, DestChar>(c); |
| 702 } else { | 576 } else { |
| 703 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); | 577 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]); |
| 704 } | 578 } |
| 705 } | 579 } |
| 706 } | 580 } |
| 707 | 581 |
| 708 builder_.Append<uint8_t, DestChar>('"'); | 582 builder_.Append<uint8_t, DestChar>('"'); |
| 709 } | 583 } |
| 710 | 584 |
| 711 | |
| 712 template <> | 585 template <> |
| 713 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { | 586 bool BasicJsonStringifier::DoNotEscape(uint8_t c) { |
| 714 return c >= '#' && c <= '~' && c != '\\'; | 587 return c >= '#' && c <= '~' && c != '\\'; |
| 715 } | 588 } |
| 716 | 589 |
| 717 | |
| 718 template <> | 590 template <> |
| 719 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { | 591 bool BasicJsonStringifier::DoNotEscape(uint16_t c) { |
| 720 return c >= '#' && c != '\\' && c != 0x7f; | 592 return c >= '#' && c != '\\' && c != 0x7f; |
| 721 } | 593 } |
| 722 | 594 |
| 723 void BasicJsonStringifier::NewLine() { | 595 void BasicJsonStringifier::NewLine() { |
| 724 if (gap_ == nullptr) return; | 596 if (gap_ == nullptr) return; |
| 725 builder_.AppendCharacter('\n'); | 597 builder_.AppendCharacter('\n'); |
| 726 for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_); | 598 for (int i = 0; i < indent_; i++) builder_.AppendCString(gap_); |
| 727 } | 599 } |
| 728 | 600 |
| 601 void BasicJsonStringifier::Separator(bool first) { |
| 602 if (!first) builder_.AppendCharacter(','); |
| 603 NewLine(); |
| 604 } |
| 605 |
| 606 void BasicJsonStringifier::SerializeDeferredKey(bool deferred_comma, |
| 607 Handle<Object> deferred_key) { |
| 608 Separator(!deferred_comma); |
| 609 SerializeString(Handle<String>::cast(deferred_key)); |
| 610 builder_.AppendCharacter(':'); |
| 611 if (gap_ != nullptr) builder_.AppendCharacter(' '); |
| 612 } |
| 613 |
| 729 void BasicJsonStringifier::SerializeString(Handle<String> object) { | 614 void BasicJsonStringifier::SerializeString(Handle<String> object) { |
| 730 object = String::Flatten(object); | 615 object = String::Flatten(object); |
| 731 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { | 616 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) { |
| 732 if (object->IsOneByteRepresentationUnderneath()) { | 617 if (object->IsOneByteRepresentationUnderneath()) { |
| 733 SerializeString_<uint8_t, uint8_t>(object); | 618 SerializeString_<uint8_t, uint8_t>(object); |
| 734 } else { | 619 } else { |
| 735 builder_.ChangeEncoding(); | 620 builder_.ChangeEncoding(); |
| 736 SerializeString(object); | 621 SerializeString(object); |
| 737 } | 622 } |
| 738 } else { | 623 } else { |
| 739 if (object->IsOneByteRepresentationUnderneath()) { | 624 if (object->IsOneByteRepresentationUnderneath()) { |
| 740 SerializeString_<uint8_t, uc16>(object); | 625 SerializeString_<uint8_t, uc16>(object); |
| 741 } else { | 626 } else { |
| 742 SerializeString_<uc16, uc16>(object); | 627 SerializeString_<uc16, uc16>(object); |
| 743 } | 628 } |
| 744 } | 629 } |
| 745 } | 630 } |
| 746 | 631 |
| 747 } // namespace internal | 632 } // namespace internal |
| 748 } // namespace v8 | 633 } // namespace v8 |
| 749 | |
| 750 #endif // V8_JSON_STRINGIFIER_H_ | |
| OLD | NEW |