class Byebug::DAP::Session
Public Class Methods
Record a {ChildSpawnedEventBody childSpawned event} and send the event to the current session's client, if {gem:byebug:Byebug::Context.interface} is a {Session}.
# File lib/byebug/dap/session.rb, line 21 def self.child_spawned(name, pid, socket) child = ChildSpawnedEventBody.new(name: name, pid: pid, socket: socket) (@@children ||= []) << child session = Context.interface return false unless session.is_a?(Session) session.event! child return true rescue IOError, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNABORTED return false end
Create a new session instance. @param connection [std:IO] the connection to the client @param ios [CapturedIO] the captured IO @yield called once the client is done configuring the session (optional)
# File lib/byebug/dap/session.rb, line 39 def initialize(connection, ios = nil, &block) @connection = connection @ios = ios @on_configured = block @pid = Process.pid @log_points = {} @frame_ids = Handles.new @variable_refs = Handles.new @trace = TracePoint.new(:thread_begin, :thread_end) { |t| process_trace t } notify_of_children end
Call {Session#stop!} on {gem:byebug:Byebug::Context.interface} if it is a {Session}. @return [Boolean] whether {gem:byebug:Byebug::Context.interface} was a {Session}
# File lib/byebug/dap/session.rb, line 10 def self.stop! session = Byebug::Context.interface return false unless session.is_a?(Session) session.stop! true end
Public Instance Methods
Delete the specified breakpoints and any log points associated with them. @param breakpoints [std:Array<gem:byebug:Byebug::Breakpoint>] the breakpoints
# File lib/byebug/dap/session.rb, line 191 def clear_breakpoints(*breakpoints) breakpoints.each do |breakpoint| Byebug.breakpoints.delete(breakpoint) @log_points.delete(breakpoint.id) end end
Call the block passed to {#initialize}. @note This should only be used by the {Command::ConfigurationDone configurationDone} commands @api private
# File lib/byebug/dap/session.rb, line 97 def configured! return unless @on_configured callback, @on_configured = @on_configured, callback callback.call end
Send an event to the client. Either call with an event name and body attributes, or call with an already constructed body. @param event [std:String|Protocol::Base] the event name or event body @param values [std:Hash] event body attributes
# File lib/byebug/dap/session.rb, line 119 def event!(event, **values) if (cls = event.class.name.split('::').last) && cls.end_with?('EventBody') body, event = event, cls[0].downcase + cls[1...-9] elsif event.is_a?(String) && !values.empty? body = Protocol.const_get("#{event[0].upcase}#{event[1..]}EventBody").new(values) end send Protocol::Event.new(event: event, body: body) end
Execute requests from the client until the connection is closed.
# File lib/byebug/dap/session.rb, line 66 def execute Context.interface = self Context.processor = DAP::CommandProcessor Command.execute(self, receive) until @connection.closed? Context.interface = LocalInterface.new end
Get the log point expression associated with `breakpoint`. @param breakpoint [gem:byebug:Byebug::Breakpoint] the breakpoint @return [std:String] the log point expression @note This should only be used by a {CommandProcessor command processor} @api private
# File lib/byebug/dap/session.rb, line 171 def get_log_point(breakpoint) @log_points[breakpoint.id] end
Invalidate frame IDs and variables references. @note This should only be used by a {ContextualCommand contextual command} that un-pauses its context @api private
# File lib/byebug/dap/session.rb, line 78 def invalidate_handles! @frame_ids.clear! @variable_refs.clear! end
Write a message to the log.
# File lib/byebug/dap/session.rb, line 53 def log(*args) logger = if @ios @ios.log elsif defined?(LOG) LOG else STDERR end logger.puts(*args) end
Send a response to the client. @param request [Protocol::Request] the request to respond to @param body [std:Hash|Protocol::Base] the response body @param success [std:Boolean] whether the request was successful @param message [std:String] the response message @param values [std:Hash] additional response attributes
# File lib/byebug/dap/session.rb, line 136 def respond!(request, body = nil, success: true, message: 'Success', **values) send Protocol::Response.new( request_seq: request.seq, command: request.command, success: success, message: message, body: body, **values) end
Restore a frame from an ID.
# File lib/byebug/dap/session.rb, line 162 def restore_frame(id) @frame_ids[id] end
Retrieve variables from a reference.
# File lib/byebug/dap/session.rb, line 152 def restore_variables(ref) @variable_refs[ref] end
Create a frame ID.
# File lib/byebug/dap/session.rb, line 157 def save_frame(*args) @frame_ids << args end
Create a variables reference.
# File lib/byebug/dap/session.rb, line 147 def save_variables(*args) @variable_refs << args end
Associate a log point expression with `breakpoint`. @param breakpoint [gem:byebug:Byebug::Breakpoint] the breakpoint @param expr [std:String] the log point expression @note This should only be used by a {CommandProcessor command processor} @api private
# File lib/byebug/dap/session.rb, line 180 def set_log_point(breakpoint, expr) if expr.nil? || expr.empty? @log_points.delete(breakpoint.id) else @log_points[breakpoint.id] = expr end end
Start Byebug
. @param mode [std:Symbol] `:attached` or `:launched` @note This should only be used by the {Command::Attach attach} or {Command::Launch launch} commands @api private
# File lib/byebug/dap/session.rb, line 87 def start!(mode) @trace.enable Byebug.mode = mode Byebug.start @exit_on_stop = true if mode == :launched end
Stop Byebug
and close the client's connection. @note If the session was started with the `launch` command, this will {std:Kernel#exit exit}
# File lib/byebug/dap/session.rb, line 106 def stop! exit if @exit_on_stop && @pid == Process.pid Byebug.mode = :off Byebug.stop @trace.disable @connection.close end
Private Instance Methods
# File lib/byebug/dap/session.rb, line 200 def notify_of_children @@children.each { |c| event! c } if defined?(@@children) rescue IOError, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNABORTED # client is closed end
# File lib/byebug/dap/session.rb, line 218 def process_trace(trace) return unless Byebug.started? ctx = Byebug.contexts.find { |c| c.thread == Thread.current } case trace.event when :thread_begin event! 'thread', reason: 'started', threadId: ctx.thnum when :thread_end event! 'thread', reason: 'exited', threadId: ctx.thnum end rescue IOError, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNABORTED # client disconnected, ignore error end
# File lib/byebug/dap/session.rb, line 212 def receive m = Protocol.decode(@connection) log "#{Process.pid} < #{m.to_wire}" if Debug.protocol m end
# File lib/byebug/dap/session.rb, line 206 def send(message) log "#{Process.pid} > #{message.to_wire}" if Debug.protocol message.validate! @connection.write Protocol.encode(message) end