Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: src/json-stringifier.h

Issue 1994183002: [json] handle proxies in BasicJsonSerializer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase onto indent CL Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/js/json.js ('k') | src/objects.h » ('j') | src/objects.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 #ifndef V8_JSON_STRINGIFIER_H_
6 #define V8_JSON_STRINGIFIER_H_ 6 #define V8_JSON_STRINGIFIER_H_
7 7
8 #include "src/conversions.h" 8 #include "src/conversions.h"
9 #include "src/lookup.h" 9 #include "src/lookup.h"
10 #include "src/messages.h" 10 #include "src/messages.h"
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 Result SerializeDouble(double number); 78 Result SerializeDouble(double number);
79 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) { 79 INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) {
80 return SerializeDouble(object->value()); 80 return SerializeDouble(object->value());
81 } 81 }
82 82
83 Result SerializeJSValue(Handle<JSValue> object); 83 Result SerializeJSValue(Handle<JSValue> object);
84 84
85 INLINE(Result SerializeJSArray(Handle<JSArray> object)); 85 INLINE(Result SerializeJSArray(Handle<JSArray> object));
86 INLINE(Result SerializeJSObject(Handle<JSObject> object)); 86 INLINE(Result SerializeJSObject(Handle<JSObject> object));
87 87
88 Result SerializeJSArraySlow(Handle<JSArray> object, uint32_t start, 88 Result SerializeJSProxy(Handle<JSProxy> object);
89 uint32_t length); 89 Result SerializeJSReceiverSlow(Handle<JSReceiver> object);
90 Result SerializeArrayLikeSlow(Handle<JSReceiver> object, uint32_t start,
91 uint32_t length);
90 92
91 void SerializeString(Handle<String> object); 93 void SerializeString(Handle<String> object);
92 94
93 template <typename SrcChar, typename DestChar> 95 template <typename SrcChar, typename DestChar>
94 INLINE(static void SerializeStringUnchecked_( 96 INLINE(static void SerializeStringUnchecked_(
95 Vector<const SrcChar> src, 97 Vector<const SrcChar> src,
96 IncrementalStringBuilder::NoExtend<DestChar>* dest)); 98 IncrementalStringBuilder::NoExtend<DestChar>* dest));
97 99
98 template <typename SrcChar, typename DestChar> 100 template <typename SrcChar, typename DestChar>
99 INLINE(void SerializeString_(Handle<String> string)); 101 INLINE(void SerializeString_(Handle<String> string));
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 321
320 void BasicJsonStringifier::StackPop() { 322 void BasicJsonStringifier::StackPop() {
321 int length = Smi::cast(stack_->length())->value(); 323 int length = Smi::cast(stack_->length())->value();
322 stack_->set_length(Smi::FromInt(length - 1)); 324 stack_->set_length(Smi::FromInt(length - 1));
323 } 325 }
324 326
325 327
326 template <bool deferred_string_key> 328 template <bool deferred_string_key>
327 BasicJsonStringifier::Result BasicJsonStringifier::Serialize_( 329 BasicJsonStringifier::Result BasicJsonStringifier::Serialize_(
328 Handle<Object> object, bool comma, Handle<Object> key) { 330 Handle<Object> object, bool comma, Handle<Object> key) {
329 if (object->IsJSObject()) { 331 if (object->IsJSReceiver()) {
330 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 332 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
331 isolate_, object, 333 isolate_, object,
332 ApplyToJsonFunction(object, key), 334 ApplyToJsonFunction(object, key),
333 EXCEPTION); 335 EXCEPTION);
334 } 336 }
335 337
336 if (object->IsSmi()) { 338 if (object->IsSmi()) {
337 if (deferred_string_key) SerializeDeferredKey(comma, key); 339 if (deferred_string_key) SerializeDeferredKey(comma, key);
338 return SerializeSmi(Smi::cast(*object)); 340 return SerializeSmi(Smi::cast(*object));
339 } 341 }
(...skipping 25 matching lines...) Expand all
365 if (deferred_string_key) SerializeDeferredKey(comma, key); 367 if (deferred_string_key) SerializeDeferredKey(comma, key);
366 return SerializeJSArray(Handle<JSArray>::cast(object)); 368 return SerializeJSArray(Handle<JSArray>::cast(object));
367 case JS_VALUE_TYPE: 369 case JS_VALUE_TYPE:
368 if (deferred_string_key) SerializeDeferredKey(comma, key); 370 if (deferred_string_key) SerializeDeferredKey(comma, key);
369 return SerializeJSValue(Handle<JSValue>::cast(object)); 371 return SerializeJSValue(Handle<JSValue>::cast(object));
370 default: 372 default:
371 if (object->IsString()) { 373 if (object->IsString()) {
372 if (deferred_string_key) SerializeDeferredKey(comma, key); 374 if (deferred_string_key) SerializeDeferredKey(comma, key);
373 SerializeString(Handle<String>::cast(object)); 375 SerializeString(Handle<String>::cast(object));
374 return SUCCESS; 376 return SUCCESS;
375 } else if (object->IsJSObject()) { 377 } else if (object->IsJSReceiver()) {
376 if (object->IsCallable()) return UNCHANGED; 378 if (object->IsCallable()) return UNCHANGED;
377 // Go to slow path for global proxy and objects requiring access checks. 379 // Go to slow path for global proxy and objects requiring access checks.
378 if (object->IsAccessCheckNeeded() || object->IsJSGlobalProxy()) break; 380 if (object->IsAccessCheckNeeded() || object->IsJSGlobalProxy()) break;
379 if (deferred_string_key) SerializeDeferredKey(comma, key); 381 if (deferred_string_key) SerializeDeferredKey(comma, key);
382 if (object->IsJSProxy()) {
383 return SerializeJSProxy(Handle<JSProxy>::cast(object));
384 }
380 return SerializeJSObject(Handle<JSObject>::cast(object)); 385 return SerializeJSObject(Handle<JSObject>::cast(object));
381 } 386 }
382 } 387 }
383 388
384 return SerializeGeneric(object, key, comma, deferred_string_key); 389 return SerializeGeneric(object, key, comma, deferred_string_key);
385 } 390 }
386 391
387 392
388 BasicJsonStringifier::Result BasicJsonStringifier::SerializeGeneric( 393 BasicJsonStringifier::Result BasicJsonStringifier::SerializeGeneric(
389 Handle<Object> object, 394 Handle<Object> object,
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 Separator(i == 0); 492 Separator(i == 0);
488 SerializeDouble(elements->get_scalar(i)); 493 SerializeDouble(elements->get_scalar(i));
489 } 494 }
490 break; 495 break;
491 } 496 }
492 case FAST_ELEMENTS: { 497 case FAST_ELEMENTS: {
493 Handle<Object> old_length(object->length(), isolate_); 498 Handle<Object> old_length(object->length(), isolate_);
494 for (uint32_t i = 0; i < length; i++) { 499 for (uint32_t i = 0; i < length; i++) {
495 if (object->length() != *old_length || 500 if (object->length() != *old_length ||
496 object->GetElementsKind() != FAST_ELEMENTS) { 501 object->GetElementsKind() != FAST_ELEMENTS) {
497 Result result = SerializeJSArraySlow(object, i, length); 502 Result result = SerializeArrayLikeSlow(object, i, length);
498 if (result != SUCCESS) return result; 503 if (result != SUCCESS) return result;
499 break; 504 break;
500 } 505 }
501 Separator(i == 0); 506 Separator(i == 0);
502 Result result = SerializeElement( 507 Result result = SerializeElement(
503 isolate_, 508 isolate_,
504 Handle<Object>(FixedArray::cast(object->elements())->get(i), 509 Handle<Object>(FixedArray::cast(object->elements())->get(i),
505 isolate_), 510 isolate_),
506 i); 511 i);
507 if (result == SUCCESS) continue; 512 if (result == SUCCESS) continue;
508 if (result == UNCHANGED) { 513 if (result == UNCHANGED) {
509 builder_.AppendCString("null"); 514 builder_.AppendCString("null");
510 } else { 515 } else {
511 return result; 516 return result;
512 } 517 }
513 } 518 }
514 break; 519 break;
515 } 520 }
516 // The FAST_HOLEY_* cases could be handled in a faster way. They resemble 521 // The FAST_HOLEY_* cases could be handled in a faster way. They resemble
517 // the non-holey cases except that a lookup is necessary for holes. 522 // the non-holey cases except that a lookup is necessary for holes.
518 default: { 523 default: {
519 Result result = SerializeJSArraySlow(object, 0, length); 524 Result result = SerializeArrayLikeSlow(object, 0, length);
520 if (result != SUCCESS) return result; 525 if (result != SUCCESS) return result;
521 break; 526 break;
522 } 527 }
523 } 528 }
524 Unindent(); 529 Unindent();
525 if (length > 0) NewLine(); 530 if (length > 0) NewLine();
526 builder_.AppendCharacter(']'); 531 builder_.AppendCharacter(']');
527 StackPop(); 532 StackPop();
528 return SUCCESS; 533 return SUCCESS;
529 } 534 }
530 535
531 536 BasicJsonStringifier::Result BasicJsonStringifier::SerializeArrayLikeSlow(
532 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSArraySlow( 537 Handle<JSReceiver> object, uint32_t start, uint32_t length) {
533 Handle<JSArray> object, uint32_t start, uint32_t length) {
534 for (uint32_t i = start; i < length; i++) { 538 for (uint32_t i = start; i < length; i++) {
535 Separator(i == 0); 539 Separator(i == 0);
536 Handle<Object> element; 540 Handle<Object> element;
537 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 541 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
538 isolate_, element, JSReceiver::GetElement(isolate_, object, i), 542 isolate_, element, JSReceiver::GetElement(isolate_, object, i),
539 EXCEPTION); 543 EXCEPTION);
540 if (element->IsUndefined()) { 544 if (element->IsUndefined()) {
541 builder_.AppendCString("null"); 545 builder_.AppendCString("null");
542 } else { 546 } else {
543 Result result = SerializeElement(isolate_, element, i); 547 Result result = SerializeElement(isolate_, element, i);
544 if (result == SUCCESS) continue; 548 if (result == SUCCESS) continue;
545 if (result == UNCHANGED) { 549 if (result == UNCHANGED) {
546 builder_.AppendCString("null"); 550 builder_.AppendCString("null");
547 } else { 551 } else {
548 return result; 552 return result;
549 } 553 }
550 } 554 }
551 } 555 }
552 return SUCCESS; 556 return SUCCESS;
553 } 557 }
554 558
555
556 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject( 559 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSObject(
557 Handle<JSObject> object) { 560 Handle<JSObject> object) {
558 HandleScope handle_scope(isolate_); 561 HandleScope handle_scope(isolate_);
559 Result stack_push = StackPush(object); 562 Result stack_push = StackPush(object);
560 if (stack_push != SUCCESS) return stack_push; 563 if (stack_push != SUCCESS) return stack_push;
561 DCHECK(!object->IsJSGlobalProxy() && !object->IsJSGlobalObject()); 564 DCHECK(!object->IsJSGlobalProxy() && !object->IsJSGlobalObject());
562 565
563 builder_.AppendCharacter('{'); 566 if (object->IsJSObject() && object->HasFastProperties() &&
564 Indent(); 567 !Handle<JSObject>::cast(object)->HasIndexedInterceptor() &&
565 bool comma = false; 568 !Handle<JSObject>::cast(object)->HasNamedInterceptor() &&
Camillo Bruni 2016/05/20 09:55:55 You can simplify parts of the check to: map->inst
Yang 2016/05/20 12:47:18 Done. Thanks for the tip. We take the slow path w
566 569 Handle<JSObject>::cast(object)->elements()->length() == 0) {
567 if (object->HasFastProperties() && 570 Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
568 !object->HasIndexedInterceptor() && 571 Handle<Map> map(js_obj->map());
569 !object->HasNamedInterceptor() && 572 builder_.AppendCharacter('{');
570 object->elements()->length() == 0) { 573 Indent();
571 Handle<Map> map(object->map()); 574 bool comma = false;
572 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { 575 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
573 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_); 576 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_);
574 // TODO(rossberg): Should this throw? 577 // TODO(rossberg): Should this throw?
575 if (!name->IsString()) continue; 578 if (!name->IsString()) continue;
576 Handle<String> key = Handle<String>::cast(name); 579 Handle<String> key = Handle<String>::cast(name);
577 PropertyDetails details = map->instance_descriptors()->GetDetails(i); 580 PropertyDetails details = map->instance_descriptors()->GetDetails(i);
578 if (details.IsDontEnum()) continue; 581 if (details.IsDontEnum()) continue;
579 Handle<Object> property; 582 Handle<Object> property;
580 if (details.type() == DATA && *map == object->map()) { 583 if (details.type() == DATA && *map == js_obj->map()) {
581 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); 584 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
582 Isolate* isolate = object->GetIsolate(); 585 if (js_obj->IsUnboxedDoubleField(field_index)) {
583 if (object->IsUnboxedDoubleField(field_index)) { 586 double value = js_obj->RawFastDoublePropertyAt(field_index);
584 double value = object->RawFastDoublePropertyAt(field_index); 587 property = isolate_->factory()->NewHeapNumber(value);
585 property = isolate->factory()->NewHeapNumber(value);
586
587 } else { 588 } else {
588 property = handle(object->RawFastPropertyAt(field_index), isolate); 589 property = handle(js_obj->RawFastPropertyAt(field_index), isolate_);
589 } 590 }
590 } else { 591 } else {
591 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 592 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
592 isolate_, property, 593 isolate_, property, Object::GetPropertyOrElement(js_obj, key),
593 Object::GetPropertyOrElement(object, key),
594 EXCEPTION); 594 EXCEPTION);
595 } 595 }
596 Result result = SerializeProperty(property, comma, key); 596 Result result = SerializeProperty(property, comma, key);
597 if (!comma && result == SUCCESS) comma = true; 597 if (!comma && result == SUCCESS) comma = true;
598 if (result == EXCEPTION) return result; 598 if (result == EXCEPTION) return result;
599 } 599 }
600 Unindent();
601 if (comma) NewLine();
602 builder_.AppendCharacter('}');
600 } else { 603 } else {
601 Handle<FixedArray> contents; 604 Result result = SerializeJSReceiverSlow(object);
602 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 605 if (result != SUCCESS) return result;
603 isolate_, contents, 606 }
604 JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION); 607 StackPop();
608 return SUCCESS;
609 }
605 610
606 for (int i = 0; i < contents->length(); i++) { 611 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSReceiverSlow(
607 Object* key = contents->get(i); 612 Handle<JSReceiver> object) {
608 Handle<String> key_handle; 613 Handle<FixedArray> contents;
609 MaybeHandle<Object> maybe_property; 614 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
610 if (key->IsString()) { 615 isolate_, contents,
611 key_handle = Handle<String>(String::cast(key), isolate_); 616 JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION);
617
618 builder_.AppendCharacter('{');
619 Indent();
620 bool comma = false;
621 for (int i = 0; i < contents->length(); i++) {
622 Object* key = contents->get(i);
623 Handle<String> key_handle;
624 MaybeHandle<Object> maybe_property;
625 if (key->IsString()) {
626 key_handle = Handle<String>(String::cast(key), isolate_);
627 maybe_property = Object::GetPropertyOrElement(object, key_handle);
628 } else {
629 DCHECK(key->IsNumber());
630 key_handle = factory()->NumberToString(Handle<Object>(key, isolate_));
631 if (key->IsSmi()) {
632 maybe_property =
633 JSReceiver::GetElement(isolate_, object, Smi::cast(key)->value());
634 } else {
612 maybe_property = Object::GetPropertyOrElement(object, key_handle); 635 maybe_property = Object::GetPropertyOrElement(object, key_handle);
613 } else {
614 DCHECK(key->IsNumber());
615 key_handle = factory()->NumberToString(Handle<Object>(key, isolate_));
616 if (key->IsSmi()) {
617 maybe_property =
618 JSReceiver::GetElement(isolate_, object, Smi::cast(key)->value());
619 } else {
620 maybe_property = Object::GetPropertyOrElement(object, key_handle);
621 }
622 } 636 }
623 Handle<Object> property;
624 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
625 isolate_, property, maybe_property, EXCEPTION);
626 Result result = SerializeProperty(property, comma, key_handle);
627 if (!comma && result == SUCCESS) comma = true;
628 if (result == EXCEPTION) return result;
629 } 637 }
638 Handle<Object> property;
639 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, property, maybe_property,
640 EXCEPTION);
641 Result result = SerializeProperty(property, comma, key_handle);
642 if (!comma && result == SUCCESS) comma = true;
643 if (result == EXCEPTION) return result;
630 } 644 }
631 Unindent(); 645 Unindent();
632 if (comma) NewLine(); 646 if (comma) NewLine();
633 builder_.AppendCharacter('}'); 647 builder_.AppendCharacter('}');
648 return SUCCESS;
649 }
650
651 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSProxy(
652 Handle<JSProxy> object) {
653 Result stack_push = StackPush(object);
654 if (stack_push != SUCCESS) return stack_push;
655 Maybe<bool> is_array = Object::IsArray(object);
656 if (is_array.IsNothing()) return EXCEPTION;
657 if (is_array.FromJust()) {
658 Handle<Object> length_object;
659 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
660 isolate_, length_object,
661 Object::GetLengthFromArrayLike(isolate_, object), EXCEPTION);
662 uint32_t length;
663 if (!length_object->ToUint32(&length)) {
664 // Technically, we need to be able to handle lengths outside the
665 // uint32_t range. However, we would run into string size overflow
666 // if we tried to stringify such an array.
667 isolate_->Throw(*isolate_->factory()->NewInvalidStringLengthError());
668 return EXCEPTION;
669 }
670 builder_.AppendCharacter('[');
671 Indent();
672 Result result = SerializeArrayLikeSlow(object, 0, length);
673 if (result != SUCCESS) return result;
674 Unindent();
675 if (length > 0) NewLine();
676 builder_.AppendCharacter(']');
677 } else {
678 Result result = SerializeJSReceiverSlow(object);
679 if (result != SUCCESS) return result;
680 }
634 StackPop(); 681 StackPop();
635 return SUCCESS; 682 return SUCCESS;
636 } 683 }
637 684
638 685
639 template <typename SrcChar, typename DestChar> 686 template <typename SrcChar, typename DestChar>
640 void BasicJsonStringifier::SerializeStringUnchecked_( 687 void BasicJsonStringifier::SerializeStringUnchecked_(
641 Vector<const SrcChar> src, 688 Vector<const SrcChar> src,
642 IncrementalStringBuilder::NoExtend<DestChar>* dest) { 689 IncrementalStringBuilder::NoExtend<DestChar>* dest) {
643 // Assert that uc16 character is not truncated down to 8 bit. 690 // Assert that uc16 character is not truncated down to 8 bit.
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 } else { 765 } else {
719 SerializeString_<uc16, uc16>(object); 766 SerializeString_<uc16, uc16>(object);
720 } 767 }
721 } 768 }
722 } 769 }
723 770
724 } // namespace internal 771 } // namespace internal
725 } // namespace v8 772 } // namespace v8
726 773
727 #endif // V8_JSON_STRINGIFIER_H_ 774 #endif // V8_JSON_STRINGIFIER_H_
OLDNEW
« no previous file with comments | « src/js/json.js ('k') | src/objects.h » ('j') | src/objects.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698