diff options
author | Jeremy Evans <[email protected]> | 2019-08-25 00:04:14 -0700 |
---|---|---|
committer | Jeremy Evans <[email protected]> | 2019-10-10 13:15:00 -0700 |
commit | 2322c94dd65c0247b103e2f91411e37458e1466d (patch) | |
tree | 80e3bcebe14c0505590ecfff5bc4e622a7e087eb /lib/delegate.rb | |
parent | 41719096957aa3d80e2e23d04ae288d2dee5328e (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.rb | 18 |
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. |