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:
parent
a1337ae567
commit
95260f66d0
10
src/debug.cc
10
src/debug.cc
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user