| Index: src/debug/debug.h
|
| diff --git a/src/debug/debug.h b/src/debug/debug.h
|
| index 2ca740fb90c84981145ac3f0c459001102e5c851..86c5b4bf3f4e79ee515c587f021472d8252b3b6b 100644
|
| --- a/src/debug/debug.h
|
| +++ b/src/debug/debug.h
|
| @@ -244,16 +244,62 @@
|
| DebugInfoListNode* next_;
|
| };
|
|
|
| +// 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::Local<v8::Object> GetExecutionState() const;
|
| + virtual v8::Local<v8::Object> GetEventData() const;
|
| + virtual v8::Local<v8::String> GetJSON() const;
|
| + virtual v8::Local<v8::Context> GetEventContext() const;
|
| + virtual v8::Debug::ClientData* GetClientData() const;
|
| + virtual v8::Isolate* GetIsolate() 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.
|
| +};
|
| +
|
| // 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);
|
| + EventDetailsImpl(DebugEvent event,
|
| + Handle<JSObject> exec_state,
|
| + Handle<JSObject> event_data,
|
| + Handle<Object> callback_data,
|
| + v8::Debug::ClientData* client_data);
|
| virtual DebugEvent GetEvent() const;
|
| virtual v8::Local<v8::Object> GetExecutionState() const;
|
| virtual v8::Local<v8::Object> GetEventData() const;
|
| virtual v8::Local<v8::Context> GetEventContext() const;
|
| virtual v8::Local<v8::Value> GetCallbackData() const;
|
| + virtual v8::Debug::ClientData* GetClientData() const;
|
| virtual v8::Isolate* GetIsolate() const;
|
|
|
| private:
|
| @@ -262,8 +308,70 @@
|
| Handle<JSObject> event_data_; // Data associated with the event.
|
| Handle<Object> callback_data_; // User data passed with the callback
|
| // when it was registered.
|
| -};
|
| -
|
| + v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand.
|
| +};
|
| +
|
| +// 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
|
| +// handler.
|
| +class CommandMessage {
|
| + public:
|
| + static CommandMessage New(const Vector<uint16_t>& command,
|
| + v8::Debug::ClientData* data);
|
| + CommandMessage();
|
| +
|
| + // Deletes user data and disposes of the text.
|
| + void Dispose();
|
| + Vector<uint16_t> text() const { return text_; }
|
| + v8::Debug::ClientData* client_data() const { return client_data_; }
|
| +
|
| + private:
|
| + CommandMessage(const Vector<uint16_t>& text, v8::Debug::ClientData* data);
|
| +
|
| + Vector<uint16_t> text_;
|
| + v8::Debug::ClientData* client_data_;
|
| +};
|
| +
|
| +// A Queue of CommandMessage objects. A thread-safe version is
|
| +// LockingCommandMessageQueue, based on this class.
|
| +class CommandMessageQueue BASE_EMBEDDED {
|
| + public:
|
| + explicit CommandMessageQueue(int size);
|
| + ~CommandMessageQueue();
|
| + bool IsEmpty() const { return start_ == end_; }
|
| + CommandMessage Get();
|
| + void Put(const CommandMessage& message);
|
| + void Clear() { start_ = end_ = 0; } // Queue is empty after Clear().
|
| +
|
| + private:
|
| + // Doubles the size of the message queue, and copies the messages.
|
| + void Expand();
|
| +
|
| + CommandMessage* messages_;
|
| + int start_;
|
| + int end_;
|
| + int size_; // The size of the queue buffer. Queue can hold size-1 messages.
|
| +};
|
| +
|
| +// LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage
|
| +// messages. The message data is not managed by LockingCommandMessageQueue.
|
| +// Pointers to the data are passed in and out. Implemented by adding a
|
| +// Mutex to CommandMessageQueue. Includes logging of all puts and gets.
|
| +class LockingCommandMessageQueue BASE_EMBEDDED {
|
| + public:
|
| + LockingCommandMessageQueue(Logger* logger, int size);
|
| + bool IsEmpty() const;
|
| + CommandMessage Get();
|
| + void Put(const CommandMessage& message);
|
| + void Clear();
|
| +
|
| + private:
|
| + Logger* logger_;
|
| + CommandMessageQueue queue_;
|
| + mutable base::Mutex mutex_;
|
| + DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
|
| +};
|
|
|
| class DebugFeatureTracker {
|
| public:
|
| @@ -297,7 +405,7 @@
|
| class Debug {
|
| public:
|
| // Debug event triggers.
|
| - void OnDebugBreak(Handle<Object> break_points_hit);
|
| + void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
|
|
|
| void OnThrow(Handle<Object> exception);
|
| void OnPromiseReject(Handle<Object> promise, Handle<Object> value);
|
| @@ -307,10 +415,14 @@
|
|
|
| // API facing.
|
| void SetEventListener(Handle<Object> callback, Handle<Object> data);
|
| + void SetMessageHandler(v8::Debug::MessageHandler handler);
|
| + void EnqueueCommandMessage(Vector<const uint16_t> command,
|
| + v8::Debug::ClientData* client_data = NULL);
|
| MUST_USE_RESULT MaybeHandle<Object> Call(Handle<Object> fun,
|
| Handle<Object> data);
|
| Handle<Context> GetDebugContext();
|
| void HandleDebugBreak();
|
| + void ProcessDebugMessages(bool debug_command_only);
|
|
|
| // Internal logic
|
| bool Load();
|
| @@ -467,6 +579,8 @@
|
| thread_local_.break_id_ = ++thread_local_.break_count_;
|
| }
|
|
|
| + // Check whether there are commands in the command queue.
|
| + inline bool has_commands() const { return !command_queue_.IsEmpty(); }
|
| inline bool ignore_events() const {
|
| return is_suppressed_ || !is_active_ || isolate_->needs_side_effect_check();
|
| }
|
| @@ -490,7 +604,8 @@
|
| // is presented. Other clients can install JavaScript event listener
|
| // (e.g. some of NodeJS module).
|
| bool non_inspector_listener_exists() const {
|
| - return !event_listener_.is_null() && !event_listener_->IsForeign();
|
| + return message_handler_ != nullptr ||
|
| + (!event_listener_.is_null() && !event_listener_->IsForeign());
|
| }
|
|
|
| void OnException(Handle<Object> exception, Handle<Object> promise);
|
| @@ -511,8 +626,16 @@
|
| // Mirror cache handling.
|
| void ClearMirrorCache();
|
|
|
| + void CallEventCallback(v8::DebugEvent event,
|
| + Handle<Object> exec_state,
|
| + Handle<Object> event_data,
|
| + v8::Debug::ClientData* client_data);
|
| void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script);
|
| - void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data);
|
| + void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data,
|
| + bool auto_continue);
|
| + void NotifyMessageHandler(v8::DebugEvent event, Handle<JSObject> exec_state,
|
| + Handle<JSObject> event_data, bool auto_continue);
|
| + void InvokeMessageHandler(MessageImpl message);
|
|
|
| // Find the closest source position for a break point for a given position.
|
| int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position,
|
| @@ -553,7 +676,13 @@
|
| Handle<Object> event_listener_;
|
| Handle<Object> event_listener_data_;
|
|
|
| + v8::Debug::MessageHandler message_handler_;
|
| +
|
| debug::DebugEventListener* debug_event_listener_ = nullptr;
|
| +
|
| + static const int kQueueInitialSize = 4;
|
| + base::Semaphore command_received_; // Signaled for each command received.
|
| + LockingCommandMessageQueue command_queue_;
|
|
|
| // Debugger is active, i.e. there is a debug event listener attached.
|
| bool is_active_;
|
|
|