Skip to content

Commit

Permalink
Showing 3 changed files with 86 additions and 21 deletions.
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;
}

9 changes: 5 additions & 4 deletions core/src/main/java/org/jruby/exceptions/RaiseException.java
Original file line number Diff line number Diff line change
@@ -131,13 +131,13 @@ public RaiseException(Ruby runtime, RubyClass excptnClass, String msg, IRubyObje
preRaise(context, backtrace);
}

public RaiseException(RubyException exception, boolean isNativeException) {
public RaiseException(RubyException exception, boolean nativeException) {
super(exception.message.toString());
if (DEBUG) {
Thread.dumpStack();
}
this.nativeException = isNativeException;
setException(exception, isNativeException);
this.nativeException = nativeException;
setException(exception, nativeException);
preRaise(exception.getRuntime().getCurrentContext());
}

@@ -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());
}

}

0 comments on commit dbc4b02

Please sign in to comment.