File Coverage

blib/lib/Eval/Safe/Eval.pm
Criterion Covered Total %
statement 24 50 48.0
branch 1 14 7.1
condition 0 3 0.0
subroutine 8 12 66.6
pod 3 3 100.0
total 36 82 43.9


line stmt bran cond sub pod time code
1             # This is an implementation of Eval::Safe that uses `eval` to execute the user
2             # provided code.
3              
4             package Eval::Safe::Eval;
5              
6 3     3   39 use 5.022;
  3         10  
7 3     3   12 use strict;
  3         5  
  3         46  
8 3     3   10 use warnings;
  3         4  
  3         251  
9              
10 3     3   1093 use parent 'Eval::Safe';
  3         828  
  3         14  
11              
12 3     3   145 use Carp;
  3         5  
  3         132  
13 3     3   1304 use File::Spec::Functions qw(rel2abs);
  3         2321  
  3         1456  
14              
15             # Count the number of Eval::Safe::Eval object created to assign each of them a
16             # specific package name.
17             my $env_count = 0;
18              
19             sub new {
20 2     2 1 8 my ($class, %options) = @_;
21 2         5 my $self = bless \%options, $class;
22 2 50       11 $self->{package} = 'Eval::Safe::Eval::Env'.($env_count++) unless $self->{package};
23 2         10 return $self;
24             }
25              
26             sub DESTROY {
27 2     2   1079 local($., $@, $!, $^E, $?);
28 2         4 my ($this) = @_;
29 2         94 CORE::eval('undef %'.($this->{package}).'::');
30             }
31              
32             sub eval {
33 0     0 1   my ($this, $code) = @_;
34             my $eval_str = sprintf "package %s; %s; %s; %s", $this->{package},
35 0           $this->{strict}, $this->{warnings}, $code;
36 0 0         print {$this->{debug}} "Evaling (eval): '${eval_str}'\n" if $this->{debug};
  0            
37 0           my @ret;
38 0 0         if (not defined wantarray) {
    0          
39 0           CORE::eval($eval_str);
40             } elsif (wantarray) {
41 0           @ret = CORE::eval($eval_str);
42             } else {
43 0           @ret = scalar CORE::eval($eval_str);
44             }
45 0 0 0       print {$this->{debug}} "Eval returned an error: $@" if $this->{debug} && $@;
  0            
46 0           return $this->_wrap_code_refs(\&_wrap_in_eval, @ret);
47             }
48              
49             sub do {
50 0     0 1   my ($this, $file) = @_;
51             # do can open relative paths, but in that case it looks them up in the @INC
52             # directory, which we want to avoid.
53             # We don't use abs_path here to not die (just yet) if the file does not exist.
54 0           my $abs_path = rel2abs($file);
55 0           $this->eval("my \$r = do '${abs_path}'; die \$@ if \$@; \$r");
56             }
57              
58             # To emulate the behavior of the Safe approach (where code returned by eval is
59             # wrapped to trap all exception, we're using this method to wrap code returned
60             # by eval in the same way).
61             sub _wrap_in_eval {
62 0     0     my ($this, $sub) = @_;
63             # When $sub is called, we're executing it in an `eval` and also wrapping all
64             # its returned code in the same way.
65             return sub {
66 0     0     my @ret;
67 0 0         if (not defined wantarray) {
    0          
68 0           eval { $sub->() };
  0            
69             } elsif (wantarray) {
70 0           @ret = eval { $sub->() };
  0            
71             } else {
72 0           @ret = scalar eval { $sub->() };
  0            
73             }
74 0           $this->_wrap_code_refs(\&_wrap_in_eval, @ret)
75 0           };
76             }
77              
78             1;