5 #include "src/json-stringifier.h" 7 #include "src/conversions.h" 8 #include "src/lookup.h" 9 #include "src/message-template.h" 10 #include "src/objects-inl.h" 11 #include "src/objects/js-array-inl.h" 12 #include "src/objects/smi.h" 13 #include "src/string-builder-inl.h" 14 #include "src/utils.h" 30 enum Result { UNCHANGED, SUCCESS, EXCEPTION };
42 return Serialize_<false>(obj,
false, factory()->empty_string());
49 return Serialize_<false>(object,
false,
56 V8_INLINE Result SerializeProperty(
Handle<Object> object,
bool deferred_comma,
58 DCHECK(!deferred_key.is_null());
59 return Serialize_<true>(object, deferred_comma, deferred_key);
62 template <
bool deferred_
string_key>
65 V8_INLINE
void SerializeDeferredKey(
bool deferred_comma,
68 Result SerializeSmi(
Smi object);
70 Result SerializeDouble(
double number);
72 return SerializeDouble(object->value());
87 template <
typename SrcChar,
typename DestChar>
88 V8_INLINE
static void SerializeStringUnchecked_(
92 template <
typename SrcChar,
typename DestChar>
95 template <
typename Char>
96 V8_INLINE
static bool DoNotEscape(Char c);
98 V8_INLINE
void NewLine();
99 V8_INLINE
void Indent() { indent_++; }
100 V8_INLINE
void Unindent() { indent_--; }
101 V8_INLINE
void Separator(
bool first);
109 Factory* factory() {
return isolate_->factory(); }
120 static const int kJsonEscapeTableEntrySize = 8;
121 static const char*
const JsonEscapeTable;
127 return stringifier.Stringify(
object, replacer, gap);
132 const char*
const JsonStringifier::JsonEscapeTable =
133 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 " 134 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 " 135 "\\b\0 \\t\0 \\n\0 \\u000b\0 " 136 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 " 137 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 " 138 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 " 139 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 " 140 "\\u001c\0 \\u001d\0 \\u001e\0 \\u001f\0 " 141 " \0 !\0 \\\"\0 #\0 " 156 "\\\\\0 ]\0 ^\0 _\0 " 164 "|\0 }\0 ~\0 \x7F\0 " 165 "\x80\0 \x81\0 \x82\0 \x83\0 " 166 "\x84\0 \x85\0 \x86\0 \x87\0 " 167 "\x88\0 \x89\0 \x8A\0 \x8B\0 " 168 "\x8C\0 \x8D\0 \x8E\0 \x8F\0 " 169 "\x90\0 \x91\0 \x92\0 \x93\0 " 170 "\x94\0 \x95\0 \x96\0 \x97\0 " 171 "\x98\0 \x99\0 \x9A\0 \x9B\0 " 172 "\x9C\0 \x9D\0 \x9E\0 \x9F\0 " 173 "\xA0\0 \xA1\0 \xA2\0 \xA3\0 " 174 "\xA4\0 \xA5\0 \xA6\0 \xA7\0 " 175 "\xA8\0 \xA9\0 \xAA\0 \xAB\0 " 176 "\xAC\0 \xAD\0 \xAE\0 \xAF\0 " 177 "\xB0\0 \xB1\0 \xB2\0 \xB3\0 " 178 "\xB4\0 \xB5\0 \xB6\0 \xB7\0 " 179 "\xB8\0 \xB9\0 \xBA\0 \xBB\0 " 180 "\xBC\0 \xBD\0 \xBE\0 \xBF\0 " 181 "\xC0\0 \xC1\0 \xC2\0 \xC3\0 " 182 "\xC4\0 \xC5\0 \xC6\0 \xC7\0 " 183 "\xC8\0 \xC9\0 \xCA\0 \xCB\0 " 184 "\xCC\0 \xCD\0 \xCE\0 \xCF\0 " 185 "\xD0\0 \xD1\0 \xD2\0 \xD3\0 " 186 "\xD4\0 \xD5\0 \xD6\0 \xD7\0 " 187 "\xD8\0 \xD9\0 \xDA\0 \xDB\0 " 188 "\xDC\0 \xDD\0 \xDE\0 \xDF\0 " 189 "\xE0\0 \xE1\0 \xE2\0 \xE3\0 " 190 "\xE4\0 \xE5\0 \xE6\0 \xE7\0 " 191 "\xE8\0 \xE9\0 \xEA\0 \xEB\0 " 192 "\xEC\0 \xED\0 \xEE\0 \xEF\0 " 193 "\xF0\0 \xF1\0 \xF2\0 \xF3\0 " 194 "\xF4\0 \xF5\0 \xF6\0 \xF7\0 " 195 "\xF8\0 \xF9\0 \xFA\0 \xFB\0 " 196 "\xFC\0 \xFD\0 \xFE\0 \xFF\0 ";
198 JsonStringifier::JsonStringifier(Isolate* isolate)
199 : isolate_(isolate), builder_(isolate), gap_(nullptr), indent_(0) {
200 tojson_string_ = factory()->toJSON_string();
201 stack_ = factory()->NewJSArray(8);
204 MaybeHandle<Object> JsonStringifier::Stringify(Handle<Object>
object,
205 Handle<Object> replacer,
206 Handle<Object> gap) {
207 if (!InitializeReplacer(replacer))
return MaybeHandle<Object>();
208 if (!gap->IsUndefined(isolate_) && !InitializeGap(gap)) {
209 return MaybeHandle<Object>();
211 Result result = SerializeObject(
object);
212 if (result == UNCHANGED)
return factory()->undefined_value();
213 if (result == SUCCESS)
return builder_.Finish();
214 DCHECK(result == EXCEPTION);
215 return MaybeHandle<Object>();
218 bool JsonStringifier::InitializeReplacer(Handle<Object> replacer) {
219 DCHECK(property_list_.is_null());
220 DCHECK(replacer_function_.is_null());
221 Maybe<bool> is_array = Object::IsArray(replacer);
222 if (is_array.IsNothing())
return false;
223 if (is_array.FromJust()) {
224 HandleScope handle_scope(isolate_);
225 Handle<OrderedHashSet>
set = factory()->NewOrderedHashSet();
226 Handle<Object> length_obj;
227 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
228 isolate_, length_obj,
229 Object::GetLengthFromArrayLike(isolate_,
230 Handle<JSReceiver>::cast(replacer)),
233 if (!length_obj->ToUint32(&length)) length = kMaxUInt32;
235 Handle<Object> element;
237 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
238 isolate_, element, Object::GetElement(isolate_, replacer,
i),
false);
239 if (element->IsNumber() || element->IsString()) {
240 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
241 isolate_, key, Object::ToString(isolate_, element),
false);
242 }
else if (element->IsJSValue()) {
243 Handle<Object> value(Handle<JSValue>::cast(element)->value(), isolate_);
244 if (value->IsNumber() || value->IsString()) {
245 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
246 isolate_, key, Object::ToString(isolate_, element),
false);
249 if (key.is_null())
continue;
251 key = factory()->InternalizeString(key);
252 set = OrderedHashSet::Add(isolate_,
set, key);
254 property_list_ = OrderedHashSet::ConvertToKeysArray(
255 isolate_,
set, GetKeysConversion::kKeepNumbers);
256 property_list_ = handle_scope.CloseAndEscape(property_list_);
257 }
else if (replacer->IsCallable()) {
258 replacer_function_ = Handle<JSReceiver>::cast(replacer);
263 bool JsonStringifier::InitializeGap(Handle<Object> gap) {
265 HandleScope scope(isolate_);
266 if (gap->IsJSValue()) {
267 Handle<Object> value(Handle<JSValue>::cast(gap)->value(), isolate_);
268 if (value->IsString()) {
269 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap,
270 Object::ToString(isolate_, gap),
false);
271 }
else if (value->IsNumber()) {
272 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, gap,
273 Object::ToNumber(isolate_, gap),
false);
277 if (gap->IsString()) {
278 Handle<String> gap_string = Handle<String>::cast(gap);
279 if (gap_string->length() > 0) {
280 int gap_length = std::min(gap_string->length(), 10);
281 gap_ = NewArray<uc16>(gap_length + 1);
282 String::WriteToFlat(*gap_string, gap_, 0, gap_length);
283 for (
int i = 0;
i < gap_length;
i++) {
284 if (gap_[
i] > String::kMaxOneByteCharCode) {
285 builder_.ChangeEncoding();
289 gap_[gap_length] =
'\0';
291 }
else if (gap->IsNumber()) {
292 int num_value = DoubleToInt32(gap->Number());
294 int gap_length = std::min(num_value, 10);
295 gap_ = NewArray<uc16>(gap_length + 1);
296 for (
int i = 0;
i < gap_length;
i++) gap_[
i] =
' ';
297 gap_[gap_length] =
'\0';
303 MaybeHandle<Object> JsonStringifier::ApplyToJsonFunction(Handle<Object>
object,
304 Handle<Object> key) {
305 HandleScope scope(isolate_);
307 Handle<Object> object_for_lookup = object;
308 if (object->IsBigInt()) {
309 ASSIGN_RETURN_ON_EXCEPTION(isolate_, object_for_lookup,
310 Object::ToObject(isolate_,
object), Object);
312 DCHECK(object_for_lookup->IsJSReceiver());
317 LookupIterator it(isolate_, object_for_lookup, tojson_string_,
318 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
319 ASSIGN_RETURN_ON_EXCEPTION(isolate_, fun, Object::GetProperty(&it), Object);
320 if (!fun->IsCallable())
return object;
324 if (key->IsSmi()) key = factory()->NumberToString(key);
325 Handle<Object> argv[] = {key};
326 ASSIGN_RETURN_ON_EXCEPTION(isolate_,
object,
327 Execution::Call(isolate_, fun,
object, 1, argv),
329 return scope.CloseAndEscape(
object);
332 MaybeHandle<Object> JsonStringifier::ApplyReplacerFunction(
333 Handle<Object> value, Handle<Object> key, Handle<Object> initial_holder) {
334 HandleScope scope(isolate_);
335 if (key->IsSmi()) key = factory()->NumberToString(key);
336 Handle<Object> argv[] = {key, value};
337 Handle<JSReceiver> holder = CurrentHolder(value, initial_holder);
338 ASSIGN_RETURN_ON_EXCEPTION(
340 Execution::Call(isolate_, replacer_function_, holder, 2, argv), Object);
341 return scope.CloseAndEscape(value);
344 Handle<JSReceiver> JsonStringifier::CurrentHolder(
345 Handle<Object> value, Handle<Object> initial_holder) {
346 int length = Smi::ToInt(stack_->length());
348 Handle<JSObject> holder =
349 factory()->NewJSObject(isolate_->object_function());
350 JSObject::AddProperty(isolate_, holder, factory()->empty_string(),
351 initial_holder, NONE);
354 FixedArray elements = FixedArray::cast(stack_->elements());
355 return Handle<JSReceiver>(JSReceiver::cast(elements->get(length - 1)),
360 JsonStringifier::Result JsonStringifier::StackPush(Handle<Object>
object) {
361 StackLimitCheck check(isolate_);
362 if (check.HasOverflowed()) {
363 isolate_->StackOverflow();
367 int length = Smi::ToInt(stack_->length());
369 DisallowHeapAllocation no_allocation;
370 FixedArray elements = FixedArray::cast(stack_->elements());
371 for (
int i = 0;
i < length;
i++) {
372 if (elements->get(
i) == *object) {
373 AllowHeapAllocation allow_to_return_error;
374 Handle<Object> error =
375 factory()->NewTypeError(MessageTemplate::kCircularStructure);
376 isolate_->Throw(*error);
381 JSArray::SetLength(stack_, length + 1);
382 FixedArray::cast(stack_->elements())->
set(length, *
object);
386 void JsonStringifier::StackPop() {
387 int length = Smi::ToInt(stack_->length());
388 stack_->set_length(Smi::FromInt(length - 1));
391 template <
bool deferred_
string_key>
392 JsonStringifier::Result JsonStringifier::Serialize_(Handle<Object>
object,
394 Handle<Object> key) {
395 StackLimitCheck interrupt_check(isolate_);
396 Handle<Object> initial_value = object;
397 if (interrupt_check.InterruptRequested() &&
398 isolate_->stack_guard()->HandleInterrupts()->IsException(isolate_)) {
401 if (object->IsJSReceiver() ||
object->IsBigInt()) {
402 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
403 isolate_,
object, ApplyToJsonFunction(
object, key), EXCEPTION);
405 if (!replacer_function_.is_null()) {
406 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
407 isolate_,
object, ApplyReplacerFunction(
object, key, initial_value),
411 if (object->IsSmi()) {
412 if (deferred_string_key) SerializeDeferredKey(comma, key);
413 return SerializeSmi(Smi::cast(*
object));
416 switch (HeapObject::cast(*object)->map()->instance_type()) {
417 case HEAP_NUMBER_TYPE:
418 case MUTABLE_HEAP_NUMBER_TYPE:
419 if (deferred_string_key) SerializeDeferredKey(comma, key);
420 return SerializeHeapNumber(Handle<HeapNumber>::cast(
object));
423 *factory()->NewTypeError(MessageTemplate::kBigIntSerializeJSON));
426 switch (Oddball::cast(*object)->kind()) {
427 case Oddball::kFalse:
428 if (deferred_string_key) SerializeDeferredKey(comma, key);
429 builder_.AppendCString(
"false");
432 if (deferred_string_key) SerializeDeferredKey(comma, key);
433 builder_.AppendCString(
"true");
436 if (deferred_string_key) SerializeDeferredKey(comma, key);
437 builder_.AppendCString(
"null");
443 if (deferred_string_key) SerializeDeferredKey(comma, key);
444 return SerializeJSArray(Handle<JSArray>::cast(
object));
446 if (deferred_string_key) SerializeDeferredKey(comma, key);
447 return SerializeJSValue(Handle<JSValue>::cast(
object));
451 if (object->IsString()) {
452 if (deferred_string_key) SerializeDeferredKey(comma, key);
453 SerializeString(Handle<String>::cast(
object));
456 DCHECK(object->IsJSReceiver());
457 if (object->IsCallable())
return UNCHANGED;
459 if (deferred_string_key) SerializeDeferredKey(comma, key);
460 if (object->IsJSProxy()) {
461 return SerializeJSProxy(Handle<JSProxy>::cast(
object));
463 return SerializeJSObject(Handle<JSObject>::cast(
object));
470 JsonStringifier::Result JsonStringifier::SerializeJSValue(
471 Handle<JSValue>
object) {
472 Object* raw =
object->value();
473 if (raw->IsString()) {
474 Handle<Object> value;
475 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
476 isolate_, value, Object::ToString(isolate_,
object), EXCEPTION);
477 SerializeString(Handle<String>::cast(value));
478 }
else if (raw->IsNumber()) {
479 Handle<Object> value;
480 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
481 isolate_, value, Object::ToNumber(isolate_,
object), EXCEPTION);
482 if (value->IsSmi())
return SerializeSmi(Smi::cast(*value));
483 SerializeHeapNumber(Handle<HeapNumber>::cast(value));
484 }
else if (raw->IsBigInt()) {
486 *factory()->NewTypeError(MessageTemplate::kBigIntSerializeJSON));
488 }
else if (raw->IsBoolean()) {
489 builder_.AppendCString(raw->IsTrue(isolate_) ?
"true" :
"false");
492 return SerializeJSObject(
object);
497 JsonStringifier::Result JsonStringifier::SerializeSmi(Smi
object) {
498 static const int kBufferSize = 100;
499 char chars[kBufferSize];
500 Vector<char> buffer(chars, kBufferSize);
501 builder_.AppendCString(IntToCString(object->value(), buffer));
505 JsonStringifier::Result JsonStringifier::SerializeDouble(
double number) {
506 if (std::isinf(number) || std::isnan(number)) {
507 builder_.AppendCString(
"null");
510 static const int kBufferSize = 100;
511 char chars[kBufferSize];
512 Vector<char> buffer(chars, kBufferSize);
513 builder_.AppendCString(DoubleToCString(number, buffer));
517 JsonStringifier::Result JsonStringifier::SerializeJSArray(
518 Handle<JSArray>
object) {
519 HandleScope handle_scope(isolate_);
520 Result stack_push = StackPush(
object);
521 if (stack_push != SUCCESS)
return stack_push;
523 CHECK(object->length()->ToArrayLength(&length));
524 DCHECK(!object->IsAccessCheckNeeded());
525 builder_.AppendCharacter(
'[');
528 if (replacer_function_.is_null()) {
529 switch (object->GetElementsKind()) {
530 case PACKED_SMI_ELEMENTS: {
531 Handle<FixedArray> elements(FixedArray::cast(object->elements()),
533 StackLimitCheck interrupt_check(isolate_);
535 if (interrupt_check.InterruptRequested() &&
536 isolate_->stack_guard()->HandleInterrupts()->IsException(
541 SerializeSmi(Smi::cast(elements->get(
i)));
546 case PACKED_DOUBLE_ELEMENTS: {
548 if (length == 0)
break;
549 Handle<FixedDoubleArray> elements(
550 FixedDoubleArray::cast(object->elements()), isolate_);
551 StackLimitCheck interrupt_check(isolate_);
553 if (interrupt_check.InterruptRequested() &&
554 isolate_->stack_guard()->HandleInterrupts()->IsException(
559 SerializeDouble(elements->get_scalar(
i));
564 case PACKED_ELEMENTS: {
565 Handle<Object> old_length(object->length(), isolate_);
567 if (object->length() != *old_length ||
568 object->GetElementsKind() != PACKED_ELEMENTS) {
573 Result result = SerializeElement(
575 Handle<Object>(FixedArray::cast(object->elements())->
get(
i),
578 if (result == UNCHANGED) {
579 builder_.AppendCString(
"null");
580 }
else if (result != SUCCESS) {
595 Result result = SerializeArrayLikeSlow(
object,
i, length);
596 if (result != SUCCESS)
return result;
599 if (length > 0) NewLine();
600 builder_.AppendCharacter(
']');
605 JsonStringifier::Result JsonStringifier::SerializeArrayLikeSlow(
608 static const int kMaxSerializableArrayLength = String::kMaxLength / 2;
609 if (length > kMaxSerializableArrayLength) {
610 isolate_->Throw(*isolate_->factory()->NewInvalidStringLengthError());
615 Handle<Object> element;
616 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
617 isolate_, element, JSReceiver::GetElement(isolate_,
object,
i),
619 Result result = SerializeElement(isolate_, element,
i);
620 if (result == SUCCESS)
continue;
621 if (result == UNCHANGED) {
623 if (builder_.HasOverflowed())
return EXCEPTION;
624 builder_.AppendCString(
"null");
632 JsonStringifier::Result JsonStringifier::SerializeJSObject(
633 Handle<JSObject>
object) {
634 HandleScope handle_scope(isolate_);
635 Result stack_push = StackPush(
object);
636 if (stack_push != SUCCESS)
return stack_push;
638 if (property_list_.is_null() &&
639 !
object->map()->IsCustomElementsReceiverMap() &&
640 object->HasFastProperties() &&
object->elements()->length() == 0) {
641 DCHECK(!object->IsJSGlobalProxy());
642 DCHECK(!object->HasIndexedInterceptor());
643 DCHECK(!object->HasNamedInterceptor());
644 Handle<Map> map(object->map(), isolate_);
645 builder_.AppendCharacter(
'{');
648 for (
int i = 0;
i < map->NumberOfOwnDescriptors();
i++) {
649 Handle<Name> name(map->instance_descriptors()->GetKey(
i), isolate_);
651 if (!name->IsString())
continue;
652 Handle<String> key = Handle<String>::cast(name);
653 PropertyDetails details = map->instance_descriptors()->GetDetails(
i);
654 if (details.IsDontEnum())
continue;
655 Handle<Object> property;
656 if (details.location() == kField && *map ==
object->map()) {
657 DCHECK_EQ(kData, details.kind());
658 FieldIndex field_index = FieldIndex::ForDescriptor(*map,
i);
659 property = JSObject::FastPropertyAt(
object, details.representation(),
662 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
664 Object::GetPropertyOrElement(isolate_,
object, key), EXCEPTION);
666 Result result = SerializeProperty(property, comma, key);
667 if (!comma && result == SUCCESS) comma =
true;
668 if (result == EXCEPTION)
return result;
671 if (comma) NewLine();
672 builder_.AppendCharacter(
'}');
674 Result result = SerializeJSReceiverSlow(
object);
675 if (result != SUCCESS)
return result;
681 JsonStringifier::Result JsonStringifier::SerializeJSReceiverSlow(
682 Handle<JSReceiver>
object) {
683 Handle<FixedArray> contents = property_list_;
684 if (contents.is_null()) {
685 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
687 KeyAccumulator::GetKeys(
object, KeyCollectionMode::kOwnOnly,
689 GetKeysConversion::kConvertToString),
692 builder_.AppendCharacter(
'{');
695 for (
int i = 0;
i < contents->length();
i++) {
696 Handle<String> key(String::cast(contents->get(
i)), isolate_);
697 Handle<Object> property;
698 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
699 isolate_, property, Object::GetPropertyOrElement(isolate_,
object, key),
701 Result result = SerializeProperty(property, comma, key);
702 if (!comma && result == SUCCESS) comma =
true;
703 if (result == EXCEPTION)
return result;
706 if (comma) NewLine();
707 builder_.AppendCharacter(
'}');
711 JsonStringifier::Result JsonStringifier::SerializeJSProxy(
712 Handle<JSProxy>
object) {
713 HandleScope scope(isolate_);
714 Result stack_push = StackPush(
object);
715 if (stack_push != SUCCESS)
return stack_push;
716 Maybe<bool> is_array = Object::IsArray(
object);
717 if (is_array.IsNothing())
return EXCEPTION;
718 if (is_array.FromJust()) {
719 Handle<Object> length_object;
720 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
721 isolate_, length_object,
722 Object::GetLengthFromArrayLike(isolate_,
723 Handle<JSReceiver>::cast(
object)),
726 if (!length_object->ToUint32(&length)) {
730 isolate_->Throw(*isolate_->factory()->NewInvalidStringLengthError());
733 builder_.AppendCharacter(
'[');
735 Result result = SerializeArrayLikeSlow(
object, 0, length);
736 if (result != SUCCESS)
return result;
738 if (length > 0) NewLine();
739 builder_.AppendCharacter(
']');
741 Result result = SerializeJSReceiverSlow(
object);
742 if (result != SUCCESS)
return result;
748 template <
typename SrcChar,
typename DestChar>
749 void JsonStringifier::SerializeStringUnchecked_(
750 Vector<const SrcChar> src,
751 IncrementalStringBuilder::NoExtend<DestChar>* dest) {
754 DCHECK(
sizeof(DestChar) >=
sizeof(SrcChar));
755 for (
int i = 0;
i < src.length();
i++) {
757 if (DoNotEscape(c)) {
759 }
else if (FLAG_harmony_json_stringify && c >= 0xD800 && c <= 0xDFFF) {
763 if (
i + 1 < src.length()) {
765 SrcChar next = src[
i + 1];
766 if (next >= 0xDC00 && next <= 0xDFFF) {
775 dest->AppendCString(
"\\u");
776 char*
const hex = DoubleToRadixCString(c, 16);
777 dest->AppendCString(hex);
783 dest->AppendCString(
"\\u");
784 char*
const hex = DoubleToRadixCString(c, 16);
785 dest->AppendCString(hex);
793 dest->AppendCString(
"\\u");
794 char*
const hex = DoubleToRadixCString(c, 16);
795 dest->AppendCString(hex);
799 dest->AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
804 template <
typename SrcChar,
typename DestChar>
805 void JsonStringifier::SerializeString_(Handle<String>
string) {
806 int length =
string->length();
807 builder_.Append<uint8_t, DestChar>(
'"');
810 if (
int worst_case_length = builder_.EscapedLengthIfCurrentPartFits(length)) {
811 DisallowHeapAllocation no_gc;
812 Vector<const SrcChar> vector =
string->GetCharVector<SrcChar>();
813 IncrementalStringBuilder::NoExtendBuilder<DestChar> no_extend(
814 &builder_, worst_case_length);
815 SerializeStringUnchecked_(vector, &no_extend);
817 FlatStringReader reader(isolate_,
string);
818 for (
int i = 0;
i < reader.length();
i++) {
819 SrcChar c = reader.Get<SrcChar>(
i);
820 if (DoNotEscape(c)) {
821 builder_.Append<SrcChar, DestChar>(c);
822 }
else if (FLAG_harmony_json_stringify && c >= 0xD800 && c <= 0xDFFF) {
826 if (
i + 1 < reader.length()) {
828 SrcChar next = reader.Get<SrcChar>(
i + 1);
829 if (next >= 0xDC00 && next <= 0xDFFF) {
832 builder_.Append<SrcChar, DestChar>(c);
833 builder_.Append<SrcChar, DestChar>(next);
838 builder_.AppendCString(
"\\u");
839 char*
const hex = DoubleToRadixCString(c, 16);
840 builder_.AppendCString(hex);
846 builder_.AppendCString(
"\\u");
847 char*
const hex = DoubleToRadixCString(c, 16);
848 builder_.AppendCString(hex);
856 builder_.AppendCString(
"\\u");
857 char*
const hex = DoubleToRadixCString(c, 16);
858 builder_.AppendCString(hex);
862 builder_.AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
866 builder_.Append<uint8_t, DestChar>(
'"');
870 bool JsonStringifier::DoNotEscape(uint8_t c) {
872 return c >= 0x23 && c <= 0x7E && c != 0x5C;
876 bool JsonStringifier::DoNotEscape(uint16_t c) {
878 return c >= 0x23 && c != 0x5C && c != 0x7F &&
879 (!FLAG_harmony_json_stringify || (c < 0xD800 || c > 0xDFFF));
882 void JsonStringifier::NewLine() {
883 if (gap_ ==
nullptr)
return;
884 builder_.AppendCharacter(
'\n');
885 for (
int i = 0;
i < indent_;
i++) builder_.AppendCString(gap_);
888 void JsonStringifier::Separator(
bool first) {
889 if (!first) builder_.AppendCharacter(
',');
893 void JsonStringifier::SerializeDeferredKey(
bool deferred_comma,
894 Handle<Object> deferred_key) {
895 Separator(!deferred_comma);
896 SerializeString(Handle<String>::cast(deferred_key));
897 builder_.AppendCharacter(
':');
898 if (gap_ !=
nullptr) builder_.AppendCharacter(
' ');
901 void JsonStringifier::SerializeString(Handle<String>
object) {
902 object = String::Flatten(isolate_,
object);
903 if (builder_.CurrentEncoding() == String::ONE_BYTE_ENCODING) {
904 if (object->IsOneByteRepresentationUnderneath()) {
905 SerializeString_<uint8_t, uint8_t>(object);
907 builder_.ChangeEncoding();
908 SerializeString(
object);
911 if (object->IsOneByteRepresentationUnderneath()) {
912 SerializeString_<uint8_t, uc16>(object);
914 SerializeString_<uc16, uc16>(object);