+ "uplevel $code, @args, $context"
+ Executes the code reference $code with arguments @args as if it were
+ located at the subroutine stack frame pointed by $context, effectively
+ fooling "caller" and "die" into believing that the call actually
+ happened higher in the stack. The code is executed in the context of the
+ "uplevel" call, and what it returns is returned as-is by "uplevel".
+
+ sub target {
+ faker(@_);
+ }
+
+ sub faker {
+ uplevel {
+ map { 1 / $_ } @_;
+ } @_ => CALLER(1);
+ }
+
+ my @inverses = target(1, 2, 4); # @inverses contains (0, 0.5, 0.25)
+ my $count = target(1, 2, 4); # $target is 3
+
+ Sub::Uplevel also implements a pure-Perl version of "uplevel". Both are
+ identical, with the following caveats :
+
+ * The Sub::Uplevel implementation of "uplevel" may execute a code
+ reference in the context of any upper stack frame. The Scope::Upper
+ version only allows to uplevel to a subroutine stack frame, and will
+ croak if you try to target an "eval" or a format.
+
+ * Exceptions thrown from the code called by this version of "uplevel"
+ will not be caught by "eval" blocks between the target frame and the
+ uplevel call, while they will for Sub::Uplevel's version. This means
+ that :
+
+ eval {
+ sub {
+ local $@;
+ eval {
+ sub {
+ uplevel { die 'wut' } CALLER(2); # for Scope::Upper
+ # uplevel(3, sub { die 'wut' }) # for Sub::Uplevel
+ }->();
+ };
+ print "inner block: $@";
+ $@ and exit;
+ }->();
+ };
+ print "outer block: $@";
+
+ will print "inner block: wut..." with Sub::Uplevel and "outer block:
+ wut..." with Scope::Upper.
+
+ * Sub::Uplevel globally overrides "CORE::GLOBAL::caller", while
+ Scope::Upper does not.
+
+ A simple wrapper lets you mimic the interface of "uplevel" in
+ Sub::Uplevel :
+
+ use Scope::Upper;
+
+ sub uplevel {
+ my $frame = shift;
+ my $code = shift;
+ my $cxt = Scope::Upper::CALLER($frame);
+ &Scope::Upper::uplevel($code => @_ => $cxt);
+ }
+
+ Albeit the three exceptions listed above, it passes all the tests of
+ Sub::Uplevel.
+