Skip to content

Commit

Permalink
Fix #1690: Identify define_method scopes to catch nonlocal returns
Browse files Browse the repository at this point in the history
* The old check was walking past all closure scopes which meant
  it was walking past method bodies defined via define_method.
  • Loading branch information
subbuss committed Sep 11, 2014
1 parent 9062455 commit 332cb2a
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 3 deletions.
12 changes: 9 additions & 3 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Expand Up @@ -56,6 +56,7 @@ public static boolean inProc(Block.Type blockType) {
public static void initiateNonLocalReturn(ThreadContext context, DynamicScope dynScope, boolean maybeLambda, IRubyObject returnValue) {
IRStaticScope scope = (IRStaticScope)dynScope.getStaticScope();
IRScopeType scopeType = scope.getScopeType();
boolean inDefineMethod = false;
while (dynScope != null) {
IRStaticScope ss = (IRStaticScope)dynScope.getStaticScope();
// SSS FIXME: Why is scopeType empty? Looks like this static-scope
Expand All @@ -65,8 +66,13 @@ public static void initiateNonLocalReturn(ThreadContext context, DynamicScope dy
//
// To be investigated.
IRScopeType ssType = ss.getScopeType();
if (ssType != null && ssType.isMethodType()) {
break;
if (ssType != null) {
if (ssType.isMethodType()) {
break;
} else if (ss.isArgumentScope() && ssType.isClosureType() && ssType != IRScopeType.EVAL_SCRIPT) {
inDefineMethod = true;
break;
}
}
dynScope = dynScope.getNextCapturedScope();
}
Expand All @@ -77,7 +83,7 @@ public static void initiateNonLocalReturn(ThreadContext context, DynamicScope dy
// Ruby code: lambda { Thread.new { return }.join }.call
//
// To be investigated.
if ( (scopeType == null || (scopeType.isClosureType() && scopeType != IRScopeType.EVAL_SCRIPT))
if ( (scopeType == null || (!inDefineMethod && scopeType.isClosureType() && scopeType != IRScopeType.EVAL_SCRIPT))
&& (maybeLambda || !context.scopeExistsOnCallStack(dynScope)))
{
// Cannot return from the call that we have long since exited.
Expand Down
13 changes: 13 additions & 0 deletions spec/regression/GH-1690_nonlocal_return_in_define_method_block.rb
@@ -0,0 +1,13 @@
# https://github.com/jruby/jruby/issues/1690

def yielder; yield; end

class C
define_method(:foo) { yielder { return :foo; } }
end

describe 'NonLocalReturn' do
it 'inside a block of a define_method block body returns normally' do
C.new.foo.should_be :foo
end
end

1 comment on commit 332cb2a

@subbuss
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gah! This was meant to be 1960 ... so much for late night commits!

Please sign in to comment.