File Coverage

blib/lib/EJS/Template/JSAdapter/JavaScript.pm
Criterion Covered Total %
statement 21 60 35.0
branch 1 16 6.2
condition n/a
subroutine 8 13 61.5
pod 2 2 100.0
total 32 91 35.1


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