From 159cc8ddf2bb3c661562d1486c88849bf05573ac Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Thu, 7 Aug 2014 08:55:49 +0000 Subject: [PATCH] v8::TryCatch should cancel the scheduled exception on Reset. v8::TryCatch cancels the scheduled exception on destruction if |Rethrow| was never called. It is reasonable to do the same in |Reset|. BUG=362388, 359386 LOG= R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/443853002 Patch from Yutaka Hirano . git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22963 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8.h | 5 ++++- src/api.cc | 13 ++++++++++++- test/cctest/test-api.cc | 25 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/include/v8.h b/include/v8.h index f702166..ef0bda6 100644 --- a/include/v8.h +++ b/include/v8.h @@ -5114,7 +5114,8 @@ class V8_EXPORT TryCatch { /** * Clears any exceptions that may have been caught by this try/catch block. - * After this method has been called, HasCaught() will return false. + * After this method has been called, HasCaught() will return false. Cancels + * the scheduled exception if it is caught and ReThrow() is not called before. * * It is not necessary to clear a try/catch block before using it again; if * another exception is thrown the previously caught exception will just be @@ -5157,6 +5158,8 @@ class V8_EXPORT TryCatch { } private: + void ResetInternal(); + // Make it hard to create heap-allocated TryCatch blocks. TryCatch(const TryCatch&); void operator=(const TryCatch&); diff --git a/src/api.cc b/src/api.cc index bd49c84..7098859 100644 --- a/src/api.cc +++ b/src/api.cc @@ -1823,7 +1823,7 @@ v8::TryCatch::TryCatch() capture_message_(true), rethrow_(false), has_terminated_(false) { - Reset(); + ResetInternal(); // Special handling for simulators which have a separate JS stack. js_stack_comparable_address_ = reinterpret_cast(v8::internal::SimulatorStack::RegisterCTryCatch( @@ -1935,6 +1935,17 @@ v8::Local v8::TryCatch::Message() const { void v8::TryCatch::Reset() { DCHECK(isolate_ == i::Isolate::Current()); + if (!rethrow_ && HasCaught() && isolate_->has_scheduled_exception()) { + // If an exception was caught but is still scheduled because no API call + // promoted it, then it is canceled to prevent it from being propagated. + // Note that this will not cancel termination exceptions. + isolate_->CancelScheduledExceptionFromTryCatch(this); + } + ResetInternal(); +} + + +void v8::TryCatch::ResetInternal() { i::Object* the_hole = isolate_->heap()->the_hole_value(); exception_ = the_hole; message_obj_ = the_hole; diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 5fb99c6..45c5d46 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -5421,6 +5421,31 @@ TEST(TryCatchNative) { } +void TryCatchNativeResetHelper( + const v8::FunctionCallbackInfo& args) { + ApiTestFuzzer::Fuzz(); + v8::TryCatch try_catch; + args.GetIsolate()->ThrowException(v8_str("boom")); + CHECK(try_catch.HasCaught()); + try_catch.Reset(); + CHECK(!try_catch.HasCaught()); +} + + +TEST(TryCatchNativeReset) { + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + v8::V8::Initialize(); + v8::TryCatch try_catch; + Local templ = ObjectTemplate::New(isolate); + templ->Set(v8_str("TryCatchNativeResetHelper"), + v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper)); + LocalContext context(0, templ); + CompileRun("TryCatchNativeResetHelper();"); + CHECK(!try_catch.HasCaught()); +} + + THREADED_TEST(Equality) { LocalContext context; v8::Isolate* isolate = context->GetIsolate(); -- 2.7.4