OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 #include "src/messages.h" | 5 #include "src/messages.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/execution.h" | 10 #include "src/execution.h" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 | 94 |
95 // Turn the exception on the message into a string if it is an object. | 95 // Turn the exception on the message into a string if it is an object. |
96 if (message->argument()->IsJSObject()) { | 96 if (message->argument()->IsJSObject()) { |
97 HandleScope scope(isolate); | 97 HandleScope scope(isolate); |
98 Handle<Object> argument(message->argument(), isolate); | 98 Handle<Object> argument(message->argument(), isolate); |
99 | 99 |
100 MaybeHandle<Object> maybe_stringified; | 100 MaybeHandle<Object> maybe_stringified; |
101 Handle<Object> stringified; | 101 Handle<Object> stringified; |
102 // Make sure we don't leak uncaught internally generated Error objects. | 102 // Make sure we don't leak uncaught internally generated Error objects. |
103 if (argument->IsJSError()) { | 103 if (argument->IsJSError()) { |
104 Handle<Object> args[] = {argument}; | 104 maybe_stringified = Object::NoSideEffectsToString(isolate, argument); |
105 maybe_stringified = Execution::TryCall( | |
106 isolate, isolate->no_side_effects_to_string_fun(), | |
107 isolate->factory()->undefined_value(), arraysize(args), args); | |
108 } else { | 105 } else { |
109 v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate)); | 106 v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate)); |
110 catcher.SetVerbose(false); | 107 catcher.SetVerbose(false); |
111 catcher.SetCaptureMessage(false); | 108 catcher.SetCaptureMessage(false); |
112 | 109 |
113 maybe_stringified = Object::ToString(isolate, argument); | 110 maybe_stringified = Object::ToString(isolate, argument); |
114 } | 111 } |
115 | 112 |
116 if (!maybe_stringified.ToHandle(&stringified)) { | 113 if (!maybe_stringified.ToHandle(&stringified)) { |
117 stringified = isolate->factory()->NewStringFromAsciiChecked("exception"); | 114 stringified = isolate->factory()->NewStringFromAsciiChecked("exception"); |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 } | 660 } |
664 } | 661 } |
665 | 662 |
666 RETURN_RESULT(isolate, builder.Finish(), Object); | 663 RETURN_RESULT(isolate, builder.Finish(), Object); |
667 } | 664 } |
668 | 665 |
669 Handle<String> MessageTemplate::FormatMessage(Isolate* isolate, | 666 Handle<String> MessageTemplate::FormatMessage(Isolate* isolate, |
670 int template_index, | 667 int template_index, |
671 Handle<Object> arg) { | 668 Handle<Object> arg) { |
672 Factory* factory = isolate->factory(); | 669 Factory* factory = isolate->factory(); |
673 Handle<String> result_string; | 670 Handle<String> result_string = Object::NoSideEffectsToString(isolate, arg); |
674 if (arg->IsString()) { | |
675 result_string = Handle<String>::cast(arg); | |
676 } else { | |
677 Handle<JSFunction> fun = isolate->no_side_effects_to_string_fun(); | |
678 | |
679 MaybeHandle<Object> maybe_result = | |
680 Execution::TryCall(isolate, fun, factory->undefined_value(), 1, &arg); | |
681 Handle<Object> result; | |
682 if (!maybe_result.ToHandle(&result) || !result->IsString()) { | |
683 return factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("<error>")); | |
684 } | |
685 result_string = Handle<String>::cast(result); | |
686 } | |
687 MaybeHandle<String> maybe_result_string = MessageTemplate::FormatMessage( | 671 MaybeHandle<String> maybe_result_string = MessageTemplate::FormatMessage( |
688 template_index, result_string, factory->empty_string(), | 672 template_index, result_string, factory->empty_string(), |
689 factory->empty_string()); | 673 factory->empty_string()); |
690 if (!maybe_result_string.ToHandle(&result_string)) { | 674 if (!maybe_result_string.ToHandle(&result_string)) { |
691 return factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("<error>")); | 675 return factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("<error>")); |
692 } | 676 } |
693 // A string that has been obtained from JS code in this way is | 677 // A string that has been obtained from JS code in this way is |
694 // likely to be a complicated ConsString of some sort. We flatten it | 678 // likely to be a complicated ConsString of some sort. We flatten it |
695 // here to improve the efficiency of converting it to a C string and | 679 // here to improve the efficiency of converting it to a C string and |
696 // other operations that are likely to take place (see GetLocalizedMessage | 680 // other operations that are likely to take place (see GetLocalizedMessage |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 } else { | 726 } else { |
743 builder.AppendCharacter(*c); | 727 builder.AppendCharacter(*c); |
744 } | 728 } |
745 } | 729 } |
746 | 730 |
747 return builder.Finish(); | 731 return builder.Finish(); |
748 } | 732 } |
749 | 733 |
750 MaybeHandle<Object> ErrorUtils::Construct( | 734 MaybeHandle<Object> ErrorUtils::Construct( |
751 Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target, | 735 Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target, |
752 Handle<Object> message, FrameSkipMode mode, bool suppress_detailed_trace) { | 736 Handle<Object> message, FrameSkipMode mode, Handle<Object> caller, |
| 737 bool suppress_detailed_trace) { |
753 // 1. If NewTarget is undefined, let newTarget be the active function object, | 738 // 1. If NewTarget is undefined, let newTarget be the active function object, |
754 // else let newTarget be NewTarget. | 739 // else let newTarget be NewTarget. |
755 | 740 |
756 Handle<JSReceiver> new_target_recv = | 741 Handle<JSReceiver> new_target_recv = |
757 new_target->IsJSReceiver() ? Handle<JSReceiver>::cast(new_target) | 742 new_target->IsJSReceiver() ? Handle<JSReceiver>::cast(new_target) |
758 : Handle<JSReceiver>::cast(target); | 743 : Handle<JSReceiver>::cast(target); |
759 | 744 |
760 // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%ErrorPrototype%", | 745 // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%ErrorPrototype%", |
761 // « [[ErrorData]] »). | 746 // « [[ErrorData]] »). |
762 Handle<JSObject> err; | 747 Handle<JSObject> err; |
(...skipping 16 matching lines...) Expand all Loading... |
779 msg_string, DONT_ENUM), | 764 msg_string, DONT_ENUM), |
780 Object); | 765 Object); |
781 } | 766 } |
782 | 767 |
783 // Optionally capture a more detailed stack trace for the message. | 768 // Optionally capture a more detailed stack trace for the message. |
784 if (!suppress_detailed_trace) { | 769 if (!suppress_detailed_trace) { |
785 RETURN_ON_EXCEPTION(isolate, isolate->CaptureAndSetDetailedStackTrace(err), | 770 RETURN_ON_EXCEPTION(isolate, isolate->CaptureAndSetDetailedStackTrace(err), |
786 Object); | 771 Object); |
787 } | 772 } |
788 | 773 |
789 // When we're passed a JSFunction as new target, we can skip frames until that | |
790 // specific function is seen instead of unconditionally skipping the first | |
791 // frame. | |
792 Handle<Object> caller; | |
793 if (mode == SKIP_FIRST && new_target->IsJSFunction()) { | |
794 mode = SKIP_UNTIL_SEEN; | |
795 caller = new_target; | |
796 } | |
797 | |
798 // Capture a simple stack trace for the stack property. | 774 // Capture a simple stack trace for the stack property. |
799 RETURN_ON_EXCEPTION(isolate, | 775 RETURN_ON_EXCEPTION(isolate, |
800 isolate->CaptureAndSetSimpleStackTrace(err, mode, caller), | 776 isolate->CaptureAndSetSimpleStackTrace(err, mode, caller), |
801 Object); | 777 Object); |
802 | 778 |
803 return err; | 779 return err; |
804 } | 780 } |
805 | 781 |
806 namespace { | 782 namespace { |
807 | 783 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 IncrementalStringBuilder builder(isolate); | 847 IncrementalStringBuilder builder(isolate); |
872 builder.AppendString(name); | 848 builder.AppendString(name); |
873 builder.AppendCString(": "); | 849 builder.AppendCString(": "); |
874 builder.AppendString(msg); | 850 builder.AppendString(msg); |
875 | 851 |
876 Handle<String> result; | 852 Handle<String> result; |
877 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String); | 853 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String); |
878 return result; | 854 return result; |
879 } | 855 } |
880 | 856 |
| 857 namespace { |
| 858 |
| 859 Handle<String> FormatMessage(Isolate* isolate, int template_index, |
| 860 Handle<Object> arg0, Handle<Object> arg1, |
| 861 Handle<Object> arg2) { |
| 862 Handle<String> arg0_str = Object::NoSideEffectsToString(isolate, arg0); |
| 863 Handle<String> arg1_str = Object::NoSideEffectsToString(isolate, arg1); |
| 864 Handle<String> arg2_str = Object::NoSideEffectsToString(isolate, arg2); |
| 865 |
| 866 isolate->native_context()->IncrementErrorsThrown(); |
| 867 |
| 868 Handle<String> msg; |
| 869 if (!MessageTemplate::FormatMessage(template_index, arg0_str, arg1_str, |
| 870 arg2_str) |
| 871 .ToHandle(&msg)) { |
| 872 DCHECK(isolate->has_pending_exception()); |
| 873 isolate->clear_pending_exception(); |
| 874 return isolate->factory()->NewStringFromAsciiChecked("<error>"); |
| 875 } |
| 876 |
| 877 return msg; |
| 878 } |
| 879 |
| 880 } // namespace |
| 881 |
| 882 // static |
| 883 MaybeHandle<Object> ErrorUtils::MakeGenericError( |
| 884 Isolate* isolate, Handle<JSFunction> constructor, int template_index, |
| 885 Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2, |
| 886 FrameSkipMode mode) { |
| 887 // This function used to be implemented in JavaScript, and JSEntryStub clears |
| 888 // any pending exceptions - so whenever we'd call this from C++, pending |
| 889 // exceptions would be cleared. Preserve this behavior. |
| 890 isolate->clear_pending_exception(); |
| 891 |
| 892 DCHECK(mode != SKIP_UNTIL_SEEN); |
| 893 |
| 894 Handle<Object> no_caller; |
| 895 Handle<String> msg = FormatMessage(isolate, template_index, arg0, arg1, arg2); |
| 896 return ErrorUtils::Construct(isolate, constructor, constructor, msg, mode, |
| 897 no_caller, false); |
| 898 } |
| 899 |
881 #define SET_CALLSITE_PROPERTY(target, key, value) \ | 900 #define SET_CALLSITE_PROPERTY(target, key, value) \ |
882 RETURN_ON_EXCEPTION( \ | 901 RETURN_ON_EXCEPTION( \ |
883 isolate, JSObject::SetOwnPropertyIgnoreAttributes( \ | 902 isolate, JSObject::SetOwnPropertyIgnoreAttributes( \ |
884 target, isolate->factory()->key(), value, DONT_ENUM), \ | 903 target, isolate->factory()->key(), value, DONT_ENUM), \ |
885 Object) | 904 Object) |
886 | 905 |
887 MaybeHandle<Object> CallSiteUtils::Construct(Isolate* isolate, | 906 MaybeHandle<Object> CallSiteUtils::Construct(Isolate* isolate, |
888 Handle<Object> receiver, | 907 Handle<Object> receiver, |
889 Handle<Object> fun, | 908 Handle<Object> fun, |
890 Handle<Object> pos, | 909 Handle<Object> pos, |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 builder.AppendCString(" ("); | 1177 builder.AppendCString(" ("); |
1159 RETURN_ON_EXCEPTION( | 1178 RETURN_ON_EXCEPTION( |
1160 isolate, AppendFileLocation(isolate, recv, &call_site, &builder), String); | 1179 isolate, AppendFileLocation(isolate, recv, &call_site, &builder), String); |
1161 builder.AppendCString(")"); | 1180 builder.AppendCString(")"); |
1162 | 1181 |
1163 RETURN_RESULT(isolate, builder.Finish(), String); | 1182 RETURN_RESULT(isolate, builder.Finish(), String); |
1164 } | 1183 } |
1165 | 1184 |
1166 } // namespace internal | 1185 } // namespace internal |
1167 } // namespace v8 | 1186 } // namespace v8 |
OLD | NEW |