File Coverage

blib/lib/EJS/Template/JSAdapter.pm
Criterion Covered Total %
statement 29 39 74.3
branch 10 20 50.0
condition n/a
subroutine 6 8 75.0
pod 5 5 100.0
total 50 72 69.4


line stmt bran cond sub pod time code
1 8     8   503 use 5.006;
  8         17  
2 8     8   26 use strict;
  8         340  
  8         134  
3 8     8   25 use warnings;
  8         6  
  8         2527  
4              
5             =head1 NAME
6              
7             EJS::Template::JSAdapter - JavaScript engine adapter for EJS::Template
8              
9             =cut
10              
11             package EJS::Template::JSAdapter;
12              
13             =head1 Variables
14              
15             =head2 @SUPPORTED_ENGINES
16              
17             Supported JavaScript engine classes
18              
19             =over 4
20              
21             =item * L
22              
23             =item * L
24              
25             =item * L
26              
27             =item * L
28              
29             =back
30              
31             =cut
32              
33             our @SUPPORTED_ENGINES = qw(
34             JavaScript::V8
35             JavaScript
36             JavaScript::SpiderMonkey
37             JE
38             );
39              
40             my $default_adapter_class;
41              
42             =head1 Methods
43              
44             =head2 create
45              
46             Instantiates a JavaScript engine adapter object.
47              
48             my $adapter = EJS::Template::JSAdapter->create();
49              
50             If no argument is passed, an engine is selected from the available ones.
51              
52             An explicit engine can also be specified. E.g.
53              
54             my $je_engine = EJS::Template::JSAdapter->create('JE');
55             my $v8_engine = EJS::Template::JSAdapter->create('JavaScript::V8');
56              
57             =cut
58              
59             sub create {
60 58     58 1 89441 my ($class, $engine) = @_;
61            
62 58 100       133 if ($engine) {
    100          
63 30         61 my $adapter_class = $class.'::'.$engine;
64 30         1535 eval "require $adapter_class";
65            
66 30 50       108 if ($@) {
67 0         0 $adapter_class = $engine;
68 0         0 eval "require $adapter_class";
69 0 0       0 die $@ if $@;
70             }
71            
72 30         99 return $adapter_class->new();
73             } elsif ($default_adapter_class) {
74 23         106 return $default_adapter_class->new();
75             } else {
76 5         14 for my $candidate (@SUPPORTED_ENGINES) {
77 20         1086 eval "require $candidate";
78 20 100       397495 next if $@;
79            
80 5         23 my $adapter_class = $class.'::'.$candidate;
81 5         291 eval "require $adapter_class";
82 5 50       29 next if $@;
83            
84 5         9 $default_adapter_class = $adapter_class;
85 5         42 return $adapter_class->new();
86             }
87            
88 0         0 die "No JavaScript engine modules are found. ".
89             "Consider to install JavaScript::V8";
90             }
91             }
92              
93             =head2 new
94              
95             Creates an adapter object.
96              
97             This method should be overridden, and a property named 'engine' is expected to be set up.
98              
99             package Some::Extended::JSAdapter;
100             use base 'EJS::Template::JSAdapter';
101            
102             sub new {
103             my ($class) = @_;
104             my $engine = Some::Underlying::JavaScript::Engine->new();
105             return bless {engine => $engine}, $class;
106             }
107              
108             =cut
109              
110             sub new {
111 0     0 1 0 my ($class) = @_;
112 0         0 return bless {engine => undef}, $class;
113             }
114              
115             =head2 engine
116              
117             Retrieves the underlying engine object.
118              
119             =cut
120              
121             sub engine {
122 257     257 1 223 my ($self) = @_;
123 257         454 return $self->{engine};
124             }
125              
126             =head2 bind
127              
128             Binds variable mapping to JavaScript objects.
129              
130             This method should be overridden in a way that it can be invoked like this:
131              
132             $engine->bind({
133             varname1 => $object1,
134             funcname2 => sub {...},
135             ...
136             });
137              
138             =cut
139              
140             sub bind {
141 0     0 1 0 my ($self, $variables) = @_;
142            
143 0 0       0 if (my $engine = $self->engine) {
144 0 0       0 if ($engine->can('bind')) {
145 0         0 return $engine->bind($variables);
146             }
147             }
148             }
149              
150             =head2 eval
151              
152             Evaluates a JavaScript code.
153              
154             This method should be overridden in a way that it can be invoked like this:
155              
156             $engine->eval('print("ok\n")');
157              
158             =cut
159              
160             sub eval {
161 63     63 1 81 my ($self) = @_;
162            
163 63 50       96 if (my $engine = $self->engine) {
164 63 50       504 if ($engine->can('eval')) {
165 63         160 return $engine->eval($_[1]);
166             }
167             }
168             }
169              
170             =head1 SEE ALSO
171              
172             =over 4
173              
174             =item * L
175              
176             =back
177              
178             =cut
179              
180             1;