line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Aspect::Point; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=pod |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 NAME |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
Aspect::Point - The Join Point context |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 SYNOPSIS |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# An anonymous function suitable for use as advice code |
12
|
|
|
|
|
|
|
# across all advice types (as it uses no limited access methods) |
13
|
|
|
|
|
|
|
my $advice_code = sub { |
14
|
|
|
|
|
|
|
print $_->type; # The advice type ('before') |
15
|
|
|
|
|
|
|
print $_->pointcut; # The matching pointcut ($pointcut) |
16
|
|
|
|
|
|
|
print $_->enclosing; # Access cflow pointcut advice context |
17
|
|
|
|
|
|
|
print $_->sub_name; # The full package_name::sub_name |
18
|
|
|
|
|
|
|
print $_->package_name; # The package name ('Person') |
19
|
|
|
|
|
|
|
print $_->short_name; # The sub name (a get or set method) |
20
|
|
|
|
|
|
|
print $_->self; # 1st parameter to the matching sub |
21
|
|
|
|
|
|
|
print ($_->args)[1]; # 2nd parameter to the matching sub |
22
|
|
|
|
|
|
|
$_->original->(x => 3); # Call matched sub independently |
23
|
|
|
|
|
|
|
$->return_value(4) # Set the return value |
24
|
|
|
|
|
|
|
}; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 DESCRIPTION |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
Advice code is called when the advice pointcut is matched. In this code, |
29
|
|
|
|
|
|
|
there is often a need to access information about the join point context |
30
|
|
|
|
|
|
|
of the advice. Information like: |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
What is the actual sub name matched? |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
What are the parameters in this call that we matched? |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
Sometimes you want to change the context for the matched sub, such as |
37
|
|
|
|
|
|
|
appending a parameter or even stopping the matched sub from being called |
38
|
|
|
|
|
|
|
at all. |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
You do all these things through the C, which is an object |
41
|
|
|
|
|
|
|
that isa L. It is the only parameter provided to the advice |
42
|
|
|
|
|
|
|
code. It provides all the information required about the match context, |
43
|
|
|
|
|
|
|
and allows you to change the behavior of the matched sub. |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
Note: Modifying parameters through the context in the code of an I |
46
|
|
|
|
|
|
|
advice, will have no effect, since the matched sub has already been called. |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
In a future release this will be fixed so that the context for each advice |
49
|
|
|
|
|
|
|
type only responds to the methods relevant to that context, with the rest |
50
|
|
|
|
|
|
|
throwing an exception. |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=head2 Cflows |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
If the pointcut of an advice is composed of at least one C the |
55
|
|
|
|
|
|
|
advice code may require not only the context of the advice, but the join |
56
|
|
|
|
|
|
|
point context of the cflows as well. |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
This is required if you want to find out, for example, what the name of the |
59
|
|
|
|
|
|
|
sub that matched a cflow. In the synopsis example above, which method from |
60
|
|
|
|
|
|
|
C started the chain of calls that eventually reached the get/set |
61
|
|
|
|
|
|
|
on C? |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
You can access cflow context in the synopsis above, by calling: |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
$point->enclosing; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
You get it from the main advice join point by calling a method named after |
68
|
|
|
|
|
|
|
the context key used in the cflow spec (which is "enclosing" if a custom name |
69
|
|
|
|
|
|
|
was not provided, in line with AspectJ terminology). In the synopsis pointcut |
70
|
|
|
|
|
|
|
definition, the cflow part was equivalent to: |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
cflow enclosing => qr/^Company::/ |
73
|
|
|
|
|
|
|
^^^^^^^^^ |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
An L will be created for the cflow, and you can access it |
76
|
|
|
|
|
|
|
using the C method. |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head1 EXAMPLES |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
Print parameters to matched sub: |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
before { |
83
|
|
|
|
|
|
|
print join ',', $_->args; |
84
|
|
|
|
|
|
|
} $pointcut; |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
Append a parameter: |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
before { |
89
|
|
|
|
|
|
|
$_->args( $_->args, 'extra parameter' ); |
90
|
|
|
|
|
|
|
} $pointcut; |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
Don't proceed to matched sub, return 4 instead: |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
before { |
95
|
|
|
|
|
|
|
shift->return_value(4); |
96
|
|
|
|
|
|
|
} $pointcut; |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
Call matched sub again and again until it returns something defined: |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
after { |
101
|
|
|
|
|
|
|
my $point = shift; |
102
|
|
|
|
|
|
|
my $return = $point->return_value; |
103
|
|
|
|
|
|
|
while ( not defined $return ) { |
104
|
|
|
|
|
|
|
$return = $point->original($point->params); |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
$point->return_value($return); |
107
|
|
|
|
|
|
|
} $pointcut; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
Print the name of the C object that started the chain of calls |
110
|
|
|
|
|
|
|
that eventually reached the get/set on C: |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
before { |
113
|
|
|
|
|
|
|
print shift->enclosing->self->name; |
114
|
|
|
|
|
|
|
} $pointcut; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head1 METHODS |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=cut |
119
|
|
|
|
|
|
|
|
120
|
21
|
|
|
21
|
|
79
|
use strict; |
|
21
|
|
|
|
|
29
|
|
|
21
|
|
|
|
|
1057
|
|
121
|
21
|
|
|
21
|
|
100
|
use warnings; |
|
21
|
|
|
|
|
24
|
|
|
21
|
|
|
|
|
482
|
|
122
|
21
|
|
|
21
|
|
97
|
use Carp (); |
|
21
|
|
|
|
|
34
|
|
|
21
|
|
|
|
|
349
|
|
123
|
21
|
|
|
21
|
|
77
|
use Sub::Uplevel (); |
|
21
|
|
|
|
|
32
|
|
|
21
|
|
|
|
|
293
|
|
124
|
21
|
|
|
21
|
|
72
|
use Aspect::Point::Static (); |
|
21
|
|
|
|
|
26
|
|
|
21
|
|
|
|
|
5143
|
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
our $VERSION = '0.97_06'; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
###################################################################### |
133
|
|
|
|
|
|
|
# Constructor and Built-In Accessors |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
# sub new { |
136
|
|
|
|
|
|
|
# my $class = shift; |
137
|
|
|
|
|
|
|
# bless { @_ }, $class; |
138
|
|
|
|
|
|
|
# } |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=pod |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head2 pointcut |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
my $pointcut = $_->pointcut; |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
The C method provides access to the original join point specification |
147
|
|
|
|
|
|
|
(as a tree of L objects) that the current join point matched |
148
|
|
|
|
|
|
|
against. |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
Please note that the pointcut returned is the full and complete pointcut tree, |
151
|
|
|
|
|
|
|
due to the heavy optimisation used on the actual pointcut code when it is run |
152
|
|
|
|
|
|
|
there is no way at the time of advice execution to indicate which specific |
153
|
|
|
|
|
|
|
conditions in the pointcut tree matched and which did not. |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
Returns an object which is a sub-class of L. |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=cut |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
sub pointcut { |
160
|
|
|
|
|
|
|
$_[0]->{pointcut}; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=pod |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head2 sub_name |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
# Prints "Full::Function::name" |
168
|
|
|
|
|
|
|
before { |
169
|
|
|
|
|
|
|
print $_->sub_name . "\n"; |
170
|
|
|
|
|
|
|
} call 'Full::Function::name'; |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
The C method returns a string with the full resolved function name |
173
|
|
|
|
|
|
|
at the join point the advice code is running at. |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=cut |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
sub sub_name { |
178
|
|
|
|
|
|
|
$_[0]->{sub_name}; |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=pod |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=head2 package_name |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# Prints "Just::Package" |
186
|
|
|
|
|
|
|
before { |
187
|
|
|
|
|
|
|
print $_->package_name . "\n"; |
188
|
|
|
|
|
|
|
} call 'Just::Package::name'; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
The C parameter is a convenience wrapper around the C |
191
|
|
|
|
|
|
|
method. Where C will return the fully resolved function name, the |
192
|
|
|
|
|
|
|
C method will return just the namespace of the package of the |
193
|
|
|
|
|
|
|
join point. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=cut |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
sub package_name { |
198
|
0
|
|
|
0
|
1
|
0
|
my $name = $_[0]->{sub_name}; |
199
|
0
|
0
|
|
|
|
0
|
return '' unless $name =~ /::/; |
200
|
0
|
|
|
|
|
0
|
$name =~ s/::[^:]+$//; |
201
|
0
|
|
|
|
|
0
|
return $name; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=pod |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=head2 short_name |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# Prints "name" |
209
|
|
|
|
|
|
|
before { |
210
|
|
|
|
|
|
|
print $_->short_name . "\n"; |
211
|
|
|
|
|
|
|
} call 'Just::Package::name'; |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
The C parameter is a convenience wrapper around the C |
214
|
|
|
|
|
|
|
method. Where C will return the fully resolved function name, the |
215
|
|
|
|
|
|
|
C method will return just the name of the function. |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=cut |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
sub short_name { |
220
|
0
|
|
|
0
|
1
|
0
|
my $name = $_[0]->{sub_name}; |
221
|
0
|
0
|
|
|
|
0
|
return $name unless $name =~ /::/; |
222
|
0
|
|
|
|
|
0
|
$name =~ /::([^:]+)$/; |
223
|
0
|
|
|
|
|
0
|
return $1; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
# Back compatibility |
227
|
|
|
|
|
|
|
BEGIN { |
228
|
21
|
|
|
21
|
|
9546
|
*short_sub_name = *short_name; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=pod |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# Add a parameter to the function call |
234
|
|
|
|
|
|
|
$_->args( $_->args, 'more' ); |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
The C method allows you to get or set the list of parameters to a |
237
|
|
|
|
|
|
|
function. It is the method equivalent of manipulating the C<@_> array. |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
It uses a slightly unusual calling convention based on list context, but does |
240
|
|
|
|
|
|
|
so in a way that allows your advice code to read very naturally. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
To summarise the situation, the three uses of the C method are listed |
243
|
|
|
|
|
|
|
below, along with their C<@_> equivalents. |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
# Get the parameters as a list |
246
|
|
|
|
|
|
|
my @list = $_->args; # my $list = @_; |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# Get the number of parameters |
249
|
|
|
|
|
|
|
my $count = $_->args; # my $count = @_; |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# Set the parameters |
252
|
|
|
|
|
|
|
$_->args( 1, 2, 3 ); # @_ = ( 1, 2, 3 ); |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
As you can see from the above example, when C is called in list context |
255
|
|
|
|
|
|
|
it returns the list of parameters. When it is called in scalar context, it |
256
|
|
|
|
|
|
|
returns the number of parameters. And when it is called in void context, it |
257
|
|
|
|
|
|
|
sets the parameters to the passed values. |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
Although this is somewhat unconventional, it does allow the most common existing |
260
|
|
|
|
|
|
|
uses of the older C method to be changed directly to the new C |
261
|
|
|
|
|
|
|
method (such as the first example above). |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
And unlike the original, you can legally call C in such a way as to set |
264
|
|
|
|
|
|
|
the function parameters to be an empty list (which you could not do with the |
265
|
|
|
|
|
|
|
older C method). |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# Set the function parameters to a null list |
268
|
|
|
|
|
|
|
$_->args(); |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=cut |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
sub args { |
273
|
69
|
100
|
|
69
|
0
|
270
|
if ( defined CORE::wantarray ) { |
274
|
57
|
|
|
|
|
51
|
return @{$_[0]->{args}}; |
|
57
|
|
|
|
|
614
|
|
275
|
|
|
|
|
|
|
} else { |
276
|
12
|
|
|
|
|
36
|
@{$_[0]->{args}} = @_[1..$#_]; |
|
12
|
|
|
|
|
184
|
|
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=pod |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=head2 self |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
after_returning { |
285
|
|
|
|
|
|
|
$_->self->save; |
286
|
|
|
|
|
|
|
} My::Foo::set; |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
The C method is a convenience provided for when you are writing advice |
289
|
|
|
|
|
|
|
that will be working with object-oriented Perl code. It returns the first the |
290
|
|
|
|
|
|
|
first parameter to the method (which should be object), which you can then call |
291
|
|
|
|
|
|
|
methods on. |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
The result is advice code that is much more natural to read, as you can see in |
294
|
|
|
|
|
|
|
the above example where we implement an auto-save feature on the class |
295
|
|
|
|
|
|
|
C, writing the contents to disk every time a value is set without |
296
|
|
|
|
|
|
|
error. |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
At present the C method is implemented fairly naively, if used outside |
299
|
|
|
|
|
|
|
of object-oriented code it will still return something (including C in |
300
|
|
|
|
|
|
|
the case where there were no parameters to the join point function). |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=cut |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
sub self { |
305
|
17
|
|
|
17
|
1
|
86
|
$_[0]->{args}->[0]; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=pod |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=head2 wantarray |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
# Return differently depending on the calling context |
313
|
|
|
|
|
|
|
if ( $_->wantarray ) { |
314
|
|
|
|
|
|
|
$_->return_value(5); |
315
|
|
|
|
|
|
|
} else { |
316
|
|
|
|
|
|
|
$_->return_value(1, 2, 3, 4, 5); |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
The C method returns the L context of the |
320
|
|
|
|
|
|
|
call to the function for the current join point. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
As with the core Perl C function, returns true if the function is |
323
|
|
|
|
|
|
|
being called in list context, false if the function is being called in scalar |
324
|
|
|
|
|
|
|
context, or C if the function is being called in void context. |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
B |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
Prior to L 0.98 the wantarray context of the call to the join point |
329
|
|
|
|
|
|
|
was available not only via the C method, but the advice code itself |
330
|
|
|
|
|
|
|
was called in matching wantarray context to the function call, allowing you to |
331
|
|
|
|
|
|
|
use plain C in the advice code as well. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
As all the other information about the join point was available through methods, |
334
|
|
|
|
|
|
|
having this one piece of metadata available different was becoming an oddity. |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
The C context of the join point is now B available by the |
337
|
|
|
|
|
|
|
C method. |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=cut |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
sub wantarray { |
342
|
|
|
|
|
|
|
$_[0]->{wantarray}; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=pod |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=head2 return_value |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
# Add an extra value to the returned list |
350
|
|
|
|
|
|
|
$_->return_value( $_->return_value, 'thing' ); |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
The C method is used to get or set the return value for the |
353
|
|
|
|
|
|
|
join point function, in a similar way to the normal Perl C keyword. |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
As with the C method, the C method is sensitive to the |
356
|
|
|
|
|
|
|
context in which it is called. |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
When called in list context, the C method returns the join point |
359
|
|
|
|
|
|
|
return value as a list. If the join point is called in scalar context, this will |
360
|
|
|
|
|
|
|
be a single-element list containing the scalar return value. If the join point |
361
|
|
|
|
|
|
|
is called in void context, this will be a null list. |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
When called in scalar context, the C method returns the join |
364
|
|
|
|
|
|
|
point return value as a scalar. If the join point is called in list context, |
365
|
|
|
|
|
|
|
this will be the number of vales in the return list. If the join point is called |
366
|
|
|
|
|
|
|
in void context, this will be C |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
When called in void context, the C method sets the return value |
369
|
|
|
|
|
|
|
for the join point using semantics identical to the C keyword. |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
Because of this change in behavior based on the context in which C |
372
|
|
|
|
|
|
|
is called, you should generally always set C in it's own statement |
373
|
|
|
|
|
|
|
to prevent accidentally calling it in non-void context. |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
# Return null (equivalent to "return;") |
376
|
|
|
|
|
|
|
$_->return_value; |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
In advice types that can be triggered by an exception, or need to determine |
379
|
|
|
|
|
|
|
whether to continue to the join point function, setting a return value via |
380
|
|
|
|
|
|
|
C is seen as implicitly indicating that any exception should be |
381
|
|
|
|
|
|
|
suppressed, or that we do B want to continue to the join point function. |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
When you call the C method this does NOT trigger an immediate |
384
|
|
|
|
|
|
|
C equivalent in the advice code, the lines after C will |
385
|
|
|
|
|
|
|
continue to be executed as normal (to provide an opportunity for cleanup |
386
|
|
|
|
|
|
|
operations to be done and so on). |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
If you use C inside an if/else structure you will still need to |
389
|
|
|
|
|
|
|
do an explicit C if you wish to break out of the advice code. |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
Thus, if you wish to break out of the advice code as well as return with an |
392
|
|
|
|
|
|
|
alternative value, you should do the following. |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
return $_->return_value('value'); |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
This usage of C appears to be contrary to the above instruction |
397
|
|
|
|
|
|
|
that setting the return value should always be done on a standalone line to |
398
|
|
|
|
|
|
|
guarentee void context. |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
However, in Perl the context of the current function is inherited by a function |
401
|
|
|
|
|
|
|
called with return in the manner shown above. Thus the usage of C |
402
|
|
|
|
|
|
|
in this way alone is guarenteed to also set the return value rather than fetch |
403
|
|
|
|
|
|
|
it. |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
=cut |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
sub return_value { |
408
|
78
|
|
|
78
|
1
|
821
|
my $self = shift; |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
# Handle usage in getter form |
411
|
78
|
100
|
|
|
|
195
|
if ( defined CORE::wantarray() ) { |
412
|
|
|
|
|
|
|
# Let the inherent magic of Perl do the work between the |
413
|
|
|
|
|
|
|
# list and scalar context calls to return_value |
414
|
10
|
50
|
|
|
|
44
|
if ( $self->{wantarray} ) { |
|
|
50
|
|
|
|
|
|
415
|
0
|
|
|
|
|
0
|
return @{$self->{return_value}}; |
|
0
|
|
|
|
|
0
|
|
416
|
|
|
|
|
|
|
} elsif ( defined $self->{wantarray} ) { |
417
|
10
|
|
|
|
|
73
|
return $self->{return_value}; |
418
|
|
|
|
|
|
|
} else { |
419
|
0
|
|
|
|
|
0
|
return; |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
# Having provided a return value, suppress any exceptions |
424
|
|
|
|
|
|
|
# and don't proceed if applicable. |
425
|
68
|
|
|
|
|
152
|
$self->{exception} = ''; |
426
|
68
|
|
|
|
|
136
|
$self->{proceed} = 0; |
427
|
68
|
100
|
|
|
|
253
|
if ( $self->{wantarray} ) { |
|
|
50
|
|
|
|
|
|
428
|
4
|
|
|
|
|
7
|
@{$self->{return_value}} = @_; |
|
4
|
|
|
|
|
80
|
|
429
|
|
|
|
|
|
|
} elsif ( defined $self->{wantarray} ) { |
430
|
64
|
|
|
|
|
1125
|
$self->{return_value} = pop; |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
# Accelerate the recommended cflow key |
435
|
|
|
|
|
|
|
sub enclosing { |
436
|
|
|
|
|
|
|
$_[0]->{enclosing}; |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
sub AUTOLOAD { |
440
|
19
|
|
|
19
|
|
1019
|
my $self = shift; |
441
|
19
|
|
|
|
|
27
|
my $key = our $AUTOLOAD; |
442
|
19
|
|
|
|
|
87
|
$key =~ s/^.*:://; |
443
|
19
|
100
|
|
|
|
227
|
Carp::croak "Key does not exist: [$key]" unless exists $self->{$key}; |
444
|
11
|
|
|
|
|
66
|
return $self->{$key}; |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
# Improves performance by not having to send DESTROY calls |
448
|
|
|
|
|
|
|
# through AUTOLOAD, and not having to check for DESTROY in AUTOLOAD. |
449
|
|
|
|
0
|
|
|
sub DESTROY () { } |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
####################################################################### |
456
|
|
|
|
|
|
|
# Back Compatibility |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
sub params_ref { |
459
|
|
|
|
|
|
|
$_[0]->{args}; |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
sub params { |
463
|
0
|
0
|
|
0
|
0
|
|
$_[0]->{args} = [ @_[1..$#_] ] if @_ > 1; |
464
|
|
|
|
|
|
|
return CORE::wantarray |
465
|
0
|
|
|
|
|
|
? @{$_[0]->{args}} |
466
|
0
|
0
|
|
|
|
|
: $_[0]->{args}; |
467
|
|
|
|
|
|
|
} |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
###################################################################### |
474
|
|
|
|
|
|
|
# Optional XS Acceleration |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
BEGIN { |
477
|
21
|
|
|
21
|
|
45
|
local $@; |
478
|
21
|
|
|
21
|
|
1700
|
eval <<'END_PERL'; |
|
21
|
|
|
|
|
106
|
|
|
21
|
|
|
|
|
516
|
|
|
21
|
|
|
|
|
207
|
|
479
|
|
|
|
|
|
|
use Class::XSAccessor 1.08 { |
480
|
|
|
|
|
|
|
replace => 1, |
481
|
|
|
|
|
|
|
getters => { |
482
|
|
|
|
|
|
|
'pointcut' => 'pointcut', |
483
|
|
|
|
|
|
|
'sub_name' => 'sub_name', |
484
|
|
|
|
|
|
|
'wantarray' => 'wantarray', |
485
|
|
|
|
|
|
|
'params_ref' => 'args', |
486
|
|
|
|
|
|
|
'enclosing' => 'enclosing', |
487
|
|
|
|
|
|
|
}, |
488
|
|
|
|
|
|
|
}; |
489
|
|
|
|
|
|
|
END_PERL |
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
1; |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=pod |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
=head1 AUTHORS |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
Adam Kennedy Eadamk@cpan.orgE |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
Marcel GrEnauer Emarcel@cpan.orgE |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
Ran Eilam Eeilara@cpan.orgE |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
=head1 COPYRIGHT |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
Copyright 2001 by Marcel GrEnauer |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
Some parts copyright 2009 - 2011 Adam Kennedy. |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
511
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
=cut |