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

Side by Side Diff: src/isolate.cc

Issue 607913002: Report promise reject with no handler (behind a flag). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: more comments Created 6 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « src/isolate.h ('k') | src/messages.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 #include <stdlib.h> 5 #include <stdlib.h>
6 6
7 #include "src/v8.h" 7 #include "src/v8.h"
8 8
9 #include "src/ast.h" 9 #include "src/ast.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
(...skipping 988 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 if (JSObject::cast(iter.GetCurrent())->map()->constructor() == 999 if (JSObject::cast(iter.GetCurrent())->map()->constructor() ==
1000 *error_constructor) { 1000 *error_constructor) {
1001 return true; 1001 return true;
1002 } 1002 }
1003 } 1003 }
1004 return false; 1004 return false;
1005 } 1005 }
1006 1006
1007 static int fatal_exception_depth = 0; 1007 static int fatal_exception_depth = 0;
1008 1008
1009
1010 Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception,
1011 MessageLocation* location,
1012 Handle<JSObject> promise) {
1013 Handle<JSArray> stack_trace_object;
1014 if (capture_stack_trace_for_uncaught_exceptions_) {
1015 if (IsErrorObject(exception)) {
1016 // We fetch the stack trace that corresponds to this error object.
1017 Handle<Name> key = factory()->detailed_stack_trace_symbol();
1018 // Look up as own property. If the lookup fails, the exception is
1019 // probably not a valid Error object. In that case, we fall through
1020 // and capture the stack trace at this throw site.
1021 LookupIterator lookup(exception, key,
1022 LookupIterator::OWN_SKIP_INTERCEPTOR);
1023 Handle<Object> stack_trace_property;
1024 if (Object::GetProperty(&lookup).ToHandle(&stack_trace_property) &&
1025 stack_trace_property->IsJSArray()) {
1026 stack_trace_object = Handle<JSArray>::cast(stack_trace_property);
1027 }
1028 }
1029 if (stack_trace_object.is_null()) {
1030 // Not an error object, we capture at throw site.
1031 stack_trace_object = CaptureCurrentStackTrace(
1032 stack_trace_for_uncaught_exceptions_frame_limit_,
1033 stack_trace_for_uncaught_exceptions_options_);
1034 }
1035 }
1036
1037 // If the exception argument is a custom object, turn it into a string
1038 // before throwing as uncaught exception. Note that the pending
1039 // exception object to be set later must not be turned into a string.
1040 if (exception->IsJSObject() && !IsErrorObject(exception)) {
1041 MaybeHandle<Object> maybe_exception =
1042 Execution::ToDetailString(this, exception);
1043 if (!maybe_exception.ToHandle(&exception)) {
1044 exception =
1045 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("exception"));
1046 }
1047 }
1048 return MessageHandler::MakeMessageObject(this, "uncaught_exception", location,
1049 HandleVector<Object>(&exception, 1),
1050 promise, stack_trace_object);
1051 }
1052
1053
1054 void ReportBootstrappingException(Handle<Object> exception,
1055 MessageLocation* location) {
1056 base::OS::PrintError("Exception thrown during bootstrapping\n");
1057 if (location == NULL || location->script().is_null()) return;
1058 // We are bootstrapping and caught an error where the location is set
1059 // and we have a script for the location.
1060 // In this case we could have an extension (or an internal error
1061 // somewhere) and we print out the line number at which the error occured
1062 // to the console for easier debugging.
1063 int line_number =
1064 location->script()->GetLineNumber(location->start_pos()) + 1;
1065 if (exception->IsString() && location->script()->name()->IsString()) {
1066 base::OS::PrintError(
1067 "Extension or internal compilation error: %s in %s at line %d.\n",
1068 String::cast(*exception)->ToCString().get(),
1069 String::cast(location->script()->name())->ToCString().get(),
1070 line_number);
1071 } else if (location->script()->name()->IsString()) {
1072 base::OS::PrintError(
1073 "Extension or internal compilation error in %s at line %d.\n",
1074 String::cast(location->script()->name())->ToCString().get(),
1075 line_number);
1076 } else {
1077 base::OS::PrintError("Extension or internal compilation error.\n");
1078 }
1079 #ifdef OBJECT_PRINT
1080 // Since comments and empty lines have been stripped from the source of
1081 // builtins, print the actual source here so that line numbers match.
1082 if (location->script()->source()->IsString()) {
1083 Handle<String> src(String::cast(location->script()->source()));
1084 PrintF("Failing script:\n");
1085 int len = src->length();
1086 int line_number = 1;
1087 PrintF("%5d: ", line_number);
1088 for (int i = 0; i < len; i++) {
1089 uint16_t character = src->Get(i);
1090 PrintF("%c", character);
1091 if (character == '\n' && i < len - 2) {
1092 PrintF("%5d: ", ++line_number);
1093 }
1094 }
1095 }
1096 #endif
1097 }
1098
1099
1009 void Isolate::DoThrow(Object* exception, MessageLocation* location) { 1100 void Isolate::DoThrow(Object* exception, MessageLocation* location) {
1010 DCHECK(!has_pending_exception()); 1101 DCHECK(!has_pending_exception());
1011 1102
1012 HandleScope scope(this); 1103 HandleScope scope(this);
1013 Handle<Object> exception_handle(exception, this); 1104 Handle<Object> exception_handle(exception, this);
1014 1105
1015 // Determine reporting and whether the exception is caught externally. 1106 // Determine reporting and whether the exception is caught externally.
1016 bool catchable_by_javascript = is_catchable_by_javascript(exception); 1107 bool catchable_by_javascript = is_catchable_by_javascript(exception);
1017 bool can_be_caught_externally = false; 1108 bool can_be_caught_externally = false;
1018 bool should_report_exception = 1109 bool should_report_exception =
1019 ShouldReportException(&can_be_caught_externally, catchable_by_javascript); 1110 ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
1020 bool report_exception = catchable_by_javascript && should_report_exception; 1111 bool report_exception = catchable_by_javascript && should_report_exception;
1021 bool try_catch_needs_message = 1112 bool try_catch_needs_message =
1022 can_be_caught_externally && try_catch_handler()->capture_message_; 1113 can_be_caught_externally && try_catch_handler()->capture_message_;
1023 bool bootstrapping = bootstrapper()->IsActive();
1024 bool rethrowing_message = thread_local_top()->rethrowing_message_; 1114 bool rethrowing_message = thread_local_top()->rethrowing_message_;
1025 1115
1026 thread_local_top()->rethrowing_message_ = false; 1116 thread_local_top()->rethrowing_message_ = false;
1027 1117
1118 Handle<Object> promise = GetPromiseOnStackOnThrow();
1028 // Notify debugger of exception. 1119 // Notify debugger of exception.
1029 if (catchable_by_javascript) { 1120 if (catchable_by_javascript) {
1030 debug()->OnThrow(exception_handle, report_exception); 1121 debug()->OnThrow(exception_handle, promise, report_exception);
1031 } 1122 }
1032 1123
1033 // Generate the message if required. 1124 // Generate the message if required.
1034 if (!rethrowing_message && (report_exception || try_catch_needs_message)) { 1125 if (!rethrowing_message && (report_exception || try_catch_needs_message)) {
1035 MessageLocation potential_computed_location; 1126 MessageLocation potential_computed_location;
1036 if (location == NULL) { 1127 if (location == NULL) {
1037 // If no location was specified we use a computed one instead. 1128 // If no location was specified we use a computed one instead.
1038 ComputeLocation(&potential_computed_location); 1129 ComputeLocation(&potential_computed_location);
1039 location = &potential_computed_location; 1130 location = &potential_computed_location;
1040 } 1131 }
1041 // It's not safe to try to make message objects or collect stack traces
1042 // while the bootstrapper is active since the infrastructure may not have
1043 // been properly initialized.
1044 if (!bootstrapping) {
1045 Handle<JSArray> stack_trace_object;
1046 if (capture_stack_trace_for_uncaught_exceptions_) {
1047 if (IsErrorObject(exception_handle)) {
1048 // We fetch the stack trace that corresponds to this error object.
1049 Handle<Name> key = factory()->detailed_stack_trace_symbol();
1050 // Look up as own property. If the lookup fails, the exception is
1051 // probably not a valid Error object. In that case, we fall through
1052 // and capture the stack trace at this throw site.
1053 LookupIterator lookup(exception_handle, key,
1054 LookupIterator::OWN_SKIP_INTERCEPTOR);
1055 Handle<Object> stack_trace_property;
1056 if (Object::GetProperty(&lookup).ToHandle(&stack_trace_property) &&
1057 stack_trace_property->IsJSArray()) {
1058 stack_trace_object = Handle<JSArray>::cast(stack_trace_property);
1059 }
1060 }
1061 if (stack_trace_object.is_null()) {
1062 // Not an error object, we capture at throw site.
1063 stack_trace_object = CaptureCurrentStackTrace(
1064 stack_trace_for_uncaught_exceptions_frame_limit_,
1065 stack_trace_for_uncaught_exceptions_options_);
1066 }
1067 }
1068 1132
1069 Handle<Object> exception_arg = exception_handle; 1133 if (bootstrapper()->IsActive()) {
1070 // If the exception argument is a custom object, turn it into a string 1134 // It's not safe to try to make message objects or collect stack traces
1071 // before throwing as uncaught exception. Note that the pending 1135 // while the bootstrapper is active since the infrastructure may not have
1072 // exception object to be set later must not be turned into a string. 1136 // been properly initialized.
1073 if (exception_arg->IsJSObject() && !IsErrorObject(exception_arg)) { 1137 ReportBootstrappingException(exception_handle, location);
1074 MaybeHandle<Object> maybe_exception = 1138 } else {
1075 Execution::ToDetailString(this, exception_arg); 1139 Handle<Object> message_obj = CreateMessage(exception_handle, location);
1076 if (!maybe_exception.ToHandle(&exception_arg)) { 1140
1077 exception_arg = factory()->InternalizeOneByteString(
1078 STATIC_CHAR_VECTOR("exception"));
1079 }
1080 }
1081 Handle<Object> message_obj = MessageHandler::MakeMessageObject(
1082 this,
1083 "uncaught_exception",
1084 location,
1085 HandleVector<Object>(&exception_arg, 1),
1086 stack_trace_object);
1087 thread_local_top()->pending_message_obj_ = *message_obj; 1141 thread_local_top()->pending_message_obj_ = *message_obj;
1088 if (location != NULL) { 1142 if (location != NULL) {
1089 thread_local_top()->pending_message_script_ = *location->script(); 1143 thread_local_top()->pending_message_script_ = *location->script();
1090 thread_local_top()->pending_message_start_pos_ = location->start_pos(); 1144 thread_local_top()->pending_message_start_pos_ = location->start_pos();
1091 thread_local_top()->pending_message_end_pos_ = location->end_pos(); 1145 thread_local_top()->pending_message_end_pos_ = location->end_pos();
1092 } 1146 }
1093 1147
1094 // If the abort-on-uncaught-exception flag is specified, abort on any 1148 // If the abort-on-uncaught-exception flag is specified, abort on any
1095 // exception not caught by JavaScript, even when an external handler is 1149 // exception not caught by JavaScript, even when an external handler is
1096 // present. This flag is intended for use by JavaScript developers, so 1150 // present. This flag is intended for use by JavaScript developers, so
1097 // print a user-friendly stack trace (not an internal one). 1151 // print a user-friendly stack trace (not an internal one).
1098 if (fatal_exception_depth == 0 && 1152 if (fatal_exception_depth == 0 && FLAG_abort_on_uncaught_exception &&
1099 FLAG_abort_on_uncaught_exception &&
1100 (report_exception || can_be_caught_externally)) { 1153 (report_exception || can_be_caught_externally)) {
1101 fatal_exception_depth++; 1154 fatal_exception_depth++;
1102 PrintF(stderr, 1155 PrintF(stderr, "%s\n\nFROM\n",
1103 "%s\n\nFROM\n",
1104 MessageHandler::GetLocalizedMessage(this, message_obj).get()); 1156 MessageHandler::GetLocalizedMessage(this, message_obj).get());
1105 PrintCurrentStackTrace(stderr); 1157 PrintCurrentStackTrace(stderr);
1106 base::OS::Abort(); 1158 base::OS::Abort();
1107 } 1159 }
1108 } else if (location != NULL && !location->script().is_null()) { 1160 }
1109 // We are bootstrapping and caught an error where the location is set 1161 } else if (!can_be_caught_externally) {
1110 // and we have a script for the location. 1162 // Only if not intercepted externally by a TryCatch this exception may
1111 // In this case we could have an extension (or an internal error 1163 // reject a promise.
1112 // somewhere) and we print out the line number at which the error occured 1164 if (!promise->IsUndefined()) {
1113 // to the console for easier debugging. 1165 Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
1114 int line_number = 1166 ReportPromiseReject(jspromise, exception_handle, location);
1115 location->script()->GetLineNumber(location->start_pos()) + 1; 1167 // Mark the promise as already having triggered a message.
1116 if (exception->IsString() && location->script()->name()->IsString()) { 1168 Handle<Symbol> key = factory()->promise_debug_symbol();
1117 base::OS::PrintError( 1169 Handle<Object> value = factory()->true_value();
1118 "Extension or internal compilation error: %s in %s at line %d.\n", 1170 JSObject::SetProperty(jspromise, key, value, STRICT);
1119 String::cast(exception)->ToCString().get(),
1120 String::cast(location->script()->name())->ToCString().get(),
1121 line_number);
1122 } else if (location->script()->name()->IsString()) {
1123 base::OS::PrintError(
1124 "Extension or internal compilation error in %s at line %d.\n",
1125 String::cast(location->script()->name())->ToCString().get(),
1126 line_number);
1127 } else {
1128 base::OS::PrintError("Extension or internal compilation error.\n");
1129 }
1130 #ifdef OBJECT_PRINT
1131 // Since comments and empty lines have been stripped from the source of
1132 // builtins, print the actual source here so that line numbers match.
1133 if (location->script()->source()->IsString()) {
1134 Handle<String> src(String::cast(location->script()->source()));
1135 PrintF("Failing script:\n");
1136 int len = src->length();
1137 int line_number = 1;
1138 PrintF("%5d: ", line_number);
1139 for (int i = 0; i < len; i++) {
1140 uint16_t character = src->Get(i);
1141 PrintF("%c", character);
1142 if (character == '\n' && i < len - 2) {
1143 PrintF("%5d: ", ++line_number);
1144 }
1145 }
1146 }
1147 #endif
1148 } 1171 }
1149 } 1172 }
1150 1173
1174 set_pending_exception(*exception_handle);
1175
1151 // Save the message for reporting if the the exception remains uncaught. 1176 // Save the message for reporting if the the exception remains uncaught.
1152 thread_local_top()->has_pending_message_ = report_exception; 1177 thread_local_top()->has_pending_message_ = report_exception;
1153 1178
1154 // Do not forget to clean catcher_ if currently thrown exception cannot 1179 // Do not forget to clean catcher_ if currently thrown exception cannot
1155 // be caught. If necessary, ReThrow will update the catcher. 1180 // be caught. If necessary, ReThrow will update the catcher.
1156 thread_local_top()->catcher_ = can_be_caught_externally ? 1181 thread_local_top()->catcher_ =
1157 try_catch_handler() : NULL; 1182 can_be_caught_externally ? try_catch_handler() : NULL;
1158
1159 set_pending_exception(*exception_handle);
1160 } 1183 }
1161 1184
1162 1185
1186 void Isolate::ReportPromiseReject(Handle<JSObject> promise,
1187 Handle<Object> exception,
1188 MessageLocation* location) {
1189 if (!FLAG_report_promise_reject) return;
1190 Handle<Object> uncaught;
1191 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1192 this, uncaught, i::Execution::PromiseHasRejectHandler(this, promise),
1193 /* void */);
1194 if (uncaught->IsTrue()) return; // Promise has reject handler.
1195
1196 MessageLocation potential_computed_location;
1197 if (location == NULL) {
1198 // If no location was specified we use a computed one instead.
1199 ComputeLocation(&potential_computed_location);
1200 location = &potential_computed_location;
1201 }
1202 Handle<JSMessageObject> message = CreateMessage(exception, location, promise);
1203 set_pending_exception(*exception);
1204 MessageHandler::ReportMessage(this, location, message);
1205 clear_pending_exception();
1206 }
1207
1208
1163 bool Isolate::HasExternalTryCatch() { 1209 bool Isolate::HasExternalTryCatch() {
1164 DCHECK(has_pending_exception()); 1210 DCHECK(has_pending_exception());
1165 1211
1166 return (thread_local_top()->catcher_ != NULL) && 1212 return (thread_local_top()->catcher_ != NULL) &&
1167 (try_catch_handler() == thread_local_top()->catcher_); 1213 (try_catch_handler() == thread_local_top()->catcher_);
1168 } 1214 }
1169 1215
1170 1216
1171 bool Isolate::IsFinallyOnTop() { 1217 bool Isolate::IsFinallyOnTop() {
1172 // Get the address of the external handler so we can compare the address to 1218 // Get the address of the external handler so we can compare the address to
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1313 1359
1314 Handle<Object> Isolate::GetPromiseOnStackOnThrow() { 1360 Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
1315 Handle<Object> undefined = factory()->undefined_value(); 1361 Handle<Object> undefined = factory()->undefined_value();
1316 ThreadLocalTop* tltop = thread_local_top(); 1362 ThreadLocalTop* tltop = thread_local_top();
1317 if (tltop->promise_on_stack_ == NULL) return undefined; 1363 if (tltop->promise_on_stack_ == NULL) return undefined;
1318 StackHandler* promise_try = tltop->promise_on_stack_->handler(); 1364 StackHandler* promise_try = tltop->promise_on_stack_->handler();
1319 // Find the top-most try-catch handler. 1365 // Find the top-most try-catch handler.
1320 StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop)); 1366 StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop));
1321 do { 1367 do {
1322 if (handler == promise_try) { 1368 if (handler == promise_try) {
1323 // Mark the pushed try-catch handler to prevent a later duplicate event
1324 // triggered with the following reject.
1325 return tltop->promise_on_stack_->promise(); 1369 return tltop->promise_on_stack_->promise();
1326 } 1370 }
1327 handler = handler->next(); 1371 handler = handler->next();
1328 // Throwing inside a Promise can be intercepted by an inner try-catch, so 1372 // Throwing inside a Promise can be intercepted by an inner try-catch, so
1329 // we stop at the first try-catch handler. 1373 // we stop at the first try-catch handler.
1330 } while (handler != NULL && !handler->is_catch()); 1374 } while (handler != NULL && !handler->is_catch());
1331 return undefined; 1375 return undefined;
1332 } 1376 }
1333 1377
1334 1378
(...skipping 1045 matching lines...) Expand 10 before | Expand all | Expand 10 after
2380 if (prev_ && prev_->Intercept(flag)) return true; 2424 if (prev_ && prev_->Intercept(flag)) return true;
2381 // Then check whether this scope intercepts. 2425 // Then check whether this scope intercepts.
2382 if ((flag & intercept_mask_)) { 2426 if ((flag & intercept_mask_)) {
2383 intercepted_flags_ |= flag; 2427 intercepted_flags_ |= flag;
2384 return true; 2428 return true;
2385 } 2429 }
2386 return false; 2430 return false;
2387 } 2431 }
2388 2432
2389 } } // namespace v8::internal 2433 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/isolate.h ('k') | src/messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698