Prevented local variables from being leaked into bindings used by Pry (fixes #662)

This commit is contained in:
Mon ouïe 2012-07-22 23:30:05 +02:00
parent d86f374cc8
commit 083b06aba2
2 changed files with 32 additions and 16 deletions

View File

@ -1,3 +1,23 @@
class Pry
# @retun [String] Code of the method used when implementing Pry's
# __binding__.
#
# @see Object#__binding__
BindingImplMethod = [<<-METHOD, __FILE__, __LINE__ + 1]
# Get a binding with 'self' set to self, and no locals.
#
# The default definee is determined by the context in which the
# definition is eval'd.
#
# Please don't call this method directly, see {__binding__}.
#
# @return [Binding]
def __pry__
binding
end
METHOD
end
class Object
# Start a Pry REPL on self.
#
@ -45,6 +65,10 @@ class Object
#
# @return [Binding]
def __binding__
# If you ever feel like changing this method, be careful about variables
# that you use. They shouldn't be inserted into the binding that will
# eventually be retruning.
# When you're cd'd into a class, methods you define should be added to it.
if is_a?(Module)
# class_eval sets both self and the default definee to this class.
@ -52,20 +76,6 @@ class Object
end
unless respond_to?(:__pry__)
binding_impl_method = [<<-METHOD, __FILE__, __LINE__ + 1]
# Get a binding with 'self' set to self, and no locals.
#
# The default definee is determined by the context in which the
# definition is eval'd.
#
# Please don't call this method directly, see {__binding__}.
#
# @return [Binding]
def __pry__
binding
end
METHOD
# 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`).
@ -73,14 +83,14 @@ class Object
# it has the nice property that we can memoize this check.
begin
# instance_eval sets the default definee to the object's singleton class
instance_eval(*binding_impl_method)
instance_eval(*Pry::BindingImplMethod)
# If we can't define methods on the Object's singleton_class. Then we fall
# back to setting the default definee to be the Object's class. That seems
# nicer than having a REPL in which you can't define methods.
rescue TypeError
# class_eval sets the default definee to self.class
self.class.class_eval(*binding_impl_method)
self.class.class_eval(*Pry::BindingImplMethod)
end
end

View File

@ -31,6 +31,12 @@ describe Pry do
lambda { Pry.binding_for(o) }.should.not.raise Exception
end
it "should not leak local variables" do
[Object.new, Array, 3].each do |obj|
Pry.binding_for(obj).eval("local_variables").should.be.empty
end
end
end
describe "open a Pry session on an object" do