ed-precompiled_debug 1.11.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.
@@ -0,0 +1,191 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DEBUGGER__
4
+ FrameInfo = Struct.new(:location, :self, :binding, :iseq, :class, :frame_depth,
5
+ :has_return_value, :return_value,
6
+ :has_raised_exception, :raised_exception,
7
+ :show_line,
8
+ :_local_variables, :_callee, # for recorder
9
+ :dupped_binding,
10
+ )
11
+
12
+ # extend FrameInfo with debug.so
13
+ begin
14
+ ruby_version = /(\d+\.\d+)/.match(::RUBY_VERSION)
15
+ require "#{ruby_version}/debug/debug.so"
16
+ rescue LoadError
17
+ require 'debug/debug.so'
18
+ end
19
+
20
+ class FrameInfo
21
+ HOME = ENV['HOME'] ? (ENV['HOME'] + '/') : nil
22
+
23
+ def path
24
+ location.path
25
+ end
26
+
27
+ def realpath
28
+ location.absolute_path
29
+ end
30
+
31
+ def self.pretty_path path
32
+ return '#<none>' unless path
33
+ use_short_path = CONFIG[:use_short_path]
34
+
35
+ case
36
+ when use_short_path && path.start_with?(dir = RbConfig::CONFIG["rubylibdir"] + '/')
37
+ path.sub(dir, '$(rubylibdir)/')
38
+ when use_short_path && Gem.path.any? do |gp|
39
+ path.start_with?(dir = gp + '/gems/')
40
+ end
41
+ path.sub(dir, '$(Gem)/')
42
+ when HOME && path.start_with?(HOME)
43
+ path.sub(HOME, '~/')
44
+ else
45
+ path
46
+ end
47
+ end
48
+
49
+ def pretty_path
50
+ FrameInfo.pretty_path path
51
+ end
52
+
53
+ def name
54
+ # p frame_type: frame_type, self: self
55
+ case frame_type
56
+ when :block
57
+ level, block_loc = block_identifier
58
+ "block in #{block_loc}#{level}"
59
+ when :method
60
+ method_identifier
61
+ when :c
62
+ c_identifier
63
+ when :other
64
+ other_identifier
65
+ end
66
+ end
67
+
68
+ def file_lines
69
+ SESSION.source(self.iseq)
70
+ end
71
+
72
+ def frame_type
73
+ if self.local_variables && iseq
74
+ if iseq.type == :block
75
+ :block
76
+ elsif callee
77
+ :method
78
+ else
79
+ :other
80
+ end
81
+ else
82
+ :c
83
+ end
84
+ end
85
+
86
+ BLOCK_LABL_REGEXP = /\Ablock( \(\d+ levels\))* in (.+)\z/
87
+
88
+ def block_identifier
89
+ return unless frame_type == :block
90
+ re_match = location.label.match(BLOCK_LABL_REGEXP)
91
+ _, level, block_loc = re_match ? re_match.to_a : [nil, nil, location.label]
92
+
93
+ [level || "", block_loc]
94
+ end
95
+
96
+ def method_identifier
97
+ return unless frame_type == :method
98
+ "#{klass_sig}#{callee}"
99
+ end
100
+
101
+ def c_identifier
102
+ return unless frame_type == :c
103
+ "[C] #{klass_sig}#{location.base_label}"
104
+ end
105
+
106
+ def other_identifier
107
+ return unless frame_type == :other
108
+ location.label
109
+ end
110
+
111
+ def callee
112
+ self._callee ||= begin
113
+ self.binding&.eval('__callee__')
114
+ rescue NameError # BasicObject
115
+ nil
116
+ end
117
+ end
118
+
119
+ def return_str
120
+ if self.binding && iseq && has_return_value
121
+ DEBUGGER__.safe_inspect(return_value, short: true)
122
+ end
123
+ end
124
+
125
+ def matchable_location
126
+ # realpath can sometimes be nil so we can't use it here
127
+ "#{path}:#{location.lineno}"
128
+ end
129
+
130
+ def location_str
131
+ "#{pretty_path}:#{location.lineno}"
132
+ end
133
+
134
+ def eval_binding
135
+ if b = self.dupped_binding
136
+ b
137
+ else
138
+ b = self.binding || TOPLEVEL_BINDING
139
+ self.dupped_binding = b.dup
140
+ end
141
+ end
142
+
143
+ def local_variables
144
+ if lvars = self._local_variables
145
+ lvars
146
+ elsif b = self.binding
147
+ b.local_variables.map{|var|
148
+ [var, b.local_variable_get(var)]
149
+ }.to_h
150
+ end
151
+ end
152
+
153
+ def iseq_parameters_info
154
+ case frame_type
155
+ when :block, :method
156
+ parameters_info
157
+ else
158
+ nil
159
+ end
160
+ end
161
+
162
+ def parameters_info
163
+ vars = iseq.parameters_symbols
164
+ vars.map{|var|
165
+ begin
166
+ { name: var, value: DEBUGGER__.safe_inspect(local_variable_get(var), short: true) }
167
+ rescue NameError, TypeError
168
+ nil
169
+ end
170
+ }.compact
171
+ end
172
+
173
+ private def get_singleton_class obj
174
+ obj.singleton_class # TODO: don't use it
175
+ rescue TypeError
176
+ nil
177
+ end
178
+
179
+ private def local_variable_get var
180
+ local_variables[var]
181
+ end
182
+
183
+ private def klass_sig
184
+ if self.class == get_singleton_class(self.self)
185
+ "#{self.self}."
186
+ else
187
+ "#{self.class}#"
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,37 @@
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
+
28
+ class Session
29
+ def deactivate_irb_integration
30
+ Reline.completion_proc = nil
31
+ Reline.output_modifier_proc = nil
32
+ Reline.autocompletion = false
33
+ Reline.dig_perfect_match_proc = nil
34
+ reset_ui UI_LocalConsole.new
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,115 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'io/console/size'
4
+ require_relative 'console'
5
+
6
+ module DEBUGGER__
7
+ class UI_LocalConsole < UI_Base
8
+ def initialize
9
+ @console = Console.new
10
+ end
11
+
12
+ def remote?
13
+ false
14
+ end
15
+
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
23
+ end
24
+
25
+ def deactivate_sigint
26
+ if SESSION.intercept_trap_sigint?
27
+ prev = SESSION.intercept_trap_sigint_end
28
+ trap(:SIGINT, prev)
29
+ end
30
+ end
31
+
32
+ def activate session, on_fork: false
33
+ activate_sigint unless CONFIG[:no_sigint_hook]
34
+ end
35
+
36
+ def deactivate
37
+ deactivate_sigint
38
+ @console.deactivate
39
+ end
40
+
41
+ def width
42
+ if (w = IO.console_size[1]) == 0 # for tests PTY
43
+ 80
44
+ else
45
+ w
46
+ end
47
+ end
48
+
49
+ def quit n
50
+ yield
51
+ exit n
52
+ end
53
+
54
+ def ask prompt
55
+ setup_interrupt do
56
+ print prompt
57
+ ($stdin.gets || '').strip
58
+ end
59
+ end
60
+
61
+ def puts str = nil
62
+ case str
63
+ when Array
64
+ str.each{|line|
65
+ $stdout.puts line.chomp
66
+ }
67
+ when String
68
+ str.each_line{|line|
69
+ $stdout.puts line.chomp
70
+ }
71
+ when nil
72
+ $stdout.puts
73
+ end
74
+ end
75
+
76
+ def readline prompt = '(rdbg)'
77
+ setup_interrupt do
78
+ (@console.readline(prompt) || 'quit').strip
79
+ end
80
+ end
81
+
82
+ def setup_interrupt
83
+ SESSION.intercept_trap_sigint false do
84
+ current_thread = Thread.current # should be session_server thread
85
+
86
+ prev_handler = trap(:INT){
87
+ current_thread.raise Interrupt
88
+ }
89
+
90
+ yield
91
+ ensure
92
+ trap(:INT, prev_handler)
93
+ end
94
+ end
95
+
96
+ def after_fork_parent
97
+ parent_pid = Process.pid
98
+
99
+ at_exit{
100
+ SESSION.intercept_trap_sigint_end
101
+ trap(:SIGINT, :IGNORE)
102
+
103
+ if Process.pid == parent_pid
104
+ # only check child process from its parent
105
+ begin
106
+ # wait for all child processes to keep terminal
107
+ Process.waitpid
108
+ rescue Errno::ESRCH, Errno::ECHILD
109
+ end
110
+ end
111
+ }
112
+ end
113
+ end
114
+ end
115
+
data/lib/debug/open.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Open the door for the debugger to connect.
4
+ # Users can connect to debuggee program with "rdbg --attach" option.
5
+ #
6
+ # If RUBY_DEBUG_PORT envval is provided (digits), open TCP/IP port.
7
+ # Otherwise, UNIX domain socket is used.
8
+ #
9
+
10
+ require_relative 'session'
11
+ return unless defined?(DEBUGGER__)
12
+
13
+ DEBUGGER__.open
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Open the door for the debugger to connect.
4
+ # Unlike debug/open, it does not stop at the beginning of the program.
5
+ # Users can connect to debuggee program with "rdbg --attach" option or
6
+ # VSCode attach type.
7
+ #
8
+ # If RUBY_DEBUG_PORT envval is provided (digits), open TCP/IP port.
9
+ # Otherwise, UNIX domain socket is used.
10
+ #
11
+
12
+ require_relative 'session'
13
+ return unless defined?(DEBUGGER__)
14
+
15
+ DEBUGGER__.open(nonstop: true)
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ return if ENV['RUBY_DEBUG_ENABLE'] == '0'
4
+ return if defined?(::DEBUGGER__::Session)
5
+
6
+ # Put the following line in your login script (e.g. ~/.bash_profile) with modified path:
7
+ #
8
+ # export RUBYOPT="-r /path/to/debug/prelude ${RUBYOPT}"
9
+ #
10
+ module Kernel
11
+ def debugger(*a, up_level: 0, **kw)
12
+ begin
13
+ require_relative 'version'
14
+ cur_version = ::DEBUGGER__::VERSION
15
+ require_relative 'frame_info'
16
+
17
+ if !defined?(::DEBUGGER__::SO_VERSION) || ::DEBUGGER__::VERSION != ::DEBUGGER__::SO_VERSION
18
+ ::Object.send(:remove_const, :DEBUGGER__)
19
+ raise LoadError
20
+ end
21
+ require_relative 'session'
22
+ up_level += 1
23
+ rescue LoadError
24
+ $LOADED_FEATURES.delete_if{|e|
25
+ e.start_with?(__dir__) || e.end_with?('debug/debug.so')
26
+ }
27
+ require 'debug/session'
28
+ require 'debug/version'
29
+ ::DEBUGGER__.info "Can not activate debug #{cur_version} specified by debug/prelude.rb. Activate debug #{DEBUGGER__::VERSION} instead."
30
+ up_level += 1
31
+ end
32
+
33
+ ::DEBUGGER__::start no_sigint_hook: true, nonstop: true
34
+
35
+ begin
36
+ debugger(*a, up_level: up_level, **kw)
37
+ self
38
+ rescue ArgumentError # for 1.2.4 and earlier
39
+ debugger(*a, **kw)
40
+ self
41
+ end
42
+ end
43
+
44
+ alias bb debugger if ENV['RUBY_DEBUG_BB']
45
+ end
46
+
47
+ class Binding
48
+ alias break debugger
49
+ alias b debugger
50
+ end