debug 1.5.0 → 1.6.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.
data/lib/debug/config.rb CHANGED
@@ -7,46 +7,50 @@ module DEBUGGER__
7
7
  ERROR: 2,
8
8
  WARN: 3,
9
9
  INFO: 4,
10
+ DEBUG: 5
10
11
  }.freeze
11
12
 
12
13
  CONFIG_SET = {
13
14
  # UI setting
14
- log_level: ['RUBY_DEBUG_LOG_LEVEL', "UI: Log level same as Logger (default: WARN)", :loglevel],
15
- show_src_lines: ['RUBY_DEBUG_SHOW_SRC_LINES', "UI: Show n lines source code on breakpoint (default: 10 lines)", :int],
16
- show_frames: ['RUBY_DEBUG_SHOW_FRAMES', "UI: Show n frames on breakpoint (default: 2 frames)", :int],
17
- use_short_path: ['RUBY_DEBUG_USE_SHORT_PATH', "UI: Show shorten PATH (like $(Gem)/foo.rb)", :bool],
18
- no_color: ['RUBY_DEBUG_NO_COLOR', "UI: Do not use colorize (default: false)", :bool],
19
- no_sigint_hook: ['RUBY_DEBUG_NO_SIGINT_HOOK', "UI: Do not suspend on SIGINT (default: false)", :bool],
20
- no_reline: ['RUBY_DEBUG_NO_RELINE', "UI: Do not use Reline library (default: false)", :bool],
15
+ log_level: ['RUBY_DEBUG_LOG_LEVEL', "UI: Log level same as Logger", :loglevel, "WARN"],
16
+ show_src_lines: ['RUBY_DEBUG_SHOW_SRC_LINES', "UI: Show n lines source code on breakpoint", :int, "10"],
17
+ show_frames: ['RUBY_DEBUG_SHOW_FRAMES', "UI: Show n frames on breakpoint", :int, "2"],
18
+ use_short_path: ['RUBY_DEBUG_USE_SHORT_PATH', "UI: Show shorten PATH (like $(Gem)/foo.rb)", :bool, "false"],
19
+ no_color: ['RUBY_DEBUG_NO_COLOR', "UI: Do not use colorize", :bool, "false"],
20
+ no_sigint_hook: ['RUBY_DEBUG_NO_SIGINT_HOOK', "UI: Do not suspend on SIGINT", :bool, "false"],
21
+ no_reline: ['RUBY_DEBUG_NO_RELINE', "UI: Do not use Reline library", :bool, "false"],
22
+ no_hint: ['RUBY_DEBUG_NO_HINT', "UI: Do not show the hint on the REPL", :bool, "false"],
21
23
 
22
24
  # control setting
23
- skip_path: ['RUBY_DEBUG_SKIP_PATH', "CONTROL: Skip showing/entering frames for given paths (default: [])", :path],
24
- skip_nosrc: ['RUBY_DEBUG_SKIP_NOSRC', "CONTROL: Skip on no source code lines (default: false)", :bool],
25
- keep_alloc_site:['RUBY_DEBUG_KEEP_ALLOC_SITE',"CONTROL: Keep allocation site and p, pp shows it (default: false)", :bool],
26
- postmortem: ['RUBY_DEBUG_POSTMORTEM', "CONTROL: Enable postmortem debug (default: false)", :bool],
27
- fork_mode: ['RUBY_DEBUG_FORK_MODE', "CONTROL: Control which process activates a debugger after fork (both/parent/child) (default: both)", :forkmode],
28
- sigdump_sig: ['RUBY_DEBUG_SIGDUMP_SIG', "CONTROL: Sigdump signal (default: disabled)"],
25
+ skip_path: ['RUBY_DEBUG_SKIP_PATH', "CONTROL: Skip showing/entering frames for given paths", :path],
26
+ skip_nosrc: ['RUBY_DEBUG_SKIP_NOSRC', "CONTROL: Skip on no source code lines", :bool, "false"],
27
+ keep_alloc_site:['RUBY_DEBUG_KEEP_ALLOC_SITE',"CONTROL: Keep allocation site and p, pp shows it", :bool, "false"],
28
+ postmortem: ['RUBY_DEBUG_POSTMORTEM', "CONTROL: Enable postmortem debug", :bool, "false"],
29
+ fork_mode: ['RUBY_DEBUG_FORK_MODE', "CONTROL: Control which process activates a debugger after fork (both/parent/child)", :forkmode, "both"],
30
+ sigdump_sig: ['RUBY_DEBUG_SIGDUMP_SIG', "CONTROL: Sigdump signal", :bool, "false"],
29
31
 
30
32
  # boot setting
31
- nonstop: ['RUBY_DEBUG_NONSTOP', "BOOT: Nonstop mode", :bool],
32
- stop_at_load: ['RUBY_DEBUG_STOP_AT_LOAD',"BOOT: Stop at just loading location", :bool],
33
+ nonstop: ['RUBY_DEBUG_NONSTOP', "BOOT: Nonstop mode", :bool, "false"],
34
+ stop_at_load: ['RUBY_DEBUG_STOP_AT_LOAD',"BOOT: Stop at just loading location", :bool, "false"],
33
35
  init_script: ['RUBY_DEBUG_INIT_SCRIPT', "BOOT: debug command script path loaded at first stop"],
34
36
  commands: ['RUBY_DEBUG_COMMANDS', "BOOT: debug commands invoked at first stop. commands should be separated by ';;'"],
35
- no_rc: ['RUBY_DEBUG_NO_RC', "BOOT: ignore loading ~/.rdbgrc(.rb)", :bool],
36
- history_file: ['RUBY_DEBUG_HISTORY_FILE',"BOOT: history file (default: ~/.rdbg_history)"],
37
- save_history: ['RUBY_DEBUG_SAVE_HISTORY',"BOOT: maximum save history lines (default: 10,000)"],
37
+ no_rc: ['RUBY_DEBUG_NO_RC', "BOOT: ignore loading ~/.rdbgrc(.rb)", :bool, "false"],
38
+ history_file: ['RUBY_DEBUG_HISTORY_FILE',"BOOT: history file", :string, "~/.rdbg_history"],
39
+ save_history: ['RUBY_DEBUG_SAVE_HISTORY',"BOOT: maximum save history lines", :int, "10000"],
38
40
 
39
41
  # remote setting
40
42
  port: ['RUBY_DEBUG_PORT', "REMOTE: TCP/IP remote debugging: port"],
41
- host: ['RUBY_DEBUG_HOST', "REMOTE: TCP/IP remote debugging: host (localhost if not given)"],
43
+ host: ['RUBY_DEBUG_HOST', "REMOTE: TCP/IP remote debugging: host", :string, "127.0.0.1"],
42
44
  sock_path: ['RUBY_DEBUG_SOCK_PATH', "REMOTE: UNIX Domain Socket remote debugging: socket path"],
43
45
  sock_dir: ['RUBY_DEBUG_SOCK_DIR', "REMOTE: UNIX Domain Socket remote debugging: socket directory"],
46
+ local_fs_map: ['RUBY_DEBUG_LOCAL_FS_MAP', "REMOTE: Specify local fs map", :path_map],
47
+ skip_bp: ['RUBY_DEBUG_SKIP_BP', "REMOTE: Skip breakpoints if no clients are attached", :bool, 'false'],
44
48
  cookie: ['RUBY_DEBUG_COOKIE', "REMOTE: Cookie for negotiation"],
45
49
  open_frontend: ['RUBY_DEBUG_OPEN_FRONTEND',"REMOTE: frontend used by open command (vscode, chrome, default: rdbg)."],
46
50
  chrome_path: ['RUBY_DEBUG_CHROME_PATH', "REMOTE: Platform dependent path of Chrome (For more information, See [here](https://github.com/ruby/debug/pull/334/files#diff-5fc3d0a901379a95bc111b86cf0090b03f857edfd0b99a0c1537e26735698453R55-R64))"],
47
51
 
48
52
  # obsolete
49
- parent_on_fork: ['RUBY_DEBUG_PARENT_ON_FORK', "OBSOLETE: Keep debugging parent process on fork (default: false)", :bool],
53
+ parent_on_fork: ['RUBY_DEBUG_PARENT_ON_FORK', "OBSOLETE: Keep debugging parent process on fork", :bool, "false"],
50
54
  }.freeze
51
55
 
52
56
  CONFIG_MAP = CONFIG_SET.map{|k, (ev, _)| [k, ev]}.to_h.freeze
@@ -59,11 +63,23 @@ module DEBUGGER__
59
63
  end
60
64
 
61
65
  def initialize argv
66
+ @skip_all = false
67
+
62
68
  if self.class.config
63
69
  raise 'Can not make multiple configurations in one process'
64
70
  end
65
71
 
66
- update self.class.parse_argv(argv)
72
+ config = self.class.parse_argv(argv)
73
+
74
+ # apply defaults
75
+ CONFIG_SET.each do |k, config_detail|
76
+ unless config.key?(k)
77
+ default_value = config_detail[3]
78
+ config[k] = parse_config_value(k, default_value)
79
+ end
80
+ end
81
+
82
+ update config
67
83
  end
68
84
 
69
85
  def inspect
@@ -78,6 +94,14 @@ module DEBUGGER__
78
94
  set_config(key => val)
79
95
  end
80
96
 
97
+ def skip_all
98
+ @skip_all = true
99
+ end
100
+
101
+ def skip?
102
+ @skip_all
103
+ end
104
+
81
105
  def set_config(**kw)
82
106
  conf = config.dup
83
107
  kw.each{|k, v|
@@ -114,11 +138,13 @@ module DEBUGGER__
114
138
  self.class.instance_variable_set(:@config, conf.freeze)
115
139
 
116
140
  # Post process
117
- if_updated old_conf, conf, :keep_alloc_site do |_, new|
141
+ if_updated old_conf, conf, :keep_alloc_site do |old, new|
118
142
  if new
119
143
  require 'objspace'
120
144
  ObjectSpace.trace_object_allocations_start
121
- else
145
+ end
146
+
147
+ if old && !new
122
148
  ObjectSpace.trace_object_allocations_stop
123
149
  end
124
150
  end
@@ -215,6 +241,8 @@ module DEBUGGER__
215
241
  e
216
242
  end
217
243
  }
244
+ when :path_map
245
+ valstr.split(',').map{|e| e.split(':')}
218
246
  else
219
247
  valstr
220
248
  end
@@ -223,6 +251,7 @@ module DEBUGGER__
223
251
  def self.parse_argv argv
224
252
  config = {
225
253
  mode: :start,
254
+ no_color: (nc = ENV['NO_COLOR']) && !nc.empty?,
226
255
  }
227
256
  CONFIG_MAP.each{|key, evname|
228
257
  if val = ENV[evname]
@@ -361,6 +390,8 @@ module DEBUGGER__
361
390
  case CONFIG_SET[key][2]
362
391
  when :path
363
392
  valstr = config[key].map{|e| e.kind_of?(Regexp) ? e.inspect : e}.join(':')
393
+ when :path_map
394
+ valstr = config[key].map{|e| e.join(':')}.join(',')
364
395
  else
365
396
  valstr = config[key].to_s
366
397
  end
@@ -428,7 +459,7 @@ module DEBUGGER__
428
459
  end
429
460
 
430
461
  def self.create_unix_domain_socket_name_prefix(base_dir = unix_domain_socket_dir)
431
- user = ENV['USER'] || 'ruby-debug'
462
+ user = ENV['USER'] || 'UnknownUser'
432
463
  File.join(base_dir, "ruby-debug-#{user}")
433
464
  end
434
465
 
data/lib/debug/console.rb CHANGED
@@ -98,7 +98,7 @@ module DEBUGGER__
98
98
  when :ruby
99
99
  colorize_code(buff.chomp)
100
100
  end
101
- end
101
+ end unless CONFIG[:no_hint]
102
102
 
103
103
  yield
104
104
 
@@ -174,7 +174,13 @@ module DEBUGGER__
174
174
  end
175
175
 
176
176
  def history_file
177
- CONFIG[:history_file] || File.expand_path("~/.rdbg_history")
177
+ history_file = CONFIG[:history_file]
178
+
179
+ if !history_file.empty?
180
+ File.expand_path(history_file)
181
+ else
182
+ history_file
183
+ end
178
184
  end
179
185
 
180
186
  FH = "# Today's OMIKUJI: "
@@ -202,7 +208,7 @@ module DEBUGGER__
202
208
  if history && @init_history_lines
203
209
  added_records = history.to_a[@init_history_lines .. -1]
204
210
  path = history_file
205
- max = CONFIG[:save_history] || 10_000
211
+ max = CONFIG[:save_history]
206
212
 
207
213
  if !added_records.empty? && !path.empty?
208
214
  orig_records = read_history_file
@@ -27,8 +27,8 @@ module DEBUGGER__
27
27
  location.absolute_path
28
28
  end
29
29
 
30
- def pretty_path
31
- return '#<none>' unless path = self.path
30
+ def self.pretty_path path
31
+ return '#<none>' unless path
32
32
  use_short_path = CONFIG[:use_short_path]
33
33
 
34
34
  case
@@ -45,15 +45,18 @@ module DEBUGGER__
45
45
  end
46
46
  end
47
47
 
48
+ def pretty_path
49
+ FrameInfo.pretty_path path
50
+ end
51
+
48
52
  def name
49
53
  # p frame_type: frame_type, self: self
50
54
  case frame_type
51
55
  when :block
52
- level, block_loc, _args = block_identifier
56
+ level, block_loc = block_identifier
53
57
  "block in #{block_loc}#{level}"
54
58
  when :method
55
- ci, _args = method_identifier
56
- "#{ci}"
59
+ method_identifier
57
60
  when :c
58
61
  c_identifier
59
62
  when :other
@@ -83,16 +86,13 @@ module DEBUGGER__
83
86
 
84
87
  def block_identifier
85
88
  return unless frame_type == :block
86
- args = parameters_info
87
89
  _, level, block_loc = location.label.match(BLOCK_LABL_REGEXP).to_a
88
- [level || "", block_loc, args]
90
+ [level || "", block_loc]
89
91
  end
90
92
 
91
93
  def method_identifier
92
94
  return unless frame_type == :method
93
- args = parameters_info
94
- ci = "#{klass_sig}#{callee}"
95
- [ci, args]
95
+ "#{klass_sig}#{callee}"
96
96
  end
97
97
 
98
98
  def c_identifier
@@ -106,7 +106,11 @@ module DEBUGGER__
106
106
  end
107
107
 
108
108
  def callee
109
- self._callee ||= self.binding&.eval('__callee__')
109
+ self._callee ||= begin
110
+ self.binding&.eval('__callee__')
111
+ rescue NameError # BasicObject
112
+ nil
113
+ end
110
114
  end
111
115
 
112
116
  def return_str
@@ -115,6 +119,11 @@ module DEBUGGER__
115
119
  end
116
120
  end
117
121
 
122
+ def matchable_location
123
+ # realpath can sometimes be nil so we can't use it here
124
+ "#{path}:#{location.lineno}"
125
+ end
126
+
118
127
  def location_str
119
128
  "#{pretty_path}:#{location.lineno}"
120
129
  end
@@ -138,18 +147,6 @@ module DEBUGGER__
138
147
  end
139
148
  end
140
149
 
141
- private
142
-
143
- def get_singleton_class obj
144
- obj.singleton_class # TODO: don't use it
145
- rescue TypeError
146
- nil
147
- end
148
-
149
- private def local_variable_get var
150
- local_variables[var]
151
- end
152
-
153
150
  def parameters_info
154
151
  vars = iseq.parameters_symbols
155
152
  vars.map{|var|
@@ -161,7 +158,17 @@ module DEBUGGER__
161
158
  }.compact
162
159
  end
163
160
 
164
- def klass_sig
161
+ private def get_singleton_class obj
162
+ obj.singleton_class # TODO: don't use it
163
+ rescue TypeError
164
+ nil
165
+ end
166
+
167
+ private def local_variable_get var
168
+ local_variables[var]
169
+ end
170
+
171
+ private def klass_sig
165
172
  if self.class == get_singleton_class(self.self)
166
173
  "#{self.self}."
167
174
  else
data/lib/debug/server.rb CHANGED
@@ -49,6 +49,7 @@ module DEBUGGER__
49
49
  accept do |server, already_connected: false|
50
50
  DEBUGGER__.warn "Connected."
51
51
  greeting_done = false
52
+ @need_pause_at_first = true
52
53
 
53
54
  @accept_m.synchronize{
54
55
  @sock = server
@@ -68,7 +69,7 @@ module DEBUGGER__
68
69
  } unless already_connected
69
70
 
70
71
  setup_interrupt do
71
- pause unless already_connected
72
+ pause if !already_connected && @need_pause_at_first
72
73
  process
73
74
  end
74
75
 
@@ -106,6 +107,24 @@ module DEBUGGER__
106
107
  end
107
108
  end
108
109
 
110
+ def parse_option params
111
+ case params.strip
112
+ when /width:\s+(\d+)/
113
+ @width = $1.to_i
114
+ parse_option $~.post_match
115
+ when /cookie:\s+(\S+)/
116
+ check_cookie $1 if $1 != '-'
117
+ parse_option $~.post_match
118
+ when /nonstop: (true|false)/
119
+ @need_pause_at_first = false if $1 == 'true'
120
+ parse_option $~.post_match
121
+ when /(.+):(.+)/
122
+ raise GreetingError, "Unkown option: #{params}"
123
+ else
124
+ # OK
125
+ end
126
+ end
127
+
109
128
  def greeting
110
129
  case g = @sock.gets
111
130
  when /^info cookie:\s+(.*)$/
@@ -116,16 +135,18 @@ module DEBUGGER__
116
135
  @sock.close
117
136
  raise GreetingError, "HEAD request"
118
137
 
119
- when /^version:\s+(.+)\s+width: (\d+) cookie:\s+(.*)$/
120
- v, w, c = $1, $2, $3
138
+ when /^version:\s+(\S+)\s+(.+)$/
139
+ v, params = $1, $2
140
+
121
141
  # TODO: protocol version
122
142
  if v != VERSION
123
143
  raise GreetingError, "Incompatible version (server:#{VERSION} and client:#{$1})"
124
144
  end
145
+ parse_option(params)
125
146
 
126
- check_cookie c
127
-
128
- @width = w.to_i
147
+ puts "DEBUGGER (client): Connected. PID:#{Process.pid}, $0:#{$0}"
148
+ puts "DEBUGGER (client): Type `Ctrl-C` to enter the debug console." unless @need_pause_at_first
149
+ puts
129
150
 
130
151
  when /^Content-Length: (\d+)/
131
152
  require_relative 'server_dap'
@@ -133,12 +154,15 @@ module DEBUGGER__
133
154
  raise unless @sock.read(2) == "\r\n"
134
155
  self.extend(UI_DAP)
135
156
  @repl = false
157
+ @need_pause_at_first = false
136
158
  dap_setup @sock.read($1.to_i)
159
+
137
160
  when /^GET \/.* HTTP\/1.1/
138
161
  require_relative 'server_cdp'
139
162
 
140
163
  self.extend(UI_CDP)
141
164
  @repl = false
165
+ @need_pause_at_first = false
142
166
  CONFIG.set_config no_color: true
143
167
 
144
168
  @ws_server = UI_CDP::WebSocketServer.new(@sock)
@@ -164,6 +188,7 @@ module DEBUGGER__
164
188
  }
165
189
  end
166
190
 
191
+ return unless line
167
192
  next if line == :can_not_read
168
193
 
169
194
  case line
@@ -187,7 +212,7 @@ module DEBUGGER__
187
212
  raise "pid:#{Process.pid} but get #{line}"
188
213
  end
189
214
  else
190
- STDERR.puts "unsupported: #{line}"
215
+ STDERR.puts "unsupported: #{line.inspect}"
191
216
  exit!
192
217
  end
193
218
  end
@@ -309,7 +334,9 @@ module DEBUGGER__
309
334
  end
310
335
 
311
336
  def readline prompt
312
- input = (sock do |s|
337
+ input = (sock(skip: CONFIG[:skip_bp]) do |s|
338
+ next unless s
339
+
313
340
  if @repl
314
341
  raise "not in subsession, but received: #{line.inspect}" unless @session.in_subsession?
315
342
  line = "input #{Process.pid}"
@@ -353,8 +380,8 @@ module DEBUGGER__
353
380
 
354
381
  class UI_TcpServer < UI_ServerBase
355
382
  def initialize host: nil, port: nil
356
- @addr = nil
357
- @host = host || CONFIG[:host] || '127.0.0.1'
383
+ @local_addr = nil
384
+ @host = host || CONFIG[:host]
358
385
  @port_save_file = nil
359
386
  @port = begin
360
387
  port_str = (port && port.to_s) || CONFIG[:port] || raise("Specify listening port by RUBY_DEBUG_PORT environment variable.")
@@ -375,12 +402,12 @@ module DEBUGGER__
375
402
  def chrome_setup
376
403
  require_relative 'server_cdp'
377
404
 
378
- unless @chrome_pid = UI_CDP.setup_chrome(@addr)
405
+ unless @chrome_pid = UI_CDP.setup_chrome(@local_addr.inspect_sockaddr)
379
406
  DEBUGGER__.warn <<~EOS
380
407
  With Chrome browser, type the following URL in the address-bar:
381
408
 
382
- devtools://devtools/bundled/inspector.html?v8only=true&panel=sources&ws=#{@addr}/#{SecureRandom.uuid}
383
-
409
+ devtools://devtools/bundled/inspector.html?v8only=true&panel=sources&ws=#{@local_addr.inspect_sockaddr}/#{SecureRandom.uuid}
410
+
384
411
  EOS
385
412
  end
386
413
  end
@@ -391,9 +418,9 @@ module DEBUGGER__
391
418
 
392
419
  begin
393
420
  Socket.tcp_server_sockets @host, @port do |socks|
394
- @addr = socks[0].local_address.inspect_sockaddr # Change this part if `socks` are multiple.
421
+ @local_addr = socks.first.local_address # Change this part if `socks` are multiple.
395
422
  rdbg = File.expand_path('../../exe/rdbg', __dir__)
396
- DEBUGGER__.warn "Debugger can attach via TCP/IP (#{@addr})"
423
+ DEBUGGER__.warn "Debugger can attach via TCP/IP (#{@local_addr.inspect_sockaddr})"
397
424
 
398
425
  if @port_save_file
399
426
  File.write(@port_save_file, "#{socks[0].local_address.ip_port.to_s}\n")
@@ -403,7 +430,7 @@ module DEBUGGER__
403
430
  DEBUGGER__.info <<~EOS
404
431
  With rdbg, use the following command line:
405
432
  #
406
- # #{rdbg} --attach #{@addr.split(':').join(' ')}
433
+ # #{rdbg} --attach #{@local_addr.ip_address} #{@local_addr.ip_port}
407
434
  #
408
435
  EOS
409
436
 
@@ -411,7 +438,7 @@ module DEBUGGER__
411
438
  when 'chrome'
412
439
  chrome_setup
413
440
  when 'vscode'
414
- vscode_setup @addr
441
+ vscode_setup @local_addr.inspect_sockaddr
415
442
  end
416
443
 
417
444
  Socket.accept_loop(socks) do |sock, client|
@@ -346,7 +346,7 @@ module DEBUGGER__
346
346
  send_event 'Runtime.executionContextCreated',
347
347
  context: {
348
348
  id: SecureRandom.hex(16),
349
- origin: "http://#{@addr}",
349
+ origin: "http://#{@local_addr.inspect_sockaddr}",
350
350
  name: ''
351
351
  }
352
352
  when 'Runtime.getIsolateId'
@@ -572,13 +572,13 @@ module DEBUGGER__
572
572
  def process_protocol_request req
573
573
  case req['method']
574
574
  when 'Debugger.stepOver', 'Debugger.stepInto', 'Debugger.stepOut', 'Debugger.resume', 'Debugger.enable'
575
- @tc << [:cdp, :backtrace, req]
575
+ request_tc [:cdp, :backtrace, req]
576
576
  when 'Debugger.evaluateOnCallFrame'
577
577
  frame_id = req.dig('params', 'callFrameId')
578
578
  group = req.dig('params', 'objectGroup')
579
579
  if fid = @frame_map[frame_id]
580
580
  expr = req.dig('params', 'expression')
581
- @tc << [:cdp, :evaluate, req, fid, expr, group]
581
+ request_tc [:cdp, :evaluate, req, fid, expr, group]
582
582
  else
583
583
  fail_response req,
584
584
  code: INVALID_PARAMS,
@@ -591,9 +591,9 @@ module DEBUGGER__
591
591
  when 'local'
592
592
  frame_id = ref[1]
593
593
  fid = @frame_map[frame_id]
594
- @tc << [:cdp, :scope, req, fid]
594
+ request_tc [:cdp, :scope, req, fid]
595
595
  when 'properties'
596
- @tc << [:cdp, :properties, req, oid]
596
+ request_tc [:cdp, :properties, req, oid]
597
597
  when 'script', 'global'
598
598
  # TODO: Support script and global types
599
599
  @ui.respond req, result: []