Index: test/cctest/test-debug.cc |
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc |
index 4de243b6cc149097f8ddb497c0b3d1775ca980f0..89fdabb46a272aef30f5302bafa5a0a702279d4b 100644 |
--- a/test/cctest/test-debug.cc |
+++ b/test/cctest/test-debug.cc |
@@ -3856,6 +3856,13 @@ TEST(PauseInScript) { |
} |
+static void DebugEventCounterCheck(int caught, int uncaught, int message) { |
+ CHECK_EQ(caught, exception_hit_count); |
+ CHECK_EQ(uncaught, uncaught_exception_hit_count); |
+ CHECK_EQ(message, message_callback_count); |
+} |
+ |
+ |
// Test break on exceptions. For each exception break combination the number |
// of debug event exception callbacks and message callbacks are collected. The |
// number of debug event exception callbacks are used to check that the |
@@ -3875,6 +3882,15 @@ TEST(BreakOnException) { |
"caught"); |
v8::Local<v8::Function> notCaught = |
CompileFunction(&env, "function notCaught(){throws();}", "notCaught"); |
+ v8::Local<v8::Function> notCaughtFinally = CompileFunction( |
+ &env, "function notCaughtFinally(){try{throws();}finally{}}", |
+ "notCaughtFinally"); |
+ // In this edge case, even though this finally does not propagate the |
+ // exception, the debugger considers this uncaught, since we want to break |
+ // at the first throw for the general case where finally implicitly rethrows. |
+ v8::Local<v8::Function> edgeCaseFinally = CompileFunction( |
+ &env, "function caughtFinally(){L:try{throws();}finally{break L;}}", |
+ "caughtFinally"); |
v8::V8::AddMessageListener(MessageCallbackCount); |
v8::Debug::SetDebugEventListener(DebugEventCounter); |
@@ -3883,117 +3899,117 @@ TEST(BreakOnException) { |
DebugEventCounterClear(); |
MessageCallbackCountClear(); |
caught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(0, exception_hit_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
- CHECK_EQ(0, message_callback_count); |
+ DebugEventCounterCheck(0, 0, 0); |
notCaught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(0, exception_hit_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
- CHECK_EQ(1, message_callback_count); |
+ DebugEventCounterCheck(0, 0, 1); |
+ notCaughtFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(0, 0, 2); |
+ edgeCaseFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(0, 0, 2); |
// No break on exception |
DebugEventCounterClear(); |
MessageCallbackCountClear(); |
ChangeBreakOnException(false, false); |
caught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(0, exception_hit_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
- CHECK_EQ(0, message_callback_count); |
+ DebugEventCounterCheck(0, 0, 0); |
notCaught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(0, exception_hit_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
- CHECK_EQ(1, message_callback_count); |
+ DebugEventCounterCheck(0, 0, 1); |
+ notCaughtFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(0, 0, 2); |
+ edgeCaseFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(0, 0, 2); |
// Break on uncaught exception |
DebugEventCounterClear(); |
MessageCallbackCountClear(); |
ChangeBreakOnException(false, true); |
caught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(0, exception_hit_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
- CHECK_EQ(0, message_callback_count); |
+ DebugEventCounterCheck(0, 0, 0); |
notCaught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(1, exception_hit_count); |
- CHECK_EQ(1, uncaught_exception_hit_count); |
- CHECK_EQ(1, message_callback_count); |
+ DebugEventCounterCheck(1, 1, 1); |
+ notCaughtFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(2, 2, 2); |
+ edgeCaseFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(3, 3, 2); |
// Break on exception and uncaught exception |
DebugEventCounterClear(); |
MessageCallbackCountClear(); |
ChangeBreakOnException(true, true); |
caught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(1, exception_hit_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
- CHECK_EQ(0, message_callback_count); |
+ DebugEventCounterCheck(1, 0, 0); |
notCaught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(2, exception_hit_count); |
- CHECK_EQ(1, uncaught_exception_hit_count); |
- CHECK_EQ(1, message_callback_count); |
+ DebugEventCounterCheck(2, 1, 1); |
+ notCaughtFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(3, 2, 2); |
+ edgeCaseFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(4, 3, 2); |
// Break on exception |
DebugEventCounterClear(); |
MessageCallbackCountClear(); |
ChangeBreakOnException(true, false); |
caught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(1, exception_hit_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
- CHECK_EQ(0, message_callback_count); |
+ DebugEventCounterCheck(1, 0, 0); |
notCaught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(2, exception_hit_count); |
- CHECK_EQ(1, uncaught_exception_hit_count); |
- CHECK_EQ(1, message_callback_count); |
+ DebugEventCounterCheck(2, 1, 1); |
+ notCaughtFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(3, 2, 2); |
+ edgeCaseFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(4, 3, 2); |
// No break on exception using JavaScript |
DebugEventCounterClear(); |
MessageCallbackCountClear(); |
ChangeBreakOnExceptionFromJS(env->GetIsolate(), false, false); |
caught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(0, exception_hit_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
- CHECK_EQ(0, message_callback_count); |
+ DebugEventCounterCheck(0, 0, 0); |
notCaught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(0, exception_hit_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
- CHECK_EQ(1, message_callback_count); |
+ DebugEventCounterCheck(0, 0, 1); |
+ notCaughtFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(0, 0, 2); |
+ edgeCaseFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(0, 0, 2); |
// Break on uncaught exception using JavaScript |
DebugEventCounterClear(); |
MessageCallbackCountClear(); |
ChangeBreakOnExceptionFromJS(env->GetIsolate(), false, true); |
caught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(0, exception_hit_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
- CHECK_EQ(0, message_callback_count); |
+ DebugEventCounterCheck(0, 0, 0); |
notCaught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(1, exception_hit_count); |
- CHECK_EQ(1, uncaught_exception_hit_count); |
- CHECK_EQ(1, message_callback_count); |
+ DebugEventCounterCheck(1, 1, 1); |
+ notCaughtFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(2, 2, 2); |
+ edgeCaseFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(3, 3, 2); |
// Break on exception and uncaught exception using JavaScript |
DebugEventCounterClear(); |
MessageCallbackCountClear(); |
ChangeBreakOnExceptionFromJS(env->GetIsolate(), true, true); |
caught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(1, exception_hit_count); |
- CHECK_EQ(0, message_callback_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
+ DebugEventCounterCheck(1, 0, 0); |
notCaught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(2, exception_hit_count); |
- CHECK_EQ(1, uncaught_exception_hit_count); |
- CHECK_EQ(1, message_callback_count); |
+ DebugEventCounterCheck(2, 1, 1); |
+ notCaughtFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(3, 2, 2); |
+ edgeCaseFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(4, 3, 2); |
// Break on exception using JavaScript |
DebugEventCounterClear(); |
MessageCallbackCountClear(); |
ChangeBreakOnExceptionFromJS(env->GetIsolate(), true, false); |
caught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(1, exception_hit_count); |
- CHECK_EQ(0, uncaught_exception_hit_count); |
- CHECK_EQ(0, message_callback_count); |
+ DebugEventCounterCheck(1, 0, 0); |
notCaught->Call(env->Global(), 0, NULL); |
- CHECK_EQ(2, exception_hit_count); |
- CHECK_EQ(1, uncaught_exception_hit_count); |
- CHECK_EQ(1, message_callback_count); |
+ DebugEventCounterCheck(2, 1, 1); |
+ notCaughtFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(3, 2, 2); |
+ edgeCaseFinally->Call(env->Global(), 0, NULL); |
+ DebugEventCounterCheck(4, 3, 2); |
v8::Debug::SetDebugEventListener(NULL); |
CheckDebuggerUnloaded(); |
@@ -4001,6 +4017,35 @@ TEST(BreakOnException) { |
} |
+static void try_finally_original_message(v8::Handle<v8::Message> message, |
+ v8::Handle<v8::Value> data) { |
+ CHECK_EQ(2, message->GetLineNumber()); |
+ CHECK_EQ(2, message->GetStartColumn()); |
+ message_callback_count++; |
+} |
+ |
+ |
+TEST(TryFinallyOriginalMessage) { |
+ // Test that the debugger plays nicely with the pending message. |
+ message_callback_count = 0; |
+ DebugEventCounterClear(); |
+ v8::V8::AddMessageListener(try_finally_original_message); |
+ v8::Debug::SetDebugEventListener(DebugEventCounter); |
+ ChangeBreakOnException(true, true); |
+ DebugLocalContext env; |
+ v8::Isolate* isolate = CcTest::isolate(); |
+ v8::HandleScope scope(isolate); |
+ CompileRun( |
+ "try {\n" |
+ " throw 1;\n" |
+ "} finally {\n" |
+ "}\n"); |
+ DebugEventCounterCheck(1, 1, 1); |
+ v8::Debug::SetDebugEventListener(NULL); |
+ v8::V8::RemoveMessageListeners(try_finally_original_message); |
+} |
+ |
+ |
TEST(EvalJSInDebugEventListenerOnNativeReThrownException) { |
DebugLocalContext env; |
v8::HandleScope scope(env->GetIsolate()); |