Skip to content

Commit

Permalink
Fix lookup of respond_to_missing? method and add some specs.
Browse files Browse the repository at this point in the history
Resolves #3451.
  • Loading branch information
jemc committed Jul 3, 2015
1 parent 0808464 commit 677a149
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 10 deletions.
13 changes: 13 additions & 0 deletions spec/core/type/fixtures/classes.rb
Expand Up @@ -67,4 +67,17 @@ def public_method
def private_method
end
end

module RespondToMissing
def respond_to_missing?(name, include_private)
if :missing_public == name
true
elsif :missing_private == name && include_private
true
else
false
end
end
module_function :respond_to_missing?
end
end
36 changes: 36 additions & 0 deletions spec/core/type/object_respond_to_spec.rb
Expand Up @@ -21,4 +21,40 @@
it "returns true when the method is private and should look for private methods" do
Rubinius::Type.object_respond_to?(@obj, :private_method, true).should be_true
end

describe "given a kind of Object with respond_to_missing?" do
before :each do
@obj.extend TypeSpecs::RespondToMissing
end

it "returns true if respond_to_missing? returns true" do
Rubinius::Type.object_respond_to?(@obj, :missing_public).should be_true
end

it "returns false if respond_to_missing? returns false" do
Rubinius::Type.object_respond_to?(@obj, :missing_private).should be_false
end

it "passes the include_private argument to the respond_to_missing? method" do
Rubinius::Type.object_respond_to?(@obj, :missing_private, true).should be_true
end
end

describe "given a kind of BasicObject with respond_to_missing?" do
before :each do
@obj = Class.new(BasicObject) { include TypeSpecs::RespondToMissing }.new
end

it "returns true if respond_to_missing? returns true" do
Rubinius::Type.object_respond_to?(@obj, :missing_public).should be_true
end

it "returns false if respond_to_missing? returns false" do
Rubinius::Type.object_respond_to?(@obj, :missing_private).should be_false
end

it "passes the include_private argument to the respond_to_missing? method" do
Rubinius::Type.object_respond_to?(@obj, :missing_private, true).should be_true
end
end
end
22 changes: 12 additions & 10 deletions vm/builtin/object.cpp
Expand Up @@ -872,24 +872,26 @@ namespace rubinius {

if(dis.resolve(state, name, lookup)) {
return cTrue;
} else if(instance_of<BasicObject>(self)) {
return cFalse;
} else {
LookupData lookup(self, self->lookup_begin(state), G(sym_private));
Symbol* missing = G(sym_respond_to_missing);
Dispatch dis(missing);

Object* buf[2];
buf[0] = name;
buf[1] = priv;
if(dis.resolve(state, missing, lookup)) {
Object* buf[2];
buf[0] = name;
buf[1] = priv;

Arguments args(missing, self, 2, buf);
OnStack<3> os(state, self, name, priv);
Object* responds = dis.send(state, 0, lookup, args);
Arguments args(missing, self, 2, buf);
OnStack<3> os(state, self, name, priv);
Object* responds = dis.send(state, 0, lookup, args);

if(!responds) return NULL;
if(!responds) return NULL;

return RBOOL(CBOOL(responds));
return RBOOL(CBOOL(responds));
} else {
return cFalse;
}
}
}

Expand Down

0 comments on commit 677a149

Please sign in to comment.