File Coverage

blib/lib/Data/JavaScript.pm
Criterion Covered Total %
statement 83 87 95.4
branch 31 38 81.5
condition 8 12 66.6
subroutine 8 9 88.8
pod 2 2 100.0
total 132 148 89.1


line stmt bran cond sub pod time code
1             package Data::JavaScript;
2             require 5;
3 6     6   6584 use vars qw(@EXPORT @EXPORT_OK %OPT $VERSION);
  6         13  
  6         1132  
4             %OPT = (JS=>1.3);
5             $VERSION = 1.13;
6              
7             @EXPORT = qw(jsdump hjsdump);
8             @EXPORT_OK = '__quotemeta';
9              
10 6     6   36 use strict;
  6         8  
  6         1058  
11             require Encode unless $] < 5.007;
12              
13             sub import{
14 7     7   75 my $package = shift;
15              
16 7         105 foreach( @_ ){
17 4 100       26 if(ref($_) eq 'HASH'){
18 2 100       16 $OPT{JS} = $$_{JS} if exists($$_{JS});
19 2 100       37 $OPT{UNDEF} = $$_{UNDEF} if exists($$_{UNDEF});
20             }
21             }
22 7 100 66     86 $OPT{UNDEF} ||= $OPT{JS} > 1.2 ? 'undefined' : q('');
23              
24             #use (); #imports nothing, as package is not supplied
25 7 50       40 if( defined $package ){
26 6     6   39 no strict 'refs';
  6         19  
  6         7005  
27              
28             #Remove options hash
29 7         43 my @import = grep { ! length ref } @_;
  4         26  
30              
31 7 100       24 if( scalar @import ){
32 2 100       4 if( grep {/^:all$/} @import ){
  2         10  
33 1         4 @import = (@EXPORT, @EXPORT_OK) }
34             else{
35             #only user-specfied subset of @EXPORT, @EXPORT_OK
36 1         2 my $q = qr/@{[join('|', @EXPORT, @EXPORT_OK)]}/;
  1         45  
37 1         4 @import = grep { $_ =~ /$q/ } @import;
  1         11  
38             }
39             }
40             else{
41 5         18 @import = @EXPORT;
42             }
43            
44 7         25 my $caller = caller;
45 7         18 for my $func (@import) {
46 14         38 *{"$caller\::$func"} = \&$func;
  14         14960  
47             }
48             }
49             }
50              
51             sub hjsdump {
52 0     0 1 0 my @res = (qq(');
54 0 0       0 wantarray ? @res : join("\n", @res, "");
55             }
56              
57             sub jsdump {
58 18     18 1 3710 my $sym = shift;
59 18 50       55 return "var $sym;\n" unless (@_);
60 18         33 my $elem = shift;
61 18         22 my $undef = shift;
62 18         38 my %dict;
63 18         55 my @res = __jsdump($sym, $elem, \%dict, $undef);
64 18         50 $res[0] = "var " . $res[0];
65 18 50       1211 wantarray ? @res : join("\n", @res, "");
66             }
67              
68              
69             my $QMver;
70             if( $] < 5.007 ){
71             $QMver=<<'EO5';
72             s<([^ \x21-\x5B\x5D-\x7E]+)>{sprintf(join('', '\x%02X' x length$1), unpack'C*',$1)}ge;
73             EO5
74             }
75             else{
76             $QMver=<<'EO58';
77             if( $OPT{JS} >= 1.3 && Encode::is_utf8($_) ){
78             s<([\x{0080}-\x{fffd}]+)>{sprintf '\u%0*v4X', '\u', $1}ge;
79             }
80              
81             {
82             use bytes;
83             s<((?:[^ \x21-\x7E]|(?:\\(?!u)))+)>{sprintf '\x%0*v2X', '\x', $1}ge;
84             }
85             EO58
86             }
87              
88 6 100 100 6   56 eval 'sub __quotemeta {local $_ = shift;' . $QMver . <<'EOQM';
  6     16   12  
  6         46  
  16         89  
  16         740  
  2         30  
  3         20  
  16         20  
  16         93  
  9         71  
  16         41  
  16         36  
  16         26  
  16         28  
  16         59  
  16         28  
  16         87  
89              
90             #This is kind of ugly/inconsistent output for munged UTF-8
91             #tr won't work because we need the escaped \ for JS output
92             s/\\x09/\\t/g;
93             s/\\x0A/\\n/g;
94             s/\\x0D/\\r/g;
95             s/"/\\"/g;
96             s/\\x5C/\\\\/g;
97              
98             #Escape for stupid browsers that stop parsing
99             s%%\\x3C\\x2Fscript\\x3E%g;
100              
101             return $_;
102             }
103             EOQM
104              
105              
106             sub __jsdump {
107 33     33   56 my ($sym, $elem, $dict, $undef) = @_;
108 33         39 my $ref;
109              
110 33 100       93 unless( $ref = ref($elem) ){
111 28 100       68 unless( defined($elem) ){
112 4 100       11 return "$sym = @{[defined($undef) ? $undef : $OPT{UNDEF}]};";
  4         35  
113             }
114              
115             #Translated from $Regexp::Common::RE{num}{real}
116 24 100       163 if( $elem =~ /^[+-]?(?:(?=\d|\.)\d*(?:\.\d{0,})?)$/ ){
117             # (?:[eE][+-]?\d+)?
118 12 100       39 return qq($sym = "$elem";) if $elem =~ /^0\d+$/;
119 11         91 return "$sym = $elem;";
120             }
121              
122             #Fall-back to quoted string
123 12         1029 return qq($sym = ") . __quotemeta($elem) . '";';
124             }
125              
126             #Circular references
127 5 50       27 if ($dict->{$elem}) {
128 0         0 return "$sym = " . $dict->{$elem} . ";";
129             }
130 5         15 $dict->{$elem} = $sym;
131              
132             #isa over ref in case we're given objects
133 5 100 66     38 if( $ref eq 'ARRAY' || UNIVERSAL::isa($elem, 'ARRAY') ){
    50 33        
134 4         16 my @list = ("$sym = new Array;");
135 4         7 my $n = 0;
136 4         9 foreach (@$elem) {
137 12         32 my $newsym = "$sym\[$n]";
138 12         42 push(@list, __jsdump($newsym, $_, $dict, $undef));
139 12         31 $n++;
140             }
141 4         56 return @list;
142             }
143             elsif( $ref eq 'HASH' || UNIVERSAL::isa($elem, 'HASH') ){
144 1         4 my @list = ("$sym = new Object;");
145 1         2 my ($k, $old_k, $v);
146 1         9 foreach $k (sort keys %$elem) {
147 3         100 $k = __quotemeta($old_k=$k);
148 3         8 my $newsym = qq($sym\["$k"]);
149 3         7 push(@list, __jsdump($newsym, $elem->{$old_k}, $dict, $undef));
150             }
151 1         6 return @list;
152             }
153             else{
154 0           return "//Unknown reference: $sym=$ref";
155             }
156             }
157              
158              
159             1;
160             __END__