Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 19 additions & 17 deletions core/src/main/java/org/jruby/RubyException.java
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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);
}

Expand All @@ -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)) {
Expand All @@ -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);
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}

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

Expand Down Expand Up @@ -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) {
Expand All @@ -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,
Expand Down
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());
}

}