File Coverage

blib/lib/Devel/Confess/_Util.pm
Criterion Covered Total %
statement 35 39 89.7
branch 3 4 75.0
condition 2 5 40.0
subroutine 14 16 87.5
pod n/a
total 54 64 84.3


line stmt bran cond sub pod time code
1             package Devel::Confess::_Util;
2 9     9   159 use 5.006;
  9         24  
3 9     9   41 use strict;
  9         13  
  9         307  
4 9     9   35 use warnings FATAL => 'all';
  9         15  
  9         464  
5 9     9   55 no warnings 'once';
  9         13  
  9         285  
6              
7 9     9   39 use Exporter (); BEGIN { *import = \&Exporter::import }
  9     9   21  
  9         267  
  9         397  
8              
9             our @EXPORT = qw(
10             blessed
11             refaddr
12             weaken
13             longmess
14             _str_val
15             _in_END
16             _can_stringify
17             _can
18             _isa
19             );
20              
21 9     9   41 use Carp ();
  9         15  
  9         144  
22 9     9   3115 use Carp::Heavy ();
  9         761  
  9         236  
23 9     9   43 use Scalar::Util qw(blessed refaddr reftype);
  9         10  
  9         4679  
24              
25             # fake weaken if it isn't available. will cause leaks, but this
26             # is a brute force debugging tool, so we can deal with it.
27             *weaken = defined &Scalar::Util::weaken
28             ? \&Scalar::Util::weaken
29             : sub ($) { 0 };
30              
31 9 50 50 9   48 *longmess = !Carp->VERSION ? eval q{
  9   33 85   12  
  9         753  
  85         349  
  85         267  
  0         0  
  0         0  
  85         19850  
32             package
33             Carp;
34             our (%CarpInternal, %Internal, $CarpLevel);
35             $CarpInternal{Carp}++;
36             $CarpInternal{warnings}++;
37             $Internal{Exporter}++;
38             $Internal{'Exporter::Heavy'}++;
39             sub {
40             my $level = 0;
41             while (1) {
42             my $p = (caller($level))[0] || last;
43             last
44             unless $CarpInternal{$p} || $Internal{$p};
45             $level++;
46             }
47             local $CarpLevel = $CarpLevel + $level;
48             no strict 'refs';
49             local *{"threads::tid"} = \&threads::tid
50             if defined &threads::tid && !defined &{"threads::tid"};
51             &longmess;
52             };
53             } : eval q{
54             package
55             Carp;
56             sub {
57             local $INC{'Carp/Heavy.pm'} = $INC{'Carp/Heavy.pm'} || 1;
58             no strict 'refs';
59             local *{"threads::tid"} = \&threads::tid
60             if defined &threads::tid && !defined &{"threads::tid"};
61             &longmess;
62             };
63             } or die $@;
64              
65             if (defined &Carp::format_arg && $Carp::VERSION < 1.32) {
66             my $format_arg = \&Carp::format_arg;
67             eval q{
68             package
69             Carp;
70             our $in_recurse;
71             $format_arg if 0; # capture
72             no warnings 'redefine';
73             sub format_arg {
74             if (! $in_recurse) {
75             local $SIG{__DIE__} = sub {};
76             local $in_recurse = 1;
77             local $@;
78              
79             my $arg;
80             if (
81             Devel::Confess::_Util::blessed($_[0])
82             && eval { $_[0]->can('CARP_TRACE') }
83             ) {
84             return $_[0]->CARP_TRACE;
85             }
86             elsif (
87             ref $_[0]
88             and our $RefArgFormatter
89             and eval { $arg = $RefArgFormatter->(@_); 1 }
90             ) {
91             return $arg;
92             }
93             }
94             $format_arg->(@_);
95             }
96             1;
97             } or die $@;
98             }
99              
100 9     9   53 eval q{
  9     6   17  
  9         498  
  6         574  
101             sub _str_val {
102             no overloading;
103             "$_[0]";
104             }
105             1;
106             } or eval q{
107             sub _str_val {
108             my $class = &blessed;
109             return "$_[0]" unless defined $class;
110             return sprintf("%s=%s(0x%x)", $class, &reftype, &refaddr);
111             }
112             1;
113             } or die $@;
114              
115             {
116             if (defined ${^GLOBAL_PHASE}) {
117 0     0   0 eval q{
  0     0   0  
118             sub _global_destruction () { ${^GLOBAL_PHASE} eq q[DESTRUCT] }
119             sub _in_END () { ${^GLOBAL_PHASE} eq "END" }
120             1;
121             } or die $@;
122             }
123             else {
124             eval q{
125             # this is slightly a lie, but accurate enough for our purposes
126             our $global_phase = 'RUN';
127              
128             sub _global_destruction () {
129             if ($global_phase ne 'DESTRUCT') {
130             local $SIG{__WARN__} = sub {
131             $global_phase = 'DESTRUCT' if $_[0] =~ /global destruction\.\n\z/
132             };
133             warn 1;
134             }
135             $global_phase eq 'DESTRUCT';
136             }
137              
138             sub _in_END () {
139             if ($global_phase eq 'RUN' && $^S) {
140             # END blocks are FILO so we can't install one to run first.
141             # only way to detect END reliably seems to be by using caller.
142             # I hate this but it seems to be the best available option.
143             # The top two frames will be an eval and the END block.
144             my $i;
145             1 while CORE::caller(++$i);
146             if ($i > 2) {
147             my @top = CORE::caller($i - 1);
148             my @next = CORE::caller($i - 2);
149             if (
150             $top[3] eq '(eval)'
151             && $next[3] =~ /::END$/
152             && $top[2] == $next[2]
153             && $top[1] eq $next[1]
154             && $top[0] eq 'main'
155             && $next[0] eq 'main'
156             ) {
157             $global_phase = 'END';
158             }
159             }
160             }
161             $global_phase eq 'END';
162             }
163             END {
164             $global_phase = 'END';
165             }
166              
167             1;
168             } or die $@;
169             }
170             }
171              
172             if ("$]" < 5.008) {
173             eval q{
174             sub _can_stringify () {
175             my $i = 0;
176             while (my @caller = caller($i++)) {
177             if ($caller[3] eq '(eval)') {
178             return 0;
179             }
180             elsif ($caller[7]) {
181             return 0;
182             }
183             }
184             return 1;
185             }
186             1;
187             } or die $@;
188             }
189             else {
190 61 100   61   438 eval q{
191             sub _can_stringify () {
192             defined $^S && !$^S;
193             }
194             1;
195             } or die $@;
196             }
197              
198             sub _isa;
199             if ($INC{'UNIVERSAL/isa.pm'}) {
200             *__isa = \&UNIVERSAL::isa;
201             eval q{
202             sub _isa {
203             local $UNIVERSAL::isa::recursing = 1;
204             local $UNIVERSAL::isa::_recursing = 1;
205             __isa(@_);
206             }
207             1;
208             } or die $@;
209             }
210             else {
211             *_isa = \&UNIVERSAL::isa;
212             }
213              
214             sub _can;
215             if ($INC{'UNIVERSAL/can.pm'}) {
216             *__can = \&UNIVERSAL::can;
217             eval q{
218             sub _can {
219             local $UNIVERSAL::can::recursing = 1;
220             __can(@_);
221             }
222             1;
223             } or die $@;
224             }
225             else {
226             *_can = \&UNIVERSAL::can;
227             }
228              
229             1;