Skip to content

Commit

Permalink
Avoid calling private methods on the main object (#498)
Browse files Browse the repository at this point in the history
When the main object is frozen, `IRB` wraps a `SimpleDelegator` around it.
But because `SimpleDelegator` doesn't delegate private methods, methods like
`require_relative` or `const_get` would cause error, which are needed for
lazily loading commands.

This commit works around this limitation by avoiding those private method calls
when setting up command execution.
  • Loading branch information
st0012 authored Jan 12, 2023
1 parent bfe9915 commit fa0fbb7
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 4 deletions.
8 changes: 4 additions & 4 deletions lib/irb/extend-command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ def self.def_extend_command(cmd_name, cmd_class, load_file = nil, *aliases)
kwargs = ", **kwargs" if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0"
line = __LINE__; eval %[
def #{cmd_name}(*opts#{kwargs}, &b)
require_relative "#{load_file}"
arity = ExtendCommand::#{cmd_class}.instance_method(:execute).arity
Kernel.require_relative "#{load_file}"
arity = ::IRB::ExtendCommand::#{cmd_class}.instance_method(:execute).arity
args = (1..(arity < 0 ? ~arity : arity)).map {|i| "arg" + i.to_s }
args << "*opts#{kwargs}" if arity < 0
args << "&block"
Expand All @@ -269,7 +269,7 @@ def #{cmd_name}(*opts#{kwargs}, &b)
unless singleton_class.class_variable_defined?(:@@#{cmd_name}_)
singleton_class.class_variable_set(:@@#{cmd_name}_, true)
def self.#{cmd_name}_(\#{args})
ExtendCommand::#{cmd_class}.execute(irb_context, \#{args})
::IRB::ExtendCommand::#{cmd_class}.execute(irb_context, \#{args})
end
end
], nil, __FILE__, line
Expand All @@ -279,7 +279,7 @@ def self.#{cmd_name}_(\#{args})
else
line = __LINE__; eval %[
def #{cmd_name}(*opts, &b)
ExtendCommand::#{cmd_class}.execute(irb_context, *opts, &b)
::IRB::ExtendCommand::#{cmd_class}.execute(irb_context, *opts, &b)
end
], nil, __FILE__, line
end
Expand Down
13 changes: 13 additions & 0 deletions test/irb/test_cmd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ def execute_lines(*lines, conf: {}, main: self, irb_path: nil)
end
end

class FrozenObjectTest < CommandTestCase
def test_calling_command_on_a_frozen_main
main = Object.new.freeze

out, err = execute_lines(
"irb_info",
main: main
)
assert_empty err
assert_match(/RUBY_PLATFORM/, out)
end
end

class CommnadAliasTest < CommandTestCase
def test_vars_with_aliases
@foo = "foo"
Expand Down

0 comments on commit fa0fbb7

Please sign in to comment.