summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@github.com>2019-01-09 13:53:48 -0800
committerGitHub <noreply@github.com>2019-01-09 13:53:48 -0800
commit63c94cf4f1a877a84c9bbed2ccabc773f9e56035 (patch)
tree36540abdd3e1e6286f6da14b4674e91c939d93f3
parent8eb0be0d8dfc8d25facb0db078d9c90d753c6c82 (diff)
parente07a9d845410db939c22d357fdcebca5a7b00006 (diff)
downloadpsych-63c94cf4f1a877a84c9bbed2ccabc773f9e56035.zip
Merge pull request #382 from ruby/exception-handling-refactor
Exception backtraces should round trip
-rw-r--r--lib/psych/visitors/to_ruby.rb2
-rw-r--r--lib/psych/visitors/yaml_tree.rb52
-rw-r--r--test/psych/test_exception.rb14
3 files changed, 36 insertions, 32 deletions
diff --git a/lib/psych/visitors/to_ruby.rb b/lib/psych/visitors/to_ruby.rb
index 74a52df..c265acb 100644
--- a/lib/psych/visitors/to_ruby.rb
+++ b/lib/psych/visitors/to_ruby.rb
@@ -252,6 +252,8 @@ module Psych
e = build_exception((resolve_class($1) || class_loader.exception),
h.delete('message'))
+
+ e.set_backtrace h.delete('backtrace') if h.key? 'backtrace'
init_with(e, h, o)
when '!set', 'tag:yaml.org,2002:set'
diff --git a/lib/psych/visitors/yaml_tree.rb b/lib/psych/visitors/yaml_tree.rb
index cfed8f1..62d1d5c 100644
--- a/lib/psych/visitors/yaml_tree.rb
+++ b/lib/psych/visitors/yaml_tree.rb
@@ -181,41 +181,11 @@ module Psych
end
def visit_Exception o
- tag = ['!ruby/exception', o.class.name].join ':'
-
- @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
-
- {
- 'message' => private_iv_get(o, 'mesg'),
- 'backtrace' => private_iv_get(o, 'backtrace'),
- }.each do |k,v|
- next unless v
- @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
- accept v
- end
-
- dump_ivars o
-
- @emitter.end_mapping
+ dump_exception o, private_iv_get(o, 'mesg')
end
def visit_NameError o
- tag = ['!ruby/exception', o.class.name].join ':'
-
- @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
-
- {
- 'message' => o.message.to_s,
- 'backtrace' => private_iv_get(o, 'backtrace'),
- }.each do |k,v|
- next unless v
- @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
- accept v
- end
-
- dump_ivars o
-
- @emitter.end_mapping
+ dump_exception o, o.message.to_s
end
def visit_Regexp o
@@ -492,6 +462,24 @@ module Psych
def dump_list o
end
+ def dump_exception o, msg
+ tag = ['!ruby/exception', o.class.name].join ':'
+
+ @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
+
+ if msg
+ @emitter.scalar 'message', nil, nil, true, false, Nodes::Scalar::ANY
+ accept msg
+ end
+
+ @emitter.scalar 'backtrace', nil, nil, true, false, Nodes::Scalar::ANY
+ accept o.backtrace
+
+ dump_ivars o
+
+ @emitter.end_mapping
+ end
+
def format_time time
if time.utc?
time.strftime("%Y-%m-%d %H:%M:%S.%9N Z")
diff --git a/test/psych/test_exception.rb b/test/psych/test_exception.rb
index df7fd73..e7fc88c 100644
--- a/test/psych/test_exception.rb
+++ b/test/psych/test_exception.rb
@@ -23,6 +23,20 @@ module Psych
$VERBOSE = @orig_verbose
end
+ def make_ex msg = 'oh no!'
+ begin
+ raise msg
+ rescue ::Exception => e
+ e
+ end
+ end
+
+ def test_backtrace
+ err = make_ex
+ new_err = Psych.load(Psych.dump(err))
+ assert_equal err.backtrace, new_err.backtrace
+ end
+
def test_naming_exception
err = String.xxx rescue $!
new_err = Psych.load(Psych.dump(err))