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
This commit is contained in:
aandrey@chromium.org 2014-09-11 09:43:30 +00:00
parent a1337ae567
commit 95260f66d0
2 changed files with 58 additions and 1 deletions

View File

@ -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;
}
}

View File

@ -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.