void Debug::OnThrow(Handle<Object> exception, bool uncaught) {
if (in_debug_scope() || ignore_events()) return;
+ // Temporarily clear any scheduled_exception to allow evaluating
+ // JavaScript from the debug event handler.
HandleScope scope(isolate_);
+ Handle<Object> scheduled_exception;
+ if (isolate_->has_scheduled_exception()) {
+ scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
+ isolate_->clear_scheduled_exception();
+ }
OnException(exception, uncaught, isolate_->GetPromiseOnStackOnThrow());
+ if (!scheduled_exception.is_null()) {
+ isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
+ }
}
int exception_hit_count = 0;
int uncaught_exception_hit_count = 0;
int last_js_stack_height = -1;
+v8::Handle<v8::Function> debug_event_listener_callback;
+int debug_event_listener_callback_result;
static void DebugEventCounterClear() {
break_point_hit_count = 0;
static const int kArgc = 1;
v8::Handle<v8::Value> argv[kArgc] = { exec_state };
// Using exec_state as receiver is just to have a receiver.
- v8::Handle<v8::Value> result = frame_count->Call(exec_state, kArgc, argv);
+ v8::Handle<v8::Value> result = frame_count->Call(exec_state, kArgc, argv);
last_js_stack_height = result->Int32Value();
}
+
+ // Run callback from DebugEventListener and check the result.
+ if (!debug_event_listener_callback.IsEmpty()) {
+ v8::Handle<v8::Value> result =
+ debug_event_listener_callback->Call(event_data, 0, NULL);
+ CHECK(!result.IsEmpty());
+ CHECK_EQ(debug_event_listener_callback_result, result->Int32Value());
+ }
}
}
+TEST(EvalJSInDebugEventListenerOnNativeReThrownException) {
+ DebugLocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ env.ExposeDebug();
+
+ // Create functions for testing break on exception.
+ v8::Local<v8::Function> noThrowJS = CompileFunction(
+ &env, "function noThrowJS(){var a=[1]; a.push(2); return a.length;}",
+ "noThrowJS");
+
+ debug_event_listener_callback = noThrowJS;
+ debug_event_listener_callback_result = 2;
+
+ v8::V8::AddMessageListener(MessageCallbackCount);
+ v8::Debug::SetDebugEventListener(DebugEventCounter);
+ // Break on uncaught exception
+ ChangeBreakOnException(false, true);
+ DebugEventCounterClear();
+ MessageCallbackCountClear();
+
+ // ReThrow native error
+ {
+ v8::TryCatch tryCatch;
+ env->GetIsolate()->ThrowException(v8::Exception::TypeError(
+ v8::String::NewFromUtf8(env->GetIsolate(), "Type error")));
+ CHECK(tryCatch.HasCaught());
+ tryCatch.ReThrow();
+ }
+ CHECK_EQ(1, exception_hit_count);
+ CHECK_EQ(1, uncaught_exception_hit_count);
+ CHECK_EQ(0, message_callback_count); // FIXME: Should it be 1 ?
+ CHECK(!debug_event_listener_callback.IsEmpty());
+
+ debug_event_listener_callback.Clear();
+}
+
+
// Test break on exception from compiler errors. When compiling using
// v8::Script::Compile there is no JavaScript stack whereas when compiling using
// eval there are JavaScript frames.