From 1982ed6e6356070241d695f77888a7681fd3c23c Mon Sep 17 00:00:00 2001 From: Jeremy Whitlock Date: Mon, 28 Sep 2015 09:51:42 -0600 Subject: [PATCH] v8: port fbff705 from v0.10 to v0.12 fbff705 Add v8::Isolate::SetAbortOnUncaughtException() so the user can be notified when an uncaught exception has bubbled. Fixes: https://github.com/nodejs/node-v0.x-archive/issues/8877 PR-URL: https://github.com/nodejs/node-v0.x-archive/pull/25835 Reviewed-By: misterdjules - Julien Gilli --- deps/v8/include/v8.h | 11 +++++++++++ deps/v8/src/api.cc | 7 +++++++ deps/v8/src/isolate.cc | 40 +++++++++++++++++++++++++++++----------- deps/v8/src/isolate.h | 5 +++++ 4 files changed, 52 insertions(+), 11 deletions(-) diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index ef0bda63f43d82..8ae075797ce940 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -4186,6 +4186,17 @@ class V8_EXPORT Isolate { */ static Isolate* GetCurrent(); + /** + * Custom callback used by embedders to help V8 determine if it should abort + * when it throws and no internal handler can catch the exception. + * If FLAG_abort_on_uncaught_exception is true, then V8 will abort if either: + * - no custom callback is set. + * - the custom callback set returns true. + * Otherwise it won't abort. + */ + typedef bool (*abort_on_uncaught_exception_t)(Isolate*); + void SetAbortOnUncaughtException(abort_on_uncaught_exception_t callback); + /** * Methods below this point require holding a lock (using Locker) in * a multi-threaded environment. diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 3d9e9d8310abbe..e6597246eac687 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -6556,6 +6556,13 @@ void Isolate::Enter() { } +void Isolate::SetAbortOnUncaughtException( + abort_on_uncaught_exception_t callback) { + i::Isolate* isolate = reinterpret_cast(this); + isolate->SetAbortOnUncaughtException(callback); +} + + void Isolate::Exit() { i::Isolate* isolate = reinterpret_cast(this); isolate->Exit(); diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc index 215296d735cc5b..6ca0f1fd0256a0 100644 --- a/deps/v8/src/isolate.cc +++ b/deps/v8/src/isolate.cc @@ -1090,19 +1090,30 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) { thread_local_top()->pending_message_end_pos_ = location->end_pos(); } - // If the abort-on-uncaught-exception flag is specified, abort on any - // exception not caught by JavaScript, even when an external handler is - // present. This flag is intended for use by JavaScript developers, so - // print a user-friendly stack trace (not an internal one). + // If the abort-on-uncaught-exception flag is specified, and if the + // exception is not caught by JavaScript (even when an external handler is + // present). if (fatal_exception_depth == 0 && FLAG_abort_on_uncaught_exception && (report_exception || can_be_caught_externally)) { - fatal_exception_depth++; - PrintF(stderr, - "%s\n\nFROM\n", - MessageHandler::GetLocalizedMessage(this, message_obj).get()); - PrintCurrentStackTrace(stderr); - base::OS::Abort(); + // If the embedder didn't specify a custom uncaught exception callback, + // or if the custom callback determined that V8 should abort, then + // abort + bool should_abort = !abort_on_uncaught_exception_callback_ || + abort_on_uncaught_exception_callback_( + reinterpret_cast(this) + ); + + if (should_abort) { + fatal_exception_depth++; + // This flag is intended for use by JavaScript developers, so + // print a user-friendly stack trace (not an internal one). + PrintF(stderr, + "%s\n\nFROM\n", + MessageHandler::GetLocalizedMessage(this, message_obj).get()); + PrintCurrentStackTrace(stderr); + base::OS::Abort(); + } } } else if (location != NULL && !location->script().is_null()) { // We are bootstrapping and caught an error where the location is set @@ -1299,6 +1310,12 @@ void Isolate::SetCaptureStackTraceForUncaughtExceptions( } +void Isolate::SetAbortOnUncaughtException( + v8::Isolate::abort_on_uncaught_exception_t callback) { + abort_on_uncaught_exception_callback_ = callback; +} + + Handle Isolate::native_context() { return handle(context()->native_context()); } @@ -1474,7 +1491,8 @@ Isolate::Isolate() num_sweeper_threads_(0), stress_deopt_count_(0), next_optimization_id_(0), - use_counter_callback_(NULL) { + use_counter_callback_(NULL), + abort_on_uncaught_exception_callback_(NULL) { id_ = base::NoBarrier_AtomicIncrement(&isolate_counter_, 1); TRACE_ISOLATE(constructor); diff --git a/deps/v8/src/isolate.h b/deps/v8/src/isolate.h index eae5cad2827a6e..c621fcc2f57e68 100644 --- a/deps/v8/src/isolate.h +++ b/deps/v8/src/isolate.h @@ -707,6 +707,9 @@ class Isolate { int frame_limit, StackTrace::StackTraceOptions options); + typedef bool (*abort_on_uncaught_exception_t)(v8::Isolate*); + void SetAbortOnUncaughtException(abort_on_uncaught_exception_t callback); + void PrintCurrentStackTrace(FILE* out); void PrintStack(StringStream* accumulator); void PrintStack(FILE* out); @@ -1331,6 +1334,8 @@ class Isolate { v8::Isolate::UseCounterCallback use_counter_callback_; + abort_on_uncaught_exception_t abort_on_uncaught_exception_callback_; + friend class ExecutionAccess; friend class HandleScopeImplementer; friend class IsolateInitializer;