diff --git a/deps/v8/include/v8-debug.h b/deps/v8/include/v8-debug.h index 3c5c923b3d5..d93e5543b46 100644 --- a/deps/v8/include/v8-debug.h +++ b/deps/v8/include/v8-debug.h @@ -188,6 +188,11 @@ class EXPORT Debug { */ typedef void (*HostDispatchHandler)(); + /** + * Callback function for the host to ensure debug messages are processed. + */ + typedef void (*DebugMessageDispatchHandler)(); + // Set a C debug event listener. static bool SetDebugEventListener(EventCallback that, Handle data = Handle()); @@ -211,6 +216,18 @@ class EXPORT Debug { static void SetHostDispatchHandler(HostDispatchHandler handler, int period = 100); + /** + * Register a callback function to be called when a debug message has been + * received and is ready to be precessed. For the debug messages to be + * processed V8 needs to be entered, and in certain embedding scenarios this + * callback can be used to make sure V8 is entered for the debug message to + * be processed. Note that debug messages will only be processed if there is + * a V8 break. This can happen automatically by using the option + * --debugger-auto-break. + */ + static void SetDebugMessageDispatchHandler( + DebugMessageDispatchHandler handler); + /** * Run a JavaScript function in the debugger. * \param fun the function to call diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 00f1e0b7e15..25354b269c8 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -3642,6 +3642,14 @@ void Debug::SetHostDispatchHandler(HostDispatchHandler handler, } +void Debug::SetDebugMessageDispatchHandler( + DebugMessageDispatchHandler handler) { + EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler"); + ENTER_V8; + i::Debugger::SetDebugMessageDispatchHandler(handler); +} + + Local Debug::Call(v8::Handle fun, v8::Handle data) { if (!i::V8::IsRunning()) return Local(); diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc index 4f89f92e97c..c82b53abb9c 100644 --- a/deps/v8/src/debug.cc +++ b/deps/v8/src/debug.cc @@ -1758,6 +1758,8 @@ bool Debugger::never_unload_debugger_ = false; v8::Debug::MessageHandler2 Debugger::message_handler_ = NULL; bool Debugger::debugger_unload_pending_ = false; v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL; +v8::Debug::DebugMessageDispatchHandler + Debugger::debug_message_dispatch_handler_ = NULL; int Debugger::host_dispatch_micros_ = 100 * 1000; DebuggerAgent* Debugger::agent_ = NULL; LockingCommandMessageQueue Debugger::command_queue_(kQueueInitialSize); @@ -2389,6 +2391,12 @@ void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, } +void Debugger::SetDebugMessageDispatchHandler( + v8::Debug::DebugMessageDispatchHandler handler) { + debug_message_dispatch_handler_ = handler; +} + + // Calls the registered debug message handler. This callback is part of the // public API. void Debugger::InvokeMessageHandler(MessageImpl message) { @@ -2419,6 +2427,10 @@ void Debugger::ProcessCommand(Vector command, if (!Debug::InDebugger()) { StackGuard::DebugCommand(); } + + if (Debugger::debug_message_dispatch_handler_ != NULL) { + Debugger::debug_message_dispatch_handler_(); + } } diff --git a/deps/v8/src/debug.h b/deps/v8/src/debug.h index 29c2bc20369..19da2519a1d 100644 --- a/deps/v8/src/debug.h +++ b/deps/v8/src/debug.h @@ -625,6 +625,8 @@ class Debugger { static void SetMessageHandler(v8::Debug::MessageHandler2 handler); static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, int period); + static void SetDebugMessageDispatchHandler( + v8::Debug::DebugMessageDispatchHandler handler); // Invoke the message handler function. static void InvokeMessageHandler(MessageImpl message); @@ -685,6 +687,7 @@ class Debugger { static v8::Debug::MessageHandler2 message_handler_; static bool debugger_unload_pending_; // Was message handler cleared? static v8::Debug::HostDispatchHandler host_dispatch_handler_; + static v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_; static int host_dispatch_micros_; static DebuggerAgent* agent_; diff --git a/src/node.cc b/src/node.cc index cef87134566..b2c4a4087c2 100644 --- a/src/node.cc +++ b/src/node.cc @@ -30,6 +30,7 @@ extern char **environ; namespace node { static int dash_dash_index = 0; +static bool use_debug_agent = false; enum encoding ParseEncoding(Handle encoding_v, enum encoding _default) { HandleScope scope; @@ -325,6 +326,21 @@ static void EIOWantPoll(void) { ev_async_send(EV_DEFAULT_UC_ &eio_watcher); } +static ev_async debug_watcher; + +static void DebugMessageCallback(EV_P_ ev_async *watcher, int revents) { + HandleScope scope; + assert(watcher == &debug_watcher); + assert(revents == EV_ASYNC); + ExecuteString(String::New("1+1;"), + String::New("debug_poll")); +} + +static void DebugMessageDispatch(void) { + ev_async_send(EV_DEFAULT_UC_ &debug_watcher); +} + + static void ExecuteNativeJS(const char *filename, const char *data) { HandleScope scope; TryCatch try_catch; @@ -434,6 +450,7 @@ static void CallExitHandler() { static void PrintHelp() { printf("Usage: node [options] [--] script.js [arguments] \n" " -v, --version print node's version\n" + " --debug enable remote debugging\n" // TODO specify port " --cflags print pre-processor and compiler flags\n" " --v8-options print v8 command line options\n\n" "Documentation can be found at http://tinyclouds.org/node/api.html" @@ -441,11 +458,16 @@ static void PrintHelp() { } static void ParseArgs(int *argc, char **argv) { + // TODO use parse opts for (int i = 1; i < *argc; i++) { const char *arg = argv[i]; if (strcmp(arg, "--") == 0) { dash_dash_index = i; break; + } else if (strcmp(arg, "--debug") == 0) { + argv[i] = reinterpret_cast(""); + use_debug_agent = true; + dash_dash_index = i; } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) { printf("%s\n", NODE_VERSION); exit(0); @@ -488,6 +510,20 @@ int main(int argc, char *argv[]) { HandleScope handle_scope; +#define AUTO_BREAK_FLAG "--debugger_auto_break" + if (node::use_debug_agent) { + V8::SetFlagsFromString(AUTO_BREAK_FLAG, sizeof(AUTO_BREAK_FLAG)); + ev_async_init(&node::debug_watcher, node::DebugMessageCallback); + Debug::SetDebugMessageDispatchHandler(node::DebugMessageDispatch); + ev_async_start(EV_DEFAULT_UC_ &node::debug_watcher); + ev_unref(EV_DEFAULT_UC); + + bool r = Debug::EnableAgent("node " NODE_VERSION, 5858); + assert(r); + printf("debugger listening on port 5858\n" + "Use 'd8 --remote_debugger' to access it.\n"); + } + Local process_template = FunctionTemplate::New(); // The global object / "process" is an instance of EventEmitter. For