diff --git a/spec/tags/optional/capi/binding_tags.txt b/spec/tags/optional/capi/binding_tags.txt index cc3433aca16d..1112bcc66ebe 100644 --- a/spec/tags/optional/capi/binding_tags.txt +++ b/spec/tags/optional/capi/binding_tags.txt @@ -1,2 +1 @@ fails:CApiBindingSpecs Kernel#binding gives the top-most Ruby binding when called from C -fails:CApiBindingSpecs Kernel#binding raises when called from C diff --git a/src/main/java/org/truffleruby/core/kernel/KernelNodes.java b/src/main/java/org/truffleruby/core/kernel/KernelNodes.java index b1da3d150421..54fc2fd45e44 100644 --- a/src/main/java/org/truffleruby/core/kernel/KernelNodes.java +++ b/src/main/java/org/truffleruby/core/kernel/KernelNodes.java @@ -17,6 +17,7 @@ import java.util.Objects; import java.util.concurrent.TimeUnit; +import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached.Shared; import com.oracle.truffle.api.dsl.Fallback; @@ -24,6 +25,7 @@ import com.oracle.truffle.api.dsl.GenerateInline; import com.oracle.truffle.api.dsl.NeverDefault; import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameInstance; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.object.PropertyGetter; @@ -92,6 +94,7 @@ import org.truffleruby.interop.ToJavaStringNode; import org.truffleruby.core.string.ImmutableRubyString; import org.truffleruby.interop.TranslateInteropExceptionNode; +import org.truffleruby.language.CallStackManager; import org.truffleruby.language.ImmutableRubyObject; import org.truffleruby.language.LexicalScope; import org.truffleruby.language.Nil; @@ -334,6 +337,18 @@ RubyBinding binding(Frame callerFrame, Object self, Object[] rubyArgs, RootCallT @Cached( value = "getAdoptedNode(this).getEncapsulatingSourceSection()", allowUncached = true, neverDefault = false) SourceSection sourceSection) { + + final MaterializedFrame materializedCallerFrame = Truffle.getRuntime() + .iterateFrames(f -> f.getFrame(FrameInstance.FrameAccess.MATERIALIZE).materialize(), 1); + + if (!CallStackManager.isRubyFrame(materializedCallerFrame)) { + throw new RaiseException( + getContext(), + coreExceptions().runtimeError( + "Cannot create Binding object for non-Ruby caller", + this)); + } + needCallerFrame(callerFrame, target); return BindingNodes.createBinding(getContext(), getLanguage(), callerFrame.materialize(), sourceSection); }