Peter Michaux wrote:
Hi,
I'm writing a new version of JavaScript::Minification on CPAN. This is
my first CPAN module and first Perl project! If someone is willing to
take a look to see if I've done something terribly wrong packaging the
code I would greatly appreciate any feedback.
Currently the new module is in a subversion repository. If you have
subversion you should be able to check it out and test it with
svn co http://dev.michaux.ca/svn/random/JavaScript-Minifier
cd JavaScript-Minifier
perl MakeFile.PL
make test
1. Makefile.PL: Do you really need to use Perl version 5.008006 to use
this module? Why won't just 5.8, or 5.6 do?
2. README: Replace boilerplate content.
3. POD: section on EXPORT should indicate which subs/variables are
exportable on demand.
4. See attached for test coverage. Quite good for a first effort, and
better than most CPAN distros. However, the excessive, C-ish use of ||
conditions mentioned by Adriano lowers your condition coverage and means
your code is actually less well tested than it may first appear.
5. This is perfectly acceptable for a 0.01. Go ahead and upload it to
CPAN so that others have easier access to it and can send you patches.
Thank you very much.
Jim Keenan
Reading database from /Users/jimk/work/jsm/cover_db
---------------------------- ------ ------ ------ ------ ------ ------ ------
File stmt bran cond sub pod time total
---------------------------- ------ ------ ------ ------ ------ ------ ------
...ib/JavaScript/Minifier.pm 97.3 88.8 79.0 100.0 0.0 100.0 83.9
Total 97.3 88.8 79.0 100.0 0.0 100.0 83.9
---------------------------- ------ ------ ------ ------ ------ ------ ------
Run: t/JavaScript-Minifier.t
Perl version: 5.8.8
OS: darwin
Start: Thu May 24 23:02:16 2007
Finish: Thu May 24 23:02:16 2007
blib/lib/JavaScript/Minifier.pm
line err stmt bran cond sub pod time code
1 package
JavaScript::Minifier;
2
3 1 1 19 use strict;
1 4
1 24
4 1 1 22 use warnings;
1 3
1 20
5
6 require Exporter;
7 our @ISA = qw(Exporter);
8 our @EXPORT_OK =
qw(minify);
9
10 our $VERSION = '1.0';
11
12 #
-----------------------------------------------------------------------------
13
14 sub isAlphanum {
15 *** 327 327 0 974 my $x = shift;
16 #return true if the
character is allowed in identifier.
17 327 100 17422 return (($x ge 'a' &&
$x le 'z') || ($x ge '0' && $x le '9') ||
100
100
100
100
*** 66
*** 66
*** 66
*** 66
18 ($x ge 'A' &&
$x le 'Z') || $x eq '_' || $x eq '$' ||
19 $x eq '\\' ||
ord($x) > 126);
20 }
21
22 sub isSpace {
23 *** 2067 2067 0 13590 my $x = shift;
24 *** 2067 66 31917 return ($x eq ' ' || $x
eq "\t");
25 }
26
27 sub isEndspace {
28 *** 2069 2069 0 5538 my $x = shift;
29 *** 2069 66 51764 return ($x eq "\n" ||
$x eq "\r" || $x eq "\f");
*** 66
30 }
31
32 sub isWhitespace {
33 *** 2067 2067 0 6325 my $x = shift;
34 2067 100 9858 return (isSpace($x) ||
isEndspace($x));
35 }
36
37 # TRICKY: isAt() is the
only "is" function here that checks if argument is defined
38 sub isAt {
39 *** 66 66 0 207 my $x = shift;
40 *** 66 100 66 679 return (defined($x) &&
$x eq '@') ? 1 : 0;
41 }
42
43 # New line characters
before or after these characters can be removed.
44 # Not + - / in this list
because they require special care.
45 sub isInfix {
46 *** 58 58 0 186 my $x = shift;
47 *** 58 33 4022 return ($x eq ',' || $x
eq '=' || $x eq ';' ||
*** 66
*** 66
*** 66
*** 66
*** 66
*** 66
*** 66
*** 66
*** 66
100
48 $x eq '?' || $x
eq ':' || $x eq '&' ||
49 $x eq '%' || $x
eq '*' || $x eq '|' ||
50 $x eq '<' || $x
eq '>' || $x eq "\n");
51 }
52
53 # New line characters
after these characters can be removed.
54 sub isPrefix {
55 *** 31 31 0 117 my $x = shift;
56 *** 31 33 837 return ($x eq '{' || $x
eq '(' || $x eq '[' || $x eq '!' || isInfix($x));
*** 33
*** 33
*** 66
57 }
58
59 # New line characters
before these characters can removed.
60 sub isPostfix {
61 *** 41 41 0 136 my $x = shift;
62 41 100 809 return ($x eq ']' || $x
eq '}' || $x eq ')' || isInfix($x));
100
*** 66
63 }
64
65 #
-----------------------------------------------------------------------------
66
67 sub _get {
68 1251 1251 3348 my $s = shift;
69 1251 100 5153 if ($s->{inputType} eq
'file') {
*** 50
70 1182 38922 return
getc($s->{input});
71 }
72 elsif ($s->{inputType}
eq 'string') {
73 69 100 309 if ($s->{'inputPos'}
< length($s->{input})) {
74 57 662 return
substr($s->{input}, $s->{inputPos}++, 1);
75 }
76 else { # Simulate
getc() when off the end of the input string.
77 12 101 return undef;
78 }
79 }
80 else {
81 *** 0 0 die "no input";
82 }
83 }
84
85 sub _put {
86 620 620 1768 my $s = shift;
87 620 1540 my $x = shift;
88 620 4186 my $outfile =
($s->{outfile});
89 620 100 5667 if
(defined($s->{outfile})) {
90 587 4549 print $outfile $x;
91 }
92 else {
93 33 147 $s->{output} .= $x;
94 }
95 }
96
97 #
-----------------------------------------------------------------------------
98
99 # print a
100 # move b to a
101 # move c to b
102 # move d to c
103 # new d
104 #
105 # i.e. print a and advance
106 sub action1 {
107 *** 454 454 0 1202 my $s = shift;
108 454 100 1699 if
(!isWhitespace($s->{a})) {
109 375 1433 $s->{lastnws} =
$s->{a};
110 }
111 454 3384 $s->{last} = $s->{a};
112 454 1612 action2($s);
113 }
114
115 # sneeky output $s->{a}
for comments
116 sub action2 {
117 *** 619 619 0 1552 my $s = shift;
118 619 2464 _put($s, $s->{a});
119 619 3447 action3($s);
120 }
121
122 # move b to a
123 # move c to b
124 # move d to c
125 # new d
126 #
127 # i.e. delete a
128 sub action3 {
129 *** 1093 1093 0 2965 my $s = shift;
130 1093 3605 $s->{a} = $s->{b};
131 1093 3679 action4($s);
132 }
133
134 # move c to b
135 # move d to c
136 # new d
137 #
138 # i.e. delete b
139 sub action4 {
140 *** 1190 1190 0 3034 my $s = shift;
141 1190 3805 $s->{b} = $s->{c};
142 1190 3698 $s->{c} = $s->{d};
143 1190 4702 $s->{d} = _get($s);
144 }
145
146 #
-----------------------------------------------------------------------------
147
148 # put string and regexp
literals
149 # when this sub is
called, $s->{a} is on the opening delimiter character
150 sub putLiteral {
151 *** 11 11 0 47 my $s = shift;
152 11 48 my $delimiter =
$s->{a}; # ', " or /
153 11 52 action1($s);
154 *** 11 66 55 do {
155 *** 77 66 824 while
(defined($s->{a}) && $s->{a} eq '\\') { # escape character only escapes only
the next one character
156 11 42 action1($s);
157 11 58 action1($s);
158 }
159 77 270 action1($s);
160 } until ($s->{last} eq
$delimiter || !defined($s->{a}));
161 *** 11 50 79 if ($s->{last} ne
$delimiter) { # ran off end of file before printing the closing delimiter
162 *** 0 0 0 die 'unterminated ' .
($delimiter eq '\'' ? 'single quoted string' : $delimiter eq '"' ? 'double
quoted string' : 'regular expression') . ' literal, stopped';
*** 0
163 }
164 }
165
166 #
-----------------------------------------------------------------------------
167
168 # If $s->{a} is a
whitespace then collapse all following whitespace.
169 # If any of the
whitespace is a new line then ensure $s->{a} is a new line
170 # when this function ends.
171 sub collapseWhitespace {
172 *** 328 328 0 1090 my $s = shift;
173 328 100 12263 while (defined($s->{a})
&& isWhitespace($s->{a}) &&
100
100
174 defined($s->{b})
&& isWhitespace($s->{b})) {
175 97 100 100 603 if
(isEndspace($s->{a}) || isEndspace($s->{b})) {
176 81 248 $s->{a} = "\n";
177 }
178 97 462 action4($s); # delete
b
179 }
180 }
181
182 # Advance $s->{a} to
non-whitespace or end of file.
183 # Doesn't print any of
this whitespace.
184 sub skipWhitespace {
185 *** 198 198 0 696 my $s = shift;
186 198 100 1939 while (defined($s->{a})
&& isWhitespace($s->{a})) {
187 172 789 action3($s);
188 }
189 }
190
191 # Advance $s->{a} to
non-whitespace or end of file
192 # If any of the
whitespace is a new line then print one new line.
193 sub preserveEndspace {
194 *** 102 102 0 331 my $s = shift;
195 102 376 collapseWhitespace($s);
196 102 100 100 1099 if (defined($s->{a}) &&
isEndspace($s->{a}) && defined($s->{b}) && !isPostfix($s->{b}) ) {
100
100
197 27 125 action1($s);
198 }
199 102 627 skipWhitespace($s);
200 }
201
202 sub
onWhitespaceConditionalComment {
203 *** 27 27 0 103 my $s = shift;
204 *** 27 66 216 return
(defined($s->{a}) && isWhitespace($s->{a}) &&
100
100
*** 66
*** 66
*** 66
*** 66
100
205
defined($s->{b}) && $s->{b} eq '/' &&
206
defined($s->{c}) && ($s->{c} eq '/' || $s->{c} eq '*') &&
207
defined($s->{d}) && $s->{d} eq '@');
208 }
209
210 #
-----------------------------------------------------------------------------
211
212 sub minify {
213 *** 14 14 0 454 my %h = @_;
214 # Immediately turn hash
into a hash reference so that notation is the same in this function
215 # as others. Easier
refactoring.
216 14 100 my $s = \%h; # hash
reference for "state". This module is functional programming and the state is
passed between functions.
217
218 # determine if the the
input is a string or a file handle.
219 14 132 my $ref = \$s->{input};
220 *** 14 100 66 396 if (defined($ref) &&
ref($ref) eq 'SCALAR'){
221 3 15 $s->{inputPos} = 0;
222 3 20 $s->{inputType} =
'string';
223 }
224 else {
225 11 124 $s->{inputType} =
'file';
226 }
227
228 # Determine if the
output is to a string or a file.
229 14 100 222 if
(!defined($s->{outfile})) {
230 3 16 $s->{output} = '';
231 }
232
233 # Print the copyright
notice first
234 14 100 144 if ($s->{copyright}) {
235 1 13 _put($s, '/* ' .
$s->{copyright} . ' */');
236 }
237
238 # Initialize the buffer.
239 *** 14 66 47 do {
240 19 127 $s->{a} = _get($s);
241 } while
(defined($s->{a}) && isWhitespace($s->{a}));
242 14 100 $s->{b} = _get($s);
243 14 105 $s->{c} = _get($s);
244 14 113 $s->{d} = _get($s);
245 14 102 $s->{last} = undef; #
assign for safety
246 14 64 $s->{lastnws} = undef;
# assign for safety
247
248 # local variables
249 14 41 my $ccFlag; # marks if
a comment is an Internet Explorer conditional comment and should be printed to
output
250
251 14 122 while
(defined($s->{a})) { # on this line $s->{a} should always be a non-whitespace
character or undef (i.e. end of file)
252
253 *** 355 50 1517 if
(isWhitespace($s->{a})) { # check that this program is running correctly
254 *** 0 0 die 'minifier bug:
minify while loop starting with whitespace, stopped';
255 }
256
257 # Each branch handles
trailing whitespace and ensures $s->{a} is on non-whitespace or undef when
branch finishes
258 355 100 100 6351 if ($s->{a} eq '/') {
# a division, comment, or regexp literal
100 100
100 100
100 100
100 100
100 100
100
*** 66
*** 66
259 *** 93 100 66 1946 if
(defined($s->{b}) && $s->{b} eq '/') { # slash-slash comment
*** 100 66
*** 100 33
*** 66
*** 66
260 29 153 $ccFlag =
isAt($s->{c}); # tests in IE7 show no space allowed between slashes and at
symbol
261 *** 29 66 378 do {
262 156 100 686 $ccFlag ?
action2($s) : action3($s);
263 } until
(!defined($s->{a}) || isEndspace($s->{a}));
264 *** 29 50 178 if
(defined($s->{a})) { # $s->{a} is a new line
265 29 100 100 220 if ($ccFlag) {
100 100
266 14 56 action1($s);
# cannot use preserveEndspace($s) here because it might not print the new line
267 14 84
skipWhitespace($s);
268 }
269 elsif
(defined($s->{last}) && !isEndspace($s->{last}) && !isPrefix($s->{last})) {
270 8 37
preserveEndspace($s);
271 }
272 else {
273 7 32
skipWhitespace($s);
274 }
275 }
276 }
277 elsif
(defined($s->{b}) && $s->{b} eq '*') { # slash-star comment
278 37 168 $ccFlag =
isAt($s->{c}); # test in IE7 shows no space allowed between star and at symbol
279 37 100 105 do {
*** 66
280 258 100 1195 $ccFlag ?
action2($s) : action3($s);
281 } until
(!defined($s->{b}) || ($s->{a} eq '*' && $s->{b} eq '/'));
282 *** 37 50 182 if
(defined($s->{b})) { # $s->{a} is asterisk and $s->{b} is foreslash
283 37 100 134 if ($ccFlag) {
284 15 53 action2($s);
# the *
285 15 83 action2($s);
# the /
286 # inside the
conditional comment there may be a missing terminal semi-colon
287 15 89
preserveEndspace($s);
288 }
289 else { # the
comment is being removed
290 22 99 action3($s);
# the *
291 22 124 $s->{a} = '
'; # the /
292 22 95
collapseWhitespace($s);
293 *** 22 100 33 393 if
(defined($s->{last}) && defined($s->{b}) &&
100 100
100
*** 66
100
*** 66
100
*** 66
294
((isAlphanum($s->{last}) && (isAlphanum($s->{b})||$s->{b} eq '.')) ||
295
($s->{last} eq '+' && $s->{b} eq '+') || ($s->{last} eq '-' && $s->{b} eq
'-'))) { # for a situation like 5-/**/-2 or a/**/a
296 # When
entering this block $s->{a} is whitespace.
297 # The
comment represented whitespace that cannot be removed. Therefore replace the
now gone comment with a whitespace.
298 4 18 action1($s);
299 }
300 elsif
(!isPrefix($s->{last})) {
301 7 33
preserveEndspace($s);
302 }
303 else {
304 11 90
skipWhitespace($s);
305 }
306 }
307 }
308 else {
309 *** 0 0 die
'unterminated comment, stopped';
310 }
311 }
312 elsif
(defined($s->{lastnws}) && ($s->{lastnws} eq ')' || $s->{lastnws} eq '.' ||
isAlphanum($s->{lastnws}))) { # division
313 18 113 action1($s);
314 18 108
collapseWhitespace($s);
315 # don't want a
division to become a slash-slash comment with following conditional comment
316 18 100 119
onWhitespaceConditionalComment($s) ? action1($s) : preserveEndspace($s);
317 }
318 else { # regexp
literal
319 9 61 putLiteral($s);
320 9 45
collapseWhitespace($s);
321 # don't want
closing delimiter to become a slash-slash comment with following conditional
comment
322 9 100 74
onWhitespaceConditionalComment($s) ? action1($s) : preserveEndspace($s);
323 }
324 }
325 elsif ($s->{a} eq
'\'' || $s->{a} eq '"' ) { # string literal
326 2 15 putLiteral($s);
327 2 12
preserveEndspace($s);
328 }
329 elsif ($s->{a} eq '+'
|| $s->{a} eq '-') { # careful with + + and - -
330 31 122 action1($s);
331 31 181
collapseWhitespace($s);
332 31 100 100 310 if
(defined($s->{a}) && isWhitespace($s->{a})) {
333 *** 4 100 66 64 (defined($s->{b})
&& $s->{b} eq $s->{last}) ? action1($s) : preserveEndspace($s);
334 }
335 }
336 elsif
(isAlphanum($s->{a})) { # keyword, identifiers, numbers
337 146 551 action1($s);
338 146 778
collapseWhitespace($s);
339 146 100 100 1326 if
(defined($s->{a}) && isWhitespace($s->{a})) {
340 # if $s->{b} is
'.' could be (12 .toString()) which is property invocation. If space removed
becomes decimal point and error.
341 43 100 100 426 (defined($s->{b})
&& (isAlphanum($s->{b}) || $s->{b} eq '.')) ? action1($s) :
preserveEndspace($s);
*** 66
342 }
343 }
344 elsif ($s->{a} eq ']'
|| $s->{a} eq '}' || $s->{a} eq ')') { # no need to be followed by space but
maybe needs following new line
345 18 76 action1($s);
346 18 114
preserveEndspace($s);
347 }
348 elsif
($s->{stripDebug} && $s->{a} eq ';' &&
349
defined($s->{b}) && $s->{b} eq ';' &&
350
defined($s->{c}) && $s->{c} eq ';') {
351 1 7 action3($s); #
delete one of the semi-colons
352 1 7 $s->{a} = '/'; #
replace the other two semi-colons
353 1 9 $s->{b} = '/'; # so
the remainder of line is removed
354 }
355 else { # anything
else just prints and trailing whitespace discarded
356 64 347 action1($s);
357 64 472 skipWhitespace($s);
358 }
359 }
360
361 14 100 397 if
(!defined($s->{outfile})) {
362 3 75 return $s->{output};
363 }
364
365 } # minify()
366
367 #
-----------------------------------------------------------------------------
368
369 1;
370 __END__
Branches
--------
line err % true false branch
----- --- ------ ------ ------ ------
40 100 29 37 defined $x && $x eq '@' ? :
69 100 1182 69 if ($$s{'inputType'} eq 'file') { }
*** 50 69 0 elsif ($$s{'inputType'} eq 'string') { }
73 100 57 12 if ($$s{'inputPos'} < length $$s{'input'}) { }
89 100 587 33 if (defined $$s{'outfile'}) { }
108 100 375 79 if (not isWhitespace($$s{'a'}))
161 *** 50 0 11 if ($$s{'last'} ne $delimiter)
162 *** 0 0 0 $delimiter eq '"' ? :
*** 0 0 0 $delimiter eq q['] ? :
175 100 81 16 if (isEndspace($$s{'a'}) or
isEndspace($$s{'b'}))
196 100 27 75 if (defined $$s{'a'} and isEndspace($$s{'a'})
and defined $$s{'b'} and not isPostfix($$s{'b'}))
220 100 3 11 if (defined $ref and ref $ref eq 'SCALAR') { }
229 100 3 11 if (not defined $$s{'outfile'})
234 100 1 13 if ($$s{'copyright'})
253 *** 50 0 355 if (isWhitespace($$s{'a'}))
258 100 93 262 if ($$s{'a'} eq '/') { }
100 2 260 elsif ($$s{'a'} eq q['] or $$s{'a'} eq '"') { }
100 31 229 elsif ($$s{'a'} eq '+' or $$s{'a'} eq '-') { }
100 146 83 elsif (isAlphanum($$s{'a'})) { }
100 18 65 elsif ($$s{'a'} eq ']' or $$s{'a'} eq '}' or
$$s{'a'} eq ')') { }
100 1 64 elsif ($$s{'stripDebug'} and $$s{'a'} eq ';'
and defined $$s{'b'} and $$s{'b'} eq ';' and defined $$s{'c'} and $$s{'c'} eq
';') { }
259 100 29 64 if (defined $$s{'b'} and $$s{'b'} eq '/') { }
100 37 27 elsif (defined $$s{'b'} and $$s{'b'} eq '*') {
}
100 18 9 elsif (defined $$s{'lastnws'} and
$$s{'lastnws'} eq ')' || $$s{'lastnws'} eq '.' || isAlphanum($$s{'lastnws'})) {
}
262 100 68 88 $ccFlag ? :
264 *** 50 29 0 if (defined $$s{'a'})
265 100 14 15 if ($ccFlag) { }
100 8 7 elsif (defined $$s{'last'} and not
isEndspace($$s{'last'}) and not isPrefix($$s{'last'})) { }
280 100 67 191 $ccFlag ? :
282 *** 50 37 0 if (defined $$s{'b'}) { }
283 100 15 22 if ($ccFlag) { }
293 100 4 18 if (defined $$s{'last'} and defined $$s{'b'}
and isAlphanum($$s{'last'}) && (isAlphanum($$s{'b'}) || $$s{'b'} eq '.') ||
$$s{'last'} eq '+' && $$s{'b'} eq '+' || $$s{'last'} eq '-' && $$s{'b'} eq '-')
{ }
100 7 11 elsif (not isPrefix($$s{'last'})) { }
316 100 2 16 onWhitespaceConditionalComment($s) ? :
322 100 2 7 onWhitespaceConditionalComment($s) ? :
332 100 4 27 if (defined $$s{'a'} and
isWhitespace($$s{'a'}))
333 100 2 2 defined $$s{'b'} && $$s{'b'} eq $$s{'last'} ? :
339 100 43 103 if (defined $$s{'a'} and
isWhitespace($$s{'a'}))
341 100 16 27 defined $$s{'b'} && (isAlphanum($$s{'b'}) ||
$$s{'b'} eq '.') ? :
361 100 3 11 if (not defined $$s{'outfile'})
Conditions
----------
and 3 conditions
line err % !l l&&!r l&&r expr
----- --- ------ ------ ------ ------ ----
17 100 181 11 135 $x ge 'a' && $x le 'z'
100 51 91 50 $x ge '0' && $x le '9'
100 120 21 1 $x ge 'A' && $x le 'Z'
40 *** 66 0 37 29 defined $x && $x eq '@'
155 *** 66 0 77 11 defined $$s{'a'} and $$s{'a'} eq '\\'
173 100 7 155 263 defined $$s{'a'} and
isWhitespace($$s{'a'})
100 162 2 261 defined $$s{'a'} and
isWhitespace($$s{'a'}) and defined $$s{'b'}
100 164 164 97 defined $$s{'a'} and
isWhitespace($$s{'a'}) and defined $$s{'b'} and isWhitespace($$s{'b'})
186 100 9 189 172 defined $$s{'a'} and
isWhitespace($$s{'a'})
196 100 2 58 42 defined $$s{'a'} and
isEndspace($$s{'a'})
100 60 1 41 defined $$s{'a'} and
isEndspace($$s{'a'}) and defined $$s{'b'}
100 61 14 27 defined $$s{'a'} and
isEndspace($$s{'a'}) and defined $$s{'b'} and not isPostfix($$s{'b'})
204 *** 66 0 12 15 defined $$s{'a'} &&
isWhitespace($$s{'a'})
100 12 1 14 defined $$s{'a'} &&
isWhitespace($$s{'a'}) && defined $$s{'b'}
100 13 6 8 defined $$s{'a'} &&
isWhitespace($$s{'a'}) && defined $$s{'b'} && $$s{'b'} eq '/'
*** 66 19 0 8 defined $$s{'a'} &&
isWhitespace($$s{'a'}) && defined $$s{'b'} && $$s{'b'} eq '/' && defined
$$s{'c'}
*** 66 19 0 8 defined $$s{'a'} &&
isWhitespace($$s{'a'}) && defined $$s{'b'} && $$s{'b'} eq '/' && defined
$$s{'c'} && ($$s{'c'} eq '/' || $$s{'c'} eq '*')
*** 66 19 0 8 defined $$s{'a'} &&
isWhitespace($$s{'a'}) && defined $$s{'b'} && $$s{'b'} eq '/' && defined
$$s{'c'} && ($$s{'c'} eq '/' || $$s{'c'} eq '*') && defined $$s{'d'}
100 19 4 4 defined $$s{'a'} &&
isWhitespace($$s{'a'}) && defined $$s{'b'} && $$s{'b'} eq '/' && defined
$$s{'c'} && ($$s{'c'} eq '/' || $$s{'c'} eq '*') && defined $$s{'d'} &&
$$s{'d'} eq '@'
220 *** 66 0 11 3 defined $ref and ref $ref eq 'SCALAR'
239 *** 66 0 14 5 defined $$s{'a'} and
isWhitespace($$s{'a'})
258 100 60 2 3 $$s{'stripDebug'} and $$s{'a'} eq ';'
100 62 1 2 $$s{'stripDebug'} and $$s{'a'} eq ';'
and defined $$s{'b'}
100 63 1 1 $$s{'stripDebug'} and $$s{'a'} eq ';'
and defined $$s{'b'} and $$s{'b'} eq ';'
*** 66 64 0 1 $$s{'stripDebug'} and $$s{'a'} eq ';'
and defined $$s{'b'} and $$s{'b'} eq ';' and defined $$s{'c'}
*** 66 64 0 1 $$s{'stripDebug'} and $$s{'a'} eq ';'
and defined $$s{'b'} and $$s{'b'} eq ';' and defined $$s{'c'} and $$s{'c'} eq
';'
259 *** 66 0 64 29 defined $$s{'b'} and $$s{'b'} eq '/'
*** 66 0 27 37 defined $$s{'b'} and $$s{'b'} eq '*'
*** 66 0 9 18 defined $$s{'lastnws'} and
$$s{'lastnws'} eq ')' || $$s{'lastnws'} eq '.' || isAlphanum($$s{'lastnws'})
265 100 1 1 13 defined $$s{'last'} and not
isEndspace($$s{'last'})
100 2 5 8 defined $$s{'last'} and not
isEndspace($$s{'last'}) and not isPrefix($$s{'last'})
279 100 180 41 37 $$s{'a'} eq '*' and $$s{'b'} eq '/'
293 *** 33 0 0 22 defined $$s{'last'} and defined $$s{'b'}
100 16 4 2 isAlphanum($$s{'last'}) &&
(isAlphanum($$s{'b'}) || $$s{'b'} eq '.')
*** 66 19 0 1 $$s{'last'} eq '+' && $$s{'b'} eq '+'
*** 66 18 0 1 $$s{'last'} eq '-' && $$s{'b'} eq '-'
*** 66 0 18 4 defined $$s{'last'} and defined
$$s{'b'} and isAlphanum($$s{'last'}) && (isAlphanum($$s{'b'}) || $$s{'b'} eq
'.') || $$s{'last'} eq '+' && $$s{'b'} eq '+' || $$s{'last'} eq '-' && $$s{'b'}
eq '-'
332 100 1 26 4 defined $$s{'a'} and
isWhitespace($$s{'a'})
333 *** 66 0 2 2 defined $$s{'b'} && $$s{'b'} eq
$$s{'last'}
339 100 4 99 43 defined $$s{'a'} and
isWhitespace($$s{'a'})
341 *** 66 0 27 16 defined $$s{'b'} &&
(isAlphanum($$s{'b'}) || $$s{'b'} eq '.')
or 3 conditions
line err % l !l&&r !l&&!r expr
----- --- ------ ------ ------ ------ ----
17 100 135 50 142 $x ge 'a' && $x le 'z' || $x ge '0' &&
$x le '9'
100 185 1 141 $x ge 'a' && $x le 'z' || $x ge '0' &&
$x le '9' || $x ge 'A' && $x le 'Z'
*** 66 186 0 141 $x ge 'a' && $x le 'z' || $x ge '0' &&
$x le '9' || $x ge 'A' && $x le 'Z' || $x eq '_'
*** 66 186 0 141 $x ge 'a' && $x le 'z' || $x ge '0' &&
$x le '9' || $x ge 'A' && $x le 'Z' || $x eq '_' || $x eq '$'
*** 66 186 0 141 $x ge 'a' && $x le 'z' || $x ge '0' &&
$x le '9' || $x ge 'A' && $x le 'Z' || $x eq '_' || $x eq '$' || $x eq '\\'
*** 66 186 0 141 $x ge 'a' && $x le 'z' || $x ge '0' &&
$x le '9' || $x ge 'A' && $x le 'Z' || $x eq '_' || $x eq '$' || $x eq '\\' ||
ord $x > 126
24 *** 66 401 0 1666 $x eq ' ' || $x eq "\t"
29 *** 66 430 0 1639 $x eq "\n" || $x eq "\r"
*** 66 430 0 1639 $x eq "\n" || $x eq "\r" || $x eq "\f"
34 100 401 277 1389 isSpace($x) || isEndspace($x)
47 *** 33 0 0 58 $x eq ',' || $x eq '='
*** 66 0 11 47 $x eq ',' || $x eq '=' || $x eq ';'
*** 66 11 0 47 $x eq ',' || $x eq '=' || $x eq ';' ||
$x eq '?'
*** 66 11 0 47 $x eq ',' || $x eq '=' || $x eq ';' ||
$x eq '?' || $x eq ':'
*** 66 11 0 47 $x eq ',' || $x eq '=' || $x eq ';' ||
$x eq '?' || $x eq ':' || $x eq '&'
*** 66 11 0 47 $x eq ',' || $x eq '=' || $x eq ';' ||
$x eq '?' || $x eq ':' || $x eq '&' || $x eq '%'
*** 66 11 0 47 $x eq ',' || $x eq '=' || $x eq ';' ||
$x eq '?' || $x eq ':' || $x eq '&' || $x eq '%' || $x eq '*'
*** 66 11 0 47 $x eq ',' || $x eq '=' || $x eq ';' ||
$x eq '?' || $x eq ':' || $x eq '&' || $x eq '%' || $x eq '*' || $x eq '|'
*** 66 11 0 47 $x eq ',' || $x eq '=' || $x eq ';' ||
$x eq '?' || $x eq ':' || $x eq '&' || $x eq '%' || $x eq '*' || $x eq '|' ||
$x eq '<'
*** 66 11 0 47 $x eq ',' || $x eq '=' || $x eq ';' ||
$x eq '?' || $x eq ':' || $x eq '&' || $x eq '%' || $x eq '*' || $x eq '|' ||
$x eq '<' || $x eq '>'
100 11 5 42 $x eq ',' || $x eq '=' || $x eq ';' ||
$x eq '?' || $x eq ':' || $x eq '&' || $x eq '%' || $x eq '*' || $x eq '|' ||
$x eq '<' || $x eq '>' || $x eq "\n"
56 *** 33 0 0 31 $x eq '{' || $x eq '('
*** 33 0 0 31 $x eq '{' || $x eq '(' || $x eq '['
*** 33 0 0 31 $x eq '{' || $x eq '(' || $x eq '[' ||
$x eq '!'
*** 66 0 16 15 $x eq '{' || $x eq '(' || $x eq '[' ||
$x eq '!' || isInfix($x)
62 100 5 5 31 $x eq ']' || $x eq '}'
100 10 4 27 $x eq ']' || $x eq '}' || $x eq ')'
*** 66 14 0 27 $x eq ']' || $x eq '}' || $x eq ')' ||
isInfix($x)
154 *** 66 11 0 66 $$s{'last'} eq $delimiter or not
defined $$s{'a'}
175 100 61 20 16 isEndspace($$s{'a'}) or
isEndspace($$s{'b'})
204 *** 66 4 4 0 $$s{'c'} eq '/' || $$s{'c'} eq '*'
258 100 1 1 260 $$s{'a'} eq q['] or $$s{'a'} eq '"'
100 15 16 229 $$s{'a'} eq '+' or $$s{'a'} eq '-'
100 6 6 71 $$s{'a'} eq ']' or $$s{'a'} eq '}'
100 12 6 65 $$s{'a'} eq ']' or $$s{'a'} eq '}' or
$$s{'a'} eq ')'
259 *** 33 0 0 27 $$s{'lastnws'} eq ')' || $$s{'lastnws'}
eq '.'
*** 66 0 18 9 $$s{'lastnws'} eq ')' || $$s{'lastnws'}
eq '.' || isAlphanum($$s{'lastnws'})
261 *** 66 0 29 127 not defined $$s{'a'} or
isEndspace($$s{'a'})
279 *** 66 0 37 221 not defined $$s{'b'} or $$s{'a'} eq '*'
and $$s{'b'} eq '/'
293 100 1 1 4 isAlphanum($$s{'b'}) || $$s{'b'} eq '.'
100 2 1 19 isAlphanum($$s{'last'}) &&
(isAlphanum($$s{'b'}) || $$s{'b'} eq '.') || $$s{'last'} eq '+' && $$s{'b'} eq
'+'
100 3 1 18 isAlphanum($$s{'last'}) &&
(isAlphanum($$s{'b'}) || $$s{'b'} eq '.') || $$s{'last'} eq '+' && $$s{'b'} eq
'+' || $$s{'last'} eq '-' && $$s{'b'} eq '-'
341 100 15 1 27 isAlphanum($$s{'b'}) || $$s{'b'} eq '.'
Covered Subroutines
-------------------
Subroutine Count Location
------------------------------ ----- -----------------------------------
BEGIN 1 blib/lib/JavaScript/Minifier.pm:3
BEGIN 1 blib/lib/JavaScript/Minifier.pm:4
_get 1251 blib/lib/JavaScript/Minifier.pm:68
_put 620 blib/lib/JavaScript/Minifier.pm:86
action1 454 blib/lib/JavaScript/Minifier.pm:107
action2 619 blib/lib/JavaScript/Minifier.pm:117
action3 1093 blib/lib/JavaScript/Minifier.pm:129
action4 1190 blib/lib/JavaScript/Minifier.pm:140
collapseWhitespace 328 blib/lib/JavaScript/Minifier.pm:172
isAlphanum 327 blib/lib/JavaScript/Minifier.pm:15
isAt 66 blib/lib/JavaScript/Minifier.pm:39
isEndspace 2069 blib/lib/JavaScript/Minifier.pm:28
isInfix 58 blib/lib/JavaScript/Minifier.pm:46
isPostfix 41 blib/lib/JavaScript/Minifier.pm:61
isPrefix 31 blib/lib/JavaScript/Minifier.pm:55
isSpace 2067 blib/lib/JavaScript/Minifier.pm:23
isWhitespace 2067 blib/lib/JavaScript/Minifier.pm:33
minify 14 blib/lib/JavaScript/Minifier.pm:213
onWhitespaceConditionalComment 27 blib/lib/JavaScript/Minifier.pm:203
preserveEndspace 102 blib/lib/JavaScript/Minifier.pm:194
putLiteral 11 blib/lib/JavaScript/Minifier.pm:151
skipWhitespace 198 blib/lib/JavaScript/Minifier.pm:185