File Coverage

blib/lib/Devel/Confess/_Util.pm
Criterion Covered Total %
statement 34 38 89.4
branch 3 4 75.0
condition 2 5 40.0
subroutine 13 15 86.6
pod n/a
total 52 62 83.8


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