Skip to content

Commit 81ad76e

Browse files
committed
[GR-18163] Call #method_missing if #singleton_method_added is undefined (#2258)
PullRequest: truffleruby/2415
2 parents ddc6eef + 8a3918e commit 81ad76e

File tree

2 files changed

+61
-27
lines changed

2 files changed

+61
-27
lines changed

spec/ruby/core/basicobject/singleton_method_added_spec.rb

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,63 @@ class << self
8383
end
8484
ScratchPad.recorded.should == [:singleton_method_added, :new_method_with_define_method]
8585
end
86+
87+
describe "when singleton_method_added is undefined" do
88+
it "raises NoMethodError for a metaclass" do
89+
class BasicObjectSpecs::NoSingletonMethodAdded
90+
class << self
91+
undef_method :singleton_method_added
92+
end
93+
94+
-> {
95+
def self.foo
96+
end
97+
}.should raise_error(NoMethodError, /undefined method `singleton_method_added' for/)
98+
end
99+
end
100+
101+
it "raises NoMethodError for a singleton instance" do
102+
object = Object.new
103+
class << object
104+
undef_method :singleton_method_added
105+
106+
-> {
107+
def foo
108+
end
109+
}.should raise_error(NoMethodError, /undefined method `singleton_method_added' for #<Object:/)
110+
111+
-> {
112+
define_method(:bar) {}
113+
}.should raise_error(NoMethodError, /undefined method `singleton_method_added' for #<Object:/)
114+
end
115+
116+
-> {
117+
object.define_singleton_method(:baz) {}
118+
}.should raise_error(NoMethodError, /undefined method `singleton_method_added' for #<Object:/)
119+
end
120+
121+
it "calls #method_missing" do
122+
ScratchPad.record []
123+
object = Object.new
124+
class << object
125+
def method_missing(*args)
126+
ScratchPad << args
127+
end
128+
129+
undef_method :singleton_method_added
130+
131+
def foo
132+
end
133+
134+
define_method(:bar) {}
135+
end
136+
object.define_singleton_method(:baz) {}
137+
138+
ScratchPad.recorded.should == [
139+
[:singleton_method_added, :foo],
140+
[:singleton_method_added, :bar],
141+
[:singleton_method_added, :baz],
142+
]
143+
end
144+
end
86145
end

src/main/java/org/truffleruby/RubyContext.java

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@
4545
import org.truffleruby.core.hash.ReHashable;
4646
import org.truffleruby.core.inlined.CoreMethods;
4747
import org.truffleruby.core.kernel.AtExitManager;
48-
import org.truffleruby.core.kernel.KernelNodes;
4948
import org.truffleruby.core.kernel.TraceManager;
50-
import org.truffleruby.core.module.ModuleOperations;
5149
import org.truffleruby.core.module.RubyModule;
5250
import org.truffleruby.core.objectspace.ObjectSpaceManager;
5351
import org.truffleruby.core.proc.ProcOperations;
@@ -63,16 +61,13 @@
6361
import org.truffleruby.language.CallStackManager;
6462
import org.truffleruby.core.string.ImmutableRubyString;
6563
import org.truffleruby.language.LexicalScope;
66-
import org.truffleruby.language.Nil;
6764
import org.truffleruby.language.RubyBaseNode;
6865
import org.truffleruby.language.SafepointManager;
69-
import org.truffleruby.language.arguments.RubyArguments;
7066
import org.truffleruby.language.backtrace.BacktraceFormatter;
7167
import org.truffleruby.language.control.RaiseException;
68+
import org.truffleruby.language.dispatch.DispatchNode;
7269
import org.truffleruby.language.loader.CodeLoader;
7370
import org.truffleruby.language.loader.FeatureLoader;
74-
import org.truffleruby.language.methods.InternalMethod;
75-
import org.truffleruby.language.objects.MetaClassNode;
7671
import org.truffleruby.language.objects.shared.SharedObjects;
7772
import org.truffleruby.options.LanguageOptions;
7873
import org.truffleruby.options.Options;
@@ -435,27 +430,7 @@ private TruffleNFIPlatform createNativePlatform() {
435430

436431
@TruffleBoundary
437432
public static Object send(Object receiver, String methodName, Object... arguments) {
438-
final InternalMethod method = ModuleOperations
439-
.lookupMethodUncached(MetaClassNode.getUncached().execute(receiver), methodName, null);
440-
if (method == null || method.isUndefined()) {
441-
final RubyContext context = RubyLanguage.getCurrentContext();
442-
final String message = String.format(
443-
"undefined method `%s' for %s when using RubyContext#send() which ignores #method_missing",
444-
methodName,
445-
KernelNodes.ToSNode.uncachedBasicToS(receiver));
446-
throw new RaiseException(
447-
context,
448-
context.getCoreExceptions().noMethodError(
449-
message,
450-
receiver,
451-
methodName,
452-
arguments,
453-
EncapsulatingNodeReference.getCurrent().get()));
454-
}
455-
456-
return IndirectCallNode.getUncached().call(
457-
method.getCallTarget(),
458-
RubyArguments.pack(null, null, method, null, receiver, Nil.INSTANCE, arguments));
433+
return DispatchNode.getUncached().call(receiver, methodName, arguments);
459434
}
460435

461436
@TruffleBoundary

0 commit comments

Comments
 (0)