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: 65145de4bf8e^
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 72914d70b343
Choose a head ref
  • 4 commits
  • 3 files changed
  • 1 contributor

Commits on Nov 23, 2015

  1. Copy the full SHA
    65145de View commit details
  2. allow RaiseException() with passed nil backtrace to correctly force t…

    …he backtrace as nil
    kares committed Nov 23, 2015
    Copy the full SHA
    eb2aa90 View commit details
  3. improve forceBacktrace (called on RaiseException()) to keep backtrace…

    …() lazy
    
    the `backtrace()` return value when doing `set_backtrace` was ignored anyway
    kares committed Nov 23, 2015
    Copy the full SHA
    7841a87 View commit details
  4. prefer StandardError.isInstance(ex) check - over ex.kind_of(StandardE…

    …rror)
    
    which is slightly faster ... avoids an instanceof check + Ruby boolean wrapping
    kares committed Nov 23, 2015
    Copy the full SHA
    72914d7 View commit details
36 changes: 19 additions & 17 deletions core/src/main/java/org/jruby/RubyException.java
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@
* Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
* Copyright (C) 2005 David Corbin <dcorbin@users.sf.net>
* Copyright (C) 2006 Michael Studman <codehaus@michaelstudman.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -68,7 +68,7 @@ protected RubyException(Ruby runtime, RubyClass rubyClass) {

public RubyException(Ruby runtime, RubyClass rubyClass, String message) {
super(runtime, rubyClass);

this.message = message == null ? runtime.getNil() : runtime.newString(message);
}

@@ -83,12 +83,16 @@ public IRubyObject initialize(IRubyObject[] args, Block block) {

@JRubyMethod
public IRubyObject backtrace() {
IRubyObject bt = getBacktrace();
return bt;
return getBacktrace();
}

@JRubyMethod(required = 1)
public IRubyObject set_backtrace(IRubyObject obj) {
setBacktrace(obj);
return backtrace();
}

private void setBacktrace(IRubyObject obj) {
if (obj.isNil()) {
backtrace = null;
} else if (isArrayOfStrings(obj)) {
@@ -98,15 +102,13 @@ public IRubyObject set_backtrace(IRubyObject obj) {
} else {
throw getRuntime().newTypeError("backtrace must be Array of String or a single String");
}

return backtrace();
}

@JRubyMethod(omit = true)
public IRubyObject backtrace_locations(ThreadContext context) {
Ruby runtime = context.runtime;
RubyStackTraceElement[] elements = backtraceData.getBacktrace(runtime);

return RubyThread.Location.newLocationArray(runtime, elements);
}

@@ -239,17 +241,17 @@ public void prepareIntegratedBacktrace(ThreadContext context, StackTraceElement[
}

public void forceBacktrace(IRubyObject backtrace) {
backtraceData = BacktraceData.EMPTY;
set_backtrace(backtrace);
backtraceData = (backtrace != null && backtrace.isNil()) ? null : BacktraceData.EMPTY;
setBacktrace(backtrace);
}

public IRubyObject getBacktrace() {
if (backtrace == null) {
initBacktrace();
}
return backtrace;
}

public void initBacktrace() {
Ruby runtime = getRuntime();
if (backtraceData == null) {
@@ -300,16 +302,16 @@ public void printBacktrace(PrintStream errorStream, int skip) {
private void printStackTraceLine(PrintStream errorStream, IRubyObject stackTraceLine) {
errorStream.print("\tfrom " + stackTraceLine + '\n');
}

private boolean isArrayOfStrings(IRubyObject backtrace) {
if (!(backtrace instanceof RubyArray)) return false;
if (!(backtrace instanceof RubyArray)) return false;

IRubyObject[] elements = ((RubyArray) backtrace).toJavaArray();

for (int i = 0 ; i < elements.length ; i++) {
if (!(elements[i] instanceof RubyString)) return false;
}

return true;
}

3 changes: 2 additions & 1 deletion core/src/main/java/org/jruby/exceptions/RaiseException.java
Original file line number Diff line number Diff line change
@@ -213,7 +213,7 @@ private boolean requiresBacktrace(ThreadContext context) {
// We can only omit backtraces of descendents of Standard error for 'foo rescue nil'
return context.exceptionRequiresBacktrace ||
(debugMode != null && debugMode.isTrue()) ||
!exception.kind_of_p(context, context.runtime.getStandardError()).isTrue();
! context.runtime.getStandardError().isInstance(exception);
}

private void preRaise(ThreadContext context, IRubyObject backtrace) {
@@ -229,6 +229,7 @@ private void preRaise(ThreadContext context, IRubyObject backtrace) {
exception.prepareBacktrace(context, nativeException);
} else {
exception.forceBacktrace(backtrace);
if ( backtrace.isNil() ) return;
}

// call Throwable.setStackTrace so that when RaiseException appears nested inside another exception,
62 changes: 62 additions & 0 deletions core/src/test/java/org/jruby/exceptions/TestRaiseException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2015 JRuby.
*/
package org.jruby.exceptions;

import org.jruby.RubyArray;
import org.jruby.RubyClass;
import org.jruby.RubyException;
import org.jruby.runtime.backtrace.RubyStackTraceElement;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.test.TestRubyBase;

public class TestRaiseException extends TestRubyBase {

public void testBacktrace() {
IRubyObject ex = runtime.evalScriptlet("ex = nil; " +
"begin; raise 'with-bracktrace'; rescue => e; ex = e end; ex"
);
assertEquals("org.jruby.RubyException", ex.getClass().getName());
IRubyObject backtrace = ((RubyException) ex).getBacktrace();
assertNotNil( backtrace );
assertFalse( ((RubyArray) backtrace).isEmpty() );
}

public void testJavaGeneratedBacktrace() {
final int count = runtime.getBacktraceCount();

final RubyClass RuntimeError = runtime.getRuntimeError();
RaiseException re = new RaiseException(runtime, RuntimeError, "", false);
IRubyObject backtrace = re.getException().backtrace();
assertNotNil( backtrace );
assertTrue( ((RubyArray) backtrace).isEmpty() );

assertNotSame( RubyStackTraceElement.EMPTY_ARRAY, re.getException().getBacktraceElements() );

assertEquals( count + 1, runtime.getBacktraceCount() );
}

public void testJavaGeneratedNilBacktrace() {
final int count = runtime.getBacktraceCount();
IRubyObject backtrace = runtime.getNil();

final RubyClass RuntimeError = runtime.getRuntimeError();
RaiseException re = new RaiseException(runtime, RuntimeError, "", backtrace, false);
backtrace = re.getException().backtrace();
assertNil( backtrace );

assertNil( re.getException().getBacktrace() );
assertSame( RubyStackTraceElement.EMPTY_ARRAY, re.getException().getBacktraceElements() );

assertEquals( count, runtime.getBacktraceCount() );
}

private void assertNil(IRubyObject val) {
assertTrue("expected: " + val.inspect() + " to be nil", val.isNil());
}

private void assertNotNil(IRubyObject val) {
assertFalse("expected: " + val.inspect() + " to not be nil", val.isNil());
}

}