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

Side by Side Diff: src/isolate.cc

Issue 600723005: Introduce PromiseRejectCallback. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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
« include/v8.h ('K') | « src/isolate.h ('k') | src/promise.js » ('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 960 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 if (*can_be_caught_externally) { 971 if (*can_be_caught_externally) {
972 // Only report the exception if the external handler is verbose. 972 // Only report the exception if the external handler is verbose.
973 return try_catch_handler()->is_verbose_; 973 return try_catch_handler()->is_verbose_;
974 } else { 974 } else {
975 // Report the exception if it isn't caught by JavaScript code. 975 // Report the exception if it isn't caught by JavaScript code.
976 return handler == NULL; 976 return handler == NULL;
977 } 977 }
978 } 978 }
979 979
980 980
981 // Traverse prototype chain to find out whether the object is derived from
982 // the Error object.
981 bool Isolate::IsErrorObject(Handle<Object> obj) { 983 bool Isolate::IsErrorObject(Handle<Object> obj) {
982 if (!obj->IsJSObject()) return false; 984 if (!obj->IsJSObject()) return false;
983 985
984 Handle<String> error_key = 986 Handle<String> error_key =
985 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("$Error")); 987 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("$Error"));
986 Handle<Object> error_constructor = Object::GetProperty( 988 Handle<Object> error_constructor = Object::GetProperty(
987 js_builtins_object(), error_key).ToHandleChecked(); 989 js_builtins_object(), error_key).ToHandleChecked();
988 990
989 DisallowHeapAllocation no_gc; 991 DisallowHeapAllocation no_gc;
990 for (PrototypeIterator iter(this, *obj, PrototypeIterator::START_AT_RECEIVER); 992 for (PrototypeIterator iter(this, *obj, PrototypeIterator::START_AT_RECEIVER);
991 !iter.IsAtEnd(); iter.Advance()) { 993 !iter.IsAtEnd(); iter.Advance()) {
992 if (iter.GetCurrent()->IsJSProxy()) return false; 994 if (iter.GetCurrent()->IsJSProxy()) return false;
993 if (JSObject::cast(iter.GetCurrent())->map()->constructor() == 995 if (JSObject::cast(iter.GetCurrent())->map()->constructor() ==
994 *error_constructor) { 996 *error_constructor) {
995 return true; 997 return true;
996 } 998 }
997 } 999 }
998 return false; 1000 return false;
999 } 1001 }
1000 1002
1001 static int fatal_exception_depth = 0; 1003 static int fatal_exception_depth = 0;
1002 1004
1005
1006 Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception,
1007 MessageLocation* location) {
1008 Handle<JSArray> stack_trace_object;
1009 if (capture_stack_trace_for_uncaught_exceptions_) {
1010 if (IsErrorObject(exception)) {
1011 // We fetch the stack trace that corresponds to this error object.
1012 Handle<Name> key = factory()->detailed_stack_trace_symbol();
1013 // Look up as own property. If the lookup fails, the exception is
1014 // probably not a valid Error object. In that case, we fall through
1015 // and capture the stack trace at this throw site.
1016 LookupIterator lookup(exception, key,
1017 LookupIterator::OWN_SKIP_INTERCEPTOR);
1018 Handle<Object> stack_trace_property;
1019 if (Object::GetProperty(&lookup).ToHandle(&stack_trace_property) &&
1020 stack_trace_property->IsJSArray()) {
1021 stack_trace_object = Handle<JSArray>::cast(stack_trace_property);
1022 }
1023 }
1024 if (stack_trace_object.is_null()) {
1025 // Not an error object, we capture at throw site.
1026 stack_trace_object = CaptureCurrentStackTrace(
1027 stack_trace_for_uncaught_exceptions_frame_limit_,
1028 stack_trace_for_uncaught_exceptions_options_);
1029 }
1030 }
1031
1032 // If the exception argument is a custom object, turn it into a string
1033 // before throwing as uncaught exception. Note that the pending
1034 // exception object to be set later must not be turned into a string.
1035 if (exception->IsJSObject() && !IsErrorObject(exception)) {
1036 MaybeHandle<Object> maybe_exception =
1037 Execution::ToDetailString(this, exception);
1038 if (!maybe_exception.ToHandle(&exception)) {
1039 exception =
1040 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("exception"));
1041 }
1042 }
1043 return MessageHandler::MakeMessageObject(this, "uncaught_exception", location,
1044 HandleVector<Object>(&exception, 1),
1045 stack_trace_object);
1046 }
1047
1048
1049 void ReportBootstrappingException(Handle<Object> exception,
1050 MessageLocation* location) {
1051 base::OS::PrintError("Exception thrown during bootstrapping\n");
1052 if (location == NULL || location->script().is_null()) return;
1053 // We are bootstrapping and caught an error where the location is set
1054 // and we have a script for the location.
1055 // In this case we could have an extension (or an internal error
1056 // somewhere) and we print out the line number at which the error occured
1057 // to the console for easier debugging.
1058 int line_number =
1059 location->script()->GetLineNumber(location->start_pos()) + 1;
1060 if (exception->IsString() && location->script()->name()->IsString()) {
1061 base::OS::PrintError(
1062 "Extension or internal compilation error: %s in %s at line %d.\n",
1063 String::cast(*exception)->ToCString().get(),
1064 String::cast(location->script()->name())->ToCString().get(),
1065 line_number);
1066 } else if (location->script()->name()->IsString()) {
1067 base::OS::PrintError(
1068 "Extension or internal compilation error in %s at line %d.\n",
1069 String::cast(location->script()->name())->ToCString().get(),
1070 line_number);
1071 } else {
1072 base::OS::PrintError("Extension or internal compilation error.\n");
1073 }
1074 #ifdef OBJECT_PRINT
1075 // Since comments and empty lines have been stripped from the source of
1076 // builtins, print the actual source here so that line numbers match.
1077 if (location->script()->source()->IsString()) {
1078 Handle<String> src(String::cast(location->script()->source()));
1079 PrintF("Failing script:\n");
1080 int len = src->length();
1081 int line_number = 1;
1082 PrintF("%5d: ", line_number);
1083 for (int i = 0; i < len; i++) {
1084 uint16_t character = src->Get(i);
1085 PrintF("%c", character);
1086 if (character == '\n' && i < len - 2) {
1087 PrintF("%5d: ", ++line_number);
1088 }
1089 }
1090 }
1091 #endif
1092 }
1093
1094
1003 void Isolate::DoThrow(Object* exception, MessageLocation* location) { 1095 void Isolate::DoThrow(Object* exception, MessageLocation* location) {
1004 DCHECK(!has_pending_exception()); 1096 DCHECK(!has_pending_exception());
1005 1097
1006 HandleScope scope(this); 1098 HandleScope scope(this);
1007 Handle<Object> exception_handle(exception, this); 1099 Handle<Object> exception_handle(exception, this);
1008 1100
1009 // Determine reporting and whether the exception is caught externally. 1101 // Determine reporting and whether the exception is caught externally.
1010 bool catchable_by_javascript = is_catchable_by_javascript(exception); 1102 bool catchable_by_javascript = is_catchable_by_javascript(exception);
1011 bool can_be_caught_externally = false; 1103 bool can_be_caught_externally = false;
1012 bool should_report_exception = 1104 bool should_report_exception =
1013 ShouldReportException(&can_be_caught_externally, catchable_by_javascript); 1105 ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
1014 bool report_exception = catchable_by_javascript && should_report_exception; 1106 bool report_exception = catchable_by_javascript && should_report_exception;
1015 bool try_catch_needs_message = 1107 bool try_catch_needs_message =
1016 can_be_caught_externally && try_catch_handler()->capture_message_; 1108 can_be_caught_externally && try_catch_handler()->capture_message_;
1017 bool bootstrapping = bootstrapper()->IsActive();
1018 bool rethrowing_message = thread_local_top()->rethrowing_message_; 1109 bool rethrowing_message = thread_local_top()->rethrowing_message_;
1019 1110
1020 thread_local_top()->rethrowing_message_ = false; 1111 thread_local_top()->rethrowing_message_ = false;
1021 1112
1022 // Notify debugger of exception. 1113 // Notify debugger of exception.
1023 if (catchable_by_javascript) { 1114 if (catchable_by_javascript) {
1024 debug()->OnThrow(exception_handle, report_exception); 1115 debug()->OnThrow(exception_handle, report_exception);
1025 } 1116 }
1026 1117
1027 // Generate the message if required. 1118 // Generate the message if required.
1028 if (!rethrowing_message && (report_exception || try_catch_needs_message)) { 1119 if (!rethrowing_message && (report_exception || try_catch_needs_message)) {
1029 MessageLocation potential_computed_location; 1120 MessageLocation potential_computed_location;
1030 if (location == NULL) { 1121 if (location == NULL) {
1031 // If no location was specified we use a computed one instead. 1122 // If no location was specified we use a computed one instead.
1032 ComputeLocation(&potential_computed_location); 1123 ComputeLocation(&potential_computed_location);
1033 location = &potential_computed_location; 1124 location = &potential_computed_location;
1034 } 1125 }
1035 // It's not safe to try to make message objects or collect stack traces
1036 // while the bootstrapper is active since the infrastructure may not have
1037 // been properly initialized.
1038 if (!bootstrapping) {
1039 Handle<JSArray> stack_trace_object;
1040 if (capture_stack_trace_for_uncaught_exceptions_) {
1041 if (IsErrorObject(exception_handle)) {
1042 // We fetch the stack trace that corresponds to this error object.
1043 Handle<Name> key = factory()->detailed_stack_trace_symbol();
1044 // Look up as own property. If the lookup fails, the exception is
1045 // probably not a valid Error object. In that case, we fall through
1046 // and capture the stack trace at this throw site.
1047 LookupIterator lookup(exception_handle, key,
1048 LookupIterator::OWN_SKIP_INTERCEPTOR);
1049 Handle<Object> stack_trace_property;
1050 if (Object::GetProperty(&lookup).ToHandle(&stack_trace_property) &&
1051 stack_trace_property->IsJSArray()) {
1052 stack_trace_object = Handle<JSArray>::cast(stack_trace_property);
1053 }
1054 }
1055 if (stack_trace_object.is_null()) {
1056 // Not an error object, we capture at throw site.
1057 stack_trace_object = CaptureCurrentStackTrace(
1058 stack_trace_for_uncaught_exceptions_frame_limit_,
1059 stack_trace_for_uncaught_exceptions_options_);
1060 }
1061 }
1062 1126
1063 Handle<Object> exception_arg = exception_handle; 1127 if (bootstrapper()->IsActive()) {
1064 // If the exception argument is a custom object, turn it into a string 1128 // It's not safe to try to make message objects or collect stack traces
1065 // before throwing as uncaught exception. Note that the pending 1129 // while the bootstrapper is active since the infrastructure may not have
1066 // exception object to be set later must not be turned into a string. 1130 // been properly initialized.
1067 if (exception_arg->IsJSObject() && !IsErrorObject(exception_arg)) { 1131 ReportBootstrappingException(exception_handle, location);
1068 MaybeHandle<Object> maybe_exception = 1132 } else {
1069 Execution::ToDetailString(this, exception_arg); 1133 Handle<Object> message_obj = CreateMessage(exception_handle, location);
1070 if (!maybe_exception.ToHandle(&exception_arg)) { 1134
1071 exception_arg = factory()->InternalizeOneByteString(
1072 STATIC_CHAR_VECTOR("exception"));
1073 }
1074 }
1075 Handle<Object> message_obj = MessageHandler::MakeMessageObject(
1076 this,
1077 "uncaught_exception",
1078 location,
1079 HandleVector<Object>(&exception_arg, 1),
1080 stack_trace_object);
1081 thread_local_top()->pending_message_obj_ = *message_obj; 1135 thread_local_top()->pending_message_obj_ = *message_obj;
1082 if (location != NULL) { 1136 if (location != NULL) {
1083 thread_local_top()->pending_message_script_ = *location->script(); 1137 thread_local_top()->pending_message_script_ = *location->script();
1084 thread_local_top()->pending_message_start_pos_ = location->start_pos(); 1138 thread_local_top()->pending_message_start_pos_ = location->start_pos();
1085 thread_local_top()->pending_message_end_pos_ = location->end_pos(); 1139 thread_local_top()->pending_message_end_pos_ = location->end_pos();
1086 } 1140 }
1087 1141
1088 // If the abort-on-uncaught-exception flag is specified, abort on any 1142 // If the abort-on-uncaught-exception flag is specified, abort on any
1089 // exception not caught by JavaScript, even when an external handler is 1143 // exception not caught by JavaScript, even when an external handler is
1090 // present. This flag is intended for use by JavaScript developers, so 1144 // present. This flag is intended for use by JavaScript developers, so
1091 // print a user-friendly stack trace (not an internal one). 1145 // print a user-friendly stack trace (not an internal one).
1092 if (fatal_exception_depth == 0 && 1146 if (fatal_exception_depth == 0 && FLAG_abort_on_uncaught_exception &&
1093 FLAG_abort_on_uncaught_exception &&
1094 (report_exception || can_be_caught_externally)) { 1147 (report_exception || can_be_caught_externally)) {
1095 fatal_exception_depth++; 1148 fatal_exception_depth++;
1096 PrintF(stderr, 1149 PrintF(stderr, "%s\n\nFROM\n",
1097 "%s\n\nFROM\n",
1098 MessageHandler::GetLocalizedMessage(this, message_obj).get()); 1150 MessageHandler::GetLocalizedMessage(this, message_obj).get());
1099 PrintCurrentStackTrace(stderr); 1151 PrintCurrentStackTrace(stderr);
1100 base::OS::Abort(); 1152 base::OS::Abort();
1101 } 1153 }
1102 } else if (location != NULL && !location->script().is_null()) {
1103 // We are bootstrapping and caught an error where the location is set
1104 // and we have a script for the location.
1105 // In this case we could have an extension (or an internal error
1106 // somewhere) and we print out the line number at which the error occured
1107 // to the console for easier debugging.
1108 int line_number =
1109 location->script()->GetLineNumber(location->start_pos()) + 1;
1110 if (exception->IsString() && location->script()->name()->IsString()) {
1111 base::OS::PrintError(
1112 "Extension or internal compilation error: %s in %s at line %d.\n",
1113 String::cast(exception)->ToCString().get(),
1114 String::cast(location->script()->name())->ToCString().get(),
1115 line_number);
1116 } else if (location->script()->name()->IsString()) {
1117 base::OS::PrintError(
1118 "Extension or internal compilation error in %s at line %d.\n",
1119 String::cast(location->script()->name())->ToCString().get(),
1120 line_number);
1121 } else {
1122 base::OS::PrintError("Extension or internal compilation error.\n");
1123 }
1124 #ifdef OBJECT_PRINT
1125 // Since comments and empty lines have been stripped from the source of
1126 // builtins, print the actual source here so that line numbers match.
1127 if (location->script()->source()->IsString()) {
1128 Handle<String> src(String::cast(location->script()->source()));
1129 PrintF("Failing script:\n");
1130 int len = src->length();
1131 int line_number = 1;
1132 PrintF("%5d: ", line_number);
1133 for (int i = 0; i < len; i++) {
1134 uint16_t character = src->Get(i);
1135 PrintF("%c", character);
1136 if (character == '\n' && i < len - 2) {
1137 PrintF("%5d: ", ++line_number);
1138 }
1139 }
1140 }
1141 #endif
1142 } 1154 }
1143 } 1155 }
1144 1156
1145 // Save the message for reporting if the the exception remains uncaught. 1157 // Save the message for reporting if the the exception remains uncaught.
1146 thread_local_top()->has_pending_message_ = report_exception; 1158 thread_local_top()->has_pending_message_ = report_exception;
1147 1159
1148 // Do not forget to clean catcher_ if currently thrown exception cannot 1160 // Do not forget to clean catcher_ if currently thrown exception cannot
1149 // be caught. If necessary, ReThrow will update the catcher. 1161 // be caught. If necessary, ReThrow will update the catcher.
1150 thread_local_top()->catcher_ = can_be_caught_externally ? 1162 thread_local_top()->catcher_ = can_be_caught_externally ?
1151 try_catch_handler() : NULL; 1163 try_catch_handler() : NULL;
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1307 1319
1308 Handle<Object> Isolate::GetPromiseOnStackOnThrow() { 1320 Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
1309 Handle<Object> undefined = factory()->undefined_value(); 1321 Handle<Object> undefined = factory()->undefined_value();
1310 ThreadLocalTop* tltop = thread_local_top(); 1322 ThreadLocalTop* tltop = thread_local_top();
1311 if (tltop->promise_on_stack_ == NULL) return undefined; 1323 if (tltop->promise_on_stack_ == NULL) return undefined;
1312 StackHandler* promise_try = tltop->promise_on_stack_->handler(); 1324 StackHandler* promise_try = tltop->promise_on_stack_->handler();
1313 // Find the top-most try-catch handler. 1325 // Find the top-most try-catch handler.
1314 StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop)); 1326 StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop));
1315 do { 1327 do {
1316 if (handler == promise_try) { 1328 if (handler == promise_try) {
1317 // Mark the pushed try-catch handler to prevent a later duplicate event
1318 // triggered with the following reject.
1319 return tltop->promise_on_stack_->promise(); 1329 return tltop->promise_on_stack_->promise();
1320 } 1330 }
1321 handler = handler->next(); 1331 handler = handler->next();
1322 // Throwing inside a Promise can be intercepted by an inner try-catch, so 1332 // Throwing inside a Promise can be intercepted by an inner try-catch, so
1323 // we stop at the first try-catch handler. 1333 // we stop at the first try-catch handler.
1324 } while (handler != NULL && !handler->is_catch()); 1334 } while (handler != NULL && !handler->is_catch());
1325 return undefined; 1335 return undefined;
1326 } 1336 }
1327 1337
1328 1338
(...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after
2271 if (run_microtasks) RunMicrotasks(); 2281 if (run_microtasks) RunMicrotasks();
2272 // Fire callbacks. Increase call depth to prevent recursive callbacks. 2282 // Fire callbacks. Increase call depth to prevent recursive callbacks.
2273 v8::Isolate::SuppressMicrotaskExecutionScope suppress( 2283 v8::Isolate::SuppressMicrotaskExecutionScope suppress(
2274 reinterpret_cast<v8::Isolate*>(this)); 2284 reinterpret_cast<v8::Isolate*>(this));
2275 for (int i = 0; i < call_completed_callbacks_.length(); i++) { 2285 for (int i = 0; i < call_completed_callbacks_.length(); i++) {
2276 call_completed_callbacks_.at(i)(); 2286 call_completed_callbacks_.at(i)();
2277 } 2287 }
2278 } 2288 }
2279 2289
2280 2290
2291 void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
2292 promise_reject_callback_ = callback;
2293 }
2294
2295
2296 void Isolate::ReportPromiseReject(Handle<JSObject> promise,
2297 Handle<Object> value,
2298 v8::PromiseRejectEvent event) {
2299 if (promise_reject_callback_ == NULL) return;
2300 promise_reject_callback_(v8::Utils::PromiseToLocal(promise),
2301 v8::Utils::ToLocal(value), event);
2302 }
2303
2304
2281 void Isolate::EnqueueMicrotask(Handle<Object> microtask) { 2305 void Isolate::EnqueueMicrotask(Handle<Object> microtask) {
2282 DCHECK(microtask->IsJSFunction() || microtask->IsCallHandlerInfo()); 2306 DCHECK(microtask->IsJSFunction() || microtask->IsCallHandlerInfo());
2283 Handle<FixedArray> queue(heap()->microtask_queue(), this); 2307 Handle<FixedArray> queue(heap()->microtask_queue(), this);
2284 int num_tasks = pending_microtask_count(); 2308 int num_tasks = pending_microtask_count();
2285 DCHECK(num_tasks <= queue->length()); 2309 DCHECK(num_tasks <= queue->length());
2286 if (num_tasks == 0) { 2310 if (num_tasks == 0) {
2287 queue = factory()->NewFixedArray(8); 2311 queue = factory()->NewFixedArray(8);
2288 heap()->set_microtask_queue(*queue); 2312 heap()->set_microtask_queue(*queue);
2289 } else if (num_tasks == queue->length()) { 2313 } else if (num_tasks == queue->length()) {
2290 queue = FixedArray::CopySize(queue, num_tasks * 2); 2314 queue = FixedArray::CopySize(queue, num_tasks * 2);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2387 if (prev_ && prev_->Intercept(flag)) return true; 2411 if (prev_ && prev_->Intercept(flag)) return true;
2388 // Then check whether this scope intercepts. 2412 // Then check whether this scope intercepts.
2389 if ((flag & intercept_mask_)) { 2413 if ((flag & intercept_mask_)) {
2390 intercepted_flags_ |= flag; 2414 intercepted_flags_ |= flag;
2391 return true; 2415 return true;
2392 } 2416 }
2393 return false; 2417 return false;
2394 } 2418 }
2395 2419
2396 } } // namespace v8::internal 2420 } } // namespace v8::internal
OLDNEW
« include/v8.h ('K') | « src/isolate.h ('k') | src/promise.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698