Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix exception(backtrace=nil) prints nothing #782

Merged
merged 1 commit into from
Nov 25, 2023
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
67 changes: 32 additions & 35 deletions lib/irb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -697,52 +697,49 @@ def encode_with_invalid_byte_sequence(str, enc)
end

def handle_exception(exc)
if exc.backtrace && exc.backtrace[0] =~ /\/irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
st0012 marked this conversation as resolved.
Show resolved Hide resolved
if exc.backtrace[0] =~ /\/irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
!(SyntaxError === exc) && !(EncodingError === exc)
# The backtrace of invalid encoding hash (ex. {"\xAE": 1}) raises EncodingError without lineno.
irb_bug = true
else
irb_bug = false
end

if exc.backtrace
order = nil
if RUBY_VERSION < '3.0.0'
if STDOUT.tty?
message = exc.full_message(order: :bottom)
order = :bottom
else
message = exc.full_message(order: :top)
order = :top
end
else # '3.0.0' <= RUBY_VERSION
if RUBY_VERSION < '3.0.0'
if STDOUT.tty?
message = exc.full_message(order: :bottom)
order = :bottom
else
message = exc.full_message(order: :top)
order = :top
end
message = convert_invalid_byte_sequence(message, exc.message.encoding)
message = encode_with_invalid_byte_sequence(message, IRB.conf[:LC_MESSAGES].encoding) unless message.encoding.to_s.casecmp?(IRB.conf[:LC_MESSAGES].encoding.to_s)
message = message.gsub(/((?:^\t.+$\n)+)/) { |m|
case order
when :top
lines = m.split("\n")
when :bottom
lines = m.split("\n").reverse
end
unless irb_bug
lines = lines.map { |l| @context.workspace.filter_backtrace(l) }.compact
if lines.size > @context.back_trace_limit
omit = lines.size - @context.back_trace_limit
lines = lines[0..(@context.back_trace_limit - 1)]
lines << "\t... %d levels..." % omit
end
end
lines = lines.reverse if order == :bottom
lines.map{ |l| l + "\n" }.join
}
# The "<top (required)>" in "(irb)" may be the top level of IRB so imitate the main object.
message = message.gsub(/\(irb\):(?<num>\d+):in `<(?<frame>top \(required\))>'/) { "(irb):#{$~[:num]}:in `<main>'" }
puts message
else # '3.0.0' <= RUBY_VERSION
message = exc.full_message(order: :top)
order = :top
end
message = convert_invalid_byte_sequence(message, exc.message.encoding)
message = encode_with_invalid_byte_sequence(message, IRB.conf[:LC_MESSAGES].encoding) unless message.encoding.to_s.casecmp?(IRB.conf[:LC_MESSAGES].encoding.to_s)
message = message.gsub(/((?:^\t.+$\n)+)/) { |m|
case order
when :top
lines = m.split("\n")
when :bottom
lines = m.split("\n").reverse
end
unless irb_bug
lines = lines.map { |l| @context.workspace.filter_backtrace(l) }.compact
if lines.size > @context.back_trace_limit
omit = lines.size - @context.back_trace_limit
lines = lines[0..(@context.back_trace_limit - 1)]
lines << "\t... %d levels..." % omit
end
end
lines = lines.reverse if order == :bottom
lines.map{ |l| l + "\n" }.join
}
# The "<top (required)>" in "(irb)" may be the top level of IRB so imitate the main object.
message = message.gsub(/\(irb\):(?<num>\d+):in `<(?<frame>top \(required\))>'/) { "(irb):#{$~[:num]}:in `<main>'" }
puts message
puts 'Maybe IRB bug!' if irb_bug
rescue Exception => handler_exc
begin
Expand Down
7 changes: 2 additions & 5 deletions test/irb/test_raise_exception.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@ module TestIRB
class RaiseExceptionTest < TestCase
def test_raise_exception_with_nil_backtrace
bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<-IRB, /Exception: foo/, [])
e = Exception.new("foo")
puts e.inspect
def e.backtrace; nil; end
raise e
assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<-IRB, /#<Exception: foo>/, [])
raise Exception.new("foo").tap {|e| def e.backtrace; nil; end }
IRB
end

Expand Down
Loading