debug 1.8.0 → 1.9.2
Sign up to get free protection for your applications and to get access to all the features.
- 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