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
@ -103,13 +103,20 @@ class Delegator < BasicObject
|
|||||||
r
|
r
|
||||||
end
|
end
|
||||||
|
|
||||||
|
KERNEL_RESPOND_TO = ::Kernel.instance_method(:respond_to?)
|
||||||
|
private_constant :KERNEL_RESPOND_TO
|
||||||
|
|
||||||
# Handle BasicObject instances
|
# Handle BasicObject instances
|
||||||
private def target_respond_to?(target, m, include_private)
|
private def target_respond_to?(target, m, include_private)
|
||||||
case target
|
case target
|
||||||
when Object
|
when Object
|
||||||
target.respond_to?(m, include_private)
|
target.respond_to?(m, include_private)
|
||||||
else
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -344,6 +344,20 @@ class TestDelegateClass < Test::Unit::TestCase
|
|||||||
assert_raise(NoMethodError, /undefined method `foo' for/) { delegate.foo }
|
assert_raise(NoMethodError, /undefined method `foo' for/) { delegate.foo }
|
||||||
end
|
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
|
def test_keyword_argument
|
||||||
k = EnvUtil.labeled_class("Target") do
|
k = EnvUtil.labeled_class("Target") do
|
||||||
def test(a, k:) [a, k]; end
|
def test(a, k:) [a, k]; end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user