document Perl 5.14.0 fixed $@ clobbering in DESTROY
[p5sagit/Try-Tiny.git] / lib / Try / Tiny.pm
index 90963b0..501b006 100644 (file)
@@ -1,8 +1,8 @@
 package Try::Tiny;
 use 5.006;
-# ABSTRACT: minimal try/catch with proper preservation of $@
+# ABSTRACT: Minimal try/catch with proper preservation of $@
 
-our $VERSION = '0.25';
+our $VERSION = '0.29';
 
 use strict;
 use warnings;
@@ -29,7 +29,7 @@ BEGIN {
   *_HAS_SUBNAME = ($su || $sn) ? sub(){1} : sub(){0};
 }
 
-our @_finally_guards;
+my %_finally_guards;
 
 # Need to prototype as @ not $$ because of the way Perl evaluates the prototype.
 # Keeping it at $$ means you only ever get 1 sub because we need to eval in a list
@@ -70,16 +70,17 @@ sub try (&;@) {
   # $catch->();
 
   # name the blocks if we have Sub::Name installed
-  my $caller = caller;
-  _subname("${caller}::try {...} " => $try)
+  _subname(caller().'::try {...} ' => $try)
     if _HAS_SUBNAME;
 
   # set up scope guards to invoke the finally blocks at the end.
-  # this should really be a lexical variable instead of our/local but that
-  # causes issues with perls < 5.20 due to perl rt#119311
-  local @_finally_guards =
+  # this should really be a function scope lexical variable instead of
+  # file scope + local but that causes issues with perls < 5.20 due to
+  # perl rt#119311
+  local $_finally_guards{guards} = [
     map { Try::Tiny::ScopeGuard->_new($_) }
-    @finally;
+    @finally
+  ];
 
   # save the value of $@ so we can set $@ back to it in the beginning of the eval
   # and restore $@ after the eval finishes
@@ -112,7 +113,7 @@ sub try (&;@) {
   # destructor overwrote $@ as the eval was unwinding.
   if ( $failed ) {
     # pass $error to the finally blocks
-    push @$_, $error for @_finally_guards;
+    push @$_, $error for @{$_finally_guards{guards}};
 
     # if we got an error, invoke the catch block.
     if ( $catch ) {
@@ -138,8 +139,7 @@ sub catch (&;@) {
 
   croak 'Useless bare catch()' unless wantarray;
 
-  my $caller = caller;
-  _subname("${caller}::catch {...} " => $block)
+  _subname(caller().'::catch {...} ' => $block)
     if _HAS_SUBNAME;
   return (
     bless(\$block, 'Try::Tiny::Catch'),
@@ -152,8 +152,7 @@ sub finally (&;@) {
 
   croak 'Useless bare finally()' unless wantarray;
 
-  my $caller = caller;
-  _subname("${caller}::finally {...} " => $block)
+  _subname(caller().'::finally {...} ' => $block)
     if _HAS_SUBNAME;
   return (
     bless(\$block, 'Try::Tiny::Finally'),
@@ -165,7 +164,7 @@ sub finally (&;@) {
   package # hide from PAUSE
     Try::Tiny::ScopeGuard;
 
-  use constant UNSTABLE_DOLLARAT => ($] < '5.013002') ? 1 : 0;
+  use constant UNSTABLE_DOLLARAT => ("$]" < '5.013002') ? 1 : 0;
 
   sub _new {
     shift;
@@ -387,8 +386,10 @@ not yet handled.
 C<$@> must be properly localized before invoking C<eval> in order to avoid this
 issue.
 
-More specifically, C<$@> is clobbered at the beginning of the C<eval>, which
-also makes it impossible to capture the previous error before you die (for
+More specifically,
+L<before Perl version 5.14.0|perl5140delta/"Exception Handling">
+C<$@> was clobbered at the beginning of the C<eval>, which
+also made 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 (the one
@@ -431,7 +432,7 @@ because due to the previous caveats it may have been unset.
 C<$@> could also be an overloaded error object that evaluates to false, but
 that's asking for trouble anyway.
 
-The classic failure mode is:
+The classic failure mode (fixed in L<Perl 5.14.0|perl5140delta/"Exception Handling">) is:
 
   sub Object::DESTROY {
     eval { ... }
@@ -467,9 +468,11 @@ be sure the C<eval> was aborted due to an error:
 This is because an C<eval> that caught a C<die> will always return a false
 value.
 
-=head1 SHINY SYNTAX
+=head1 ALTERNATE SYNTAX
 
-Using Perl 5.10 you can use L<perlsyn/"Switch statements">.
+Using Perl 5.10 you can use L<perlsyn/"Switch statements"> (but please don't,
+because that syntax has since been deprecated because there was too much
+unexpected magical behaviour).
 
 =for stopwords topicalizer
 
@@ -614,8 +617,8 @@ confusing behavior:
     }
   }
 
-Note that this behavior was changed once again in L<Perl5 version 18
-|https://metacpan.org/module/perldelta#given-now-aliases-the-global-_>.
+Note that this behavior was changed once again in
+L<Perl5 version 18|https://metacpan.org/module/perldelta#given-now-aliases-the-global-_>.
 However, since the entirety of lexical C<$_> is now L<considered experimental
 |https://metacpan.org/module/perldelta#Lexical-_-is-now-experimental>, it
 is unclear whether the new version 18 behavior is final.
@@ -666,9 +669,4 @@ Or read the source:
 
 L<http://web.archive.org/web/20100305133605/http://nothingmuch.woobling.org/talks/yapc_asia_2009/try_tiny.yml>
 
-=head1 VERSION CONTROL
-
-L<http://github.com/doy/try-tiny/>
-
 =cut
-