debug 1.4.0 → 1.5.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/CONTRIBUTING.md +124 -0
- data/Gemfile +1 -0
- data/README.md +16 -16
- data/Rakefile +5 -5
- data/debug.gemspec +6 -4
- data/ext/debug/debug.c +84 -0
- data/ext/debug/extconf.rb +11 -0
- data/lib/debug/breakpoint.rb +24 -35
- data/lib/debug/client.rb +9 -3
- data/lib/debug/console.rb +34 -13
- data/lib/debug/frame_info.rb +4 -5
- data/lib/debug/local.rb +1 -1
- data/lib/debug/server.rb +65 -27
- data/lib/debug/server_cdp.rb +369 -148
- data/lib/debug/server_dap.rb +72 -75
- data/lib/debug/session.rb +225 -114
- data/lib/debug/source_repository.rb +91 -51
- data/lib/debug/thread_client.rb +94 -42
- data/lib/debug/tracer.rb +3 -9
- data/lib/debug/version.rb +1 -1
- data/misc/README.md.erb +6 -6
- metadata +4 -13
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -24
- data/.github/ISSUE_TEMPLATE/custom.md +0 -10
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -14
- data/.github/pull_request_template.md +0 -9
- data/.github/workflows/ruby.yml +0 -34
- data/.gitignore +0 -12
- data/bin/console +0 -14
- data/bin/gentest +0 -30
- data/bin/setup +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 121cdb1003971d234dbeb40878f693d06053fa32f28024c5d2a7c0e0fd6d3719
|
4
|
+
data.tar.gz: fd95c68d4bf99b38a83cef1a6851680bb9abb65d39fa9fc69a94d248295a5829
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4354a11670db6e0fd49e4b8151b268a08c7843c80ccd36b5c492cf5fabc7b42c6632939905b9912c81434f5513e36dac8378686b5d47c274248c523eea88a0c8
|
7
|
+
data.tar.gz: e22274473f567bed800c25d46a46d32adf263f070e8147cd71778ef9cbd95b8e239e2912b226892f032266a92322045a62e7f9c908f176e601a984e254acd2a7
|
data/CONTRIBUTING.md
CHANGED
@@ -249,6 +249,130 @@ Passes if `text` is not included in the last debugger log.
|
|
249
249
|
|
250
250
|
Passes if `text` is included in the debuggee log.
|
251
251
|
|
252
|
+
### Tests for DAP and CDP
|
253
|
+
|
254
|
+
Currently, there are 2 kinds of test frameworks for DAP and CDP.
|
255
|
+
|
256
|
+
1. Protocol-based tests
|
257
|
+
|
258
|
+
If you want to write protocol-based tests, you should use the test generator.
|
259
|
+
To run the test generator, you can enter `$ bin/gentest target.rb --open=vscode` in the terminal, VSCode will be executed.
|
260
|
+
Also, if you enter ``$ bin/gentest target.rb --open=chrome` there, Chrome will be executed.
|
261
|
+
If you need to modify existing tests, it is basically a good idea to regenerate them by the test generator instead of rewriting them directly.
|
262
|
+
Please refer to [the Microsoft "Debug Adapter Protocol" article](https://microsoft.github.io/debug-adapter-protocol/specification) to learn more about DAP formats.
|
263
|
+
Please refer to [Procol viewer for "Chrome DevTools Protocol"](https://chromedevtools.github.io/devtools-protocol/) to learn more about CDP formats.
|
264
|
+
|
265
|
+
2. High-level tests
|
266
|
+
|
267
|
+
High-level tests are designed to test both DAP and CDP for a single method.
|
268
|
+
You can write tests as follows:
|
269
|
+
**NOTE:** Use `req_terminate_debuggee` to finish debugging. You can't use any methods such as `req_continue`, `req_next` and so on.
|
270
|
+
|
271
|
+
```ruby
|
272
|
+
require_relative '../support/test_case'
|
273
|
+
module DEBUGGER__
|
274
|
+
class BreakTest < TestCase
|
275
|
+
# PROGRAM is the target script.
|
276
|
+
PROGRAM = <<~RUBY
|
277
|
+
1| module Foo
|
278
|
+
2| class Bar
|
279
|
+
3| def self.a
|
280
|
+
4| "hello"
|
281
|
+
5| end
|
282
|
+
6| end
|
283
|
+
7| Bar.a
|
284
|
+
8| bar = Bar.new
|
285
|
+
9| end
|
286
|
+
RUBY
|
287
|
+
|
288
|
+
def test_break1
|
289
|
+
run_protocol_scenario PROGRAM do # Start debugging with DAP and CDP
|
290
|
+
req_add_breakpoint 5 # Set a breakpoint on line 5.
|
291
|
+
req_add_breakpoint 8 # Set a breakpoint on line 8.
|
292
|
+
req_continue # Resume the program.
|
293
|
+
assert_line_num 5 # Check if debugger stops at line 5.
|
294
|
+
req_continue # Resume the program.
|
295
|
+
assert_line_num 8 # Check if debugger stops at line 8.
|
296
|
+
req_terminate_debuggee # Terminate debugging.
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
```
|
302
|
+
|
303
|
+
#### API
|
304
|
+
|
305
|
+
- run_protocol_scenario program, dap: true, cdp: true, &scenario
|
306
|
+
|
307
|
+
Execute debugging `program` with `&scenario`. If you want to test it only for DAP, you can write as follows:
|
308
|
+
|
309
|
+
`run_protocol_scenario program, cdp: false ...`
|
310
|
+
|
311
|
+
- req_add_breakpoint(lineno, path: temp_file_path, cond: nil)
|
312
|
+
|
313
|
+
Sends request to rdbg to add a breakpoint.
|
314
|
+
|
315
|
+
- req_delete_breakpoint bpnum
|
316
|
+
|
317
|
+
Sends request to rdbg to delete a breakpoint.
|
318
|
+
|
319
|
+
- req_set_exception_breakpoints
|
320
|
+
|
321
|
+
Sends request to rdbg to set exception breakpoints.
|
322
|
+
|
323
|
+
- req_continue
|
324
|
+
|
325
|
+
Sends request to rdbg to resume the program.
|
326
|
+
|
327
|
+
- req_step
|
328
|
+
|
329
|
+
Sends request to rdbg to step into next method.
|
330
|
+
|
331
|
+
- req_next
|
332
|
+
|
333
|
+
Sends request to rdbg to step over next method.
|
334
|
+
|
335
|
+
- req_finish
|
336
|
+
|
337
|
+
Sends request to rdbg to step out of current method.
|
338
|
+
|
339
|
+
- req_step_back
|
340
|
+
|
341
|
+
Sends request to rdbg to step back from current method.
|
342
|
+
|
343
|
+
- req_terminate_debuggee
|
344
|
+
|
345
|
+
Sends request to rdbg to terminate the debuggee.
|
346
|
+
|
347
|
+
- assert_reattach
|
348
|
+
|
349
|
+
Passes if reattaching to rdbg is successful.
|
350
|
+
|
351
|
+
- assert_hover_result(expected, expression: nil)
|
352
|
+
|
353
|
+
Passes if result of `expression` is equal to `expected`.
|
354
|
+
|
355
|
+
- assert_repl_result(expected, expression: nil)
|
356
|
+
|
357
|
+
Passes if result of `expression` is equal to `expected`.
|
358
|
+
|
359
|
+
- assert_watch_result(expected, expression: nil)
|
360
|
+
|
361
|
+
Passes if result of `expression` is equal to `expected`.
|
362
|
+
|
363
|
+
- assert_line_num(expected)
|
364
|
+
|
365
|
+
Passes if `expected` is equal to the location where debugger stops.
|
366
|
+
|
367
|
+
- assert_locals_result(expected)
|
368
|
+
|
369
|
+
Passes if all of `expected` local variable entries match the ones returned by debugger.
|
370
|
+
|
371
|
+
An variable entry looks like this: `{ name: "bar", value: "nil", type: "NilClass" }`.
|
372
|
+
|
373
|
+
Please note that both `value` and `type` need to be strings.
|
374
|
+
|
375
|
+
|
252
376
|
## To Update README
|
253
377
|
|
254
378
|
This project generates `README.md` from the template `misc/README.md.erb`
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
[](https://github.com/ruby/debug/actions/workflows/ruby.yml?query=branch%3Amaster)
|
1
|
+
[](https://github.com/ruby/debug/actions/workflows/ruby.yml?query=branch%3Amaster) [](https://github.com/ruby/debug/actions/workflows/protocol.yml)
|
2
2
|
|
3
3
|
# debug.rb
|
4
4
|
|
5
|
-
This library provides debugging functionality to Ruby.
|
5
|
+
This library provides debugging functionality to Ruby (MRI) 2.6 and later.
|
6
6
|
|
7
7
|
This debug.rb is replacement of traditional lib/debug.rb standard library which is implemented by `set_trace_func`.
|
8
8
|
New debug.rb has several advantages:
|
@@ -113,7 +113,7 @@ d => nil
|
|
113
113
|
5| binding.break
|
114
114
|
6| c = 3
|
115
115
|
7| d = 4
|
116
|
-
=> 8| binding.break # Again the program stops
|
116
|
+
=> 8| binding.break # Again the program stops here
|
117
117
|
9| p [a, b, c, d]
|
118
118
|
10|
|
119
119
|
11| __END__
|
@@ -358,6 +358,8 @@ Also `open` command allows opening the debug port.
|
|
358
358
|
|
359
359
|
#### VSCode integration
|
360
360
|
|
361
|
+
([vscode-rdbg v0.0.9](https://marketplace.visualstudio.com/items?itemName=KoichiSasada.vscode-rdbg) or later is required)
|
362
|
+
|
361
363
|
If you don't run a debuggee Ruby process on VSCode, you can attach with VSCode later with the following steps.
|
362
364
|
|
363
365
|
`rdbg --open=vscode` opens the debug port and tries to invoke the VSCode (`code` command).
|
@@ -417,7 +419,7 @@ Note that you can attach with `rdbg --attach` and continue REPL debugging.
|
|
417
419
|
|
418
420
|
#### Chrome DevTool integration
|
419
421
|
|
420
|
-
With `rdbg --open=chrome` command will
|
422
|
+
With `rdbg --open=chrome` command will show the following message.
|
421
423
|
|
422
424
|
```
|
423
425
|
$ rdbg target.rb --open=chrome
|
@@ -435,8 +437,6 @@ Also `open chrome` command works like `open vscode`.
|
|
435
437
|
|
436
438
|
For more information about how to use Chrome debugging, you might want to read [here](https://developer.chrome.com/docs/devtools/).
|
437
439
|
|
438
|
-
Note: If you want to maximize Chrome DevTools, click [Toggle Device Toolbar](https://developer.chrome.com/docs/devtools/device-mode/#viewport).
|
439
|
-
|
440
440
|
## Configuration
|
441
441
|
|
442
442
|
You can configure the debugger's behavior with debug commands and environment variables.
|
@@ -567,8 +567,8 @@ The `<...>` notation means the argument.
|
|
567
567
|
* break and run `<command>` before stopping.
|
568
568
|
* `b[reak] ... do: <command>`
|
569
569
|
* break and run `<command>`, and continue.
|
570
|
-
* `b[reak] ... path: <
|
571
|
-
* break if the
|
570
|
+
* `b[reak] ... path: <path>`
|
571
|
+
* break if the path matches to `<path>`. `<path>` can be a regexp with `/regexp/`.
|
572
572
|
* `b[reak] if: <expr>`
|
573
573
|
* break if: `<expr>` is true at any lines.
|
574
574
|
* Note that this feature is super slow.
|
@@ -580,8 +580,8 @@ The `<...>` notation means the argument.
|
|
580
580
|
* runs `<command>` before stopping.
|
581
581
|
* `catch ... do: <command>`
|
582
582
|
* stops and run `<command>`, and continue.
|
583
|
-
* `catch ... path: <
|
584
|
-
* stops if the exception is raised from a path
|
583
|
+
* `catch ... path: <path>`
|
584
|
+
* stops if the exception is raised from a `<path>`. `<path>` can be a regexp with `/regexp/`.
|
585
585
|
* `watch @ivar`
|
586
586
|
* Stop the execution when the result of current scope's `@ivar` is changed.
|
587
587
|
* Note that this feature is super slow.
|
@@ -591,8 +591,8 @@ The `<...>` notation means the argument.
|
|
591
591
|
* runs `<command>` before stopping.
|
592
592
|
* `watch ... do: <command>`
|
593
593
|
* stops and run `<command>`, and continue.
|
594
|
-
* `watch ... path: <
|
595
|
-
* stops if the
|
594
|
+
* `watch ... path: <path>`
|
595
|
+
* stops if the path matches `<path>`. `<path>` can be a regexp with `/regexp/`.
|
596
596
|
* `del[ete]`
|
597
597
|
* delete all breakpoints.
|
598
598
|
* `del[ete] <bpnum>`
|
@@ -631,8 +631,8 @@ The `<...>` notation means the argument.
|
|
631
631
|
* Show information about accessible constants except toplevel constants.
|
632
632
|
* `i[nfo] g[lobal[s]]`
|
633
633
|
* Show information about global variables
|
634
|
-
* `i[nfo] ...
|
635
|
-
* Filter the output with
|
634
|
+
* `i[nfo] ... /regexp/`
|
635
|
+
* Filter the output with `/regexp/`.
|
636
636
|
* `i[nfo] th[read[s]]`
|
637
637
|
* Show all threads (same as `th[read]`).
|
638
638
|
* `o[utline]` or `ls`
|
@@ -683,8 +683,8 @@ The `<...>` notation means the argument.
|
|
683
683
|
* Add an exception tracer. It indicates raising exceptions.
|
684
684
|
* `trace object <expr>`
|
685
685
|
* Add an object tracer. It indicates that an object by `<expr>` is passed as a parameter or a receiver on method call.
|
686
|
-
* `trace ...
|
687
|
-
* Indicates only matched events to
|
686
|
+
* `trace ... /regexp/`
|
687
|
+
* Indicates only matched events to `/regexp/`.
|
688
688
|
* `trace ... into: <file>`
|
689
689
|
* Save trace information into: `<file>`.
|
690
690
|
* `trace off <num>`
|
data/Rakefile
CHANGED
@@ -2,8 +2,6 @@ require "bundler/gem_tasks"
|
|
2
2
|
require "rake/testtask"
|
3
3
|
|
4
4
|
Rake::TestTask.new(:test) do |t|
|
5
|
-
t.libs << "test"
|
6
|
-
t.libs << "lib"
|
7
5
|
t.test_files = FileList["test/**/*_test.rb"]
|
8
6
|
end
|
9
7
|
|
@@ -17,7 +15,6 @@ begin
|
|
17
15
|
rescue LoadError
|
18
16
|
end
|
19
17
|
|
20
|
-
|
21
18
|
task :default => [:clobber, :compile, 'README.md', :test]
|
22
19
|
|
23
20
|
file 'README.md' => ['lib/debug/session.rb', 'lib/debug/config.rb',
|
@@ -28,7 +25,10 @@ file 'README.md' => ['lib/debug/session.rb', 'lib/debug/config.rb',
|
|
28
25
|
puts 'README.md is updated.'
|
29
26
|
end
|
30
27
|
|
31
|
-
task :
|
32
|
-
|
28
|
+
task :test_protocol do
|
29
|
+
ENV['RUBY_DEBUG_PROTOCOL_TEST'] = '1'
|
33
30
|
end
|
34
31
|
|
32
|
+
Rake::TestTask.new(:test_protocol) do |t|
|
33
|
+
t.test_files = FileList["test/protocol/*_test.rb"]
|
34
|
+
end
|
data/debug.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.email = ["ko1@atdot.net"]
|
8
8
|
|
9
9
|
spec.summary = %q{Debugging functionality for Ruby}
|
10
|
-
spec.description = %q{Debugging functionality for Ruby. This is completely rewritten debug.rb which was contained by the
|
10
|
+
spec.description = %q{Debugging functionality for Ruby. This is completely rewritten debug.rb which was contained by the ancient Ruby versions.}
|
11
11
|
spec.homepage = "https://github.com/ruby/debug"
|
12
12
|
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
13
13
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
|
@@ -17,11 +17,13 @@ Gem::Specification.new do |spec|
|
|
17
17
|
|
18
18
|
# Specify which files should be added to the gem when it is released.
|
19
19
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
20
|
-
spec.files
|
21
|
-
`git ls-files -z`.split("\x0").reject
|
20
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
21
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
22
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
23
|
+
end
|
22
24
|
end
|
23
25
|
spec.bindir = "exe"
|
24
|
-
spec.executables = spec.files.grep(%r{
|
26
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
25
27
|
spec.require_paths = ["lib"]
|
26
28
|
spec.extensions = ['ext/debug/extconf.rb']
|
27
29
|
|
data/ext/debug/debug.c
CHANGED
@@ -118,11 +118,82 @@ create_method_added_tracker(VALUE self)
|
|
118
118
|
return rb_tracepoint_new(0, RUBY_EVENT_CALL, method_added_tracker, NULL);
|
119
119
|
}
|
120
120
|
|
121
|
+
// iseq
|
122
|
+
|
123
|
+
const struct rb_iseq *rb_iseqw_to_iseq(VALUE iseqw);
|
124
|
+
|
125
|
+
#ifdef HAVE_RB_ISEQ_TYPE
|
126
|
+
VALUE rb_iseq_type(const struct rb_iseq *);
|
127
|
+
|
128
|
+
static VALUE
|
129
|
+
iseq_type(VALUE iseqw)
|
130
|
+
{
|
131
|
+
const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw);
|
132
|
+
return rb_iseq_type(iseq);
|
133
|
+
}
|
134
|
+
#endif
|
135
|
+
|
136
|
+
#ifdef HAVE_RB_ISEQ_PARAMETERS
|
137
|
+
VALUE rb_iseq_parameters(const struct rb_iseq *, int is_proc);
|
138
|
+
|
139
|
+
static VALUE
|
140
|
+
iseq_parameters_symbols(VALUE iseqw)
|
141
|
+
{
|
142
|
+
const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw);
|
143
|
+
VALUE params = rb_iseq_parameters(iseq, 0);
|
144
|
+
VALUE ary = rb_ary_new();
|
145
|
+
|
146
|
+
static VALUE sym_ast, sym_astast, sym_amp;
|
147
|
+
|
148
|
+
if (sym_ast == 0) {
|
149
|
+
sym_ast = ID2SYM(rb_intern("*"));
|
150
|
+
sym_astast = ID2SYM(rb_intern("**"));
|
151
|
+
sym_amp = ID2SYM(rb_intern("&"));
|
152
|
+
}
|
153
|
+
|
154
|
+
for (long i=0; i<RARRAY_LEN(params); i++) {
|
155
|
+
VALUE e = RARRAY_AREF(params, i);
|
156
|
+
if (RARRAY_LEN(e) == 2) {
|
157
|
+
VALUE sym = RARRAY_AREF(e, 1);
|
158
|
+
if (sym != sym_ast &&
|
159
|
+
sym != sym_astast &&
|
160
|
+
sym != sym_amp) rb_ary_push(ary, RARRAY_AREF(e, 1));
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
return ary;
|
165
|
+
}
|
166
|
+
#endif
|
167
|
+
|
168
|
+
#ifdef HAVE_RB_ISEQ_CODE_LOCATION
|
169
|
+
void rb_iseq_code_location(const struct rb_iseq *, int *first_lineno, int *first_column, int *last_lineno, int *last_column);
|
170
|
+
|
171
|
+
static VALUE
|
172
|
+
iseq_first_line(VALUE iseqw)
|
173
|
+
{
|
174
|
+
const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw);
|
175
|
+
int line;
|
176
|
+
rb_iseq_code_location(iseq, &line, NULL, NULL, NULL);
|
177
|
+
return INT2NUM(line);
|
178
|
+
}
|
179
|
+
|
180
|
+
static VALUE
|
181
|
+
iseq_last_line(VALUE iseqw)
|
182
|
+
{
|
183
|
+
const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw);
|
184
|
+
int line;
|
185
|
+
rb_iseq_code_location(iseq, NULL, NULL, &line, NULL);
|
186
|
+
return INT2NUM(line);
|
187
|
+
}
|
188
|
+
#endif
|
189
|
+
|
121
190
|
void Init_iseq_collector(void);
|
122
191
|
|
123
192
|
void
|
124
193
|
Init_debug(void)
|
125
194
|
{
|
195
|
+
VALUE rb_mRubyVM = rb_const_get(rb_cObject, rb_intern("RubyVM"));
|
196
|
+
VALUE rb_cISeq = rb_const_get(rb_mRubyVM, rb_intern("InstructionSequence"));
|
126
197
|
rb_mDebugger = rb_const_get(rb_cObject, rb_intern("DEBUGGER__"));
|
127
198
|
rb_cFrameInfo = rb_const_get(rb_mDebugger, rb_intern("FrameInfo"));
|
128
199
|
|
@@ -134,5 +205,18 @@ Init_debug(void)
|
|
134
205
|
rb_define_singleton_method(rb_mDebugger, "frame_depth", frame_depth, 0);
|
135
206
|
rb_define_singleton_method(rb_mDebugger, "create_method_added_tracker", create_method_added_tracker, 0);
|
136
207
|
rb_define_const(rb_mDebugger, "SO_VERSION", rb_str_new2(RUBY_DEBUG_VERSION));
|
208
|
+
|
209
|
+
// iseq
|
210
|
+
#ifdef HAVE_RB_ISEQ_TYPE
|
211
|
+
rb_define_method(rb_cISeq, "type", iseq_type, 0);
|
212
|
+
#endif
|
213
|
+
#ifdef HAVE_RB_ISEQ_PARAMETERS
|
214
|
+
rb_define_method(rb_cISeq, "parameters_symbols", iseq_parameters_symbols, 0);
|
215
|
+
#endif
|
216
|
+
#ifdef HAVE_RB_ISEQ_CODE_LOCATION
|
217
|
+
rb_define_method(rb_cISeq, "first_line", iseq_first_line, 0);
|
218
|
+
rb_define_method(rb_cISeq, "last_line", iseq_last_line, 0);
|
219
|
+
#endif
|
220
|
+
|
137
221
|
Init_iseq_collector();
|
138
222
|
}
|
data/ext/debug/extconf.rb
CHANGED
@@ -1,4 +1,15 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
require_relative '../../lib/debug/version'
|
3
3
|
File.write("debug_version.h", "#define RUBY_DEBUG_VERSION \"#{DEBUGGER__::VERSION}\"\n")
|
4
|
+
|
5
|
+
have_func "rb_iseq_parameters(NULL, 0)",
|
6
|
+
[["VALUE rb_iseq_parameters(void *, int is_proc);"]]
|
7
|
+
|
8
|
+
have_func "rb_iseq_code_location(NULL, NULL, NULL, NULL, NULL)",
|
9
|
+
[["void rb_iseq_code_location(void *, int *first_lineno, int *first_column, int *last_lineno, int *last_column);"]]
|
10
|
+
|
11
|
+
# from Ruby 3.1
|
12
|
+
have_func "rb_iseq_type(NULL)",
|
13
|
+
[["VALUE rb_iseq_type(void *);"]]
|
14
|
+
|
4
15
|
create_makefile 'debug/debug'
|
data/lib/debug/breakpoint.rb
CHANGED
@@ -8,9 +8,13 @@ module DEBUGGER__
|
|
8
8
|
|
9
9
|
attr_reader :key
|
10
10
|
|
11
|
-
def initialize do_enable
|
11
|
+
def initialize cond, command, path, do_enable: true
|
12
12
|
@deleted = false
|
13
13
|
|
14
|
+
@cond = cond
|
15
|
+
@command = command
|
16
|
+
@path = path
|
17
|
+
|
14
18
|
setup
|
15
19
|
enable if do_enable
|
16
20
|
end
|
@@ -82,8 +86,11 @@ module DEBUGGER__
|
|
82
86
|
end
|
83
87
|
|
84
88
|
def skip_path?(path)
|
85
|
-
|
89
|
+
case @path
|
90
|
+
when Regexp
|
86
91
|
!path.match?(@path)
|
92
|
+
when String
|
93
|
+
!path.include?(@path)
|
87
94
|
else
|
88
95
|
super
|
89
96
|
end
|
@@ -108,7 +115,7 @@ module DEBUGGER__
|
|
108
115
|
@oneshot = oneshot
|
109
116
|
@key = [:iseq, @iseq.path, @iseq.first_lineno].freeze
|
110
117
|
|
111
|
-
super()
|
118
|
+
super(nil, nil, nil)
|
112
119
|
end
|
113
120
|
|
114
121
|
def setup
|
@@ -127,20 +134,17 @@ module DEBUGGER__
|
|
127
134
|
attr_reader :path, :line, :iseq
|
128
135
|
|
129
136
|
def initialize path, line, cond: nil, oneshot: false, hook_call: true, command: nil
|
130
|
-
@path = path
|
131
137
|
@line = line
|
132
|
-
@cond = cond
|
133
138
|
@oneshot = oneshot
|
134
139
|
@hook_call = hook_call
|
135
|
-
@command = command
|
136
140
|
@pending = false
|
137
141
|
|
138
142
|
@iseq = nil
|
139
143
|
@type = nil
|
140
144
|
|
141
|
-
@key = [
|
145
|
+
@key = [path, @line].freeze
|
142
146
|
|
143
|
-
super()
|
147
|
+
super(cond, command, path)
|
144
148
|
|
145
149
|
try_activate
|
146
150
|
@pending = !@iseq
|
@@ -216,7 +220,7 @@ module DEBUGGER__
|
|
216
220
|
nearest = nil # NearestISeq
|
217
221
|
|
218
222
|
ObjectSpace.each_iseq{|iseq|
|
219
|
-
if (iseq.absolute_path || iseq.path)
|
223
|
+
if DEBUGGER__.compare_path((iseq.absolute_path || iseq.path), self.path) &&
|
220
224
|
iseq.first_lineno <= self.line &&
|
221
225
|
iseq.type != :ensure # ensure iseq is copied (duplicated)
|
222
226
|
|
@@ -277,11 +281,7 @@ module DEBUGGER__
|
|
277
281
|
@key = [:catch, @pat].freeze
|
278
282
|
@last_exc = nil
|
279
283
|
|
280
|
-
|
281
|
-
@command = command
|
282
|
-
@path = path
|
283
|
-
|
284
|
-
super()
|
284
|
+
super(cond, command, path)
|
285
285
|
end
|
286
286
|
|
287
287
|
def setup
|
@@ -314,29 +314,28 @@ module DEBUGGER__
|
|
314
314
|
end
|
315
315
|
|
316
316
|
class CheckBreakpoint < Breakpoint
|
317
|
-
def initialize
|
318
|
-
@
|
319
|
-
@key = [:check, @expr].freeze
|
320
|
-
@path = path
|
317
|
+
def initialize cond:, command: nil, path: nil
|
318
|
+
@key = [:check, cond].freeze
|
321
319
|
|
322
|
-
super()
|
320
|
+
super(cond, command, path)
|
323
321
|
end
|
324
322
|
|
325
323
|
def setup
|
326
324
|
@tp = TracePoint.new(:line){|tp|
|
327
|
-
next if
|
328
|
-
next if tp.path.start_with? '<internal:'
|
325
|
+
next if SESSION.in_subsession? # TODO: Ractor support
|
329
326
|
next if ThreadClient.current.management?
|
330
327
|
next if skip_path?(tp.path)
|
331
328
|
|
332
|
-
if safe_eval tp.binding, @
|
329
|
+
if safe_eval tp.binding, @cond
|
333
330
|
suspend
|
334
331
|
end
|
335
332
|
}
|
336
333
|
end
|
337
334
|
|
338
335
|
def to_s
|
339
|
-
"#{generate_label("Check")}
|
336
|
+
s = "#{generate_label("Check")}"
|
337
|
+
s += super
|
338
|
+
s
|
340
339
|
end
|
341
340
|
end
|
342
341
|
|
@@ -348,10 +347,7 @@ module DEBUGGER__
|
|
348
347
|
|
349
348
|
@current = current
|
350
349
|
|
351
|
-
|
352
|
-
@command = command
|
353
|
-
@path = path
|
354
|
-
super()
|
350
|
+
super(cond, command, path)
|
355
351
|
end
|
356
352
|
|
357
353
|
def watch_eval(tp)
|
@@ -374,9 +370,6 @@ module DEBUGGER__
|
|
374
370
|
|
375
371
|
def setup
|
376
372
|
@tp = TracePoint.new(:line, :return, :b_return){|tp|
|
377
|
-
next if tp.path.start_with? __dir__
|
378
|
-
next if tp.path.start_with? '<internal:'
|
379
|
-
|
380
373
|
watch_eval(tp)
|
381
374
|
}
|
382
375
|
end
|
@@ -404,13 +397,10 @@ module DEBUGGER__
|
|
404
397
|
|
405
398
|
@klass = nil
|
406
399
|
@method = nil
|
407
|
-
@cond = cond
|
408
400
|
@cond_class = nil
|
409
|
-
@command = command
|
410
|
-
@path = path
|
411
401
|
@key = "#{klass_name}#{op}#{method_name}".freeze
|
412
402
|
|
413
|
-
super(false)
|
403
|
+
super(cond, command, path, do_enable: false)
|
414
404
|
end
|
415
405
|
|
416
406
|
def setup
|
@@ -419,7 +409,6 @@ module DEBUGGER__
|
|
419
409
|
next if @cond_class && !tp.self.kind_of?(@cond_class)
|
420
410
|
|
421
411
|
caller_location = caller_locations(2, 1).first.to_s
|
422
|
-
next if caller_location.start_with?(__dir__)
|
423
412
|
next if skip_path?(caller_location)
|
424
413
|
|
425
414
|
suspend
|
data/lib/debug/client.rb
CHANGED
@@ -18,6 +18,10 @@ module DEBUGGER__
|
|
18
18
|
case name
|
19
19
|
when 'gen-sockpath'
|
20
20
|
puts DEBUGGER__.create_unix_domain_socket_name
|
21
|
+
when 'gen-portpath'
|
22
|
+
port_path = File.join(DEBUGGER__.unix_domain_socket_dir, 'tcp_port')
|
23
|
+
File.unlink port_path if File.exist?(port_path)
|
24
|
+
puts port_path
|
21
25
|
when 'list-socks'
|
22
26
|
cleanup_unix_domain_sockets
|
23
27
|
puts list_connections
|
@@ -76,7 +80,7 @@ module DEBUGGER__
|
|
76
80
|
|
77
81
|
def cleanup_unix_domain_sockets
|
78
82
|
Dir.glob(DEBUGGER__.create_unix_domain_socket_name_prefix + '*') do |file|
|
79
|
-
if
|
83
|
+
if File.socket?(file) && (/-(\d+)-\d+$/ =~ file || /-(\d+)$/ =~ file)
|
80
84
|
begin
|
81
85
|
Process.kill(0, $1.to_i)
|
82
86
|
rescue Errno::EPERM
|
@@ -88,7 +92,9 @@ module DEBUGGER__
|
|
88
92
|
end
|
89
93
|
|
90
94
|
def list_connections
|
91
|
-
Dir.glob(DEBUGGER__.create_unix_domain_socket_name_prefix + '*')
|
95
|
+
Dir.glob(DEBUGGER__.create_unix_domain_socket_name_prefix + '*').find_all do |path|
|
96
|
+
File.socket?(path)
|
97
|
+
end
|
92
98
|
end
|
93
99
|
end
|
94
100
|
|
@@ -175,7 +181,7 @@ module DEBUGGER__
|
|
175
181
|
trap(:SIGWINCH){
|
176
182
|
@width = IO.console_size[1]
|
177
183
|
}
|
178
|
-
rescue ArgumentError
|
184
|
+
rescue ArgumentError
|
179
185
|
@width = 80
|
180
186
|
end
|
181
187
|
|