Implement issue 554 Add "ProcessDebuggerRequests" call to Debug Agent API

Review URL: http://codereview.chromium.org/549057

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3623 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
peter.rybin@gmail.com 2010-01-15 21:14:56 +00:00
parent 23fe22e7c8
commit ec86bea132
5 changed files with 101 additions and 5 deletions

View File

@ -263,6 +263,43 @@ class EXPORT Debug {
*/
static bool EnableAgent(const char* name, int port,
bool wait_for_connection = false);
/**
* Makes V8 process all pending debug messages.
*
* From V8 point of view all debug messages come asynchronously (e.g. from
* remote debugger) but they all must be handled synchronously: V8 cannot
* do 2 things at one time so normal script execution must be interrupted
* for a while.
*
* Generally when message arrives V8 may be in one of 3 states:
* 1. V8 is running script; V8 will automatically interrupt and process all
* pending messages (however auto_break flag should be enabled);
* 2. V8 is suspended on debug breakpoint; in this state V8 is dedicated
* to reading and processing debug messages;
* 3. V8 is not running at all or has called some long-working C++ function;
* by default it means that processing of all debug message will be deferred
* until V8 gets control again; however, embedding application may improve
* this by manually calling this method.
*
* It makes sense to call this method whenever a new debug message arrived and
* V8 is not already running. Method v8::Debug::SetDebugMessageDispatchHandler
* should help with the former condition.
*
* Technically this method in many senses is equivalent to executing empty
* script:
* 1. It does nothing except for processing all pending debug messages.
* 2. It should be invoked with the same precautions and from the same context
* as V8 script would be invoked from, because:
* a. with "evaluate" command it can do whatever normal script can do,
* including all native calls;
* b. no other thread should call V8 while this method is running
* (v8::Locker may be used here).
*
* "Evaluate" debug command behavior currently is not specified in scope
* of this method.
*/
static void ProcessDebugMessages();
};

View File

@ -3744,6 +3744,11 @@ Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
return i::Debugger::StartAgent(name, port, wait_for_connection);
}
void Debug::ProcessDebugMessages() {
i::Execution::ProcessDebugMesssages(true);
}
#endif // ENABLE_DEBUGGER_SUPPORT
namespace internal {

View File

@ -638,24 +638,32 @@ Object* Execution::DebugBreakHelper() {
bool debug_command_only =
StackGuard::IsDebugCommand() && !StackGuard::IsDebugBreak();
// Clear the debug request flags.
// Clear the debug break request flag.
StackGuard::Continue(DEBUGBREAK);
ProcessDebugMesssages(debug_command_only);
// Return to continue execution.
return Heap::undefined_value();
}
void Execution::ProcessDebugMesssages(bool debug_command_only) {
// Clear the debug command request flag.
StackGuard::Continue(DEBUGCOMMAND);
HandleScope scope;
// Enter the debugger. Just continue if we fail to enter the debugger.
EnterDebugger debugger;
if (debugger.FailedToEnter()) {
return Heap::undefined_value();
return;
}
// Notify the debug event listeners. Indicate auto continue if the break was
// a debug command break.
Debugger::OnDebugBreak(Factory::undefined_value(), debug_command_only);
// Return to continue execution.
return Heap::undefined_value();
}
#endif
Object* Execution::HandleStackGuardInterrupt() {

View File

@ -122,6 +122,7 @@ class Execution : public AllStatic {
Handle<Object> is_global);
#ifdef ENABLE_DEBUGGER_SUPPORT
static Object* DebugBreakHelper();
static void ProcessDebugMesssages(bool debug_command_only);
#endif
// If the stack guard is triggered, but it is not an actual

View File

@ -5655,6 +5655,51 @@ TEST(NoDebugBreakInAfterCompileMessageHandler) {
}
static int counting_message_handler_counter;
static void CountingMessageHandler(const v8::Debug::Message& message) {
counting_message_handler_counter++;
}
// Test that debug messages get processed when ProcessDebugMessages is called.
TEST(ProcessDebugMessages) {
v8::HandleScope scope;
DebugLocalContext env;
counting_message_handler_counter = 0;
v8::Debug::SetMessageHandler2(CountingMessageHandler);
const int kBufferSize = 1000;
uint16_t buffer[kBufferSize];
const char* scripts_command =
"{\"seq\":0,"
"\"type\":\"request\","
"\"command\":\"scripts\"}";
// Send scripts command.
v8::Debug::SendCommand(buffer, AsciiToUtf16(scripts_command, buffer));
CHECK_EQ(0, counting_message_handler_counter);
v8::Debug::ProcessDebugMessages();
// At least one message should come
CHECK_GE(counting_message_handler_counter, 1);
counting_message_handler_counter = 0;
v8::Debug::SendCommand(buffer, AsciiToUtf16(scripts_command, buffer));
v8::Debug::SendCommand(buffer, AsciiToUtf16(scripts_command, buffer));
CHECK_EQ(0, counting_message_handler_counter);
v8::Debug::ProcessDebugMessages();
// At least two messages should come
CHECK_GE(counting_message_handler_counter, 2);
// Get rid of the debug message handler.
v8::Debug::SetMessageHandler2(NULL);
CheckDebuggerUnloaded();
}
TEST(GetMirror) {
v8::HandleScope scope;
DebugLocalContext env;