};
- /**
- * A message object passed to the debug message handler.
- */
- class Message {
- public:
- /**
- * Check type of message.
- */
- virtual bool IsEvent() const = 0;
- virtual bool IsResponse() const = 0;
- virtual DebugEvent GetEvent() const = 0;
-
- /**
- * Indicate whether this is a response to a continue command which will
- * start the VM running after this is processed.
- */
- virtual bool WillStartRunning() const = 0;
-
- /**
- * Access to execution state and event data. Don't store these cross
- * callbacks as their content becomes invalid. These objects are from the
- * debugger event that started the debug message loop.
- */
- virtual Handle<Object> GetExecutionState() const = 0;
- virtual Handle<Object> GetEventData() const = 0;
-
- /**
- * Get the debugger protocol JSON.
- */
- virtual Handle<String> GetJSON() const = 0;
-
- /**
- * Get the context active when the debug event happened. Note this is not
- * the current active context as the JavaScript part of the debugger is
- * running in it's own context which is entered at this point.
- */
- virtual Handle<Context> GetEventContext() const = 0;
-
- /**
- * Client data passed with the corresponding request if any. This is the
- * client_data data value passed into Debug::SendCommand along with the
- * request that led to the message or NULL if the message is an event. The
- * debugger takes ownership of the data and will delete it even if there is
- * no message handler.
- */
- virtual ClientData* GetClientData() const = 0;
- };
-
-
/**
* Debug event callback function.
*
* \param data value passed by the user to SetDebugEventListener
*/
typedef void (*EventCallback)(DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data,
- Handle<Value> data);
+ Handle<Object> exec_state,
+ Handle<Object> event_data,
+ Handle<Value> data);
/**
* Debug message callback function.
*
- * \param message the debug message handler message object
+ * \param message the debug message
* \param length length of the message
* \param data the data value passed when registering the message handler
-
+ * \param client_data the data value passed into Debug::SendCommand along
+ * with the request that led to the message or NULL if the message is an
+ * asynchronous event. The debugger takes ownership of the data and will
+ * delete it before dying even if there is no message handler.
* A MessageHandler does not take posession of the message string,
* and must not rely on the data persisting after the handler returns.
*/
- typedef void (*MessageHandler)(const Message& message);
+ typedef void (*MessageHandler)(const uint16_t* message, int length,
+ ClientData* client_data);
/**
* Debug host dispatch callback function.
// Public V8 debugger API message handler function. This function just delegates
// to the debugger agent through it's data parameter.
-void DebuggerAgentMessageHandler(const v8::Debug::Message& message) {
- DebuggerAgent::instance_->DebuggerMessage(message);
+void DebuggerAgentMessageHandler(const uint16_t* message, int length,
+ v8::Debug::ClientData* client_data) {
+ DebuggerAgent::instance_->DebuggerMessage(message, length);
}
// static
}
-void DebuggerAgent::DebuggerMessage(const v8::Debug::Message& message) {
+void DebuggerAgent::DebuggerMessage(const uint16_t* message, int length) {
ScopedLock with(session_access_);
// Forward the message handling to the session.
if (session_ != NULL) {
- v8::String::Value val(message.GetJSON());
- session_->DebuggerMessage(Vector<uint16_t>(const_cast<uint16_t*>(*val),
- val.length()));
+ session_->DebuggerMessage(Vector<uint16_t>(const_cast<uint16_t*>(message),
+ length));
}
}
private:
void Run();
void CreateSession(Socket* socket);
- void DebuggerMessage(const v8::Debug::Message& message);
+ void DebuggerMessage(const uint16_t* message, int length);
void CloseSession();
void OnSessionClosed(DebuggerAgentSession* session);
static DebuggerAgent* instance_;
friend class DebuggerAgentSession;
- friend void DebuggerAgentMessageHandler(const v8::Debug::Message& message);
+ friend void DebuggerAgentMessageHandler(const uint16_t* message, int length,
+ v8::Debug::ClientData* client_data);
DISALLOW_COPY_AND_ASSIGN(DebuggerAgent);
};
#include "stub-cache.h"
#include "log.h"
-#include "../include/v8-debug.h"
-
namespace v8 { namespace internal {
#ifdef ENABLE_DEBUGGER_SUPPORT
// is set the patching performed by the runtime system will take place in
// the code copy and will therefore have no effect on the running code
// keeping it from using the inlined code.
- if (code->is_keyed_load_stub() && KeyedLoadIC::HasInlinedVersion(pc())) {
- KeyedLoadIC::ClearInlinedVersion(pc());
- }
+ if (code->is_keyed_load_stub()) KeyedLoadIC::ClearInlinedVersion(pc());
}
}
return;
}
- // Process debug event.
- ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
+ // Process debug event
+ ProcessDebugEvent(v8::Exception, event_data, false);
// Return to continue execution from where the exception was thrown.
}
return;
}
- // Process debug event.
- ProcessDebugEvent(v8::Break,
- Handle<JSObject>::cast(event_data),
- auto_continue);
+ // Process debug event
+ ProcessDebugEvent(v8::Break, event_data, auto_continue);
}
return;
}
- // Process debug event.
- ProcessDebugEvent(v8::BeforeCompile,
- Handle<JSObject>::cast(event_data),
- true);
+ // Process debug event
+ ProcessDebugEvent(v8::BeforeCompile, event_data, true);
}
if (caught_exception) {
return;
}
- // Process debug event.
- ProcessDebugEvent(v8::AfterCompile,
- Handle<JSObject>::cast(event_data),
- true);
+ // Process debug event
+ ProcessDebugEvent(v8::AfterCompile, event_data, true);
}
return;
}
// Process debug event.
- ProcessDebugEvent(v8::NewFunction, Handle<JSObject>::cast(event_data), true);
+ ProcessDebugEvent(v8::NewFunction, event_data, true);
}
void Debugger::ProcessDebugEvent(v8::DebugEvent event,
- Handle<JSObject> event_data,
+ Handle<Object> event_data,
bool auto_continue) {
HandleScope scope;
}
// First notify the message handler if any.
if (message_handler_ != NULL) {
- NotifyMessageHandler(event,
- Handle<JSObject>::cast(exec_state),
- event_data,
- auto_continue);
+ NotifyMessageHandler(event, exec_state, event_data, auto_continue);
}
// Notify registered debug event listener. This can be either a C or a
// JavaScript function.
FUNCTION_CAST<v8::Debug::EventCallback>(callback_obj->proxy());
callback(event,
v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
- v8::Utils::ToLocal(event_data),
+ v8::Utils::ToLocal(Handle<JSObject>::cast(event_data)),
v8::Utils::ToLocal(Handle<Object>::cast(event_listener_data_)));
} else {
// 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_data.location(),
event_listener_data_.location() };
Handle<Object> result = Execution::TryCall(fun, Top::global(),
argc, argv, &caught_exception);
void Debugger::NotifyMessageHandler(v8::DebugEvent event,
- Handle<JSObject> exec_state,
- Handle<JSObject> event_data,
+ Handle<Object> exec_state,
+ Handle<Object> event_data,
bool auto_continue) {
HandleScope scope;
// Notify the debugger that a debug event has occurred unless auto continue is
// active in which case no event is send.
if (sendEventMessage) {
- MessageImpl message = MessageImpl::NewEvent(
- event,
- auto_continue,
- Handle<JSObject>::cast(exec_state),
- Handle<JSObject>::cast(event_data));
- InvokeMessageHandler(message);
+ InvokeMessageHandlerWithEvent(event_data);
}
if (auto_continue && !HasCommands()) {
return;
request = v8::String::New(command.text().start(),
command.text().length());
+ command.text().Dispose();
static const int kArgc = 1;
v8::Handle<Value> argv[kArgc] = { request };
v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
}
// Return the result.
- MessageImpl message = MessageImpl::NewResponse(
- event,
- running,
- Handle<JSObject>::cast(exec_state),
- Handle<JSObject>::cast(event_data),
- Handle<String>(Utils::OpenHandle(*response)),
- command.client_data());
- InvokeMessageHandler(message);
- command.Dispose();
+ InvokeMessageHandler(response, command.client_data());
// Return from debug event processing if either the VM is put into the
// runnning state (through a continue command) or auto continue is active
// Calls the registered debug message handler. This callback is part of the
-// public API.
-void Debugger::InvokeMessageHandler(MessageImpl message) {
+// public API. Messages are kept internally as Vector<uint16_t> strings, which
+// are allocated in various places and deallocated by the calling function
+// sometime after this call.
+void Debugger::InvokeMessageHandler(v8::Handle<v8::String> output,
+ v8::Debug::ClientData* data) {
ScopedLock with(debugger_access_);
if (message_handler_ != NULL) {
- message_handler_(message);
+ Vector<uint16_t> text = Vector<uint16_t>::New(output->Length());
+ output->Write(text.start(), 0, output->Length());
+
+ message_handler_(text.start(),
+ text.length(),
+ data);
+
+ text.Dispose();
+ }
+ delete data;
+}
+
+
+bool Debugger::InvokeMessageHandlerWithEvent(Handle<Object> event_data) {
+ v8::HandleScope scope;
+ // Call toJSONProtocol on the debug event object.
+ v8::Local<v8::Object> api_event_data =
+ v8::Utils::ToLocal(Handle<JSObject>::cast(event_data));
+ v8::Local<v8::String> fun_name = v8::String::New("toJSONProtocol");
+ v8::Local<v8::Function> fun =
+ v8::Function::Cast(*api_event_data->Get(fun_name));
+ v8::TryCatch try_catch;
+ v8::Local<v8::Value> json_event = *fun->Call(api_event_data, 0, NULL);
+ v8::Local<v8::String> json_event_string;
+ if (!try_catch.HasCaught()) {
+ if (!json_event->IsUndefined()) {
+ json_event_string = json_event->ToString();
+ if (FLAG_trace_debug_json) {
+ PrintLn(json_event_string);
+ }
+ InvokeMessageHandler(json_event_string,
+ NULL /* no user data since there was no request */);
+ } else {
+ InvokeMessageHandler(v8::String::Empty(), NULL);
+ }
+ } else {
+ PrintLn(try_catch.Exception());
+ return false;
}
+ return true;
}
}
-MessageImpl MessageImpl::NewEvent(DebugEvent event,
- bool running,
- Handle<JSObject> exec_state,
- Handle<JSObject> event_data) {
- MessageImpl message(true, event, running,
- exec_state, event_data, Handle<String>(), NULL);
- return message;
-}
-
-
-MessageImpl MessageImpl::NewResponse(DebugEvent event,
- bool running,
- Handle<JSObject> exec_state,
- Handle<JSObject> event_data,
- Handle<String> response_json,
- v8::Debug::ClientData* client_data) {
- MessageImpl message(false, event, running,
- exec_state, event_data, response_json, client_data);
- return message;
-}
-
-
-MessageImpl::MessageImpl(bool is_event,
- DebugEvent event,
- bool running,
- Handle<JSObject> exec_state,
- Handle<JSObject> event_data,
- Handle<String> response_json,
- v8::Debug::ClientData* client_data)
- : is_event_(is_event),
- event_(event),
- running_(running),
- exec_state_(exec_state),
- event_data_(event_data),
- response_json_(response_json),
- client_data_(client_data) {}
-
-
-bool MessageImpl::IsEvent() const {
- return is_event_;
-}
-
-
-bool MessageImpl::IsResponse() const {
- return !is_event_;
-}
-
-
-DebugEvent MessageImpl::GetEvent() const {
- return event_;
-}
-
-
-bool MessageImpl::WillStartRunning() const {
- return running_;
-}
-
-
-v8::Handle<v8::Object> MessageImpl::GetExecutionState() const {
- return v8::Utils::ToLocal(exec_state_);
-}
-
-
-v8::Handle<v8::Object> MessageImpl::GetEventData() const {
- return v8::Utils::ToLocal(event_data_);
-}
-
-
-v8::Handle<v8::String> MessageImpl::GetJSON() const {
- v8::HandleScope scope;
-
- if (IsEvent()) {
- // Call toJSONProtocol on the debug event object.
- Handle<Object> fun = GetProperty(event_data_, "toJSONProtocol");
- if (!fun->IsJSFunction()) {
- return v8::Handle<v8::String>();
- }
- bool caught_exception;
- Handle<Object> json = Execution::TryCall(Handle<JSFunction>::cast(fun),
- event_data_,
- 0, NULL, &caught_exception);
- if (caught_exception || !json->IsString()) {
- return v8::Handle<v8::String>();
- }
- return scope.Close(v8::Utils::ToLocal(Handle<String>::cast(json)));
- } else {
- return v8::Utils::ToLocal(response_json_);
- }
-}
-
-
-v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
- return v8::Handle<v8::Context>();
-}
-
-
-v8::Debug::ClientData* MessageImpl::GetClientData() const {
- return client_data_;
-}
-
-
CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
client_data_(NULL) {
}
};
-// Message delivered to the message handler callback. This is either a debugger
-// event or the response to a command.
-class MessageImpl: public v8::Debug::Message {
- public:
- // Create a message object for a debug event.
- static MessageImpl NewEvent(DebugEvent event,
- bool running,
- Handle<JSObject> exec_state,
- Handle<JSObject> event_data);
-
- // Create a message object for the response to a debug command.
- static MessageImpl NewResponse(DebugEvent event,
- bool running,
- Handle<JSObject> exec_state,
- Handle<JSObject> event_data,
- Handle<String> response_json,
- v8::Debug::ClientData* client_data);
-
- // Implementation of interface v8::Debug::Message.
- virtual bool IsEvent() const;
- virtual bool IsResponse() const;
- virtual DebugEvent GetEvent() const;
- virtual bool WillStartRunning() const;
- virtual v8::Handle<v8::Object> GetExecutionState() const;
- virtual v8::Handle<v8::Object> GetEventData() const;
- virtual v8::Handle<v8::String> GetJSON() const;
- virtual v8::Handle<v8::Context> GetEventContext() const;
- virtual v8::Debug::ClientData* GetClientData() const;
-
- private:
- MessageImpl(bool is_event,
- DebugEvent event,
- bool running,
- Handle<JSObject> exec_state,
- Handle<JSObject> event_data,
- Handle<String> response_json,
- v8::Debug::ClientData* client_data);
-
- bool is_event_; // Does this message represent a debug event?
- DebugEvent event_; // Debug event causing the break.
- bool running_; // Will the VM start running after this event?
- Handle<JSObject> exec_state_; // Current execution state.
- Handle<JSObject> event_data_; // Data associated with the event.
- Handle<String> response_json_; // Response JSON if message holds a response.
- v8::Debug::ClientData* client_data_; // Client data passed with the request.
-};
-
-
// Message send by user to v8 debugger or debugger output message.
// In addition to command text it may contain a pointer to some user data
// which are expected to be passed along with the command reponse to message
Handle<JSFunction> fun);
static void OnNewFunction(Handle<JSFunction> fun);
static void ProcessDebugEvent(v8::DebugEvent event,
- Handle<JSObject> event_data,
+ Handle<Object> event_data,
bool auto_continue);
static void NotifyMessageHandler(v8::DebugEvent event,
- Handle<JSObject> exec_state,
- Handle<JSObject> event_data,
+ Handle<Object> exec_state,
+ Handle<Object> event_data,
bool auto_continue);
static void SetEventListener(Handle<Object> callback, Handle<Object> data);
static void SetMessageHandler(v8::Debug::MessageHandler handler);
int period);
// Invoke the message handler function.
- static void InvokeMessageHandler(MessageImpl message);
+ static void InvokeMessageHandler(v8::Handle<v8::String> output,
+ v8::Debug::ClientData* data);
+
+ // Send the JSON message for a debug event.
+ static bool InvokeMessageHandlerWithEvent(Handle<Object> event_data);
// Add a debugger command to the command queue.
static void ProcessCommand(Vector<const uint16_t> command,
void Run();
};
-static void MessageHandler(const v8::Debug::Message& message) {
+static void MessageHandler(const uint16_t* message, int length,
+ v8::Debug::ClientData* client_data) {
static char print_buffer[1000];
- v8::String::Value json(message.GetJSON());
- Utf16ToAscii(*json, json.length(), print_buffer);
+ Utf16ToAscii(message, length, print_buffer);
if (IsBreakEventMessage(print_buffer)) {
// Lets test script wait until break occurs to send commands.
// Signals when a break is reported.
static int handled_client_data_instances_count = 0;
static void MessageHandlerCountingClientData(
- const v8::Debug::Message& message) {
- if (message.GetClientData() != NULL) {
+ const uint16_t* message,
+ int length,
+ v8::Debug::ClientData* client_data) {
+ if (client_data) {
handled_client_data_instances_count++;
}
}
}
-static void ThreadedMessageHandler(const v8::Debug::Message& message) {
+static void ThreadedMessageHandler(const uint16_t* message, int length,
+ v8::Debug::ClientData* client_data) {
static char print_buffer[1000];
- v8::String::Value json(message.GetJSON());
- Utf16ToAscii(*json, json.length(), print_buffer);
+ Utf16ToAscii(message, length, print_buffer);
if (IsBreakEventMessage(print_buffer)) {
threaded_debugging_barriers.barrier_2.Wait();
}
Barriers* breakpoints_barriers;
-static void BreakpointsMessageHandler(const v8::Debug::Message& message) {
+static void BreakpointsMessageHandler(const uint16_t* message,
+ int length,
+ v8::Debug::ClientData* client_data) {
static char print_buffer[1000];
- v8::String::Value json(message.GetJSON());
- Utf16ToAscii(*json, json.length(), print_buffer);
+ Utf16ToAscii(message, length, print_buffer);
printf("%s\n", print_buffer);
fflush(stdout);
}
-static void DummyMessageHandler(const v8::Debug::Message& message) {
+static void DummyMessageHandler(const uint16_t* message,
+ int length,
+ v8::Debug::ClientData* client_data) {
}
// Debugger message handler which counts the number of times it is called.
static int message_handler_hit_count = 0;
-static void MessageHandlerHitCount(const v8::Debug::Message& message) {
+static void MessageHandlerHitCount(const uint16_t* message,
+ int length,
+ v8::Debug::ClientData* client_data) {
message_handler_hit_count++;
const int kBufferSize = 1000;
// Debugger message handler which clears the message handler while active.
static void MessageHandlerClearingMessageHandler(
- const v8::Debug::Message& message) {
+ const uint16_t* message,
+ int length,
+ v8::Debug::ClientData* client_data) {
message_handler_hit_count++;
// Clear debug message handler.
Barriers* host_dispatch_barriers;
-static void HostDispatchMessageHandler(const v8::Debug::Message& message) {
+static void HostDispatchMessageHandler(const uint16_t* message,
+ int length,
+ v8::Debug::ClientData* client_data) {
static char print_buffer[1000];
- v8::String::Value json(message.GetJSON());
- Utf16ToAscii(*json, json.length(), print_buffer);
+ Utf16ToAscii(message, length, print_buffer);
printf("%s\n", print_buffer);
fflush(stdout);
}