mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Fix SimpleDelegator respond_to? regression
In 2.6, SimpleDelegator would always use the target `respond_to?` In 2.7.0 it doesn't if the target does not inherit from Object. This breaks compatibility for delegated objects that inherit from BasicObject and redefine `respond_to?`.
This commit is contained in:
parent
11963da9e8
commit
f2552216d4
Notes:
git
2020-02-04 01:16:53 +09:00
2 changed files with 22 additions and 1 deletions
|
@ -103,13 +103,20 @@ class Delegator < BasicObject
|
|||
r
|
||||
end
|
||||
|
||||
KERNEL_RESPOND_TO = ::Kernel.instance_method(:respond_to?)
|
||||
private_constant :KERNEL_RESPOND_TO
|
||||
|
||||
# Handle BasicObject instances
|
||||
private def target_respond_to?(target, m, include_private)
|
||||
case target
|
||||
when Object
|
||||
target.respond_to?(m, include_private)
|
||||
else
|
||||
::Kernel.instance_method(:respond_to?).bind_call(target, m, include_private)
|
||||
if KERNEL_RESPOND_TO.bind_call(target, :respond_to?)
|
||||
target.respond_to?(m, include_private)
|
||||
else
|
||||
KERNEL_RESPOND_TO.bind_call(target, m, include_private)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -344,6 +344,20 @@ class TestDelegateClass < Test::Unit::TestCase
|
|||
assert_raise(NoMethodError, /undefined method `foo' for/) { delegate.foo }
|
||||
end
|
||||
|
||||
def test_basicobject_respond_to
|
||||
o = BasicObject.new
|
||||
def o.bar
|
||||
nil
|
||||
end
|
||||
|
||||
def o.respond_to?(method, include_private=false)
|
||||
return false if method == :bar
|
||||
::Kernel.instance_method(:respond_to?).bind_call(self, method, include_private)
|
||||
end
|
||||
delegate = SimpleDelegator.new(o)
|
||||
refute delegate.respond_to?(:bar)
|
||||
end
|
||||
|
||||
def test_keyword_argument
|
||||
k = EnvUtil.labeled_class("Target") do
|
||||
def test(a, k:) [a, k]; end
|
||||
|
|
Loading…
Reference in a new issue