File Coverage

blib/lib/EJS/Template/JSAdapter/JavaScript.pm
Criterion Covered Total %
statement 21 60 35.0
branch 1 20 5.0
condition n/a
subroutine 8 13 61.5
pod 2 2 100.0
total 32 95 33.6


line stmt bran cond sub pod time code
1 1     1   21 use 5.006;
  1         3  
2 1     1   7 use strict;
  1         2  
  1         27  
3 1     1   5 use warnings;
  1         2  
  1         40  
4              
5             =head1 NAME
6              
7             EJS::Template::JSAdapter::JavaScript
8              
9             =cut
10              
11             package EJS::Template::JSAdapter::JavaScript;
12 1     1   6 use base 'EJS::Template::JSAdapter';
  1         2  
  1         86  
13              
14 1     1   8 use EJS::Template::Util qw(clean_text_ref);
  1         3  
  1         59  
15 1     1   13 use Scalar::Util qw(reftype);
  1         2  
  1         847  
16              
17             our $ENCODE_UTF8 = 1;
18             our $SANITIZE_UTF8 = 1;
19             our $FORCE_UNTAINT = 1;
20             our $PRESERVE_UTF8 = 0;
21              
22             =head1 Methods
23              
24             =head2 new
25              
26             Creates an adapter object.
27              
28             =cut
29              
30             sub new {
31 1     1 1 3 my ($class) = @_;
32 1     1   147 eval 'use JavaScript';
  0         0  
  0         0  
  1         61  
33 1 50       9 die $@ if $@;
34 0           my $runtime = JavaScript::Runtime->new;
35 0           my $engine = $runtime->create_context;
36 0           return bless {runtime => $runtime, engine => $engine}, $class;
37             }
38              
39             =head2 bind
40              
41             Implements the bind method.
42              
43             =cut
44              
45             sub bind {
46 0     0 1   my ($self, $variables) = @_;
47 0           my $engine = $self->engine;
48            
49 0           my $assign_value;
50             my $assign_hash;
51 0           my $assign_array;
52            
53             $assign_value = sub {
54 0     0     my ($parent_path, $name, $source_ref, $in_array) = @_;
55            
56 0           my $reftype = reftype $$source_ref;
57            
58 0 0         my $path = $parent_path ne '' ?
    0          
59             ($in_array ? "$parent_path\[$name]" : "$parent_path.$name") : $name;
60            
61 0 0         if ($reftype) {
62 0 0         if ($reftype eq 'HASH') {
    0          
    0          
    0          
63             #$engine->bind_value($path, {});
64 0           JavaScript::Context::jsc_bind_value($engine, $parent_path, $name, {});
65 0           $assign_hash->($path, $$source_ref);
66             } elsif ($reftype eq 'ARRAY') {
67             #$engine->bind_value($path, []);
68 0           JavaScript::Context::jsc_bind_value($engine, $parent_path, $name, []);
69 0           $assign_array->($path, $$source_ref);
70             } elsif ($reftype eq 'CODE') {
71             #$engine->bind_function($path, $$source_ref);
72 0           JavaScript::Context::jsc_bind_value($engine, $parent_path, $name, $$source_ref);
73             } elsif ($reftype eq 'SCALAR') {
74 0           $assign_value->($parent_path, $name, $$source_ref, $in_array);
75             } else {
76             # ignore?
77             }
78             } else {
79             # NOTE: Do NOT call a subroutine that takes $self as an argument here:
80             # E.g.
81             # some_routine($self);
82             # $self->some_method();
83             # If $self is passed as above, an odd memory leak occurs, detected by
84             # JavaScript::Context::DESTROY
85            
86             #$engine->bind_value($path, $$source_ref);
87 0           my $text_ref = clean_text_ref($source_ref, $ENCODE_UTF8, $SANITIZE_UTF8, $FORCE_UNTAINT);
88 0           JavaScript::Context::jsc_bind_value($engine, $parent_path, $name, $$text_ref);
89             }
90 0           };
91            
92             $assign_hash = sub {
93 0     0     my ($parent_path, $source) = @_;
94            
95 0           for my $name (keys %$source) {
96 0           $assign_value->($parent_path, $name, \$source->{$name});
97             }
98 0           };
99            
100             $assign_array = sub {
101 0     0     my ($parent_path, $source) = @_;
102 0           my $len = scalar(@$source);
103            
104 0           for (my $i = 0; $i < $len; $i++) {
105 0           $assign_value->($parent_path, $i, \$source->[$i], 1);
106             }
107 0           };
108            
109 0           $assign_hash->('', $variables);
110 0           return $engine;
111             }
112              
113             sub DESTROY {
114 0     0     my ($self) = @_;
115 0 0         $self->{engine}->_destroy() if $self->{engine};
116 0 0         $self->{runtime}->_destroy() if $self->{runtime};
117 0           delete $self->{engine};
118 0           delete $self->{runtime};
119             }
120              
121             =head1 SEE ALSO
122              
123             =over 4
124              
125             =item * L
126              
127             =item * L
128              
129             =item * L
130              
131             =back
132              
133             =cut
134              
135             1;