From 850487401d0748da3dc15e487f4fc77ce353dda6 Mon Sep 17 00:00:00 2001 From: "christian.plesner.hansen@gmail.com" Date: Tue, 3 Nov 2009 08:53:34 +0000 Subject: [PATCH] Added TryCatch::ReThrow method. Review URL: http://codereview.chromium.org/342078 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3201 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 16 +++++++++++++--- src/api.cc | 17 ++++++++++++++++- test/cctest/test-api.cc | 26 ++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/include/v8.h b/include/v8.h index 5f3b68b..c372d0c 100644 --- a/include/v8.h +++ b/include/v8.h @@ -2473,6 +2473,15 @@ class V8EXPORT TryCatch { bool CanContinue() const; /** + * Throws the exception caught by this TryCatch in a way that avoids + * it being caught again by this same TryCatch. As with ThrowException + * it is illegal to execute any JavaScript operations after calling + * ReThrow; the caller must return immediately to where the exception + * is caught. + */ + Handle ReThrow(); + + /** * Returns the exception caught by this try/catch block. If no exception has * been caught an empty handle is returned. * @@ -2527,9 +2536,10 @@ class V8EXPORT TryCatch { TryCatch* next_; void* exception_; void* message_; - bool is_verbose_; - bool can_continue_; - bool capture_message_; + bool is_verbose_ : 1; + bool can_continue_ : 1; + bool capture_message_ : 1; + bool rethrow_ : 1; void* js_handler_; }; diff --git a/src/api.cc b/src/api.cc index bde5fdc..20edbc5 100644 --- a/src/api.cc +++ b/src/api.cc @@ -1197,13 +1197,21 @@ v8::TryCatch::TryCatch() is_verbose_(false), can_continue_(true), capture_message_(true), + rethrow_(false), js_handler_(NULL) { i::Top::RegisterTryCatchHandler(this); } v8::TryCatch::~TryCatch() { - i::Top::UnregisterTryCatchHandler(this); + if (rethrow_) { + v8::HandleScope scope; + v8::Local exc = v8::Local::New(Exception()); + i::Top::UnregisterTryCatchHandler(this); + v8::ThrowException(exc); + } else { + i::Top::UnregisterTryCatchHandler(this); + } } @@ -1217,6 +1225,13 @@ bool v8::TryCatch::CanContinue() const { } +v8::Handle v8::TryCatch::ReThrow() { + if (!HasCaught()) return v8::Local(); + rethrow_ = true; + return v8::Undefined(); +} + + v8::Local v8::TryCatch::Exception() const { if (HasCaught()) { // Check for out of memory exception. diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index b3c8515..514a22f 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -8662,3 +8662,29 @@ THREADED_TEST(QuietSignalingNaNs) { } } } + + +static v8::Handle SpaghettiIncident(const v8::Arguments& args) { + v8::HandleScope scope; + v8::TryCatch tc; + v8::Handle str = args[0]->ToString(); + if (tc.HasCaught()) + return tc.ReThrow(); + return v8::Undefined(); +} + + +// Test that a stack overflow can be propagated down through a spaghetti +// stack using ReThrow. +THREADED_TEST(SpaghettiStackOverflow) { + v8::HandleScope scope; + LocalContext context; + context->Global()->Set( + v8::String::New("s"), + v8::FunctionTemplate::New(SpaghettiIncident)->GetFunction()); + v8::TryCatch try_catch; + CompileRun("var o = {toString: function () {return s(o);}}; s(o);"); + CHECK(try_catch.HasCaught()); + v8::String::Utf8Value value(try_catch.Exception()); + CHECK_NE(0, strstr(*value, "RangeError")); +} -- 2.7.4