Skip to content

Commit

Permalink
Use flag instead of caller for debug's binding.irb check (#947)
Browse files Browse the repository at this point in the history
  • Loading branch information
st0012 authored May 4, 2024
1 parent c8bba9f commit 4a4d7a4
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 18 deletions.
7 changes: 5 additions & 2 deletions lib/irb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -931,8 +931,11 @@ class Irb
# The lexer used by this irb session
attr_accessor :scanner

attr_reader :from_binding

# Creates a new irb session
def initialize(workspace = nil, input_method = nil)
def initialize(workspace = nil, input_method = nil, from_binding: false)
@from_binding = from_binding
@context = Context.new(self, workspace, input_method)
@context.workspace.load_helper_methods_to_main
@signal_status = :IN_IRB
Expand Down Expand Up @@ -1596,7 +1599,7 @@ def irb(show_code: true)
else
# If we're not in a debugger session, create a new IRB instance with the current
# workspace
binding_irb = IRB::Irb.new(workspace)
binding_irb = IRB::Irb.new(workspace, from_binding: true)
binding_irb.context.irb_path = irb_path
binding_irb.run(IRB.conf)
binding_irb.debug_break
Expand Down
17 changes: 1 addition & 16 deletions lib/irb/command/debug.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ class Debug < Base
category "Debugging"
description "Start the debugger of debug.gem."

BINDING_IRB_FRAME_REGEXPS = [
'<internal:prelude>',
binding.method(:irb).source_location.first,
].map { |file| /\A#{Regexp.escape(file)}:\d+:in (`|'Binding#)irb'\z/ }

def execute(_arg)
execute_debug_command
end
Expand All @@ -36,7 +31,7 @@ def execute_debug_command(pre_cmds: nil, do_cmds: nil)
# 3. Insert a debug breakpoint at `Irb#debug_break` with the intended command.
# 4. Exit the current Irb#run call via `throw :IRB_EXIT`.
# 5. `Irb#debug_break` will be called and trigger the breakpoint, which will run the intended command.
unless binding_irb?
unless irb_context.from_binding?
puts "Debugging commands are only available when IRB is started with binding.irb"
return
end
Expand All @@ -60,16 +55,6 @@ def execute_debug_command(pre_cmds: nil, do_cmds: nil)
throw :IRB_EXIT
end
end

private

def binding_irb?
caller.any? do |frame|
BINDING_IRB_FRAME_REGEXPS.any? do |regexp|
frame.match?(regexp)
end
end
end
end

class DebugCommand < Debug
Expand Down
4 changes: 4 additions & 0 deletions lib/irb/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,10 @@ def evaluate(statement, line_no) # :nodoc:
nil
end

def from_binding?
@irb.from_binding
end

def evaluate_expression(code, line_no) # :nodoc:
result = nil
if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
Expand Down
16 changes: 16 additions & 0 deletions test/irb/test_debugger_integration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,22 @@ def test_debug_command_only_runs_once
assert_match(/IRB is already running with a debug session/, output)
end

def test_debug_command_can_only_be_called_from_binding_irb
write_ruby <<~'ruby'
require "irb"
# trick test framework
puts "binding.irb"
IRB.start
ruby

output = run_ruby_file do
type "debug"
type "exit"
end

assert_include(output, "Debugging commands are only available when IRB is started with binding.irb")
end

def test_next
write_ruby <<~'ruby'
binding.irb
Expand Down

0 comments on commit 4a4d7a4

Please sign in to comment.