Commit 95260f66 authored by aandrey@chromium.org's avatar aandrey@chromium.org

Fix crash in ScriptDebugServer::wrapCallFrames

The crash happens in DebugEventListener that gets called for an unhandled exception thrown by TryCatch.ReThrow().

In DevTools some parts of DebugEventListener are implemented in JavaScript, thus we should allow JavaScript execution while handling ReThrow exception in debugger.

BUG=411196
LOG=Y
R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/553043002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23858 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a1337ae5
......@@ -2503,8 +2503,18 @@ MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
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;
}
}
......
......@@ -669,6 +669,8 @@ static void DebugEventBreakPointHitCount(
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;
......@@ -709,9 +711,17 @@ static void DebugEventCounter(
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());
}
}
......@@ -3967,6 +3977,43 @@ TEST(BreakOnException) {
}
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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment