core_extensions: make '__binding__' work with redefined #respond_to?

Fixes https://github.com/pry/pry/issues/1596
(Unable to inspect object built from class)
Replaces https://github.com/pry/pry/pull/1719
Big thanks to @egwspiti for the repro case and the proposed PR.

When a class redefines `respond_to?` or `method_missing` this leads to some
problems and confuses Pry. I found another example where Pry misbehaves:

```
[1] pry(main)> cd Class.new { def method_missing(*) end; def respond_to_missing?(*) true end; }.new
NoMethodError: private method `eval' called for nil:NilClass
from /Users/kyrylo/.gem/ruby/2.4.2/gems/pry-0.11.3/lib/pry/pry_instance.rb:163:in `inject_local'
```

By using `method_defined?` we can work around these bugs since this method
doesn't check whether the receiver responds to a certain message but checks
whether this method is defined (so we don't redefine it later). Seems like a
win-win.
This commit is contained in:
Kyrylo Silin 2018-10-17 22:57:15 +08:00
parent 0993c2b82a
commit 157c7db32a
2 changed files with 7 additions and 1 deletions

View File

@ -87,7 +87,7 @@ class Object
return class_eval("binding")
end
unless respond_to?(:__pry__)
unless self.class.method_defined?(:__pry__)
# The easiest way to check whether an object has a working singleton class
# is to try and define a method on it. (just checking for the presence of
# the singleton class gives false positives for `true` and `false`).

View File

@ -250,4 +250,10 @@ describe 'cd' do
it 'should be able to cd into the Object BasicObject' do
expect { @t.eval 'cd BasicObject.new' }.to_not raise_error
end
# https://github.com/pry/pry/issues/1596
it "can cd into objects that redefine #respond_to? to return true" do
expect { @t.eval('cd Class.new { def respond_to?(m) true end }.new') }
.to_not raise_error
end
end