# to $failed
my $wantarray = wantarray;
+ # save the value of $@ so we can set $@ back to it in the begining of the eval
+ my $prev_error = $@;
+
my ( @ret, $error, $failed );
# FIXME consider using local $SIG{__DIE__} to accumilate all errors. It's
# failed will be true if the eval dies, because 1 will not be returned
# from the eval body
$failed = not eval {
+ $@ = $prev_error;
# evaluate the try block in the correct context
if ( $wantarray ) {
C<$@> must be properly localized before invoking C<eval> in order to avoid this
issue.
+More specifically, C<$@> is clobbered at the begining of the C<eval>, which
+also makes it impossible to capture the previous error before you die (for
+instance when making exception objects with error stacks).
+
+For this reason C<try> will actually set C<$@> to its previous value (before
+the localization) in the begining of the C<eval> block.
+
=head2 Localizing $@ silently masks errors
Inside an eval block C<die> behaves sort of like:
use strict;
#use warnings;
-use Test::More tests => 19;
+use Test::More tests => 21;
BEGIN { use_ok 'Try::Tiny' };
}
+my $prev;
+
lives_ok {
try {
die "foo";
is( $@, "magic", '$@ untouched' );
is( $_, "other magic", '$_ untouched' );
}
+
+{
+ my $caught;
+
+ {
+ local $@;
+
+ eval { die "bar\n" };
+
+ is( $@, "bar\n", 'previous value of $@' );
+
+ try {
+ die {
+ prev => $@,
+ }
+ } catch {
+ $caught = $_;
+ }
+ }
+
+ is_deeply( $caught, { prev => "bar\n" }, 'previous value of $@ available for capture' );
+}