Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: c885d6f193e4
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: fad37ea767ae
Choose a head ref
  • 4 commits
  • 2 files changed
  • 1 contributor

Commits on Mar 2, 2015

  1. Add spec for GH-1270.

    Note that there's an unfixable (in 1.7) edge case described and
    disabled in the spec. I will apply the unmodified case to master,
    which handles it ok.
    headius committed Mar 2, 2015
    Copy the full SHA
    ab2d782 View commit details
  2. Copy the full SHA
    25499af View commit details
  3. Copy the full SHA
    c4cdb07 View commit details
  4. Copy the full SHA
    fad37ea View commit details
Showing with 48 additions and 8 deletions.
  1. +10 −8 core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
  2. +38 −0 spec/regression/GH-1270_break_propagates_through_escaped_proc_spec.rb
18 changes: 10 additions & 8 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
@@ -183,21 +183,23 @@ public static IRubyObject initiateBreak(ThreadContext context, DynamicScope dynS
}
}

@JIT
@Interp @JIT
public static IRubyObject handleBreakAndReturnsInLambdas(ThreadContext context, StaticScope scope, DynamicScope dynScope, Object exc, Block.Type blockType) throws RuntimeException {
if ((exc instanceof IRBreakJump) && inNonMethodBodyLambda(scope, blockType)) {
// We just unwound all the way up because of a non-local break
throw IRException.BREAK_LocalJumpError.getException(context.getRuntime());
} else if (exc instanceof IRReturnJump && (blockType == null || inLambda(blockType))) {
if (((IRBreakJump)exc).scopeToReturnTo == dynScope) throw IRException.BREAK_LocalJumpError.getException(context.getRuntime());
}

if (exc instanceof IRReturnJump && (blockType == null || inLambda(blockType))) {
// Ignore non-local return processing in non-lambda blocks.
// Methods have a null blocktype
return handleNonlocalReturn(scope, dynScope, exc, blockType);
} else {
// Propagate
Helpers.throwException((Throwable)exc);
// should not get here
return null;
}

// Propagate
Helpers.throwException((Throwable)exc);
// should not get here
return null;
}

@JIT
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
describe "A break passing through an intermediate escaped closure" do
it "does not turn into a LocalJumpError" do
class Enumerator1270
def initialize(&b)
@g = Generator1270.new(&b)
end

def each
@g.each do |x|
yield x
end
end
end

class Generator1270
def initialize(&b)
@b = b
end

def each(&b)
y = Yielder1270.new(&b)
@b.call(y)
end
end

class Yielder1270
def initialize(&b)
@b = b
end

def yield(x)
@b.call(x)
end
end

Enumerator1270.new {|y| y.yield 1}.each {break 1}.should == 1
end
end