summaryrefslogtreecommitdiff
path: root/lib/delegate.rb
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-08-25 00:04:14 -0700
committerJeremy Evans <code@jeremyevans.net>2019-10-10 13:15:00 -0700
commit2322c94dd65c0247b103e2f91411e37458e1466d (patch)
tree80e3bcebe14c0505590ecfff5bc4e622a7e087eb /lib/delegate.rb
parent41719096957aa3d80e2e23d04ae288d2dee5328e (diff)
Support delegates for BasicObject
For BasicObject, bind the Kernel respond_to? instance method to the object and call it instead of calling the method directly. Also, use bind_call(recv, ...) for better performance. Fixes [Bug #16127]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2546
Diffstat (limited to 'lib/delegate.rb')
-rw-r--r--lib/delegate.rb18
1 files changed, 14 insertions, 4 deletions
diff --git a/lib/delegate.rb b/lib/delegate.rb
index a1589ecd08..7a2ad50ac3 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -79,10 +79,10 @@ class Delegator < BasicObject
r = true
target = self.__getobj__ {r = false}
- if r && target.respond_to?(m)
+ if r && target_respond_to?(target, m, false)
target.__send__(m, *args, &block)
elsif ::Kernel.method_defined?(m) || ::Kernel.private_method_defined?(m)
- ::Kernel.instance_method(m).bind(self).(*args, &block)
+ ::Kernel.instance_method(m).bind_call(self, *args, &block)
else
super(m, *args, &block)
end
@@ -95,14 +95,24 @@ class Delegator < BasicObject
def respond_to_missing?(m, include_private)
r = true
target = self.__getobj__ {r = false}
- r &&= target.respond_to?(m, include_private)
- if r && include_private && !target.respond_to?(m, false)
+ r &&= target_respond_to?(target, m, include_private)
+ if r && include_private && !target_respond_to?(target, m, false)
warn "delegator does not forward private method \##{m}", uplevel: 3
return false
end
r
end
+ # 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)
+ end
+ end
+
#
# Returns the methods available to this delegate object as the union
# of this object's and \_\_getobj\_\_ methods.