debug 1.6.1 → 1.9.1
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 +22 -10
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +84 -55
- data/Rakefile +8 -3
- data/TODO.md +8 -8
- data/debug.gemspec +3 -3
- data/exe/rdbg +19 -4
- data/ext/debug/debug.c +33 -5
- data/ext/debug/extconf.rb +1 -0
- data/ext/debug/iseq_collector.c +2 -0
- data/lib/debug/abbrev_command.rb +77 -0
- data/lib/debug/breakpoint.rb +15 -11
- data/lib/debug/client.rb +26 -8
- data/lib/debug/color.rb +0 -0
- data/lib/debug/config.rb +69 -23
- data/lib/debug/console.rb +8 -29
- data/lib/debug/dap_custom/traceInspector.rb +336 -0
- data/lib/debug/frame_info.rb +9 -0
- data/lib/debug/irb_integration.rb +27 -0
- data/lib/debug/local.rb +16 -10
- data/lib/debug/open.rb +0 -0
- data/lib/debug/open_nonstop.rb +0 -0
- data/lib/debug/prelude.rb +2 -1
- data/lib/debug/server.rb +32 -27
- data/lib/debug/server_cdp.rb +360 -155
- data/lib/debug/server_dap.rb +330 -197
- data/lib/debug/session.rb +494 -258
- data/lib/debug/source_repository.rb +41 -21
- data/lib/debug/start.rb +1 -1
- data/lib/debug/thread_client.rb +241 -82
- data/lib/debug/tracer.rb +4 -5
- data/lib/debug/version.rb +1 -1
- data/lib/debug.rb +7 -2
- data/misc/README.md.erb +50 -44
- metadata +13 -10
@@ -0,0 +1,336 @@
|
|
1
|
+
module DEBUGGER__
|
2
|
+
module DAP_TraceInspector
|
3
|
+
class MultiTracer < Tracer
|
4
|
+
def initialize ui, evts, trace_params, max_log_size: nil, **kw
|
5
|
+
@evts = evts
|
6
|
+
@log = []
|
7
|
+
@trace_params = trace_params
|
8
|
+
if max_log_size
|
9
|
+
@max_log_size = max_log_size
|
10
|
+
else
|
11
|
+
@max_log_size = 50000
|
12
|
+
end
|
13
|
+
@dropped_trace_cnt = 0
|
14
|
+
super(ui, **kw)
|
15
|
+
@type = 'multi'
|
16
|
+
@name = 'TraceInspector'
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_accessor :dropped_trace_cnt
|
20
|
+
attr_reader :log
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@tracer = TracePoint.new(*@evts){|tp|
|
24
|
+
next if skip?(tp)
|
25
|
+
|
26
|
+
case tp.event
|
27
|
+
when :call, :c_call, :b_call
|
28
|
+
if @trace_params
|
29
|
+
params = parameters_info tp
|
30
|
+
end
|
31
|
+
append(call_trace_log(tp, params: params))
|
32
|
+
when :return, :c_return, :b_return
|
33
|
+
return_str = DEBUGGER__.safe_inspect(tp.return_value, short: true, max_length: 4096)
|
34
|
+
append(call_trace_log(tp, return_str: return_str))
|
35
|
+
when :line
|
36
|
+
append(line_trace_log(tp))
|
37
|
+
end
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def parameters_info tp
|
42
|
+
b = tp.binding
|
43
|
+
tp.parameters.map{|_type, name|
|
44
|
+
begin
|
45
|
+
{ name: name, value: DEBUGGER__.safe_inspect(b.local_variable_get(name), short: true, max_length: 4096) }
|
46
|
+
rescue NameError, TypeError
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
}.compact
|
50
|
+
end
|
51
|
+
|
52
|
+
def call_identifier_str tp
|
53
|
+
if tp.defined_class
|
54
|
+
minfo(tp)
|
55
|
+
else
|
56
|
+
"block"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def append log
|
61
|
+
if @log.size >= @max_log_size
|
62
|
+
@dropped_trace_cnt += 1
|
63
|
+
@log.shift
|
64
|
+
end
|
65
|
+
@log << log
|
66
|
+
end
|
67
|
+
|
68
|
+
def call_trace_log tp, return_str: nil, params: nil
|
69
|
+
log = {
|
70
|
+
depth: DEBUGGER__.frame_depth,
|
71
|
+
name: call_identifier_str(tp),
|
72
|
+
threadId: Thread.current.instance_variable_get(:@__thread_client_id),
|
73
|
+
location: {
|
74
|
+
path: tp.path,
|
75
|
+
line: tp.lineno
|
76
|
+
}
|
77
|
+
}
|
78
|
+
log[:returnValue] = return_str if return_str
|
79
|
+
log[:parameters] = params if params && params.size > 0
|
80
|
+
log
|
81
|
+
end
|
82
|
+
|
83
|
+
def line_trace_log tp
|
84
|
+
{
|
85
|
+
depth: DEBUGGER__.frame_depth,
|
86
|
+
threadId: Thread.current.instance_variable_get(:@__thread_client_id),
|
87
|
+
location: {
|
88
|
+
path: tp.path,
|
89
|
+
line: tp.lineno
|
90
|
+
}
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def skip? tp
|
95
|
+
super || !@evts.include?(tp.event)
|
96
|
+
end
|
97
|
+
|
98
|
+
def skip_with_pattern?(tp)
|
99
|
+
super && !tp.method_id&.match?(@pattern)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class Custom_Recorder < ThreadClient::Recorder
|
104
|
+
def initialize max_log_size: nil
|
105
|
+
if max_log_size
|
106
|
+
@max_log_size = max_log_size
|
107
|
+
else
|
108
|
+
@max_log_size = 50000
|
109
|
+
end
|
110
|
+
@dropped_trace_cnt = 0
|
111
|
+
super()
|
112
|
+
end
|
113
|
+
|
114
|
+
attr_accessor :dropped_trace_cnt
|
115
|
+
|
116
|
+
def append frames
|
117
|
+
if @log.size >= @max_log_size
|
118
|
+
@dropped_trace_cnt += 1
|
119
|
+
@log.shift
|
120
|
+
end
|
121
|
+
@log << frames
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
module Custom_UI_DAP
|
126
|
+
def custom_dap_request_rdbgTraceInspector(req)
|
127
|
+
@q_msg << req
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
module Custom_Session
|
132
|
+
def process_trace_cmd req
|
133
|
+
cmd = req.dig('arguments', 'subCommand')
|
134
|
+
case cmd
|
135
|
+
when 'enable'
|
136
|
+
events = req.dig('arguments', 'events')
|
137
|
+
evts = []
|
138
|
+
trace_params = false
|
139
|
+
filter = req.dig('arguments', 'filterRegExp')
|
140
|
+
max_log_size = req.dig('arguments', 'maxLogSize')
|
141
|
+
events.each{|evt|
|
142
|
+
case evt
|
143
|
+
when 'traceLine'
|
144
|
+
evts << :line
|
145
|
+
when 'traceCall'
|
146
|
+
evts << :call
|
147
|
+
evts << :b_call
|
148
|
+
when 'traceReturn'
|
149
|
+
evts << :return
|
150
|
+
evts << :b_return
|
151
|
+
when 'traceParams'
|
152
|
+
trace_params = true
|
153
|
+
when 'traceClanguageCall'
|
154
|
+
evts << :c_call
|
155
|
+
when 'traceClanguageReturn'
|
156
|
+
evts << :c_return
|
157
|
+
else
|
158
|
+
raise "unknown trace type #{evt}"
|
159
|
+
end
|
160
|
+
}
|
161
|
+
add_tracer MultiTracer.new @ui, evts, trace_params, max_log_size: max_log_size, pattern: filter
|
162
|
+
@ui.respond req, {}
|
163
|
+
when 'disable'
|
164
|
+
if t = find_multi_trace
|
165
|
+
t.disable
|
166
|
+
end
|
167
|
+
@ui.respond req, {}
|
168
|
+
when 'collect'
|
169
|
+
logs = []
|
170
|
+
if t = find_multi_trace
|
171
|
+
logs = t.log
|
172
|
+
if t.dropped_trace_cnt > 0
|
173
|
+
@ui.puts "Return #{logs.size} traces and #{t.dropped_trace_cnt} traces are dropped"
|
174
|
+
else
|
175
|
+
@ui.puts "Return #{logs.size} traces"
|
176
|
+
end
|
177
|
+
t.dropped_trace_cnt = 0
|
178
|
+
end
|
179
|
+
@ui.respond req, logs: logs
|
180
|
+
else
|
181
|
+
raise "Unknown trace sub command #{cmd}"
|
182
|
+
end
|
183
|
+
return :retry
|
184
|
+
end
|
185
|
+
|
186
|
+
def find_multi_trace
|
187
|
+
@tracers.values.each{|t|
|
188
|
+
if t.type == 'multi'
|
189
|
+
return t
|
190
|
+
end
|
191
|
+
}
|
192
|
+
return nil
|
193
|
+
end
|
194
|
+
|
195
|
+
def process_record_cmd req
|
196
|
+
cmd = req.dig('arguments', 'subCommand')
|
197
|
+
case cmd
|
198
|
+
when 'enable'
|
199
|
+
@tc << [:dap, :rdbgTraceInspector, req]
|
200
|
+
when 'disable'
|
201
|
+
@tc << [:dap, :rdbgTraceInspector, req]
|
202
|
+
when 'step'
|
203
|
+
tid = req.dig('arguments', 'threadId')
|
204
|
+
count = req.dig('arguments', 'count')
|
205
|
+
if tc = find_waiting_tc(tid)
|
206
|
+
@ui.respond req, {}
|
207
|
+
tc << [:step, :in, count]
|
208
|
+
else
|
209
|
+
fail_response req
|
210
|
+
end
|
211
|
+
when 'stepBack'
|
212
|
+
tid = req.dig('arguments', 'threadId')
|
213
|
+
count = req.dig('arguments', 'count')
|
214
|
+
if tc = find_waiting_tc(tid)
|
215
|
+
@ui.respond req, {}
|
216
|
+
tc << [:step, :back, count]
|
217
|
+
else
|
218
|
+
fail_response req
|
219
|
+
end
|
220
|
+
when 'collect'
|
221
|
+
tid = req.dig('arguments', 'threadId')
|
222
|
+
if tc = find_waiting_tc(tid)
|
223
|
+
tc << [:dap, :rdbgTraceInspector, req]
|
224
|
+
else
|
225
|
+
fail_response req
|
226
|
+
end
|
227
|
+
else
|
228
|
+
raise "Unknown record sub command #{cmd}"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def custom_dap_request_rdbgTraceInspector(req)
|
233
|
+
cmd = req.dig('arguments', 'command')
|
234
|
+
case cmd
|
235
|
+
when 'trace'
|
236
|
+
process_trace_cmd req
|
237
|
+
when 'record'
|
238
|
+
process_record_cmd req
|
239
|
+
else
|
240
|
+
raise "Unknown command #{cmd}"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def custom_dap_request_event_rdbgTraceInspector(req, result)
|
245
|
+
cmd = req.dig('arguments', 'command')
|
246
|
+
case cmd
|
247
|
+
when 'record'
|
248
|
+
process_event_record_cmd(req, result)
|
249
|
+
else
|
250
|
+
raise "Unknown command #{cmd}"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def process_event_record_cmd(req, result)
|
255
|
+
cmd = req.dig('arguments', 'subCommand')
|
256
|
+
case cmd
|
257
|
+
when 'enable'
|
258
|
+
@ui.respond req, {}
|
259
|
+
when 'disable'
|
260
|
+
@ui.respond req, {}
|
261
|
+
when 'collect'
|
262
|
+
cnt = result.delete :dropped_trace_cnt
|
263
|
+
if cnt > 0
|
264
|
+
@ui.puts "Return #{result[:logs].size} traces and #{cnt} traces are dropped"
|
265
|
+
else
|
266
|
+
@ui.puts "Return #{result[:logs].size} traces"
|
267
|
+
end
|
268
|
+
@ui.respond req, result
|
269
|
+
else
|
270
|
+
raise "Unknown command #{cmd}"
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
module Custom_ThreadClient
|
276
|
+
def custom_dap_request_rdbgTraceInspector(req)
|
277
|
+
cmd = req.dig('arguments', 'command')
|
278
|
+
case cmd
|
279
|
+
when 'record'
|
280
|
+
process_record_cmd(req)
|
281
|
+
else
|
282
|
+
raise "Unknown command #{cmd}"
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def process_record_cmd(req)
|
287
|
+
cmd = req.dig('arguments', 'subCommand')
|
288
|
+
case cmd
|
289
|
+
when 'enable'
|
290
|
+
size = req.dig('arguments', 'maxLogSize')
|
291
|
+
@recorder = Custom_Recorder.new max_log_size: size
|
292
|
+
@recorder.enable
|
293
|
+
event! :protocol_result, :rdbgTraceInspector, req
|
294
|
+
when 'disable'
|
295
|
+
if @recorder&.enabled?
|
296
|
+
@recorder.disable
|
297
|
+
end
|
298
|
+
@recorder = nil
|
299
|
+
event! :protocol_result, :rdbgTraceInspector, req
|
300
|
+
when 'collect'
|
301
|
+
logs = []
|
302
|
+
log_index = nil
|
303
|
+
trace_cnt = 0
|
304
|
+
unless @recorder.nil?
|
305
|
+
log_index = @recorder.log_index
|
306
|
+
@recorder.log.each{|frames|
|
307
|
+
crt_frame = frames[0]
|
308
|
+
log = {
|
309
|
+
name: crt_frame.name,
|
310
|
+
location: {
|
311
|
+
path: crt_frame.location.path,
|
312
|
+
line: crt_frame.location.lineno,
|
313
|
+
},
|
314
|
+
depth: crt_frame.frame_depth
|
315
|
+
}
|
316
|
+
if params = crt_frame.iseq_parameters_info
|
317
|
+
log[:parameters] = params
|
318
|
+
end
|
319
|
+
if return_str = crt_frame.return_str
|
320
|
+
log[:returnValue] = return_str
|
321
|
+
end
|
322
|
+
logs << log
|
323
|
+
}
|
324
|
+
trace_cnt = @recorder.dropped_trace_cnt
|
325
|
+
@recorder.dropped_trace_cnt = 0
|
326
|
+
end
|
327
|
+
event! :protocol_result, :rdbgTraceInspector, req, logs: logs, stoppedIndex: log_index, dropped_trace_cnt: trace_cnt
|
328
|
+
else
|
329
|
+
raise "Unknown command #{cmd}"
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
::DEBUGGER__::SESSION.extend_feature session: Custom_Session, thread_client: Custom_ThreadClient, ui: Custom_UI_DAP
|
335
|
+
end
|
336
|
+
end
|
data/lib/debug/frame_info.rb
CHANGED
@@ -147,6 +147,15 @@ module DEBUGGER__
|
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
150
|
+
def iseq_parameters_info
|
151
|
+
case frame_type
|
152
|
+
when :block, :method
|
153
|
+
parameters_info
|
154
|
+
else
|
155
|
+
nil
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
150
159
|
def parameters_info
|
151
160
|
vars = iseq.parameters_symbols
|
152
161
|
vars.map{|var|
|
@@ -0,0 +1,27 @@
|
|
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
|
+
end
|
data/lib/debug/local.rb
CHANGED
@@ -13,23 +13,28 @@ module DEBUGGER__
|
|
13
13
|
false
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
session.intercept_trap_sigint_start prev_handler
|
24
|
-
end
|
16
|
+
def activate_sigint
|
17
|
+
prev_handler = trap(:SIGINT){
|
18
|
+
if SESSION.active?
|
19
|
+
ThreadClient.current.on_trap :SIGINT
|
20
|
+
end
|
21
|
+
}
|
22
|
+
SESSION.intercept_trap_sigint_start prev_handler
|
25
23
|
end
|
26
24
|
|
27
|
-
def
|
25
|
+
def deactivate_sigint
|
28
26
|
if SESSION.intercept_trap_sigint?
|
29
27
|
prev = SESSION.intercept_trap_sigint_end
|
30
28
|
trap(:SIGINT, prev)
|
31
29
|
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def activate session, on_fork: false
|
33
|
+
activate_sigint unless CONFIG[:no_sigint_hook]
|
34
|
+
end
|
32
35
|
|
36
|
+
def deactivate
|
37
|
+
deactivate_sigint
|
33
38
|
@console.deactivate
|
34
39
|
end
|
35
40
|
|
@@ -42,6 +47,7 @@ module DEBUGGER__
|
|
42
47
|
end
|
43
48
|
|
44
49
|
def quit n
|
50
|
+
yield
|
45
51
|
exit n
|
46
52
|
end
|
47
53
|
|
data/lib/debug/open.rb
CHANGED
File without changes
|
data/lib/debug/open_nonstop.rb
CHANGED
File without changes
|
data/lib/debug/prelude.rb
CHANGED
data/lib/debug/server.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'socket'
|
4
|
-
require 'etc'
|
5
4
|
require_relative 'config'
|
6
5
|
require_relative 'version'
|
7
6
|
|
@@ -22,6 +21,7 @@ module DEBUGGER__
|
|
22
21
|
|
23
22
|
class Terminate < StandardError; end
|
24
23
|
class GreetingError < StandardError; end
|
24
|
+
class RetryConnection < StandardError; end
|
25
25
|
|
26
26
|
def deactivate
|
27
27
|
@reader_thread.raise Terminate
|
@@ -78,6 +78,8 @@ module DEBUGGER__
|
|
78
78
|
next
|
79
79
|
rescue Terminate
|
80
80
|
raise # should catch at outer scope
|
81
|
+
rescue RetryConnection
|
82
|
+
next
|
81
83
|
rescue => e
|
82
84
|
DEBUGGER__.warn "ReaderThreadError: #{e}"
|
83
85
|
pp e.backtrace
|
@@ -128,8 +130,10 @@ module DEBUGGER__
|
|
128
130
|
def greeting
|
129
131
|
case g = @sock.gets
|
130
132
|
when /^info cookie:\s+(.*)$/
|
133
|
+
require 'etc'
|
134
|
+
|
131
135
|
check_cookie $1
|
132
|
-
@sock.puts "PID: #{Process.pid}, $0: #{$0}"
|
136
|
+
@sock.puts "PID: #{Process.pid}, $0: #{$0}, session_name: #{CONFIG[:session_name]}"
|
133
137
|
@sock.puts "debug #{VERSION} on #{RUBY_DESCRIPTION}"
|
134
138
|
@sock.puts "uname: #{Etc.uname.inspect}"
|
135
139
|
@sock.close
|
@@ -140,11 +144,14 @@ module DEBUGGER__
|
|
140
144
|
|
141
145
|
# TODO: protocol version
|
142
146
|
if v != VERSION
|
143
|
-
|
147
|
+
@sock.puts msg = "out DEBUGGER: Incompatible version (server:#{VERSION} and client:#{$1})"
|
148
|
+
raise GreetingError, msg
|
144
149
|
end
|
145
150
|
parse_option(params)
|
146
151
|
|
147
|
-
|
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}"
|
148
155
|
puts "DEBUGGER (client): Type `Ctrl-C` to enter the debug console." unless @need_pause_at_first
|
149
156
|
puts
|
150
157
|
|
@@ -157,16 +164,13 @@ module DEBUGGER__
|
|
157
164
|
@need_pause_at_first = false
|
158
165
|
dap_setup @sock.read($1.to_i)
|
159
166
|
|
160
|
-
when /^GET
|
167
|
+
when /^GET\s\/json\sHTTP\/1.1/, /^GET\s\/json\/version\sHTTP\/1.1/, /^GET\s\/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}\sHTTP\/1.1/
|
168
|
+
# The reason for not using @uuid here is @uuid is nil if users run debugger without `--open=chrome`.
|
169
|
+
|
161
170
|
require_relative 'server_cdp'
|
162
171
|
|
163
172
|
self.extend(UI_CDP)
|
164
|
-
|
165
|
-
@need_pause_at_first = false
|
166
|
-
CONFIG.set_config no_color: true
|
167
|
-
|
168
|
-
@ws_server = UI_CDP::WebSocketServer.new(@sock)
|
169
|
-
@ws_server.handshake
|
173
|
+
send_chrome_response g
|
170
174
|
else
|
171
175
|
raise GreetingError, "Unknown greeting message: #{g}"
|
172
176
|
end
|
@@ -174,17 +178,17 @@ module DEBUGGER__
|
|
174
178
|
|
175
179
|
def process
|
176
180
|
while true
|
177
|
-
DEBUGGER__.
|
178
|
-
|
179
|
-
DEBUGGER__.
|
181
|
+
DEBUGGER__.debug{ "sleep IO.select" }
|
182
|
+
_r = IO.select([@sock])
|
183
|
+
DEBUGGER__.debug{ "wakeup IO.select" }
|
180
184
|
|
181
185
|
line = @session.process_group.sync do
|
182
186
|
unless IO.select([@sock], nil, nil, 0)
|
183
|
-
DEBUGGER__.
|
187
|
+
DEBUGGER__.debug{ "UI_Server can not read" }
|
184
188
|
break :can_not_read
|
185
189
|
end
|
186
190
|
@sock.gets&.chomp.tap{|line|
|
187
|
-
DEBUGGER__.
|
191
|
+
DEBUGGER__.debug{ "UI_Server received: #{line}" }
|
188
192
|
}
|
189
193
|
end
|
190
194
|
|
@@ -340,12 +344,12 @@ module DEBUGGER__
|
|
340
344
|
if @repl
|
341
345
|
raise "not in subsession, but received: #{line.inspect}" unless @session.in_subsession?
|
342
346
|
line = "input #{Process.pid}"
|
343
|
-
DEBUGGER__.
|
347
|
+
DEBUGGER__.debug{ "send: #{line}" }
|
344
348
|
s.puts line
|
345
349
|
end
|
346
350
|
sleep 0.01 until @q_msg
|
347
351
|
@q_msg.pop.tap{|msg|
|
348
|
-
DEBUGGER__.
|
352
|
+
DEBUGGER__.debug{ "readline: #{msg.inspect}" }
|
349
353
|
}
|
350
354
|
end || 'continue')
|
351
355
|
|
@@ -361,7 +365,7 @@ module DEBUGGER__
|
|
361
365
|
Process.kill(TRAP_SIGNAL, Process.pid)
|
362
366
|
end
|
363
367
|
|
364
|
-
def quit n
|
368
|
+
def quit n, &_b
|
365
369
|
# ignore n
|
366
370
|
sock do |s|
|
367
371
|
s.puts "quit"
|
@@ -395,6 +399,7 @@ module DEBUGGER__
|
|
395
399
|
raise "Specify digits for port number"
|
396
400
|
end
|
397
401
|
end
|
402
|
+
@uuid = nil # for CDP
|
398
403
|
|
399
404
|
super()
|
400
405
|
end
|
@@ -402,14 +407,14 @@ module DEBUGGER__
|
|
402
407
|
def chrome_setup
|
403
408
|
require_relative 'server_cdp'
|
404
409
|
|
405
|
-
|
406
|
-
|
407
|
-
|
410
|
+
@uuid = SecureRandom.uuid
|
411
|
+
@chrome_pid = UI_CDP.setup_chrome(@local_addr.inspect_sockaddr, @uuid)
|
412
|
+
DEBUGGER__.warn <<~EOS
|
413
|
+
With Chrome browser, type the following URL in the address-bar:
|
408
414
|
|
409
|
-
|
415
|
+
devtools://devtools/bundled/inspector.html?v8only=true&panel=sources&noJavaScriptCompletion=true&ws=#{@local_addr.inspect_sockaddr}/#{@uuid}
|
410
416
|
|
411
|
-
|
412
|
-
end
|
417
|
+
EOS
|
413
418
|
end
|
414
419
|
|
415
420
|
def accept
|
@@ -434,7 +439,7 @@ module DEBUGGER__
|
|
434
439
|
#
|
435
440
|
EOS
|
436
441
|
|
437
|
-
case CONFIG[:
|
442
|
+
case CONFIG[:open]
|
438
443
|
when 'chrome'
|
439
444
|
chrome_setup
|
440
445
|
when 'vscode'
|
@@ -491,7 +496,7 @@ module DEBUGGER__
|
|
491
496
|
end
|
492
497
|
|
493
498
|
::DEBUGGER__.warn "Debugger can attach via UNIX domain socket (#{@sock_path})"
|
494
|
-
vscode_setup @sock_path if CONFIG[:
|
499
|
+
vscode_setup @sock_path if CONFIG[:open] == 'vscode'
|
495
500
|
|
496
501
|
begin
|
497
502
|
Socket.unix_server_loop @sock_path do |sock, client|
|