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

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: address comments 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') | no next file with comments »
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->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER &&
564 Indent(); 567 object->HasFastProperties() &&
565 bool comma = false; 568 Handle<JSObject>::cast(object)->elements()->length() == 0) {
566 569 DCHECK(object->IsJSObject());
567 if (object->HasFastProperties() && 570 Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
568 !object->HasIndexedInterceptor() && 571 DCHECK(!js_obj->HasIndexedInterceptor());
569 !object->HasNamedInterceptor() && 572 DCHECK(!js_obj->HasNamedInterceptor());
570 object->elements()->length() == 0) { 573 Handle<Map> map(js_obj->map());
571 Handle<Map> map(object->map()); 574 builder_.AppendCharacter('{');
575 Indent();
576 bool comma = false;
572 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { 577 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
573 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_); 578 Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_);
574 // TODO(rossberg): Should this throw? 579 // TODO(rossberg): Should this throw?
575 if (!name->IsString()) continue; 580 if (!name->IsString()) continue;
576 Handle<String> key = Handle<String>::cast(name); 581 Handle<String> key = Handle<String>::cast(name);
577 PropertyDetails details = map->instance_descriptors()->GetDetails(i); 582 PropertyDetails details = map->instance_descriptors()->GetDetails(i);
578 if (details.IsDontEnum()) continue; 583 if (details.IsDontEnum()) continue;
579 Handle<Object> property; 584 Handle<Object> property;
580 if (details.type() == DATA && *map == object->map()) { 585 if (details.type() == DATA && *map == js_obj->map()) {
581 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); 586 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
582 Isolate* isolate = object->GetIsolate(); 587 if (js_obj->IsUnboxedDoubleField(field_index)) {
583 if (object->IsUnboxedDoubleField(field_index)) { 588 double value = js_obj->RawFastDoublePropertyAt(field_index);
584 double value = object->RawFastDoublePropertyAt(field_index); 589 property = isolate_->factory()->NewHeapNumber(value);
585 property = isolate->factory()->NewHeapNumber(value);
586
587 } else { 590 } else {
588 property = handle(object->RawFastPropertyAt(field_index), isolate); 591 property = handle(js_obj->RawFastPropertyAt(field_index), isolate_);
589 } 592 }
590 } else { 593 } else {
591 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 594 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
592 isolate_, property, 595 isolate_, property, Object::GetPropertyOrElement(js_obj, key),
593 Object::GetPropertyOrElement(object, key),
594 EXCEPTION); 596 EXCEPTION);
595 } 597 }
596 Result result = SerializeProperty(property, comma, key); 598 Result result = SerializeProperty(property, comma, key);
597 if (!comma && result == SUCCESS) comma = true; 599 if (!comma && result == SUCCESS) comma = true;
598 if (result == EXCEPTION) return result; 600 if (result == EXCEPTION) return result;
599 } 601 }
602 Unindent();
603 if (comma) NewLine();
604 builder_.AppendCharacter('}');
600 } else { 605 } else {
601 Handle<FixedArray> contents; 606 Result result = SerializeJSReceiverSlow(object);
602 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 607 if (result != SUCCESS) return result;
603 isolate_, contents, 608 }
604 JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION); 609 StackPop();
610 return SUCCESS;
611 }
605 612
606 for (int i = 0; i < contents->length(); i++) { 613 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSReceiverSlow(
607 Object* key = contents->get(i); 614 Handle<JSReceiver> object) {
608 Handle<String> key_handle; 615 Handle<FixedArray> contents;
609 MaybeHandle<Object> maybe_property; 616 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
610 if (key->IsString()) { 617 isolate_, contents,
611 key_handle = Handle<String>(String::cast(key), isolate_); 618 JSReceiver::GetKeys(object, OWN_ONLY, ENUMERABLE_STRINGS), EXCEPTION);
619
620 builder_.AppendCharacter('{');
621 Indent();
622 bool comma = false;
623 for (int i = 0; i < contents->length(); i++) {
624 Object* key = contents->get(i);
625 Handle<String> key_handle;
626 MaybeHandle<Object> maybe_property;
627 if (key->IsString()) {
628 key_handle = Handle<String>(String::cast(key), isolate_);
629 maybe_property = Object::GetPropertyOrElement(object, key_handle);
630 } else {
631 DCHECK(key->IsNumber());
632 key_handle = factory()->NumberToString(Handle<Object>(key, isolate_));
633 if (key->IsSmi()) {
634 maybe_property =
635 JSReceiver::GetElement(isolate_, object, Smi::cast(key)->value());
636 } else {
612 maybe_property = Object::GetPropertyOrElement(object, key_handle); 637 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 } 638 }
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 } 639 }
640 Handle<Object> property;
641 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, property, maybe_property,
642 EXCEPTION);
643 Result result = SerializeProperty(property, comma, key_handle);
644 if (!comma && result == SUCCESS) comma = true;
645 if (result == EXCEPTION) return result;
630 } 646 }
631 Unindent(); 647 Unindent();
632 if (comma) NewLine(); 648 if (comma) NewLine();
633 builder_.AppendCharacter('}'); 649 builder_.AppendCharacter('}');
650 return SUCCESS;
651 }
652
653 BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSProxy(
654 Handle<JSProxy> object) {
655 Result stack_push = StackPush(object);
656 if (stack_push != SUCCESS) return stack_push;
657 Maybe<bool> is_array = Object::IsArray(object);
658 if (is_array.IsNothing()) return EXCEPTION;
659 if (is_array.FromJust()) {
660 Handle<Object> length_object;
661 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
662 isolate_, length_object,
663 Object::GetLengthFromArrayLike(isolate_, object), EXCEPTION);
664 uint32_t length;
665 if (!length_object->ToUint32(&length)) {
666 // Technically, we need to be able to handle lengths outside the
667 // uint32_t range. However, we would run into string size overflow
668 // if we tried to stringify such an array.
669 isolate_->Throw(*isolate_->factory()->NewInvalidStringLengthError());
670 return EXCEPTION;
671 }
672 builder_.AppendCharacter('[');
673 Indent();
674 Result result = SerializeArrayLikeSlow(object, 0, length);
675 if (result != SUCCESS) return result;
676 Unindent();
677 if (length > 0) NewLine();
678 builder_.AppendCharacter(']');
679 } else {
680 Result result = SerializeJSReceiverSlow(object);
681 if (result != SUCCESS) return result;
682 }
634 StackPop(); 683 StackPop();
635 return SUCCESS; 684 return SUCCESS;
636 } 685 }
637 686
638 687
639 template <typename SrcChar, typename DestChar> 688 template <typename SrcChar, typename DestChar>
640 void BasicJsonStringifier::SerializeStringUnchecked_( 689 void BasicJsonStringifier::SerializeStringUnchecked_(
641 Vector<const SrcChar> src, 690 Vector<const SrcChar> src,
642 IncrementalStringBuilder::NoExtend<DestChar>* dest) { 691 IncrementalStringBuilder::NoExtend<DestChar>* dest) {
643 // Assert that uc16 character is not truncated down to 8 bit. 692 // 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 { 767 } else {
719 SerializeString_<uc16, uc16>(object); 768 SerializeString_<uc16, uc16>(object);
720 } 769 }
721 } 770 }
722 } 771 }
723 772
724 } // namespace internal 773 } // namespace internal
725 } // namespace v8 774 } // namespace v8
726 775
727 #endif // V8_JSON_STRINGIFIER_H_ 776 #endif // V8_JSON_STRINGIFIER_H_
OLDNEW
« no previous file with comments | « src/js/json.js ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698