File Coverage

blib/lib/Mite/Shim.pm
Criterion Covered Total %
statement 235 251 93.6
branch 55 68 80.8
condition 9 19 47.3
subroutine 64 66 96.9
pod 0 20 0.0
total 363 424 85.6


line stmt bran cond sub pod time code
1             # NOTE: Since the intention is to ship this file with a project, this file
2             # cannot have any non-core dependencies.
3             package Mite::Shim;
4 236     236   32208 use 5.008001;
  216         6879  
5 212     195   5444 use strict;
  191         1394  
  191         7734  
6 191     204   3192 use warnings;
  204         1384  
  204         13536  
7 204     179   4136 no strict 'refs';
  179         5572  
  179         106628  
8              
9             if ( $] < 5.009005 ) { require MRO::Compat; }
10             else { require mro; }
11              
12             defined ${^GLOBAL_PHASE}
13             or eval { require Devel::GlobalDestruction; 1 }
14             or do {
15             carp( "WARNING: Devel::GlobalDestruction recommended!" );
16             *Devel::GlobalDestruction::in_global_destruction = sub { undef; };
17             };
18              
19             # Constants
20             sub true () { !!1 }
21             sub false () { !!0 }
22             sub ro () { 'ro' }
23             sub rw () { 'rw' }
24             sub rwp () { 'rwp' }
25             sub lazy () { 'lazy' }
26             sub bare () { 'bare' }
27              
28             # More complicated constants
29             BEGIN {
30 179     179   2338 my @bool = ( \&false, \&true );
31 179         863 *_HAS_AUTOCLEAN = $bool[ 0+!! eval { require namespace::autoclean } ];
  179         106141  
32 179   0     3210871 *STRICT = $bool[ 0+!! ( $ENV{PERL_STRICT} || $ENV{EXTENDED_TESTING} || $ENV{AUTHOR_TESTING} || $ENV{RELEASE_TESTING} ) ];
33             };
34              
35             # Exportable error handlers
36             sub _error_handler {
37 880     880   2996 my ( $func, $message, @args ) = @_;
38 880 100       3114 if ( @args ) {
39 44         10317 require Data::Dumper;
40 44         104490 local $Data::Dumper::Terse = 1;
41 44         290 local $Data::Dumper::Indent = 0;
42             $message = sprintf $message, map {
43 44 50       157 ref($_) ? Data::Dumper::Dumper($_) : defined($_) ? $_ : '(undef)'
  100 50       705  
44             } @args;
45             }
46 880         1708 my $next = do { require Carp; \&{"Carp::$func"} };
  880         5177  
  880         1540  
  880         3706  
47 880         2538 @_ = ( $message );
48 880         136703 goto $next;
49             }
50              
51 0     0 0 0 sub carp { unshift @_, 'carp' ; goto \&_error_handler }
  0         0  
52 880     880 0 3006 sub croak { unshift @_, 'croak' ; goto \&_error_handler }
  880         4023  
53 0     0 0 0 sub confess { unshift @_, 'confess'; goto \&_error_handler }
  0         0  
54              
55             # Exportable guard function
56             {
57             my $GUARD_PACKAGE = __PACKAGE__ . '::Guard';
58 261 100   261   4290 *{"$GUARD_PACKAGE\::DESTROY"} = sub { $_[0][0] or $_[0][1]->() };
59 1     1   3 *{"$GUARD_PACKAGE\::restore"} = sub { $_[0]->DESTROY; $_[0][0] = true };
  1         3  
60 1     1   5 *{"$GUARD_PACKAGE\::dismiss"} = sub { $_[0][0] = true };
61 3     3   23 *{"$GUARD_PACKAGE\::peek"} = sub { $_[0][2] };
62 260     260   2278 *guard = sub (&) { bless [ 0, @_ ] => $GUARD_PACKAGE };
63             }
64              
65             # Exportable lock and unlock
66             sub _lul {
67 6     6   14 my ( $lul, $ref ) = @_;
68 6 50       17 if ( ref $ref eq 'ARRAY' ) {
69 6         16 &Internals::SvREADONLY( $ref, $lul );
70 6         24 &Internals::SvREADONLY( \$_, $lul ) for @$ref;
71 6         18 return;
72             }
73 0 0       0 if ( ref $ref eq 'HASH' ) {
74 0         0 &Internals::hv_clear_placeholders( $ref );
75 0         0 &Internals::SvREADONLY( $ref, $lul );
76 0         0 &Internals::SvREADONLY( \$_, $lul ) for values %$ref;
77 0         0 return;
78             }
79 0         0 return;
80             }
81              
82             sub lock {
83 2     2 0 5 unshift @_, true;
84 2         8 goto \&_lul;
85             }
86              
87             sub unlock {
88 2     2 0 5 my $ref = shift;
89 2         4 _lul( 0 , $ref );
90 2     2   12 &guard( sub { _lul( 1, $ref ) } );
  2         31  
91             }
92              
93             sub _is_compiling {
94 1947 100   1947   16788 defined $Mite::COMPILING and $Mite::COMPILING eq __PACKAGE__;
95             }
96              
97             sub import {
98 294     294   1726 my $me = shift;
99 294         2441 my %arg = map +( lc($_) => true ), @_;
100 294         2962 my ( $caller, $file ) = caller;
101              
102 294 100       1644 if( _is_compiling() ) {
103 111         826 require Mite::Project;
104 111         805 'Mite::Project'->default->inject_mite_functions(
105             'package' => $caller,
106             'file' => $file,
107             'arg' => \%arg,
108             'shim' => $me,
109             );
110             }
111             else {
112             # Changes to this filename must be coordinated with Mite::Compiled
113 183         1388 my $mite_file = $file . '.mite.pm';
114 183         3860 local @INC = ( '.', @INC );
115 183         799 local $@;
116 183 50       799 if ( not eval { require $mite_file; 1 } ) {
  183         86671  
  183         6791  
117 0         0 my $e = $@;
118 0         0 croak "Compiled Mite file ($mite_file) for $file is missing or an error occurred loading it: $e";
119             }
120             }
121              
122 294         4020 'warnings'->import;
123 294         2193 'strict'->import;
124             'namespace::autoclean'->import( -cleanee => $caller )
125 294 100       6106 if _HAS_AUTOCLEAN && !$arg{'-unclean'};
126             }
127              
128             {
129             my ( $cb_before, $cb_after );
130             sub _finalize_application_roletiny {
131 2     2   6 my ( $me, $role, $caller, $args ) = @_;
132 2 100       4 if ( $INC{'Role/Hooks.pm'} ) {
133 1   50     6 $cb_before ||= \%Role::Hooks::CALLBACKS_BEFORE_APPLY;
134 1   50     5 $cb_after ||= \%Role::Hooks::CALLBACKS_AFTER_APPLY;
135             }
136 2 100       5 if ( $cb_before ) {
137 1 50       2 $_->( $role, $caller ) for @{ $cb_before->{$role} || [] };
  1         5  
138             }
139 2         12 'Role::Tiny'->_check_requires( $caller, $role );
140 2         23 my $info = $Role::Tiny::INFO{$role};
141 2 100       5 for ( @{ $info->{modifiers} || [] } ) {
  2         12  
142 2         5 my @args = @$_;
143 2         3 my $modification = shift @args;
144 2         4 my $handler = "HANDLE_$modification";
145 2         9 $me->$handler( $caller, undef, @args );
146             }
147 2 100       7 if ( $cb_after ) {
148 1 50       2 $_->( $role, $caller ) for @{ $cb_after->{$role} || [] };
  1         10  
149             }
150 2         22 return;
151             }
152              
153             # Usage: $me, $caller, @with_args
154             sub HANDLE_with {
155 139     139 0 709 my ( $me, $caller ) = ( shift, shift );
156 139         732 while ( @_ ) {
157 853         1846 my $role = shift;
158 853 100       2253 my $args = ref($_[0]) ? shift : undef;
159 853 100 100     3089 if ( $INC{'Role/Tiny.pm'} and 'Role::Tiny'->is_role( $role ) ) {
160 2         24 $me->_finalize_application_roletiny( $role, $caller, $args );
161             }
162             else {
163 851         8146 $role->__FINALIZE_APPLICATION__( $caller, $args );
164             }
165             }
166 136         533 return;
167             }
168             }
169              
170             # Usage: $me, $caller, $keyword, @has_args
171             sub HANDLE_has {
172 5817     5817 0 19690 my ( $me, $caller, $keyword, $names ) = ( shift, shift, shift, shift );
173 5817 100       17064 if ( @_ % 2 ) {
174 4         8 my $default = shift;
175 4 100       18 unshift @_, ( 'CODE' eq ref( $default ) )
176             ? ( is => lazy, builder => $default )
177             : ( is => ro, default => $default );
178             }
179 5817         50907 my %spec = @_;
180 5817         9882 my $code;
181 5817 100       16010 for my $name ( ref($names) ? @$names : $names ) {
182 6612         12466 $name =~ s/^\+//;
183             'CODE' eq ref( $code = $spec{default} )
184 6612 100       18725 and ${"$caller\::__$name\_DEFAULT__"} = $code;
  1455         8181  
185             'CODE' eq ref( $code = $spec{builder} )
186 6612 100       17185 and *{"$caller\::_build_$name"} = $code;
  1132         8530  
187             'CODE' eq ref( $code = $spec{trigger} )
188 6612 100       14839 and *{"$caller\::_trigger_$name"} = $code;
  109         860  
189             'CODE' eq ref( $code = $spec{clone} )
190 6612 100       15217 and *{"$caller\::_clone_$name"} = $code;
  1         9  
191             }
192 5817         17953 return;
193             }
194              
195             {
196             my $_kind = sub { ${ shift() . '::USES_MITE' } =~ /Role/ ? 'role' : 'class' };
197              
198             sub _get_orig_method {
199 2662     2662   5284 my ( $caller, $name ) = @_;
200 2662         13693 my $orig = $caller->can( $name );
201 2662 50       7831 return $orig if $orig;
202 0         0 croak "Cannot modify method $name in $caller: no such method";
203             }
204              
205             sub _parse_mm_args {
206 4440     4440   6891 my $coderef = pop;
207 4440 100       8230 my $names = [ map { ref($_) ? @$_ : $_ } @_ ];
  4440         18078  
208 4440         11690 ( $names, $coderef );
209             }
210              
211             # Usage: $me, $caller, $caller_kind, @before_args
212             sub HANDLE_before {
213 948     948 0 2922 my ( $me, $caller, $kind ) = ( shift, shift, shift );
214 948         2286 my ( $names, $coderef ) = &_parse_mm_args;
215 948   33     2764 $kind ||= $caller->$_kind;
216 948 100       2816 if ( $kind eq 'role' ) {
217 451         858 push @{"$caller\::METHOD_MODIFIERS"},
  451         3042  
218             [ before => $names, $coderef ];
219 451         1480 return;
220             }
221 497         1891 for my $name ( @$names ) {
222 497         1428 my $orig = _get_orig_method( $caller, $name );
223 497         940 local $@;
224 125 50   125 0 995 eval <<"BEFORE" or die $@;
  125     109   1113  
  125     109   8171  
  109     109   812  
  109     108   354  
  109         6097  
  109         868  
  109         332  
  109         6309  
  109         835  
  109         373  
  109         6283  
  497         40488  
  108         1078  
  108         2683  
225             package $caller;
226             no warnings 'redefine';
227             sub $name {
228             \$coderef->( \@_ );
229             \$orig->( \@_ );
230             }
231             1;
232             BEFORE
233             }
234 497         2399 return;
235             }
236              
237             # Usage: $me, $caller, $caller_kind, @after_args
238             sub HANDLE_after {
239 10     10 0 112 my ( $me, $caller, $kind ) = ( shift, shift, shift );
240 10         221 my ( $names, $coderef ) = &_parse_mm_args;
241 1   33     18 $kind ||= $caller->$_kind;
242 1 50       3 if ( $kind eq 'role' ) {
243 0         0 push @{"$caller\::METHOD_MODIFIERS"},
  0         0  
244             [ after => $names, $coderef ];
245 0         0 return;
246             }
247 1         3 for my $name ( @$names ) {
248 1         5 my $orig = _get_orig_method( $caller, $name );
249 1         2 local $@;
250 1 50       83 eval <<"AFTER" or die $@;
    50          
251             package $caller;
252             no warnings 'redefine';
253             sub $name {
254             my \@r;
255             if ( wantarray ) {
256             \@r = \$orig->( \@_ );
257             }
258             elsif ( defined wantarray ) {
259             \@r = scalar \$orig->( \@_ );
260             }
261             else {
262             \$orig->( \@_ );
263             1;
264             }
265             \$coderef->( \@_ );
266             wantarray ? \@r : \$r[0];
267             }
268             1;
269             AFTER
270             }
271 1         4 return;
272             }
273              
274             # Usage: $me, $caller, $caller_kind, @around_args
275             sub HANDLE_around {
276 3488     3488 0 21621 my ( $me, $caller, $kind ) = ( shift, shift, shift );
277 3488         6744 my ( $names, $coderef ) = &_parse_mm_args;
278 3487   66     8708 $kind ||= $caller->$_kind;
279 3488 100       8343 if ( $kind eq 'role' ) {
280 1325         1913 push @{"$caller\::METHOD_MODIFIERS"},
  1325         5716  
281             [ around => $names, $coderef ];
282 1326         3343 return;
283             }
284 2163         4586 for my $name ( @$names ) {
285 2164         4582 my $orig = _get_orig_method( $caller, $name );
286 2164         3659 local $@;
287 134 100   134 0 1400 eval <<"AROUND" or die $@;
  134     132 0 398  
  134     128 0 9289  
  132     131 0 1044  
  132     130 0 427  
  132     109 0 6986  
  128     109 0 1053  
  128     109 0 407  
  128     109   6669  
  131     109   1983  
  131     109   462  
  131     109   7118  
  130     109   1113  
  130     109   504  
  130     107   7067  
  109     107   849  
  109     107   336  
  109     107   5888  
  109     129   975  
  109     16   323  
  109     16   5842  
  109     110   846  
  109     26   346  
  109     89   5137  
  109     116   812  
  109     335   327  
  109     112   5287  
  109     16   781  
  109     117   351  
  109     81   5550  
  109     34   840  
  109     3   348  
  109         5061  
  109         793  
  109         322  
  109         6050  
  109         891  
  109         364  
  109         5480  
  109         824  
  109         304  
  109         5687  
  107         769  
  107         288  
  107         5310  
  107         893  
  107         322  
  107         6672  
  107         828  
  107         293  
  107         5863  
  107         823  
  107         362  
  107         6406  
  2164         170606  
  129         1271  
  16         166  
  16         196  
  110         1108  
  26         291  
  89         1016  
  116         1169  
  335         3913  
  112         1213  
  16         188  
  117         1196  
  81         3887  
  34         38562  
  4         11696  
  1         130  
288             package $caller;
289             no warnings 'redefine';
290             sub $name {
291             \$coderef->( \$orig, \@_ );
292             }
293             1;
294             AROUND
295             }
296 2162         9050 return;
297             }
298             }
299              
300             # Usage: $me, $caller, $caller_kind, @signature_for_args
301             sub HANDLE_signature_for {
302 557     557 0 2361 my ( $me, $caller, $kind, $name ) = @_;
303 557         15997 $name =~ s/^\+//;
304 557         1278 $me->HANDLE_around( $caller, $kind, $name, ${"$caller\::SIGNATURE_FOR"}{$name} );
  557         18019  
305 557         1549 return;
306             }
307              
308             1;