Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion lib/debug/frame_info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,11 @@ def other_identifier
end

def callee
self._callee ||= self.binding&.eval('__callee__')
self._callee ||= begin
self.binding&.eval('__callee__')
rescue NameError # BasicObject
nil
end
end

def return_str
Expand Down
18 changes: 10 additions & 8 deletions lib/debug/server_dap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -718,10 +718,10 @@ def process_dap args
]
end

vars += obj.instance_variables.map{|iv|
variable(iv, obj.instance_variable_get(iv))
vars += M_INSTANCE_VARIABLES.bind_call(obj).map{|iv|
variable(iv, M_INSTANCE_VARIABLE_GET.bind_call(obj, iv))
}
vars.unshift variable('#class', obj.class)
vars.unshift variable('#class', M_CLASS.bind_call(obj))
end
end
event! :dap_result, :variable, req, variables: (vars || []), tid: self.id
Expand All @@ -748,7 +748,7 @@ def process_dap args
case expr
when /\A\@\S/
begin
result = b.receiver.instance_variable_get(expr)
result = M_INSTANCE_VARIABLE_GET.bind_call(b.receiver, expr)
rescue NameError
message = "Error: Not defined instance variable: #{expr.inspect}"
end
Expand All @@ -759,6 +759,8 @@ def process_dap args
break false
end
} and (message = "Error: Not defined global variable: #{expr.inspect}")
when /\Aself$/
result = b.receiver
when /(\A((::[A-Z]|[A-Z])\w*)+)/
unless result = search_const(b, $1)
message = "Error: Not defined constants: #{expr.inspect}"
Expand All @@ -768,8 +770,8 @@ def process_dap args
result = b.local_variable_get(expr)
rescue NameError
# try to check method
if b.receiver.respond_to? expr, include_all: true
result = b.receiver.method(expr)
if M_RESPOND_TO_P.bind_call(b.receiver, expr, include_all: true)
result = M_METHOD.bind_call(b.receiver, expr)
else
message = "Error: Can not evaluate: #{expr.inspect}"
end
Expand Down Expand Up @@ -849,11 +851,11 @@ def variable_ name, obj, indexedVariables: 0, namedVariables: 0
vid = 0
end

ivnum = obj.instance_variables.size
ivnum = M_INSTANCE_VARIABLES.bind_call(obj).size

{ name: name,
value: DEBUGGER__.safe_inspect(obj),
type: obj.class.name || obj.class.to_s,
type: (klass = M_CLASS.bind_call(obj)).name || klass.to_s,
variablesReference: vid,
indexedVariables: indexedVariables,
namedVariables: namedVariables + ivnum,
Expand Down
9 changes: 9 additions & 0 deletions lib/debug/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2310,3 +2310,12 @@ class Binding
alias break debugger
alias b debugger
end

# for Ruby 2.6 compatibility
unless method(:p).unbind.respond_to? :bind_call
class UnboundMethod
def bind_call(obj, *args)
self.bind(obj).call(*args)
end
end
end
38 changes: 27 additions & 11 deletions lib/debug/thread_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
require_relative 'color'

module DEBUGGER__
M_INSTANCE_VARIABLES = method(:instance_variables).unbind
M_INSTANCE_VARIABLE_GET = method(:instance_variable_get).unbind
M_CLASS = method(:class).unbind
M_SINGLETON_CLASS = method(:singleton_class).unbind
M_KIND_OF_P = method(:kind_of?).unbind
M_RESPOND_TO_P = method(:respond_to?).unbind
M_METHOD = method(:method).unbind
M_OBJECT_ID = method(:object_id).unbind

module SkipPathHelper
def skip_path?(path)
CONFIG.skip? || !path ||
Expand Down Expand Up @@ -532,8 +541,8 @@ def show_locals pat

def show_ivars pat
if s = current_frame&.self
s.instance_variables.sort.each{|iv|
value = s.instance_variable_get(iv)
M_INSTANCE_VARIABLES.bind_call(s).sort.each{|iv|
value = M_INSTANCE_VARIABLE_GET.bind_call(s, iv)
puts_variable_info iv, value, pat
}
end
Expand All @@ -542,10 +551,10 @@ def show_ivars pat
def show_consts pat, only_self: false
if s = current_frame&.self
cs = {}
if s.kind_of? Module
if M_KIND_OF_P.bind_call(s, Module)
cs[s] = :self
else
s = s.class
s = M_CLASS.bind_call(s)
cs[s] = :self unless only_self
end

Expand Down Expand Up @@ -583,7 +592,7 @@ def puts_variable_info label, obj, pat
return if pat && pat !~ label

begin
inspected = obj.inspect
inspected = DEBUGGER__.safe_inspect(obj)
rescue Exception => e
inspected = e.inspect
end
Expand Down Expand Up @@ -687,18 +696,25 @@ def show_outline expr
o = Output.new(@output)

locals = current_frame&.local_variables
klass = (obj.class == Class || obj.class == Module ? obj : obj.class)

o.dump("constants", obj.constants) if obj.respond_to?(:constants)
klass = M_CLASS.bind_call(obj)
klass = obj if Class == klass || Module == klass

o.dump("constants", obj.constants) if M_RESPOND_TO_P.bind_call(obj, :constants)
outline_method(o, klass, obj)
o.dump("instance variables", obj.instance_variables)
o.dump("instance variables", M_INSTANCE_VARIABLES.bind_call(obj))
o.dump("class variables", klass.class_variables)
o.dump("locals", locals.keys) if locals
end
end

def outline_method(o, klass, obj)
singleton_class = begin obj.singleton_class; rescue TypeError; nil end
begin
singleton_class = M_SINGLETON_CLASS.bind_call(obj)
rescue TypeError
singleton_class = nil
end

maps = class_method_map((singleton_class || klass).ancestors)
maps.each do |mod, methods|
name = mod == singleton_class ? "#{klass}.methods" : "#{mod}#methods"
Expand Down Expand Up @@ -1000,15 +1016,15 @@ def wait_next_action_
begin
obj = frame_eval args.shift, re_raise: true
opt = args.shift
obj_inspect = obj.inspect
obj_inspect = DEBUGGER__.safe_inspect(obj)

width = 50

if obj_inspect.length >= width
obj_inspect = truncate(obj_inspect, width: width)
end

event! :result, :trace_pass, obj.object_id, obj_inspect, opt
event! :result, :trace_pass, M_OBJECT_ID.bind_call(obj), obj_inspect, opt
rescue => e
puts e.message
event! :result, nil
Expand Down
2 changes: 1 addition & 1 deletion lib/debug/tracer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def setup
@tracer = TracePoint.new(:a_call){|tp|
next if skip?(tp)

if tp.self.object_id == @obj_id
if M_OBJECT_ID.bind_call(tp.self) == @obj_id
klass = tp.defined_class
method = tp.method_id
method_info =
Expand Down