debug 1.3.1 → 1.4.0
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/.github/pull_request_template.md +9 -0
- data/CONTRIBUTING.md +43 -12
- data/README.md +38 -11
- data/bin/gentest +12 -4
- data/ext/debug/debug.c +5 -2
- data/lib/debug/breakpoint.rb +61 -11
- data/lib/debug/client.rb +57 -16
- data/lib/debug/color.rb +30 -20
- data/lib/debug/config.rb +6 -3
- data/lib/debug/console.rb +17 -3
- data/lib/debug/frame_info.rb +11 -16
- data/lib/debug/prelude.rb +2 -2
- data/lib/debug/server.rb +47 -77
- data/lib/debug/server_cdp.rb +605 -94
- data/lib/debug/server_dap.rb +256 -57
- data/lib/debug/session.rb +146 -54
- data/lib/debug/source_repository.rb +4 -6
- data/lib/debug/thread_client.rb +67 -48
- data/lib/debug/tracer.rb +1 -1
- data/lib/debug/version.rb +1 -1
- data/misc/README.md.erb +16 -8
- metadata +3 -2
data/lib/debug/thread_client.rb
CHANGED
|
@@ -22,7 +22,7 @@ module DEBUGGER__
|
|
|
22
22
|
if thc = Thread.current[:DEBUGGER__ThreadClient]
|
|
23
23
|
thc
|
|
24
24
|
else
|
|
25
|
-
thc = SESSION.
|
|
25
|
+
thc = SESSION.get_thread_client
|
|
26
26
|
Thread.current[:DEBUGGER__ThreadClient] = thc
|
|
27
27
|
end
|
|
28
28
|
end
|
|
@@ -67,7 +67,7 @@ module DEBUGGER__
|
|
|
67
67
|
result = "#{call_identifier_str} at #{location_str}"
|
|
68
68
|
|
|
69
69
|
if return_str = frame.return_str
|
|
70
|
-
result += " #=> #{colorize_magenta(
|
|
70
|
+
result += " #=> #{colorize_magenta(return_str)}"
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
result
|
|
@@ -84,6 +84,7 @@ module DEBUGGER__
|
|
|
84
84
|
@output = []
|
|
85
85
|
@frame_formatter = method(:default_frame_formatter)
|
|
86
86
|
@var_map = {} # { thread_local_var_id => obj } for DAP
|
|
87
|
+
@obj_map = {} # { object_id => obj } for CDP
|
|
87
88
|
@recorder = nil
|
|
88
89
|
@mode = :waiting
|
|
89
90
|
set_mode :running
|
|
@@ -100,13 +101,13 @@ module DEBUGGER__
|
|
|
100
101
|
@is_management
|
|
101
102
|
end
|
|
102
103
|
|
|
103
|
-
def
|
|
104
|
+
def mark_as_management
|
|
104
105
|
@is_management = true
|
|
105
106
|
end
|
|
106
107
|
|
|
107
108
|
def set_mode mode
|
|
108
109
|
# STDERR.puts "#{@mode} => #{mode} @ #{caller.inspect}"
|
|
109
|
-
#pp caller
|
|
110
|
+
# pp caller
|
|
110
111
|
|
|
111
112
|
# mode transition check
|
|
112
113
|
case mode
|
|
@@ -228,7 +229,7 @@ module DEBUGGER__
|
|
|
228
229
|
suspend :pause
|
|
229
230
|
end
|
|
230
231
|
|
|
231
|
-
def suspend event, tp = nil, bp: nil, sig: nil, postmortem_frames: nil, replay_frames: nil
|
|
232
|
+
def suspend event, tp = nil, bp: nil, sig: nil, postmortem_frames: nil, replay_frames: nil, postmortem_exc: nil
|
|
232
233
|
return if management?
|
|
233
234
|
|
|
234
235
|
@current_frame_index = 0
|
|
@@ -256,10 +257,15 @@ module DEBUGGER__
|
|
|
256
257
|
cf.has_raised_exception = true
|
|
257
258
|
cf.raised_exception = bp.last_exc
|
|
258
259
|
end
|
|
260
|
+
|
|
261
|
+
if postmortem_exc
|
|
262
|
+
cf.has_raised_exception = true
|
|
263
|
+
cf.raised_exception = postmortem_exc
|
|
264
|
+
end
|
|
259
265
|
end
|
|
260
266
|
|
|
261
267
|
if event != :pause
|
|
262
|
-
show_src
|
|
268
|
+
show_src
|
|
263
269
|
show_frames CONFIG[:show_frames] || 2
|
|
264
270
|
|
|
265
271
|
set_mode :waiting
|
|
@@ -292,15 +298,15 @@ module DEBUGGER__
|
|
|
292
298
|
SUPPORT_TARGET_THREAD = false
|
|
293
299
|
end
|
|
294
300
|
|
|
295
|
-
def step_tp iter
|
|
301
|
+
def step_tp iter, events = [:line, :b_return, :return]
|
|
296
302
|
@step_tp.disable if @step_tp
|
|
297
303
|
|
|
298
304
|
thread = Thread.current
|
|
299
305
|
|
|
300
306
|
if SUPPORT_TARGET_THREAD
|
|
301
|
-
@step_tp = TracePoint.new(
|
|
307
|
+
@step_tp = TracePoint.new(*events){|tp|
|
|
302
308
|
next if SESSION.break_at? tp.path, tp.lineno
|
|
303
|
-
next if !yield
|
|
309
|
+
next if !yield(tp.event)
|
|
304
310
|
next if tp.path.start_with?(__dir__)
|
|
305
311
|
next if tp.path.start_with?('<internal:trace_point>')
|
|
306
312
|
next unless File.exist?(tp.path) if CONFIG[:skip_nosrc]
|
|
@@ -313,10 +319,10 @@ module DEBUGGER__
|
|
|
313
319
|
}
|
|
314
320
|
@step_tp.enable(target_thread: thread)
|
|
315
321
|
else
|
|
316
|
-
@step_tp = TracePoint.new(
|
|
322
|
+
@step_tp = TracePoint.new(*events){|tp|
|
|
317
323
|
next if thread != Thread.current
|
|
318
324
|
next if SESSION.break_at? tp.path, tp.lineno
|
|
319
|
-
next if !yield
|
|
325
|
+
next if !yield(tp.event)
|
|
320
326
|
next if tp.path.start_with?(__dir__)
|
|
321
327
|
next if tp.path.start_with?('<internal:trace_point>')
|
|
322
328
|
next unless File.exist?(tp.path) if CONFIG[:skip_nosrc]
|
|
@@ -338,38 +344,45 @@ module DEBUGGER__
|
|
|
338
344
|
frame_self.instance_eval(src)
|
|
339
345
|
end
|
|
340
346
|
|
|
347
|
+
SPECIAL_LOCAL_VARS = [
|
|
348
|
+
[:raised_exception, "_raised"],
|
|
349
|
+
[:return_value, "_return"],
|
|
350
|
+
]
|
|
351
|
+
|
|
341
352
|
def frame_eval src, re_raise: false
|
|
342
|
-
|
|
343
|
-
@success_last_eval = false
|
|
353
|
+
@success_last_eval = false
|
|
344
354
|
|
|
345
|
-
|
|
355
|
+
b = current_frame.eval_binding
|
|
346
356
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
else
|
|
351
|
-
frame_self = current_frame.self
|
|
352
|
-
instance_eval_for_cmethod(frame_self, src)
|
|
353
|
-
end
|
|
354
|
-
@success_last_eval = true
|
|
355
|
-
result
|
|
357
|
+
special_local_variables current_frame do |name, var|
|
|
358
|
+
b.local_variable_set(name, var) if /\%/ !~ name
|
|
359
|
+
end
|
|
356
360
|
|
|
357
|
-
|
|
358
|
-
|
|
361
|
+
result = if b
|
|
362
|
+
f, _l = b.source_location
|
|
363
|
+
b.eval(src, "(rdbg)/#{f}")
|
|
364
|
+
else
|
|
365
|
+
frame_self = current_frame.self
|
|
366
|
+
instance_eval_for_cmethod(frame_self, src)
|
|
367
|
+
end
|
|
368
|
+
@success_last_eval = true
|
|
369
|
+
result
|
|
359
370
|
|
|
360
|
-
|
|
371
|
+
rescue Exception => e
|
|
372
|
+
return yield(e) if block_given?
|
|
361
373
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
374
|
+
puts "eval error: #{e}"
|
|
375
|
+
|
|
376
|
+
e.backtrace_locations&.each do |loc|
|
|
377
|
+
break if loc.path == __FILE__
|
|
378
|
+
puts " #{loc}"
|
|
367
379
|
end
|
|
380
|
+
raise if re_raise
|
|
368
381
|
end
|
|
369
382
|
|
|
370
383
|
def show_src(frame_index: @current_frame_index,
|
|
371
384
|
update_line: false,
|
|
372
|
-
max_lines: 10,
|
|
385
|
+
max_lines: CONFIG[:show_src_lines] || 10,
|
|
373
386
|
start_line: nil,
|
|
374
387
|
end_line: nil,
|
|
375
388
|
dir: +1)
|
|
@@ -428,15 +441,20 @@ module DEBUGGER__
|
|
|
428
441
|
|
|
429
442
|
## cmd: show
|
|
430
443
|
|
|
444
|
+
def special_local_variables frame
|
|
445
|
+
SPECIAL_LOCAL_VARS.each do |mid, name|
|
|
446
|
+
next unless frame&.send("has_#{mid}")
|
|
447
|
+
name = name.sub('_', '%') if frame.eval_binding.local_variable_defined?(name)
|
|
448
|
+
yield name, frame.send(mid)
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
|
|
431
452
|
def show_locals pat
|
|
432
453
|
if s = current_frame&.self
|
|
433
454
|
puts_variable_info '%self', s, pat
|
|
434
455
|
end
|
|
435
|
-
|
|
436
|
-
puts_variable_info
|
|
437
|
-
end
|
|
438
|
-
if current_frame&.has_raised_exception
|
|
439
|
-
puts_variable_info "%raised", current_frame.raised_exception, pat
|
|
456
|
+
special_local_variables current_frame do |name, val|
|
|
457
|
+
puts_variable_info name, val, pat
|
|
440
458
|
end
|
|
441
459
|
|
|
442
460
|
if vars = current_frame&.local_variables
|
|
@@ -633,8 +651,8 @@ module DEBUGGER__
|
|
|
633
651
|
def make_breakpoint args
|
|
634
652
|
case args.first
|
|
635
653
|
when :method
|
|
636
|
-
klass_name, op, method_name, cond, cmd = args[1..]
|
|
637
|
-
bp = MethodBreakpoint.new(current_frame.
|
|
654
|
+
klass_name, op, method_name, cond, cmd, path = args[1..]
|
|
655
|
+
bp = MethodBreakpoint.new(current_frame.eval_binding, klass_name, op, method_name, cond: cond, command: cmd, path: path)
|
|
638
656
|
begin
|
|
639
657
|
bp.enable
|
|
640
658
|
rescue Exception => e
|
|
@@ -644,8 +662,8 @@ module DEBUGGER__
|
|
|
644
662
|
|
|
645
663
|
bp
|
|
646
664
|
when :watch
|
|
647
|
-
ivar, object, result = args[1..]
|
|
648
|
-
WatchIVarBreakpoint.new(ivar, object, result)
|
|
665
|
+
ivar, object, result, cond, command, path = args[1..]
|
|
666
|
+
WatchIVarBreakpoint.new(ivar, object, result, cond: cond, command: command, path: path)
|
|
649
667
|
else
|
|
650
668
|
raise "unknown breakpoint: #{args}"
|
|
651
669
|
end
|
|
@@ -732,10 +750,11 @@ module DEBUGGER__
|
|
|
732
750
|
break
|
|
733
751
|
|
|
734
752
|
when :finish
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
753
|
+
finish_frames = (iter || 1) - 1
|
|
754
|
+
goal_depth = @target_frames.first.frame_depth - finish_frames
|
|
755
|
+
|
|
756
|
+
step_tp nil, [:return, :b_return] do
|
|
757
|
+
DEBUGGER__.frame_depth - 3 <= goal_depth ? true : false
|
|
739
758
|
end
|
|
740
759
|
break
|
|
741
760
|
|
|
@@ -887,7 +906,7 @@ module DEBUGGER__
|
|
|
887
906
|
bp = make_breakpoint args
|
|
888
907
|
event! :result, :method_breakpoint, bp
|
|
889
908
|
when :watch
|
|
890
|
-
ivar = args[1]
|
|
909
|
+
ivar, cond, command, path = args[1..]
|
|
891
910
|
result = frame_eval(ivar)
|
|
892
911
|
|
|
893
912
|
if @success_last_eval
|
|
@@ -897,7 +916,7 @@ module DEBUGGER__
|
|
|
897
916
|
else
|
|
898
917
|
current_frame.self
|
|
899
918
|
end
|
|
900
|
-
bp = make_breakpoint [:watch, ivar, object, result]
|
|
919
|
+
bp = make_breakpoint [:watch, ivar, object, result, cond, command, path]
|
|
901
920
|
event! :result, :watch_breakpoint, bp
|
|
902
921
|
else
|
|
903
922
|
event! :result, nil
|
|
@@ -1067,7 +1086,7 @@ module DEBUGGER__
|
|
|
1067
1086
|
end
|
|
1068
1087
|
end
|
|
1069
1088
|
|
|
1070
|
-
#
|
|
1089
|
+
# copied from irb
|
|
1071
1090
|
class Output
|
|
1072
1091
|
include Color
|
|
1073
1092
|
|
data/lib/debug/tracer.rb
CHANGED
|
@@ -142,7 +142,7 @@ module DEBUGGER__
|
|
|
142
142
|
out tp, ">#{sp}#{call_identifier_str}", depth
|
|
143
143
|
when :return, :c_return, :b_return
|
|
144
144
|
depth += 1 if tp.event == :c_return
|
|
145
|
-
return_str = colorize_magenta(DEBUGGER__.
|
|
145
|
+
return_str = colorize_magenta(DEBUGGER__.safe_inspect(tp.return_value, short: true))
|
|
146
146
|
out tp, "<#{sp}#{call_identifier_str} #=> #{return_str}", depth
|
|
147
147
|
end
|
|
148
148
|
}
|
data/lib/debug/version.rb
CHANGED
data/misc/README.md.erb
CHANGED
|
@@ -11,7 +11,7 @@ New debug.rb has several advantages:
|
|
|
11
11
|
* [Remote debugging](#remote-debugging): Support remote debugging natively.
|
|
12
12
|
* UNIX domain socket
|
|
13
13
|
* TCP/IP
|
|
14
|
-
*
|
|
14
|
+
* Integration with rich debugger frontend
|
|
15
15
|
* VSCode/DAP ([VSCode rdbg Ruby Debugger - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=KoichiSasada.vscode-rdbg))
|
|
16
16
|
* Chrome DevTools
|
|
17
17
|
* Extensible: application can introduce debugging support with several ways:
|
|
@@ -60,8 +60,14 @@ There are several options for (1) and (2). Please choose your favorite way.
|
|
|
60
60
|
|
|
61
61
|
### Modify source code with [`binding.break`](#bindingbreak-method) (similar to `binding.pry` or `binding.irb`)
|
|
62
62
|
|
|
63
|
-
If you can modify the source code, you can use the debugger by adding `require 'debug'`
|
|
64
|
-
|
|
63
|
+
If you can modify the source code, you can use the debugger by adding `require 'debug'` at the top of your program and putting [`binding.break`](#bindingbreak-method) method into lines where you want to stop as breakpoints like `binding.pry` and `binding.irb`.
|
|
64
|
+
|
|
65
|
+
You can also use its 2 aliases in the same way:
|
|
66
|
+
|
|
67
|
+
- `binding.b`
|
|
68
|
+
- `debugger`
|
|
69
|
+
|
|
70
|
+
After that, run the program as usual and you will enter the debug console at breakpoints you inserted.
|
|
65
71
|
|
|
66
72
|
The following example shows the demonstration of [`binding.break`](#bindingbreak-method).
|
|
67
73
|
|
|
@@ -340,19 +346,19 @@ $ RUBY_DEBUG_PORT=12345 ruby target.rb
|
|
|
340
346
|
|
|
341
347
|
### Integration with external debugger frontend
|
|
342
348
|
|
|
343
|
-
You can attach with external
|
|
349
|
+
You can attach with external debugger frontend with VSCode and Chrome.
|
|
344
350
|
|
|
345
351
|
```
|
|
346
352
|
$ rdbg --open=[frontend] target.rb
|
|
347
353
|
```
|
|
348
354
|
|
|
349
|
-
will open a debug port and `[
|
|
355
|
+
will open a debug port and `[frontend]` can attach to the port.
|
|
350
356
|
|
|
351
357
|
Also `open` command allows opening the debug port.
|
|
352
358
|
|
|
353
359
|
#### VSCode integration
|
|
354
360
|
|
|
355
|
-
If you don't run a debuggee Ruby process on VSCode, you can attach with VSCode later with the
|
|
361
|
+
If you don't run a debuggee Ruby process on VSCode, you can attach with VSCode later with the following steps.
|
|
356
362
|
|
|
357
363
|
`rdbg --open=vscode` opens the debug port and tries to invoke the VSCode (`code` command).
|
|
358
364
|
|
|
@@ -364,7 +370,7 @@ Launching: code /tmp/ruby-debug-vscode-20211014-27706-gd7e85/ /tmp/ruby-debug-vs
|
|
|
364
370
|
DEBUGGER: Connected.
|
|
365
371
|
```
|
|
366
372
|
|
|
367
|
-
And it
|
|
373
|
+
And it tries to invoke the new VSCode window and VSCode starts attaching to the debuggee Ruby program automatically.
|
|
368
374
|
|
|
369
375
|
You can also use `open vscode` command in REPL.
|
|
370
376
|
|
|
@@ -427,7 +433,9 @@ Type `devtools://devtools/bundled/inspector.html?ws=127.0.0.1:43633` in the addr
|
|
|
427
433
|
|
|
428
434
|
Also `open chrome` command works like `open vscode`.
|
|
429
435
|
|
|
430
|
-
For more information about how to use Chrome debugging, you might want to read [here](https://developer.chrome.com/docs/devtools/)
|
|
436
|
+
For more information about how to use Chrome debugging, you might want to read [here](https://developer.chrome.com/docs/devtools/).
|
|
437
|
+
|
|
438
|
+
Note: If you want to maximize Chrome DevTools, click [Toggle Device Toolbar](https://developer.chrome.com/docs/devtools/device-mode/#viewport).
|
|
431
439
|
|
|
432
440
|
## Configuration
|
|
433
441
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: debug
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Koichi Sasada
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-
|
|
11
|
+
date: 2021-12-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: irb
|
|
@@ -51,6 +51,7 @@ files:
|
|
|
51
51
|
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
|
52
52
|
- ".github/ISSUE_TEMPLATE/custom.md"
|
|
53
53
|
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
|
54
|
+
- ".github/pull_request_template.md"
|
|
54
55
|
- ".github/workflows/ruby.yml"
|
|
55
56
|
- ".gitignore"
|
|
56
57
|
- CONTRIBUTING.md
|