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.
@@ -22,7 +22,7 @@ module DEBUGGER__
22
22
  if thc = Thread.current[:DEBUGGER__ThreadClient]
23
23
  thc
24
24
  else
25
- thc = SESSION.thread_client
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(frame.return_str)}"
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 is_management
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 max_lines: (CONFIG[:show_src_lines] || 10)
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(:line, :b_return, :return){|tp|
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(:line, :b_return, :return){|tp|
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
- begin
343
- @success_last_eval = false
353
+ @success_last_eval = false
344
354
 
345
- b = current_frame&.eval_binding || TOPLEVEL_BINDING
355
+ b = current_frame.eval_binding
346
356
 
347
- result = if b
348
- f, _l = b.source_location
349
- b.eval(src, "(rdbg)/#{f}")
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
- rescue Exception => e
358
- return yield(e) if block_given?
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
- puts "eval error: #{e}"
371
+ rescue Exception => e
372
+ return yield(e) if block_given?
361
373
 
362
- e.backtrace_locations&.each do |loc|
363
- break if loc.path == __FILE__
364
- puts " #{loc}"
365
- end
366
- raise if re_raise
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
- if current_frame&.has_return_value
436
- puts_variable_info '%return', current_frame.return_value, pat
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.binding, klass_name, op, method_name, cond: cond, command: cmd)
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
- depth = @target_frames.first.frame_depth
736
- step_tp iter do
737
- # 3 is debugger's frame count
738
- DEBUGGER__.frame_depth - 3 < depth
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
- # copyed from irb
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__.short_inspect(tp.return_value))
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DEBUGGER__
4
- VERSION = "1.3.1"
4
+ VERSION = "1.4.0"
5
5
  end
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
- * Integeration with rich debugger frontend
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'` line at the top of your program and putting [`binding.break`](#bindingbreak-method) method (`binding.b` for short) into lines where you want to stop as breakpoints like `binding.pry` and `binding.irb`.
64
- After that, you run the program as usual and you will enter the debug console at breakpoints you inserted.
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 debuger frontend with VSCode and Chrome.
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 `[frontned]` can attache to the port.
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 fowllowing steps.
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 tris to invoke the new VSCode window and VSCode starts attaching to the debuggee Ruby program automatically.
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.3.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-10-22 00:00:00.000000000 Z
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