Skip to content

Commit 677a149

Browse files
committedJul 3, 2015
Fix lookup of respond_to_missing? method and add some specs.
Resolves #3451.
1 parent 0808464 commit 677a149

File tree

3 files changed

+61
-10
lines changed

3 files changed

+61
-10
lines changed
 

‎spec/core/type/fixtures/classes.rb

+13
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,17 @@ def public_method
6767
def private_method
6868
end
6969
end
70+
71+
module RespondToMissing
72+
def respond_to_missing?(name, include_private)
73+
if :missing_public == name
74+
true
75+
elsif :missing_private == name && include_private
76+
true
77+
else
78+
false
79+
end
80+
end
81+
module_function :respond_to_missing?
82+
end
7083
end

‎spec/core/type/object_respond_to_spec.rb

+36
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,40 @@
2121
it "returns true when the method is private and should look for private methods" do
2222
Rubinius::Type.object_respond_to?(@obj, :private_method, true).should be_true
2323
end
24+
25+
describe "given a kind of Object with respond_to_missing?" do
26+
before :each do
27+
@obj.extend TypeSpecs::RespondToMissing
28+
end
29+
30+
it "returns true if respond_to_missing? returns true" do
31+
Rubinius::Type.object_respond_to?(@obj, :missing_public).should be_true
32+
end
33+
34+
it "returns false if respond_to_missing? returns false" do
35+
Rubinius::Type.object_respond_to?(@obj, :missing_private).should be_false
36+
end
37+
38+
it "passes the include_private argument to the respond_to_missing? method" do
39+
Rubinius::Type.object_respond_to?(@obj, :missing_private, true).should be_true
40+
end
41+
end
42+
43+
describe "given a kind of BasicObject with respond_to_missing?" do
44+
before :each do
45+
@obj = Class.new(BasicObject) { include TypeSpecs::RespondToMissing }.new
46+
end
47+
48+
it "returns true if respond_to_missing? returns true" do
49+
Rubinius::Type.object_respond_to?(@obj, :missing_public).should be_true
50+
end
51+
52+
it "returns false if respond_to_missing? returns false" do
53+
Rubinius::Type.object_respond_to?(@obj, :missing_private).should be_false
54+
end
55+
56+
it "passes the include_private argument to the respond_to_missing? method" do
57+
Rubinius::Type.object_respond_to?(@obj, :missing_private, true).should be_true
58+
end
59+
end
2460
end

‎vm/builtin/object.cpp

+12-10
Original file line numberDiff line numberDiff line change
@@ -872,24 +872,26 @@ namespace rubinius {
872872

873873
if(dis.resolve(state, name, lookup)) {
874874
return cTrue;
875-
} else if(instance_of<BasicObject>(self)) {
876-
return cFalse;
877875
} else {
878876
LookupData lookup(self, self->lookup_begin(state), G(sym_private));
879877
Symbol* missing = G(sym_respond_to_missing);
880878
Dispatch dis(missing);
881879

882-
Object* buf[2];
883-
buf[0] = name;
884-
buf[1] = priv;
880+
if(dis.resolve(state, missing, lookup)) {
881+
Object* buf[2];
882+
buf[0] = name;
883+
buf[1] = priv;
885884

886-
Arguments args(missing, self, 2, buf);
887-
OnStack<3> os(state, self, name, priv);
888-
Object* responds = dis.send(state, 0, lookup, args);
885+
Arguments args(missing, self, 2, buf);
886+
OnStack<3> os(state, self, name, priv);
887+
Object* responds = dis.send(state, 0, lookup, args);
889888

890-
if(!responds) return NULL;
889+
if(!responds) return NULL;
891890

892-
return RBOOL(CBOOL(responds));
891+
return RBOOL(CBOOL(responds));
892+
} else {
893+
return cFalse;
894+
}
893895
}
894896
}
895897

0 commit comments

Comments
 (0)
Please sign in to comment.