Fixing a bug where a try-finally block obscured a try-catch block when registering...
authorolehougaard <olehougaard@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 9 Dec 2008 10:16:38 +0000 (10:16 +0000)
committerolehougaard <olehougaard@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 9 Dec 2008 10:16:38 +0000 (10:16 +0000)
Review URL: http://codereview.chromium.org/13658

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@945 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/top.cc
test/cctest/test-api.cc

index 6c096daf8ecc2eb11b461528975063a1d5ee277a..9dd536194b4734218e87a7d2b71550ea09b4d7a8 100644 (file)
@@ -280,7 +280,15 @@ void Top::TearDown() {
 // is on the top. Otherwise, it means the C try-catch handler is on the top.
 //
 void Top::RegisterTryCatchHandler(v8::TryCatch* that) {
-  that->js_handler_ = thread_local_.handler_;  // casted to void*
+  StackHandler* handler =
+    reinterpret_cast<StackHandler*>(thread_local_.handler_);
+
+  // Find the top-most try-catch handler.
+  while (handler != NULL && !handler->is_try_catch()) {
+    handler = handler->next();
+  }
+
+  that->js_handler_ = handler;  // casted to void*
   thread_local_.try_catch_handler_ = that;
 }
 
index b69debc127f269f0d857193c4fcbc5fee7f617e2..7e1d464ad24a001cfb7eae13df37f828498235bf 100644 (file)
@@ -1648,6 +1648,15 @@ v8::Handle<Value> ThrowFromC(const v8::Arguments& args) {
 }
 
 
+v8::Handle<Value> CCatcher(const v8::Arguments& args) {
+  if (args.Length() < 1) return v8::Boolean::New(false);
+  v8::HandleScope scope;
+  v8::TryCatch try_catch;
+  v8::Script::Compile(args[0]->ToString())->Run();
+  return v8::Boolean::New(try_catch.HasCaught());
+}
+
+
 THREADED_TEST(APICatch) {
   v8::HandleScope scope;
   Local<ObjectTemplate> templ = ObjectTemplate::New();
@@ -1678,6 +1687,25 @@ THREADED_TEST(APIThrowTryCatch) {
 }
 
 
+// Test that a try-finally block doesn't shadow a try-catch block
+// when setting up an external handler.
+THREADED_TEST(TryCatchInTryFinally) {
+  v8::HandleScope scope;
+  Local<ObjectTemplate> templ = ObjectTemplate::New();
+  templ->Set(v8_str("CCatcher"),
+             v8::FunctionTemplate::New(CCatcher));
+  LocalContext context(0, templ);
+  Local<Value> result = CompileRun("try {"
+                                   "  try {"
+                                   "    CCatcher('throw 7;');"
+                                   "  } finally {"
+                                   "  }"
+                                   "} catch (e) {"
+                                   "}");
+  CHECK(result->IsTrue());
+}
+
+
 static void receive_message(v8::Handle<v8::Message> message,
                             v8::Handle<v8::Value> data) {
   message_received = true;