Revision: 3201 Author: [email protected] Date: Tue Nov 3 00:53:34 2009 Log: Added TryCatch::ReThrow method.
Review URL: http://codereview.chromium.org/342078 http://code.google.com/p/v8/source/detail?r=3201 Modified: /branches/bleeding_edge/include/v8.h /branches/bleeding_edge/src/api.cc /branches/bleeding_edge/test/cctest/test-api.cc ======================================= --- /branches/bleeding_edge/include/v8.h Tue Oct 27 04:54:01 2009 +++ /branches/bleeding_edge/include/v8.h Tue Nov 3 00:53:34 2009 @@ -2472,6 +2472,15 @@ */ 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<Value> 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 @@ 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_; }; ======================================= --- /branches/bleeding_edge/src/api.cc Fri Oct 30 03:23:12 2009 +++ /branches/bleeding_edge/src/api.cc Tue Nov 3 00:53:34 2009 @@ -1197,13 +1197,21 @@ 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<v8::Value> exc = v8::Local<v8::Value>::New(Exception()); + i::Top::UnregisterTryCatchHandler(this); + v8::ThrowException(exc); + } else { + i::Top::UnregisterTryCatchHandler(this); + } } @@ -1215,6 +1223,13 @@ bool v8::TryCatch::CanContinue() const { return can_continue_; } + + +v8::Handle<v8::Value> v8::TryCatch::ReThrow() { + if (!HasCaught()) return v8::Local<v8::Value>(); + rethrow_ = true; + return v8::Undefined(); +} v8::Local<Value> v8::TryCatch::Exception() const { ======================================= --- /branches/bleeding_edge/test/cctest/test-api.cc Thu Oct 29 16:06:59 2009 +++ /branches/bleeding_edge/test/cctest/test-api.cc Tue Nov 3 00:53:34 2009 @@ -8662,3 +8662,29 @@ } } } + + +static v8::Handle<Value> SpaghettiIncident(const v8::Arguments& args) { + v8::HandleScope scope; + v8::TryCatch tc; + v8::Handle<v8::String> 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")); +} --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
