/**
+ * An event details object passed to the debug event listener.
+ */
+ class EventDetails {
+ public:
+ /**
+ * Event type.
+ */
+ virtual DebugEvent GetEvent() const = 0;
+
+ /**
+ * Access to execution state and event data of the debug event. Don't store
+ * these cross callbacks as their content becomes invalid.
+ */
+ virtual Handle<Object> GetExecutionState() const = 0;
+ virtual Handle<Object> GetEventData() 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 callbak whet it was registered.
+ */
+ virtual Handle<Value> GetCallbackData() const = 0;
+
+ virtual ~EventDetails() {}
+ };
+
+
+ /**
* Debug event callback function.
*
* \param event the type of the debug event that triggered the callback
Handle<Object> event_data,
Handle<Value> data);
+ /**
+ * Debug event callback function.
+ *
+ * \param event_details object providing information about the debug event
+ *
+ * A EventCallback2 does not take possession of the event data,
+ * and must not rely on the data persisting after the handler returns.
+ */
+ typedef void (*EventCallback2)(const EventDetails& event_details);
/**
* Debug message callback function.
* \param length length of the message
* \param client_data the data value passed when registering the message handler
- * A MessageHandler does not take posession of the message string,
+ * A MessageHandler does not take possession of the message string,
* and must not rely on the data persisting after the handler returns.
*
* This message handler is deprecated. Use MessageHandler2 instead.
*
* \param message the debug message handler message object
- * A MessageHandler does not take posession of the message data,
+ * A MessageHandler does not take possession of the message data,
* and must not rely on the data persisting after the handler returns.
*/
typedef void (*MessageHandler2)(const Message& message);
// Set a C debug event listener.
static bool SetDebugEventListener(EventCallback that,
Handle<Value> data = Handle<Value>());
+ static bool SetDebugEventListener2(EventCallback2 that,
+ Handle<Value> data = Handle<Value>());
// Set a JavaScript debug event listener.
static bool SetDebugEventListener(v8::Handle<v8::Object> that,
// --- D e b u g S u p p o r t ---
#ifdef ENABLE_DEBUGGER_SUPPORT
+
+static v8::Debug::EventCallback event_callback = NULL;
+
+static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
+ if (event_callback) {
+ event_callback(event_details.GetEvent(),
+ event_details.GetExecutionState(),
+ event_details.GetEventData(),
+ event_details.GetCallbackData());
+ }
+}
+
+
bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
EnsureInitialized("v8::Debug::SetDebugEventListener()");
ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
ENTER_V8;
+
+ event_callback = that;
+
+ HandleScope scope;
+ i::Handle<i::Object> proxy = i::Factory::undefined_value();
+ if (that != NULL) {
+ proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
+ }
+ i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
+ return true;
+}
+
+
+bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
+ EnsureInitialized("v8::Debug::SetDebugEventListener2()");
+ ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
+ ENTER_V8;
HandleScope scope;
i::Handle<i::Object> proxy = i::Factory::undefined_value();
if (that != NULL) {
}
+static v8::Handle<v8::Context> GetDebugEventContext() {
+ Handle<Context> context = Debug::debugger_entry()->GetContext();
+ // Top::context() may have been NULL when "script collected" event occured.
+ if (*context == NULL) {
+ return v8::Local<v8::Context>();
+ }
+ Handle<Context> global_context(context->global_context());
+ return v8::Utils::ToLocal(global_context);
+}
+
+
BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
BreakLocatorType type) {
debug_info_ = debug_info;
if (event_listener_->IsProxy()) {
// C debug event listener.
Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_));
- v8::Debug::EventCallback callback =
- 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<Object>::cast(event_listener_data_)));
+ 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());
v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
- Handle<Context> context = Debug::debugger_entry()->GetContext();
- // Top::context() may have been NULL when "script collected" event occured.
- if (*context == NULL) {
- ASSERT(event_ == v8::ScriptCollected);
- return v8::Local<v8::Context>();
- }
- Handle<Context> global_context(context->global_context());
- return v8::Utils::ToLocal(global_context);
+ v8::Handle<v8::Context> context = GetDebugEventContext();
+ // Top::context() may be NULL when "script collected" event occures.
+ ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected);
+ return GetDebugEventContext();
}
}
+EventDetailsImpl::EventDetailsImpl(DebugEvent event,
+ Handle<JSObject> exec_state,
+ Handle<JSObject> event_data,
+ Handle<Object> callback_data)
+ : event_(event),
+ exec_state_(exec_state),
+ event_data_(event_data),
+ callback_data_(callback_data) {}
+
+
+DebugEvent EventDetailsImpl::GetEvent() const {
+ return event_;
+}
+
+
+v8::Handle<v8::Object> EventDetailsImpl::GetExecutionState() const {
+ return v8::Utils::ToLocal(exec_state_);
+}
+
+
+v8::Handle<v8::Object> EventDetailsImpl::GetEventData() const {
+ return v8::Utils::ToLocal(event_data_);
+}
+
+
+v8::Handle<v8::Context> EventDetailsImpl::GetEventContext() const {
+ return GetDebugEventContext();
+}
+
+
+v8::Handle<v8::Value> EventDetailsImpl::GetCallbackData() const {
+ return v8::Utils::ToLocal(callback_data_);
+}
+
+
CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
client_data_(NULL) {
}
};
+// Details of the debug event delivered to the debug event listener.
+class EventDetailsImpl : public v8::Debug::EventDetails {
+ public:
+ EventDetailsImpl(DebugEvent event,
+ Handle<JSObject> exec_state,
+ Handle<JSObject> event_data,
+ Handle<Object> callback_data);
+ virtual DebugEvent GetEvent() const;
+ virtual v8::Handle<v8::Object> GetExecutionState() const;
+ virtual v8::Handle<v8::Object> GetEventData() const;
+ virtual v8::Handle<v8::Context> GetEventContext() const;
+ virtual v8::Handle<v8::Value> GetCallbackData() const;
+ private:
+ DebugEvent event_; // Debug event causing the break.
+ Handle<JSObject> exec_state_; // Current execution state.
+ Handle<JSObject> event_data_; // Data associated with the event.
+ Handle<Object> callback_data_; // User data passed with the callback when
+ // it was registered.
+};
+
+
// 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
v8::Local<v8::Context> context1 = v8::Debug::GetDebugContext();
v8::Local<v8::Context> context2 = v8::Debug::GetDebugContext();
CHECK_EQ(*context1, *context2);
- // Make sure debugger is unloaded before running other tests.
- v8::internal::ForceUnloadDebugger();
+}
+
+
+static v8::Handle<v8::Value> expected_callback_data;
+static void DebugEventContextChecker(const v8::Debug::EventDetails& details) {
+ CHECK(details.GetEventContext() == expected_context);
+ CHECK_EQ(expected_callback_data, details.GetCallbackData());
+}
+
+// Check that event details contain context where debug event occured.
+TEST(DebugEventContext) {
+ v8::HandleScope scope;
+ expected_callback_data = v8::Int32::New(2010);
+ v8::Debug::SetDebugEventListener2(DebugEventContextChecker,
+ expected_callback_data);
+ expected_context = v8::Context::New();
+ v8::Context::Scope context_scope(expected_context);
+ v8::Script::Compile(v8::String::New("(function(){debugger;})();"))->Run();
+ expected_context.Dispose();
+ expected_context.Clear();
+ v8::Debug::SetDebugEventListener(NULL);
+ expected_context_data = v8::Handle<v8::Value>();
CheckDebuggerUnloaded();
}
+