Index: src/debug.cc |
=================================================================== |
--- src/debug.cc (revision 5064) |
+++ src/debug.cc (working copy) |
@@ -1882,6 +1882,7 @@ |
DebuggerAgent* Debugger::agent_ = NULL; |
LockingCommandMessageQueue Debugger::command_queue_(kQueueInitialSize); |
Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0); |
+LockingCommandMessageQueue Debugger::event_command_queue_(kQueueInitialSize); |
Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name, |
@@ -2207,39 +2208,75 @@ |
event_data, |
auto_continue); |
} |
- // Notify registered debug event listener. This can be either a C or a |
- // JavaScript function. |
- if (!event_listener_.is_null()) { |
- if (event_listener_->IsProxy()) { |
- // C debug event listener. |
- Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_)); |
- v8::Debug::EventCallback2 callback = |
- FUNCTION_CAST<v8::Debug::EventCallback2>(callback_obj->proxy()); |
- EventDetailsImpl event_details( |
- event, |
- Handle<JSObject>::cast(exec_state), |
- event_data, |
- event_listener_data_); |
- callback(event_details); |
- } else { |
- // JavaScript debug event listener. |
- ASSERT(event_listener_->IsJSFunction()); |
- Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_)); |
- |
- // Invoke the JavaScript debug event listener. |
- const int argc = 4; |
- Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(), |
- exec_state.location(), |
- Handle<Object>::cast(event_data).location(), |
- event_listener_data_.location() }; |
- Handle<Object> result = Execution::TryCall(fun, Top::global(), |
- argc, argv, &caught_exception); |
- // Silently ignore exceptions from debug event listeners. |
+ // Notify registered debug event listener. This can be either a C or |
+ // a JavaScript function. Don't call event listener for v8::Break |
+ // here, if it's only a debug command -- they will be processed later. |
+ if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) { |
+ CallEventCallback(event, exec_state, event_data, NULL); |
+ } |
+ // Process pending debug commands. |
+ if (event == v8::Break) { |
+ while (!event_command_queue_.IsEmpty()) { |
+ CommandMessage command = event_command_queue_.Get(); |
+ if (!event_listener_.is_null()) { |
+ CallEventCallback(v8::BreakForCommand, |
+ exec_state, |
+ event_data, |
+ command.client_data()); |
+ } |
+ command.Dispose(); |
} |
} |
} |
+void Debugger::CallEventCallback(v8::DebugEvent event, |
+ Handle<Object> exec_state, |
+ Handle<Object> event_data, |
+ v8::Debug::ClientData* client_data) { |
+ if (event_listener_->IsProxy()) { |
+ CallCEventCallback(event, exec_state, event_data, client_data); |
+ } else { |
+ CallJSEventCallback(event, exec_state, event_data); |
+ } |
+} |
+ |
+ |
+void Debugger::CallCEventCallback(v8::DebugEvent event, |
+ Handle<Object> exec_state, |
+ Handle<Object> event_data, |
+ v8::Debug::ClientData* client_data) { |
+ Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_)); |
+ v8::Debug::EventCallback2 callback = |
+ FUNCTION_CAST<v8::Debug::EventCallback2>(callback_obj->proxy()); |
+ EventDetailsImpl event_details( |
+ event, |
+ Handle<JSObject>::cast(exec_state), |
+ Handle<JSObject>::cast(event_data), |
+ event_listener_data_, |
+ client_data); |
+ callback(event_details); |
+} |
+ |
+ |
+void Debugger::CallJSEventCallback(v8::DebugEvent event, |
+ Handle<Object> exec_state, |
+ Handle<Object> event_data) { |
+ ASSERT(event_listener_->IsJSFunction()); |
+ Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_)); |
+ |
+ // Invoke the JavaScript debug event listener. |
+ const int argc = 4; |
+ Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(), |
+ exec_state.location(), |
+ Handle<Object>::cast(event_data).location(), |
+ event_listener_data_.location() }; |
+ bool caught_exception = false; |
+ Execution::TryCall(fun, Top::global(), argc, argv, &caught_exception); |
+ // Silently ignore exceptions from debug event listeners. |
+} |
+ |
+ |
Handle<Context> Debugger::GetDebugContext() { |
never_unload_debugger_ = true; |
EnterDebugger debugger; |
@@ -2273,6 +2310,7 @@ |
bool sendEventMessage = false; |
switch (event) { |
case v8::Break: |
+ case v8::BreakForCommand: |
sendEventMessage = !auto_continue; |
break; |
case v8::Exception: |
@@ -2560,6 +2598,17 @@ |
} |
+void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { |
+ CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); |
+ event_command_queue_.Put(message); |
+ |
+ // Set the debug command break flag to have the command processed. |
+ if (!Debug::InDebugger()) { |
+ StackGuard::DebugCommand(); |
+ } |
+} |
+ |
+ |
bool Debugger::IsDebuggerActive() { |
ScopedLock with(debugger_access_); |
@@ -2761,11 +2810,13 @@ |
EventDetailsImpl::EventDetailsImpl(DebugEvent event, |
Handle<JSObject> exec_state, |
Handle<JSObject> event_data, |
- Handle<Object> callback_data) |
+ Handle<Object> callback_data, |
+ v8::Debug::ClientData* client_data) |
: event_(event), |
exec_state_(exec_state), |
event_data_(event_data), |
- callback_data_(callback_data) {} |
+ callback_data_(callback_data), |
+ client_data_(client_data) {} |
DebugEvent EventDetailsImpl::GetEvent() const { |
@@ -2793,6 +2844,11 @@ |
} |
+v8::Debug::ClientData* EventDetailsImpl::GetClientData() const { |
+ return client_data_; |
+} |
+ |
+ |
CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()), |
client_data_(NULL) { |
} |