File Coverage

blib/lib/Object/Deadly.pm
Criterion Covered Total %
statement 84 143 58.7
branch 13 44 29.5
condition n/a
subroutine 22 34 64.7
pod 18 21 85.7
total 137 242 56.6


line stmt bran cond sub pod time code
1             ## no critic (PodSections,UseWarnings,RcsKeywords)
2             package Object::Deadly;
3              
4 3     3   80524 use strict;
  3         11  
  3         162  
5              
6 3     3   17 use Devel::Symdump ();
  3         6  
  3         66  
7 3     3   18 use Scalar::Util qw(refaddr blessed);
  3         8  
  3         432  
8 3     3   3012 use English '$EVAL_ERROR'; ## no critic Interpolation
  3         14398  
  3         19  
9 3     3   3984 use Carp::Clan 5.4;
  3         14898  
  3         22  
10              
11 3     3   499 use vars '$VERSION'; ## no critic Interpolation
  3         6  
  3         645  
12             $VERSION = '0.09';
13              
14             sub new_with {
15              
16             # Public, overridable class method. Returns an _unsafe
17             # object. Accepts a single reference which will be blessed.
18 7     7 1 29 my ( $class, $self ) = @_;
19 7         16 my $implementation_class = "$class\::_unsafe";
20              
21 7         39 return bless $self, $implementation_class;
22             }
23              
24             sub new {
25              
26             # Public, overridable class method. Returns an ${class}::_unsafe
27             # object.
28              
29 21     21 1 5101 my $class = shift @_;
30 21         51 my $implementation_class = "$class\::_unsafe";
31              
32 21         37 my $data;
33 21 100       74 if (@_) {
34 10         23 $data = shift @_;
35             }
36             else {
37              
38             # No sense in loading this unless we actually use it.
39 11         9398 require Devel::StackTrace;
40              
41 11         8488 $data = Devel::StackTrace->new( ignore_package => $class )->as_string;
42 11         7411 $data =~ s/\AT/Object::Deadly t/xm;
43              
44             }
45              
46 21         77 my $self = bless \$data, $implementation_class;
47 3     3   18 no strict 'refs'; ## no critic strict
  3         6  
  3         354  
48 21         37 ${"${implementation_class}::SIMPLE_OBJECTS"}{ refaddr $self} = undef;
  21         206  
49              
50 21         85 return $self;
51             }
52              
53             sub kill_function {
54              
55             # Public, overridable class method. Creates a deadly function in
56             # the ${class}::_unsafe class.
57              
58 204     204 1 284 my ( $class, $func, $death ) = @_;
59 204         270 my $implementation_class = "$class\::_unsafe";
60 204         311 my $function_name = "$implementation_class\::$func";
61 3     3   17 no strict 'refs'; ## no critic Strict
  3         7  
  3         1097  
62              
63 204 100       763 if ( defined &$function_name ) { ## no critic Sigil
64 150         301 return;
65             }
66              
67             # Get a default death if our caller hasn't given us something
68             # special.
69 54 50       175 if ( not defined $death ) {
70 54         113 $death = $class->get_death;
71             }
72              
73 54         72 my $src = <<"PROXY_FOR_DEATH";
74 54         163 #line @{[__LINE__+2]} "@{[__FILE__]}"
  54         206  
75             package $implementation_class;
76             \$death = \$death;
77             sub $func {
78             if ( defined Object::Deadly::blessed \$_[0] ) {
79 0 0   0 1 0  
  9 50   9 0 11474  
  0 0   0 0 0  
  9 50   9 1 9443  
  0 0   0 1 0  
  11 100   11 1 20934  
  0 0   0 1 0  
  0 0   0 1 0  
  9 50   9 1 342  
  9 50   9 1 10653  
  0 0   0 1 0  
  0 0   0 1 0  
  0 0   0 1 0  
  0 0   0 0 0  
  9 50   9 1 13520  
  0 0   0 1 0  
  0 0   0   0  
  0 0   0   0  
80             # Object method calls are fatal.
81             \$death->( \$_[0], "Function $func" );
82 0         0 }
  9         41  
  0         0  
  9         34  
  0         0  
  9         48  
  0         0  
  0         0  
  9         37  
  9         39  
  0         0  
  0         0  
  0         0  
  0         0  
  9         46  
  0         0  
  0         0  
  0         0  
83             else {
84             my \$class = shift \@_;
85 0         0 return \$class->SUPER::$func( \@_ );
  0         0  
  0         0  
  0         0  
  0         0  
  2         5  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
86 0         0 }
  0         0  
  0         0  
  0         0  
  0         0  
  2         19  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
87             }
88             PROXY_FOR_DEATH
89 54         9108 eval $src; ## no critic eval
90 54 50       237 if ($EVAL_ERROR) {
91 0         0 croak "$src\n$EVAL_ERROR";
92             }
93              
94 54         135 return 1;
95             }
96              
97             # A dictionary of stuff that can show up in UNIVERSAL.
98             our @UNIVERSAL_METHODS = (
99              
100             # core perl
101             qw( isa can VERSION ),
102              
103             # core perl 5.9.4+
104             'DOES',
105              
106             # UNIVERSAL.pm
107             'import',
108              
109             # UNIVERSAL/require.pm
110             qw( require use ),
111              
112             # UNIVERSAL/dump.pm
113             qw( blessed dump peek refaddr ),
114              
115             # UNIVERSAL/exports.pm
116             'exports',
117              
118             # UNIVERSAL/moniker.pm
119             qw( moniker plural_moniker ),
120              
121             # UNIVERSAL/which.pm
122             'which',
123              
124             # SUPER.pm
125             qw( super SUPER ),
126             );
127              
128             sub kill_UNIVERSAL {
129              
130             # Public, overridable method call. Creates deadly functions in
131             # ${class}::_unsafe to mask all UNIVERSAL methods.
132              
133 12     12 1 39 my $class = shift @_;
134 12         1821 for my $fqf_function (
135             @UNIVERSAL_METHODS,
136              
137             # Anything else we happen to find
138             Devel::Symdump->rnew('UNIVERSAL')->functions
139             )
140             {
141 201         248 my $function = $fqf_function;
142 201         317 $function =~ s/\AUNIVERSAL:://mx;
143              
144 201         419 $class->kill_function($function);
145             }
146              
147 12         429199 return 1;
148             }
149              
150             sub get_death {
151              
152             # Public, overridable method call. Returns the _death function
153 57     57 1 87 my $class = shift @_;
154              
155 3     3   16 no strict 'refs'; ## no critic Strict
  3         14  
  3         175  
156 57         60 return \&{"${class}::_unsafe::death"};
  57         209  
157             }
158              
159             # Compile and load our implementing classes.
160 3     3   1909 use Object::Deadly::_safe ();
  3         10  
  3         63  
161 3     3   1654 use Object::Deadly::_unsafe ();
  3         9  
  3         135  
162              
163             ## no critic EndWithOne
164             'For the SAKE... of the FUTURE of ALL... mankind... I WILL have
165             a... SMALL sprite!';
166              
167             __END__