forked from jdegoes/stax
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathminify-js
executable file
·65 lines (43 loc) · 3.04 KB
/
minify-js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/perl
$|++;
my @includes = ('$Main.init', grep s/^--include=//, @ARGV);
sub d {print STDERR ++$count, ': ', join(' ', @_) || '<empty>', "\n";
wantarray ? @_ : $_[0]}
sub j {join "\n", @_}
sub h {map {$_ => 1} @_}
sub e {my ($xs, $ys) = @_; @$xs == @$ys and not scalar grep $$xs[$_] ne $$ys[$_], 0 .. $#$xs}
sub fix {my ($f, @xs) = @_; my @ys = sort &$f(sort @xs); e(\@xs, \@ys) ? @xs : fix($f, @ys)}
sub uniq {my %h; grep ! $h{$_}++, @_}
sub statics_in {map(/(?:[\.\w\$]+|(?:\[['"][\w\$]+['"]\]))*/go, @_), grep s/\$closure\(([\.\w\$\[\]'"]+),\s*"(\w+)"\)/$1.$2/go, @_}
sub methods_in {map /\.[\w\$]+|\[["'][^"']+["']\]/go, @_}
sub classes_in {map /new\h+([\w\.\$\[\]"']+)/go, @_}
sub roots {fix sub {uniq @_, map /(([\.\w\$\[\]"']+)(?:\.[\w\$]+|\[["'][^"']+["']\]))/go, @_}, @_}
my @pieces = split /^([\$\w\.\[\]"']+)(\h*=\h*(?:function.*?\{(?:\V|\n\h)+\n^\}+;?$|\V*$))/mo, join '', <STDIN>;
# For my own sanity: Add error backtraces to thrown errors. Nobody in their right mind throws bare strings.
s/throw\s+(".*;?$)/throw new Error(\1)/g for @pieces;
# At this point, @pieces looks like this:
# '', 'foo.bar', ' = function () {\n...\n}', 'global = null', 'bif.baz', ' = function (x) {\n...\n}', ...
my %definitions = map @pieces[$_ * 3 + 1, $_ * 3 + 2], 0 .. $#pieces / 3;
my @non_defs = map $pieces[$_ * 3], 0 .. $#pieces / 3;
my @instance = grep /\.prototype\W/o, keys %definitions;
my @static = grep ! /\.prototype\W/o, keys %definitions;
my $extras = sub {my ($base, @xs) = @_; map $definitions{"$base.$_"} ? ($base, "$base.$_") : ($base), @xs};
my $cover = sub {
d 'Following graph links';
my @code = (@_, @definitions{@_});
my @statics = uniq map(&$extras($_, qw/__name__ __interfaces__/), statics_in(@code), classes_in(@code));
# Grab all instance methods that might be mentioned here. We have to include statics, since sometimes a field is assigned the value of a static.
my @resolved_methods = uniq map {my $r = $_; grep(index($_, $r) == length($_) - length($r), @instance, @static)} uniq methods_in @code;
uniq roots @statics, @resolved_methods;
};
my %live_set = h fix($cover, @includes, @non_defs);
print join '', map @pieces[$_ * 3, $live_set{$pieces[$_ * 3 + 1]} ? ($_ * 3 + 1, $_ * 3 + 2) : ()], 0 .. $#pieces / 3;
__END__
=head1 SYNOPSYS
minify-js [--include=x] [--include=y] < input.js > output.js
=head1 DESCRIPTION
This program minifies HaXe-generated JavaScript. It removes unused classes, static methods, and instance methods, though because of the dynamically-typed nature of JavaScript it doesn't
necessarily catch everything. Note that this script doesn't work for JS minification in the general case. It relies on HaXe-formatted output, which is of a very specific form. Each definition
occurs on its own line, and indentation is consistent enough to reflect the structure of the generated code. Neither of these is true for JavaScript in general.
Manually-specified --include options indicate additional root-set definitions; this can be useful if your code is a library without a single entry point.
=cut