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

Commits on Mar 26, 2018

  1. Copy the full SHA
    936e2b3 View commit details
  2. Copy the full SHA
    4ef8992 View commit details
  3. Copy the full SHA
    5e6feb4 View commit details
Showing with 64 additions and 6 deletions.
  1. +16 −5 core/src/main/java/org/jruby/RubyException.java
  2. +39 −0 spec/ruby/core/exception/backtrace_locations_spec.rb
  3. +9 −1 spec/ruby/core/exception/fixtures/common.rb
21 changes: 16 additions & 5 deletions core/src/main/java/org/jruby/RubyException.java
Original file line number Diff line number Diff line change
@@ -107,10 +107,19 @@ private void setBacktrace(IRubyObject obj) {

@JRubyMethod(omit = true)
public IRubyObject backtrace_locations(ThreadContext context) {
BacktraceData backtraceData = this.backtraceData;

if (backtraceData == null) return context.nil;

RubyArray backtraceLocations = this.backtraceLocations;

if (backtraceLocations != null) return backtraceLocations;

Ruby runtime = context.runtime;

RubyStackTraceElement[] elements = backtraceData.getBacktrace(runtime);

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

@JRubyMethod(name = "exception", optional = 1, rest = true, meta = true)
@@ -216,6 +225,7 @@ public Object getCause() {

public void setBacktraceData(BacktraceData backtraceData) {
this.backtraceData = backtraceData;
this.backtraceLocations = null; // clear any generated locations
}

public BacktraceData getBacktraceData() {
@@ -232,7 +242,7 @@ public RubyStackTraceElement[] getBacktraceElements() {
public void prepareBacktrace(ThreadContext context, boolean nativeException) {
// if it's null, build a backtrace
if (backtraceData == null) {
backtraceData = context.runtime.getInstanceConfig().getTraceType().getBacktrace(context, nativeException);
setBacktraceData(context.runtime.getInstanceConfig().getTraceType().getBacktrace(context, nativeException));
}
}

@@ -246,12 +256,12 @@ public void prepareBacktrace(ThreadContext context, boolean nativeException) {
public void prepareIntegratedBacktrace(ThreadContext context, StackTraceElement[] javaTrace) {
// if it's null, build a backtrace
if (backtraceData == null) {
backtraceData = context.runtime.getInstanceConfig().getTraceType().getIntegratedBacktrace(context, javaTrace);
setBacktraceData(context.runtime.getInstanceConfig().getTraceType().getIntegratedBacktrace(context, javaTrace));
}
}

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

@@ -275,7 +285,7 @@ public void initBacktrace() {
@SuppressWarnings("deprecated")
public void copySpecialInstanceVariables(IRubyObject clone) {
RubyException exception = (RubyException)clone;
exception.backtraceData = backtraceData;
exception.setBacktraceData(backtraceData);
exception.backtrace = backtrace;
exception.message = message;
}
@@ -413,6 +423,7 @@ public String getMessageAsJavaString() {

private BacktraceData backtraceData;
private IRubyObject backtrace;
private RubyArray backtraceLocations;
IRubyObject message;
IRubyObject cause;

39 changes: 39 additions & 0 deletions spec/ruby/core/exception/backtrace_locations_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/common', __FILE__)

describe "Exception#backtrace_locations" do
before :each do
@backtrace = ExceptionSpecs::Backtrace.backtrace_locations
end

it "returns nil if no backtrace was set" do
Exception.new.backtrace_locations.should be_nil
end

it "returns an Array" do
@backtrace.should be_an_instance_of(Array)
end

it "sets each element to a String" do
@backtrace.each {|l| l.should be_an_instance_of(Thread::Backtrace::Location)}
end

it "produces a backtrace for an exception captured using $!" do
exception = begin
raise
rescue RuntimeError
$!
end

exception.backtrace_locations.first.path.should =~ /backtrace_locations_spec/
end

it "returns an Array that can be updated" do
begin
raise
rescue RuntimeError => e
e.backtrace_locations.unshift "backtrace first"
e.backtrace_locations[0].should == "backtrace first"
end
end
end
10 changes: 9 additions & 1 deletion spec/ruby/core/exception/fixtures/common.rb
Original file line number Diff line number Diff line change
@@ -4,11 +4,19 @@ class Exceptional < Exception; end
class Backtrace
def self.backtrace
begin
raise # Do not move this line or update backtrace_spec.rb
raise # If you move this line, update backtrace_spec.rb
rescue RuntimeError => e
e.backtrace
end
end

def self.backtrace_locations
begin
raise
rescue RuntimeError => e
e.backtrace_locations
end
end
end

class UnExceptional < Exception