debug 1.8.0 → 1.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +77 -50
- data/debug.gemspec +3 -3
- data/ext/debug/debug.c +28 -14
- data/ext/debug/extconf.rb +1 -0
- data/ext/debug/iseq_collector.c +2 -0
- data/lib/debug/client.rb +3 -2
- data/lib/debug/config.rb +28 -6
- data/lib/debug/console.rb +9 -30
- data/lib/debug/irb_integration.rb +37 -0
- data/lib/debug/prelude.rb +1 -1
- data/lib/debug/server.rb +5 -3
- data/lib/debug/server_cdp.rb +10 -11
- data/lib/debug/server_dap.rb +3 -1
- data/lib/debug/session.rb +56 -31
- data/lib/debug/source_repository.rb +1 -1
- data/lib/debug/thread_client.rb +19 -18
- data/lib/debug/version.rb +1 -1
- data/misc/README.md.erb +73 -49
- metadata +11 -13
data/lib/debug/console.rb
CHANGED
@@ -5,30 +5,9 @@ module DEBUGGER__
|
|
5
5
|
raise LoadError if CONFIG[:no_reline]
|
6
6
|
require 'reline'
|
7
7
|
|
8
|
-
# reline 0.2.7 or later is required.
|
9
|
-
raise LoadError if Reline::VERSION < '0.2.7'
|
10
|
-
|
11
8
|
require_relative 'color'
|
12
|
-
include Color
|
13
|
-
|
14
|
-
begin
|
15
|
-
prev = trap(:SIGWINCH, nil)
|
16
|
-
trap(:SIGWINCH, prev)
|
17
|
-
SIGWINCH_SUPPORTED = true
|
18
|
-
rescue ArgumentError
|
19
|
-
SIGWINCH_SUPPORTED = false
|
20
|
-
end
|
21
9
|
|
22
|
-
|
23
|
-
class ::Reline::LineEditor
|
24
|
-
m = Module.new do
|
25
|
-
def reset(prompt = '', encoding:)
|
26
|
-
super
|
27
|
-
Signal.trap(:SIGWINCH, nil)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
prepend m
|
31
|
-
end if SIGWINCH_SUPPORTED
|
10
|
+
include Color
|
32
11
|
|
33
12
|
def parse_input buff, commands
|
34
13
|
c, rest = get_command buff
|
@@ -56,10 +35,10 @@ module DEBUGGER__
|
|
56
35
|
Reline.prompt_proc = -> args, *kw do
|
57
36
|
case state = parse_input(args.first, commands)
|
58
37
|
when nil, :command
|
59
|
-
[prompt
|
38
|
+
[prompt]
|
60
39
|
when :ruby
|
61
|
-
[prompt.sub('rdbg'){colorize('ruby', [:RED])}]
|
62
|
-
end
|
40
|
+
[prompt.sub('rdbg'){colorize('ruby', [:RED])}]
|
41
|
+
end * args.size
|
63
42
|
end
|
64
43
|
|
65
44
|
Reline.completion_proc = -> given do
|
@@ -96,7 +75,7 @@ module DEBUGGER__
|
|
96
75
|
when nil
|
97
76
|
buff
|
98
77
|
when :ruby
|
99
|
-
colorize_code(buff
|
78
|
+
colorize_code(buff)
|
100
79
|
end
|
101
80
|
end unless CONFIG[:no_hint]
|
102
81
|
|
@@ -164,7 +143,7 @@ module DEBUGGER__
|
|
164
143
|
rescue LoadError
|
165
144
|
def readline prompt
|
166
145
|
print prompt
|
167
|
-
gets
|
146
|
+
$stdin.gets
|
168
147
|
end
|
169
148
|
|
170
149
|
def history
|
@@ -224,11 +203,11 @@ module DEBUGGER__
|
|
224
203
|
end
|
225
204
|
|
226
205
|
def load_history
|
227
|
-
read_history_file.
|
206
|
+
read_history_file.each{|line|
|
228
207
|
line.strip!
|
229
208
|
history << line unless line.empty?
|
230
|
-
}
|
209
|
+
} if history.empty?
|
210
|
+
history.count
|
231
211
|
end
|
232
212
|
end # class Console
|
233
213
|
end
|
234
|
-
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'irb'
|
4
|
+
|
5
|
+
module DEBUGGER__
|
6
|
+
module IrbPatch
|
7
|
+
def evaluate(line, line_no)
|
8
|
+
SESSION.send(:restart_all_threads)
|
9
|
+
super
|
10
|
+
# This is to communicate with the test framework so it can feed the next input
|
11
|
+
puts "INTERNAL_INFO: {}" if ENV['RUBY_DEBUG_TEST_UI'] == 'terminal'
|
12
|
+
ensure
|
13
|
+
SESSION.send(:stop_all_threads)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class ThreadClient
|
18
|
+
def activate_irb_integration
|
19
|
+
IRB.setup(location, argv: [])
|
20
|
+
workspace = IRB::WorkSpace.new(current_frame&.binding || TOPLEVEL_BINDING)
|
21
|
+
irb = IRB::Irb.new(workspace)
|
22
|
+
IRB.conf[:MAIN_CONTEXT] = irb.context
|
23
|
+
IRB::Debug.setup(irb)
|
24
|
+
IRB::Context.prepend(IrbPatch)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Session
|
29
|
+
def deactivate_irb_integration
|
30
|
+
Reline.completion_proc = nil
|
31
|
+
Reline.output_modifier_proc = nil
|
32
|
+
Reline.autocompletion = false
|
33
|
+
Reline.dig_perfect_match_proc = nil
|
34
|
+
reset_ui UI_LocalConsole.new
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/debug/prelude.rb
CHANGED
@@ -5,7 +5,7 @@ return if defined?(::DEBUGGER__::Session)
|
|
5
5
|
|
6
6
|
# Put the following line in your login script (e.g. ~/.bash_profile) with modified path:
|
7
7
|
#
|
8
|
-
# export RUBYOPT="-r /path/to/debug/prelude $
|
8
|
+
# export RUBYOPT="-r /path/to/debug/prelude ${RUBYOPT}"
|
9
9
|
#
|
10
10
|
module Kernel
|
11
11
|
def debugger(*a, up_level: 0, **kw)
|
data/lib/debug/server.rb
CHANGED
@@ -133,7 +133,7 @@ module DEBUGGER__
|
|
133
133
|
require 'etc'
|
134
134
|
|
135
135
|
check_cookie $1
|
136
|
-
@sock.puts "PID: #{Process.pid}, $0: #{$0}"
|
136
|
+
@sock.puts "PID: #{Process.pid}, $0: #{$0}, session_name: #{CONFIG[:session_name]}"
|
137
137
|
@sock.puts "debug #{VERSION} on #{RUBY_DESCRIPTION}"
|
138
138
|
@sock.puts "uname: #{Etc.uname.inspect}"
|
139
139
|
@sock.close
|
@@ -149,7 +149,9 @@ module DEBUGGER__
|
|
149
149
|
end
|
150
150
|
parse_option(params)
|
151
151
|
|
152
|
-
|
152
|
+
session_name = CONFIG[:session_name]
|
153
|
+
session_name_str = ", session_name:#{session_name}" if session_name
|
154
|
+
puts "DEBUGGER (client): Connected. PID:#{Process.pid}, $0:#{$0}#{session_name_str}"
|
153
155
|
puts "DEBUGGER (client): Type `Ctrl-C` to enter the debug console." unless @need_pause_at_first
|
154
156
|
puts
|
155
157
|
|
@@ -410,7 +412,7 @@ module DEBUGGER__
|
|
410
412
|
DEBUGGER__.warn <<~EOS
|
411
413
|
With Chrome browser, type the following URL in the address-bar:
|
412
414
|
|
413
|
-
devtools://devtools/bundled/inspector.html?v8only=true&panel=sources&ws=#{@local_addr.inspect_sockaddr}/#{@uuid}
|
415
|
+
devtools://devtools/bundled/inspector.html?v8only=true&panel=sources&noJavaScriptCompletion=true&ws=#{@local_addr.inspect_sockaddr}/#{@uuid}
|
414
416
|
|
415
417
|
EOS
|
416
418
|
end
|
data/lib/debug/server_cdp.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require 'json'
|
4
4
|
require 'digest/sha1'
|
5
|
-
require 'base64'
|
6
5
|
require 'securerandom'
|
7
6
|
require 'stringio'
|
8
7
|
require 'open3'
|
@@ -59,7 +58,7 @@ module DEBUGGER__
|
|
59
58
|
ws_client.send sessionId: s_id, id: 5,
|
60
59
|
method: 'Page.navigate',
|
61
60
|
params: {
|
62
|
-
url: "devtools://devtools/bundled/inspector.html?v8only=true&panel=sources&ws=#{addr}/#{uuid}",
|
61
|
+
url: "devtools://devtools/bundled/inspector.html?v8only=true&panel=sources&noJavaScriptCompletion=true&ws=#{addr}/#{uuid}",
|
63
62
|
frameId: f_id
|
64
63
|
}
|
65
64
|
when 101
|
@@ -131,7 +130,7 @@ module DEBUGGER__
|
|
131
130
|
stdout.close
|
132
131
|
data = stderr.readpartial 4096
|
133
132
|
stderr.close
|
134
|
-
if data.match
|
133
|
+
if data.match(/DevTools listening on ws:\/\/127.0.0.1:(\d+)(.*)/)
|
135
134
|
port = $1
|
136
135
|
path = $2
|
137
136
|
end
|
@@ -158,7 +157,7 @@ module DEBUGGER__
|
|
158
157
|
raise NotFoundChromeEndpointError
|
159
158
|
end
|
160
159
|
stderr.close
|
161
|
-
if data.match
|
160
|
+
if data.match(/DevTools listening on ws:\/\/127.0.0.1:(\d+)(.*)/)
|
162
161
|
port = $1
|
163
162
|
path = $2
|
164
163
|
end
|
@@ -190,7 +189,7 @@ module DEBUGGER__
|
|
190
189
|
while i < ITERATIONS
|
191
190
|
i += 1
|
192
191
|
if File.exist?(tf) && data = File.read(tf)
|
193
|
-
if data.match
|
192
|
+
if data.match(/DevTools listening on ws:\/\/127.0.0.1:(\d+)(.*)/)
|
194
193
|
port = $1
|
195
194
|
path = $2
|
196
195
|
return [port, path]
|
@@ -297,8 +296,8 @@ module DEBUGGER__
|
|
297
296
|
res = @sock.readpartial 4092
|
298
297
|
show_protocol :<, res
|
299
298
|
|
300
|
-
if res.match
|
301
|
-
correct_key =
|
299
|
+
if res.match(/^Sec-WebSocket-Accept: (.*)\r\n/)
|
300
|
+
correct_key = Digest::SHA1.base64digest "#{key}==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
302
301
|
raise "The Sec-WebSocket-Accept value: #{$1} is not valid" unless $1 == correct_key
|
303
302
|
else
|
304
303
|
raise "Unknown response: #{res}"
|
@@ -378,8 +377,8 @@ module DEBUGGER__
|
|
378
377
|
req = @sock.readpartial 4096
|
379
378
|
show_protocol '>', req
|
380
379
|
|
381
|
-
if req.match
|
382
|
-
accept =
|
380
|
+
if req.match(/^Sec-WebSocket-Key: (.*)\r\n/)
|
381
|
+
accept = Digest::SHA1.base64digest "#{$1}258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
383
382
|
res = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: #{accept}\r\n\r\n"
|
384
383
|
@sock.print res
|
385
384
|
show_protocol :<, res
|
@@ -474,7 +473,7 @@ module DEBUGGER__
|
|
474
473
|
when 'Debugger.getScriptSource'
|
475
474
|
@q_msg << req
|
476
475
|
when 'Debugger.enable'
|
477
|
-
send_response req
|
476
|
+
send_response req, debuggerId: rand.to_s
|
478
477
|
@q_msg << req
|
479
478
|
when 'Runtime.enable'
|
480
479
|
send_response req
|
@@ -658,7 +657,7 @@ module DEBUGGER__
|
|
658
657
|
|
659
658
|
def activate_bp bps
|
660
659
|
bps.each_key{|k|
|
661
|
-
if k.match
|
660
|
+
if k.match(/^\d+:(\d+):(.*)/)
|
662
661
|
line = $1
|
663
662
|
path = $2
|
664
663
|
SESSION.add_line_breakpoint(path, line.to_i + 1)
|
data/lib/debug/server_dap.rb
CHANGED
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)
|
@@ -133,7 +133,7 @@ module DEBUGGER__
|
|
133
133
|
@commands = {}
|
134
134
|
@unsafe_context = false
|
135
135
|
|
136
|
-
@has_keep_script_lines = RubyVM.
|
136
|
+
@has_keep_script_lines = defined?(RubyVM.keep_script_lines)
|
137
137
|
|
138
138
|
@tp_load_script = TracePoint.new(:script_compiled){|tp|
|
139
139
|
eval_script = tp.eval_script unless @has_keep_script_lines
|
@@ -209,6 +209,12 @@ module DEBUGGER__
|
|
209
209
|
first_q << :ok
|
210
210
|
|
211
211
|
q.pop
|
212
|
+
|
213
|
+
# For activating irb:rdbg with startup config like `RUBY_DEBUG_IRB_CONSOLE=1`
|
214
|
+
# Because in that case the `Config#if_updated` callback would not be triggered
|
215
|
+
if CONFIG[:irb_console] && !CONFIG[:open]
|
216
|
+
activate_irb_integration
|
217
|
+
end
|
212
218
|
end
|
213
219
|
|
214
220
|
def deactivate
|
@@ -256,6 +262,15 @@ module DEBUGGER__
|
|
256
262
|
@tc << req
|
257
263
|
end
|
258
264
|
|
265
|
+
def request_tc_with_restarted_threads(req)
|
266
|
+
restart_all_threads
|
267
|
+
request_tc(req)
|
268
|
+
end
|
269
|
+
|
270
|
+
def request_eval type, src
|
271
|
+
request_tc_with_restarted_threads [:eval, type, src]
|
272
|
+
end
|
273
|
+
|
259
274
|
def process_event evt
|
260
275
|
# variable `@internal_info` is only used for test
|
261
276
|
tc, output, ev, @internal_info, *ev_args = evt
|
@@ -314,7 +329,7 @@ module DEBUGGER__
|
|
314
329
|
if @displays.empty?
|
315
330
|
wait_command_loop
|
316
331
|
else
|
317
|
-
|
332
|
+
request_eval :display, @displays
|
318
333
|
end
|
319
334
|
when :result
|
320
335
|
raise "[BUG] not in subsession" if @subsession_stack.empty?
|
@@ -329,6 +344,7 @@ module DEBUGGER__
|
|
329
344
|
end
|
330
345
|
end
|
331
346
|
|
347
|
+
stop_all_threads
|
332
348
|
when :method_breakpoint, :watch_breakpoint
|
333
349
|
bp = ev_args[1]
|
334
350
|
if bp
|
@@ -342,6 +358,7 @@ module DEBUGGER__
|
|
342
358
|
obj_inspect = ev_args[2]
|
343
359
|
opt = ev_args[3]
|
344
360
|
add_tracer ObjectTracer.new(@ui, obj_id, obj_inspect, **opt)
|
361
|
+
stop_all_threads
|
345
362
|
else
|
346
363
|
stop_all_threads
|
347
364
|
end
|
@@ -685,15 +702,15 @@ module DEBUGGER__
|
|
685
702
|
register_command 'bt', 'backtrace', unsafe: false do |arg|
|
686
703
|
case arg
|
687
704
|
when /\A(\d+)\z/
|
688
|
-
|
705
|
+
request_tc_with_restarted_threads [:show, :backtrace, arg.to_i, nil]
|
689
706
|
when /\A\/(.*)\/\z/
|
690
707
|
pattern = $1
|
691
|
-
|
708
|
+
request_tc_with_restarted_threads [:show, :backtrace, nil, Regexp.compile(pattern)]
|
692
709
|
when /\A(\d+)\s+\/(.*)\/\z/
|
693
710
|
max, pattern = $1, $2
|
694
|
-
|
711
|
+
request_tc_with_restarted_threads [:show, :backtrace, max.to_i, Regexp.compile(pattern)]
|
695
712
|
else
|
696
|
-
|
713
|
+
request_tc_with_restarted_threads [:show, :backtrace, nil, nil]
|
697
714
|
end
|
698
715
|
end
|
699
716
|
|
@@ -810,15 +827,15 @@ module DEBUGGER__
|
|
810
827
|
|
811
828
|
case sub
|
812
829
|
when nil
|
813
|
-
|
830
|
+
request_tc_with_restarted_threads [:show, :default, pat] # something useful
|
814
831
|
when :locals
|
815
|
-
|
832
|
+
request_tc_with_restarted_threads [:show, :locals, pat]
|
816
833
|
when :ivars
|
817
|
-
|
834
|
+
request_tc_with_restarted_threads [:show, :ivars, pat, opt]
|
818
835
|
when :consts
|
819
|
-
|
836
|
+
request_tc_with_restarted_threads [:show, :consts, pat, opt]
|
820
837
|
when :globals
|
821
|
-
|
838
|
+
request_tc_with_restarted_threads [:show, :globals, pat]
|
822
839
|
when :threads
|
823
840
|
thread_list
|
824
841
|
:retry
|
@@ -838,7 +855,7 @@ module DEBUGGER__
|
|
838
855
|
# * Show you available methods and instance variables of the given object.
|
839
856
|
# * If the object is a class/module, it also lists its constants.
|
840
857
|
register_command 'outline', 'o', 'ls', unsafe: false do |arg|
|
841
|
-
|
858
|
+
request_tc_with_restarted_threads [:show, :outline, arg]
|
842
859
|
end
|
843
860
|
|
844
861
|
# * `display`
|
@@ -848,9 +865,9 @@ module DEBUGGER__
|
|
848
865
|
register_command 'display', postmortem: false do |arg|
|
849
866
|
if arg && !arg.empty?
|
850
867
|
@displays << arg
|
851
|
-
|
868
|
+
request_eval :try_display, @displays
|
852
869
|
else
|
853
|
-
|
870
|
+
request_eval :display, @displays
|
854
871
|
end
|
855
872
|
end
|
856
873
|
|
@@ -864,7 +881,7 @@ module DEBUGGER__
|
|
864
881
|
if @displays[n = $1.to_i]
|
865
882
|
@displays.delete_at n
|
866
883
|
end
|
867
|
-
|
884
|
+
request_eval :display, @displays
|
868
885
|
when nil
|
869
886
|
if ask "clear all?", 'N'
|
870
887
|
@displays.clear
|
@@ -922,13 +939,15 @@ module DEBUGGER__
|
|
922
939
|
end
|
923
940
|
|
924
941
|
# * `irb`
|
925
|
-
# *
|
942
|
+
# * Activate and switch to `irb:rdbg` console
|
926
943
|
register_command 'irb' do |arg|
|
927
944
|
if @ui.remote?
|
928
|
-
@ui.puts "not supported on the remote console."
|
929
|
-
|
945
|
+
@ui.puts "\nIRB is not supported on the remote console."
|
946
|
+
else
|
947
|
+
config_set :irb_console, true
|
930
948
|
end
|
931
|
-
|
949
|
+
|
950
|
+
:retry
|
932
951
|
end
|
933
952
|
|
934
953
|
### Trace
|
@@ -983,7 +1002,7 @@ module DEBUGGER__
|
|
983
1002
|
:retry
|
984
1003
|
|
985
1004
|
when /\Aobject\s+(.+)/
|
986
|
-
|
1005
|
+
request_tc_with_restarted_threads [:trace, :object, $1.strip, {pattern: pattern, into: into}]
|
987
1006
|
|
988
1007
|
when /\Aoff\s+(\d+)\z/
|
989
1008
|
if t = @tracers.values[$1.to_i]
|
@@ -1164,11 +1183,6 @@ module DEBUGGER__
|
|
1164
1183
|
return :retry
|
1165
1184
|
end
|
1166
1185
|
|
1167
|
-
def request_eval type, src
|
1168
|
-
restart_all_threads
|
1169
|
-
request_tc [:eval, type, src]
|
1170
|
-
end
|
1171
|
-
|
1172
1186
|
def step_command type, arg
|
1173
1187
|
if type == :until
|
1174
1188
|
leave_subsession [:step, type, arg]
|
@@ -1739,15 +1753,19 @@ module DEBUGGER__
|
|
1739
1753
|
# check breakpoints
|
1740
1754
|
if file_path
|
1741
1755
|
@bps.find_all do |_key, bp|
|
1742
|
-
LineBreakpoint === bp && bp.path_is?(file_path)
|
1756
|
+
LineBreakpoint === bp && bp.path_is?(file_path) && (iseq.first_lineno..iseq.last_line).cover?(bp.line)
|
1743
1757
|
end.each do |_key, bp|
|
1744
1758
|
if !bp.iseq
|
1745
1759
|
bp.try_activate iseq
|
1746
1760
|
elsif reloaded
|
1747
1761
|
@bps.delete bp.key # to allow duplicate
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1762
|
+
|
1763
|
+
# When we delete a breakpoint from the @bps hash, we also need to deactivate it or else its tracepoint event
|
1764
|
+
# will continue to be enabled and we'll suspend on ghost breakpoints
|
1765
|
+
bp.delete
|
1766
|
+
|
1767
|
+
nbp = LineBreakpoint.copy(bp, iseq)
|
1768
|
+
add_bp nbp
|
1751
1769
|
end
|
1752
1770
|
end
|
1753
1771
|
else # !file_path => file_path is not existing
|
@@ -1860,6 +1878,12 @@ module DEBUGGER__
|
|
1860
1878
|
end
|
1861
1879
|
end
|
1862
1880
|
|
1881
|
+
def activate_irb_integration
|
1882
|
+
require_relative "irb_integration"
|
1883
|
+
thc = get_thread_client(@session_server)
|
1884
|
+
thc.activate_irb_integration
|
1885
|
+
end
|
1886
|
+
|
1863
1887
|
def enter_postmortem_session exc
|
1864
1888
|
return unless exc.instance_variable_defined? :@__debugger_postmortem_frames
|
1865
1889
|
|
@@ -2174,6 +2198,7 @@ module DEBUGGER__
|
|
2174
2198
|
case loc.absolute_path
|
2175
2199
|
when dir_prefix
|
2176
2200
|
when %r{rubygems/core_ext/kernel_require\.rb}
|
2201
|
+
when %r{bundled_gems\.rb}
|
2177
2202
|
else
|
2178
2203
|
return loc if loc.absolute_path
|
2179
2204
|
end
|
@@ -2534,7 +2559,7 @@ module DEBUGGER__
|
|
2534
2559
|
sig
|
2535
2560
|
end
|
2536
2561
|
|
2537
|
-
case
|
2562
|
+
case sym
|
2538
2563
|
when :INT, :SIGINT
|
2539
2564
|
if defined?(SESSION) && SESSION.active? && SESSION.intercept_trap_sigint?
|
2540
2565
|
return SESSION.save_int_trap(command.empty? ? command_proc : command.first)
|
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
|
@@ -48,12 +52,7 @@ module DEBUGGER__
|
|
48
52
|
|
49
53
|
class ThreadClient
|
50
54
|
def self.current
|
51
|
-
|
52
|
-
thc
|
53
|
-
else
|
54
|
-
thc = SESSION.get_thread_client
|
55
|
-
Thread.current[:DEBUGGER__ThreadClient] = thc
|
56
|
-
end
|
55
|
+
Thread.current.debug_thread_client ||= SESSION.get_thread_client
|
57
56
|
end
|
58
57
|
|
59
58
|
include Color
|
@@ -614,7 +613,7 @@ module DEBUGGER__
|
|
614
613
|
if expr && !expr.empty?
|
615
614
|
begin
|
616
615
|
_self = frame_eval(expr, re_raise: true)
|
617
|
-
rescue Exception
|
616
|
+
rescue Exception
|
618
617
|
# ignore
|
619
618
|
else
|
620
619
|
if M_KIND_OF_P.bind_call(_self, Module)
|
@@ -862,8 +861,18 @@ module DEBUGGER__
|
|
862
861
|
class SuspendReplay < Exception
|
863
862
|
end
|
864
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
|
+
|
865
874
|
def wait_next_action
|
866
|
-
wait_next_action_
|
875
|
+
fiber_blocking{wait_next_action_}
|
867
876
|
rescue SuspendReplay
|
868
877
|
replay_suspend
|
869
878
|
end
|
@@ -980,7 +989,7 @@ module DEBUGGER__
|
|
980
989
|
true
|
981
990
|
else
|
982
991
|
true if depth >= DEBUGGER__.frame_depth - 3 &&
|
983
|
-
caller_locations(2, 1).first.
|
992
|
+
caller_locations(2, 1).first.base_label == target_location_label
|
984
993
|
# TODO: imcomplete condition
|
985
994
|
end
|
986
995
|
end
|
@@ -996,7 +1005,7 @@ module DEBUGGER__
|
|
996
1005
|
true if pat === tp.callee_id.to_s
|
997
1006
|
else # :return, :b_return
|
998
1007
|
true if depth >= DEBUGGER__.frame_depth - 3 &&
|
999
|
-
caller_locations(2, 1).first.
|
1008
|
+
caller_locations(2, 1).first.base_label == target_location_label
|
1000
1009
|
# TODO: imcomplete condition
|
1001
1010
|
end
|
1002
1011
|
end
|
@@ -1047,14 +1056,6 @@ module DEBUGGER__
|
|
1047
1056
|
end
|
1048
1057
|
when :call
|
1049
1058
|
result = frame_eval(eval_src)
|
1050
|
-
when :irb
|
1051
|
-
require 'irb' # prelude's binding.irb doesn't have show_code option
|
1052
|
-
begin
|
1053
|
-
result = frame_eval('binding.irb(show_code: false)', binding_location: true)
|
1054
|
-
ensure
|
1055
|
-
# workaround: https://github.com/ruby/debug/issues/308
|
1056
|
-
Reline.prompt_proc = nil if defined? Reline
|
1057
|
-
end
|
1058
1059
|
when :display, :try_display
|
1059
1060
|
failed_results = []
|
1060
1061
|
eval_src.each_with_index{|src, i|
|
data/lib/debug/version.rb
CHANGED