[ruby/irb] Don't use delegator to install helper methods to main
object (https://github.com/ruby/irb/pull/1031) IRB used delegator to install command as a method of frozen main object. Command is not a method now. We can drop it. https://github.com/ruby/irb/commit/2f1c593801
This commit is contained in:
parent
edf5a738a3
commit
bc92379664
@ -1463,16 +1463,21 @@ module IRB
|
||||
end
|
||||
end
|
||||
|
||||
def basic_object_safe_main_call(method)
|
||||
main = @context.main
|
||||
Object === main ? main.__send__(method) : Object.instance_method(method).bind_call(main)
|
||||
end
|
||||
|
||||
def format_prompt(format, ltype, indent, line_no) # :nodoc:
|
||||
format.gsub(/%([0-9]+)?([a-zA-Z%])/) do
|
||||
case $2
|
||||
when "N"
|
||||
@context.irb_name
|
||||
when "m"
|
||||
main_str = @context.main.to_s rescue "!#{$!.class}"
|
||||
main_str = basic_object_safe_main_call(:to_s) rescue "!#{$!.class}"
|
||||
truncate_prompt_main(main_str)
|
||||
when "M"
|
||||
main_str = @context.main.inspect rescue "!#{$!.class}"
|
||||
main_str = basic_object_safe_main_call(:inspect) rescue "!#{$!.class}"
|
||||
truncate_prompt_main(main_str)
|
||||
when "l"
|
||||
ltype
|
||||
|
@ -19,7 +19,7 @@ module IRB
|
||||
# Use throw and catch to handle arg that includes `;`
|
||||
# For example: "1, kw: (2; 3); 4" will be parsed to [[1], { kw: 3 }]
|
||||
catch(:EXTRACT_RUBY_ARGS) do
|
||||
@irb_context.workspace.binding.eval "IRB::Command.extract_ruby_args #{arg}"
|
||||
@irb_context.workspace.binding.eval "::IRB::Command.extract_ruby_args #{arg}"
|
||||
end || [[], {}]
|
||||
end
|
||||
end
|
||||
|
@ -156,7 +156,8 @@ module IRB
|
||||
end
|
||||
|
||||
def eval_class_constants
|
||||
::Module.instance_method(:constants).bind(eval("self.class")).call
|
||||
klass = ::Object.instance_method(:class).bind_call(receiver)
|
||||
::Module.instance_method(:constants).bind_call(klass)
|
||||
end
|
||||
end
|
||||
}
|
||||
|
@ -4,8 +4,6 @@
|
||||
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
||||
#
|
||||
|
||||
require "delegate"
|
||||
|
||||
require_relative "helper_method"
|
||||
|
||||
IRB::TOPLEVEL_BINDING = binding
|
||||
@ -16,7 +14,7 @@ module IRB # :nodoc:
|
||||
# set self to main if specified, otherwise
|
||||
# inherit main from TOPLEVEL_BINDING.
|
||||
def initialize(*main)
|
||||
if main[0].kind_of?(Binding)
|
||||
if Binding === main[0]
|
||||
@binding = main.shift
|
||||
elsif IRB.conf[:SINGLE_IRB]
|
||||
@binding = TOPLEVEL_BINDING
|
||||
@ -70,37 +68,16 @@ EOF
|
||||
unless main.empty?
|
||||
case @main
|
||||
when Module
|
||||
@binding = eval("IRB.conf[:__MAIN__].module_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
|
||||
@binding = eval("::IRB.conf[:__MAIN__].module_eval('::Kernel.binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
|
||||
else
|
||||
begin
|
||||
@binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
|
||||
@binding = eval("::IRB.conf[:__MAIN__].instance_eval('::Kernel.binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
|
||||
rescue TypeError
|
||||
fail CantChangeBinding, @main.inspect
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
case @main
|
||||
when Object
|
||||
use_delegator = @main.frozen?
|
||||
else
|
||||
use_delegator = true
|
||||
end
|
||||
|
||||
if use_delegator
|
||||
@main = SimpleDelegator.new(@main)
|
||||
IRB.conf[:__MAIN__] = @main
|
||||
@main.singleton_class.class_eval do
|
||||
private
|
||||
define_method(:binding, Kernel.instance_method(:binding))
|
||||
define_method(:local_variables, Kernel.instance_method(:local_variables))
|
||||
# Define empty method to avoid delegator warning, will be overridden.
|
||||
define_method(:exit) {|*a, &b| }
|
||||
define_method(:exit!) {|*a, &b| }
|
||||
end
|
||||
@binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, *@binding.source_location)
|
||||
end
|
||||
|
||||
@binding.local_variable_set(:_, nil)
|
||||
end
|
||||
|
||||
@ -111,6 +88,9 @@ EOF
|
||||
attr_reader :main
|
||||
|
||||
def load_helper_methods_to_main
|
||||
# Do not load helper methods to frozen objects and BasicObject
|
||||
return unless Object === @main && !@main.frozen?
|
||||
|
||||
ancestors = class<<main;ancestors;end
|
||||
main.extend ExtendCommandBundle if !ancestors.include?(ExtendCommandBundle)
|
||||
main.extend HelpersContainer if !ancestors.include?(HelpersContainer)
|
||||
|
@ -19,6 +19,12 @@ module TestIRB
|
||||
end
|
||||
end
|
||||
|
||||
class BO < BasicObject
|
||||
def baz
|
||||
"this is baz"
|
||||
end
|
||||
end
|
||||
|
||||
binding.irb
|
||||
RUBY
|
||||
end
|
||||
@ -40,6 +46,19 @@ module TestIRB
|
||||
assert_match(/irb\(Foo\):006>/, out)
|
||||
end
|
||||
|
||||
def test_cd_basic_object_or_frozen
|
||||
out = run_ruby_file do
|
||||
type "cd BO.new"
|
||||
type "cd 1"
|
||||
type "cd Object.new.freeze"
|
||||
type "exit"
|
||||
end
|
||||
|
||||
assert_match(/irb\(#<BO:.+\):002>/, out)
|
||||
assert_match(/irb\(1\):003>/, out)
|
||||
assert_match(/irb\(#<Object:.+\):004>/, out)
|
||||
end
|
||||
|
||||
def test_cd_moves_top_level_with_no_args
|
||||
out = run_ruby_file do
|
||||
type "cd Foo"
|
||||
|
@ -652,6 +652,13 @@ module TestIRB
|
||||
assert_equal('irb("aaaaaaaaaaaaaaaaaaaaaaaaaaaa...)>', irb.send(:format_prompt, 'irb(%M)>', nil, 1, 1))
|
||||
end
|
||||
|
||||
def test_prompt_main_basic_object
|
||||
main = BasicObject.new
|
||||
irb = IRB::Irb.new(IRB::WorkSpace.new(main), TestInputMethod.new)
|
||||
assert_match(/irb\(#<BasicObject:.+\)/, irb.send(:format_prompt, 'irb(%m)>', nil, 1, 1))
|
||||
assert_match(/irb\(#<BasicObject:.+\)/, irb.send(:format_prompt, 'irb(%M)>', nil, 1, 1))
|
||||
end
|
||||
|
||||
def test_prompt_main_raise
|
||||
main = Object.new
|
||||
def main.to_s; raise TypeError; end
|
||||
|
Loading…
x
Reference in New Issue
Block a user