File Coverage

blib/lib/Aspect/Advice/After.pm
Criterion Covered Total %
statement 395 472 83.6
branch 191 278 68.7
condition n/a
subroutine 13 13 100.0
pod n/a
total 599 763 78.5


line stmt bran cond sub pod time code
1             package Aspect::Advice::After;
2              
3 21     21   79 use strict;
  21         26  
  21         505  
4 21     21   71 use warnings;
  21         29  
  21         448  
5              
6             # Added by eilara as hack around caller() core dump
7             # NOTE: Now we've switched to Sub::Uplevel can this be removed? --ADAMK
8 21     21   77 use Carp::Heavy ();
  21         23  
  21         247  
9 21     21   68 use Carp ();
  21         23  
  21         231  
10 21     21   71 use Sub::Uplevel ();
  21         26  
  21         238  
11 21     21   7080 use Aspect::Hook ();
  21         36  
  21         292  
12 21     21   84 use Aspect::Advice ();
  21         25  
  21         239  
13 21     21   7088 use Aspect::Point::After ();
  21         41  
  21         2276  
14              
15             our $VERSION = '0.97_06';
16             our @ISA = 'Aspect::Advice';
17              
18             # NOTE: To simplify debugging of the generated code, all injected string
19             # fragments will be defined in $UPPERCASE, and all lexical variables to be
20             # accessed via the closure will be in $lowercase.
21             sub _install {
22 58     58   90 my $self = shift;
23 58         149 my $pointcut = $self->pointcut;
24 58         189 my $code = $self->code;
25 58         171 my $lexical = $self->lexical;
26              
27             # Get the curried version of the pointcut we will use for the
28             # runtime checks instead of the original.
29             # Because $MATCH_RUN is used in boolean conditionals, if there
30             # is nothing to do the compiler will optimise away the code entirely.
31 58         217 my $curried = $pointcut->curry_runtime;
32 58 100       323 my $compiled = $curried ? $curried->compiled_runtime : undef;
33 58 100       211 my $MATCH_RUN = $compiled ? '$compiled->()' : 1;
34              
35             # When an aspect falls out of scope, we don't attempt to remove
36             # the generated hook code, because it might (for reasons potentially
37             # outside our control) have been recursively hooked several times
38             # by both Aspect and other modules.
39             # Instead, we store an "out of scope" flag that is used to shortcut
40             # past the hook as quickely as possible.
41             # This flag is shared between all the generated hooks for each
42             # installed Aspect.
43             # If the advice is going to last lexical then we don't need to
44             # check or use the $out_of_scope variable.
45 58         92 my $out_of_scope = undef;
46 58 100       121 my $MATCH_DISABLED = $lexical ? '$out_of_scope' : '0';
47              
48             # Find all pointcuts that are statically matched
49             # wrap the method with advice code and install the wrapper
50 58         285 foreach my $name ( $pointcut->match_all ) {
51 71         152 my $NAME = $name; # For completeness
52              
53 21     21   147 no strict 'refs';
  21         45  
  21         1713  
54 71         313 my $original = *$name{CODE};
55 71 50       220 unless ( $original ) {
56 0         0 Carp::croak("Can't wrap non-existent subroutine ", $name);
57             }
58              
59             # Any way to set prototypes other than eval?
60 71         151 my $PROTOTYPE = prototype($original);
61 71 100       236 $PROTOTYPE = defined($PROTOTYPE) ? "($PROTOTYPE)" : '';
62              
63             # Generate the new function
64 21     21   93 no warnings 'redefine';
  21         28  
  21         3720  
65 71 50   18   30977 eval <<"END_PERL"; die $@ if $@;
  71 100       265  
  18 100       2849  
  12 100       24  
  12 100       26  
  3 100       4  
  3 100       10  
  3 50       123  
  3 100       43  
  2 100       11  
  1 100       28  
  2 100       7  
  2 100       35  
  2 100       16  
  3 50       7  
  2 100       2  
  8 50       26  
  5 50       77  
  5 100       12  
  5 100       96  
  5 100       777  
  2 100       6  
  2 100       10  
  4 100       14  
  4 100       57  
  4 50       46  
  3 100       14  
  4 50       7  
  4 50       29  
  4 100       124  
  4 100       57  
  6 100       537  
  3 100       11  
  3 100       8  
  1 100       24  
  1 100       9  
  0 50       0  
  9 100       2352  
  7 50       13  
  7 100       24  
  1 50       1  
  1 100       4  
  1 50       34  
  1 100       18  
  1 100       4  
  3 100       11  
  2 100       3  
  2 100       9  
  2 100       55  
  2 50       8  
  1 100       9  
  6 50       19  
  4 100       9  
  4 100       17  
  4 100       88  
  4 100       58  
  0 100       0  
  0 100       0  
  3 100       14  
  3 100       31  
  3 50       22  
  2 100       24  
  3 0       7  
  3 100       11  
  3 50       82  
  3 50       39  
  4 100       1798  
  4 100       43  
  1 50       3  
  0 50       0  
  0 100       0  
  0 50       0  
  6 50       1400  
  6 0       11  
  6 100       39  
  1 50       2  
  1 50       3  
  1 100       36  
  2 100       40  
  2 50       12  
  2 0       13  
  1 100       110  
  1 50       1  
  1 50       3  
  1 0       16  
  1 100       2  
  6 0       24  
  3 50       6  
  3 50       14  
  3 50       167  
  3 50       58  
  0 0       0  
  0 100       0  
  3 0       15  
  3 50       940  
  7 50       1090  
  4 100       24  
  4 50       9  
  2 50       11  
  2 0       70  
  2 0       32  
  2 50       11  
  2 50       13  
  0 100       0  
  0 50       0  
  0 50       0  
  0 0       0  
  11 100       1472  
  8 50       16  
  10 50       33  
  3 0       6  
  3 0       12  
  3 50       85  
  3 50       36  
  1 100       3  
  1 50       7  
  2 50       7  
  2 0       37  
  2 100       6  
  2 50       10  
  2 50       8  
  7 0       20  
  4 0       12  
  4 50       17  
  4 50       140  
  4 100       63  
  1 50       3  
  1 50       7  
  2 0       6  
  2 100       23  
  3 50       1761  
  3 50       18  
  4 0       8  
  3         10  
  3         98  
  3         69  
  0         0  
  0         0  
  3         14  
  3         39  
  3         22  
  1         9  
  10         2479  
  7         13  
  7         17  
  1         2  
  1         5  
  1         42  
  1         17  
  0         0  
  0         0  
  2         6  
  2         21  
  2         109  
  1         1  
  1         3  
  7         32  
  4         13  
  3         10  
  4         104  
  4         35  
  3         14  
  1         11  
  1         3  
  1         1  
  1         3  
  1         18  
  3         5  
  3         15  
  3         188  
  3         52  
  3         11  
  3         17  
  2         7  
  2         57  
  2         12  
  1         3  
  7         2237  
  6         11  
  6         20  
  1         1  
  1         4  
  1         33  
  1         16  
  1         7  
  0         0  
  0         0  
  0         0  
  1         20  
  1         3  
  1         3  
  4         10  
  3         7  
  3         11  
  3         167  
  3         48  
  2         19  
  0         0  
  1         3  
  1         15  
  2         8  
  2         9  
  2         6  
  2         46  
  2         28  
  2         18  
  1         2  
  1         3  
  2         13  
  1         18  
  1         3  
  1         3  
  4         1317  
  4         7  
  4         10  
  1         2  
  1         4  
  13         2000  
  7         23  
  7         13  
  3         9  
  2         7  
  2         90  
  2         2  
  2         5  
  2         54  
  5         19  
  3         5  
  3         16  
  6         82  
  4         31  
  3         9  
  3         71  
  3         6  
  3         6  
  3         49  
  3         20  
  2         5  
  3         6  
  3         36  
  3         73  
  2         3  
  2         3  
  3         44  
  3         30  
  2         11  
  1         103  
  4         650  
  4         11  
  3         9  
  1         2  
  1         5  
  1         54  
  1         29  
  1         10  
  0         0  
  0         0  
  0         0  
  1         4  
  0         0  
  0         0  
  2         6  
  1         2  
  1         4  
  1         43  
  1         24  
  1         9  
  1         3  
  1         6  
  1         48  
  1         3  
  1         6  
  2         6  
  2         31  
  1         54  
  1         32  
  0         0  
  0         0  
  1         6  
  1         29  
  1         4  
  1         5  
  3         1023  
  3         7  
  3         9  
  1         2  
  1         6  
  1         57  
  1         27  
  1         11  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  2         8  
  1         2  
  1         4  
  1         42  
  1         30  
  0         0  
  0         0  
  1         6  
  1         26  
  1         4  
  1         6  
  1         3  
  1         5  
  1         44  
  1         36  
  1         9  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  3         49  
  3         5  
  3         9  
  1         2  
  1         7  
  1         65  
  1         28  
  0         0  
  0         0  
  1         5  
  1         27  
  1         4  
  1         2  
  1         12  
  2         6  
  1         2  
  1         4  
  1         47  
  1         24  
  1         8  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  1         3  
  1         5  
  1         42  
  1         23  
  1         9  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  3         35  
  3         5  
  3         7  
  1         1  
  1         5  
  1         44  
  1         18  
  0         0  
  0         0  
  1         5  
  1         162  
  1         5  
  1         1  
  1         8  
  2         4  
  1         1  
  1         3  
  1         28  
  1         15  
  1         5  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  1         2  
  1         3  
  1         26  
  1         14  
  1         5  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  3         1039  
  3         286  
  3         8  
  1         1  
  1         6  
  1         36  
  1         17  
  0         0  
  0         0  
  1         4  
  1         16  
  1         8  
  0         0  
  0         0  
  2         5  
  1         2  
  1         3  
  1         31  
  1         16  
  1         4  
  1         6  
  0         0  
  0         0  
  0         0  
  0         0  
  1         3  
  1         4  
  1         35  
  1         16  
  1         3  
  1         8  
  0            
  0            
  0            
  0            
66             package Aspect::Hook;
67              
68             *$NAME = sub $PROTOTYPE {
69             # Is this a lexically scoped hook that has finished
70             goto &\$original if $MATCH_DISABLED;
71              
72             my \$wantarray = wantarray;
73             if ( \$wantarray ) {
74             my \$return = eval { [
75             Sub::Uplevel::uplevel(
76             2, \$original, \@_,
77             )
78             ] };
79              
80             local \$_ = bless {
81             sub_name => \$name,
82             wantarray => \$wantarray,
83             args => \\\@_,
84             return_value => \$return,
85             exception => \$\@,
86             pointcut => \$pointcut,
87             original => \$original,
88             }, 'Aspect::Point::After';
89             unless ( $MATCH_RUN ) {
90             return \@\$return unless \$_->{exception};
91             die \$_->{exception};
92             }
93              
94             # Execute the advice code
95             &\$code(\$_);
96              
97             # Throw the same (or modified) exception
98             my \$exception = \$_->{exception};
99             die \$exception if \$exception;
100              
101             # Get the (potentially) modified return value
102             return \@{\$_->{return_value}};
103             }
104              
105             if ( defined \$wantarray ) {
106             my \$return = eval {
107             Sub::Uplevel::uplevel(
108             2, \$original, \@_,
109             )
110             };
111              
112             local \$_ = bless {
113             sub_name => \$name,
114             wantarray => \$wantarray,
115             args => \\\@_,
116             return_value => \$return,
117             exception => \$\@,
118             pointcut => \$pointcut,
119             original => \$original,
120             }, 'Aspect::Point::After';
121              
122             unless ( $MATCH_RUN ) {
123             return \$return unless \$_->{exception};
124             die \$_->{exception};
125             }
126              
127             # Execute the advice code
128             &\$code(\$_);
129              
130             # Throw the same (or modified) exception
131             my \$exception = \$_->{exception};
132             die \$exception if \$exception;
133              
134             # Return the potentially-modified value
135             return \$_->{return_value};
136              
137             }
138              
139             eval {
140             Sub::Uplevel::uplevel(
141             2, \$original, \@_,
142             )
143             };
144              
145             local \$_ = bless {
146             sub_name => \$name,
147             wantarray => \$wantarray,
148             args => \\\@_,
149             return_value => undef,
150             exception => \$\@,
151             pointcut => \$pointcut,
152             original => \$original,
153             }, 'Aspect::Point::After';
154             unless ( $MATCH_RUN ) {
155             return unless \$_->{exception};
156             die \$_->{exception};
157             }
158              
159             # Execute the advice code
160             &\$code(\$_);
161              
162             # Throw the same (or modified) exception
163             my \$exception = \$_->{exception};
164             die \$exception if \$exception;
165              
166             return;
167             };
168             END_PERL
169 71         276 $self->{installed}++;
170             }
171              
172             # If this will run lexical we don't need a descoping hook
173 58 100       331 return unless $lexical;
174              
175             # Return the lexical descoping hook.
176             # This MUST be stored and run at DESTROY-time by the
177             # parent object calling _install. This is less bullet-proof
178             # than the DESTROY-time self-executing blessed coderef
179 40     40   342 return sub { $out_of_scope = 1 };
  40         207  
180             }
181              
182             1;
183              
184             __END__