debug 1.7.1 → 1.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +2 -2
- data/README.md +50 -44
- data/Rakefile +8 -3
- data/debug.gemspec +3 -3
- data/ext/debug/debug.c +18 -4
- data/ext/debug/extconf.rb +1 -0
- data/ext/debug/iseq_collector.c +2 -0
- data/lib/debug/breakpoint.rb +6 -8
- data/lib/debug/client.rb +3 -2
- data/lib/debug/config.rb +35 -7
- data/lib/debug/console.rb +8 -29
- data/lib/debug/dap_custom/traceInspector.rb +336 -0
- data/lib/debug/frame_info.rb +9 -0
- data/lib/debug/irb_integration.rb +27 -0
- data/lib/debug/server.rb +9 -8
- data/lib/debug/server_cdp.rb +71 -72
- data/lib/debug/server_dap.rb +227 -179
- data/lib/debug/session.rb +105 -58
- data/lib/debug/source_repository.rb +3 -3
- data/lib/debug/thread_client.rb +51 -25
- data/lib/debug/tracer.rb +4 -5
- data/lib/debug/version.rb +1 -1
- data/misc/README.md.erb +42 -42
- metadata +12 -10
data/lib/debug/session.rb
CHANGED
@@ -82,7 +82,7 @@ class RubyVM::InstructionSequence
|
|
82
82
|
def first_line
|
83
83
|
self.to_a[4][:code_location][0]
|
84
84
|
end unless method_defined?(:first_line)
|
85
|
-
end
|
85
|
+
end if defined?(RubyVM::InstructionSequence)
|
86
86
|
|
87
87
|
module DEBUGGER__
|
88
88
|
PresetCommands = Struct.new(:commands, :source, :auto_continue)
|
@@ -128,16 +128,16 @@ module DEBUGGER__
|
|
128
128
|
@obj_map = {} # { object_id => ... } for CDP
|
129
129
|
|
130
130
|
@tp_thread_begin = nil
|
131
|
+
@tp_thread_end = nil
|
132
|
+
|
131
133
|
@commands = {}
|
132
134
|
@unsafe_context = false
|
133
135
|
|
134
|
-
has_keep_script_lines = RubyVM.
|
136
|
+
@has_keep_script_lines = defined?(RubyVM.keep_script_lines)
|
135
137
|
|
136
138
|
@tp_load_script = TracePoint.new(:script_compiled){|tp|
|
137
|
-
|
138
|
-
|
139
|
-
ThreadClient.current.on_load tp.instruction_sequence, eval_script
|
140
|
-
end
|
139
|
+
eval_script = tp.eval_script unless @has_keep_script_lines
|
140
|
+
ThreadClient.current.on_load tp.instruction_sequence, eval_script
|
141
141
|
}
|
142
142
|
@tp_load_script.enable
|
143
143
|
|
@@ -169,12 +169,17 @@ module DEBUGGER__
|
|
169
169
|
@ui = ui if ui
|
170
170
|
|
171
171
|
@tp_thread_begin&.disable
|
172
|
+
@tp_thread_end&.disable
|
172
173
|
@tp_thread_begin = nil
|
173
|
-
|
174
|
+
@tp_thread_end = nil
|
174
175
|
@ui.activate self, on_fork: on_fork
|
175
176
|
|
176
177
|
q = Queue.new
|
178
|
+
first_q = Queue.new
|
177
179
|
@session_server = Thread.new do
|
180
|
+
# make sure `@session_server` is assigned
|
181
|
+
first_q.pop; first_q = nil
|
182
|
+
|
178
183
|
Thread.current.name = 'DEBUGGER__::SESSION@server'
|
179
184
|
Thread.current.abort_on_exception = true
|
180
185
|
|
@@ -192,10 +197,21 @@ module DEBUGGER__
|
|
192
197
|
end
|
193
198
|
@tp_thread_begin.enable
|
194
199
|
|
200
|
+
@tp_thread_end = TracePoint.new(:thread_end) do |tp|
|
201
|
+
@th_clients.delete(Thread.current)
|
202
|
+
end
|
203
|
+
@tp_thread_end.enable
|
204
|
+
|
205
|
+
if CONFIG[:irb_console] && !CONFIG[:open]
|
206
|
+
require_relative "irb_integration"
|
207
|
+
thc.activate_irb_integration
|
208
|
+
end
|
209
|
+
|
195
210
|
# session start
|
196
211
|
q << true
|
197
212
|
session_server_main
|
198
213
|
end
|
214
|
+
first_q << :ok
|
199
215
|
|
200
216
|
q.pop
|
201
217
|
end
|
@@ -205,6 +221,7 @@ module DEBUGGER__
|
|
205
221
|
@thread_stopper.disable
|
206
222
|
@tp_load_script.disable
|
207
223
|
@tp_thread_begin.disable
|
224
|
+
@tp_thread_end.disable
|
208
225
|
@bps.each_value{|bp| bp.disable}
|
209
226
|
@th_clients.each_value{|thc| thc.close}
|
210
227
|
@tracers.values.each{|t| t.disable}
|
@@ -219,11 +236,13 @@ module DEBUGGER__
|
|
219
236
|
|
220
237
|
# activate new ui
|
221
238
|
@tp_thread_begin.disable
|
239
|
+
@tp_thread_end.disable
|
222
240
|
@ui.activate self
|
223
241
|
if @ui.respond_to?(:reader_thread) && thc = get_thread_client(@ui.reader_thread)
|
224
242
|
thc.mark_as_management
|
225
243
|
end
|
226
244
|
@tp_thread_begin.enable
|
245
|
+
@tp_thread_end.enable
|
227
246
|
end
|
228
247
|
|
229
248
|
def pop_event
|
@@ -242,6 +261,15 @@ module DEBUGGER__
|
|
242
261
|
@tc << req
|
243
262
|
end
|
244
263
|
|
264
|
+
def request_tc_with_restarted_threads(req)
|
265
|
+
restart_all_threads
|
266
|
+
request_tc(req)
|
267
|
+
end
|
268
|
+
|
269
|
+
def request_eval type, src
|
270
|
+
request_tc_with_restarted_threads [:eval, type, src]
|
271
|
+
end
|
272
|
+
|
245
273
|
def process_event evt
|
246
274
|
# variable `@internal_info` is only used for test
|
247
275
|
tc, output, ev, @internal_info, *ev_args = evt
|
@@ -300,7 +328,7 @@ module DEBUGGER__
|
|
300
328
|
if @displays.empty?
|
301
329
|
wait_command_loop
|
302
330
|
else
|
303
|
-
|
331
|
+
request_eval :display, @displays
|
304
332
|
end
|
305
333
|
when :result
|
306
334
|
raise "[BUG] not in subsession" if @subsession_stack.empty?
|
@@ -315,6 +343,7 @@ module DEBUGGER__
|
|
315
343
|
end
|
316
344
|
end
|
317
345
|
|
346
|
+
stop_all_threads
|
318
347
|
when :method_breakpoint, :watch_breakpoint
|
319
348
|
bp = ev_args[1]
|
320
349
|
if bp
|
@@ -328,17 +357,15 @@ module DEBUGGER__
|
|
328
357
|
obj_inspect = ev_args[2]
|
329
358
|
opt = ev_args[3]
|
330
359
|
add_tracer ObjectTracer.new(@ui, obj_id, obj_inspect, **opt)
|
360
|
+
stop_all_threads
|
331
361
|
else
|
332
|
-
|
362
|
+
stop_all_threads
|
333
363
|
end
|
334
364
|
|
335
365
|
wait_command_loop
|
336
366
|
|
337
|
-
when :
|
338
|
-
|
339
|
-
wait_command_loop
|
340
|
-
when :cdp_result
|
341
|
-
cdp_event ev_args
|
367
|
+
when :protocol_result
|
368
|
+
process_protocol_result ev_args
|
342
369
|
wait_command_loop
|
343
370
|
end
|
344
371
|
end
|
@@ -480,9 +507,9 @@ module DEBUGGER__
|
|
480
507
|
# * `u[ntil]`
|
481
508
|
# * Similar to `next` command, but only stop later lines or the end of the current frame.
|
482
509
|
# * Similar to gdb's `advance` command.
|
483
|
-
# * `u[ntil] <[file:]line
|
510
|
+
# * `u[ntil] <[file:]line>`
|
484
511
|
# * Run til the program reaches given location or the end of the current frame.
|
485
|
-
# * `u[ntil] <name
|
512
|
+
# * `u[ntil] <name>`
|
486
513
|
# * Run til the program invokes a method `<name>`. `<name>` can be a regexp with `/name/`.
|
487
514
|
register_command 'u', 'until',
|
488
515
|
repeat: true,
|
@@ -674,15 +701,15 @@ module DEBUGGER__
|
|
674
701
|
register_command 'bt', 'backtrace', unsafe: false do |arg|
|
675
702
|
case arg
|
676
703
|
when /\A(\d+)\z/
|
677
|
-
|
704
|
+
request_tc_with_restarted_threads [:show, :backtrace, arg.to_i, nil]
|
678
705
|
when /\A\/(.*)\/\z/
|
679
706
|
pattern = $1
|
680
|
-
|
707
|
+
request_tc_with_restarted_threads [:show, :backtrace, nil, Regexp.compile(pattern)]
|
681
708
|
when /\A(\d+)\s+\/(.*)\/\z/
|
682
709
|
max, pattern = $1, $2
|
683
|
-
|
710
|
+
request_tc_with_restarted_threads [:show, :backtrace, max.to_i, Regexp.compile(pattern)]
|
684
711
|
else
|
685
|
-
|
712
|
+
request_tc_with_restarted_threads [:show, :backtrace, nil, nil]
|
686
713
|
end
|
687
714
|
end
|
688
715
|
|
@@ -799,15 +826,15 @@ module DEBUGGER__
|
|
799
826
|
|
800
827
|
case sub
|
801
828
|
when nil
|
802
|
-
|
829
|
+
request_tc_with_restarted_threads [:show, :default, pat] # something useful
|
803
830
|
when :locals
|
804
|
-
|
831
|
+
request_tc_with_restarted_threads [:show, :locals, pat]
|
805
832
|
when :ivars
|
806
|
-
|
833
|
+
request_tc_with_restarted_threads [:show, :ivars, pat, opt]
|
807
834
|
when :consts
|
808
|
-
|
835
|
+
request_tc_with_restarted_threads [:show, :consts, pat, opt]
|
809
836
|
when :globals
|
810
|
-
|
837
|
+
request_tc_with_restarted_threads [:show, :globals, pat]
|
811
838
|
when :threads
|
812
839
|
thread_list
|
813
840
|
:retry
|
@@ -827,7 +854,7 @@ module DEBUGGER__
|
|
827
854
|
# * Show you available methods and instance variables of the given object.
|
828
855
|
# * If the object is a class/module, it also lists its constants.
|
829
856
|
register_command 'outline', 'o', 'ls', unsafe: false do |arg|
|
830
|
-
|
857
|
+
request_tc_with_restarted_threads [:show, :outline, arg]
|
831
858
|
end
|
832
859
|
|
833
860
|
# * `display`
|
@@ -837,9 +864,9 @@ module DEBUGGER__
|
|
837
864
|
register_command 'display', postmortem: false do |arg|
|
838
865
|
if arg && !arg.empty?
|
839
866
|
@displays << arg
|
840
|
-
|
867
|
+
request_eval :try_display, @displays
|
841
868
|
else
|
842
|
-
|
869
|
+
request_eval :display, @displays
|
843
870
|
end
|
844
871
|
end
|
845
872
|
|
@@ -853,7 +880,7 @@ module DEBUGGER__
|
|
853
880
|
if @displays[n = $1.to_i]
|
854
881
|
@displays.delete_at n
|
855
882
|
end
|
856
|
-
|
883
|
+
request_eval :display, @displays
|
857
884
|
when nil
|
858
885
|
if ask "clear all?", 'N'
|
859
886
|
@displays.clear
|
@@ -889,13 +916,13 @@ module DEBUGGER__
|
|
889
916
|
# * `p <expr>`
|
890
917
|
# * Evaluate like `p <expr>` on the current frame.
|
891
918
|
register_command 'p' do |arg|
|
892
|
-
|
919
|
+
request_eval :p, arg.to_s
|
893
920
|
end
|
894
921
|
|
895
922
|
# * `pp <expr>`
|
896
923
|
# * Evaluate like `pp <expr>` on the current frame.
|
897
924
|
register_command 'pp' do |arg|
|
898
|
-
|
925
|
+
request_eval :pp, arg.to_s
|
899
926
|
end
|
900
927
|
|
901
928
|
# * `eval <expr>`
|
@@ -906,7 +933,7 @@ module DEBUGGER__
|
|
906
933
|
@ui.puts "\nTo evaluate the variable `#{cmd}`, use `pp #{cmd}` instead."
|
907
934
|
:retry
|
908
935
|
else
|
909
|
-
|
936
|
+
request_eval :call, arg
|
910
937
|
end
|
911
938
|
end
|
912
939
|
|
@@ -914,10 +941,11 @@ module DEBUGGER__
|
|
914
941
|
# * Invoke `irb` on the current frame.
|
915
942
|
register_command 'irb' do |arg|
|
916
943
|
if @ui.remote?
|
917
|
-
@ui.puts "not supported on the remote console."
|
944
|
+
@ui.puts "\nIRB is not supported on the remote console."
|
918
945
|
:retry
|
946
|
+
else
|
947
|
+
request_eval :irb, nil
|
919
948
|
end
|
920
|
-
request_tc [:eval, :irb]
|
921
949
|
end
|
922
950
|
|
923
951
|
### Trace
|
@@ -972,7 +1000,7 @@ module DEBUGGER__
|
|
972
1000
|
:retry
|
973
1001
|
|
974
1002
|
when /\Aobject\s+(.+)/
|
975
|
-
|
1003
|
+
request_tc_with_restarted_threads [:trace, :object, $1.strip, {pattern: pattern, into: into}]
|
976
1004
|
|
977
1005
|
when /\Aoff\s+(\d+)\z/
|
978
1006
|
if t = @tracers.values[$1.to_i]
|
@@ -1137,7 +1165,7 @@ module DEBUGGER__
|
|
1137
1165
|
@repl_prev_line = nil
|
1138
1166
|
check_unsafe
|
1139
1167
|
|
1140
|
-
|
1168
|
+
request_eval :pp, line
|
1141
1169
|
end
|
1142
1170
|
|
1143
1171
|
rescue Interrupt
|
@@ -1321,10 +1349,6 @@ module DEBUGGER__
|
|
1321
1349
|
|
1322
1350
|
# breakpoint management
|
1323
1351
|
|
1324
|
-
def bps_pending_until_load?
|
1325
|
-
@bps.any?{|key, bp| bp.pending_until_load?}
|
1326
|
-
end
|
1327
|
-
|
1328
1352
|
def iterate_bps
|
1329
1353
|
deleted_bps = []
|
1330
1354
|
i = 0
|
@@ -1500,7 +1524,7 @@ module DEBUGGER__
|
|
1500
1524
|
def clear_line_breakpoints path
|
1501
1525
|
path = resolve_path(path)
|
1502
1526
|
clear_breakpoints do |k, bp|
|
1503
|
-
bp.is_a?(LineBreakpoint) &&
|
1527
|
+
bp.is_a?(LineBreakpoint) && bp.path_is?(path)
|
1504
1528
|
end
|
1505
1529
|
rescue Errno::ENOENT
|
1506
1530
|
# just ignore
|
@@ -1524,7 +1548,7 @@ module DEBUGGER__
|
|
1524
1548
|
# tracers
|
1525
1549
|
|
1526
1550
|
def add_tracer tracer
|
1527
|
-
if @tracers
|
1551
|
+
if @tracers[tracer.key]&.enabled?
|
1528
1552
|
tracer.disable
|
1529
1553
|
@ui.puts "Duplicated tracer: #{tracer}"
|
1530
1554
|
else
|
@@ -1724,25 +1748,30 @@ module DEBUGGER__
|
|
1724
1748
|
file_path, reloaded = @sr.add(iseq, src)
|
1725
1749
|
@ui.event :load, file_path, reloaded
|
1726
1750
|
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1751
|
+
# check breakpoints
|
1752
|
+
if file_path
|
1753
|
+
@bps.find_all do |_key, bp|
|
1754
|
+
LineBreakpoint === bp && bp.path_is?(file_path) && (iseq.first_lineno..iseq.last_line).cover?(bp.line)
|
1755
|
+
end.each do |_key, bp|
|
1756
|
+
if !bp.iseq
|
1757
|
+
bp.try_activate iseq
|
1758
|
+
elsif reloaded
|
1759
|
+
@bps.delete bp.key # to allow duplicate
|
1730
1760
|
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
end
|
1735
|
-
end
|
1761
|
+
# When we delete a breakpoint from the @bps hash, we also need to deactivate it or else its tracepoint event
|
1762
|
+
# will continue to be enabled and we'll suspend on ghost breakpoints
|
1763
|
+
bp.delete
|
1736
1764
|
|
1737
|
-
|
1738
|
-
@bps.find_all do |key, bp|
|
1739
|
-
LineBreakpoint === bp && DEBUGGER__.compare_path(bp.path, file_path)
|
1740
|
-
end.each do |_key, bp|
|
1741
|
-
@bps.delete bp.key # to allow duplicate
|
1742
|
-
if nbp = LineBreakpoint.copy(bp, iseq)
|
1765
|
+
nbp = LineBreakpoint.copy(bp, iseq)
|
1743
1766
|
add_bp nbp
|
1744
1767
|
end
|
1745
1768
|
end
|
1769
|
+
else # !file_path => file_path is not existing
|
1770
|
+
@bps.find_all do |_key, bp|
|
1771
|
+
LineBreakpoint === bp && !bp.iseq && DEBUGGER__.compare_path(bp.path, (iseq.absolute_path || iseq.path))
|
1772
|
+
end.each do |_key, bp|
|
1773
|
+
bp.try_activate iseq
|
1774
|
+
end
|
1746
1775
|
end
|
1747
1776
|
end
|
1748
1777
|
|
@@ -1980,6 +2009,13 @@ module DEBUGGER__
|
|
1980
2009
|
def after_fork_parent
|
1981
2010
|
@ui.after_fork_parent
|
1982
2011
|
end
|
2012
|
+
|
2013
|
+
# experimental API
|
2014
|
+
def extend_feature session: nil, thread_client: nil, ui: nil
|
2015
|
+
Session.include session if session
|
2016
|
+
ThreadClient.include thread_client if thread_client
|
2017
|
+
@ui.extend ui if ui
|
2018
|
+
end
|
1983
2019
|
end
|
1984
2020
|
|
1985
2021
|
class ProcessGroup
|
@@ -2154,6 +2190,7 @@ module DEBUGGER__
|
|
2154
2190
|
case loc.absolute_path
|
2155
2191
|
when dir_prefix
|
2156
2192
|
when %r{rubygems/core_ext/kernel_require\.rb}
|
2193
|
+
when %r{bundled_gems\.rb}
|
2157
2194
|
else
|
2158
2195
|
return loc if loc.absolute_path
|
2159
2196
|
end
|
@@ -2438,7 +2475,7 @@ module DEBUGGER__
|
|
2438
2475
|
end
|
2439
2476
|
|
2440
2477
|
module DaemonInterceptor
|
2441
|
-
def daemon
|
2478
|
+
def daemon(*args)
|
2442
2479
|
return super unless defined?(SESSION) && SESSION.active?
|
2443
2480
|
|
2444
2481
|
_, child_hook = __fork_setup_for_debugger(:child)
|
@@ -2504,7 +2541,17 @@ module DEBUGGER__
|
|
2504
2541
|
|
2505
2542
|
module TrapInterceptor
|
2506
2543
|
def trap sig, *command, &command_proc
|
2507
|
-
|
2544
|
+
sym =
|
2545
|
+
case sig
|
2546
|
+
when String
|
2547
|
+
sig.to_sym
|
2548
|
+
when Integer
|
2549
|
+
Signal.signame(sig)&.to_sym
|
2550
|
+
else
|
2551
|
+
sig
|
2552
|
+
end
|
2553
|
+
|
2554
|
+
case sym
|
2508
2555
|
when :INT, :SIGINT
|
2509
2556
|
if defined?(SESSION) && SESSION.active? && SESSION.intercept_trap_sigint?
|
2510
2557
|
return SESSION.save_int_trap(command.empty? ? command_proc : command.first)
|
@@ -22,7 +22,7 @@ module DEBUGGER__
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
if RubyVM.
|
25
|
+
if defined?(RubyVM.keep_script_lines)
|
26
26
|
# Ruby 3.1 and later
|
27
27
|
RubyVM.keep_script_lines = true
|
28
28
|
require 'objspace'
|
@@ -34,7 +34,7 @@ module DEBUGGER__
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def add iseq, src
|
37
|
-
#
|
37
|
+
# only manage loaded file names
|
38
38
|
if (path = (iseq.absolute_path || iseq.path)) && File.exist?(path)
|
39
39
|
if @loaded_file_map.has_key? path
|
40
40
|
return path, true # reloaded
|
@@ -49,7 +49,7 @@ module DEBUGGER__
|
|
49
49
|
lines = iseq.script_lines&.map(&:chomp)
|
50
50
|
line = iseq.first_line
|
51
51
|
if line > 1
|
52
|
-
|
52
|
+
[*([''] * (line - 1)), *lines]
|
53
53
|
else
|
54
54
|
lines
|
55
55
|
end
|
data/lib/debug/thread_client.rb
CHANGED
@@ -5,6 +5,10 @@ require 'pp'
|
|
5
5
|
|
6
6
|
require_relative 'color'
|
7
7
|
|
8
|
+
class ::Thread
|
9
|
+
attr_accessor :debug_thread_client
|
10
|
+
end
|
11
|
+
|
8
12
|
module DEBUGGER__
|
9
13
|
M_INSTANCE_VARIABLES = method(:instance_variables).unbind
|
10
14
|
M_INSTANCE_VARIABLE_GET = method(:instance_variable_get).unbind
|
@@ -14,6 +18,7 @@ module DEBUGGER__
|
|
14
18
|
M_RESPOND_TO_P = method(:respond_to?).unbind
|
15
19
|
M_METHOD = method(:method).unbind
|
16
20
|
M_OBJECT_ID = method(:object_id).unbind
|
21
|
+
M_NAME = method(:name).unbind
|
17
22
|
|
18
23
|
module SkipPathHelper
|
19
24
|
def skip_path?(path)
|
@@ -47,12 +52,7 @@ module DEBUGGER__
|
|
47
52
|
|
48
53
|
class ThreadClient
|
49
54
|
def self.current
|
50
|
-
|
51
|
-
thc
|
52
|
-
else
|
53
|
-
thc = SESSION.get_thread_client
|
54
|
-
Thread.current[:DEBUGGER__ThreadClient] = thc
|
55
|
-
end
|
55
|
+
Thread.current.debug_thread_client ||= SESSION.get_thread_client
|
56
56
|
end
|
57
57
|
|
58
58
|
include Color
|
@@ -468,10 +468,14 @@ module DEBUGGER__
|
|
468
468
|
if file_lines = frame.file_lines
|
469
469
|
frame_line = frame.location.lineno - 1
|
470
470
|
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
471
|
+
if CONFIG[:no_lineno]
|
472
|
+
lines = file_lines
|
473
|
+
else
|
474
|
+
lines = file_lines.map.with_index do |e, i|
|
475
|
+
cur = i == frame_line ? '=>' : ' '
|
476
|
+
line = colorize_dim('%4d|' % (i+1))
|
477
|
+
"#{cur}#{line} #{e}"
|
478
|
+
end
|
475
479
|
end
|
476
480
|
|
477
481
|
unless start_line
|
@@ -607,12 +611,17 @@ module DEBUGGER__
|
|
607
611
|
|
608
612
|
def get_consts expr = nil, only_self: false, &block
|
609
613
|
if expr && !expr.empty?
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
+
begin
|
615
|
+
_self = frame_eval(expr, re_raise: true)
|
616
|
+
rescue Exception
|
617
|
+
# ignore
|
614
618
|
else
|
615
|
-
|
619
|
+
if M_KIND_OF_P.bind_call(_self, Module)
|
620
|
+
iter_consts _self, &block
|
621
|
+
return
|
622
|
+
else
|
623
|
+
puts "#{_self.inspect} (by #{expr}) is not a Module."
|
624
|
+
end
|
616
625
|
end
|
617
626
|
elsif _self = current_frame&.self
|
618
627
|
cs = {}
|
@@ -852,8 +861,18 @@ module DEBUGGER__
|
|
852
861
|
class SuspendReplay < Exception
|
853
862
|
end
|
854
863
|
|
864
|
+
if ::Fiber.respond_to?(:blocking)
|
865
|
+
private def fiber_blocking
|
866
|
+
::Fiber.blocking{yield}
|
867
|
+
end
|
868
|
+
else
|
869
|
+
private def fiber_blocking
|
870
|
+
yield
|
871
|
+
end
|
872
|
+
end
|
873
|
+
|
855
874
|
def wait_next_action
|
856
|
-
wait_next_action_
|
875
|
+
fiber_blocking{wait_next_action_}
|
857
876
|
rescue SuspendReplay
|
858
877
|
replay_suspend
|
859
878
|
end
|
@@ -1038,13 +1057,8 @@ module DEBUGGER__
|
|
1038
1057
|
when :call
|
1039
1058
|
result = frame_eval(eval_src)
|
1040
1059
|
when :irb
|
1041
|
-
|
1042
|
-
|
1043
|
-
result = frame_eval('binding.irb(show_code: false)', binding_location: true)
|
1044
|
-
ensure
|
1045
|
-
# workaround: https://github.com/ruby/debug/issues/308
|
1046
|
-
Reline.prompt_proc = nil if defined? Reline
|
1047
|
-
end
|
1060
|
+
require_relative "irb_integration"
|
1061
|
+
activate_irb_integration
|
1048
1062
|
when :display, :try_display
|
1049
1063
|
failed_results = []
|
1050
1064
|
eval_src.each_with_index{|src, i|
|
@@ -1230,7 +1244,15 @@ module DEBUGGER__
|
|
1230
1244
|
rescue SuspendReplay, SystemExit, Interrupt
|
1231
1245
|
raise
|
1232
1246
|
rescue Exception => e
|
1233
|
-
|
1247
|
+
STDERR.puts e.cause.inspect
|
1248
|
+
STDERR.puts e.inspect
|
1249
|
+
Thread.list.each{|th|
|
1250
|
+
STDERR.puts "@@@ #{th}"
|
1251
|
+
th.backtrace.each{|b|
|
1252
|
+
STDERR.puts " > #{b}"
|
1253
|
+
}
|
1254
|
+
}
|
1255
|
+
p ["DEBUGGER Exception: #{__FILE__}:#{__LINE__}", e, e.backtrace]
|
1234
1256
|
raise
|
1235
1257
|
ensure
|
1236
1258
|
@returning = false
|
@@ -1292,10 +1314,14 @@ module DEBUGGER__
|
|
1292
1314
|
frame._callee = b.eval('__callee__')
|
1293
1315
|
end
|
1294
1316
|
}
|
1295
|
-
|
1317
|
+
append(frames)
|
1296
1318
|
}
|
1297
1319
|
end
|
1298
1320
|
|
1321
|
+
def append frames
|
1322
|
+
@log << frames
|
1323
|
+
end
|
1324
|
+
|
1299
1325
|
def enable
|
1300
1326
|
unless @tp_recorder.enabled?
|
1301
1327
|
@log.clear
|
data/lib/debug/tracer.rb
CHANGED
@@ -54,6 +54,10 @@ module DEBUGGER__
|
|
54
54
|
@tracer.disable
|
55
55
|
end
|
56
56
|
|
57
|
+
def enabled?
|
58
|
+
@tracer.enabled?
|
59
|
+
end
|
60
|
+
|
57
61
|
def description
|
58
62
|
nil
|
59
63
|
end
|
@@ -85,11 +89,6 @@ module DEBUGGER__
|
|
85
89
|
end
|
86
90
|
end
|
87
91
|
|
88
|
-
def puts msg
|
89
|
-
@output.puts msg
|
90
|
-
@output.flush
|
91
|
-
end
|
92
|
-
|
93
92
|
def minfo tp
|
94
93
|
return "block{}" if tp.event == :b_call
|
95
94
|
|
data/lib/debug/version.rb
CHANGED