Compare commits
765 Commits
v2.3.5
...
harmony-v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
514fc68f4f | ||
|
|
478aaab469 | ||
|
|
ab217539e9 | ||
|
|
a942dc07c4 | ||
|
|
a0eaff750d | ||
|
|
57777b6cfa | ||
|
|
858e6c78a4 | ||
|
|
8d205f7f39 | ||
|
|
bc9bfd15a2 | ||
|
|
9fc1c4b3b5 | ||
|
|
c59bf5e8d8 | ||
|
|
d2d3a6e065 | ||
|
|
7755733716 | ||
|
|
b3a987b0df | ||
|
|
88a338f29e | ||
|
|
0b0296eb2a | ||
|
|
872270b149 | ||
|
|
b1c593a041 | ||
|
|
13be50a4a9 | ||
|
|
16cd5d57a5 | ||
|
|
834f9f3924 | ||
|
|
cf0951f726 | ||
|
|
852f78491a | ||
|
|
07734b000a | ||
|
|
85c1cba760 | ||
|
|
229e42cdee | ||
|
|
4e49302916 | ||
|
|
1e51586996 | ||
|
|
d48a3080ac | ||
|
|
26fbeece1c | ||
|
|
8898b8a0fe | ||
|
|
ec64acd2c8 | ||
|
|
ac0b61ed6e | ||
|
|
c06a50f338 | ||
|
|
09f9ae2de9 | ||
|
|
7e6331bb39 | ||
|
|
e275148998 | ||
|
|
974247c8c0 | ||
|
|
a0f4fd390a | ||
|
|
b8b133d91a | ||
|
|
c525a2b190 | ||
|
|
6ffbecb72b | ||
|
|
f0ff6189be | ||
|
|
6b3c49e458 | ||
|
|
f584ca8d07 | ||
|
|
ae4db00991 | ||
|
|
100307ab31 | ||
|
|
148047fbbf | ||
|
|
d11dca3cf9 | ||
|
|
e5badb9541 | ||
|
|
fa668a28b4 | ||
|
|
686a496b1c | ||
|
|
11676f9d72 | ||
|
|
dd31d12a91 | ||
|
|
eb55d8a9bb | ||
|
|
81f1df14d7 | ||
|
|
4bd31607f6 | ||
|
|
7f8d72d9d3 | ||
|
|
1eaa211e09 | ||
|
|
0610c020b1 | ||
|
|
0d7d4918eb | ||
|
|
4728bc73ad | ||
|
|
48284844a4 | ||
|
|
52ce9a333c | ||
|
|
abbeb266b5 | ||
|
|
ec2e5fa3a2 | ||
|
|
da17766ddd | ||
|
|
b11c5151bc | ||
|
|
0913db8c84 | ||
|
|
962b1f3d40 | ||
|
|
5c7705fcad | ||
|
|
3ee46e91e8 | ||
|
|
f6372483a0 | ||
|
|
ee26e7f11b | ||
|
|
937f534392 | ||
|
|
98f330658f | ||
|
|
1b2c02c944 | ||
|
|
0aa526e72c | ||
|
|
a7b3b0d3a5 | ||
|
|
0a35acbbe7 | ||
|
|
2a9989dd18 | ||
|
|
79b98a9fe8 | ||
|
|
c2112d5886 | ||
|
|
057de570e6 | ||
|
|
5f6825f9ec | ||
|
|
7e80a979a7 | ||
|
|
b7bb706150 | ||
|
|
557b3e412f | ||
|
|
8d74f34373 | ||
|
|
266ddd9639 | ||
|
|
e51c6ba380 | ||
|
|
32c2cc33bb | ||
|
|
947b8750e8 | ||
|
|
6389e52305 | ||
|
|
e05510f3bc | ||
|
|
fc9804b909 | ||
|
|
4761d07e0b | ||
|
|
88f6ff38d1 | ||
|
|
4198095a9c | ||
|
|
0111497fc9 | ||
|
|
13ed445607 | ||
|
|
1db50c3b16 | ||
|
|
7d8dea3b26 | ||
|
|
25fc02743a | ||
|
|
7f6b5d662b | ||
|
|
0bd8053524 | ||
|
|
1c15d0db45 | ||
|
|
67461666dc | ||
|
|
1a78bbcd23 | ||
|
|
45d81f881b | ||
|
|
8430123e9d | ||
|
|
614db97cca | ||
|
|
8c7d23dfb1 | ||
|
|
d854523783 | ||
|
|
7fa0dbdeb9 | ||
|
|
c644c1292d | ||
|
|
781f26eda1 | ||
|
|
37f4395cc0 | ||
|
|
de619ae5a6 | ||
|
|
86859f6d7e | ||
|
|
dcdcfe4d39 | ||
|
|
72306b9885 | ||
|
|
d224d71b8d | ||
|
|
38756b1f26 | ||
|
|
85a09fc3b6 | ||
|
|
307b88d6cc | ||
|
|
fb049d3a81 | ||
|
|
27d3669800 | ||
|
|
67cca43358 | ||
|
|
110a1ac885 | ||
|
|
3f8fc3a316 | ||
|
|
88384cf351 | ||
|
|
72a9d799b6 | ||
|
|
642273c290 | ||
|
|
766fafda8b | ||
|
|
e8b23c7798 | ||
|
|
842ac27efb | ||
|
|
9edbe93df5 | ||
|
|
af37ecafe1 | ||
|
|
41a9329409 | ||
|
|
0af42d1831 | ||
|
|
7eb52d2837 | ||
|
|
eb63fece2f | ||
|
|
2d8af8947e | ||
|
|
ff7f6139ba | ||
|
|
2650182f47 | ||
|
|
572b97b0bb | ||
|
|
0db7caf13b | ||
|
|
d9bc6f303c | ||
|
|
6fd9b338dd | ||
|
|
698705a820 | ||
|
|
d8d4e71b9e | ||
|
|
debc525fa1 | ||
|
|
5576e2737a | ||
|
|
b40d5de69c | ||
|
|
b7ef7840f3 | ||
|
|
fb2f8d1a51 | ||
|
|
54a783ba84 | ||
|
|
63c432f4fa | ||
|
|
85924bb32e | ||
|
|
a97690fc72 | ||
|
|
02c638209e | ||
|
|
030611b729 | ||
|
|
335b72df03 | ||
|
|
3a7d53f3cf | ||
|
|
07785d0003 | ||
|
|
9676167aac | ||
|
|
6eaeb19a4a | ||
|
|
1840a0b282 | ||
|
|
ace8aaa0f4 | ||
|
|
0c003c92a8 | ||
|
|
2246c79318 | ||
|
|
85fbf86d7b | ||
|
|
dda58244b6 | ||
|
|
aa82027a17 | ||
|
|
55c592dd43 | ||
|
|
fc1abd1c11 | ||
|
|
e645ba84cf | ||
|
|
6c99816855 | ||
|
|
ca04508cd1 | ||
|
|
2149bfb707 | ||
|
|
6b03b800b3 | ||
|
|
f9cab7ad61 | ||
|
|
d7971ba0e4 | ||
|
|
5c4cfaa0a7 | ||
|
|
bb9c9707aa | ||
|
|
0a3d780327 | ||
|
|
6c8e001fee | ||
|
|
9c53c7ada7 | ||
|
|
f99b7b630d | ||
|
|
ea31da2455 | ||
|
|
4d7746baf3 | ||
|
|
b0555a123a | ||
|
|
fa29344781 | ||
|
|
dcfc514c38 | ||
|
|
31d5825a86 | ||
|
|
8287ef6781 | ||
|
|
5cb5305cf3 | ||
|
|
00ad57e393 | ||
|
|
09d5707a8a | ||
|
|
8ad8d7b717 | ||
|
|
0357e5923f | ||
|
|
1e390269d4 | ||
|
|
bc49dfd27a | ||
|
|
27eedbc302 | ||
|
|
f63803e3e3 | ||
|
|
5f464b41e2 | ||
|
|
63be1f3a4d | ||
|
|
bcc1318d4b | ||
|
|
e36e07fa77 | ||
|
|
a0e03c9df4 | ||
|
|
6641dcafb6 | ||
|
|
d2945744f2 | ||
|
|
35bc716625 | ||
|
|
f39fd3d583 | ||
|
|
65887d9a56 | ||
|
|
d1b4f61f93 | ||
|
|
e9224ab444 | ||
|
|
4d9a085687 | ||
|
|
5b893c8ec3 | ||
|
|
4fe630431c | ||
|
|
c55dd5ed74 | ||
|
|
8571a08a93 | ||
|
|
68cc14f846 | ||
|
|
f94497d1d6 | ||
|
|
e4fa4b109a | ||
|
|
4b4528ee05 | ||
|
|
eaf3911c31 | ||
|
|
91cdb93e57 | ||
|
|
187a0caf9d | ||
|
|
b5a7a231f7 | ||
|
|
3907a5e3b2 | ||
|
|
b434b75b36 | ||
|
|
c70d176f35 | ||
|
|
9317237372 | ||
|
|
98434258d0 | ||
|
|
45ddb9caeb | ||
|
|
9bcf702a6e | ||
|
|
634f231b78 | ||
|
|
6702cae918 | ||
|
|
f68de86a17 | ||
|
|
c3c7587796 | ||
|
|
07bb7262d0 | ||
|
|
21befe583f | ||
|
|
a9d4a6291b | ||
|
|
6d2f77c180 | ||
|
|
accca2445f | ||
|
|
0bc4f6edb4 | ||
|
|
ce84a706a3 | ||
|
|
86b5248837 | ||
|
|
59e1601fb8 | ||
|
|
d35a9e7839 | ||
|
|
0465bd270d | ||
|
|
ee6c9fabb7 | ||
|
|
6780d0906c | ||
|
|
102d1b9137 | ||
|
|
294861ba96 | ||
|
|
11b0efdf84 | ||
|
|
5486b68850 | ||
|
|
bdd8e34f63 | ||
|
|
6547437725 | ||
|
|
9662228f6a | ||
|
|
31a9b05c96 | ||
|
|
63b01fe8f9 | ||
|
|
7a4ed9d200 | ||
|
|
0b303379c0 | ||
|
|
d5c651a5e5 | ||
|
|
d7ec2ecc12 | ||
|
|
cdba43cfa4 | ||
|
|
a123e232b9 | ||
|
|
601780acc1 | ||
|
|
7c3fee9e31 | ||
|
|
929de2b0de | ||
|
|
12e6ad326c | ||
|
|
00c8d1d241 | ||
|
|
af2472d85e | ||
|
|
3eb9101918 | ||
|
|
0a38a688f9 | ||
|
|
f4c2ea37bf | ||
|
|
915f907186 | ||
|
|
799509e145 | ||
|
|
b5a7197ae5 | ||
|
|
1b703349cf | ||
|
|
4a7179ff91 | ||
|
|
f97da4294a | ||
|
|
918c17bd88 | ||
|
|
8b71c6559b | ||
|
|
26641f3fb2 | ||
|
|
ebe118dc79 | ||
|
|
2827fa8699 | ||
|
|
c80ec625ec | ||
|
|
5e78f20f1c | ||
|
|
1f75232062 | ||
|
|
028ff64e9a | ||
|
|
7a8cffd631 | ||
|
|
5b553aafe2 | ||
|
|
084437bc6d | ||
|
|
70e5b6f15b | ||
|
|
57e0fafd5c | ||
|
|
8439c8ba98 | ||
|
|
5c4e470d43 | ||
|
|
6605d15783 | ||
|
|
ac8db977b9 | ||
|
|
88b77ddaa9 | ||
|
|
1cd9a2df9a | ||
|
|
fe4e9f9d97 | ||
|
|
8c6af09ae0 | ||
|
|
6f3e35bb3f | ||
|
|
7f3dbb6df7 | ||
|
|
174404c0f3 | ||
|
|
60c4030a4d | ||
|
|
ac810dc07a | ||
|
|
0cabedc526 | ||
|
|
5cd26c005b | ||
|
|
bd99b00413 | ||
|
|
9e2f9f7910 | ||
|
|
e4d73d8b7c | ||
|
|
e87c77ed41 | ||
|
|
774bda13cd | ||
|
|
8220dbbea0 | ||
|
|
59e999597e | ||
|
|
cbcb3ac44e | ||
|
|
f07ab4666f | ||
|
|
a800356ad0 | ||
|
|
e076abdbf2 | ||
|
|
425613b0d2 | ||
|
|
69da8e53e0 | ||
|
|
bb6b3a773a | ||
|
|
364d20f8fb | ||
|
|
15b5f70338 | ||
|
|
7f48d5b33c | ||
|
|
b6968b6bd2 | ||
|
|
08b80302eb | ||
|
|
645626ebe8 | ||
|
|
d895c09c70 | ||
|
|
08623aa6a7 | ||
|
|
c898a26117 | ||
|
|
619adb0308 | ||
|
|
7691bebea5 | ||
|
|
3c4346728e | ||
|
|
18d37ac761 | ||
|
|
63d35f8f6d | ||
|
|
7dbe961b2d | ||
|
|
94c4daaf9e | ||
|
|
37ee9de902 | ||
|
|
83db98ad3b | ||
|
|
bd0ae6569f | ||
|
|
841a661071 | ||
|
|
7491d07666 | ||
|
|
335e349314 | ||
|
|
392ac4ff31 | ||
|
|
2a88d07b3a | ||
|
|
a887cde9f2 | ||
|
|
9ffed2bea6 | ||
|
|
5f7cb6939c | ||
|
|
64e7a00399 | ||
|
|
c99eaae360 | ||
|
|
34213ea2f8 | ||
|
|
da8c428a07 | ||
|
|
0d8dea9538 | ||
|
|
2babe737e0 | ||
|
|
2cce61c564 | ||
|
|
246ec416c0 | ||
|
|
b5623b19d4 | ||
|
|
6be9c752d5 | ||
|
|
6b2861e086 | ||
|
|
d5138f7467 | ||
|
|
eac67b2816 | ||
|
|
ce10072824 | ||
|
|
dff54a6552 | ||
|
|
76ed083e47 | ||
|
|
b31918bbf0 | ||
|
|
1940fb682c | ||
|
|
17eef5a3c2 | ||
|
|
9f1f21b810 | ||
|
|
b14496c742 | ||
|
|
a8e67d157e | ||
|
|
e870c7db45 | ||
|
|
6500f8c52c | ||
|
|
4d2f7d83af | ||
|
|
99945fcd04 | ||
|
|
0d952ae43d | ||
|
|
593677d2ff | ||
|
|
c69294c449 | ||
|
|
2a06c7758e | ||
|
|
7ee1ec91a2 | ||
|
|
233fb62bd8 | ||
|
|
6637c267a5 | ||
|
|
99233c44cc | ||
|
|
33528002b4 | ||
|
|
20542a37a8 | ||
|
|
5fd12451f9 | ||
|
|
991fa99655 | ||
|
|
3d7f73114d | ||
|
|
dde9e293df | ||
|
|
34685a6f55 | ||
|
|
ba939ccd6c | ||
|
|
9812c826e0 | ||
|
|
2fac2bbfe4 | ||
|
|
242c61be94 | ||
|
|
e1cb1a0e3c | ||
|
|
3a5f354846 | ||
|
|
fcde6109b0 | ||
|
|
af22b9c657 | ||
|
|
adee5023c0 | ||
|
|
7ee8f3512e | ||
|
|
dc5db9b6ca | ||
|
|
e3bd223dac | ||
|
|
079aaa0d48 | ||
|
|
d4f17f29ae | ||
|
|
e99bc914ca | ||
|
|
025d34bfa2 | ||
|
|
c44c2d6c21 | ||
|
|
824ecfb8a2 | ||
|
|
ceebc466b9 | ||
|
|
35b31bdd4e | ||
|
|
c8b82583d2 | ||
|
|
9f9179ba1a | ||
|
|
872231a0ca | ||
|
|
36420183fd | ||
|
|
a8f8aa518b | ||
|
|
4c12cccff9 | ||
|
|
dcce4e5c66 | ||
|
|
56c0b834d6 | ||
|
|
6f864402d3 | ||
|
|
6c8db6eae1 | ||
|
|
3ff0b9e0c9 | ||
|
|
464a942a95 | ||
|
|
d7a4a4a462 | ||
|
|
8909e9e1cb | ||
|
|
e80ed38772 | ||
|
|
759b3f7d6d | ||
|
|
958b6c2e57 | ||
|
|
9863f0efa3 | ||
|
|
e8664e63ef | ||
|
|
ddd30eeaaa | ||
|
|
a68953c491 | ||
|
|
fa5c4f2d03 | ||
|
|
ab15d676d7 | ||
|
|
66761d7ecf | ||
|
|
3afad58a93 | ||
|
|
170e8b519e | ||
|
|
f8684f418a | ||
|
|
881bda7f59 | ||
|
|
9d7d365c2b | ||
|
|
9854deb626 | ||
|
|
d6814050dd | ||
|
|
ad344c5be3 | ||
|
|
96b89e34a3 | ||
|
|
4644becb9b | ||
|
|
f7460166dd | ||
|
|
32f76f7ff8 | ||
|
|
252fc65558 | ||
|
|
8108c7ffaf | ||
|
|
ba9936a572 | ||
|
|
905b601178 | ||
|
|
63fb2d5a44 | ||
|
|
85a5fc0aeb | ||
|
|
4fba3e0b80 | ||
|
|
9d398d999c | ||
|
|
f47b2b52a5 | ||
|
|
fedb6191a1 | ||
|
|
5bf617ebde | ||
|
|
0b82e1cd5b | ||
|
|
9aef34a816 | ||
|
|
0ac6918a41 | ||
|
|
65ee5af78c | ||
|
|
c6fa291571 | ||
|
|
bce4307e9e | ||
|
|
96ad94ab41 | ||
|
|
a5b60217ce | ||
|
|
44fd6694eb | ||
|
|
e48db3a8b6 | ||
|
|
e637bdaf4e | ||
|
|
d558abbdb7 | ||
|
|
4aed0830e5 | ||
|
|
d2dda34b2a | ||
|
|
c3a10c135e | ||
|
|
92e4340732 | ||
|
|
7b22f2031f | ||
|
|
3b14582d6b | ||
|
|
274e1b3dc7 | ||
|
|
de58b0289d | ||
|
|
efea52a4f4 | ||
|
|
763bd36b60 | ||
|
|
0552dbd93c | ||
|
|
18c63ff3d8 | ||
|
|
e04ef56243 | ||
|
|
5d60484553 | ||
|
|
3c846e6f7b | ||
|
|
2850dc69fd | ||
|
|
94205c3a37 | ||
|
|
2ada34b229 | ||
|
|
db396da734 | ||
|
|
0262b4244c | ||
|
|
73ca767d06 | ||
|
|
3ec11c781b | ||
|
|
a79ff060d0 | ||
|
|
43991f8d2f | ||
|
|
6b82069e1a | ||
|
|
276b9a31cd | ||
|
|
5801fa39e9 | ||
|
|
f0ab1b02e6 | ||
|
|
36c28e02fd | ||
|
|
e1c3861832 | ||
|
|
ecfd881ac6 | ||
|
|
81b7335267 | ||
|
|
bb010c2253 | ||
|
|
03b6121194 | ||
|
|
3ef092332b | ||
|
|
540c19792f | ||
|
|
80d1c8206b | ||
|
|
d36faffeca | ||
|
|
7c8c9b94bc | ||
|
|
f5eeed7665 | ||
|
|
80cfd063e2 | ||
|
|
aa45f6586e | ||
|
|
0c80d21e01 | ||
|
|
375c88245a | ||
|
|
ea3430102c | ||
|
|
9de7199b88 | ||
|
|
ae07714927 | ||
|
|
0e41a3fad4 | ||
|
|
61e850ceb5 | ||
|
|
992b6b9fcc | ||
|
|
7b71344051 | ||
|
|
605362f89d | ||
|
|
fbbaa42ee5 | ||
|
|
099992ecae | ||
|
|
d78ae20e64 | ||
|
|
5c02d65ddb | ||
|
|
d36067cd35 | ||
|
|
f1b2134dd1 | ||
|
|
74cda80d3b | ||
|
|
9a3a848cc8 | ||
|
|
a1a4c2ada7 | ||
|
|
189dbf02b6 | ||
|
|
42ecd42ac0 | ||
|
|
a10f6a96d7 | ||
|
|
0d232a1422 | ||
|
|
285bffd2c6 | ||
|
|
61c233a08e | ||
|
|
d2d716483a | ||
|
|
f16033aafd | ||
|
|
ae5366a31d | ||
|
|
6b23cbc852 | ||
|
|
7f9bc9e863 | ||
|
|
13219cebcb | ||
|
|
93a6e5780e | ||
|
|
fe55e0d93d | ||
|
|
e1f0747e4c | ||
|
|
e37b67d013 | ||
|
|
ad18689d92 | ||
|
|
0f80b1058d | ||
|
|
0d48af3f36 | ||
|
|
4613644cce | ||
|
|
718e475613 | ||
|
|
aa5dd15352 | ||
|
|
5bff65c132 | ||
|
|
24bc09b79b | ||
|
|
37c17d5541 | ||
|
|
120948fa48 | ||
|
|
66e6f0c3cb | ||
|
|
f7447efa8c | ||
|
|
f4d36a58c2 | ||
|
|
6d1c3e1aec | ||
|
|
73cc0505f5 | ||
|
|
c75f5a1fd8 | ||
|
|
39d8880f2c | ||
|
|
5538ec7bd8 | ||
|
|
f101d6429b | ||
|
|
fe06fc85d3 | ||
|
|
f36a1eaa8b | ||
|
|
a64bdda9ae | ||
|
|
01d19b4b52 | ||
|
|
f0c1a01bc2 | ||
|
|
7be680d3f8 | ||
|
|
57dab1e1db | ||
|
|
21b3c890a1 | ||
|
|
fb0ec720a4 | ||
|
|
7971ed33d1 | ||
|
|
885835a655 | ||
|
|
4c64554808 | ||
|
|
548beeb6b1 | ||
|
|
e3066f9577 | ||
|
|
e391367488 | ||
|
|
18ddf2f7b5 | ||
|
|
f8ee5a0785 | ||
|
|
b467a3c877 | ||
|
|
f2d48e9019 | ||
|
|
5e314bf3e9 | ||
|
|
05ba26c7c8 | ||
|
|
87b72364a4 | ||
|
|
0e3ff1f970 | ||
|
|
ec3e74d7f4 | ||
|
|
62bda71c85 | ||
|
|
83e0939088 | ||
|
|
9798d96e37 | ||
|
|
6006dd933d | ||
|
|
ac2caf1088 | ||
|
|
8511e80f48 | ||
|
|
91bc3f1f92 | ||
|
|
8463b48f90 | ||
|
|
e3342a3cf6 | ||
|
|
524a8a42a4 | ||
|
|
7bf59b5bcd | ||
|
|
025f3e9596 | ||
|
|
8258edd8a5 | ||
|
|
8669ca219b | ||
|
|
71652690b6 | ||
|
|
37693d2812 | ||
|
|
8fbe200012 | ||
|
|
1a34a13e33 | ||
|
|
ef772b0049 | ||
|
|
6fcabbde08 | ||
|
|
14f290f8ab | ||
|
|
e2e09d5754 | ||
|
|
448a8d3845 | ||
|
|
514936beb8 | ||
|
|
f5c09d0bbf | ||
|
|
014f655c5f | ||
|
|
bf30dc3038 | ||
|
|
ef2ef07cbd | ||
|
|
1a4440080d | ||
|
|
ac0086a745 | ||
|
|
2494daaf68 | ||
|
|
9b404f9de6 | ||
|
|
5344b7dab8 | ||
|
|
0007a53b9c | ||
|
|
1dd05f44eb | ||
|
|
bf7b122ab2 | ||
|
|
e29048b54a | ||
|
|
2eeb640eca | ||
|
|
ceb200fe81 | ||
|
|
f5f8239057 | ||
|
|
6f9d051784 | ||
|
|
931862e97f | ||
|
|
1d0127de21 | ||
|
|
2d8fc61677 | ||
|
|
1e31011874 | ||
|
|
75cdbf19aa | ||
|
|
4339bd5cfa | ||
|
|
1ab2fdaa10 | ||
|
|
eda540f6ec | ||
|
|
90a330da16 | ||
|
|
cad1f9cbd1 | ||
|
|
f6203bd5a8 | ||
|
|
03cf94ebe8 | ||
|
|
c3087dd179 | ||
|
|
2c305af478 | ||
|
|
72e6f64ca8 | ||
|
|
b9fac687ff | ||
|
|
2c88eb6fbe | ||
|
|
a67e3bfdd3 | ||
|
|
27142df4f5 | ||
|
|
5e4c7f4245 | ||
|
|
b521b4b926 | ||
|
|
aa9de76370 | ||
|
|
5a083a938d | ||
|
|
7a30d826b8 | ||
|
|
be55a09edf | ||
|
|
15a148ff6d | ||
|
|
428e19fed2 | ||
|
|
f65e55dff4 | ||
|
|
b634018618 | ||
|
|
fa3300f314 | ||
|
|
bd0886a2c0 | ||
|
|
248f304f02 | ||
|
|
dc5f70eab5 | ||
|
|
df8c5623af | ||
|
|
a790c09c91 | ||
|
|
8f35a363d9 | ||
|
|
d2190c2bf3 | ||
|
|
ea10642572 | ||
|
|
547561a568 | ||
|
|
c16d538ce7 | ||
|
|
73d082df2e | ||
|
|
50b8d7272c | ||
|
|
7d11b96f48 | ||
|
|
eab99a1c3d | ||
|
|
19e2fb134d | ||
|
|
f4919e3a25 | ||
|
|
bb700daa4c | ||
|
|
263577d5eb | ||
|
|
63287c0e68 | ||
|
|
c5ed2292bf | ||
|
|
b70670b69f | ||
|
|
9dd97605bc | ||
|
|
e4c5302406 | ||
|
|
bea3d90771 | ||
|
|
785c6064cc | ||
|
|
b214d3786f | ||
|
|
7cf79c302b | ||
|
|
a14c6b6574 | ||
|
|
f1b7094a57 | ||
|
|
0358e376f0 | ||
|
|
b47f7b76b9 | ||
|
|
582cc55cff | ||
|
|
8979579e55 | ||
|
|
0d6e08c541 | ||
|
|
e2daee9a65 | ||
|
|
9cd118ca3d | ||
|
|
cfd5c6155c | ||
|
|
1a5a4bd631 | ||
|
|
63e1a8e1fd | ||
|
|
7055af8221 | ||
|
|
aafe2e1db3 | ||
|
|
118105db43 | ||
|
|
63d04fff69 | ||
|
|
8c9cc920fb | ||
|
|
d09f0adae3 | ||
|
|
3fa9265ce4 | ||
|
|
3a81f60982 | ||
|
|
f2348dd98b | ||
|
|
253c7c2325 | ||
|
|
bb0a762d12 | ||
|
|
8cc86fee60 | ||
|
|
88fb83aa81 | ||
|
|
95b4507c02 | ||
|
|
afdaeba37d | ||
|
|
037199bfe2 | ||
|
|
583fac0a0f | ||
|
|
e8158279ff | ||
|
|
78e98d2611 | ||
|
|
8d14efe818 | ||
|
|
83ba338bd0 | ||
|
|
7c10b25346 | ||
|
|
cb9d16fbe4 | ||
|
|
5d8da864c5 | ||
|
|
85b527ba3d | ||
|
|
1c6efdae34 | ||
|
|
b0ca896d98 | ||
|
|
78a217b94c | ||
|
|
a89d233318 | ||
|
|
c28e1a0237 | ||
|
|
1a95007ec1 | ||
|
|
ed80b4a534 | ||
|
|
4f09df238e | ||
|
|
d9ad3c7cbf | ||
|
|
6ea3f7fe34 | ||
|
|
4c4dc2137c | ||
|
|
4aa4b3e694 | ||
|
|
2604aadb37 | ||
|
|
964d5b9aa4 | ||
|
|
b7adbcab1f | ||
|
|
3435af494f | ||
|
|
41c627379c | ||
|
|
e54df2226f | ||
|
|
dfa395f6ff | ||
|
|
b1febde3e9 | ||
|
|
193049af19 | ||
|
|
4a0bab0fa3 | ||
|
|
9243b0cb9d | ||
|
|
fc9ba323c4 | ||
|
|
d0689c81bb | ||
|
|
02a84385a0 | ||
|
|
a4889a0f2e | ||
|
|
f29f07aabd | ||
|
|
188e28efd7 | ||
|
|
2df48924cc | ||
|
|
9fc6796d2a | ||
|
|
9fc8a52142 | ||
|
|
3a21861580 | ||
|
|
1dbffd48ea | ||
|
|
22a038e6a2 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.js text eol=lf
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
/node_modules/
|
||||
/npm-debug.log
|
||||
tmp/
|
||||
node_modules/
|
||||
|
||||
11
.travis.yml
11
.travis.yml
@@ -1,7 +1,10 @@
|
||||
language: node_js
|
||||
before_install: "npm install -g npm"
|
||||
node_js:
|
||||
- "0.4"
|
||||
- "0.6"
|
||||
- "0.8"
|
||||
- "0.12"
|
||||
- "0.10"
|
||||
- "0.11"
|
||||
- "4"
|
||||
- "6"
|
||||
matrix:
|
||||
fast_finish: true
|
||||
sudo: false
|
||||
|
||||
561
README.md
561
README.md
@@ -1,6 +1,6 @@
|
||||
UglifyJS 2
|
||||
==========
|
||||
[](https://travis-ci.org/mishoo/UglifyJS2)
|
||||
[](https://travis-ci.org/mishoo/UglifyJS2)
|
||||
|
||||
UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit.
|
||||
|
||||
@@ -10,6 +10,9 @@ There's also an
|
||||
[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,
|
||||
Chrome and probably Safari).
|
||||
|
||||
Note: release versions of `uglify-js` only support ECMAScript 5 (ES5). If you wish to minify
|
||||
ES2015+ (ES6+) code then please use the [harmony](#harmony) development branch.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
@@ -44,57 +47,117 @@ variable/function declared in another file will be matched properly.
|
||||
If you want to read from STDIN instead, pass a single dash instead of input
|
||||
files.
|
||||
|
||||
If you wish to pass your options before the input files, separate the two with
|
||||
a double dash to prevent input files being used as option arguments:
|
||||
|
||||
uglifyjs --compress --mangle -- input.js
|
||||
|
||||
The available options are:
|
||||
|
||||
--source-map Specify an output file where to generate source map.
|
||||
[string]
|
||||
--source-map-root The path to the original source to be included in the
|
||||
source map. [string]
|
||||
--source-map-url The path to the source map to be added in //@
|
||||
sourceMappingURL. Defaults to the value passed with
|
||||
--source-map. [string]
|
||||
--in-source-map Input source map, useful if you're compressing JS that was
|
||||
generated from some other original code.
|
||||
--screw-ie8 Pass this flag if you don't care about full compliance with
|
||||
Internet Explorer 6-8 quirks (by default UglifyJS will try
|
||||
to be IE-proof).
|
||||
-p, --prefix Skip prefix for original filenames that appear in source
|
||||
maps. For example -p 3 will drop 3 directories from file
|
||||
names and ensure they are relative paths.
|
||||
-o, --output Output file (default STDOUT).
|
||||
-b, --beautify Beautify output/specify output options. [string]
|
||||
-m, --mangle Mangle names/pass mangler options. [string]
|
||||
-r, --reserved Reserved names to exclude from mangling.
|
||||
-c, --compress Enable compressor/pass compressor options. Pass options
|
||||
like -c hoist_vars=false,if_return=false. Use -c with no
|
||||
argument to use the default compression options. [string]
|
||||
-d, --define Global definitions [string]
|
||||
--comments Preserve copyright comments in the output. By default this
|
||||
works like Google Closure, keeping JSDoc-style comments
|
||||
that contain "@license" or "@preserve". You can optionally
|
||||
pass one of the following arguments to this flag:
|
||||
- "all" to keep all comments
|
||||
- a valid JS regexp (needs to start with a slash) to keep
|
||||
only comments that match.
|
||||
Note that currently not *all* comments can be kept when
|
||||
compression is on, because of dead code removal or
|
||||
cascading statements into sequences. [string]
|
||||
--stats Display operations run time on STDERR. [boolean]
|
||||
--acorn Use Acorn for parsing. [boolean]
|
||||
--spidermonkey Assume input files are SpiderMonkey AST format (as JSON).
|
||||
[boolean]
|
||||
--self Build itself (UglifyJS2) as a library (implies
|
||||
--wrap=UglifyJS --export-all) [boolean]
|
||||
--wrap Embed everything in a big function, making the “exports”
|
||||
and “global” variables available. You need to pass an
|
||||
argument to this option to specify the name that your
|
||||
module will take when included in, say, a browser.
|
||||
[string]
|
||||
--export-all Only used when --wrap, this tells UglifyJS to add code to
|
||||
automatically export all globals. [boolean]
|
||||
--lint Display some scope warnings [boolean]
|
||||
-v, --verbose Verbose [boolean]
|
||||
-V, --version Print version number and exit. [boolean]
|
||||
```
|
||||
--source-map Specify an output file where to generate source
|
||||
map.
|
||||
--source-map-root The path to the original source to be included
|
||||
in the source map.
|
||||
--source-map-url The path to the source map to be added in //#
|
||||
sourceMappingURL. Defaults to the value passed
|
||||
with --source-map.
|
||||
--source-map-include-sources Pass this flag if you want to include the
|
||||
content of source files in the source map as
|
||||
sourcesContent property.
|
||||
--source-map-inline Write base64-encoded source map to the end of js output.
|
||||
--in-source-map Input source map, useful if you're compressing
|
||||
JS that was generated from some other original
|
||||
code.
|
||||
--screw-ie8 Use this flag if you don't wish to support
|
||||
Internet Explorer 6/7/8.
|
||||
By default UglifyJS will not try to be IE-proof.
|
||||
--support-ie8 Use this flag to support Internet Explorer 6/7/8.
|
||||
Equivalent to setting `screw_ie8: false` in `minify()`
|
||||
for `compress`, `mangle` and `output` options.
|
||||
Note: `--support-ie8` may generate incorrect code
|
||||
for `try`/`catch` in ES5 compliant browsers.
|
||||
--expr Parse a single expression, rather than a
|
||||
program (for parsing JSON)
|
||||
-p, --prefix Skip prefix for original filenames that appear
|
||||
in source maps. For example -p 3 will drop 3
|
||||
directories from file names and ensure they are
|
||||
relative paths. You can also specify -p
|
||||
relative, which will make UglifyJS figure out
|
||||
itself the relative paths between original
|
||||
sources, the source map and the output file.
|
||||
-o, --output Output file (default STDOUT).
|
||||
-b, --beautify Beautify output/specify output options.
|
||||
-m, --mangle Mangle names/pass mangler options.
|
||||
-r, --reserved Reserved names to exclude from mangling.
|
||||
-c, --compress Enable compressor/pass compressor options, e.g.
|
||||
`-c 'if_return=false,pure_funcs=["Math.pow","console.log"]'`
|
||||
Use `-c` with no argument to enable default compression
|
||||
options.
|
||||
-d, --define Global definitions
|
||||
-e, --enclose Embed everything in a big function, with a
|
||||
configurable parameter/argument list.
|
||||
--comments Preserve copyright comments in the output. By
|
||||
default this works like Google Closure, keeping
|
||||
JSDoc-style comments that contain "@license" or
|
||||
"@preserve". You can optionally pass one of the
|
||||
following arguments to this flag:
|
||||
- "all" to keep all comments
|
||||
- a valid JS RegExp like `/foo/` or `/^!/` to
|
||||
keep only matching comments.
|
||||
Note that currently not *all* comments can be
|
||||
kept when compression is on, because of dead
|
||||
code removal or cascading statements into
|
||||
sequences.
|
||||
--preamble Preamble to prepend to the output. You can use
|
||||
this to insert a comment, for example for
|
||||
licensing information. This will not be
|
||||
parsed, but the source map will adjust for its
|
||||
presence.
|
||||
--stats Display operations run time on STDERR.
|
||||
--acorn Use Acorn for parsing.
|
||||
--spidermonkey Assume input files are SpiderMonkey AST format
|
||||
(as JSON).
|
||||
--self Build itself (UglifyJS2) as a library (implies
|
||||
--wrap=UglifyJS --export-all)
|
||||
--wrap Embed everything in a big function, making the
|
||||
“exports” and “global” variables available. You
|
||||
need to pass an argument to this option to
|
||||
specify the name that your module will take
|
||||
when included in, say, a browser.
|
||||
--export-all Only used when --wrap, this tells UglifyJS to
|
||||
add code to automatically export all globals.
|
||||
--lint Display some scope warnings
|
||||
-v, --verbose Verbose
|
||||
-V, --version Print version number and exit.
|
||||
--noerr Don't throw an error for unknown options in -c,
|
||||
-b or -m.
|
||||
--bare-returns Allow return outside of functions. Useful when
|
||||
minifying CommonJS modules and Userscripts that
|
||||
may be anonymous function wrapped (IIFE) by the
|
||||
.user.js engine `caller`.
|
||||
--keep-fnames Do not mangle/drop function names. Useful for
|
||||
code relying on Function.prototype.name.
|
||||
--reserved-file File containing reserved names
|
||||
--reserve-domprops Make (most?) DOM properties reserved for
|
||||
--mangle-props
|
||||
--mangle-props Mangle property names (default `0`). Set to
|
||||
`true` or `1` to mangle all property names. Set
|
||||
to `unquoted` or `2` to only mangle unquoted
|
||||
property names. Mode `2` also enables the
|
||||
`keep_quoted_props` beautifier option to
|
||||
preserve the quotes around property names and
|
||||
disables the `properties` compressor option to
|
||||
prevent rewriting quoted properties with dot
|
||||
notation. You can override these by setting
|
||||
them explicitly on the command line.
|
||||
--mangle-regex Only mangle property names matching the regex
|
||||
--name-cache File to hold mangled names mappings
|
||||
--pure-funcs Functions that can be safely removed if their
|
||||
return value is not used, e.g.
|
||||
`--pure-funcs Math.floor console.info`
|
||||
(requires `--compress`)
|
||||
```
|
||||
|
||||
Specify `--output` (`-o`) to declare the output file. Otherwise the output
|
||||
goes to STDOUT.
|
||||
@@ -148,15 +211,10 @@ input files from the command line.
|
||||
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
||||
(comma-separated) options are supported:
|
||||
|
||||
- `sort` — to assign shorter names to most frequently used variables. This
|
||||
saves a few hundred bytes on jQuery before gzip, but the output is
|
||||
_bigger_ after gzip (and seems to happen for other libraries I tried it
|
||||
on) therefore it's not enabled by default.
|
||||
|
||||
- `toplevel` — mangle names declared in the toplevel scope (disabled by
|
||||
default).
|
||||
|
||||
- `eval` — mangle names visible in scopes where `eval` or `when` are used
|
||||
- `eval` — mangle names visible in scopes where `eval` or `with` are used
|
||||
(disabled by default).
|
||||
|
||||
When mangling is enabled but you want to prevent certain names from being
|
||||
@@ -167,6 +225,99 @@ comma-separated list of names. For example:
|
||||
|
||||
to prevent the `require`, `exports` and `$` names from being changed.
|
||||
|
||||
### Mangling property names (`--mangle-props`)
|
||||
|
||||
**Note:** this will probably break your code. Mangling property names is a
|
||||
separate step, different from variable name mangling. Pass
|
||||
`--mangle-props`. It will mangle all properties that are seen in some
|
||||
object literal, or that are assigned to. For example:
|
||||
|
||||
```js
|
||||
var x = {
|
||||
foo: 1
|
||||
};
|
||||
|
||||
x.bar = 2;
|
||||
x["baz"] = 3;
|
||||
x[condition ? "moo" : "boo"] = 4;
|
||||
console.log(x.something());
|
||||
```
|
||||
|
||||
In the above code, `foo`, `bar`, `baz`, `moo` and `boo` will be replaced
|
||||
with single characters, while `something()` will be left as is.
|
||||
|
||||
In order for this to be of any use, we should avoid mangling standard JS
|
||||
names. For instance, if your code would contain `x.length = 10`, then
|
||||
`length` becomes a candidate for mangling and it will be mangled throughout
|
||||
the code, regardless if it's being used as part of your own objects or
|
||||
accessing an array's length. To avoid that, you can use `--reserved-file`
|
||||
to pass a filename that should contain the names to be excluded from
|
||||
mangling. This file can be used both for excluding variable names and
|
||||
property names. It could look like this, for example:
|
||||
|
||||
```js
|
||||
{
|
||||
"vars": [ "define", "require", ... ],
|
||||
"props": [ "length", "prototype", ... ]
|
||||
}
|
||||
```
|
||||
|
||||
`--reserved-file` can be an array of file names (either a single
|
||||
comma-separated argument, or you can pass multiple `--reserved-file`
|
||||
arguments) — in this case it will exclude names from all those files.
|
||||
|
||||
A default exclusion file is provided in `tools/domprops.json` which should
|
||||
cover most standard JS and DOM properties defined in various browsers. Pass
|
||||
`--reserve-domprops` to read that in.
|
||||
|
||||
You can also use a regular expression to define which property names should be
|
||||
mangled. For example, `--mangle-regex="/^_/"` will only mangle property names
|
||||
that start with an underscore.
|
||||
|
||||
When you compress multiple files using this option, in order for them to
|
||||
work together in the end we need to ensure somehow that one property gets
|
||||
mangled to the same name in all of them. For this, pass `--name-cache
|
||||
filename.json` and UglifyJS will maintain these mappings in a file which can
|
||||
then be reused. It should be initially empty. Example:
|
||||
|
||||
```
|
||||
rm -f /tmp/cache.json # start fresh
|
||||
uglifyjs file1.js file2.js --mangle-props --name-cache /tmp/cache.json -o part1.js
|
||||
uglifyjs file3.js file4.js --mangle-props --name-cache /tmp/cache.json -o part2.js
|
||||
```
|
||||
|
||||
Now, `part1.js` and `part2.js` will be consistent with each other in terms
|
||||
of mangled property names.
|
||||
|
||||
Using the name cache is not necessary if you compress all your files in a
|
||||
single call to UglifyJS.
|
||||
|
||||
#### Mangling unquoted names (`--mangle-props=unquoted` or `--mangle-props=2`)
|
||||
|
||||
Using quoted property name (`o["foo"]`) reserves the property name (`foo`)
|
||||
so that it is not mangled throughout the entire script even when used in an
|
||||
unquoted style (`o.foo`). Example:
|
||||
|
||||
```
|
||||
$ echo 'var o={"foo":1, bar:3}; o.foo += o.bar; console.log(o.foo);' | uglifyjs --mangle-props=2 -mc
|
||||
var o={"foo":1,a:3};o.foo+=o.a,console.log(o.foo);
|
||||
```
|
||||
|
||||
#### Debugging property name mangling
|
||||
|
||||
You can also pass `--mangle-props-debug` in order to mangle property names
|
||||
without completely obscuring them. For example the property `o.foo`
|
||||
would mangle to `o._$foo$_` with this option. This allows property mangling
|
||||
of a large codebase while still being able to debug the code and identify
|
||||
where mangling is breaking things.
|
||||
|
||||
You can also pass a custom suffix using `--mangle-props-debug=XYZ`. This would then
|
||||
mangle `o.foo` to `o._$foo$XYZ_`. You can change this each time you compile a
|
||||
script to identify how a property got mangled. One technique is to pass a
|
||||
random number on every compile to simulate mangling changing with different
|
||||
inputs (e.g. as you update the input script with new properties), and to help
|
||||
identify mistakes like writing mangled keys to storage.
|
||||
|
||||
## Compressor options
|
||||
|
||||
You need to pass `--compress` (`-c`) to enable the compressor. Optionally
|
||||
@@ -174,33 +325,116 @@ you can pass a comma-separated list of options. Options are in the form
|
||||
`foo=bar`, or just `foo` (the latter implies a boolean option that you want
|
||||
to set `true`; it's effectively a shortcut for `foo=true`).
|
||||
|
||||
- `sequences` -- join consecutive simple statements using the comma operator
|
||||
- `sequences` (default: true) -- join consecutive simple statements using the
|
||||
comma operator. May be set to a positive integer to specify the maximum number
|
||||
of consecutive comma sequences that will be generated. If this option is set to
|
||||
`true` then the default `sequences` limit is `200`. Set option to `false` or `0`
|
||||
to disable. The smallest `sequences` length is `2`. A `sequences` value of `1`
|
||||
is grandfathered to be equivalent to `true` and as such means `200`. On rare
|
||||
occasions the default sequences limit leads to very slow compress times in which
|
||||
case a value of `20` or less is recommended.
|
||||
|
||||
- `properties` -- rewrite property access using the dot notation, for
|
||||
example `foo["bar"] → foo.bar`
|
||||
|
||||
- `dead_code` -- remove unreachable code
|
||||
|
||||
- `drop_debugger` -- remove `debugger;` statements
|
||||
|
||||
- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below)
|
||||
|
||||
- `unsafe_comps` (default: false) -- Reverse `<` and `<=` to `>` and `>=` to
|
||||
allow improved compression. This might be unsafe when an at least one of two
|
||||
operands is an object with computed values due the use of methods like `get`,
|
||||
or `valueOf`. This could cause change in execution order after operands in the
|
||||
comparison are switching. Compression only works if both `comparisons` and
|
||||
`unsafe_comps` are both set to true.
|
||||
|
||||
- `unsafe_proto` (default: false) -- optimize expressions like
|
||||
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
||||
|
||||
- `conditionals` -- apply optimizations for `if`-s and conditional
|
||||
expressions
|
||||
|
||||
- `comparisons` -- apply certain optimizations to binary nodes, for example:
|
||||
`!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes,
|
||||
e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
|
||||
`!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary
|
||||
nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
|
||||
|
||||
- `evaluate` -- attempt to evaluate constant expressions
|
||||
|
||||
- `booleans` -- various optimizations for boolean context, for example `!!a
|
||||
? b : c → a ? b : c`
|
||||
|
||||
- `loops` -- optimizations for `do`, `while` and `for` loops when we can
|
||||
statically determine the condition
|
||||
- `unused` -- drop unreferenced functions and variables
|
||||
|
||||
- `unused` -- drop unreferenced functions and variables (simple direct variable
|
||||
assignments do not count as references unless set to `"keep_assign"`)
|
||||
|
||||
- `toplevel` -- drop unreferenced functions (`"funcs"`) and/or variables (`"vars"`)
|
||||
in the toplevel scope (`false` by default, `true` to drop both unreferenced
|
||||
functions and variables)
|
||||
|
||||
- `top_retain` -- prevent specific toplevel functions and variables from `unused`
|
||||
removal (can be array, comma-separated, RegExp or function. Implies `toplevel`)
|
||||
|
||||
- `hoist_funs` -- hoist function declarations
|
||||
|
||||
- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`
|
||||
by default because it seems to increase the size of the output in general)
|
||||
|
||||
- `if_return` -- optimizations for if/return and if/continue
|
||||
|
||||
- `join_vars` -- join consecutive `var` statements
|
||||
|
||||
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
||||
and `x = something(), x` into `x = something()`
|
||||
|
||||
- `collapse_vars` -- default `false`. Collapse single-use `var` and `const`
|
||||
definitions when possible.
|
||||
|
||||
- `reduce_vars` -- default `false`. Improve optimization on variables assigned
|
||||
with and used as constant values.
|
||||
|
||||
- `warnings` -- display warnings when dropping unreachable code or unused
|
||||
declarations etc.
|
||||
|
||||
- `negate_iife` -- negate "Immediately-Called Function Expressions"
|
||||
where the return value is discarded, to avoid the parens that the
|
||||
code generator would insert.
|
||||
|
||||
- `pure_getters` -- the default is `false`. If you pass `true` for
|
||||
this, UglifyJS will assume that object property access
|
||||
(e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
|
||||
|
||||
- `pure_funcs` -- default `null`. You can pass an array of names and
|
||||
UglifyJS will assume that those functions do not produce side
|
||||
effects. DANGER: will not check if the name is redefined in scope.
|
||||
An example case here, for instance `var q = Math.floor(a/b)`. If
|
||||
variable `q` is not used elsewhere, UglifyJS will drop it, but will
|
||||
still keep the `Math.floor(a/b)`, not knowing what it does. You can
|
||||
pass `pure_funcs: [ 'Math.floor' ]` to let it know that this
|
||||
function won't produce any side effect, in which case the whole
|
||||
statement would get discarded. The current implementation adds some
|
||||
overhead (compression will be slower).
|
||||
|
||||
- `drop_console` -- default `false`. Pass `true` to discard calls to
|
||||
`console.*` functions. If you wish to drop a specific function call
|
||||
such as `console.info` and/or retain side effects from function arguments
|
||||
after dropping the function call then use `pure_funcs` instead.
|
||||
|
||||
- `keep_fargs` -- default `true`. Prevents the
|
||||
compressor from discarding unused function arguments. You need this
|
||||
for code which relies on `Function.length`.
|
||||
|
||||
- `keep_fnames` -- default `false`. Pass `true` to prevent the
|
||||
compressor from discarding function names. Useful for code relying on
|
||||
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
|
||||
|
||||
- `passes` -- default `1`. Number of times to run compress. Use an
|
||||
integer argument larger than 1 to further reduce code size in some cases.
|
||||
Note: raising the number of passes will increase uglify compress time.
|
||||
|
||||
### The `unsafe` option
|
||||
|
||||
It enables some transformations that *might* break code logic in certain
|
||||
@@ -208,14 +442,14 @@ contrived cases, but should be fine for most code. You might want to try it
|
||||
on your own code, it should reduce the minified size. Here's what happens
|
||||
when this flag is on:
|
||||
|
||||
- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]`
|
||||
- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[ 1, 2, 3 ]`
|
||||
- `new Object()` → `{}`
|
||||
- `String(exp)` or `exp.toString()` → `"" + exp`
|
||||
- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
|
||||
- `typeof foo == "undefined"` → `foo === void 0`
|
||||
- `void 0` → `"undefined"` (if there is a variable named "undefined" in
|
||||
- `void 0` → `undefined` (if there is a variable named "undefined" in
|
||||
scope; we do it because the variable name will be mangled, typically
|
||||
reduced to a single character).
|
||||
reduced to a single character)
|
||||
|
||||
### Conditional compilation
|
||||
|
||||
@@ -229,6 +463,8 @@ if (DEBUG) {
|
||||
}
|
||||
```
|
||||
|
||||
You can specify nested constants in the form of `--define env.DEBUG=false`.
|
||||
|
||||
UglifyJS will warn about the condition being always false and about dropping
|
||||
unreachable code; for now there is no option to turn off only this specific
|
||||
warning, you can pass `warnings=false` to turn off *all* warnings.
|
||||
@@ -248,10 +484,27 @@ and build your code like this:
|
||||
|
||||
UglifyJS will notice the constants and, since they cannot be altered, it
|
||||
will evaluate references to them to the value itself and drop unreachable
|
||||
code as usual. The possible downside of this approach is that the build
|
||||
will contain the `const` declarations.
|
||||
code as usual. The build will contain the `const` declarations if you use
|
||||
them. If you are targeting < ES6 environments which does not support `const`,
|
||||
using `var` with `reduce_vars` (enabled by default) should suffice.
|
||||
|
||||
<a name="codegen-options"></a>
|
||||
|
||||
#### Conditional compilation, API
|
||||
You can also use conditional compilation via the programmatic API. With the difference that the
|
||||
property name is `global_defs` and is a compressor property:
|
||||
|
||||
```js
|
||||
uglifyJS.minify([ "input.js"], {
|
||||
compress: {
|
||||
dead_code: true,
|
||||
global_defs: {
|
||||
DEBUG: false
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Beautifier options
|
||||
|
||||
The code generator tries to output shortest code possible by default. In
|
||||
@@ -268,7 +521,7 @@ can pass additional arguments that control the code output:
|
||||
objects
|
||||
- `space-colon` (default `true`) -- insert a space after the colon signs
|
||||
- `ascii-only` (default `false`) -- escape Unicode characters in strings and
|
||||
regexps
|
||||
regexps (affects directives with non-ascii characters becoming invalid)
|
||||
- `inline-script` (default `false`) -- escape the slash in occurrences of
|
||||
`</script` in strings
|
||||
- `width` (default 80) -- only takes effect when beautification is on, this
|
||||
@@ -277,9 +530,6 @@ can pass additional arguments that control the code output:
|
||||
It doesn't work very well currently, but it does make the code generated
|
||||
by UglifyJS more readable.
|
||||
- `max-line-len` (default 32000) -- maximum line length (for uglified code)
|
||||
- `ie-proof` (default `true`) -- generate “IE-proof” code (for now this
|
||||
means add brackets around the do/while in code like this: `if (foo) do
|
||||
something(); while (bar); else ...`.
|
||||
- `bracketize` (default `false`) -- always insert brackets in `if`, `for`,
|
||||
`do`, `while` or `with` statements, even if their body is a single
|
||||
statement.
|
||||
@@ -287,6 +537,22 @@ can pass additional arguments that control the code output:
|
||||
you pass `false` then whenever possible we will use a newline instead of a
|
||||
semicolon, leading to more readable output of uglified code (size before
|
||||
gzip could be smaller; size after gzip insignificantly larger).
|
||||
- `preamble` (default `null`) -- when passed it must be a string and
|
||||
it will be prepended to the output literally. The source map will
|
||||
adjust for this text. Can be used to insert a comment containing
|
||||
licensing information, for example.
|
||||
- `quote_style` (default `0`) -- preferred quote style for strings (affects
|
||||
quoted property names and directives as well):
|
||||
- `0` -- prefers double quotes, switches to single quotes when there are
|
||||
more double quotes in the string itself.
|
||||
- `1` -- always use single quotes
|
||||
- `2` -- always use double quotes
|
||||
- `3` -- always use the original quotes
|
||||
- `keep_quoted_props` (default `false`) -- when turned on, prevents stripping
|
||||
quotes from property names in object literals.
|
||||
- `ecma` (default `5`) -- set output printing mode. This will only change the
|
||||
output in direct control of the beautifier. Non-compatible features in the
|
||||
abstract syntax tree will still be outputted as is.
|
||||
|
||||
### Keeping copyright notices or other comments
|
||||
|
||||
@@ -344,6 +610,38 @@ Acorn is really fast (e.g. 250ms instead of 380ms on some 650K code), but
|
||||
converting the SpiderMonkey tree that Acorn produces takes another 150ms so
|
||||
in total it's a bit more than just using UglifyJS's own parser.
|
||||
|
||||
### Using UglifyJS to transform SpiderMonkey AST
|
||||
|
||||
Now you can use UglifyJS as any other intermediate tool for transforming
|
||||
JavaScript ASTs in SpiderMonkey format.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
function uglify(ast, options, mangle) {
|
||||
// Conversion from SpiderMonkey AST to internal format
|
||||
var uAST = UglifyJS.AST_Node.from_mozilla_ast(ast);
|
||||
|
||||
// Compression
|
||||
uAST.figure_out_scope();
|
||||
uAST = uAST.transform(UglifyJS.Compressor(options));
|
||||
|
||||
// Mangling (optional)
|
||||
if (mangle) {
|
||||
uAST.figure_out_scope();
|
||||
uAST.compute_char_frequency();
|
||||
uAST.mangle_names();
|
||||
}
|
||||
|
||||
// Back-conversion to SpiderMonkey AST
|
||||
return uAST.to_mozilla_ast();
|
||||
}
|
||||
```
|
||||
|
||||
Check out
|
||||
[original blog post](http://rreverser.com/using-mozilla-ast-with-uglifyjs/)
|
||||
for details.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
@@ -384,9 +682,26 @@ console.log(result.code); // minified output
|
||||
console.log(result.map);
|
||||
```
|
||||
|
||||
To generate a source map with the fromString option, you can also use an object:
|
||||
```javascript
|
||||
var result = UglifyJS.minify({"file1.js": "var a = function () {};"}, {
|
||||
outSourceMap: "out.js.map",
|
||||
outFileName: "out.js",
|
||||
fromString: true
|
||||
});
|
||||
```
|
||||
|
||||
Note that the source map is not saved in a file, it's just returned in
|
||||
`result.map`. The value passed for `outSourceMap` is only used to set the
|
||||
`file` attribute in the source map (see [the spec][sm-spec]).
|
||||
`result.map`. The value passed for `outSourceMap` is only used to set
|
||||
`//# sourceMappingURL=out.js.map` in `result.code`. The value of
|
||||
`outFileName` is only used to set `file` attribute in source map file.
|
||||
|
||||
The `file` attribute in the source map (see [the spec][sm-spec]) will
|
||||
use `outFileName` firstly, if it's falsy, then will be deduced from
|
||||
`outSourceMap` (by removing `'.map'`).
|
||||
|
||||
You can set option `sourceMapInline` to be `true` and source map will
|
||||
be appended to code.
|
||||
|
||||
You can also specify sourceRoot property to be included in source map:
|
||||
```javascript
|
||||
@@ -406,9 +721,30 @@ var result = UglifyJS.minify("compiled.js", {
|
||||
// same as before, it returns `code` and `map`
|
||||
```
|
||||
|
||||
If your input source map is not in a file, you can pass it in as an object
|
||||
using the `inSourceMap` argument:
|
||||
|
||||
```javascript
|
||||
var result = UglifyJS.minify("compiled.js", {
|
||||
inSourceMap: JSON.parse(my_source_map_string),
|
||||
outSourceMap: "minified.js.map"
|
||||
});
|
||||
```
|
||||
|
||||
The `inSourceMap` is only used if you also request `outSourceMap` (it makes
|
||||
no sense otherwise).
|
||||
|
||||
To set the source map url, use the `sourceMapUrl` option.
|
||||
If you're using the X-SourceMap header instead, you can just set the `sourceMapUrl` option to false.
|
||||
Defaults to outSourceMap:
|
||||
|
||||
```javascript
|
||||
var result = UglifyJS.minify([ "file1.js" ], {
|
||||
outSourceMap: "out.js.map",
|
||||
sourceMapUrl: "localhost/out.js.map"
|
||||
});
|
||||
```
|
||||
|
||||
Other options:
|
||||
|
||||
- `warnings` (default `false`) — pass `true` to display compressor warnings.
|
||||
@@ -416,7 +752,11 @@ Other options:
|
||||
- `fromString` (default `false`) — if you pass `true` then you can pass
|
||||
JavaScript source code, rather than file names.
|
||||
|
||||
- `mangle` — pass `false` to skip mangling names.
|
||||
- `mangle` (default `true`) — pass `false` to skip mangling names, or pass
|
||||
an object to specify mangling options (see below).
|
||||
|
||||
- `mangleProperties` (default `false`) — pass an object to specify custom
|
||||
mangle property options.
|
||||
|
||||
- `output` (default `null`) — pass an object if you wish to specify
|
||||
additional [output options][codegen]. The defaults are optimized
|
||||
@@ -425,6 +765,49 @@ Other options:
|
||||
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
|
||||
Pass an object to specify custom [compressor options][compressor].
|
||||
|
||||
- `parse` (default {}) — pass an object if you wish to specify some
|
||||
additional [parser options][parser]. (not all options available... see below)
|
||||
|
||||
##### mangle
|
||||
|
||||
- `except` - pass an array of identifiers that should be excluded from mangling
|
||||
|
||||
- `toplevel` — mangle names declared in the toplevel scope (disabled by
|
||||
default).
|
||||
|
||||
- `eval` — mangle names visible in scopes where eval or with are used
|
||||
(disabled by default).
|
||||
|
||||
- `keep_fnames` -- default `false`. Pass `true` to not mangle
|
||||
function names. Useful for code relying on `Function.prototype.name`.
|
||||
See also: the `keep_fnames` [compress option](#compressor-options).
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
//tst.js
|
||||
var globalVar;
|
||||
function funcName(firstLongName, anotherLongName)
|
||||
{
|
||||
var myVariable = firstLongName + anotherLongName;
|
||||
}
|
||||
|
||||
UglifyJS.minify("tst.js").code;
|
||||
// 'function funcName(a,n){}var globalVar;'
|
||||
|
||||
UglifyJS.minify("tst.js", { mangle: { except: ['firstLongName'] } }).code;
|
||||
// 'function funcName(firstLongName,a){}var globalVar;'
|
||||
|
||||
UglifyJS.minify("tst.js", { mangle: { toplevel: true } }).code;
|
||||
// 'function n(n,a){}var a;'
|
||||
```
|
||||
|
||||
##### mangleProperties options
|
||||
|
||||
- `regex` — Pass a RegExp to only mangle certain names (maps to the `--mangle-regex` CLI arguments option)
|
||||
- `ignore_quoted` – Only mangle unquoted property names (maps to the `--mangle-props 2` CLI arguments option)
|
||||
- `debug` – Mangle names with the original name still present (maps to the `--mangle-props-debug` CLI arguments option). Defaults to `false`. Pass an empty string to enable, or a non-empty string to set the suffix.
|
||||
|
||||
We could add more options to `UglifyJS.minify` — if you need additional
|
||||
functionality please suggest!
|
||||
|
||||
@@ -443,6 +826,9 @@ properties are available:
|
||||
|
||||
- `strict` — disable automatic semicolon insertion and support for trailing
|
||||
comma in arrays and objects
|
||||
- `bare_returns` — Allow return outside of functions. (maps to the
|
||||
`--bare-returns` CLI arguments option and available to `minify` `parse`
|
||||
other options object)
|
||||
- `filename` — the name of the file where this code is coming from
|
||||
- `toplevel` — a `toplevel` node (as returned by a previous invocation of
|
||||
`parse`)
|
||||
@@ -453,7 +839,7 @@ something like this:
|
||||
```javascript
|
||||
var toplevel = null;
|
||||
files.forEach(function(file){
|
||||
var code = fs.readFileSync(file);
|
||||
var code = fs.readFileSync(file, "utf8");
|
||||
toplevel = UglifyJS.parse(code, {
|
||||
filename: file,
|
||||
toplevel: toplevel
|
||||
@@ -520,15 +906,18 @@ or, for a shortcut you can do:
|
||||
var code = compressed_ast.print_to_string(options);
|
||||
```
|
||||
|
||||
As usual, `options` is optional. The output stream accepts a lot of otions,
|
||||
As usual, `options` is optional. The output stream accepts a lot of options,
|
||||
most of them documented above in section “Beautifier options”. The two
|
||||
which we care about here are `source_map` and `comments`.
|
||||
|
||||
#### Keeping comments in the output
|
||||
|
||||
In order to keep certain comments in the output you need to pass the
|
||||
`comments` option. Pass a RegExp or a function. If you pass a RegExp, only
|
||||
those comments whose body matches the regexp will be kept. Note that body
|
||||
`comments` option. Pass a RegExp (as string starting and closing with `/`
|
||||
or pass a RegExp object), a boolean or a function. Stringified options
|
||||
`all` and `some` can be passed too, where `some` behaves like it's cli
|
||||
equivalent `--comments` without passing a value. If you pass a RegExp,
|
||||
only those comments whose body matches the RegExp will be kept. Note that body
|
||||
means without the initial `//` or `/*`. If you pass a function, it will be
|
||||
called for every comment in the tree and will receive two arguments: the
|
||||
node that the comment is attached to, and the comment token itself.
|
||||
@@ -577,8 +966,26 @@ The `source_map_options` (optional) can contain the following properties:
|
||||
came from. It can be simply a string in JSON, or a JSON object containing
|
||||
the original source map.
|
||||
|
||||
[acorn]: https://github.com/marijnh/acorn
|
||||
[acorn]: https://github.com/ternjs/acorn
|
||||
[source-map]: https://github.com/mozilla/source-map
|
||||
[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
|
||||
[codegen]: http://lisperator.net/uglifyjs/codegen
|
||||
[compressor]: http://lisperator.net/uglifyjs/compress
|
||||
[parser]: http://lisperator.net/uglifyjs/parser
|
||||
|
||||
#### Harmony
|
||||
|
||||
If you wish to use the experimental [harmony](https://github.com/mishoo/UglifyJS2/commits/harmony)
|
||||
branch to minify ES2015+ (ES6+) code please use the following in your `package.json` file:
|
||||
|
||||
```
|
||||
"uglify-js": "git+https://github.com/mishoo/UglifyJS2.git#harmony"
|
||||
```
|
||||
|
||||
or to directly install the experimental harmony version of uglify:
|
||||
|
||||
```
|
||||
npm install --save-dev uglify-js@github:mishoo/UglifyJS2#harmony
|
||||
```
|
||||
|
||||
See [#448](https://github.com/mishoo/UglifyJS2/issues/448) for additional details.
|
||||
|
||||
24
appveyor.yml
Normal file
24
appveyor.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
environment:
|
||||
matrix:
|
||||
- nodejs_version: "0.10"
|
||||
- nodejs_version: "0.12"
|
||||
- nodejs_version: "4.0"
|
||||
- nodejs_version: "6.0"
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
install:
|
||||
- ps: Install-Product node $env:nodejs_version $env:platform
|
||||
- npm install
|
||||
|
||||
test_script:
|
||||
- node --version
|
||||
- npm --version
|
||||
- npm test
|
||||
|
||||
build: off
|
||||
77
bin/extract-props.js
Executable file
77
bin/extract-props.js
Executable file
@@ -0,0 +1,77 @@
|
||||
#! /usr/bin/env node
|
||||
|
||||
"use strict";
|
||||
|
||||
var U2 = require("../tools/node");
|
||||
var fs = require("fs");
|
||||
var yargs = require("yargs");
|
||||
var ARGS = yargs
|
||||
.describe("o", "Output file")
|
||||
.argv;
|
||||
var files = ARGS._.slice();
|
||||
var output = {
|
||||
vars: {},
|
||||
props: {}
|
||||
};
|
||||
|
||||
if (ARGS.o) try {
|
||||
output = JSON.parse(fs.readFileSync(ARGS.o, "utf8"));
|
||||
} catch(ex) {}
|
||||
|
||||
files.forEach(getProps);
|
||||
|
||||
if (ARGS.o) {
|
||||
fs.writeFileSync(ARGS.o, JSON.stringify(output, null, 2), "utf8");
|
||||
} else {
|
||||
console.log("%s", JSON.stringify(output, null, 2));
|
||||
}
|
||||
|
||||
function getProps(filename) {
|
||||
var code = fs.readFileSync(filename, "utf8");
|
||||
var ast = U2.parse(code);
|
||||
|
||||
ast.walk(new U2.TreeWalker(function(node){
|
||||
if (node instanceof U2.AST_ObjectKeyVal) {
|
||||
add(node.key);
|
||||
}
|
||||
else if (node instanceof U2.AST_ObjectProperty) {
|
||||
add(node.key.name);
|
||||
}
|
||||
else if (node instanceof U2.AST_Dot) {
|
||||
add(node.property);
|
||||
}
|
||||
else if (node instanceof U2.AST_Sub) {
|
||||
addStrings(node.property);
|
||||
}
|
||||
}));
|
||||
|
||||
function addStrings(node) {
|
||||
var out = {};
|
||||
try {
|
||||
(function walk(node){
|
||||
node.walk(new U2.TreeWalker(function(node){
|
||||
if (node instanceof U2.AST_Seq) {
|
||||
walk(node.cdr);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof U2.AST_String) {
|
||||
add(node.value);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof U2.AST_Conditional) {
|
||||
walk(node.consequent);
|
||||
walk(node.alternative);
|
||||
return true;
|
||||
}
|
||||
throw out;
|
||||
}));
|
||||
})(node);
|
||||
} catch(ex) {
|
||||
if (ex !== out) throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
function add(name) {
|
||||
output.props[name] = true;
|
||||
}
|
||||
}
|
||||
445
bin/uglifyjs
445
bin/uglifyjs
@@ -5,11 +5,13 @@
|
||||
|
||||
var UglifyJS = require("../tools/node");
|
||||
var sys = require("util");
|
||||
var optimist = require("optimist");
|
||||
var yargs = require("yargs");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var async = require("async");
|
||||
var acorn;
|
||||
var ARGS = optimist
|
||||
var screw_ie8 = true;
|
||||
var ARGS = yargs
|
||||
.usage("$0 input1.js [input2.js ...] [options]\n\
|
||||
Use a single dash to read input from the standard input.\
|
||||
\n\n\
|
||||
@@ -20,12 +22,17 @@ mangling you need to use `-c` and `-m`.\
|
||||
")
|
||||
.describe("source-map", "Specify an output file where to generate source map.")
|
||||
.describe("source-map-root", "The path to the original source to be included in the source map.")
|
||||
.describe("source-map-url", "The path to the source map to be added in //@ sourceMappingURL. Defaults to the value passed with --source-map.")
|
||||
.describe("source-map-url", "The path to the source map to be added in //# sourceMappingURL. Defaults to the value passed with --source-map.")
|
||||
.describe("source-map-inline", "Write base64-encoded source map to the end of js output. Disabled by default")
|
||||
.describe("source-map-include-sources", "Pass this flag if you want to include the content of source files in the source map as sourcesContent property.")
|
||||
.describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
|
||||
.describe("screw-ie8", "Pass this flag if you don't care about full compliance with Internet Explorer 6-8 quirks (by default UglifyJS will try to be IE-proof).")
|
||||
.describe("screw-ie8", "Do not support Internet Explorer 6/7/8. This flag is enabled by default.")
|
||||
.describe("support-ie8", "Support non-standard Internet Explorer 6/7/8 javascript. Note: may generate incorrect code for try/catch in ES5 compliant browsers.")
|
||||
.describe("expr", "Parse a single expression, rather than a program (for parsing JSON)")
|
||||
.describe("p", "Skip prefix for original filenames that appear in source maps. \
|
||||
For example -p 3 will drop 3 directories from file names and ensure they are relative paths.")
|
||||
For example -p 3 will drop 3 directories from file names and ensure they are relative paths. \
|
||||
You can also specify -p relative, which will make UglifyJS figure out itself the relative paths between original sources, \
|
||||
the source map and the output file.")
|
||||
.describe("o", "Output file (default STDOUT).")
|
||||
.describe("b", "Beautify output/specify output options.")
|
||||
.describe("m", "Mangle names/pass mangler options.")
|
||||
@@ -40,11 +47,15 @@ Use -c with no argument to use the default compression options.")
|
||||
By default this works like Google Closure, keeping JSDoc-style comments that contain \"@license\" or \"@preserve\". \
|
||||
You can optionally pass one of the following arguments to this flag:\n\
|
||||
- \"all\" to keep all comments\n\
|
||||
- a valid JS regexp (needs to start with a slash) to keep only comments that match.\n\
|
||||
- a valid JS RegExp like `/foo/`or `/^!/` to keep only matching comments.\n\
|
||||
\
|
||||
Note that currently not *all* comments can be kept when compression is on, \
|
||||
because of dead code removal or cascading statements into sequences.")
|
||||
|
||||
.describe("preamble", "Preamble to prepend to the output. You can use this to insert a \
|
||||
comment, for example for licensing information. This will not be \
|
||||
parsed, but the source map will adjust for its presence.")
|
||||
|
||||
.describe("stats", "Display operations run time on STDERR.")
|
||||
.describe("acorn", "Use Acorn for parsing.")
|
||||
.describe("spidermonkey", "Assume input files are SpiderMonkey AST format (as JSON).")
|
||||
@@ -55,6 +66,18 @@ You need to pass an argument to this option to specify the name that your module
|
||||
.describe("lint", "Display some scope warnings")
|
||||
.describe("v", "Verbose")
|
||||
.describe("V", "Print version number and exit.")
|
||||
.describe("noerr", "Don't throw an error for unknown options in -c, -b or -m.")
|
||||
.describe("bare-returns", "Allow return outside of functions. Useful when minifying CommonJS modules.")
|
||||
.describe("keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.")
|
||||
.describe("quotes", "Quote style (0 - auto, 1 - single, 2 - double, 3 - original)")
|
||||
.describe("reserved-file", "File containing reserved names")
|
||||
.describe("reserve-domprops", "Make (most?) DOM properties reserved for --mangle-props")
|
||||
.describe("mangle-props", "Mangle property names (0 - disabled, 1 - mangle all properties, 2 - mangle unquoted properies)")
|
||||
.describe("mangle-regex", "Only mangle property names matching the regex")
|
||||
.describe("name-cache", "File to hold mangled names mappings")
|
||||
.describe("pure-funcs", "List of functions that can be safely removed if their return value is not used")
|
||||
.describe("dump-spidermonkey-ast", "Dump SpiderMonkey AST to stdout.")
|
||||
.describe("wrap-iife", "Wrap IIFEs in parenthesis. Note: this disables the negate_iife compression option")
|
||||
|
||||
.alias("p", "prefix")
|
||||
.alias("o", "output")
|
||||
@@ -66,28 +89,52 @@ You need to pass an argument to this option to specify the name that your module
|
||||
.alias("r", "reserved")
|
||||
.alias("V", "version")
|
||||
.alias("e", "enclose")
|
||||
.alias("q", "quotes")
|
||||
|
||||
.string("source-map")
|
||||
.string("source-map-root")
|
||||
.string("source-map-url")
|
||||
.string("b")
|
||||
.string("beautify")
|
||||
.string("m")
|
||||
.string("mangle")
|
||||
.string("mangle-props-debug")
|
||||
.string("c")
|
||||
.string("compress")
|
||||
.string("d")
|
||||
.string("define")
|
||||
.string("e")
|
||||
.string("enclose")
|
||||
.string("comments")
|
||||
.string("wrap")
|
||||
.string("p")
|
||||
.string("prefix")
|
||||
.string("name-cache")
|
||||
|
||||
.array("reserved-file")
|
||||
.array("pure-funcs")
|
||||
|
||||
.boolean("expr")
|
||||
.boolean("source-map-inline")
|
||||
.boolean("source-map-include-sources")
|
||||
.boolean("screw-ie8")
|
||||
.boolean("support-ie8")
|
||||
.boolean("export-all")
|
||||
.boolean("self")
|
||||
.boolean("v")
|
||||
.boolean("verbose")
|
||||
.boolean("stats")
|
||||
.boolean("acorn")
|
||||
.boolean("spidermonkey")
|
||||
.boolean("dump-spidermonkey-ast")
|
||||
.boolean("lint")
|
||||
.boolean("V")
|
||||
.boolean("version")
|
||||
.boolean("noerr")
|
||||
.boolean("bare-returns")
|
||||
.boolean("keep-fnames")
|
||||
.boolean("reserve-domprops")
|
||||
.boolean("wrap-iife")
|
||||
|
||||
.wrap(80)
|
||||
|
||||
@@ -96,20 +143,26 @@ You need to pass an argument to this option to specify the name that your module
|
||||
|
||||
normalize(ARGS);
|
||||
|
||||
if (ARGS.noerr) {
|
||||
UglifyJS.DefaultsError.croak = function(msg, defs) {
|
||||
print_error("WARN: " + msg);
|
||||
};
|
||||
}
|
||||
|
||||
if (ARGS.version || ARGS.V) {
|
||||
var json = require("../package.json");
|
||||
sys.puts(json.name + ' ' + json.version);
|
||||
print(json.name + ' ' + json.version);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (ARGS.ast_help) {
|
||||
var desc = UglifyJS.describe_ast();
|
||||
sys.puts(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
|
||||
print(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (ARGS.h || ARGS.help) {
|
||||
sys.puts(optimist.help());
|
||||
print(yargs.help());
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -120,115 +173,173 @@ if (ARGS.acorn) {
|
||||
var COMPRESS = getOptions("c", true);
|
||||
var MANGLE = getOptions("m", true);
|
||||
var BEAUTIFY = getOptions("b", true);
|
||||
var RESERVED = null;
|
||||
|
||||
if (ARGS.reserved_file) ARGS.reserved_file.forEach(function(filename){
|
||||
RESERVED = UglifyJS.readReservedFile(filename, RESERVED);
|
||||
});
|
||||
|
||||
if (ARGS.reserve_domprops) {
|
||||
RESERVED = UglifyJS.readDefaultReservedFile(RESERVED);
|
||||
}
|
||||
|
||||
if (ARGS.d) {
|
||||
if (COMPRESS) COMPRESS.global_defs = getOptions("d");
|
||||
}
|
||||
|
||||
if (ARGS.screw_ie8) {
|
||||
if (COMPRESS) COMPRESS.screw_ie8 = true;
|
||||
if (MANGLE) MANGLE.screw_ie8 = true;
|
||||
if (ARGS.pure_funcs) {
|
||||
if (COMPRESS) COMPRESS.pure_funcs = ARGS.pure_funcs;
|
||||
}
|
||||
|
||||
if (ARGS.r) {
|
||||
if (MANGLE) MANGLE.except = ARGS.r.replace(/^\s+|\s+$/g).split(/\s*,+\s*/);
|
||||
}
|
||||
|
||||
if (RESERVED && MANGLE) {
|
||||
if (!MANGLE.except) MANGLE.except = RESERVED.vars;
|
||||
else MANGLE.except = MANGLE.except.concat(RESERVED.vars);
|
||||
}
|
||||
|
||||
function readNameCache(key) {
|
||||
return UglifyJS.readNameCache(ARGS.name_cache, key);
|
||||
}
|
||||
|
||||
function writeNameCache(key, cache) {
|
||||
return UglifyJS.writeNameCache(ARGS.name_cache, key, cache);
|
||||
}
|
||||
|
||||
function extractRegex(str) {
|
||||
if (/^\/.*\/[a-zA-Z]*$/.test(str)) {
|
||||
var regex_pos = str.lastIndexOf("/");
|
||||
return new RegExp(str.substr(1, regex_pos - 1), str.substr(regex_pos + 1));
|
||||
} else {
|
||||
throw new Error("Invalid regular expression: " + str);
|
||||
}
|
||||
}
|
||||
|
||||
if (ARGS.quotes === true) {
|
||||
ARGS.quotes = 3;
|
||||
}
|
||||
|
||||
if (ARGS.mangle_props === true) {
|
||||
ARGS.mangle_props = 1;
|
||||
} else if (ARGS.mangle_props === "unquoted") {
|
||||
ARGS.mangle_props = 2;
|
||||
}
|
||||
|
||||
var OUTPUT_OPTIONS = {
|
||||
beautify: BEAUTIFY ? true : false
|
||||
beautify : BEAUTIFY ? true : false,
|
||||
max_line_len : 32000,
|
||||
preamble : ARGS.preamble || null,
|
||||
quote_style : ARGS.quotes != null ? ARGS.quotes : 0,
|
||||
};
|
||||
|
||||
if (ARGS.mangle_props == 2) {
|
||||
OUTPUT_OPTIONS.keep_quoted_props = true;
|
||||
if (COMPRESS && !("properties" in COMPRESS))
|
||||
COMPRESS.properties = false;
|
||||
}
|
||||
|
||||
if (ARGS.support_ie8 === true && ARGS.screw_ie8 !== true) {
|
||||
screw_ie8 = false;
|
||||
}
|
||||
|
||||
if (COMPRESS) COMPRESS.screw_ie8 = screw_ie8;
|
||||
if (MANGLE) MANGLE.screw_ie8 = screw_ie8;
|
||||
OUTPUT_OPTIONS.screw_ie8 = screw_ie8;
|
||||
|
||||
if (ARGS.keep_fnames) {
|
||||
if (COMPRESS) COMPRESS.keep_fnames = true;
|
||||
if (MANGLE) MANGLE.keep_fnames = true;
|
||||
}
|
||||
|
||||
if (ARGS.wrap_iife) {
|
||||
if (COMPRESS) COMPRESS.negate_iife = false;
|
||||
OUTPUT_OPTIONS.wrap_iife = true;
|
||||
}
|
||||
|
||||
if (BEAUTIFY)
|
||||
UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY);
|
||||
|
||||
if (ARGS.comments) {
|
||||
if (/^\//.test(ARGS.comments)) {
|
||||
OUTPUT_OPTIONS.comments = new Function("return(" + ARGS.comments + ")")();
|
||||
} else if (ARGS.comments == "all") {
|
||||
OUTPUT_OPTIONS.comments = true;
|
||||
} else {
|
||||
OUTPUT_OPTIONS.comments = function(node, comment) {
|
||||
var text = comment.value;
|
||||
var type = comment.type;
|
||||
if (type == "comment2") {
|
||||
// multiline comment
|
||||
return /@preserve|@license|@cc_on/i.test(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ARGS.comments === "") {
|
||||
OUTPUT_OPTIONS.comments = "some";
|
||||
} else {
|
||||
OUTPUT_OPTIONS.comments = ARGS.comments;
|
||||
}
|
||||
|
||||
var files = ARGS._.slice();
|
||||
|
||||
if (process.platform === "win32")
|
||||
files = UglifyJS.simple_glob(files);
|
||||
|
||||
if (ARGS.self) {
|
||||
if (files.length > 0) {
|
||||
sys.error("WARN: Ignoring input files since --self was passed");
|
||||
print_error("WARN: Ignoring input files since --self was passed");
|
||||
}
|
||||
files = UglifyJS.FILES;
|
||||
if (!ARGS.wrap) ARGS.wrap = "UglifyJS";
|
||||
ARGS.export_all = true;
|
||||
}
|
||||
|
||||
var ORIG_MAP = ARGS.in_source_map;
|
||||
|
||||
if (ORIG_MAP) {
|
||||
if (ORIG_MAP && ORIG_MAP != "inline") {
|
||||
ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
|
||||
if (files.length == 0) {
|
||||
sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file);
|
||||
print_error("INFO: Using file from the input source map: " + ORIG_MAP.file);
|
||||
files = [ ORIG_MAP.file ];
|
||||
}
|
||||
if (ARGS.source_map_root == null) {
|
||||
ARGS.source_map_root = ORIG_MAP.sourceRoot;
|
||||
}
|
||||
}
|
||||
|
||||
if (files.length == 0) {
|
||||
files = [ "-" ];
|
||||
}
|
||||
|
||||
if (files.indexOf("-") >= 0 && ARGS.source_map) {
|
||||
sys.error("ERROR: Source map doesn't work with input from STDIN");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (files.filter(function(el){ return el == "-" }).length > 1) {
|
||||
sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var STATS = {};
|
||||
var OUTPUT_FILE = ARGS.o;
|
||||
var TOPLEVEL = null;
|
||||
|
||||
var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({
|
||||
file: OUTPUT_FILE,
|
||||
root: ARGS.source_map_root,
|
||||
orig: ORIG_MAP,
|
||||
}) : null;
|
||||
|
||||
OUTPUT_OPTIONS.source_map = SOURCE_MAP;
|
||||
|
||||
try {
|
||||
var output = UglifyJS.OutputStream(OUTPUT_OPTIONS);
|
||||
var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.DefaultsError) {
|
||||
sys.error(ex.msg);
|
||||
sys.error("Supported options:");
|
||||
sys.error(sys.inspect(ex.defs));
|
||||
if (ORIG_MAP == "inline") {
|
||||
if (files.length > 1) {
|
||||
print_error("ERROR: Inline source map only works with singular input");
|
||||
process.exit(1);
|
||||
}
|
||||
if (ARGS.acorn || ARGS.spidermonkey) {
|
||||
print_error("ERROR: Inline source map only works with built-in parser");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (files.indexOf("-") >= 0 && ARGS.source_map) {
|
||||
print_error("ERROR: Source map doesn't work with input from STDIN");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (files.filter(function(el){ return el == "-" }).length > 1) {
|
||||
print_error("ERROR: Can read a single file from STDIN (two or more dashes specified)");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var STATS = {};
|
||||
var TOPLEVEL = null;
|
||||
var P_RELATIVE = ARGS.p && ARGS.p == "relative";
|
||||
var SOURCES_CONTENT = {};
|
||||
|
||||
async.eachLimit(files, 1, function (file, cb) {
|
||||
read_whole_file(file, function (err, code) {
|
||||
if (err) {
|
||||
sys.error("ERROR: can't read file: " + filename);
|
||||
print_error("ERROR: can't read file: " + file);
|
||||
process.exit(1);
|
||||
}
|
||||
if (ARGS.p != null) {
|
||||
file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/");
|
||||
if (ORIG_MAP == "inline") {
|
||||
ORIG_MAP = read_source_map(code);
|
||||
}
|
||||
if (ARGS.p != null) {
|
||||
if (P_RELATIVE) {
|
||||
file = path.relative(path.dirname(ARGS.source_map), file).replace(/\\/g, '/');
|
||||
} else {
|
||||
var p = parseInt(ARGS.p, 10);
|
||||
if (!isNaN(p)) {
|
||||
file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/");
|
||||
}
|
||||
}
|
||||
}
|
||||
SOURCES_CONTENT[file] = code;
|
||||
time_it("parse", function(){
|
||||
if (ARGS.spidermonkey) {
|
||||
var program = JSON.parse(code);
|
||||
@@ -238,45 +349,117 @@ async.eachLimit(files, 1, function (file, cb) {
|
||||
else if (ARGS.acorn) {
|
||||
TOPLEVEL = acorn.parse(code, {
|
||||
locations : true,
|
||||
trackComments : true,
|
||||
sourceFile : file,
|
||||
program : TOPLEVEL
|
||||
});
|
||||
}
|
||||
else {
|
||||
TOPLEVEL = UglifyJS.parse(code, {
|
||||
filename : file,
|
||||
toplevel : TOPLEVEL,
|
||||
expression : ARGS.expr,
|
||||
});
|
||||
try {
|
||||
TOPLEVEL = UglifyJS.parse(code, {
|
||||
filename : file,
|
||||
toplevel : TOPLEVEL,
|
||||
expression : ARGS.expr,
|
||||
bare_returns : ARGS.bare_returns,
|
||||
});
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
||||
print_error("Parse error at " + file + ":" + ex.line + "," + ex.col);
|
||||
var col = ex.col;
|
||||
var line = code.split(/\r?\n/)[ex.line - (col ? 1 : 2)];
|
||||
if (line) {
|
||||
if (col > 40) {
|
||||
line = line.slice(col - 40);
|
||||
col = 40;
|
||||
}
|
||||
if (col) {
|
||||
print_error(line.slice(0, 80));
|
||||
print_error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
||||
} else {
|
||||
print_error(line.slice(-40));
|
||||
print_error(line.slice(-40).replace(/\S/g, " ") + "^");
|
||||
}
|
||||
}
|
||||
print_error(ex.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
};
|
||||
});
|
||||
cb();
|
||||
});
|
||||
}, function () {
|
||||
var OUTPUT_FILE = ARGS.o;
|
||||
|
||||
var SOURCE_MAP = (ARGS.source_map || ARGS.source_map_inline) ? UglifyJS.SourceMap({
|
||||
file: P_RELATIVE ? path.relative(path.dirname(ARGS.source_map), OUTPUT_FILE) : OUTPUT_FILE,
|
||||
root: ARGS.source_map_root || ORIG_MAP && ORIG_MAP.sourceRoot,
|
||||
orig: ORIG_MAP,
|
||||
}) : null;
|
||||
|
||||
OUTPUT_OPTIONS.source_map = SOURCE_MAP;
|
||||
|
||||
try {
|
||||
var output = UglifyJS.OutputStream(OUTPUT_OPTIONS);
|
||||
var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.DefaultsError) {
|
||||
print_error(ex.message);
|
||||
print_error("Supported options:");
|
||||
print_error(sys.inspect(ex.defs));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
|
||||
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
|
||||
});
|
||||
|
||||
if (ARGS.wrap) {
|
||||
if (ARGS.wrap != null) {
|
||||
TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all);
|
||||
}
|
||||
|
||||
if (ARGS.enclose) {
|
||||
if (ARGS.enclose != null) {
|
||||
var arg_parameter_list = ARGS.enclose;
|
||||
|
||||
if (!(arg_parameter_list instanceof Array)) {
|
||||
if (arg_parameter_list === true) {
|
||||
arg_parameter_list = [];
|
||||
}
|
||||
else if (!(arg_parameter_list instanceof Array)) {
|
||||
arg_parameter_list = [arg_parameter_list];
|
||||
}
|
||||
|
||||
TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list);
|
||||
}
|
||||
|
||||
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint;
|
||||
if (ARGS.mangle_props || ARGS.name_cache) (function(){
|
||||
var reserved = RESERVED ? RESERVED.props : null;
|
||||
var cache = readNameCache("props");
|
||||
var regex;
|
||||
|
||||
try {
|
||||
regex = ARGS.mangle_regex ? extractRegex(ARGS.mangle_regex) : null;
|
||||
} catch (e) {
|
||||
print_error("ERROR: Invalid --mangle-regex: " + e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
TOPLEVEL = UglifyJS.mangle_properties(TOPLEVEL, {
|
||||
reserved : reserved,
|
||||
cache : cache,
|
||||
only_cache : !ARGS.mangle_props,
|
||||
regex : regex,
|
||||
ignore_quoted : ARGS.mangle_props == 2,
|
||||
debug : typeof ARGS.mangle_props_debug === "undefined" ? false : ARGS.mangle_props_debug
|
||||
});
|
||||
writeNameCache("props", cache);
|
||||
})();
|
||||
|
||||
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint
|
||||
var TL_CACHE = readNameCache("vars");
|
||||
if (MANGLE) MANGLE.cache = TL_CACHE;
|
||||
|
||||
if (SCOPE_IS_NEEDED) {
|
||||
time_it("scope", function(){
|
||||
TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 });
|
||||
TOPLEVEL.figure_out_scope(MANGLE || { screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||
if (ARGS.lint) {
|
||||
TOPLEVEL.scope_warnings();
|
||||
}
|
||||
@@ -285,14 +468,14 @@ async.eachLimit(files, 1, function (file, cb) {
|
||||
|
||||
if (COMPRESS) {
|
||||
time_it("squeeze", function(){
|
||||
TOPLEVEL = TOPLEVEL.transform(compressor);
|
||||
TOPLEVEL = compressor.compress(TOPLEVEL);
|
||||
});
|
||||
}
|
||||
|
||||
if (SCOPE_IS_NEEDED) {
|
||||
time_it("scope", function(){
|
||||
TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 });
|
||||
if (MANGLE) {
|
||||
TOPLEVEL.figure_out_scope(MANGLE || { screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||
if (MANGLE && !TL_CACHE) {
|
||||
TOPLEVEL.compute_char_frequency(MANGLE);
|
||||
}
|
||||
});
|
||||
@@ -301,30 +484,54 @@ async.eachLimit(files, 1, function (file, cb) {
|
||||
if (MANGLE) time_it("mangle", function(){
|
||||
TOPLEVEL.mangle_names(MANGLE);
|
||||
});
|
||||
time_it("generate", function(){
|
||||
TOPLEVEL.print(output);
|
||||
});
|
||||
|
||||
output = output.get();
|
||||
writeNameCache("vars", TL_CACHE);
|
||||
|
||||
if (SOURCE_MAP) {
|
||||
fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
|
||||
output += "\n/*\n//@ sourceMappingURL=" + (ARGS.source_map_url || ARGS.source_map) + "\n*/";
|
||||
if (ARGS.source_map_include_sources) {
|
||||
for (var file in SOURCES_CONTENT) {
|
||||
if (SOURCES_CONTENT.hasOwnProperty(file)) {
|
||||
SOURCE_MAP.get().setSourceContent(file, SOURCES_CONTENT[file]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OUTPUT_FILE) {
|
||||
fs.writeFileSync(OUTPUT_FILE, output, "utf8");
|
||||
if (ARGS.dump_spidermonkey_ast) {
|
||||
print(JSON.stringify(TOPLEVEL.to_mozilla_ast(), null, 2));
|
||||
} else {
|
||||
sys.print(output);
|
||||
sys.error("\n");
|
||||
time_it("generate", function(){
|
||||
TOPLEVEL.print(output);
|
||||
});
|
||||
|
||||
output = output.get();
|
||||
|
||||
if (SOURCE_MAP) {
|
||||
if (ARGS.source_map_inline) {
|
||||
var base64_string = new Buffer(SOURCE_MAP.toString()).toString('base64');
|
||||
output += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + base64_string;
|
||||
} else {
|
||||
fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
|
||||
var source_map_url = ARGS.source_map_url || (
|
||||
P_RELATIVE
|
||||
? path.relative(path.dirname(OUTPUT_FILE), ARGS.source_map)
|
||||
: ARGS.source_map
|
||||
);
|
||||
output += "\n//# sourceMappingURL=" + source_map_url;
|
||||
}
|
||||
}
|
||||
|
||||
if (OUTPUT_FILE) {
|
||||
fs.writeFileSync(OUTPUT_FILE, output, "utf8");
|
||||
} else {
|
||||
print(output);
|
||||
}
|
||||
}
|
||||
|
||||
if (ARGS.stats) {
|
||||
sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", {
|
||||
print_error(UglifyJS.string_template("Timing information (compressed {count} files):", {
|
||||
count: files.length
|
||||
}));
|
||||
for (var i in STATS) if (STATS.hasOwnProperty(i)) {
|
||||
sys.error(UglifyJS.string_template("- {name}: {time}s", {
|
||||
print_error(UglifyJS.string_template("- {name}: {time}s", {
|
||||
name: i,
|
||||
time: (STATS[i] / 1000).toFixed(3)
|
||||
}));
|
||||
@@ -341,34 +548,39 @@ function normalize(o) {
|
||||
}
|
||||
}
|
||||
|
||||
function getOptions(x, constants) {
|
||||
x = ARGS[x];
|
||||
if (!x) return null;
|
||||
function getOptions(flag, constants) {
|
||||
var x = ARGS[flag];
|
||||
if (x == null || x === false) return null;
|
||||
var ret = {};
|
||||
if (x !== true) {
|
||||
if (x !== "") {
|
||||
if (Array.isArray(x)) x = x.map(function (v) { return "(" + v + ")"; }).join(", ");
|
||||
|
||||
var ast;
|
||||
try {
|
||||
ast = UglifyJS.parse(x);
|
||||
ast = UglifyJS.parse(x, { expression: true });
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
||||
sys.error("Error parsing arguments in: " + x);
|
||||
print_error("Error parsing arguments for flag `" + flag + "': " + x);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
ast.walk(new UglifyJS.TreeWalker(function(node){
|
||||
if (node instanceof UglifyJS.AST_Toplevel) return; // descend
|
||||
if (node instanceof UglifyJS.AST_SimpleStatement) return; // descend
|
||||
if (node instanceof UglifyJS.AST_Seq) return; // descend
|
||||
if (node instanceof UglifyJS.AST_Assign) {
|
||||
var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_");
|
||||
var name = node.left.print_to_string().replace(/-/g, "_");
|
||||
var value = node.right;
|
||||
if (constants)
|
||||
value = new Function("return (" + value.print_to_string() + ")")();
|
||||
ret[name] = value;
|
||||
return true; // no descend
|
||||
}
|
||||
sys.error(node.TYPE)
|
||||
sys.error("Error parsing arguments in: " + x);
|
||||
if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_Binary) {
|
||||
var name = node.print_to_string().replace(/-/g, "_");
|
||||
ret[name] = true;
|
||||
return true; // no descend
|
||||
}
|
||||
print_error(node.TYPE)
|
||||
print_error("Error parsing arguments for flag `" + flag + "': " + x);
|
||||
process.exit(1);
|
||||
}));
|
||||
}
|
||||
@@ -390,6 +602,15 @@ function read_whole_file(filename, cb) {
|
||||
}
|
||||
}
|
||||
|
||||
function read_source_map(code) {
|
||||
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
|
||||
if (!match) {
|
||||
print_error("WARN: inline source map not found");
|
||||
return null;
|
||||
}
|
||||
return JSON.parse(new Buffer(match[2], "base64"));
|
||||
}
|
||||
|
||||
function time_it(name, cont) {
|
||||
var t1 = new Date().getTime();
|
||||
var ret = cont();
|
||||
@@ -400,3 +621,11 @@ function time_it(name, cont) {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function print_error(msg) {
|
||||
console.error("%s", msg);
|
||||
}
|
||||
|
||||
function print(txt) {
|
||||
console.log("%s", txt);
|
||||
}
|
||||
|
||||
556
lib/ast.js
556
lib/ast.js
@@ -71,7 +71,7 @@ function DEFNODE(type, props, methods, base) {
|
||||
if (type) {
|
||||
ctor.prototype.TYPE = ctor.TYPE = type;
|
||||
}
|
||||
if (methods) for (i in methods) if (methods.hasOwnProperty(i)) {
|
||||
if (methods) for (i in methods) if (HOP(methods, i)) {
|
||||
if (/^\$/.test(i)) {
|
||||
ctor[i.substr(1)] = methods[i];
|
||||
} else {
|
||||
@@ -81,10 +81,13 @@ function DEFNODE(type, props, methods, base) {
|
||||
ctor.DEFMETHOD = function(name, method) {
|
||||
this.prototype[name] = method;
|
||||
};
|
||||
if (typeof exports !== "undefined") {
|
||||
exports["AST_" + type] = ctor;
|
||||
}
|
||||
return ctor;
|
||||
};
|
||||
|
||||
var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", {
|
||||
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file raw", {
|
||||
}, null);
|
||||
|
||||
var AST_Node = DEFNODE("Node", "start end", {
|
||||
@@ -120,11 +123,12 @@ var AST_Debugger = DEFNODE("Debugger", null, {
|
||||
$documentation: "Represents a debugger statement",
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_Directive = DEFNODE("Directive", "value scope", {
|
||||
var AST_Directive = DEFNODE("Directive", "value scope quote", {
|
||||
$documentation: "Represents a directive, like \"use strict\";",
|
||||
$propdoc: {
|
||||
value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
|
||||
scope: "[AST_Scope/S] The scope that this directive affects"
|
||||
scope: "[AST_Scope/S] The scope that this directive affects",
|
||||
quote: "[string] the original quote character"
|
||||
},
|
||||
}, AST_Statement);
|
||||
|
||||
@@ -141,12 +145,13 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
|
||||
}, AST_Statement);
|
||||
|
||||
function walk_body(node, visitor) {
|
||||
if (node.body instanceof AST_Statement) {
|
||||
node.body._walk(visitor);
|
||||
var body = node.body;
|
||||
if (body instanceof AST_Node) {
|
||||
body._walk(visitor);
|
||||
}
|
||||
else for (var i = 0, len = body.length; i < len; i++) {
|
||||
body[i]._walk(visitor);
|
||||
}
|
||||
else node.body.forEach(function(stat){
|
||||
stat._walk(visitor);
|
||||
});
|
||||
};
|
||||
|
||||
var AST_Block = DEFNODE("Block", "body", {
|
||||
@@ -197,25 +202,35 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
|
||||
}
|
||||
}, AST_StatementWithBody);
|
||||
|
||||
var AST_IterationStatement = DEFNODE("IterationStatement", null, {
|
||||
$documentation: "Internal class. All loops inherit from it."
|
||||
}, AST_StatementWithBody);
|
||||
|
||||
var AST_DWLoop = DEFNODE("DWLoop", "condition", {
|
||||
$documentation: "Base class for do/while statements",
|
||||
$propdoc: {
|
||||
condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement"
|
||||
},
|
||||
}
|
||||
}, AST_IterationStatement);
|
||||
|
||||
var AST_Do = DEFNODE("Do", null, {
|
||||
$documentation: "A `do` statement",
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.body._walk(visitor);
|
||||
this.condition._walk(visitor);
|
||||
});
|
||||
}
|
||||
}, AST_DWLoop);
|
||||
|
||||
var AST_While = DEFNODE("While", null, {
|
||||
$documentation: "A `while` statement",
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.condition._walk(visitor);
|
||||
this.body._walk(visitor);
|
||||
});
|
||||
}
|
||||
}, AST_StatementWithBody);
|
||||
|
||||
var AST_Do = DEFNODE("Do", null, {
|
||||
$documentation: "A `do` statement",
|
||||
}, AST_DWLoop);
|
||||
|
||||
var AST_While = DEFNODE("While", null, {
|
||||
$documentation: "A `while` statement",
|
||||
}, AST_DWLoop);
|
||||
|
||||
var AST_For = DEFNODE("For", "init condition step", {
|
||||
@@ -233,7 +248,7 @@ var AST_For = DEFNODE("For", "init condition step", {
|
||||
this.body._walk(visitor);
|
||||
});
|
||||
}
|
||||
}, AST_StatementWithBody);
|
||||
}, AST_IterationStatement);
|
||||
|
||||
var AST_ForIn = DEFNODE("ForIn", "init name object", {
|
||||
$documentation: "A `for ... in` statement",
|
||||
@@ -249,7 +264,11 @@ var AST_ForIn = DEFNODE("ForIn", "init name object", {
|
||||
this.body._walk(visitor);
|
||||
});
|
||||
}
|
||||
}, AST_StatementWithBody);
|
||||
}, AST_IterationStatement);
|
||||
|
||||
var AST_ForOf = DEFNODE("ForOf", null, {
|
||||
$documentation: "A `for ... of` statement",
|
||||
}, AST_ForIn);
|
||||
|
||||
var AST_With = DEFNODE("With", "expression", {
|
||||
$documentation: "A `with` statement",
|
||||
@@ -278,6 +297,13 @@ var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_
|
||||
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
|
||||
cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
|
||||
},
|
||||
get_defun_scope: function () {
|
||||
var self = this;
|
||||
while (self.is_block_scope() && self.parent_scope) {
|
||||
self = self.parent_scope;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
}, AST_Block);
|
||||
|
||||
var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
@@ -291,10 +317,10 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
var parameters = [];
|
||||
|
||||
arg_parameter_pairs.forEach(function(pair) {
|
||||
var split = pair.split(":");
|
||||
var splitAt = pair.lastIndexOf(":");
|
||||
|
||||
args.push(split[0]);
|
||||
parameters.push(split[1]);
|
||||
args.push(pair.substr(0, splitAt));
|
||||
parameters.push(pair.substr(splitAt + 1));
|
||||
});
|
||||
|
||||
var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
|
||||
@@ -318,12 +344,11 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
}
|
||||
}));
|
||||
}
|
||||
var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))";
|
||||
var wrapped_tl = "(function(exports, global){ '$ORIG'; '$EXPORTS'; global['" + name + "'] = exports; }({}, (function(){return this}())))";
|
||||
wrapped_tl = parse(wrapped_tl);
|
||||
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
|
||||
if (node instanceof AST_SimpleStatement) {
|
||||
node = node.body;
|
||||
if (node instanceof AST_String) switch (node.getValue()) {
|
||||
if (node instanceof AST_Directive) {
|
||||
switch (node.value) {
|
||||
case "$ORIG":
|
||||
return MAP.splice(self.body);
|
||||
case "$EXPORTS":
|
||||
@@ -348,36 +373,199 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
}
|
||||
}, AST_Scope);
|
||||
|
||||
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
|
||||
var AST_Expansion = DEFNODE("Expansion", "expression", {
|
||||
$documentation: "An expandible argument, such as ...rest, a splat, such as [1,2,...all], or an expansion in a variable declaration, such as var [first, ...rest] = list",
|
||||
$propdoc: {
|
||||
expression: "AST_Symbol the thing to be expanded"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
var self = this;
|
||||
return visitor._visit(this, function(){
|
||||
self.expression.walk(visitor);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var AST_ArrowParametersOrSeq = DEFNODE("ArrowParametersOrSeq", "expressions", {
|
||||
$documentation: "A set of arrow function parameters or a sequence expression. This is used because when the parser sees a \"(\" it could be the start of a seq, or the start of a parameter list of an arrow function.",
|
||||
$propdoc: {
|
||||
expressions: "[AST_Expression|AST_Destructuring|AST_Expansion*] array of expressions or argument names or destructurings."
|
||||
},
|
||||
as_params: function (croak) {
|
||||
// We don't want anything which doesn't belong in a destructuring
|
||||
var root = this;
|
||||
return this.expressions.map(function to_fun_args(ex, _, __, default_seen_above) {
|
||||
var insert_default = function(ex, default_value) {
|
||||
if (default_value) {
|
||||
return new AST_DefaultAssign({
|
||||
start: ex.start,
|
||||
left: ex,
|
||||
operator: "=",
|
||||
right: default_value,
|
||||
end: default_value.end
|
||||
});
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
if (ex instanceof AST_Object) {
|
||||
return insert_default(new AST_Destructuring({
|
||||
start: ex.start,
|
||||
end: ex.end,
|
||||
is_array: false,
|
||||
names: ex.properties.map(to_fun_args)
|
||||
}), default_seen_above);
|
||||
} else if (ex instanceof AST_ObjectKeyVal) {
|
||||
if (ex.key instanceof AST_SymbolRef) {
|
||||
ex.key = to_fun_args(ex.key, 0, [ex.key]);
|
||||
}
|
||||
ex.value = to_fun_args(ex.value, 0, [ex.key]);
|
||||
return insert_default(ex, default_seen_above);
|
||||
} else if (ex instanceof AST_Hole) {
|
||||
return ex;
|
||||
} else if (ex instanceof AST_Destructuring) {
|
||||
if (ex.names.length == 0)
|
||||
croak("Invalid destructuring function parameter", ex.start.line, ex.start.col);
|
||||
ex.names = ex.names.map(to_fun_args);
|
||||
return insert_default(ex, default_seen_above);
|
||||
} else if (ex instanceof AST_SymbolRef) {
|
||||
return insert_default(new AST_SymbolFunarg({
|
||||
name: ex.name,
|
||||
start: ex.start,
|
||||
end: ex.end
|
||||
}), default_seen_above);
|
||||
} else if (ex instanceof AST_Expansion) {
|
||||
ex.expression = to_fun_args(ex.expression);
|
||||
return insert_default(ex, default_seen_above);
|
||||
} else if (ex instanceof AST_Array) {
|
||||
return insert_default(new AST_Destructuring({
|
||||
start: ex.start,
|
||||
end: ex.end,
|
||||
is_array: true,
|
||||
names: ex.elements.map(to_fun_args)
|
||||
}), default_seen_above);
|
||||
} else if (ex instanceof AST_Assign) {
|
||||
return insert_default(to_fun_args(ex.left, undefined, undefined, ex.right), default_seen_above);
|
||||
} else {
|
||||
croak("Invalid function parameter", ex.start.line, ex.start.col);
|
||||
}
|
||||
});
|
||||
},
|
||||
as_expr: function (croak) {
|
||||
return AST_Seq.from_array(this.expressions);
|
||||
}
|
||||
});
|
||||
|
||||
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments is_generator", {
|
||||
$documentation: "Base class for functions",
|
||||
$propdoc: {
|
||||
is_generator: "[boolean] is generatorFn or not",
|
||||
name: "[AST_SymbolDeclaration?] the name of this function",
|
||||
argnames: "[AST_SymbolFunarg*] array of function arguments",
|
||||
argnames: "[AST_SymbolFunarg|AST_Destructuring|AST_Expansion|AST_DefaultAssign*] array of function arguments, destructurings, or expanding arguments",
|
||||
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
|
||||
},
|
||||
args_as_names: function () {
|
||||
var out = [];
|
||||
for (var i = 0; i < this.argnames.length; i++) {
|
||||
if (this.argnames[i] instanceof AST_Destructuring) {
|
||||
out = out.concat(this.argnames[i].all_symbols());
|
||||
} else {
|
||||
out.push(this.argnames[i]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
if (this.name) this.name._walk(visitor);
|
||||
this.argnames.forEach(function(arg){
|
||||
arg._walk(visitor);
|
||||
});
|
||||
var argnames = this.argnames;
|
||||
for (var i = 0, len = argnames.length; i < len; i++) {
|
||||
argnames[i]._walk(visitor);
|
||||
}
|
||||
walk_body(this, visitor);
|
||||
});
|
||||
}
|
||||
}, AST_Scope);
|
||||
|
||||
var AST_Accessor = DEFNODE("Accessor", null, {
|
||||
$documentation: "A setter/getter function"
|
||||
$documentation: "A setter/getter function. The `name` property is always null."
|
||||
}, AST_Lambda);
|
||||
|
||||
var AST_Function = DEFNODE("Function", null, {
|
||||
$documentation: "A function expression"
|
||||
}, AST_Lambda);
|
||||
|
||||
var AST_Arrow = DEFNODE("Arrow", null, {
|
||||
$documentation: "An ES6 Arrow function ((a) => b)"
|
||||
}, AST_Lambda);
|
||||
|
||||
var AST_Defun = DEFNODE("Defun", null, {
|
||||
$documentation: "A function definition"
|
||||
}, AST_Lambda);
|
||||
|
||||
/* -----[ DESTRUCTURING ]----- */
|
||||
var AST_Destructuring = DEFNODE("Destructuring", "names is_array", {
|
||||
$documentation: "A destructuring of several names. Used in destructuring assignment and with destructuring function argument names",
|
||||
$propdoc: {
|
||||
"names": "[AST_Node*] Array of properties or elements",
|
||||
"is_array": "[Boolean] Whether the destructuring represents an object or array"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.names.forEach(function(name){
|
||||
name._walk(visitor);
|
||||
});
|
||||
});
|
||||
},
|
||||
all_symbols: function() {
|
||||
var out = [];
|
||||
this.walk(new TreeWalker(function (node) {
|
||||
if (node instanceof AST_Symbol) {
|
||||
out.push(node);
|
||||
}
|
||||
if (node instanceof AST_Expansion) {
|
||||
out.push(node.expression);
|
||||
}
|
||||
}));
|
||||
return out;
|
||||
}
|
||||
});
|
||||
|
||||
var AST_PrefixedTemplateString = DEFNODE("PrefixedTemplateString", "template_string prefix", {
|
||||
$documentation: "A templatestring with a prefix, such as String.raw`foobarbaz`",
|
||||
$propdoc: {
|
||||
template_string: "[AST_TemplateString] The template string",
|
||||
prefix: "[AST_SymbolRef|AST_PropAccess] The prefix, which can be a symbol such as `foo` or a dotted expression such as `String.raw`."
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
this.prefix._walk(visitor);
|
||||
this.template_string._walk(visitor);
|
||||
}
|
||||
})
|
||||
|
||||
var AST_TemplateString = DEFNODE("TemplateString", "segments", {
|
||||
$documentation: "A template string literal",
|
||||
$propdoc: {
|
||||
segments: "[AST_TemplateSegment|AST_Expression]* One or more segments, starting with AST_TemplateSegment. AST_Expression may follow AST_TemplateSegment, but each AST_Expression must be followed by AST_TemplateSegment."
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.segments.forEach(function(seg, i){
|
||||
if (i % 2 !== 0) {
|
||||
seg._walk(visitor);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var AST_TemplateSegment = DEFNODE("TemplateSegment", "value raw", {
|
||||
$documentation: "A segment of a template string literal",
|
||||
$propdoc: {
|
||||
value: "Content of the segment",
|
||||
raw: "Raw content of the segment"
|
||||
}
|
||||
});
|
||||
|
||||
/* -----[ JUMPS ]----- */
|
||||
|
||||
var AST_Jump = DEFNODE("Jump", null, {
|
||||
@@ -494,16 +682,10 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
|
||||
}
|
||||
}, AST_Block);
|
||||
|
||||
// XXX: this is wrong according to ECMA-262 (12.4). the catch block
|
||||
// should introduce another scope, as the argname should be visible
|
||||
// only inside the catch block. However, doing it this way because of
|
||||
// IE which simply introduces the name in the surrounding scope. If
|
||||
// we ever want to fix this then AST_Catch should inherit from
|
||||
// AST_Scope.
|
||||
var AST_Catch = DEFNODE("Catch", "argname", {
|
||||
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
|
||||
$propdoc: {
|
||||
argname: "[AST_SymbolCatch] symbol for the exception"
|
||||
argname: "[AST_SymbolCatch|AST_Destructuring|AST_Expansion|AST_DefaultAssign] symbol for the exception"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
@@ -526,9 +708,10 @@ var AST_Definitions = DEFNODE("Definitions", "definitions", {
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.definitions.forEach(function(def){
|
||||
def._walk(visitor);
|
||||
});
|
||||
var definitions = this.definitions;
|
||||
for (var i = 0, len = definitions.length; i < len; i++) {
|
||||
definitions[i]._walk(visitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AST_Statement);
|
||||
@@ -537,16 +720,78 @@ var AST_Var = DEFNODE("Var", null, {
|
||||
$documentation: "A `var` statement"
|
||||
}, AST_Definitions);
|
||||
|
||||
var AST_Let = DEFNODE("Let", null, {
|
||||
$documentation: "A `let` statement"
|
||||
}, AST_Definitions);
|
||||
|
||||
var AST_Const = DEFNODE("Const", null, {
|
||||
$documentation: "A `const` statement"
|
||||
}, AST_Definitions);
|
||||
|
||||
var AST_NameImport = DEFNODE("NameImport", "foreign_name name", {
|
||||
$documentation: "The part of the import statement that imports names from a module.",
|
||||
$propdoc: {
|
||||
foreign_name: "[AST_SymbolImportForeign] The name being imported (as specified in the module)",
|
||||
name: "[AST_SymbolImport] The name as it becomes available to this module."
|
||||
},
|
||||
_walk: function (visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
this.foreign_name._walk(visitor);
|
||||
this.name._walk(visitor);
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
var AST_Import = DEFNODE("Import", "imported_name imported_names module_name", {
|
||||
$documentation: "An `import` statement",
|
||||
$propdoc: {
|
||||
imported_name: "[AST_SymbolImport] The name of the variable holding the module's default export.",
|
||||
imported_names: "[AST_NameImport*] The names of non-default imported variables",
|
||||
module_name: "[AST_String] String literal describing where this module came from",
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
if (this.imported_name) {
|
||||
this.imported_name._walk(visitor);
|
||||
}
|
||||
if (this.imported_names) {
|
||||
this.imported_names.forEach(function (name_import) {
|
||||
name_import._walk(visitor);
|
||||
});
|
||||
}
|
||||
this.module_name._walk(visitor);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var AST_Export = DEFNODE("Export", "exported_definition exported_value is_default", {
|
||||
$documentation: "An `export` statement",
|
||||
$propdoc: {
|
||||
exported_definition: "[AST_Defun|AST_Definitions|AST_DefClass?] An exported definition",
|
||||
exported_value: "[AST_Node?] An exported value",
|
||||
is_default: "[Boolean] Whether this is the default exported value of this module"
|
||||
},
|
||||
_walk: function (visitor) {
|
||||
visitor._visit(this, function () {
|
||||
if (this.exported_definition) {
|
||||
this.exported_definition._walk(visitor);
|
||||
}
|
||||
if (this.exported_value) {
|
||||
this.exported_value._walk(visitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
||||
$propdoc: {
|
||||
name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
|
||||
name: "[AST_SymbolVar|AST_SymbolConst|AST_Destructuring] name of the variable",
|
||||
value: "[AST_Node?] initializer, or null of there's no initializer"
|
||||
},
|
||||
is_destructuring: function() {
|
||||
return this.name instanceof AST_Destructuring;
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.name._walk(visitor);
|
||||
@@ -566,9 +811,10 @@ var AST_Call = DEFNODE("Call", "expression args", {
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.expression._walk(visitor);
|
||||
this.args.forEach(function(arg){
|
||||
arg._walk(visitor);
|
||||
});
|
||||
var args = this.args;
|
||||
for (var i = 0, len = args.length; i < len; i++) {
|
||||
args[i]._walk(visitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -628,6 +874,13 @@ var AST_Seq = DEFNODE("Seq", "car cdr", {
|
||||
p = p.cdr;
|
||||
}
|
||||
},
|
||||
len: function() {
|
||||
if (this.cdr instanceof AST_Seq) {
|
||||
return this.cdr.len() + 1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.car._walk(visitor);
|
||||
@@ -719,6 +972,10 @@ var AST_Assign = DEFNODE("Assign", null, {
|
||||
$documentation: "An assignment expression — `a = b + 5`",
|
||||
}, AST_Binary);
|
||||
|
||||
var AST_DefaultAssign = DEFNODE("DefaultAssign", null, {
|
||||
$documentation: "A default assignment expression like in `(a = 3) => a`"
|
||||
}, AST_Binary);
|
||||
|
||||
/* -----[ LITERALS ]----- */
|
||||
|
||||
var AST_Array = DEFNODE("Array", "elements", {
|
||||
@@ -728,9 +985,10 @@ var AST_Array = DEFNODE("Array", "elements", {
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.elements.forEach(function(el){
|
||||
el._walk(visitor);
|
||||
});
|
||||
var elements = this.elements;
|
||||
for (var i = 0, len = elements.length; i < len; i++) {
|
||||
elements[i]._walk(visitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -742,9 +1000,10 @@ var AST_Object = DEFNODE("Object", "properties", {
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.properties.forEach(function(prop){
|
||||
prop._walk(visitor);
|
||||
});
|
||||
var properties = this.properties;
|
||||
for (var i = 0, len = properties.length; i < len; i++) {
|
||||
properties[i]._walk(visitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -752,35 +1011,91 @@ var AST_Object = DEFNODE("Object", "properties", {
|
||||
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
||||
$documentation: "Base class for literal object properties",
|
||||
$propdoc: {
|
||||
key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code",
|
||||
value: "[AST_Node] property value. For setters and getters this is an AST_Function."
|
||||
key: "[string|AST_Node] the property name converted to a string for ObjectKeyVal. For setters, getters and computed property this is an arbitrary AST_Node",
|
||||
value: "[AST_Node] property value. For setters and getters this is an AST_Function."
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
if (this.key instanceof AST_Node)
|
||||
this.key._walk(visitor);
|
||||
this.value._walk(visitor);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, {
|
||||
var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", {
|
||||
$documentation: "A key: value object property",
|
||||
$propdoc: {
|
||||
quote: "[string] the original quote character"
|
||||
}
|
||||
}, AST_ObjectProperty);
|
||||
|
||||
var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
|
||||
var AST_ObjectSetter = DEFNODE("ObjectSetter", "quote static", {
|
||||
$propdoc: {
|
||||
quote: "[string|undefined] the original quote character, if any",
|
||||
static: "[boolean] whether this is a static setter (classes only)"
|
||||
},
|
||||
$documentation: "An object setter property",
|
||||
}, AST_ObjectProperty);
|
||||
|
||||
var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
|
||||
var AST_ObjectGetter = DEFNODE("ObjectGetter", "quote static", {
|
||||
$propdoc: {
|
||||
quote: "[string|undefined] the original quote character, if any",
|
||||
static: "[boolean] whether this is a static getter (classes only)"
|
||||
},
|
||||
$documentation: "An object getter property",
|
||||
}, AST_ObjectProperty);
|
||||
|
||||
var AST_ConciseMethod = DEFNODE("ConciseMethod", "quote static is_generator", {
|
||||
$propdoc: {
|
||||
quote: "[string|undefined] the original quote character, if any",
|
||||
static: "[boolean] whether this method is static (classes only)",
|
||||
is_generator: "[boolean] is generatorFn or not",
|
||||
},
|
||||
$documentation: "An ES6 concise method inside an object or class"
|
||||
}, AST_ObjectProperty);
|
||||
|
||||
var AST_Class = DEFNODE("Class", "name extends properties", {
|
||||
$propdoc: {
|
||||
name: "[AST_SymbolClass|AST_SymbolDefClass?] optional class name.",
|
||||
extends: "[AST_Node]? optional parent class",
|
||||
properties: "[AST_ObjectProperty*] array of properties"
|
||||
},
|
||||
$documentation: "An ES6 class",
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
if (this.name) {
|
||||
this.name._walk(visitor);
|
||||
}
|
||||
if (this.extends) {
|
||||
this.extends._walk(visitor);
|
||||
}
|
||||
this.properties.forEach(function(prop){
|
||||
prop._walk(visitor);
|
||||
});
|
||||
});
|
||||
},
|
||||
}, AST_Scope);
|
||||
|
||||
var AST_DefClass = DEFNODE("DefClass", null, {
|
||||
$documentation: "A class definition",
|
||||
}, AST_Class);
|
||||
|
||||
var AST_ClassExpression = DEFNODE("ClassExpression", null, {
|
||||
$documentation: "A class expression."
|
||||
}, AST_Class);
|
||||
|
||||
var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
|
||||
$propdoc: {
|
||||
name: "[string] name of this symbol",
|
||||
scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
|
||||
thedef: "[SymbolDef/S] the definition of this symbol"
|
||||
},
|
||||
$documentation: "Base class for all symbols",
|
||||
$documentation: "Base class for all symbols"
|
||||
});
|
||||
|
||||
var AST_NewTarget = DEFNODE("NewTarget", null, {
|
||||
$documentation: "A reference to new.target"
|
||||
});
|
||||
|
||||
var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
|
||||
@@ -791,16 +1106,24 @@ var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
|
||||
$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
|
||||
$propdoc: {
|
||||
init: "[AST_Node*/S] array of initializers for this declaration."
|
||||
}
|
||||
},
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolVar = DEFNODE("SymbolVar", null, {
|
||||
$documentation: "Symbol defining a variable",
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolBlockDeclaration = DEFNODE("SymbolBlockDeclaration", null, {
|
||||
$documentation: "Base class for block-scoped declaration symbols"
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolConst = DEFNODE("SymbolConst", null, {
|
||||
$documentation: "A constant declaration"
|
||||
}, AST_SymbolDeclaration);
|
||||
}, AST_SymbolBlockDeclaration);
|
||||
|
||||
var AST_SymbolLet = DEFNODE("SymbolLet", null, {
|
||||
$documentation: "A block-scoped `let` declaration"
|
||||
}, AST_SymbolBlockDeclaration);
|
||||
|
||||
var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
|
||||
$documentation: "Symbol naming a function argument",
|
||||
@@ -810,18 +1133,42 @@ var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
|
||||
$documentation: "Symbol defining a function",
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolMethod = DEFNODE("SymbolMethod", null, {
|
||||
$documentation: "Symbol in an object defining a method",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
|
||||
$documentation: "Symbol naming a function expression",
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolDefClass = DEFNODE("SymbolDefClass", null, {
|
||||
$documentation: "Symbol naming a class's name in a class declaration. Lexically scoped to its containing scope, and accessible within the class."
|
||||
}, AST_SymbolBlockDeclaration);
|
||||
|
||||
var AST_SymbolClass = DEFNODE("SymbolClass", null, {
|
||||
$documentation: "Symbol naming a class's name. Lexically scoped to the class."
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
|
||||
$documentation: "Symbol naming the exception in catch",
|
||||
}, AST_SymbolDeclaration);
|
||||
}, AST_SymbolBlockDeclaration);
|
||||
|
||||
var AST_SymbolImport = DEFNODE("SymbolImport", null, {
|
||||
$documentation: "Symbol refering to an imported name",
|
||||
}, AST_SymbolBlockDeclaration);
|
||||
|
||||
var AST_SymbolImportForeign = DEFNODE("SymbolImportForeign", null, {
|
||||
$documentation: "A symbol imported from a module, but it is defined in the other module, and its real name is irrelevant for this module's purposes",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_Label = DEFNODE("Label", "references", {
|
||||
$documentation: "Symbol naming a label (declaration)",
|
||||
$propdoc: {
|
||||
references: "[AST_LabelRef*] a list of nodes referring to this label"
|
||||
references: "[AST_LoopControl*] a list of nodes referring to this label"
|
||||
},
|
||||
initialize: function() {
|
||||
this.references = [];
|
||||
this.thedef = this;
|
||||
}
|
||||
}, AST_Symbol);
|
||||
|
||||
@@ -837,6 +1184,10 @@ var AST_This = DEFNODE("This", null, {
|
||||
$documentation: "The `this` symbol",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_Super = DEFNODE("Super", null, {
|
||||
$documentation: "The `super` symbol",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_Constant = DEFNODE("Constant", null, {
|
||||
$documentation: "Base class for all constants",
|
||||
getValue: function() {
|
||||
@@ -844,17 +1195,19 @@ var AST_Constant = DEFNODE("Constant", null, {
|
||||
}
|
||||
});
|
||||
|
||||
var AST_String = DEFNODE("String", "value", {
|
||||
var AST_String = DEFNODE("String", "value quote", {
|
||||
$documentation: "A string literal",
|
||||
$propdoc: {
|
||||
value: "[string] the contents of this string"
|
||||
value: "[string] the contents of this string",
|
||||
quote: "[string] the original quote character"
|
||||
}
|
||||
}, AST_Constant);
|
||||
|
||||
var AST_Number = DEFNODE("Number", "value", {
|
||||
var AST_Number = DEFNODE("Number", "value literal", {
|
||||
$documentation: "A number literal",
|
||||
$propdoc: {
|
||||
value: "[number] the numeric value"
|
||||
value: "[number] the numeric value",
|
||||
literal: "[string] numeric value as string (optional)"
|
||||
}
|
||||
}, AST_Constant);
|
||||
|
||||
@@ -908,32 +1261,59 @@ var AST_True = DEFNODE("True", null, {
|
||||
value: true
|
||||
}, AST_Boolean);
|
||||
|
||||
/* -----[ Yield ]----- */
|
||||
|
||||
var AST_Yield = DEFNODE("Yield", "expression is_star", {
|
||||
$documentation: "A `yield` statement",
|
||||
$propdoc: {
|
||||
expression: "[AST_Node?] the value returned or thrown by this statement; could be null (representing undefined) but only when is_star is set to false",
|
||||
is_star: "[Boolean] Whether this is a yield or yield* statement"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, this.expression && function(){
|
||||
this.expression._walk(visitor);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/* -----[ TreeWalker ]----- */
|
||||
|
||||
function TreeWalker(callback) {
|
||||
this.visit = callback;
|
||||
this.stack = [];
|
||||
this.directives = Object.create(null);
|
||||
};
|
||||
TreeWalker.prototype = {
|
||||
_visit: function(node, descend) {
|
||||
this.stack.push(node);
|
||||
this.push(node);
|
||||
var ret = this.visit(node, descend ? function(){
|
||||
descend.call(node);
|
||||
} : noop);
|
||||
if (!ret && descend) {
|
||||
descend.call(node);
|
||||
}
|
||||
this.stack.pop();
|
||||
this.pop(node);
|
||||
return ret;
|
||||
},
|
||||
parent: function(n) {
|
||||
return this.stack[this.stack.length - 2 - (n || 0)];
|
||||
},
|
||||
push: function (node) {
|
||||
if (node instanceof AST_Lambda) {
|
||||
this.directives = Object.create(this.directives);
|
||||
} else if (node instanceof AST_Directive) {
|
||||
this.directives[node.value] = this.directives[node.value] ? "up" : true;
|
||||
} else if (node instanceof AST_Class) {
|
||||
this.directives = Object.create(this.directives);
|
||||
this.directives["use strict"] = this.directives["use strict"] ? "up" : true;
|
||||
}
|
||||
this.stack.push(node);
|
||||
},
|
||||
pop: function() {
|
||||
return this.stack.pop();
|
||||
pop: function(node) {
|
||||
this.stack.pop();
|
||||
if (node instanceof AST_Lambda || node instanceof AST_Class) {
|
||||
this.directives = Object.getPrototypeOf(this.directives);
|
||||
}
|
||||
},
|
||||
self: function() {
|
||||
return this.stack[this.stack.length - 1];
|
||||
@@ -945,6 +1325,18 @@ TreeWalker.prototype = {
|
||||
if (x instanceof type) return x;
|
||||
}
|
||||
},
|
||||
has_directive: function(type) {
|
||||
var dir = this.directives[type];
|
||||
if (dir) return dir;
|
||||
var node = this.stack[this.stack.length - 1];
|
||||
if (node instanceof AST_Scope && node.body) {
|
||||
for (var i = 0; i < node.body.length; ++i) {
|
||||
var st = node.body[i];
|
||||
if (!(st instanceof AST_Directive)) break;
|
||||
if (st.value == type) return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
in_boolean_context: function() {
|
||||
var stack = this.stack;
|
||||
var i = stack.length, self = stack[--i];
|
||||
@@ -965,21 +1357,15 @@ TreeWalker.prototype = {
|
||||
},
|
||||
loopcontrol_target: function(label) {
|
||||
var stack = this.stack;
|
||||
if (label) {
|
||||
for (var i = stack.length; --i >= 0;) {
|
||||
var x = stack[i];
|
||||
if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
|
||||
return x.body;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var i = stack.length; --i >= 0;) {
|
||||
var x = stack[i];
|
||||
if (x instanceof AST_Switch
|
||||
|| x instanceof AST_For
|
||||
|| x instanceof AST_ForIn
|
||||
|| x instanceof AST_DWLoop) return x;
|
||||
if (label) for (var i = stack.length; --i >= 0;) {
|
||||
var x = stack[i];
|
||||
if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
|
||||
return x.body;
|
||||
}
|
||||
} else for (var i = stack.length; --i >= 0;) {
|
||||
var x = stack[i];
|
||||
if (x instanceof AST_Switch || x instanceof AST_IterationStatement)
|
||||
return x;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
2186
lib/compress.js
2186
lib/compress.js
File diff suppressed because it is too large
Load Diff
@@ -45,54 +45,113 @@
|
||||
|
||||
(function(){
|
||||
|
||||
var normalize_directives = function(body) {
|
||||
var in_directive = true;
|
||||
|
||||
for (var i = 0; i < body.length; i++) {
|
||||
if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) {
|
||||
body[i] = new AST_Directive({
|
||||
start: body[i].start,
|
||||
end: body[i].end,
|
||||
value: body[i].body.value
|
||||
});
|
||||
} else if (in_directive && !(body[i] instanceof AST_Statement && body[i].body instanceof AST_String)) {
|
||||
in_directive = false;
|
||||
}
|
||||
}
|
||||
|
||||
return body;
|
||||
};
|
||||
|
||||
var MOZ_TO_ME = {
|
||||
TryStatement : function(M) {
|
||||
Program: function(M) {
|
||||
return new AST_Toplevel({
|
||||
start: my_start_token(M),
|
||||
end: my_end_token(M),
|
||||
body: normalize_directives(M.body.map(from_moz))
|
||||
});
|
||||
},
|
||||
FunctionDeclaration: function(M) {
|
||||
return new AST_Defun({
|
||||
start: my_start_token(M),
|
||||
end: my_end_token(M),
|
||||
name: from_moz(M.id),
|
||||
argnames: M.params.map(from_moz),
|
||||
body: normalize_directives(from_moz(M.body).body)
|
||||
});
|
||||
},
|
||||
FunctionExpression: function(M) {
|
||||
return new AST_Function({
|
||||
start: my_start_token(M),
|
||||
end: my_end_token(M),
|
||||
name: from_moz(M.id),
|
||||
argnames: M.params.map(from_moz),
|
||||
body: normalize_directives(from_moz(M.body).body)
|
||||
});
|
||||
},
|
||||
ExpressionStatement: function(M) {
|
||||
return new AST_SimpleStatement({
|
||||
start: my_start_token(M),
|
||||
end: my_end_token(M),
|
||||
body: from_moz(M.expression)
|
||||
});
|
||||
},
|
||||
TryStatement: function(M) {
|
||||
var handlers = M.handlers || [M.handler];
|
||||
if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {
|
||||
throw new Error("Multiple catch clauses are not supported.");
|
||||
}
|
||||
return new AST_Try({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
body : from_moz(M.block).body,
|
||||
bcatch : from_moz(M.handlers[0]),
|
||||
bcatch : from_moz(handlers[0]),
|
||||
bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
|
||||
});
|
||||
},
|
||||
CatchClause : function(M) {
|
||||
return new AST_Catch({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
argname : from_moz(M.param),
|
||||
body : from_moz(M.body).body
|
||||
Property: function(M) {
|
||||
var key = M.key;
|
||||
var name = key.type == "Identifier" ? key.name : key.value;
|
||||
var args = {
|
||||
start : my_start_token(key),
|
||||
end : my_end_token(M.value),
|
||||
key : name,
|
||||
value : from_moz(M.value)
|
||||
};
|
||||
switch (M.kind) {
|
||||
case "init":
|
||||
return new AST_ObjectKeyVal(args);
|
||||
case "set":
|
||||
args.value.name = from_moz(key);
|
||||
return new AST_ObjectSetter(args);
|
||||
case "get":
|
||||
args.value.name = from_moz(key);
|
||||
return new AST_ObjectGetter(args);
|
||||
}
|
||||
},
|
||||
ArrayExpression: function(M) {
|
||||
return new AST_Array({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
elements : M.elements.map(function(elem){
|
||||
return elem === null ? new AST_Hole() : from_moz(elem);
|
||||
})
|
||||
});
|
||||
},
|
||||
ObjectExpression : function(M) {
|
||||
ObjectExpression: function(M) {
|
||||
return new AST_Object({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
properties : M.properties.map(function(prop){
|
||||
var key = prop.key;
|
||||
var name = key.type == "Identifier" ? key.name : key.value;
|
||||
var args = {
|
||||
start : my_start_token(key),
|
||||
end : my_end_token(prop.value),
|
||||
key : name,
|
||||
value : from_moz(prop.value)
|
||||
};
|
||||
switch (prop.kind) {
|
||||
case "init":
|
||||
return new AST_ObjectKeyVal(args);
|
||||
case "set":
|
||||
args.value.name = from_moz(key);
|
||||
return new AST_ObjectSetter(args);
|
||||
case "get":
|
||||
args.value.name = from_moz(key);
|
||||
return new AST_ObjectGetter(args);
|
||||
}
|
||||
prop.type = "Property";
|
||||
return from_moz(prop)
|
||||
})
|
||||
});
|
||||
},
|
||||
SequenceExpression : function(M) {
|
||||
SequenceExpression: function(M) {
|
||||
return AST_Seq.from_array(M.expressions.map(from_moz));
|
||||
},
|
||||
MemberExpression : function(M) {
|
||||
MemberExpression: function(M) {
|
||||
return new (M.computed ? AST_Sub : AST_Dot)({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
@@ -100,7 +159,7 @@
|
||||
expression : from_moz(M.object)
|
||||
});
|
||||
},
|
||||
SwitchCase : function(M) {
|
||||
SwitchCase: function(M) {
|
||||
return new (M.test ? AST_Case : AST_Default)({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
@@ -108,7 +167,14 @@
|
||||
body : M.consequent.map(from_moz)
|
||||
});
|
||||
},
|
||||
Literal : function(M) {
|
||||
VariableDeclaration: function(M) {
|
||||
return new (M.kind === "const" ? AST_Const : AST_Var)({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
definitions : M.declarations.map(from_moz)
|
||||
});
|
||||
},
|
||||
Literal: function(M) {
|
||||
var val = M.value, args = {
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M)
|
||||
@@ -124,16 +190,20 @@
|
||||
case "boolean":
|
||||
return new (val ? AST_True : AST_False)(args);
|
||||
default:
|
||||
args.value = val;
|
||||
var rx = M.regex;
|
||||
if (rx && rx.pattern) {
|
||||
// RegExpLiteral as per ESTree AST spec
|
||||
args.value = new RegExp(rx.pattern, rx.flags).toString();
|
||||
} else {
|
||||
// support legacy RegExp
|
||||
args.value = M.regex && M.raw ? M.raw : val;
|
||||
}
|
||||
return new AST_RegExp(args);
|
||||
}
|
||||
},
|
||||
UnaryExpression: From_Moz_Unary,
|
||||
UpdateExpression: From_Moz_Unary,
|
||||
Identifier: function(M) {
|
||||
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
|
||||
return new (M.name == "this" ? AST_This
|
||||
: p.type == "LabeledStatement" ? AST_Label
|
||||
return new ( p.type == "LabeledStatement" ? AST_Label
|
||||
: p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
|
||||
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
|
||||
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
|
||||
@@ -147,7 +217,8 @@
|
||||
}
|
||||
};
|
||||
|
||||
function From_Moz_Unary(M) {
|
||||
MOZ_TO_ME.UpdateExpression =
|
||||
MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
|
||||
var prefix = "prefix" in M ? M.prefix
|
||||
: M.type == "UnaryExpression" ? true : false;
|
||||
return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
|
||||
@@ -158,14 +229,8 @@
|
||||
});
|
||||
};
|
||||
|
||||
var ME_TO_MOZ = {};
|
||||
|
||||
map("Node", AST_Node);
|
||||
map("Program", AST_Toplevel, "body@body");
|
||||
map("Function", AST_Function, "id>name, params@argnames, body%body");
|
||||
map("EmptyStatement", AST_EmptyStatement);
|
||||
map("BlockStatement", AST_BlockStatement, "body@body");
|
||||
map("ExpressionStatement", AST_SimpleStatement, "expression>body");
|
||||
map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
|
||||
map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
|
||||
map("BreakStatement", AST_Break, "label>label");
|
||||
@@ -179,72 +244,314 @@
|
||||
map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
|
||||
map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
|
||||
map("DebuggerStatement", AST_Debugger);
|
||||
map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body");
|
||||
map("VariableDeclaration", AST_Var, "declarations@definitions");
|
||||
map("VariableDeclarator", AST_VarDef, "id>name, init>value");
|
||||
map("CatchClause", AST_Catch, "param>argname, body%body");
|
||||
|
||||
map("ThisExpression", AST_This);
|
||||
map("ArrayExpression", AST_Array, "elements@elements");
|
||||
map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body");
|
||||
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
|
||||
map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
|
||||
map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
|
||||
map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
|
||||
map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
|
||||
map("NewExpression", AST_New, "callee>expression, arguments@args");
|
||||
map("CallExpression", AST_Call, "callee>expression, arguments@args");
|
||||
|
||||
def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
|
||||
return {
|
||||
type: "Program",
|
||||
body: M.body.map(to_moz)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
|
||||
return {
|
||||
type: "FunctionDeclaration",
|
||||
id: to_moz(M.name),
|
||||
params: M.argnames.map(to_moz),
|
||||
body: to_moz_block(M)
|
||||
}
|
||||
});
|
||||
|
||||
def_to_moz(AST_Function, function To_Moz_FunctionExpression(M) {
|
||||
return {
|
||||
type: "FunctionExpression",
|
||||
id: to_moz(M.name),
|
||||
params: M.argnames.map(to_moz),
|
||||
body: to_moz_block(M)
|
||||
}
|
||||
});
|
||||
|
||||
def_to_moz(AST_Directive, function To_Moz_Directive(M) {
|
||||
return {
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "Literal",
|
||||
value: M.value
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) {
|
||||
return {
|
||||
type: "ExpressionStatement",
|
||||
expression: to_moz(M.body)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {
|
||||
return {
|
||||
type: "SwitchCase",
|
||||
test: to_moz(M.expression),
|
||||
consequent: M.body.map(to_moz)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
|
||||
return {
|
||||
type: "TryStatement",
|
||||
block: to_moz_block(M),
|
||||
handler: to_moz(M.bcatch),
|
||||
guardedHandlers: [],
|
||||
finalizer: to_moz(M.bfinally)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
|
||||
return {
|
||||
type: "CatchClause",
|
||||
param: to_moz(M.argname),
|
||||
guard: null,
|
||||
body: to_moz_block(M)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
|
||||
return {
|
||||
type: "VariableDeclaration",
|
||||
kind: M instanceof AST_Const ? "const" : "var",
|
||||
declarations: M.definitions.map(to_moz)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
|
||||
return {
|
||||
type: "SequenceExpression",
|
||||
expressions: M.to_array().map(to_moz)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
|
||||
var isComputed = M instanceof AST_Sub;
|
||||
return {
|
||||
type: "MemberExpression",
|
||||
object: to_moz(M.expression),
|
||||
computed: isComputed,
|
||||
property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property}
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Unary, function To_Moz_Unary(M) {
|
||||
return {
|
||||
type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
|
||||
operator: M.operator,
|
||||
prefix: M instanceof AST_UnaryPrefix,
|
||||
argument: to_moz(M.expression)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
|
||||
return {
|
||||
type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
|
||||
left: to_moz(M.left),
|
||||
operator: M.operator,
|
||||
right: to_moz(M.right)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) {
|
||||
return {
|
||||
type: "ArrayExpression",
|
||||
elements: M.elements.map(to_moz)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) {
|
||||
return {
|
||||
type: "ObjectExpression",
|
||||
properties: M.properties.map(to_moz)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
|
||||
var key = (
|
||||
is_identifier(M.key)
|
||||
? {type: "Identifier", name: M.key}
|
||||
: {type: "Literal", value: M.key}
|
||||
);
|
||||
var kind;
|
||||
if (M instanceof AST_ObjectKeyVal) {
|
||||
kind = "init";
|
||||
} else
|
||||
if (M instanceof AST_ObjectGetter) {
|
||||
kind = "get";
|
||||
} else
|
||||
if (M instanceof AST_ObjectSetter) {
|
||||
kind = "set";
|
||||
}
|
||||
return {
|
||||
type: "Property",
|
||||
kind: kind,
|
||||
key: key,
|
||||
value: to_moz(M.value)
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Symbol, function To_Moz_Identifier(M) {
|
||||
var def = M.definition();
|
||||
return {
|
||||
type: "Identifier",
|
||||
name: def ? def.mangled_name || def.name : M.name
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
|
||||
var value = M.value;
|
||||
return {
|
||||
type: "Literal",
|
||||
value: value,
|
||||
raw: value.toString(),
|
||||
regex: {
|
||||
pattern: value.source,
|
||||
flags: value.toString().match(/[gimuy]*$/)[0]
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Constant, function To_Moz_Literal(M) {
|
||||
var value = M.value;
|
||||
if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) {
|
||||
return {
|
||||
type: "UnaryExpression",
|
||||
operator: "-",
|
||||
prefix: true,
|
||||
argument: {
|
||||
type: "Literal",
|
||||
value: -value,
|
||||
raw: M.start.raw
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: "Literal",
|
||||
value: value,
|
||||
raw: M.start.raw
|
||||
};
|
||||
});
|
||||
|
||||
def_to_moz(AST_Atom, function To_Moz_Atom(M) {
|
||||
return {
|
||||
type: "Identifier",
|
||||
name: String(M.value)
|
||||
};
|
||||
});
|
||||
|
||||
AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
|
||||
AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
|
||||
AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null });
|
||||
|
||||
AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast);
|
||||
AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast);
|
||||
|
||||
/* -----[ tools ]----- */
|
||||
|
||||
function raw_token(moznode) {
|
||||
if (moznode.type == "Literal") {
|
||||
return moznode.raw != null ? moznode.raw : moznode.value + "";
|
||||
}
|
||||
}
|
||||
|
||||
function my_start_token(moznode) {
|
||||
var loc = moznode.loc, start = loc && loc.start;
|
||||
var range = moznode.range;
|
||||
return new AST_Token({
|
||||
file : moznode.loc && moznode.loc.source,
|
||||
line : moznode.loc && moznode.loc.start.line,
|
||||
col : moznode.loc && moznode.loc.start.column,
|
||||
pos : moznode.start,
|
||||
endpos : moznode.start
|
||||
file : loc && loc.source,
|
||||
line : start && start.line,
|
||||
col : start && start.column,
|
||||
pos : range ? range[0] : moznode.start,
|
||||
endline : start && start.line,
|
||||
endcol : start && start.column,
|
||||
endpos : range ? range[0] : moznode.start,
|
||||
raw : raw_token(moznode),
|
||||
});
|
||||
};
|
||||
|
||||
function my_end_token(moznode) {
|
||||
var loc = moznode.loc, end = loc && loc.end;
|
||||
var range = moznode.range;
|
||||
return new AST_Token({
|
||||
file : moznode.loc && moznode.loc.source,
|
||||
line : moznode.loc && moznode.loc.end.line,
|
||||
col : moznode.loc && moznode.loc.end.column,
|
||||
pos : moznode.end,
|
||||
endpos : moznode.end
|
||||
file : loc && loc.source,
|
||||
line : end && end.line,
|
||||
col : end && end.column,
|
||||
pos : range ? range[1] : moznode.end,
|
||||
endline : end && end.line,
|
||||
endcol : end && end.column,
|
||||
endpos : range ? range[1] : moznode.end,
|
||||
raw : raw_token(moznode),
|
||||
});
|
||||
};
|
||||
|
||||
function map(moztype, mytype, propmap) {
|
||||
var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
|
||||
moz_to_me += "return new mytype({\n" +
|
||||
moz_to_me += "return new U2." + mytype.name + "({\n" +
|
||||
"start: my_start_token(M),\n" +
|
||||
"end: my_end_token(M)";
|
||||
|
||||
var me_to_moz = "function To_Moz_" + moztype + "(M){\n";
|
||||
me_to_moz += "return {\n" +
|
||||
"type: " + JSON.stringify(moztype);
|
||||
|
||||
if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){
|
||||
var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
|
||||
if (!m) throw new Error("Can't understand property map: " + prop);
|
||||
var moz = "M." + m[1], how = m[2], my = m[3];
|
||||
var moz = m[1], how = m[2], my = m[3];
|
||||
moz_to_me += ",\n" + my + ": ";
|
||||
if (how == "@") {
|
||||
moz_to_me += moz + ".map(from_moz)";
|
||||
} else if (how == ">") {
|
||||
moz_to_me += "from_moz(" + moz + ")";
|
||||
} else if (how == "=") {
|
||||
moz_to_me += moz;
|
||||
} else if (how == "%") {
|
||||
moz_to_me += "from_moz(" + moz + ").body";
|
||||
} else throw new Error("Can't understand operator in propmap: " + prop);
|
||||
me_to_moz += ",\n" + moz + ": ";
|
||||
switch (how) {
|
||||
case "@":
|
||||
moz_to_me += "M." + moz + ".map(from_moz)";
|
||||
me_to_moz += "M." + my + ".map(to_moz)";
|
||||
break;
|
||||
case ">":
|
||||
moz_to_me += "from_moz(M." + moz + ")";
|
||||
me_to_moz += "to_moz(M." + my + ")";
|
||||
break;
|
||||
case "=":
|
||||
moz_to_me += "M." + moz;
|
||||
me_to_moz += "M." + my;
|
||||
break;
|
||||
case "%":
|
||||
moz_to_me += "from_moz(M." + moz + ").body";
|
||||
me_to_moz += "to_moz_block(M)";
|
||||
break;
|
||||
default:
|
||||
throw new Error("Can't understand operator in propmap: " + prop);
|
||||
}
|
||||
});
|
||||
moz_to_me += "\n})}";
|
||||
|
||||
// moz_to_me = parse(moz_to_me).print_to_string({ beautify: true });
|
||||
// console.log(moz_to_me);
|
||||
moz_to_me += "\n})\n}";
|
||||
me_to_moz += "\n}\n}";
|
||||
|
||||
moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
|
||||
mytype, my_start_token, my_end_token, from_moz
|
||||
//moz_to_me = parse(moz_to_me).print_to_string({ beautify: true });
|
||||
//me_to_moz = parse(me_to_moz).print_to_string({ beautify: true });
|
||||
//console.log(moz_to_me);
|
||||
|
||||
moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
|
||||
exports, my_start_token, my_end_token, from_moz
|
||||
);
|
||||
return MOZ_TO_ME[moztype] = moz_to_me;
|
||||
me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
|
||||
to_moz, to_moz_block
|
||||
);
|
||||
MOZ_TO_ME[moztype] = moz_to_me;
|
||||
def_to_moz(mytype, me_to_moz);
|
||||
};
|
||||
|
||||
var FROM_MOZ_STACK = null;
|
||||
@@ -264,4 +571,39 @@
|
||||
return ast;
|
||||
};
|
||||
|
||||
function set_moz_loc(mynode, moznode, myparent) {
|
||||
var start = mynode.start;
|
||||
var end = mynode.end;
|
||||
if (start.pos != null && end.endpos != null) {
|
||||
moznode.range = [start.pos, end.endpos];
|
||||
}
|
||||
if (start.line) {
|
||||
moznode.loc = {
|
||||
start: {line: start.line, column: start.col},
|
||||
end: end.endline ? {line: end.endline, column: end.endcol} : null
|
||||
};
|
||||
if (start.file) {
|
||||
moznode.loc.source = start.file;
|
||||
}
|
||||
}
|
||||
return moznode;
|
||||
};
|
||||
|
||||
function def_to_moz(mytype, handler) {
|
||||
mytype.DEFMETHOD("to_mozilla_ast", function() {
|
||||
return set_moz_loc(this, handler(this));
|
||||
});
|
||||
};
|
||||
|
||||
function to_moz(node) {
|
||||
return node != null ? node.to_mozilla_ast() : null;
|
||||
};
|
||||
|
||||
function to_moz_block(node) {
|
||||
return {
|
||||
type: "BlockStatement",
|
||||
body: node.body.map(to_moz)
|
||||
};
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
948
lib/output.js
948
lib/output.js
File diff suppressed because it is too large
Load Diff
1767
lib/parse.js
1767
lib/parse.js
File diff suppressed because one or more lines are too long
282
lib/propmangle.js
Normal file
282
lib/propmangle.js
Normal file
@@ -0,0 +1,282 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
"use strict";
|
||||
|
||||
function find_builtins() {
|
||||
|
||||
// Compatibility fix for some standard defined globals not defined on every js environment
|
||||
var new_globals = ["Symbol", "Map", "Promise", "Proxy", "Reflect", "Set", "WeakMap", "WeakSet"];
|
||||
var objects = {};
|
||||
|
||||
new_globals.forEach(function (new_global) {
|
||||
objects[new_global] = global[new_global] || new Function();
|
||||
});
|
||||
|
||||
var a = [];
|
||||
[ Object, Array, Function, Number,
|
||||
String, Boolean, Error, Math,
|
||||
Date, RegExp, objects.Symbol, ArrayBuffer,
|
||||
DataView, decodeURI, decodeURIComponent,
|
||||
encodeURI, encodeURIComponent, eval, EvalError,
|
||||
Float32Array, Float64Array, Int8Array, Int16Array,
|
||||
Int32Array, isFinite, isNaN, JSON, objects.Map, parseFloat,
|
||||
parseInt, objects.Promise, objects.Proxy, RangeError, ReferenceError,
|
||||
objects.Reflect, objects.Set, SyntaxError, TypeError, Uint8Array,
|
||||
Uint8ClampedArray, Uint16Array, Uint32Array, URIError,
|
||||
objects.WeakMap, objects.WeakSet
|
||||
].forEach(function(ctor){
|
||||
Object.getOwnPropertyNames(ctor).map(add);
|
||||
if (ctor.prototype) {
|
||||
Object.getOwnPropertyNames(ctor.prototype).map(add);
|
||||
}
|
||||
});
|
||||
function add(name) {
|
||||
push_uniq(a, name);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
function mangle_properties(ast, options) {
|
||||
options = defaults(options, {
|
||||
reserved : null,
|
||||
cache : null,
|
||||
only_cache : false,
|
||||
regex : null,
|
||||
ignore_quoted : false,
|
||||
debug : false
|
||||
});
|
||||
|
||||
var reserved = options.reserved;
|
||||
if (reserved == null)
|
||||
reserved = find_builtins();
|
||||
|
||||
var cache = options.cache;
|
||||
if (cache == null) {
|
||||
cache = {
|
||||
cname: -1,
|
||||
props: new Dictionary()
|
||||
};
|
||||
}
|
||||
|
||||
var regex = options.regex;
|
||||
var ignore_quoted = options.ignore_quoted;
|
||||
|
||||
// note debug is either false (disabled), or a string of the debug suffix to use (enabled).
|
||||
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
|
||||
// the same as passing an empty string.
|
||||
var debug = (options.debug !== false);
|
||||
var debug_name_suffix;
|
||||
if (debug) {
|
||||
debug_name_suffix = (options.debug === true ? "" : options.debug);
|
||||
}
|
||||
|
||||
var names_to_mangle = [];
|
||||
var unmangleable = [];
|
||||
var ignored = {};
|
||||
|
||||
// step 1: find candidates to mangle
|
||||
ast.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
add(node.key, ignore_quoted && node.quote);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter, since KeyVal is handled above
|
||||
add(node.key.name);
|
||||
}
|
||||
else if (node instanceof AST_Dot) {
|
||||
add(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, ignore_quoted);
|
||||
}
|
||||
else if (node instanceof AST_ConciseMethod) {
|
||||
add(node.name.name);
|
||||
}
|
||||
}));
|
||||
|
||||
// step 2: transform the tree, renaming properties
|
||||
return ast.transform(new TreeTransformer(function(node){
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
if (!(ignore_quoted && node.quote))
|
||||
node.key = mangle(node.key);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter
|
||||
node.key.name = mangle(node.key.name);
|
||||
}
|
||||
else if (node instanceof AST_Dot) {
|
||||
node.property = mangle(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
if (!ignore_quoted)
|
||||
node.property = mangleStrings(node.property);
|
||||
}
|
||||
else if (node instanceof AST_ConciseMethod) {
|
||||
if (should_mangle(node.name.name)) {
|
||||
node.name.name = mangle(node.name.name);
|
||||
}
|
||||
}
|
||||
// else if (node instanceof AST_String) {
|
||||
// if (should_mangle(node.value)) {
|
||||
// AST_Node.warn(
|
||||
// "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
|
||||
// file : node.start.file,
|
||||
// line : node.start.line,
|
||||
// col : node.start.col,
|
||||
// prop : node.value
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
}));
|
||||
|
||||
// only function declarations after this line
|
||||
|
||||
function can_mangle(name) {
|
||||
if (!is_identifier(name)) return false;
|
||||
if (unmangleable.indexOf(name) >= 0) return false;
|
||||
if (reserved.indexOf(name) >= 0) return false;
|
||||
if (options.only_cache) {
|
||||
return cache.props.has(name);
|
||||
}
|
||||
if (/^[0-9.]+$/.test(name)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function should_mangle(name) {
|
||||
if (ignore_quoted && name in ignored) return false;
|
||||
if (regex && !regex.test(name)) return false;
|
||||
if (reserved.indexOf(name) >= 0) return false;
|
||||
return cache.props.has(name)
|
||||
|| names_to_mangle.indexOf(name) >= 0;
|
||||
}
|
||||
|
||||
function add(name, ignore) {
|
||||
if (ignore) {
|
||||
ignored[name] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (can_mangle(name))
|
||||
push_uniq(names_to_mangle, name);
|
||||
|
||||
if (!should_mangle(name)) {
|
||||
push_uniq(unmangleable, name);
|
||||
}
|
||||
}
|
||||
|
||||
function mangle(name) {
|
||||
if (!should_mangle(name)) {
|
||||
return name;
|
||||
}
|
||||
|
||||
var mangled = cache.props.get(name);
|
||||
if (!mangled) {
|
||||
if (debug) {
|
||||
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
|
||||
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
|
||||
|
||||
if (can_mangle(debug_mangled) && !(ignore_quoted && debug_mangled in ignored)) {
|
||||
mangled = debug_mangled;
|
||||
}
|
||||
}
|
||||
|
||||
// either debug mode is off, or it is on and we could not use the mangled name
|
||||
if (!mangled) {
|
||||
// note can_mangle() does not check if the name collides with the 'ignored' set
|
||||
// (filled with quoted properties when ignore_quoted set). Make sure we add this
|
||||
// check so we don't collide with a quoted name.
|
||||
do {
|
||||
mangled = base54(++cache.cname);
|
||||
} while (!can_mangle(mangled) || (ignore_quoted && mangled in ignored));
|
||||
}
|
||||
|
||||
cache.props.set(name, mangled);
|
||||
}
|
||||
return mangled;
|
||||
}
|
||||
|
||||
function addStrings(node, ignore) {
|
||||
var out = {};
|
||||
try {
|
||||
(function walk(node){
|
||||
node.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_Seq) {
|
||||
walk(node.cdr);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_String) {
|
||||
add(node.value, ignore);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Conditional) {
|
||||
walk(node.consequent);
|
||||
walk(node.alternative);
|
||||
return true;
|
||||
}
|
||||
throw out;
|
||||
}));
|
||||
})(node);
|
||||
} catch(ex) {
|
||||
if (ex !== out) throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
function mangleStrings(node) {
|
||||
return node.transform(new TreeTransformer(function(node){
|
||||
if (node instanceof AST_Seq) {
|
||||
node.cdr = mangleStrings(node.cdr);
|
||||
}
|
||||
else if (node instanceof AST_String) {
|
||||
node.value = mangle(node.value);
|
||||
}
|
||||
else if (node instanceof AST_Conditional) {
|
||||
node.consequent = mangleStrings(node.consequent);
|
||||
node.alternative = mangleStrings(node.alternative);
|
||||
}
|
||||
return node;
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
362
lib/scope.js
362
lib/scope.js
@@ -49,83 +49,141 @@ function SymbolDef(scope, index, orig) {
|
||||
this.scope = scope;
|
||||
this.references = [];
|
||||
this.global = false;
|
||||
this.export = false;
|
||||
this.mangled_name = null;
|
||||
this.object_destructuring_arg = false;
|
||||
this.undeclared = false;
|
||||
this.constant = false;
|
||||
this.index = index;
|
||||
this.id = SymbolDef.next_id++;
|
||||
};
|
||||
|
||||
SymbolDef.next_id = 1;
|
||||
|
||||
SymbolDef.prototype = {
|
||||
unmangleable: function(options) {
|
||||
return (this.global && !(options && options.toplevel))
|
||||
if (!options) options = {};
|
||||
|
||||
return (this.global && !options.toplevel)
|
||||
|| this.export
|
||||
|| this.object_destructuring_arg
|
||||
|| this.undeclared
|
||||
|| (!(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with));
|
||||
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|
||||
|| (options.keep_fnames
|
||||
&& (this.orig[0] instanceof AST_SymbolLambda
|
||||
|| this.orig[0] instanceof AST_SymbolDefun))
|
||||
|| this.orig[0] instanceof AST_SymbolMethod
|
||||
|| (options.keep_classnames
|
||||
&& (this.orig[0] instanceof AST_SymbolClass
|
||||
|| this.orig[0] instanceof AST_SymbolDefClass));
|
||||
},
|
||||
mangle: function(options) {
|
||||
if (!this.mangled_name && !this.unmangleable(options)) {
|
||||
var cache = options.cache && options.cache.props;
|
||||
if (this.global && cache && cache.has(this.name)) {
|
||||
this.mangled_name = cache.get(this.name);
|
||||
}
|
||||
else if (!this.mangled_name && !this.unmangleable(options)) {
|
||||
var s = this.scope;
|
||||
if (this.orig[0] instanceof AST_SymbolLambda && !options.screw_ie8)
|
||||
if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda)
|
||||
s = s.parent_scope;
|
||||
this.mangled_name = s.next_mangled(options);
|
||||
this.mangled_name = s.next_mangled(options, this);
|
||||
if (this.global && cache) {
|
||||
cache.set(this.name, this.mangled_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
||||
// This does what ast_add_scope did in UglifyJS v1.
|
||||
//
|
||||
// Part of it could be done at parse time, but it would complicate
|
||||
// the parser (and it's already kinda complex). It's also worth
|
||||
// having it separated because we might need to call it multiple
|
||||
// times on the same tree.
|
||||
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
options = defaults(options, {
|
||||
screw_ie8: true,
|
||||
cache: null
|
||||
});
|
||||
|
||||
// pass 1: setup scope chaining and handle definitions
|
||||
var self = this;
|
||||
var scope = self.parent_scope = null;
|
||||
var labels = new Dictionary();
|
||||
var nesting = 0;
|
||||
var defun = null;
|
||||
var in_destructuring = null;
|
||||
var in_export = false;
|
||||
var in_block = 0;
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node.is_block_scope()) {
|
||||
var save_scope = scope;
|
||||
scope = new AST_Scope(node);
|
||||
scope.init_scope_vars();
|
||||
scope.parent_scope = save_scope;
|
||||
if (!(node instanceof AST_Scope)) {
|
||||
scope.uses_with = save_scope.uses_with;
|
||||
scope.uses_eval = save_scope.uses_eval;
|
||||
scope.directives = save_scope.directives;
|
||||
}
|
||||
descend();
|
||||
scope = save_scope;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Destructuring && node.is_array === false) {
|
||||
in_destructuring = node; // These don't nest
|
||||
descend();
|
||||
in_destructuring = null;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Scope) {
|
||||
node.init_scope_vars(nesting);
|
||||
node.init_scope_vars();
|
||||
var save_scope = node.parent_scope = scope;
|
||||
var save_defun = defun;
|
||||
var save_labels = labels;
|
||||
++nesting;
|
||||
scope = node;
|
||||
defun = scope = node;
|
||||
labels = new Dictionary();
|
||||
descend();
|
||||
labels = save_labels;
|
||||
scope = save_scope;
|
||||
--nesting;
|
||||
defun = save_defun;
|
||||
labels = save_labels;
|
||||
return true; // don't descend again in TreeWalker
|
||||
}
|
||||
if (node instanceof AST_Directive) {
|
||||
node.scope = scope;
|
||||
push_uniq(scope.directives, node.value);
|
||||
if (node instanceof AST_Export) {
|
||||
in_export = true;
|
||||
descend();
|
||||
in_export = false;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_BlockStatement
|
||||
|| node instanceof AST_Switch
|
||||
|| node instanceof AST_Try
|
||||
|| node instanceof AST_Catch
|
||||
|| node instanceof AST_Finally) {
|
||||
in_block++;
|
||||
descend();
|
||||
in_block--;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_LabeledStatement) {
|
||||
var l = node.label;
|
||||
if (labels.has(l.name)) {
|
||||
throw new Error(string_template("Label {name} defined twice", l));
|
||||
}
|
||||
labels.set(l.name, l);
|
||||
descend();
|
||||
labels.del(l.name);
|
||||
return true; // no descend again
|
||||
}
|
||||
if (node instanceof AST_With) {
|
||||
for (var s = scope; s; s = s.parent_scope)
|
||||
s.uses_with = true;
|
||||
return;
|
||||
}
|
||||
if (node instanceof AST_LabeledStatement) {
|
||||
var l = node.label;
|
||||
if (labels.has(l.name))
|
||||
throw new Error(string_template("Label {name} defined twice", l));
|
||||
labels.set(l.name, l);
|
||||
descend();
|
||||
labels.del(l.name);
|
||||
return true; // no descend again
|
||||
}
|
||||
if (node instanceof AST_Symbol) {
|
||||
node.scope = scope;
|
||||
}
|
||||
if (node instanceof AST_SymbolFunarg) {
|
||||
node.object_destructuring_arg = !!in_destructuring;
|
||||
}
|
||||
if (node instanceof AST_Label) {
|
||||
node.thedef = node;
|
||||
node.init_scope_vars();
|
||||
node.references = [];
|
||||
}
|
||||
if (node instanceof AST_SymbolLambda) {
|
||||
scope.def_function(node);
|
||||
defun.def_function(node, in_export, in_block);
|
||||
}
|
||||
else if (node instanceof AST_SymbolDefun) {
|
||||
// Careful here, the scope where this should be defined is
|
||||
@@ -133,24 +191,34 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
||||
// scope when we encounter the AST_Defun node (which is
|
||||
// instanceof AST_Scope) but we get to the symbol a bit
|
||||
// later.
|
||||
(node.scope = scope.parent_scope).def_function(node);
|
||||
var parent_lambda = defun.parent_scope;
|
||||
while (parent_lambda.is_block_scope()) {
|
||||
parent_lambda = parent_lambda.parent_scope;
|
||||
}
|
||||
(node.scope = parent_lambda).def_function(node, in_export, in_block);
|
||||
}
|
||||
else if (node instanceof AST_SymbolClass) {
|
||||
defun.def_variable(node, in_export, in_block);
|
||||
}
|
||||
else if (node instanceof AST_SymbolImport) {
|
||||
scope.def_variable(node, in_export, in_block);
|
||||
}
|
||||
else if (node instanceof AST_SymbolDefClass) {
|
||||
// This deals with the name of the class being available
|
||||
// inside the class.
|
||||
(node.scope = defun.parent_scope).def_function(node, in_export, in_block);
|
||||
}
|
||||
else if (node instanceof AST_SymbolVar
|
||||
|| node instanceof AST_SymbolConst) {
|
||||
var def = scope.def_variable(node);
|
||||
def.constant = node instanceof AST_SymbolConst;
|
||||
|| node instanceof AST_SymbolConst
|
||||
|| node instanceof AST_SymbolLet) {
|
||||
var def = ((node instanceof AST_SymbolBlockDeclaration) ? scope : defun).def_variable(node, in_export, in_block);
|
||||
def.destructuring = in_destructuring;
|
||||
def.init = tw.parent().value;
|
||||
}
|
||||
else if (node instanceof AST_SymbolCatch) {
|
||||
// XXX: this is wrong according to ECMA-262 (12.4). the
|
||||
// `catch` argument name should be visible only inside the
|
||||
// catch block. For a quick fix AST_Catch should inherit
|
||||
// from AST_Scope. Keeping it this way because of IE,
|
||||
// which doesn't obey the standard. (it introduces the
|
||||
// identifier in the enclosing scope)
|
||||
scope.def_variable(node);
|
||||
(options.screw_ie8 ? scope : defun).def_variable(node, in_export, in_block);
|
||||
}
|
||||
if (node instanceof AST_LabelRef) {
|
||||
else if (node instanceof AST_LabelRef) {
|
||||
var sym = labels.get(node.name);
|
||||
if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
|
||||
name: node.name,
|
||||
@@ -164,6 +232,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
||||
|
||||
// pass 2: find back references and eval
|
||||
var func = null;
|
||||
var cls = null;
|
||||
var globals = self.globals = new Dictionary();
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node instanceof AST_Lambda) {
|
||||
@@ -173,42 +242,57 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
||||
func = prev_func;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_LabelRef) {
|
||||
node.reference();
|
||||
if (node instanceof AST_Class) {
|
||||
var prev_cls = cls;
|
||||
cls = node;
|
||||
descend();
|
||||
cls = prev_cls;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_LoopControl && node.label) {
|
||||
node.label.thedef.references.push(node);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var name = node.name;
|
||||
var sym = node.scope.find_variable(name);
|
||||
if (!sym) {
|
||||
var g;
|
||||
if (globals.has(name)) {
|
||||
g = globals.get(name);
|
||||
} else {
|
||||
g = new SymbolDef(self, globals.size(), node);
|
||||
g.undeclared = true;
|
||||
globals.set(name, g);
|
||||
if (name == "eval" && tw.parent() instanceof AST_Call) {
|
||||
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
|
||||
s.uses_eval = true;
|
||||
}
|
||||
node.thedef = g;
|
||||
if (name == "eval" && tw.parent() instanceof AST_Call) {
|
||||
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope)
|
||||
s.uses_eval = true;
|
||||
}
|
||||
if (name == "arguments") {
|
||||
func.uses_arguments = true;
|
||||
}
|
||||
} else {
|
||||
node.thedef = sym;
|
||||
}
|
||||
node.reference();
|
||||
var sym = node.scope.find_variable(name);
|
||||
if (node.scope instanceof AST_Lambda && name == "arguments") {
|
||||
node.scope.uses_arguments = true;
|
||||
}
|
||||
if (!sym) {
|
||||
sym = self.def_global(node);
|
||||
}
|
||||
node.thedef = sym;
|
||||
node.reference(options);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
self.walk(tw);
|
||||
|
||||
if (options.cache) {
|
||||
this.cname = options.cache.cname;
|
||||
}
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
|
||||
this.directives = []; // contains the directives defined in this scope, i.e. "use strict"
|
||||
AST_Toplevel.DEFMETHOD("def_global", function(node){
|
||||
var globals = this.globals, name = node.name;
|
||||
if (globals.has(name)) {
|
||||
return globals.get(name);
|
||||
} else {
|
||||
var g = new SymbolDef(this, globals.size(), node);
|
||||
g.undeclared = true;
|
||||
g.global = true;
|
||||
globals.set(name, g);
|
||||
return g;
|
||||
}
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("init_scope_vars", function(){
|
||||
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
||||
this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
|
||||
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
||||
@@ -216,36 +300,44 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
|
||||
this.parent_scope = null; // the parent scope
|
||||
this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
|
||||
this.cname = -1; // the current index for mangling functions/variables
|
||||
this.nesting = nesting; // the nesting level of this scope (0 means toplevel)
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("strict", function(){
|
||||
return this.has_directive("use strict");
|
||||
AST_Node.DEFMETHOD("is_block_scope", function(){
|
||||
return false; // Behaviour will be overridden by AST_Block
|
||||
});
|
||||
|
||||
AST_Block.DEFMETHOD("is_block_scope", function(){
|
||||
return (
|
||||
!(this instanceof AST_Lambda) &&
|
||||
!(this instanceof AST_Toplevel) &&
|
||||
!(this instanceof AST_Class) &&
|
||||
!(this instanceof AST_SwitchBranch)
|
||||
);
|
||||
});
|
||||
|
||||
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
|
||||
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
|
||||
this.uses_arguments = false;
|
||||
|
||||
var symbol = new AST_VarDef({ name: "arguments", start: this.start, end: this.end });
|
||||
var def = new SymbolDef(this, this.variables.size(), symbol);
|
||||
this.variables.set(symbol.name, def);
|
||||
});
|
||||
|
||||
AST_SymbolRef.DEFMETHOD("reference", function() {
|
||||
AST_SymbolRef.DEFMETHOD("reference", function(options) {
|
||||
var def = this.definition();
|
||||
def.references.push(this);
|
||||
var s = this.scope;
|
||||
while (s) {
|
||||
push_uniq(s.enclosed, def);
|
||||
if (options.keep_fnames) {
|
||||
s.functions.each(function(d) {
|
||||
push_uniq(def.scope.enclosed, d);
|
||||
});
|
||||
}
|
||||
if (s === def.scope) break;
|
||||
s = s.parent_scope;
|
||||
}
|
||||
this.frame = this.scope.nesting - def.scope.nesting;
|
||||
});
|
||||
|
||||
AST_Label.DEFMETHOD("init_scope_vars", function(){
|
||||
this.references = [];
|
||||
});
|
||||
|
||||
AST_LabelRef.DEFMETHOD("reference", function(){
|
||||
this.thedef.references.push(this);
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("find_variable", function(name){
|
||||
@@ -254,21 +346,24 @@ AST_Scope.DEFMETHOD("find_variable", function(name){
|
||||
|| (this.parent_scope && this.parent_scope.find_variable(name));
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("has_directive", function(value){
|
||||
return this.parent_scope && this.parent_scope.has_directive(value)
|
||||
|| (this.directives.indexOf(value) >= 0 ? this : null);
|
||||
AST_Scope.DEFMETHOD("def_function", function(symbol, in_export, in_block){
|
||||
this.functions.set(symbol.name, this.def_variable(symbol, in_export, in_block));
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("def_function", function(symbol){
|
||||
this.functions.set(symbol.name, this.def_variable(symbol));
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("def_variable", function(symbol){
|
||||
AST_Scope.DEFMETHOD("def_variable", function(symbol, in_export, in_block){
|
||||
var def;
|
||||
if (!this.variables.has(symbol.name)) {
|
||||
def = new SymbolDef(this, this.variables.size(), symbol);
|
||||
this.variables.set(symbol.name, def);
|
||||
def.global = !this.parent_scope;
|
||||
def.object_destructuring_arg = symbol.object_destructuring_arg;
|
||||
if (in_export) {
|
||||
def.export = true;
|
||||
}
|
||||
if (in_block && symbol instanceof AST_SymbolBlockDeclaration) {
|
||||
def.global = false;
|
||||
} else {
|
||||
def.global = !this.parent_scope;
|
||||
}
|
||||
} else {
|
||||
def = this.variables.get(symbol.name);
|
||||
def.orig.push(symbol);
|
||||
@@ -281,6 +376,11 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){
|
||||
out: while (true) {
|
||||
var m = base54(++this.cname);
|
||||
if (!is_identifier(m)) continue; // skip over "do"
|
||||
|
||||
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
|
||||
// shadow a name excepted from mangling.
|
||||
if (options.except.indexOf(m) >= 0) continue;
|
||||
|
||||
// we must ensure that the mangled name does not shadow a name
|
||||
// from some parent scope that is referenced in this or in
|
||||
// inner scopes.
|
||||
@@ -293,13 +393,26 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){
|
||||
}
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("references", function(sym){
|
||||
if (sym instanceof AST_Symbol) sym = sym.definition();
|
||||
return this.enclosed.indexOf(sym) < 0 ? null : sym;
|
||||
AST_Function.DEFMETHOD("next_mangled", function(options, def){
|
||||
// #179, #326
|
||||
// in Safari strict mode, something like (function x(x){...}) is a syntax error;
|
||||
// a function expression's argument cannot shadow the function expression's name
|
||||
|
||||
var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition();
|
||||
|
||||
// the function's mangled_name is null when keep_fnames is true
|
||||
var tricky_name = tricky_def ? tricky_def.mangled_name || tricky_def.name : null;
|
||||
|
||||
while (true) {
|
||||
var name = AST_Lambda.prototype.next_mangled.call(this, options, def);
|
||||
if (!tricky_name || tricky_name != name)
|
||||
return name;
|
||||
}
|
||||
});
|
||||
|
||||
AST_Symbol.DEFMETHOD("unmangleable", function(options){
|
||||
return this.definition().unmangleable(options);
|
||||
var def = this.definition();
|
||||
return def && def.unmangleable(options);
|
||||
});
|
||||
|
||||
// property accessors are not mangleable
|
||||
@@ -339,22 +452,37 @@ AST_Symbol.DEFMETHOD("global", function(){
|
||||
|
||||
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
||||
return defaults(options, {
|
||||
except : [],
|
||||
eval : false,
|
||||
sort : false,
|
||||
toplevel : false,
|
||||
screw_ie8 : false
|
||||
except : [],
|
||||
eval : false,
|
||||
sort : false, // Ignored. Flag retained for backwards compatibility.
|
||||
toplevel : false,
|
||||
screw_ie8 : true,
|
||||
keep_fnames : false,
|
||||
keep_classnames : false
|
||||
});
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
options = this._default_mangler_options(options);
|
||||
|
||||
// Never mangle arguments
|
||||
options.except.push('arguments');
|
||||
|
||||
// We only need to mangle declaration nodes. Special logic wired
|
||||
// into the code generator will display the mangled name if it's
|
||||
// present (and for AST_SymbolRef-s it'll use the mangled name of
|
||||
// the AST_SymbolDeclaration that it points to).
|
||||
var lname = -1;
|
||||
var to_mangle = [];
|
||||
|
||||
if (options.cache) {
|
||||
this.globals.each(function(symbol){
|
||||
if (options.except.indexOf(symbol.name) < 0) {
|
||||
to_mangle.push(symbol);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node instanceof AST_LabeledStatement) {
|
||||
// lname is incremented when we get to the AST_Label
|
||||
@@ -370,9 +498,6 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
a.push(symbol);
|
||||
}
|
||||
});
|
||||
if (options.sort) a.sort(function(a, b){
|
||||
return b.references.length - a.references.length;
|
||||
});
|
||||
to_mangle.push.apply(to_mangle, a);
|
||||
return;
|
||||
}
|
||||
@@ -382,9 +507,23 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
node.mangled_name = name;
|
||||
return true;
|
||||
}
|
||||
var mangle_with_block_scope =
|
||||
(options.screw_ie8 && node instanceof AST_SymbolCatch) ||
|
||||
node instanceof AST_SymbolBlockDeclaration;
|
||||
if (mangle_with_block_scope) {
|
||||
to_mangle.push(node.definition());
|
||||
return;
|
||||
}
|
||||
});
|
||||
this.walk(tw);
|
||||
to_mangle.forEach(function(def){ def.mangle(options) });
|
||||
to_mangle.forEach(function(def){
|
||||
if (def.destructuring && !def.destructuring.is_array) return;
|
||||
def.mangle(options);
|
||||
});
|
||||
|
||||
if (options.cache) {
|
||||
options.cache.cname = this.cname;
|
||||
}
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
||||
@@ -431,21 +570,27 @@ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
||||
else if (node instanceof AST_With)
|
||||
base54.consider("with");
|
||||
else if (node instanceof AST_ObjectSetter)
|
||||
base54.consider("set" + node.key);
|
||||
base54.consider("set" + (typeof node.key === "string" ? node.key : ""));
|
||||
else if (node instanceof AST_ObjectGetter)
|
||||
base54.consider("get" + node.key);
|
||||
else if (node instanceof AST_ObjectKeyVal)
|
||||
base54.consider("get" + (typeof node.key === "string" ? node.key : ""));
|
||||
else if (node instanceof AST_ObjectKeyVal && typeof node.key === "string")
|
||||
base54.consider(node.key);
|
||||
else if (node instanceof AST_ConciseMethod && typeof node.key === "string")
|
||||
base54.consider(node.key);
|
||||
else if (node instanceof AST_New)
|
||||
base54.consider("new");
|
||||
else if (node instanceof AST_This)
|
||||
base54.consider("this");
|
||||
else if (node instanceof AST_Super)
|
||||
base54.consider("super");
|
||||
else if (node instanceof AST_Try)
|
||||
base54.consider("try");
|
||||
else if (node instanceof AST_Catch)
|
||||
base54.consider("catch");
|
||||
else if (node instanceof AST_Finally)
|
||||
base54.consider("finally");
|
||||
else if (node instanceof AST_Yield)
|
||||
base54.consider("yield");
|
||||
else if (node instanceof AST_Symbol && node.unmangleable(options))
|
||||
base54.consider(node.name);
|
||||
else if (node instanceof AST_Unary || node instanceof AST_Binary)
|
||||
@@ -484,7 +629,9 @@ var base54 = (function() {
|
||||
base54.freq = function(){ return frequency };
|
||||
function base54(num) {
|
||||
var ret = "", base = 54;
|
||||
num++;
|
||||
do {
|
||||
num--;
|
||||
ret += String.fromCharCode(chars[num % base]);
|
||||
num = Math.floor(num / base);
|
||||
base = 64;
|
||||
@@ -545,6 +692,7 @@ AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
|
||||
}
|
||||
if (options.unreferenced
|
||||
&& (node instanceof AST_SymbolDeclaration || node instanceof AST_Label)
|
||||
&& !(node instanceof AST_SymbolCatch)
|
||||
&& node.unreferenced()) {
|
||||
AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
|
||||
type: node instanceof AST_Label ? "Label" : "Symbol",
|
||||
|
||||
@@ -49,26 +49,42 @@ function SourceMap(options) {
|
||||
file : null,
|
||||
root : null,
|
||||
orig : null,
|
||||
|
||||
orig_line_diff : 0,
|
||||
dest_line_diff : 0,
|
||||
});
|
||||
var generator = new MOZ_SourceMap.SourceMapGenerator({
|
||||
file : options.file,
|
||||
sourceRoot : options.root
|
||||
});
|
||||
var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
|
||||
|
||||
if (orig_map && Array.isArray(options.orig.sources)) {
|
||||
orig_map._sources.toArray().forEach(function(source) {
|
||||
var sourceContent = orig_map.sourceContentFor(source, true);
|
||||
if (sourceContent) {
|
||||
generator.setSourceContent(source, sourceContent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
|
||||
if (orig_map) {
|
||||
var info = orig_map.originalPositionFor({
|
||||
line: orig_line,
|
||||
column: orig_col
|
||||
});
|
||||
if (info.source === null) {
|
||||
return;
|
||||
}
|
||||
source = info.source;
|
||||
orig_line = info.line;
|
||||
orig_col = info.column;
|
||||
name = info.name;
|
||||
name = info.name || name;
|
||||
}
|
||||
generator.addMapping({
|
||||
generated : { line: gen_line, column: gen_col },
|
||||
original : { line: orig_line, column: orig_col },
|
||||
generated : { line: gen_line + options.dest_line_diff, column: gen_col },
|
||||
original : { line: orig_line + options.orig_line_diff, column: orig_col },
|
||||
source : source,
|
||||
name : name
|
||||
});
|
||||
@@ -76,6 +92,6 @@ function SourceMap(options) {
|
||||
return {
|
||||
add : add,
|
||||
get : function() { return generator },
|
||||
toString : function() { return generator.toString() }
|
||||
toString : function() { return JSON.stringify(generator.toJSON()); }
|
||||
};
|
||||
};
|
||||
|
||||
@@ -64,13 +64,13 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
x = this;
|
||||
descend(x, tw);
|
||||
} else {
|
||||
tw.stack[tw.stack.length - 1] = x = this.clone();
|
||||
tw.stack[tw.stack.length - 1] = x = this;
|
||||
descend(x, tw);
|
||||
y = tw.after(x, in_list);
|
||||
if (y !== undefined) x = y;
|
||||
}
|
||||
}
|
||||
tw.pop();
|
||||
tw.pop(this);
|
||||
return x;
|
||||
});
|
||||
};
|
||||
@@ -159,13 +159,22 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
});
|
||||
|
||||
_(AST_VarDef, function(self, tw){
|
||||
self.name = self.name.transform(tw);
|
||||
if (self.value) self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Destructuring, function(self, tw) {
|
||||
self.names = do_list(self.names, tw);
|
||||
});
|
||||
|
||||
_(AST_Lambda, function(self, tw){
|
||||
if (self.name) self.name = self.name.transform(tw);
|
||||
self.argnames = do_list(self.argnames, tw);
|
||||
self.body = do_list(self.body, tw);
|
||||
if (self.body instanceof AST_Node) {
|
||||
self.body = self.body.transform(tw);
|
||||
} else {
|
||||
self.body = do_list(self.body, tw);
|
||||
}
|
||||
});
|
||||
|
||||
_(AST_Call, function(self, tw){
|
||||
@@ -187,6 +196,10 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
self.property = self.property.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Yield, function(self, tw){
|
||||
if (self.expression) self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Unary, function(self, tw){
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
@@ -211,7 +224,32 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
});
|
||||
|
||||
_(AST_ObjectProperty, function(self, tw){
|
||||
if (self.key instanceof AST_Node) {
|
||||
self.key = self.key.transform(tw);
|
||||
}
|
||||
self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Class, function(self, tw){
|
||||
if (self.name) self.name = self.name.transform(tw);
|
||||
if (self.extends) self.extends = self.extends.transform(tw);
|
||||
self.properties = do_list(self.properties, tw);
|
||||
});
|
||||
|
||||
_(AST_Expansion, function(self, tw){
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_TemplateString, function(self, tw) {
|
||||
for (var i = 0; i < self.segments.length; i++) {
|
||||
if (!(self.segments[i] instanceof AST_TemplateSegment)) {
|
||||
self.segments[i] = self.segments[i].transform(tw);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
_(AST_PrefixedTemplateString, function(self, tw) {
|
||||
self.template_string = self.template_string.transform(tw);
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
95
lib/utils.js
95
lib/utils.js
@@ -59,10 +59,7 @@ function characters(str) {
|
||||
};
|
||||
|
||||
function member(name, array) {
|
||||
for (var i = array.length; --i >= 0;)
|
||||
if (array[i] == name)
|
||||
return true;
|
||||
return false;
|
||||
return array.indexOf(name) >= 0;
|
||||
};
|
||||
|
||||
function find_if(func, array) {
|
||||
@@ -81,31 +78,57 @@ function repeat_string(str, i) {
|
||||
return d;
|
||||
};
|
||||
|
||||
function configure_error_stack(fn) {
|
||||
Object.defineProperty(fn.prototype, "stack", {
|
||||
get: function() {
|
||||
var err = new Error(this.message);
|
||||
err.name = this.name;
|
||||
try {
|
||||
throw err;
|
||||
} catch(e) {
|
||||
return e.stack;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function DefaultsError(msg, defs) {
|
||||
this.msg = msg;
|
||||
this.message = msg;
|
||||
this.defs = defs;
|
||||
};
|
||||
DefaultsError.prototype = Object.create(Error.prototype);
|
||||
DefaultsError.prototype.constructor = DefaultsError;
|
||||
DefaultsError.prototype.name = "DefaultsError";
|
||||
configure_error_stack(DefaultsError);
|
||||
|
||||
DefaultsError.croak = function(msg, defs) {
|
||||
throw new DefaultsError(msg, defs);
|
||||
};
|
||||
|
||||
function defaults(args, defs, croak) {
|
||||
if (args === true)
|
||||
args = {};
|
||||
var ret = args || {};
|
||||
if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i))
|
||||
throw new DefaultsError("`" + i + "` is not a supported option", defs);
|
||||
for (var i in defs) if (defs.hasOwnProperty(i)) {
|
||||
ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i];
|
||||
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i))
|
||||
DefaultsError.croak("`" + i + "` is not a supported option", defs);
|
||||
for (var i in defs) if (HOP(defs, i)) {
|
||||
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
function merge(obj, ext) {
|
||||
for (var i in ext) if (ext.hasOwnProperty(i)) {
|
||||
var count = 0;
|
||||
for (var i in ext) if (HOP(ext, i)) {
|
||||
obj[i] = ext[i];
|
||||
count++;
|
||||
}
|
||||
return obj;
|
||||
return count;
|
||||
};
|
||||
|
||||
function noop() {};
|
||||
function return_false() { return false; }
|
||||
function return_true() { return true; }
|
||||
|
||||
var MAP = (function(){
|
||||
function MAP(a, f, backwards) {
|
||||
@@ -141,7 +164,7 @@ var MAP = (function(){
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i in a) if (a.hasOwnProperty(i)) if (doit()) break;
|
||||
for (i in a) if (HOP(a, i)) if (doit()) break;
|
||||
}
|
||||
return top.concat(ret);
|
||||
};
|
||||
@@ -221,10 +244,19 @@ function makePredicate(words) {
|
||||
}
|
||||
cats.push([words[i]]);
|
||||
}
|
||||
function quote(word) {
|
||||
return JSON.stringify(word).replace(/[\u2028\u2029]/g, function(s) {
|
||||
switch (s) {
|
||||
case "\u2028": return "\\u2028";
|
||||
case "\u2029": return "\\u2029";
|
||||
}
|
||||
return s;
|
||||
});
|
||||
}
|
||||
function compareTo(arr) {
|
||||
if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
|
||||
if (arr.length == 1) return f += "return str === " + quote(arr[0]) + ";";
|
||||
f += "switch(str){";
|
||||
for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
|
||||
for (var i = 0; i < arr.length; ++i) f += "case " + quote(arr[i]) + ":";
|
||||
f += "return true}return false;";
|
||||
}
|
||||
// When there are more than three length categories, an outer
|
||||
@@ -291,5 +323,38 @@ Dictionary.prototype = {
|
||||
for (var i in this._values)
|
||||
ret.push(f(this._values[i], i.substr(1)));
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
toObject: function() { return this._values }
|
||||
};
|
||||
Dictionary.fromObject = function(obj) {
|
||||
var dict = new Dictionary();
|
||||
dict._size = merge(dict._values, obj);
|
||||
return dict;
|
||||
};
|
||||
|
||||
function HOP(obj, prop) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||
}
|
||||
|
||||
// return true if the node at the top of the stack (that means the
|
||||
// innermost node in the current output) is lexically the first in
|
||||
// a statement.
|
||||
function first_in_statement(stack) {
|
||||
var node = stack.parent(-1);
|
||||
for (var i = 0, p; p = stack.parent(i); i++) {
|
||||
if (p instanceof AST_Statement && p.body === node)
|
||||
return true;
|
||||
if ((p instanceof AST_Seq && p.car === node ) ||
|
||||
(p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||
|
||||
(p instanceof AST_Dot && p.expression === node ) ||
|
||||
(p instanceof AST_Sub && p.expression === node ) ||
|
||||
(p instanceof AST_Conditional && p.condition === node ) ||
|
||||
(p instanceof AST_Binary && p.left === node ) ||
|
||||
(p instanceof AST_UnaryPostfix && p.expression === node ))
|
||||
{
|
||||
node = p;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
76
package.json
76
package.json
@@ -1,26 +1,54 @@
|
||||
{
|
||||
"name": "uglify-js",
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"homepage": "http://lisperator.net/uglifyjs",
|
||||
"main": "tools/node.js",
|
||||
"version": "2.3.5",
|
||||
"engines": { "node" : ">=0.4.0" },
|
||||
"maintainers": [{
|
||||
"name": "Mihai Bazon",
|
||||
"email": "mihai.bazon@gmail.com",
|
||||
"web": "http://lisperator.net/"
|
||||
}],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mishoo/UglifyJS2.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"async" : "~0.2.6",
|
||||
"source-map" : "~0.1.7",
|
||||
"optimist" : "~0.3.5"
|
||||
},
|
||||
"bin": {
|
||||
"uglifyjs" : "bin/uglifyjs"
|
||||
},
|
||||
"scripts": {"test": "node test/run-tests.js"}
|
||||
"name": "uglify-js",
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"homepage": "http://lisperator.net/uglifyjs",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "2.8.0",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
"maintainers": [
|
||||
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mishoo/UglifyJS2.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/mishoo/UglifyJS2/issues"
|
||||
},
|
||||
"main": "tools/node.js",
|
||||
"bin": {
|
||||
"uglifyjs": "bin/uglifyjs"
|
||||
},
|
||||
"files": [
|
||||
"bin",
|
||||
"lib",
|
||||
"tools",
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"async": "~0.2.6",
|
||||
"source-map": "~0.5.1",
|
||||
"uglify-to-browserify": "~1.0.0",
|
||||
"yargs": "~3.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "~0.6.0",
|
||||
"escodegen": "~1.3.3",
|
||||
"esfuzz": "~0.3.1",
|
||||
"estraverse": "~1.5.1",
|
||||
"mocha": "~2.3.4"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
"uglify-to-browserify"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"shrinkwrap": "rm ./npm-shrinkwrap.json; rm -rf ./node_modules; npm i && npm shrinkwrap && npm outdated",
|
||||
"test": "node test/run-tests.js"
|
||||
},
|
||||
"keywords": ["uglify", "uglify-js", "minify", "minifier"]
|
||||
}
|
||||
|
||||
49
test/benchmark.js
Normal file
49
test/benchmark.js
Normal file
@@ -0,0 +1,49 @@
|
||||
#! /usr/bin/env node
|
||||
// -*- js -*-
|
||||
|
||||
"use strict";
|
||||
|
||||
var createHash = require("crypto").createHash;
|
||||
var fork = require("child_process").fork;
|
||||
var args = process.argv.slice(2);
|
||||
if (!args.length) {
|
||||
args.push("-mc", "warnings=false");
|
||||
}
|
||||
args.push("--stats");
|
||||
var urls = [
|
||||
"https://code.jquery.com/jquery-3.1.1.js",
|
||||
"https://code.angularjs.org/1.6.1/angular.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.9.0/math.js",
|
||||
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
|
||||
"https://unpkg.com/react@15.3.2/dist/react.js",
|
||||
"http://builds.emberjs.com/tags/v2.11.0/ember.prod.js",
|
||||
"https://cdn.jsdelivr.net/lodash/4.17.4/lodash.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.js",
|
||||
];
|
||||
var results = {};
|
||||
var remaining = 2 * urls.length;
|
||||
function done() {
|
||||
if (!--remaining) {
|
||||
urls.forEach(function(url) {
|
||||
console.log();
|
||||
console.log(url);
|
||||
console.log(results[url].time);
|
||||
console.log("SHA1:", results[url].sha1);
|
||||
});
|
||||
}
|
||||
}
|
||||
urls.forEach(function(url) {
|
||||
results[url] = { time: "" };
|
||||
require(url.slice(0, url.indexOf(":"))).get(url, function(res) {
|
||||
var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
|
||||
res.pipe(uglifyjs.stdin);
|
||||
uglifyjs.stdout.pipe(createHash("sha1")).on("data", function(data) {
|
||||
results[url].sha1 = data.toString("hex");
|
||||
done();
|
||||
});
|
||||
uglifyjs.stderr.setEncoding("utf8");
|
||||
uglifyjs.stderr.on("data", function(data) {
|
||||
results[url].time += data;
|
||||
}).on("end", done)
|
||||
});
|
||||
});
|
||||
67
test/compress/angular-inject.js
vendored
Normal file
67
test/compress/angular-inject.js
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
ng_inject_defun: {
|
||||
options = {
|
||||
angular: true
|
||||
};
|
||||
input: {
|
||||
/*@ngInject*/
|
||||
function Controller(dependency) {
|
||||
return dependency;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function Controller(dependency) {
|
||||
return dependency;
|
||||
}
|
||||
Controller.$inject=['dependency']
|
||||
}
|
||||
}
|
||||
|
||||
ng_inject_assignment: {
|
||||
options = {
|
||||
angular: true
|
||||
};
|
||||
input: {
|
||||
/*@ngInject*/
|
||||
var Controller = function(dependency) {
|
||||
return dependency;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var Controller = function(dependency) {
|
||||
return dependency;
|
||||
}
|
||||
Controller.$inject=['dependency']
|
||||
}
|
||||
}
|
||||
|
||||
ng_inject_inline: {
|
||||
options = {
|
||||
angular: true
|
||||
};
|
||||
input: {
|
||||
angular.module('a').
|
||||
factory('b',
|
||||
/*@ngInject*/
|
||||
function(dependency) {
|
||||
return dependency;
|
||||
}).
|
||||
directive('c',
|
||||
/*@ngInject*/
|
||||
function(anotherDependency) {
|
||||
return anotherDependency;
|
||||
})
|
||||
}
|
||||
expect: {
|
||||
angular.module('a').
|
||||
factory('b',[
|
||||
'dependency',
|
||||
function(dependency) {
|
||||
return dependency;
|
||||
}]).
|
||||
directive('c',[
|
||||
'anotherDependency',
|
||||
function(anotherDependency) {
|
||||
return anotherDependency;
|
||||
}])
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,252 @@
|
||||
// NOTE trailing comma doesn't contribute to length of an array
|
||||
// That also means the array changes length if previous element is a hole too and got cut off
|
||||
holes_and_undefined: {
|
||||
input: {
|
||||
w = [1,,];
|
||||
x = [1, 2, undefined];
|
||||
y = [1, , 2, ];
|
||||
z = [1, undefined, 3];
|
||||
}
|
||||
expect: {
|
||||
w=[1,,];
|
||||
x=[1,2,void 0];
|
||||
y=[1,,2];
|
||||
z=[1,void 0,3];
|
||||
}
|
||||
}
|
||||
|
||||
constant_join: {
|
||||
options = {
|
||||
unsafe : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
var a = [ "foo", "bar", "baz" ].join("");
|
||||
var a1 = [ "foo", "bar", "baz" ].join();
|
||||
var a2 = [ "foo", "bar", "baz" ].join(null);
|
||||
var a3 = [ "foo", "bar", "baz" ].join(void 0);
|
||||
var a4 = [ "foo", , "baz" ].join();
|
||||
var a5 = [ "foo", null, "baz" ].join();
|
||||
var a6 = [ "foo", void 0, "baz" ].join();
|
||||
var b = [ "foo", 1, 2, 3, "bar" ].join("");
|
||||
var c = [ boo(), "foo", 1, 2, 3, "bar", bar() ].join("");
|
||||
var c1 = [ boo(), bar(), "foo", 1, 2, 3, "bar", bar() ].join("");
|
||||
var c2 = [ 1, 2, "foo", "bar", baz() ].join("");
|
||||
var c3 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join("");
|
||||
var c4 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join("");
|
||||
var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join();
|
||||
var c6 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join();
|
||||
var d = [ "foo", 1 + 2 + "bar", "baz" ].join("-");
|
||||
var e = [].join(foo + bar);
|
||||
var f = [].join("");
|
||||
var g = [].join("foo");
|
||||
}
|
||||
expect: {
|
||||
var a = "foobarbaz";
|
||||
var a1 = "foo,bar,baz";
|
||||
var a2 = "foonullbarnullbaz";
|
||||
var a3 = "foo,bar,baz";
|
||||
var a4 = "foo,,baz";
|
||||
var a5 = "foo,,baz";
|
||||
var a6 = "foo,,baz";
|
||||
var b = "foo123bar";
|
||||
var c = boo() + "foo123bar" + bar();
|
||||
var c1 = "" + boo() + bar() + "foo123bar" + bar();
|
||||
var c2 = "12foobar" + baz();
|
||||
var c3 = boo() + bar() + "foo123bar" + bar() + "foo";
|
||||
var c4 = "12foobar" + baz();
|
||||
var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join();
|
||||
var c6 = [ "1,2,,,foo,bar", baz() ].join();
|
||||
var d = "foo-3bar-baz";
|
||||
var e = [].join(foo + bar);
|
||||
var f = "";
|
||||
var g = "";
|
||||
}
|
||||
}
|
||||
|
||||
constant_join_2: {
|
||||
options = {
|
||||
unsafe : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
var a = [ "foo", "bar", boo(), "baz", "x", "y" ].join("");
|
||||
var b = [ "foo", "bar", boo(), "baz", "x", "y" ].join("-");
|
||||
var c = [ "foo", "bar", boo(), "baz", "x", "y" ].join("really-long-separator");
|
||||
var d = [ "foo", "bar", boo(),
|
||||
[ "foo", 1, 2, 3, "bar" ].join("+"),
|
||||
"baz", "x", "y" ].join("-");
|
||||
var e = [ "foo", "bar", boo(),
|
||||
[ "foo", 1, 2, 3, "bar" ].join("+"),
|
||||
"baz", "x", "y" ].join("really-long-separator");
|
||||
var f = [ "str", "str" + variable, "foo", "bar", "moo" + foo ].join("");
|
||||
}
|
||||
expect: {
|
||||
var a = "foobar" + boo() + "bazxy";
|
||||
var b = [ "foo-bar", boo(), "baz-x-y" ].join("-");
|
||||
var c = [ "foo", "bar", boo(), "baz", "x", "y" ].join("really-long-separator");
|
||||
var d = [ "foo-bar", boo(), "foo+1+2+3+bar-baz-x-y" ].join("-");
|
||||
var e = [ "foo", "bar", boo(),
|
||||
"foo+1+2+3+bar",
|
||||
"baz", "x", "y" ].join("really-long-separator");
|
||||
var f = "strstr" + variable + "foobarmoo" + foo;
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_variable_as_last_element: {
|
||||
input: {
|
||||
var values = [4, 5, 6];
|
||||
var a = [1, 2, 3, ...values];
|
||||
}
|
||||
expect: {
|
||||
var values = [4, 5, 6];
|
||||
var a = [1, 2, 3, ...values];
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_variable_in_middle: {
|
||||
input: {
|
||||
var values = [4, 5, 6];
|
||||
var a = [1, 2, 3, ...values, 7,,,];
|
||||
}
|
||||
expect: {
|
||||
var values = [4, 5, 6];
|
||||
var a = [1, 2, 3, ...values, 7,,,];
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_variable_at_front: {
|
||||
input: {
|
||||
var values = [1, 2, 3];
|
||||
var a = [...values, 4, 5, 6];
|
||||
}
|
||||
expect: {
|
||||
var values = [1, 2, 3];
|
||||
var a = [...values, 4, 5, 6];
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_variable_at_front_after_elisions: {
|
||||
input: {
|
||||
var values = [1, 2, 3];
|
||||
var a = [,,,...values, 4, 5, 6];
|
||||
}
|
||||
expect: {
|
||||
var values = [1, 2, 3];
|
||||
var a = [,,,...values, 4, 5, 6];
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_array_at_end: {
|
||||
input: {
|
||||
var a = [1, 2, ...[4, 5, 6]];
|
||||
}
|
||||
expect: {
|
||||
var a = [1, 2, ...[4, 5, 6]];
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_logical_expression_at_end: {
|
||||
options = { evaluate: true }
|
||||
input: {
|
||||
var a = [1, 2, 3, ...[2+2]]
|
||||
}
|
||||
expect: {
|
||||
var a = [1, 2, 3, ...[4]]
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_logical_expression_at_middle: {
|
||||
options = { evaluate: true }
|
||||
input: {
|
||||
var a = [1, 1, ...[1+1, 1+2, 2+3], 8]
|
||||
}
|
||||
expect: {
|
||||
var a = [1, 1, ...[2, 3, 5], 8]
|
||||
}
|
||||
}
|
||||
|
||||
constant_join_3: {
|
||||
options = {
|
||||
unsafe: true,
|
||||
evaluate: true,
|
||||
};
|
||||
input: {
|
||||
var a = [ null ].join();
|
||||
var b = [ , ].join();
|
||||
var c = [ , 1, , 3 ].join();
|
||||
var d = [ foo ].join();
|
||||
var e = [ foo, null, undefined, bar ].join("-");
|
||||
var f = [ foo, bar ].join("");
|
||||
var g = [ null, "foo", null, bar + "baz" ].join("");
|
||||
var h = [ null, "foo", null, bar + "baz" ].join("-");
|
||||
var i = [ "foo" + bar, null, baz + "moo" ].join("");
|
||||
var j = [ foo + "bar", baz ].join("");
|
||||
var k = [ foo, "bar" + baz ].join("");
|
||||
var l = [ foo, bar + "baz" ].join("");
|
||||
}
|
||||
expect: {
|
||||
var a = "";
|
||||
var b = "";
|
||||
var c = ",1,,3";
|
||||
var d = "" + foo;
|
||||
var e = [ foo, "-", bar ].join("-");
|
||||
var f = "" + foo + bar;
|
||||
var g = "foo" + bar + "baz";
|
||||
var h = [ "-foo-", bar + "baz" ].join("-");
|
||||
var i = "foo" + bar + baz + "moo";
|
||||
var j = foo + "bar" + baz;
|
||||
var k = foo + "bar" + baz;
|
||||
var l = foo + (bar + "baz");
|
||||
}
|
||||
}
|
||||
|
||||
for_loop: {
|
||||
options = {
|
||||
unsafe : true,
|
||||
unused : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true
|
||||
};
|
||||
input: {
|
||||
function f0() {
|
||||
var a = [1, 2, 3];
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
console.log(a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function f1() {
|
||||
var a = [1, 2, 3];
|
||||
for (var i = 0, len = a.length; i < len; i++) {
|
||||
console.log(a[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function f2() {
|
||||
var a = [1, 2, 3];
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
a[i]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f0() {
|
||||
var a = [1, 2, 3];
|
||||
for (var i = 0; i < 3; i++)
|
||||
console.log(a[i]);
|
||||
}
|
||||
|
||||
function f1() {
|
||||
var a = [1, 2, 3];
|
||||
for (var i = 0; i < 3; i++)
|
||||
console.log(a[i]);
|
||||
}
|
||||
|
||||
function f2() {
|
||||
var a = [1, 2, 3];
|
||||
for (var i = 0; i < a.length; i++)
|
||||
a[i]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
137
test/compress/arrow.js
Normal file
137
test/compress/arrow.js
Normal file
@@ -0,0 +1,137 @@
|
||||
arrow_functions_without_body: {
|
||||
input: {
|
||||
var a1 = () => 42;
|
||||
var a2 = (p) => p;
|
||||
var a3 = p => p;
|
||||
var a4 = (...p) => p;
|
||||
var a5 = (b, c) => b + c;
|
||||
var a6 = (b, ...c) => b + c[0];
|
||||
var a7 = (...b) => b.join();
|
||||
}
|
||||
expect: {
|
||||
var a1 = () => 42;
|
||||
var a2 = (p) => p;
|
||||
var a3 = p => p;
|
||||
var a4 = (...p) => p;
|
||||
var a5 = (b, c) => b + c;
|
||||
var a6 = (b, ...c) => b + c[0];
|
||||
var a7 = (...b) => b.join();
|
||||
}
|
||||
}
|
||||
|
||||
arrow_functions_with_body: {
|
||||
input: {
|
||||
var a1 = () => {
|
||||
var a = 42 * Math.random();
|
||||
return a;
|
||||
};
|
||||
var a2 = (p) => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a3 = p => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a4 = (...p) => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a5 = (b, c) => {
|
||||
var result = b * c + b / c;
|
||||
return result
|
||||
};
|
||||
var a6 = (b, ...c) => {
|
||||
var result = b;
|
||||
for (var i = 0; i < c.length; i++)
|
||||
result += c[i];
|
||||
return result
|
||||
};
|
||||
var a7 = (...b) => {
|
||||
b.join();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a1 = () => {
|
||||
var a = 42 * Math.random();
|
||||
return a;
|
||||
};
|
||||
var a2 = (p) => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a3 = p => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a4 = (...p) => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a5 = (b, c) => {
|
||||
var result = b * c + b / c;
|
||||
return result
|
||||
};
|
||||
var a6 = (b, ...c) => {
|
||||
var result = b;
|
||||
for (var i = 0; i < c.length; i++)
|
||||
result += c[i];
|
||||
return result
|
||||
};
|
||||
var a7 = (...b) => {
|
||||
b.join();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
arrow_function_with_single_parameter_with_default: {
|
||||
input: {
|
||||
var foo = (a = 0) => doSomething(a);
|
||||
}
|
||||
expect_exact: "var foo=(a=0)=>doSomething(a);"
|
||||
}
|
||||
|
||||
arrow_binding_pattern: {
|
||||
input: {
|
||||
var foo = ([]) => "foo";
|
||||
var bar = ({}) => "bar";
|
||||
var with_default = (foo = "default") => foo;
|
||||
var object_with_default = ({foo = "default", bar: baz = "default"}) => foo;
|
||||
var array_after_spread = (...[foo]) => foo;
|
||||
var array_after_spread = (...{foo}) => foo;
|
||||
var computed = ({ [compute()]: x }) => {};
|
||||
var array_hole = ([, , ...x] = [1, 2]) => {};
|
||||
var object_trailing_elision = ({foo,}) => {};
|
||||
var spread_empty_array = (...[]) => "foo";
|
||||
var spread_empty_object = (...{}) => "foo";
|
||||
}
|
||||
expect: {
|
||||
var foo = ([]) => "foo";
|
||||
var bar = ({}) => "bar";
|
||||
var with_default = (foo = "default") => foo;
|
||||
var object_with_default = ({foo = "default", bar: baz = "default"}) => foo;
|
||||
var array_after_spread = (...[foo]) => foo;
|
||||
var array_after_spread = (...{foo}) => foo;
|
||||
var computed = ({ [compute()]: x }) => {};
|
||||
var array_hole = ([, , ...x] = [1, 2]) => {};
|
||||
var object_trailing_elision = ({foo,}) => {};
|
||||
var spread_empty_array = (...[]) => "foo";
|
||||
var spread_empty_object = (...{}) => "foo";
|
||||
}
|
||||
}
|
||||
|
||||
arrow_binding_pattern_strict: {
|
||||
input: {
|
||||
var foo = ([,]) => "foo";
|
||||
}
|
||||
expect_exact: 'var foo=([,])=>"foo";'
|
||||
}
|
||||
|
||||
arrow_with_regexp: {
|
||||
input: {
|
||||
num => /\d{11,14}/.test( num )
|
||||
}
|
||||
expect: {
|
||||
num => /\d{11,14}/.test( num )
|
||||
}
|
||||
}
|
||||
36
test/compress/ascii.js
Normal file
36
test/compress/ascii.js
Normal file
@@ -0,0 +1,36 @@
|
||||
ascii_only_true: {
|
||||
options = {}
|
||||
beautify = {
|
||||
ascii_only : true,
|
||||
screw_ie8 : true,
|
||||
beautify : false,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return "\x000\x001\x007\x008\x00" +
|
||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
|
||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
|
||||
}
|
||||
|
||||
ascii_only_false: {
|
||||
options = {}
|
||||
beautify = {
|
||||
ascii_only : false,
|
||||
screw_ie8 : true,
|
||||
beautify : false,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return "\x000\x001\x007\x008\x00" +
|
||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
|
||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
|
||||
}
|
||||
|
||||
106
test/compress/asm.js
Normal file
106
test/compress/asm.js
Normal file
@@ -0,0 +1,106 @@
|
||||
asm_mixed: {
|
||||
options = {
|
||||
sequences : true,
|
||||
properties : true,
|
||||
dead_code : true,
|
||||
drop_debugger : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
loops : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
keep_fargs : true,
|
||||
keep_fnames : false,
|
||||
hoist_vars : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
side_effects : true,
|
||||
negate_iife : true
|
||||
};
|
||||
input: {
|
||||
// adapted from http://asmjs.org/spec/latest/
|
||||
function asm_GeometricMean(stdlib, foreign, buffer) {
|
||||
"use asm";
|
||||
var exp = stdlib.Math.exp;
|
||||
var log = stdlib.Math.log;
|
||||
var values = new stdlib.Float64Array(buffer);
|
||||
function logSum(start, end) {
|
||||
start = start|0;
|
||||
end = end|0;
|
||||
var sum = 0.0, p = 0, q = 0;
|
||||
// asm.js forces byte addressing of the heap by requiring shifting by 3
|
||||
for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {
|
||||
sum = sum + +log(values[p>>3]);
|
||||
}
|
||||
return +sum;
|
||||
}
|
||||
function geometricMean(start, end) {
|
||||
start = start|0;
|
||||
end = end|0;
|
||||
return +exp(+logSum(start, end) / +((end - start)|0));
|
||||
}
|
||||
return { geometricMean: geometricMean };
|
||||
}
|
||||
function no_asm_GeometricMean(stdlib, foreign, buffer) {
|
||||
var exp = stdlib.Math.exp;
|
||||
var log = stdlib.Math.log;
|
||||
var values = new stdlib.Float64Array(buffer);
|
||||
function logSum(start, end) {
|
||||
start = start|0;
|
||||
end = end|0;
|
||||
var sum = 0.0, p = 0, q = 0;
|
||||
// asm.js forces byte addressing of the heap by requiring shifting by 3
|
||||
for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {
|
||||
sum = sum + +log(values[p>>3]);
|
||||
}
|
||||
return +sum;
|
||||
}
|
||||
function geometricMean(start, end) {
|
||||
start = start|0;
|
||||
end = end|0;
|
||||
return +exp(+logSum(start, end) / +((end - start)|0));
|
||||
}
|
||||
return { geometricMean: geometricMean };
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function asm_GeometricMean(stdlib, foreign, buffer) {
|
||||
"use asm";
|
||||
var exp = stdlib.Math.exp;
|
||||
var log = stdlib.Math.log;
|
||||
var values = new stdlib.Float64Array(buffer);
|
||||
function logSum(start, end) {
|
||||
start = start | 0;
|
||||
end = end | 0;
|
||||
var sum = 0.0, p = 0, q = 0;
|
||||
for (p = start << 3, q = end << 3; (p | 0) < (q | 0); p = p + 8 | 0) {
|
||||
sum = sum + +log(values[p >> 3]);
|
||||
}
|
||||
return +sum;
|
||||
}
|
||||
function geometricMean(start, end) {
|
||||
start = start | 0;
|
||||
end = end | 0;
|
||||
return +exp(+logSum(start, end) / +(end - start | 0));
|
||||
}
|
||||
return { geometricMean: geometricMean };
|
||||
}
|
||||
function no_asm_GeometricMean(stdlib, foreign, buffer) {
|
||||
function logSum(start, end) {
|
||||
start |= 0, end |= 0;
|
||||
var sum = 0, p = 0, q = 0;
|
||||
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
|
||||
return +sum;
|
||||
}
|
||||
function geometricMean(start, end) {
|
||||
return start |= 0, end |= 0, +exp(+logSum(start, end) / +(end - start | 0));
|
||||
}
|
||||
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
|
||||
return { geometricMean: geometricMean };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
238
test/compress/assignment.js
Normal file
238
test/compress/assignment.js
Normal file
@@ -0,0 +1,238 @@
|
||||
op_equals_left_local_var: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var x;
|
||||
|
||||
x = x + 3;
|
||||
x = x - 3;
|
||||
x = x / 3;
|
||||
x = x * 3;
|
||||
x = x >> 3;
|
||||
x = x << 3;
|
||||
x = x >>> 3;
|
||||
x = x | 3;
|
||||
x = x ^ 3;
|
||||
x = x % 3;
|
||||
x = x & 3;
|
||||
|
||||
x = x + g();
|
||||
x = x - g();
|
||||
x = x / g();
|
||||
x = x * g();
|
||||
x = x >> g();
|
||||
x = x << g();
|
||||
x = x >>> g();
|
||||
x = x | g();
|
||||
x = x ^ g();
|
||||
x = x % g();
|
||||
x = x & g();
|
||||
}
|
||||
expect: {
|
||||
var x;
|
||||
|
||||
x += 3;
|
||||
x -= 3;
|
||||
x /= 3;
|
||||
x *= 3;
|
||||
x >>= 3;
|
||||
x <<= 3;
|
||||
x >>>= 3;
|
||||
x |= 3;
|
||||
x ^= 3;
|
||||
x %= 3;
|
||||
x &= 3;
|
||||
|
||||
x += g();
|
||||
x -= g();
|
||||
x /= g();
|
||||
x *= g();
|
||||
x >>= g();
|
||||
x <<= g();
|
||||
x >>>= g();
|
||||
x |= g();
|
||||
x ^= g();
|
||||
x %= g();
|
||||
x &= g();
|
||||
}
|
||||
}
|
||||
|
||||
op_equals_right_local_var: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var x;
|
||||
|
||||
x = (x -= 2) ^ x;
|
||||
|
||||
x = 3 + x;
|
||||
x = 3 - x;
|
||||
x = 3 / x;
|
||||
x = 3 * x;
|
||||
x = 3 >> x;
|
||||
x = 3 << x;
|
||||
x = 3 >>> x;
|
||||
x = 3 | x;
|
||||
x = 3 ^ x;
|
||||
x = 3 % x;
|
||||
x = 3 & x;
|
||||
|
||||
x = g() + x;
|
||||
x = g() - x;
|
||||
x = g() / x;
|
||||
x = g() * x;
|
||||
x = g() >> x;
|
||||
x = g() << x;
|
||||
x = g() >>> x;
|
||||
x = g() | x;
|
||||
x = g() ^ x;
|
||||
x = g() % x;
|
||||
x = g() & x;
|
||||
}
|
||||
expect: {
|
||||
var x;
|
||||
|
||||
x = (x -= 2) ^ x;
|
||||
|
||||
x = 3 + x;
|
||||
x = 3 - x;
|
||||
x = 3 / x;
|
||||
x *= 3;
|
||||
x = 3 >> x;
|
||||
x = 3 << x;
|
||||
x = 3 >>> x;
|
||||
x |= 3;
|
||||
x ^= 3;
|
||||
x = 3 % x;
|
||||
x &= 3;
|
||||
|
||||
x = g() + x;
|
||||
x = g() - x;
|
||||
x = g() / x;
|
||||
x = g() * x;
|
||||
x = g() >> x;
|
||||
x = g() << x;
|
||||
x = g() >>> x;
|
||||
x = g() | x;
|
||||
x = g() ^ x;
|
||||
x = g() % x;
|
||||
x = g() & x;
|
||||
}
|
||||
}
|
||||
op_equals_left_global_var: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
x = x + 3;
|
||||
x = x - 3;
|
||||
x = x / 3;
|
||||
x = x * 3;
|
||||
x = x >> 3;
|
||||
x = x << 3;
|
||||
x = x >>> 3;
|
||||
x = x | 3;
|
||||
x = x ^ 3;
|
||||
x = x % 3;
|
||||
x = x & 3;
|
||||
|
||||
x = x + g();
|
||||
x = x - g();
|
||||
x = x / g();
|
||||
x = x * g();
|
||||
x = x >> g();
|
||||
x = x << g();
|
||||
x = x >>> g();
|
||||
x = x | g();
|
||||
x = x ^ g();
|
||||
x = x % g();
|
||||
x = x & g();
|
||||
}
|
||||
expect: {
|
||||
x += 3;
|
||||
x -= 3;
|
||||
x /= 3;
|
||||
x *= 3;
|
||||
x >>= 3;
|
||||
x <<= 3;
|
||||
x >>>= 3;
|
||||
x |= 3;
|
||||
x ^= 3;
|
||||
x %= 3;
|
||||
x &= 3;
|
||||
|
||||
x += g();
|
||||
x -= g();
|
||||
x /= g();
|
||||
x *= g();
|
||||
x >>= g();
|
||||
x <<= g();
|
||||
x >>>= g();
|
||||
x |= g();
|
||||
x ^= g();
|
||||
x %= g();
|
||||
x &= g();
|
||||
}
|
||||
}
|
||||
|
||||
op_equals_right_global_var: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
x = (x -= 2) ^ x;
|
||||
|
||||
x = 3 + x;
|
||||
x = 3 - x;
|
||||
x = 3 / x;
|
||||
x = 3 * x;
|
||||
x = 3 >> x;
|
||||
x = 3 << x;
|
||||
x = 3 >>> x;
|
||||
x = 3 | x;
|
||||
x = 3 ^ x;
|
||||
x = 3 % x;
|
||||
x = 3 & x;
|
||||
|
||||
x = g() + x;
|
||||
x = g() - x;
|
||||
x = g() / x;
|
||||
x = g() * x;
|
||||
x = g() >> x;
|
||||
x = g() << x;
|
||||
x = g() >>> x;
|
||||
x = g() | x;
|
||||
x = g() ^ x;
|
||||
x = g() % x;
|
||||
x = g() & x;
|
||||
}
|
||||
expect: {
|
||||
x = (x -= 2) ^ x;
|
||||
|
||||
x = 3 + x;
|
||||
x = 3 - x;
|
||||
x = 3 / x;
|
||||
x *= 3;
|
||||
x = 3 >> x;
|
||||
x = 3 << x;
|
||||
x = 3 >>> x;
|
||||
x |= 3;
|
||||
x ^= 3;
|
||||
x = 3 % x;
|
||||
x &= 3;
|
||||
|
||||
x = g() + x;
|
||||
x = g() - x;
|
||||
x = g() / x;
|
||||
x = g() * x;
|
||||
x = g() >> x;
|
||||
x = g() << x;
|
||||
x = g() >>> x;
|
||||
x = g() | x;
|
||||
x = g() ^ x;
|
||||
x = g() % x;
|
||||
x = g() & x;
|
||||
}
|
||||
}
|
||||
177
test/compress/block-scope.js
Normal file
177
test/compress/block-scope.js
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
let_statement: {
|
||||
input: {
|
||||
let x = 6;
|
||||
}
|
||||
expect_exact: "let x=6;"
|
||||
}
|
||||
|
||||
do_not_hoist_let: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
};
|
||||
input: {
|
||||
function x() {
|
||||
if (FOO) {
|
||||
let let1;
|
||||
let let2;
|
||||
var var1;
|
||||
var var2;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
var var1, var2;
|
||||
if (FOO) {
|
||||
let let1;
|
||||
let let2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_not_remove_anon_blocks_if_they_have_decls: {
|
||||
input: {
|
||||
function x() {
|
||||
{
|
||||
let x;
|
||||
}
|
||||
{
|
||||
var x;
|
||||
}
|
||||
{
|
||||
const y;
|
||||
class Zee {};
|
||||
}
|
||||
}
|
||||
{
|
||||
let y;
|
||||
}
|
||||
{
|
||||
var y;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x(){
|
||||
{
|
||||
let x
|
||||
}
|
||||
var x;
|
||||
{
|
||||
const y;
|
||||
class Zee {}
|
||||
}
|
||||
}
|
||||
{
|
||||
let y
|
||||
}
|
||||
var y;
|
||||
}
|
||||
}
|
||||
|
||||
remove_unused_in_global_block: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
{
|
||||
let x;
|
||||
const y;
|
||||
class Zee {};
|
||||
var w;
|
||||
}
|
||||
let ex;
|
||||
const why;
|
||||
class Zed {};
|
||||
var wut;
|
||||
console.log(x, y, Zee);
|
||||
}
|
||||
expect: {
|
||||
var w;
|
||||
let ex;
|
||||
const why;
|
||||
class Zed {};
|
||||
var wut;
|
||||
console.log(x, y, Zee);
|
||||
}
|
||||
}
|
||||
|
||||
regression_block_scope_resolves: {
|
||||
mangle = { };
|
||||
options = {
|
||||
dead_code: false
|
||||
};
|
||||
input: {
|
||||
(function () {
|
||||
if(1) {
|
||||
let x;
|
||||
const y;
|
||||
class Zee {};
|
||||
}
|
||||
if(1) {
|
||||
let ex;
|
||||
const why;
|
||||
class Zi {};
|
||||
}
|
||||
console.log(x, y, Zee, ex, why, Zi);
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
(function () {
|
||||
if (1) {
|
||||
let o;
|
||||
const n;
|
||||
class c {};
|
||||
}
|
||||
if (1) {
|
||||
let o;
|
||||
const n;
|
||||
class c {};
|
||||
}
|
||||
console.log(x, y, Zee, ex, why, Zi);
|
||||
}());
|
||||
}
|
||||
}
|
||||
|
||||
switch_block_scope_mangler: {
|
||||
mangle = {}
|
||||
input: {
|
||||
var fn = function(code) {
|
||||
switch (code) {
|
||||
case 1:
|
||||
let apple = code + 1;
|
||||
let dog = code + 4;
|
||||
console.log(apple, dog);
|
||||
break;
|
||||
case 2:
|
||||
let banana = code + 2;
|
||||
console.log(banana);
|
||||
break;
|
||||
default:
|
||||
let cat = code + 3;
|
||||
console.log(cat);
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var fn = function(o) {
|
||||
switch (o) {
|
||||
case 1:
|
||||
let e = o + 1
|
||||
let c = o + 4;
|
||||
console.log(e, c);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
let l = o + 2;
|
||||
console.log(l);
|
||||
break;
|
||||
|
||||
default:
|
||||
let a = o + 3;
|
||||
console.log(a);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
1317
test/compress/collapse_vars.js
Normal file
1317
test/compress/collapse_vars.js
Normal file
File diff suppressed because it is too large
Load Diff
76
test/compress/comparing.js
Normal file
76
test/compress/comparing.js
Normal file
@@ -0,0 +1,76 @@
|
||||
keep_comparisons: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
unsafe_comps: false
|
||||
}
|
||||
input: {
|
||||
var obj1 = {
|
||||
valueOf: function() {triggeredFirst();}
|
||||
}
|
||||
var obj2 = {
|
||||
valueOf: function() {triggeredSecond();}
|
||||
}
|
||||
var result1 = obj1 <= obj2;
|
||||
var result2 = obj1 < obj2;
|
||||
var result3 = obj1 >= obj2;
|
||||
var result4 = obj1 > obj2;
|
||||
}
|
||||
expect: {
|
||||
var obj1 = {
|
||||
valueOf: function() {triggeredFirst();}
|
||||
}
|
||||
var obj2 = {
|
||||
valueOf: function() {triggeredSecond();}
|
||||
}
|
||||
var result1 = obj1 <= obj2;
|
||||
var result2 = obj1 < obj2;
|
||||
var result3 = obj1 >= obj2;
|
||||
var result4 = obj1 > obj2;
|
||||
}
|
||||
}
|
||||
|
||||
keep_comparisons_with_unsafe_comps: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
unsafe_comps: true
|
||||
}
|
||||
input: {
|
||||
var obj1 = {
|
||||
valueOf: function() {triggeredFirst();}
|
||||
}
|
||||
var obj2 = {
|
||||
valueOf: function() {triggeredSecond();}
|
||||
}
|
||||
var result1 = obj1 <= obj2;
|
||||
var result2 = obj1 < obj2;
|
||||
var result3 = obj1 >= obj2;
|
||||
var result4 = obj1 > obj2;
|
||||
}
|
||||
expect: {
|
||||
var obj1 = {
|
||||
valueOf: function() {triggeredFirst();}
|
||||
}
|
||||
var obj2 = {
|
||||
valueOf: function() {triggeredSecond();}
|
||||
}
|
||||
var result1 = obj2 >= obj1;
|
||||
var result2 = obj2 > obj1;
|
||||
var result3 = obj1 >= obj2;
|
||||
var result4 = obj1 > obj2;
|
||||
}
|
||||
}
|
||||
|
||||
dont_change_in_or_instanceof_expressions: {
|
||||
input: {
|
||||
1 in 1;
|
||||
null in null;
|
||||
1 instanceof 1;
|
||||
null instanceof null;
|
||||
}
|
||||
expect: {
|
||||
1 in 1;
|
||||
null in null;
|
||||
1 instanceof 1;
|
||||
null instanceof null;
|
||||
}
|
||||
}
|
||||
166
test/compress/concat-strings.js
Normal file
166
test/compress/concat-strings.js
Normal file
@@ -0,0 +1,166 @@
|
||||
concat_1: {
|
||||
options = {
|
||||
evaluate: true
|
||||
};
|
||||
input: {
|
||||
var a = "foo" + "bar" + x() + "moo" + "foo" + y() + "x" + "y" + "z" + q();
|
||||
var b = "foo" + 1 + x() + 2 + "boo";
|
||||
var c = 1 + x() + 2 + "boo";
|
||||
|
||||
// this CAN'T safely be shortened to 1 + x() + "5boo"
|
||||
var d = 1 + x() + 2 + 3 + "boo";
|
||||
|
||||
var e = 1 + x() + 2 + "X" + 3 + "boo";
|
||||
|
||||
// be careful with concatentation with "\0" with octal-looking strings.
|
||||
var f = "\0" + 360 + "\0" + 8 + "\0";
|
||||
}
|
||||
expect: {
|
||||
var a = "foobar" + x() + "moofoo" + y() + "xyz" + q();
|
||||
var b = "foo1" + x() + "2boo";
|
||||
var c = 1 + x() + 2 + "boo";
|
||||
var d = 1 + x() + 2 + 3 + "boo";
|
||||
var e = 1 + x() + 2 + "X3boo";
|
||||
var f = "\x00360\08\0";
|
||||
}
|
||||
}
|
||||
|
||||
concat_2: {
|
||||
options = {};
|
||||
input: {
|
||||
console.log(
|
||||
1 + (2 + 3),
|
||||
1 + (2 + "3"),
|
||||
1 + ("2" + 3),
|
||||
1 + ("2" + "3"),
|
||||
"1" + (2 + 3),
|
||||
"1" + (2 + "3"),
|
||||
"1" + ("2" + 3),
|
||||
"1" + ("2" + "3")
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
1 + (2 + 3),
|
||||
1 + (2 + "3"),
|
||||
1 + "2" + 3,
|
||||
1 + "2" + "3",
|
||||
"1" + (2 + 3),
|
||||
"1" + 2 + "3",
|
||||
"1" + "2" + 3,
|
||||
"1" + "2" + "3"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
concat_3: {
|
||||
options = {};
|
||||
input: {
|
||||
console.log(
|
||||
1 + 2 + (3 + 4 + 5),
|
||||
1 + 2 + (3 + 4 + "5"),
|
||||
1 + 2 + (3 + "4" + 5),
|
||||
1 + 2 + (3 + "4" + "5"),
|
||||
1 + 2 + ("3" + 4 + 5),
|
||||
1 + 2 + ("3" + 4 + "5"),
|
||||
1 + 2 + ("3" + "4" + 5),
|
||||
1 + 2 + ("3" + "4" + "5")
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
1 + 2 + (3 + 4 + 5),
|
||||
1 + 2 + (3 + 4 + "5"),
|
||||
1 + 2 + (3 + "4") + 5,
|
||||
1 + 2 + (3 + "4") + "5",
|
||||
1 + 2 + "3" + 4 + 5,
|
||||
1 + 2 + "3" + 4 + "5",
|
||||
1 + 2 + "3" + "4" + 5,
|
||||
1 + 2 + "3" + "4" + "5"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
concat_4: {
|
||||
options = {};
|
||||
input: {
|
||||
console.log(
|
||||
1 + "2" + (3 + 4 + 5),
|
||||
1 + "2" + (3 + 4 + "5"),
|
||||
1 + "2" + (3 + "4" + 5),
|
||||
1 + "2" + (3 + "4" + "5"),
|
||||
1 + "2" + ("3" + 4 + 5),
|
||||
1 + "2" + ("3" + 4 + "5"),
|
||||
1 + "2" + ("3" + "4" + 5),
|
||||
1 + "2" + ("3" + "4" + "5")
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
1 + "2" + (3 + 4 + 5),
|
||||
1 + "2" + (3 + 4) + "5",
|
||||
1 + "2" + 3 + "4" + 5,
|
||||
1 + "2" + 3 + "4" + "5",
|
||||
1 + "2" + "3" + 4 + 5,
|
||||
1 + "2" + "3" + 4 + "5",
|
||||
1 + "2" + "3" + "4" + 5,
|
||||
1 + "2" + "3" + "4" + "5"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
concat_5: {
|
||||
options = {};
|
||||
input: {
|
||||
console.log(
|
||||
"1" + 2 + (3 + 4 + 5),
|
||||
"1" + 2 + (3 + 4 + "5"),
|
||||
"1" + 2 + (3 + "4" + 5),
|
||||
"1" + 2 + (3 + "4" + "5"),
|
||||
"1" + 2 + ("3" + 4 + 5),
|
||||
"1" + 2 + ("3" + 4 + "5"),
|
||||
"1" + 2 + ("3" + "4" + 5),
|
||||
"1" + 2 + ("3" + "4" + "5")
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
"1" + 2 + (3 + 4 + 5),
|
||||
"1" + 2 + (3 + 4) + "5",
|
||||
"1" + 2 + 3 + "4" + 5,
|
||||
"1" + 2 + 3 + "4" + "5",
|
||||
"1" + 2 + "3" + 4 + 5,
|
||||
"1" + 2 + "3" + 4 + "5",
|
||||
"1" + 2 + "3" + "4" + 5,
|
||||
"1" + 2 + "3" + "4" + "5"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
concat_6: {
|
||||
options = {};
|
||||
input: {
|
||||
console.log(
|
||||
"1" + "2" + (3 + 4 + 5),
|
||||
"1" + "2" + (3 + 4 + "5"),
|
||||
"1" + "2" + (3 + "4" + 5),
|
||||
"1" + "2" + (3 + "4" + "5"),
|
||||
"1" + "2" + ("3" + 4 + 5),
|
||||
"1" + "2" + ("3" + 4 + "5"),
|
||||
"1" + "2" + ("3" + "4" + 5),
|
||||
"1" + "2" + ("3" + "4" + "5")
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
"1" + "2" + (3 + 4 + 5),
|
||||
"1" + "2" + (3 + 4) + "5",
|
||||
"1" + "2" + 3 + "4" + 5,
|
||||
"1" + "2" + 3 + "4" + "5",
|
||||
"1" + "2" + "3" + 4 + 5,
|
||||
"1" + "2" + "3" + 4 + "5",
|
||||
"1" + "2" + "3" + "4" + 5,
|
||||
"1" + "2" + "3" + "4" + "5"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -50,9 +50,11 @@ ifs_3_should_warn: {
|
||||
conditionals : true,
|
||||
dead_code : true,
|
||||
evaluate : true,
|
||||
booleans : true
|
||||
booleans : true,
|
||||
side_effects : true,
|
||||
};
|
||||
input: {
|
||||
var x, y;
|
||||
if (x && !(x + "1") && y) { // 1
|
||||
var qq;
|
||||
foo();
|
||||
@@ -68,6 +70,7 @@ ifs_3_should_warn: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var x, y;
|
||||
var qq; bar(); // 1
|
||||
var jj; foo(); // 2
|
||||
}
|
||||
@@ -84,7 +87,9 @@ ifs_4: {
|
||||
x(foo)[10].bar.baz = something_else();
|
||||
}
|
||||
expect: {
|
||||
x(foo)[10].bar.baz = (foo && bar) ? something() : something_else();
|
||||
foo && bar
|
||||
? x(foo)[10].bar.baz = something()
|
||||
: x(foo)[10].bar.baz = something_else();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,13 +136,664 @@ ifs_6: {
|
||||
comparisons: true
|
||||
};
|
||||
input: {
|
||||
var x, y;
|
||||
if (!foo && !bar && !baz && !boo) {
|
||||
x = 10;
|
||||
} else {
|
||||
x = 20;
|
||||
}
|
||||
if (y) {
|
||||
x[foo] = 10;
|
||||
} else {
|
||||
x[foo] = 20;
|
||||
}
|
||||
if (foo) {
|
||||
x[bar] = 10;
|
||||
} else {
|
||||
x[bar] = 20;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var x, y;
|
||||
x = foo || bar || baz || boo ? 20 : 10;
|
||||
x[foo] = y ? 10 : 20;
|
||||
foo ? x[bar] = 10 : x[bar] = 20;
|
||||
}
|
||||
}
|
||||
|
||||
cond_1: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
input: {
|
||||
var do_something; // if undeclared it's assumed to have side-effects
|
||||
if (some_condition()) {
|
||||
do_something(x);
|
||||
} else {
|
||||
do_something(y);
|
||||
}
|
||||
if (some_condition()) {
|
||||
side_effects(x);
|
||||
} else {
|
||||
side_effects(y);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var do_something;
|
||||
do_something(some_condition() ? x : y);
|
||||
some_condition() ? side_effects(x) : side_effects(y);
|
||||
}
|
||||
}
|
||||
|
||||
cond_2: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
input: {
|
||||
var x, FooBar;
|
||||
if (some_condition()) {
|
||||
x = new FooBar(1);
|
||||
} else {
|
||||
x = new FooBar(2);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var x, FooBar;
|
||||
x = new FooBar(some_condition() ? 1 : 2);
|
||||
}
|
||||
}
|
||||
|
||||
cond_3: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
input: {
|
||||
var FooBar;
|
||||
if (some_condition()) {
|
||||
new FooBar(1);
|
||||
} else {
|
||||
FooBar(2);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var FooBar;
|
||||
some_condition() ? new FooBar(1) : FooBar(2);
|
||||
}
|
||||
}
|
||||
|
||||
cond_4: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
input: {
|
||||
var do_something;
|
||||
if (some_condition()) {
|
||||
do_something();
|
||||
} else {
|
||||
do_something();
|
||||
}
|
||||
if (some_condition()) {
|
||||
side_effects();
|
||||
} else {
|
||||
side_effects();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var do_something;
|
||||
some_condition(), do_something();
|
||||
some_condition(), side_effects();
|
||||
}
|
||||
}
|
||||
|
||||
cond_5: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
input: {
|
||||
if (some_condition()) {
|
||||
if (some_other_condition()) {
|
||||
do_something();
|
||||
} else {
|
||||
alternate();
|
||||
}
|
||||
} else {
|
||||
alternate();
|
||||
}
|
||||
|
||||
if (some_condition()) {
|
||||
if (some_other_condition()) {
|
||||
do_something();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
some_condition() && some_other_condition() ? do_something() : alternate();
|
||||
some_condition() && some_other_condition() && do_something();
|
||||
}
|
||||
}
|
||||
|
||||
cond_7: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true,
|
||||
side_effects: true,
|
||||
};
|
||||
input: {
|
||||
var x, y, z, a, b;
|
||||
// compress these
|
||||
if (y) {
|
||||
x = 1+1;
|
||||
} else {
|
||||
x = 2;
|
||||
}
|
||||
|
||||
if (y) {
|
||||
x = 1+1;
|
||||
} else if (z) {
|
||||
x = 2;
|
||||
} else {
|
||||
x = 3-1;
|
||||
}
|
||||
|
||||
x = y ? 'foo' : 'fo'+'o';
|
||||
|
||||
x = y ? 'foo' : y ? 'foo' : 'fo'+'o';
|
||||
|
||||
// Compress conditions that have side effects
|
||||
if (condition()) {
|
||||
x = 10+10;
|
||||
} else {
|
||||
x = 20;
|
||||
}
|
||||
|
||||
if (z) {
|
||||
x = 'fuji';
|
||||
} else if (condition()) {
|
||||
x = 'fu'+'ji';
|
||||
} else {
|
||||
x = 'fuji';
|
||||
}
|
||||
|
||||
x = condition() ? 'foobar' : 'foo'+'bar';
|
||||
|
||||
// don't compress these
|
||||
x = y ? a : b;
|
||||
|
||||
x = y ? 'foo' : 'fo';
|
||||
}
|
||||
expect: {
|
||||
var x, y, z, a, b;
|
||||
x = 2;
|
||||
x = 2;
|
||||
x = 'foo';
|
||||
x = 'foo';
|
||||
x = (condition(), 20);
|
||||
x = z ? 'fuji' : (condition(), 'fuji');
|
||||
x = (condition(), 'foobar');
|
||||
x = y ? a : b;
|
||||
x = y ? 'foo' : 'fo';
|
||||
}
|
||||
}
|
||||
|
||||
cond_7_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
var x;
|
||||
// access to global should be assumed to have side effects
|
||||
if (y) {
|
||||
x = 1+1;
|
||||
} else {
|
||||
x = 2;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var x;
|
||||
x = (y, 2);
|
||||
}
|
||||
}
|
||||
|
||||
cond_8: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true,
|
||||
booleans : false
|
||||
};
|
||||
input: {
|
||||
var a;
|
||||
// compress these
|
||||
a = condition ? true : false;
|
||||
a = !condition ? true : false;
|
||||
a = condition() ? true : false;
|
||||
|
||||
a = condition ? !0 : !1;
|
||||
a = !condition ? !null : !2;
|
||||
a = condition() ? !0 : !-3.5;
|
||||
|
||||
if (condition) {
|
||||
a = true;
|
||||
} else {
|
||||
a = false;
|
||||
}
|
||||
|
||||
if (condition) {
|
||||
a = !0;
|
||||
} else {
|
||||
a = !1;
|
||||
}
|
||||
|
||||
a = condition ? false : true;
|
||||
a = !condition ? false : true;
|
||||
a = condition() ? false : true;
|
||||
|
||||
a = condition ? !3 : !0;
|
||||
a = !condition ? !2 : !0;
|
||||
a = condition() ? !1 : !0;
|
||||
|
||||
if (condition) {
|
||||
a = false;
|
||||
} else {
|
||||
a = true;
|
||||
}
|
||||
|
||||
if (condition) {
|
||||
a = !1;
|
||||
} else {
|
||||
a = !0;
|
||||
}
|
||||
|
||||
// don't compress these
|
||||
a = condition ? 1 : false;
|
||||
a = !condition ? true : 0;
|
||||
a = condition ? 1 : 0;
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
a = !!condition;
|
||||
a = !condition;
|
||||
a = !!condition();
|
||||
|
||||
a = !!condition;
|
||||
a = !condition;
|
||||
a = !!condition();
|
||||
|
||||
a = !!condition;
|
||||
a = !!condition;
|
||||
|
||||
a = !condition;
|
||||
a = !!condition;
|
||||
a = !condition();
|
||||
|
||||
a = !condition;
|
||||
a = !!condition;
|
||||
a = !condition();
|
||||
|
||||
a = !condition;
|
||||
a = !condition;
|
||||
|
||||
a = !!condition && 1;
|
||||
a = !condition || 0;
|
||||
a = condition ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
cond_8b: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true,
|
||||
booleans : true
|
||||
};
|
||||
input: {
|
||||
var a;
|
||||
// compress these
|
||||
a = condition ? true : false;
|
||||
a = !condition ? true : false;
|
||||
a = condition() ? true : false;
|
||||
|
||||
a = condition ? !0 : !1;
|
||||
a = !condition ? !null : !2;
|
||||
a = condition() ? !0 : !-3.5;
|
||||
|
||||
if (condition) {
|
||||
a = true;
|
||||
} else {
|
||||
a = false;
|
||||
}
|
||||
|
||||
if (condition) {
|
||||
a = !0;
|
||||
} else {
|
||||
a = !1;
|
||||
}
|
||||
|
||||
a = condition ? false : true;
|
||||
a = !condition ? false : true;
|
||||
a = condition() ? false : true;
|
||||
|
||||
a = condition ? !3 : !0;
|
||||
a = !condition ? !2 : !0;
|
||||
a = condition() ? !1 : !0;
|
||||
|
||||
if (condition) {
|
||||
a = false;
|
||||
} else {
|
||||
a = true;
|
||||
}
|
||||
|
||||
if (condition) {
|
||||
a = !1;
|
||||
} else {
|
||||
a = !0;
|
||||
}
|
||||
|
||||
a = condition ? 1 : false;
|
||||
a = !condition ? true : 0;
|
||||
a = condition ? 1 : 0;
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
a = !!condition;
|
||||
a = !condition;
|
||||
a = !!condition();
|
||||
|
||||
a = !!condition;
|
||||
a = !condition;
|
||||
a = !!condition();
|
||||
|
||||
a = !!condition;
|
||||
a = !!condition;
|
||||
|
||||
a = !condition;
|
||||
a = !!condition;
|
||||
a = !condition();
|
||||
|
||||
a = !condition;
|
||||
a = !!condition;
|
||||
a = !condition();
|
||||
|
||||
a = !condition;
|
||||
a = !condition;
|
||||
|
||||
a = !!condition && 1;
|
||||
a = !condition || 0;
|
||||
a = condition ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
cond_8c: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : false,
|
||||
booleans : false
|
||||
};
|
||||
input: {
|
||||
var a;
|
||||
// compress these
|
||||
a = condition ? true : false;
|
||||
a = !condition ? true : false;
|
||||
a = condition() ? true : false;
|
||||
|
||||
a = condition ? !0 : !1;
|
||||
a = !condition ? !null : !2;
|
||||
a = condition() ? !0 : !-3.5;
|
||||
|
||||
if (condition) {
|
||||
a = true;
|
||||
} else {
|
||||
a = false;
|
||||
}
|
||||
|
||||
if (condition) {
|
||||
a = !0;
|
||||
} else {
|
||||
a = !1;
|
||||
}
|
||||
|
||||
a = condition ? false : true;
|
||||
a = !condition ? false : true;
|
||||
a = condition() ? false : true;
|
||||
|
||||
a = condition ? !3 : !0;
|
||||
a = !condition ? !2 : !0;
|
||||
a = condition() ? !1 : !0;
|
||||
|
||||
if (condition) {
|
||||
a = false;
|
||||
} else {
|
||||
a = true;
|
||||
}
|
||||
|
||||
if (condition) {
|
||||
a = !1;
|
||||
} else {
|
||||
a = !0;
|
||||
}
|
||||
|
||||
a = condition ? 1 : false;
|
||||
a = !condition ? true : 0;
|
||||
a = condition ? 1 : 0;
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
a = !!condition;
|
||||
a = !condition;
|
||||
a = !!condition();
|
||||
|
||||
a = !!condition;
|
||||
a = !condition;
|
||||
a = !!condition() || !-3.5;
|
||||
|
||||
a = !!condition;
|
||||
a = !!condition;
|
||||
|
||||
a = !condition;
|
||||
a = !!condition;
|
||||
a = !condition();
|
||||
|
||||
a = !condition;
|
||||
a = !!condition;
|
||||
a = !condition();
|
||||
|
||||
a = !condition;
|
||||
a = !condition;
|
||||
|
||||
a = !!condition && 1;
|
||||
a = !condition || 0;
|
||||
a = condition ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
ternary_boolean_consequent: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
}
|
||||
input: {
|
||||
function f1() { return a == b ? true : x; }
|
||||
function f2() { return a == b ? false : x; }
|
||||
function f3() { return a < b ? !0 : x; }
|
||||
function f4() { return a < b ? !1 : x; }
|
||||
function f5() { return c ? !0 : x; }
|
||||
function f6() { return c ? false : x; }
|
||||
function f7() { return !c ? true : x; }
|
||||
function f8() { return !c ? !1 : x; }
|
||||
}
|
||||
expect: {
|
||||
function f1() { return a == b || x; }
|
||||
function f2() { return a != b && x; }
|
||||
function f3() { return a < b || x; }
|
||||
function f4() { return !(a < b) && x; }
|
||||
function f5() { return !!c || x; }
|
||||
function f6() { return !c && x; }
|
||||
function f7() { return !c || x; }
|
||||
function f8() { return !!c && x; }
|
||||
}
|
||||
}
|
||||
|
||||
ternary_boolean_alternative: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
}
|
||||
input: {
|
||||
function f1() { return a == b ? x : true; }
|
||||
function f2() { return a == b ? x : false; }
|
||||
function f3() { return a < b ? x : !0; }
|
||||
function f4() { return a < b ? x : !1; }
|
||||
function f5() { return c ? x : true; }
|
||||
function f6() { return c ? x : !1; }
|
||||
function f7() { return !c ? x : !0; }
|
||||
function f8() { return !c ? x : false; }
|
||||
}
|
||||
expect: {
|
||||
function f1() { return a != b || x; }
|
||||
function f2() { return a == b && x; }
|
||||
function f3() { return !(a < b) || x; }
|
||||
function f4() { return a < b && x; }
|
||||
function f5() { return !c || x; }
|
||||
function f6() { return !!c && x; }
|
||||
function f7() { return !!c || x; }
|
||||
function f8() { return !c && x; }
|
||||
}
|
||||
}
|
||||
|
||||
trivial_boolean_ternary_expressions : {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true,
|
||||
booleans : true
|
||||
};
|
||||
input: {
|
||||
f('foo' in m ? true : false);
|
||||
f('foo' in m ? false : true);
|
||||
|
||||
f(g ? true : false);
|
||||
f(foo() ? true : false);
|
||||
f("bar" ? true : false);
|
||||
f(5 ? true : false);
|
||||
f(5.7 ? true : false);
|
||||
f(x - y ? true : false);
|
||||
|
||||
f(x == y ? true : false);
|
||||
f(x === y ? !0 : !1);
|
||||
f(x < y ? !0 : false);
|
||||
f(x <= y ? true : false);
|
||||
f(x > y ? true : !1);
|
||||
f(x >= y ? !0 : !1);
|
||||
|
||||
f(g ? false : true);
|
||||
f(foo() ? false : true);
|
||||
f("bar" ? false : true);
|
||||
f(5 ? false : true);
|
||||
f(5.7 ? false : true);
|
||||
f(x - y ? false : true);
|
||||
|
||||
f(x == y ? !1 : !0);
|
||||
f(x === y ? false : true);
|
||||
|
||||
f(x < y ? false : true);
|
||||
f(x <= y ? false : !0);
|
||||
f(x > y ? !1 : true);
|
||||
f(x >= y ? !1 : !0);
|
||||
}
|
||||
expect: {
|
||||
f('foo' in m);
|
||||
f(!('foo' in m));
|
||||
|
||||
f(!!g);
|
||||
f(!!foo());
|
||||
f(!0);
|
||||
f(!0);
|
||||
f(!0);
|
||||
f(!!(x - y));
|
||||
|
||||
f(x == y);
|
||||
f(x === y);
|
||||
f(x < y);
|
||||
f(x <= y);
|
||||
f(x > y);
|
||||
f(x >= y);
|
||||
|
||||
f(!g);
|
||||
f(!foo());
|
||||
f(!1);
|
||||
f(!1);
|
||||
f(!1);
|
||||
f(!(x - y));
|
||||
|
||||
f(x != y);
|
||||
f(x !== y);
|
||||
|
||||
f(!(x < y));
|
||||
f(!(x <= y));
|
||||
f(!(x > y));
|
||||
f(!(x >= y));
|
||||
}
|
||||
}
|
||||
|
||||
issue_1154: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
side_effects: true,
|
||||
};
|
||||
input: {
|
||||
function f1(x) { return x ? -1 : -1; }
|
||||
function f2(x) { return x ? +2 : +2; }
|
||||
function f3(x) { return x ? ~3 : ~3; }
|
||||
function f4(x) { return x ? !4 : !4; }
|
||||
function f5(x) { return x ? void 5 : void 5; }
|
||||
function f6(x) { return x ? typeof 6 : typeof 6; }
|
||||
|
||||
function g1() { return g() ? -1 : -1; }
|
||||
function g2() { return g() ? +2 : +2; }
|
||||
function g3() { return g() ? ~3 : ~3; }
|
||||
function g4() { return g() ? !4 : !4; }
|
||||
function g5() { return g() ? void 5 : void 5; }
|
||||
function g6() { return g() ? typeof 6 : typeof 6; }
|
||||
}
|
||||
expect: {
|
||||
function f1(x) { return -1; }
|
||||
function f2(x) { return 2; }
|
||||
function f3(x) { return -4; }
|
||||
function f4(x) { return !1; }
|
||||
function f5(x) { return; }
|
||||
function f6(x) { return "number"; }
|
||||
|
||||
function g1() { return g(), -1; }
|
||||
function g2() { return g(), 2; }
|
||||
function g3() { return g(), -4; }
|
||||
function g4() { return g(), !1; }
|
||||
function g5() { return void g(); }
|
||||
function g6() { return g(), "number"; }
|
||||
}
|
||||
}
|
||||
|
||||
no_evaluate: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : false,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f(b) {
|
||||
a = b ? !0 : !0;
|
||||
a = b ? ~1 : ~1;
|
||||
a = b ? -2 : -2;
|
||||
a = b ? +3 : +3;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(b) {
|
||||
a = !0;
|
||||
a = ~1;
|
||||
a = -2;
|
||||
a = +3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
165
test/compress/const.js
Normal file
165
test/compress/const.js
Normal file
@@ -0,0 +1,165 @@
|
||||
issue_1191: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function foo(rot) {
|
||||
const rotTol = 5;
|
||||
if (rot < -rotTol || rot > rotTol)
|
||||
bar();
|
||||
baz();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(rot) {
|
||||
(rot < -5 || rot > 5) && bar();
|
||||
baz();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1194: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function f1() {const a = "X"; return a + a;}
|
||||
function f2() {const aa = "X"; return aa + aa;}
|
||||
function f3() {const aaa = "X"; return aaa + aaa;}
|
||||
}
|
||||
expect: {
|
||||
function f1(){return"XX"}
|
||||
function f2(){return"XX"}
|
||||
function f3(){return"XX"}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1396: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function foo(a) {
|
||||
const VALUE = 1;
|
||||
console.log(2 | VALUE);
|
||||
console.log(VALUE + 1);
|
||||
console.log(VALUE);
|
||||
console.log(a & VALUE);
|
||||
}
|
||||
function bar() {
|
||||
const s = "01234567890123456789";
|
||||
console.log(s + s + s + s + s);
|
||||
|
||||
const CONSTANT = "abc";
|
||||
console.log(CONSTANT + CONSTANT + CONSTANT + CONSTANT + CONSTANT);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(a) {
|
||||
console.log(3);
|
||||
console.log(2);
|
||||
console.log(1);
|
||||
console.log(1 & a);
|
||||
}
|
||||
function bar() {
|
||||
const s = "01234567890123456789";
|
||||
console.log(s + s + s + s + s);
|
||||
|
||||
console.log("abcabcabcabcabc");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_regexp_literal: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
}
|
||||
input: {
|
||||
function f(){ var a = /b/; }
|
||||
}
|
||||
expect: {
|
||||
function f(){}
|
||||
}
|
||||
}
|
||||
|
||||
regexp_literal_not_const: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
(function(){
|
||||
var result;
|
||||
const s = 'acdabcdeabbb';
|
||||
const REGEXP_LITERAL = /ab*/g;
|
||||
while (result = REGEXP_LITERAL.exec(s)) {
|
||||
console.log(result[0]);
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var result;
|
||||
const REGEXP_LITERAL = /ab*/g;
|
||||
while (result = REGEXP_LITERAL.exec("acdabcdeabbb")) console.log(result[0]);
|
||||
})();
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,8 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true
|
||||
evaluate : true,
|
||||
side_effects : true,
|
||||
};
|
||||
input: {
|
||||
while (!((foo && bar) || (x + "0"))) {
|
||||
@@ -72,7 +73,7 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
var foo;
|
||||
function bar() {}
|
||||
}
|
||||
for (var x = 10; x && (y || x) && (!typeof x); ++x) {
|
||||
for (var x = 10, y; x && (y || x) && (!typeof x); ++x) {
|
||||
asdf();
|
||||
foo();
|
||||
var moo;
|
||||
@@ -83,7 +84,148 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
function bar() {}
|
||||
// nothing for the while
|
||||
// as for the for, it should keep:
|
||||
var x = 10;
|
||||
var x = 10, y;
|
||||
var moo;
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_block_decls_die: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
booleans : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
if (0) {
|
||||
let foo = 6;
|
||||
const bar = 12;
|
||||
class Baz {};
|
||||
var qux;
|
||||
}
|
||||
console.log(foo, bar, Baz);
|
||||
}
|
||||
expect: {
|
||||
var qux;
|
||||
console.log(foo, bar, Baz);
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_const_declaration: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
const CONST_FOO = false;
|
||||
if (CONST_FOO) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
const CONST_FOO = !1;
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_const_annotation: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
/** @const */ var CONST_FOO_ANN = false;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
var CONST_FOO_ANN = !1;
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_const_annotation_regex: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
// @constraint this shouldn't be a constant
|
||||
var CONST_FOO_ANN = false;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("reachable");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
var CONST_FOO_ANN = !1;
|
||||
CONST_FOO_ANN && console.log('reachable');
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_const_annotation_complex_scope: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
};
|
||||
input: {
|
||||
var unused_var;
|
||||
/** @const */ var test = 'test';
|
||||
// @const
|
||||
var CONST_FOO_ANN = false;
|
||||
var unused_var_2;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
if (test === 'test') {
|
||||
var beef = 'good';
|
||||
/** @const */ var meat = 'beef';
|
||||
var pork = 'bad';
|
||||
if (meat === 'pork') {
|
||||
console.log('also unreachable');
|
||||
} else if (pork === 'good') {
|
||||
console.log('reached, not const');
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused_var;
|
||||
var test = 'test';
|
||||
var CONST_FOO_ANN = !1;
|
||||
var unused_var_2;
|
||||
var moo;
|
||||
function bar() {}
|
||||
var beef = 'good';
|
||||
var meat = 'beef';
|
||||
var pork = 'bad';
|
||||
}
|
||||
}
|
||||
|
||||
253
test/compress/destructuring.js
Normal file
253
test/compress/destructuring.js
Normal file
@@ -0,0 +1,253 @@
|
||||
destructuring_arrays: {
|
||||
input: {
|
||||
{const [aa, bb] = cc;}
|
||||
{const [aa, [bb, cc]] = dd;}
|
||||
{let [aa, bb] = cc;}
|
||||
{let [aa, [bb, cc]] = dd;}
|
||||
var [aa, bb] = cc;
|
||||
var [aa, [bb, cc]] = dd;
|
||||
var [,[,,,,,],,,zz,] = xx; // Trailing comma
|
||||
var [,,zzz,,] = xxx; // Trailing comma after hole
|
||||
}
|
||||
expect: {
|
||||
{const [aa, bb] = cc;}
|
||||
{const [aa, [bb, cc]] = dd;}
|
||||
{let [aa, bb] = cc;}
|
||||
{let [aa, [bb, cc]] = dd;}
|
||||
var [aa, bb] = cc;
|
||||
var [aa, [bb, cc]] = dd;
|
||||
var [,[,,,,,],,,zz] = xx;
|
||||
var [,,zzz,,] = xxx;
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_arrays_holes: {
|
||||
input: {
|
||||
var [,,,,] = a;
|
||||
var [,,b,] = c;
|
||||
var [d,,] = e;
|
||||
}
|
||||
expect_exact: "var[,,,,]=a;var[,,b]=c;var[d,,]=e;"
|
||||
}
|
||||
|
||||
destructuring_objects: {
|
||||
input: {
|
||||
{const {aa, bb} = {aa:1, bb:2};}
|
||||
{const {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
{let {aa, bb} = {aa:1, bb:2};}
|
||||
{let {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
var {aa, bb} = {aa:1, bb:2};
|
||||
var {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};
|
||||
}
|
||||
expect: {
|
||||
{const {aa, bb} = {aa:1, bb:2};}
|
||||
{const {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
{let {aa, bb} = {aa:1, bb:2};}
|
||||
{let {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
var {aa, bb} = {aa:1, bb:2};
|
||||
var {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_objects_trailing_elision: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
var {cc,} = foo;
|
||||
}
|
||||
expect_exact: "var{cc}=foo;"
|
||||
}
|
||||
|
||||
nested_destructuring_objects: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
const [{a},b] = c;
|
||||
let [{a},b] = c;
|
||||
var [{a},b] = c;
|
||||
}
|
||||
expect_exact: 'const[{a},b]=c;let[{a},b]=c;var[{a},b]=c;';
|
||||
}
|
||||
|
||||
destructuring_constdef_in_loops: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
for (const [x,y] in pairs);
|
||||
for (const [a] = 0;;);
|
||||
for (const {c} of cees);
|
||||
}
|
||||
expect_exact: "for(const[x,y]in pairs);for(const[a]=0;;);for(const{c}of cees);"
|
||||
}
|
||||
|
||||
destructuring_letdef_in_loops: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
for (let [x,y] in pairs);
|
||||
for (let [a] = 0;;);
|
||||
for (let {c} of cees);
|
||||
}
|
||||
expect_exact: "for(let[x,y]in pairs);for(let[a]=0;;);for(let{c}of cees);"
|
||||
}
|
||||
|
||||
destructuring_vardef_in_loops: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
for (var [x,y] in pairs);
|
||||
for (var [a] = 0;;);
|
||||
for (var {c} of cees);
|
||||
}
|
||||
expect_exact: "for(var[x,y]in pairs);for(var[a]=0;;);for(var{c}of cees);"
|
||||
}
|
||||
|
||||
destructuring_expressions: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
({a, b});
|
||||
[{a}];
|
||||
f({x});
|
||||
}
|
||||
expect_exact: "({a,b});[{a}];f({x});"
|
||||
}
|
||||
|
||||
destructuring_remove_unused_1: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function a() {
|
||||
var unused = "foo";
|
||||
var a = [1];
|
||||
var [b] = a;
|
||||
f(b);
|
||||
}
|
||||
function b() {
|
||||
var unused = "foo";
|
||||
var a = {b: 1};
|
||||
var {b} = a;
|
||||
f(b);
|
||||
}
|
||||
function c() {
|
||||
var unused = "foo";
|
||||
var a = [[1]];
|
||||
var [[b]] = a;
|
||||
f(b);
|
||||
}
|
||||
function d() {
|
||||
var unused = "foo";
|
||||
var a = {b: {b:1}};
|
||||
var {b:{b}} = a;
|
||||
f(b);
|
||||
}
|
||||
function e() {
|
||||
var unused = "foo";
|
||||
var a = [1, 2, 3, 4, 5];
|
||||
var [b, ...c] = a;
|
||||
f(b, c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
var a = [1];
|
||||
var [b] = a;
|
||||
f(b);
|
||||
}
|
||||
function b() {
|
||||
var a = {b: 1};
|
||||
var {b} = a;
|
||||
f(b);
|
||||
}
|
||||
function c() {
|
||||
var a = [[1]];
|
||||
var [[b]] = a;
|
||||
f(b);
|
||||
}
|
||||
function d() {
|
||||
var a = {b: {b:1}};
|
||||
var {b:{b}} = a;
|
||||
f(b);
|
||||
}
|
||||
function e() {
|
||||
var a = [1, 2, 3, 4, 5];
|
||||
var [b, ...c] = a;
|
||||
f(b, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_remove_unused_2: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function a() {
|
||||
var unused = "foo";
|
||||
var a = [,,1];
|
||||
var [b] = a;
|
||||
f(b);
|
||||
}
|
||||
function b() {
|
||||
var unused = "foo";
|
||||
var a = [{a: [1]}];
|
||||
var [{b: a}] = a;
|
||||
f(b);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
var a = [,,1];
|
||||
var [b] = a;
|
||||
f(b);
|
||||
}
|
||||
function b() {
|
||||
var a = [{a: [1]}];
|
||||
var [{b: a}] = a;
|
||||
f(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object_destructuring_may_need_parentheses: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
({a, b} = {a: 1, b: 2});
|
||||
}
|
||||
expect_exact: "({a,b}={a:1,b:2});"
|
||||
}
|
||||
|
||||
destructuring_with_undefined_as_default_assignment: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
[foo = undefined] = bar;
|
||||
[foo = void 0] = bar;
|
||||
}
|
||||
expect: {
|
||||
[foo] = bar;
|
||||
[foo] = bar;
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_dont_evaluate_with_undefined_as_default_assignment: {
|
||||
options = {
|
||||
evaluate: false
|
||||
}
|
||||
input: {
|
||||
[foo = undefined] = bar;
|
||||
}
|
||||
expect: {
|
||||
[foo = void 0] = bar;
|
||||
}
|
||||
}
|
||||
10
test/compress/directives.js
Normal file
10
test/compress/directives.js
Normal file
@@ -0,0 +1,10 @@
|
||||
class_directives_compression: {
|
||||
input: {
|
||||
class foo {
|
||||
foo() {
|
||||
"use strict";
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: "class foo{foo(){}}"
|
||||
}
|
||||
24
test/compress/drop-console.js
Normal file
24
test/compress/drop-console.js
Normal file
@@ -0,0 +1,24 @@
|
||||
drop_console_1: {
|
||||
options = {};
|
||||
input: {
|
||||
console.log('foo');
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
expect: {
|
||||
console.log('foo');
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
drop_console_2: {
|
||||
options = { drop_console: true };
|
||||
input: {
|
||||
console.log('foo');
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
expect: {
|
||||
// with regular compression these will be stripped out as well
|
||||
void 0;
|
||||
void 0;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
unused_funarg_1: {
|
||||
options = { unused: true };
|
||||
options = { unused: true, keep_fargs: false };
|
||||
input: {
|
||||
function f(a, b, c, d, e) {
|
||||
return a + b;
|
||||
@@ -13,7 +13,7 @@ unused_funarg_1: {
|
||||
}
|
||||
|
||||
unused_funarg_2: {
|
||||
options = { unused: true };
|
||||
options = { unused: true, keep_fargs: false };
|
||||
input: {
|
||||
function f(a, b, c, d, e) {
|
||||
return a + c;
|
||||
@@ -95,3 +95,668 @@ unused_circular_references_3: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_keep_setter_arg: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
var x = {
|
||||
_foo: null,
|
||||
set foo(val) {
|
||||
},
|
||||
get foo() {
|
||||
return this._foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var x = {
|
||||
_foo: null,
|
||||
set foo(val) {
|
||||
},
|
||||
get foo() {
|
||||
return this._foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_var_in_catch: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {
|
||||
var x = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
used_var_in_catch: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {
|
||||
var x = 10;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {
|
||||
var x = 10;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_block_decls_in_catch: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {
|
||||
let x = 10;
|
||||
const y = 10;
|
||||
class Zee {};
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
used_block_decls_in_catch: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {
|
||||
let x = 10;
|
||||
const y = 10;
|
||||
class Zee {};
|
||||
}
|
||||
console.log(x, y, Zee);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {}
|
||||
console.log(x, y, Zee);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_block_decls: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function foo() {
|
||||
{
|
||||
const x;
|
||||
}
|
||||
{
|
||||
let y;
|
||||
}
|
||||
console.log(x, y);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
console.log(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_keep_harmony_destructuring: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function foo() {
|
||||
var {x, y} = foo;
|
||||
var a = foo;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
var {x, y} = foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keep_fnames: {
|
||||
options = { unused: true, keep_fnames: true, unsafe: true };
|
||||
input: {
|
||||
function foo() {
|
||||
return function bar(baz) {};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
return function bar(baz) {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drop_assign: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function f1() {
|
||||
var a;
|
||||
a = 1;
|
||||
}
|
||||
function f2() {
|
||||
var a = 1;
|
||||
a = 2;
|
||||
}
|
||||
function f3(a) {
|
||||
a = 1;
|
||||
}
|
||||
function f4() {
|
||||
var a;
|
||||
return a = 1;
|
||||
}
|
||||
function f5() {
|
||||
var a;
|
||||
return function() {
|
||||
a = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1() {
|
||||
1;
|
||||
}
|
||||
function f2() {
|
||||
2;
|
||||
}
|
||||
function f3(a) {
|
||||
1;
|
||||
}
|
||||
function f4() {
|
||||
return 1;
|
||||
}
|
||||
function f5() {
|
||||
var a;
|
||||
return function() {
|
||||
a = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keep_assign: {
|
||||
options = { unused: "keep_assign" };
|
||||
input: {
|
||||
function f1() {
|
||||
var a;
|
||||
a = 1;
|
||||
}
|
||||
function f2() {
|
||||
var a = 1;
|
||||
a = 2;
|
||||
}
|
||||
function f3(a) {
|
||||
a = 1;
|
||||
}
|
||||
function f4() {
|
||||
var a;
|
||||
return a = 1;
|
||||
}
|
||||
function f5() {
|
||||
var a;
|
||||
return function() {
|
||||
a = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1() {
|
||||
var a;
|
||||
a = 1;
|
||||
}
|
||||
function f2() {
|
||||
var a = 1;
|
||||
a = 2;
|
||||
}
|
||||
function f3(a) {
|
||||
a = 1;
|
||||
}
|
||||
function f4() {
|
||||
var a;
|
||||
return a = 1;
|
||||
}
|
||||
function f5() {
|
||||
var a;
|
||||
return function() {
|
||||
a = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_funcs: {
|
||||
options = { toplevel: "funcs", unused: true };
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
var a, b = 1, c = g;
|
||||
a = 2;
|
||||
function g() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_vars: {
|
||||
options = { toplevel: "vars", unused: true };
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
var c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_vars_fargs: {
|
||||
options = { keep_fargs: false, toplevel: "vars", unused: true };
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
var c = g;
|
||||
function f() {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_all: {
|
||||
options = { toplevel: true, unused: true };
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
2;
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_retain: {
|
||||
options = { top_retain: "f,a,o", unused: true };
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
var a, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_retain_array: {
|
||||
options = { top_retain: [ "f", "a", "o" ], unused: true };
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
var a, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_retain_regex: {
|
||||
options = { top_retain: /^[fao]$/, unused: true };
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
var a, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_all_retain: {
|
||||
options = { toplevel: true, top_retain: "f,a,o", unused: true };
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
var a, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_funcs_retain: {
|
||||
options = { toplevel: "funcs", top_retain: "f,a,o", unused: true };
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_vars_retain: {
|
||||
options = { toplevel: "vars", top_retain: "f,a,o", unused: true };
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
var a, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_toplevel_keep_assign: {
|
||||
options = { toplevel: true, unused: "keep_assign" };
|
||||
input: {
|
||||
var a, b = 1, c = g;
|
||||
function f(d) {
|
||||
return function() {
|
||||
c = 2;
|
||||
}
|
||||
}
|
||||
a = 2;
|
||||
function g() {}
|
||||
function h() {}
|
||||
console.log(b = 3);
|
||||
}
|
||||
expect: {
|
||||
var a, b = 1;
|
||||
a = 2;
|
||||
console.log(b = 3);
|
||||
}
|
||||
}
|
||||
|
||||
drop_fargs: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var b = a;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {}
|
||||
}
|
||||
}
|
||||
|
||||
drop_fnames: {
|
||||
options = {
|
||||
keep_fnames: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return function g() {
|
||||
var a = g;
|
||||
};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return function() {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
global_var: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
function foo(b) {
|
||||
a;
|
||||
b;
|
||||
c;
|
||||
typeof c === "undefined";
|
||||
c + b + a;
|
||||
b && b.ar();
|
||||
return b;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
function foo(b) {
|
||||
c;
|
||||
c;
|
||||
b && b.ar();
|
||||
return b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iife: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a;
|
||||
~function() {}(b);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
~function() {}(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drop_value: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(1, [2, foo()], 3, {a:1, b:bar()});
|
||||
}
|
||||
expect: {
|
||||
foo(), bar();
|
||||
}
|
||||
}
|
||||
|
||||
const_assign: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
const b = 2;
|
||||
return 1 + b;
|
||||
}
|
||||
|
||||
function g() {
|
||||
const b = 2;
|
||||
b = 3;
|
||||
return 1 + b;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
function g() {
|
||||
const b = 2;
|
||||
b = 3;
|
||||
return 1 + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
752
test/compress/evaluate.js
Normal file
752
test/compress/evaluate.js
Normal file
@@ -0,0 +1,752 @@
|
||||
and: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
// compress these
|
||||
|
||||
a = true && condition;
|
||||
a = 1 && console.log("a");
|
||||
a = 2 * 3 && 2 * condition;
|
||||
a = 5 == 5 && condition + 3;
|
||||
a = "string" && 4 - condition;
|
||||
a = 5 + "" && condition / 5;
|
||||
a = -4.5 && 6 << condition;
|
||||
a = 6 && 7;
|
||||
|
||||
a = false && condition;
|
||||
a = NaN && console.log("b");
|
||||
a = 0 && console.log("c");
|
||||
a = undefined && 2 * condition;
|
||||
a = null && condition + 3;
|
||||
a = 2 * 3 - 6 && 4 - condition;
|
||||
a = 10 == 7 && condition / 5;
|
||||
a = !"string" && 6 % condition;
|
||||
a = 0 && 7;
|
||||
|
||||
// don't compress these
|
||||
|
||||
a = condition && true;
|
||||
a = console.log("a") && 2;
|
||||
a = 4 - condition && "string";
|
||||
a = 6 << condition && -4.5;
|
||||
|
||||
a = condition && false;
|
||||
a = console.log("b") && NaN;
|
||||
a = console.log("c") && 0;
|
||||
a = 2 * condition && undefined;
|
||||
a = condition + 3 && null;
|
||||
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
|
||||
a = condition;
|
||||
a = console.log("a");
|
||||
a = 2 * condition;
|
||||
a = condition + 3;
|
||||
a = 4 - condition;
|
||||
a = condition / 5;
|
||||
a = 6 << condition;
|
||||
a = 7;
|
||||
|
||||
a = false;
|
||||
a = NaN;
|
||||
a = 0;
|
||||
a = void 0;
|
||||
a = null;
|
||||
a = 0;
|
||||
a = false;
|
||||
a = false;
|
||||
a = 0;
|
||||
|
||||
a = condition && true;
|
||||
a = console.log("a") && 2;
|
||||
a = 4 - condition && "string";
|
||||
a = 6 << condition && -4.5;
|
||||
|
||||
a = condition && false;
|
||||
a = console.log("b") && NaN;
|
||||
a = console.log("c") && 0;
|
||||
a = 2 * condition && void 0;
|
||||
a = condition + 3 && null;
|
||||
}
|
||||
}
|
||||
|
||||
or: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
// compress these
|
||||
|
||||
a = true || condition;
|
||||
a = 1 || console.log("a");
|
||||
a = 2 * 3 || 2 * condition;
|
||||
a = 5 == 5 || condition + 3;
|
||||
a = "string" || 4 - condition;
|
||||
a = 5 + "" || condition / 5;
|
||||
a = -4.5 || 6 << condition;
|
||||
a = 6 || 7;
|
||||
|
||||
a = false || condition;
|
||||
a = 0 || console.log("b");
|
||||
a = NaN || console.log("c");
|
||||
a = undefined || 2 * condition;
|
||||
a = null || condition + 3;
|
||||
a = 2 * 3 - 6 || 4 - condition;
|
||||
a = 10 == 7 || condition / 5;
|
||||
a = !"string" || 6 % condition;
|
||||
a = null || 7;
|
||||
|
||||
a = console.log(undefined && condition || null);
|
||||
a = console.log(undefined || condition && null);
|
||||
|
||||
// don't compress these
|
||||
|
||||
a = condition || true;
|
||||
a = console.log("a") || 2;
|
||||
a = 4 - condition || "string";
|
||||
a = 6 << condition || -4.5;
|
||||
|
||||
a = condition || false;
|
||||
a = console.log("b") || NaN;
|
||||
a = console.log("c") || 0;
|
||||
a = 2 * condition || undefined;
|
||||
a = condition + 3 || null;
|
||||
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
|
||||
a = true;
|
||||
a = 1;
|
||||
a = 6;
|
||||
a = true;
|
||||
a = "string";
|
||||
a = "5";
|
||||
a = -4.5;
|
||||
a = 6;
|
||||
|
||||
a = condition;
|
||||
a = console.log("b");
|
||||
a = console.log("c");
|
||||
a = 2 * condition;
|
||||
a = condition + 3;
|
||||
a = 4 - condition;
|
||||
a = condition / 5;
|
||||
a = 6 % condition;
|
||||
a = 7;
|
||||
|
||||
a = console.log(null);
|
||||
a = console.log(condition && null);
|
||||
|
||||
a = condition || true;
|
||||
a = console.log("a") || 2;
|
||||
a = 4 - condition || "string";
|
||||
a = 6 << condition || -4.5;
|
||||
|
||||
a = condition || false;
|
||||
a = console.log("b") || NaN;
|
||||
a = console.log("c") || 0;
|
||||
a = 2 * condition || void 0;
|
||||
a = condition + 3 || null;
|
||||
}
|
||||
}
|
||||
|
||||
unary_prefix: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
a = !0 && b;
|
||||
a = !0 || b;
|
||||
a = ~1 && b;
|
||||
a = ~1 || b;
|
||||
a = -2 && b;
|
||||
a = -2 || b;
|
||||
a = +3 && b;
|
||||
a = +3 || b;
|
||||
}
|
||||
expect: {
|
||||
a = b;
|
||||
a = !0;
|
||||
a = b;
|
||||
a = -2;
|
||||
a = b;
|
||||
a = -2;
|
||||
a = b;
|
||||
a = 3;
|
||||
}
|
||||
}
|
||||
|
||||
negative_zero: {
|
||||
options = { evaluate: true }
|
||||
input: {
|
||||
console.log(
|
||||
-"",
|
||||
- -"",
|
||||
1 / (-0),
|
||||
1 / (-"")
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
-0,
|
||||
0,
|
||||
1 / (-0),
|
||||
1 / (-0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
positive_zero: {
|
||||
options = { evaluate: true }
|
||||
input: {
|
||||
console.log(
|
||||
+"",
|
||||
+ -"",
|
||||
1 / (+0),
|
||||
1 / (+"")
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
0,
|
||||
-0,
|
||||
1 / (0),
|
||||
1 / (0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pow: {
|
||||
options = { evaluate: true }
|
||||
input: {
|
||||
var a = 5 ** 3;
|
||||
}
|
||||
expect: {
|
||||
var a = 125;
|
||||
}
|
||||
}
|
||||
|
||||
pow_sequence: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a = 2 ** 3 ** 2;
|
||||
}
|
||||
expect: {
|
||||
var a = 512;
|
||||
}
|
||||
}
|
||||
|
||||
pow_mixed: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a = 5 + 2 ** 3 + 5;
|
||||
var b = 5 * 3 ** 2;
|
||||
var c = 5 ** 3 * 2;
|
||||
var d = 5 ** +3;
|
||||
}
|
||||
expect: {
|
||||
var a = 18;
|
||||
var b = 45;
|
||||
var c = 250;
|
||||
var d = 125;
|
||||
}
|
||||
}
|
||||
|
||||
pow_with_right_side_evaluating_to_unary: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a = (4 - 7) ** foo;
|
||||
var b = ++bar ** 3;
|
||||
var c = --baz ** 2;
|
||||
}
|
||||
expect_exact: "var a=(-3)**foo;var b=++bar**3;var c=--baz**2;"
|
||||
}
|
||||
|
||||
pow_with_number_constants: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a = 5 ** NaN;
|
||||
/* NaN exponent results to NaN */
|
||||
var b = 42 ** +0;
|
||||
/* +0 exponent results to NaN */
|
||||
var c = 42 ** -0;
|
||||
/* -0 exponent results to NaN */
|
||||
var d = NaN ** 1;
|
||||
/* NaN with non-zero exponent is NaN */
|
||||
var e = 2 ** Infinity;
|
||||
/* abs(base) > 1 with Infinity as exponent is Infinity */
|
||||
var f = 2 ** -Infinity;
|
||||
/* abs(base) > 1 with -Infinity as exponent is +0 */
|
||||
var g = (-7) ** (0.5);
|
||||
var h = 2324334 ** 34343443;
|
||||
var i = (-2324334) ** 34343443;
|
||||
var j = 2 ** (-3);
|
||||
var k = 2.0 ** -3;
|
||||
var l = 2.0 ** (5 - 7);
|
||||
var m = 3 ** -10; // Result will be 0.000016935087808430286, which is too long
|
||||
}
|
||||
expect: {
|
||||
var a = NaN;
|
||||
var b = 1;
|
||||
var c = 1;
|
||||
var d = NaN;
|
||||
var e = Infinity;
|
||||
var f = 0;
|
||||
var g = NaN;
|
||||
var h = Infinity;
|
||||
var i = -Infinity;
|
||||
var j = .125;
|
||||
var k = .125;
|
||||
var l = .25;
|
||||
var m = 3 ** -10;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_constant: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
true.a,
|
||||
false.a,
|
||||
null.a,
|
||||
undefined.a
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
true.a,
|
||||
false.a,
|
||||
null.a,
|
||||
(void 0).a
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_object: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
({a:1}) + 1,
|
||||
({a:1}).a + 1,
|
||||
({a:1}).b + 1,
|
||||
({a:1}).a.b + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
({a:1}) + 1,
|
||||
2,
|
||||
({a:1}).b + 1,
|
||||
1..b + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_object_nested: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
({a:{b:1}}) + 1,
|
||||
({a:{b:1}}).a + 1,
|
||||
({a:{b:1}}).b + 1,
|
||||
({a:{b:1}}).a.b + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
({a:{b:1}}) + 1,
|
||||
({a:{b:1}}).a + 1,
|
||||
({a:{b:1}}).b + 1,
|
||||
2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_object_complex: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
({a:{b:1},b:1}) + 1,
|
||||
({a:{b:1},b:1}).a + 1,
|
||||
({a:{b:1},b:1}).b + 1,
|
||||
({a:{b:1},b:1}).a.b + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
({a:{b:1},b:1}) + 1,
|
||||
({a:{b:1},b:1}).a + 1,
|
||||
2,
|
||||
2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_object_repeated: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
({a:{b:1},a:1}) + 1,
|
||||
({a:{b:1},a:1}).a + 1,
|
||||
({a:{b:1},a:1}).b + 1,
|
||||
({a:{b:1},a:1}).a.b + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
({a:{b:1},a:1}) + 1,
|
||||
2,
|
||||
({a:{b:1},a:1}).b + 1,
|
||||
1..b + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_function: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
({a:{b:1},b:function(){}}) + 1,
|
||||
({a:{b:1},b:function(){}}).a + 1,
|
||||
({a:{b:1},b:function(){}}).b + 1,
|
||||
({a:{b:1},b:function(){}}).a.b + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
({a:{b:1},b:function(){}}) + 1,
|
||||
({a:{b:1},b:function(){}}).a + 1,
|
||||
({a:{b:1},b:function(){}}).b + 1,
|
||||
({a:{b:1},b:function(){}}).a.b + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_integer_key: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
({0:1}) + 1,
|
||||
({0:1})[0] + 1,
|
||||
({0:1})["0"] + 1,
|
||||
({0:1})[1] + 1,
|
||||
({0:1})[0][1] + 1,
|
||||
({0:1})[0]["1"] + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
({0:1}) + 1,
|
||||
2,
|
||||
2,
|
||||
({0:1})[1] + 1,
|
||||
1[1] + 1,
|
||||
1["1"] + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_integer_key_complex: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
({0:{1:1},1:1}) + 1,
|
||||
({0:{1:1},1:1})[0] + 1,
|
||||
({0:{1:1},1:1})["0"] + 1,
|
||||
({0:{1:1},1:1})[1] + 1,
|
||||
({0:{1:1},1:1})[0][1] + 1,
|
||||
({0:{1:1},1:1})[0]["1"] + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
({0:{1:1},1:1}) + 1,
|
||||
"[object Object]1",
|
||||
"[object Object]1",
|
||||
2,
|
||||
2,
|
||||
2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_float_key: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
({2.72:1}) + 1,
|
||||
({2.72:1})[2.72] + 1,
|
||||
({2.72:1})["2.72"] + 1,
|
||||
({2.72:1})[3.14] + 1,
|
||||
({2.72:1})[2.72][3.14] + 1,
|
||||
({2.72:1})[2.72]["3.14"] + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
({2.72:1}) + 1,
|
||||
2,
|
||||
2,
|
||||
({2.72:1})[3.14] + 1,
|
||||
1[3.14] + 1,
|
||||
1["3.14"] + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_float_key_complex: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
({2.72:{3.14:1},3.14:1}) + 1,
|
||||
({2.72:{3.14:1},3.14:1})[2.72] + 1,
|
||||
({2.72:{3.14:1},3.14:1})["2.72"] + 1,
|
||||
({2.72:{3.14:1},3.14:1})[3.14] + 1,
|
||||
({2.72:{3.14:1},3.14:1})[2.72][3.14] + 1,
|
||||
({2.72:{3.14:1},3.14:1})[2.72]["3.14"] + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
"[object Object]1",
|
||||
"[object Object]1",
|
||||
"[object Object]1",
|
||||
2,
|
||||
2,
|
||||
2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_array: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
[1, , 3][1],
|
||||
[1, 2, 3, a] + 1,
|
||||
[1, 2, 3, 4] + 1,
|
||||
[1, 2, 3, a][0] + 1,
|
||||
[1, 2, 3, 4][0] + 1,
|
||||
[1, 2, 3, 4][6 - 5] + 1,
|
||||
[1, , 3, 4][6 - 5] + 1,
|
||||
[[1, 2], [3, 4]][0] + 1,
|
||||
[[1, 2], [3, 4]][6 - 5][1] + 1,
|
||||
[[1, 2], , [3, 4]][6 - 5][1] + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
void 0,
|
||||
[1, 2, 3, a] + 1,
|
||||
"1,2,3,41",
|
||||
[1, 2, 3, a][0] + 1,
|
||||
2,
|
||||
3,
|
||||
NaN,
|
||||
"1,21",
|
||||
5,
|
||||
(void 0)[1] + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_string: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
"1234" + 1,
|
||||
"1234"[0] + 1,
|
||||
"1234"[6 - 5] + 1,
|
||||
("12" + "34")[0] + 1,
|
||||
("12" + "34")[6 - 5] + 1,
|
||||
[1, 2, 3, 4].join("")[0] + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
"12341",
|
||||
"11",
|
||||
"21",
|
||||
"11",
|
||||
"21",
|
||||
"11"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_array_bad_index: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
[1, 2, 3, 4].a + 1,
|
||||
[1, 2, 3, 4]["a"] + 1,
|
||||
[1, 2, 3, 4][3.14] + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
[1, 2, 3, 4].a + 1,
|
||||
[1, 2, 3, 4]["a"] + 1,
|
||||
[1, 2, 3, 4][3.14] + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_string_bad_index: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
"1234".a + 1,
|
||||
"1234"["a"] + 1,
|
||||
"1234"[3.14] + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
"1234".a + 1,
|
||||
"1234"["a"] + 1,
|
||||
"1234"[3.14] + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_prototype_function: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
var a = ({valueOf: 0}) < 1;
|
||||
var b = ({toString: 0}) < 1;
|
||||
var c = ({valueOf: 0}) + "";
|
||||
var d = ({toString: 0}) + "";
|
||||
var e = (({valueOf: 0}) + "")[2];
|
||||
var f = (({toString: 0}) + "")[2];
|
||||
var g = ({valueOf: 0}).valueOf();
|
||||
var h = ({toString: 0}).toString();
|
||||
}
|
||||
expect: {
|
||||
var a = ({valueOf: 0}) < 1;
|
||||
var b = ({toString: 0}) < 1;
|
||||
var c = ({valueOf: 0}) + "";
|
||||
var d = ({toString: 0}) + "";
|
||||
var e = (({valueOf: 0}) + "")[2];
|
||||
var f = (({toString: 0}) + "")[2];
|
||||
var g = ({valueOf: 0}).valueOf();
|
||||
var h = "" + ({toString: 0});
|
||||
}
|
||||
}
|
||||
|
||||
call_args: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
const a = 1;
|
||||
console.log(a);
|
||||
+function(a) {
|
||||
return a;
|
||||
}(a);
|
||||
}
|
||||
expect: {
|
||||
const a = 1;
|
||||
console.log(1);
|
||||
+function(a) {
|
||||
return 1;
|
||||
}(1);
|
||||
}
|
||||
}
|
||||
|
||||
in_boolean_context: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
!42,
|
||||
!"foo",
|
||||
![1, 2],
|
||||
!/foo/,
|
||||
!b(42),
|
||||
!b("foo"),
|
||||
!b([1, 2]),
|
||||
!b(/foo/),
|
||||
![1, foo()],
|
||||
![1, foo(), 2]
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
!1,
|
||||
!1,
|
||||
!1,
|
||||
!1,
|
||||
!b(42),
|
||||
!b("foo"),
|
||||
!b([1, 2]),
|
||||
!b(/foo/),
|
||||
![1, foo()],
|
||||
(foo(), !1)
|
||||
);
|
||||
}
|
||||
}
|
||||
28
test/compress/expansions.js
Normal file
28
test/compress/expansions.js
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
expand_arguments: {
|
||||
input: {
|
||||
func(a, ...rest);
|
||||
func(...all);
|
||||
}
|
||||
expect_exact: "func(a,...rest);func(...all);"
|
||||
}
|
||||
|
||||
expand_expression_arguments: {
|
||||
input: {
|
||||
f(...a.b);
|
||||
f(...a.b());
|
||||
f(...(a));
|
||||
f(...(a.b));
|
||||
f(...a[i]);
|
||||
}
|
||||
expect_exact: "f(...a.b);f(...a.b());f(...a);f(...a.b);f(...a[i]);"
|
||||
}
|
||||
|
||||
expand_parameters: {
|
||||
input: {
|
||||
(function (a, ...b){});
|
||||
(function (...args){});
|
||||
}
|
||||
expect_exact: "(function(a,...b){});(function(...args){});"
|
||||
}
|
||||
|
||||
52
test/compress/expression.js
Normal file
52
test/compress/expression.js
Normal file
@@ -0,0 +1,52 @@
|
||||
pow: {
|
||||
input: {
|
||||
var a = 2 ** 7;
|
||||
var b = 3;
|
||||
b **= 2;
|
||||
}
|
||||
expect: {
|
||||
var a = 2 ** 7;
|
||||
var b = 3;
|
||||
b **= 2;
|
||||
}
|
||||
}
|
||||
|
||||
pow_with_number_constants: {
|
||||
input: {
|
||||
var a = 5 ** NaN;
|
||||
var b = 42 ** +0;
|
||||
var c = 42 ** -0;
|
||||
var d = NaN ** 1;
|
||||
var e = 2 ** Infinity;
|
||||
var f = 2 ** -Infinity;
|
||||
}
|
||||
expect: {
|
||||
var a = 5 ** NaN;
|
||||
var b = 42 ** +0;
|
||||
var c = 42 ** -0;
|
||||
var d = NaN ** 1;
|
||||
var e = 2 ** (1/0);
|
||||
var f = 2 ** -(1/0);
|
||||
}
|
||||
}
|
||||
|
||||
pow_with_parentheses: {
|
||||
input: {
|
||||
var g = (-7) ** (0.5);
|
||||
var h = 2324334 ** 34343443;
|
||||
var i = (-2324334) ** 34343443;
|
||||
var j = 2 ** (-3);
|
||||
var k = 2.0 ** -3;
|
||||
var l = 2.0 ** (5 - 7);
|
||||
}
|
||||
expect_exact: "var g=(-7)**.5;var h=2324334**34343443;var i=(-2324334)**34343443;var j=2**-3;var k=2**-3;var l=2**(5-7);"
|
||||
}
|
||||
|
||||
pow_with_unary_between_brackets: {
|
||||
input: {
|
||||
var a = (-(+5)) ** 3;
|
||||
}
|
||||
expect: {
|
||||
var a = (-+5)**3;
|
||||
}
|
||||
}
|
||||
8
test/compress/functions.js
Normal file
8
test/compress/functions.js
Normal file
@@ -0,0 +1,8 @@
|
||||
non_ascii_function_identifier_name: {
|
||||
input: {
|
||||
function fooλ(δλ) {}
|
||||
function λ(δλ) {}
|
||||
(function λ(δλ) {})()
|
||||
}
|
||||
expect_exact: "function fooλ(δλ){}function λ(δλ){}(function λ(δλ){})();"
|
||||
}
|
||||
147
test/compress/global_defs.js
Normal file
147
test/compress/global_defs.js
Normal file
@@ -0,0 +1,147 @@
|
||||
must_replace: {
|
||||
options = {
|
||||
global_defs: {
|
||||
D: "foo bar",
|
||||
}
|
||||
}
|
||||
input: {
|
||||
console.log(D);
|
||||
}
|
||||
expect: {
|
||||
console.log("foo bar");
|
||||
}
|
||||
}
|
||||
|
||||
keyword: {
|
||||
options = {
|
||||
global_defs: {
|
||||
undefined: 0,
|
||||
NaN: 1,
|
||||
Infinity: 2,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
console.log(undefined, NaN, Infinity);
|
||||
}
|
||||
expect: {
|
||||
console.log(0, 1, 2);
|
||||
}
|
||||
}
|
||||
|
||||
object: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
global_defs: {
|
||||
CONFIG: {
|
||||
DEBUG: [ 0 ],
|
||||
VALUE: 42,
|
||||
},
|
||||
},
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
function f(CONFIG) {
|
||||
// CONFIG not global - do not replace
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function g() {
|
||||
var CONFIG = { VALUE: 1 };
|
||||
// CONFIG not global - do not replace
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function h() {
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
if (CONFIG.DEBUG[0])
|
||||
console.debug("foo");
|
||||
}
|
||||
expect: {
|
||||
function f(CONFIG) {
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function g() {
|
||||
var CONFIG = { VALUE: 1 };
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function h() {
|
||||
return 42;
|
||||
}
|
||||
if (0)
|
||||
console.debug("foo");
|
||||
}
|
||||
}
|
||||
|
||||
expanded: {
|
||||
options = {
|
||||
global_defs: {
|
||||
"CONFIG.DEBUG": [ 0 ],
|
||||
"CONFIG.VALUE": 42,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
function f(CONFIG) {
|
||||
// CONFIG not global - do not replace
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function g() {
|
||||
var CONFIG = { VALUE: 1 };
|
||||
// CONFIG not global - do not replace
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function h() {
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
if (CONFIG.DEBUG[0])
|
||||
console.debug("foo");
|
||||
}
|
||||
expect: {
|
||||
function f(CONFIG) {
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function g() {
|
||||
var CONFIG = { VALUE: 1 };
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function h() {
|
||||
return 42;
|
||||
}
|
||||
if ([0][0])
|
||||
console.debug("foo");
|
||||
}
|
||||
}
|
||||
|
||||
mixed: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
global_defs: {
|
||||
"CONFIG.VALUE": 42,
|
||||
"FOO.BAR": "moo",
|
||||
},
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
const FOO = { BAR: 0 };
|
||||
console.log(FOO.BAR);
|
||||
console.log(++CONFIG.DEBUG);
|
||||
console.log(++CONFIG.VALUE);
|
||||
console.log(++CONFIG["VAL" + "UE"]);
|
||||
console.log(++DEBUG[CONFIG.VALUE]);
|
||||
CONFIG.VALUE.FOO = "bar";
|
||||
console.log(CONFIG);
|
||||
}
|
||||
expect: {
|
||||
const FOO = { BAR: 0 };
|
||||
console.log("moo");
|
||||
console.log(++CONFIG.DEBUG);
|
||||
console.log(++CONFIG.VALUE);
|
||||
console.log(++CONFIG.VALUE);
|
||||
console.log(++DEBUG[42]);
|
||||
CONFIG.VALUE.FOO = "bar";
|
||||
console.log(CONFIG);
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:126,22]',
|
||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]',
|
||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:129,8]',
|
||||
]
|
||||
}
|
||||
288
test/compress/harmony.js
Normal file
288
test/compress/harmony.js
Normal file
@@ -0,0 +1,288 @@
|
||||
arrow_function_parens: {
|
||||
input: {
|
||||
something && (() => {});
|
||||
}
|
||||
expect_exact: "something&&(()=>{});"
|
||||
}
|
||||
arrow_function_parens_2: {
|
||||
input: {
|
||||
(() => null)();
|
||||
}
|
||||
expect_exact: "(()=>null)();"
|
||||
}
|
||||
|
||||
typeof_arrow_functions: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = typeof (x) => null;
|
||||
}
|
||||
expect_exact: "var foo=\"function\";"
|
||||
}
|
||||
|
||||
classes: {
|
||||
input: {
|
||||
class SomeClass {
|
||||
constructor() {
|
||||
};
|
||||
foo() {};
|
||||
};
|
||||
class NoSemi {
|
||||
constructor(...args) {
|
||||
}
|
||||
foo() {}
|
||||
};
|
||||
class ChildClass extends SomeClass {};
|
||||
var asExpression = class AsExpression {};
|
||||
var nameless = class {};
|
||||
}
|
||||
expect_exact: "class SomeClass{constructor(){}foo(){}}class NoSemi{constructor(...args){}foo(){}}class ChildClass extends SomeClass{}var asExpression=class AsExpression{};var nameless=class{};"
|
||||
}
|
||||
|
||||
class_statics: {
|
||||
input: {
|
||||
x = class {
|
||||
static staticMethod() {}
|
||||
static get foo() {}
|
||||
static set bar() {}
|
||||
static() { /* "static" can be a method name! */ }
|
||||
get() { /* "get" can be a method name! */ }
|
||||
set() { /* "set" can be a method name! */ }
|
||||
}
|
||||
}
|
||||
expect_exact: "x=class{static staticMethod(){}static get foo(){}static set bar(){}static(){}get(){}set(){}};"
|
||||
}
|
||||
|
||||
class_name_can_be_mangled: {
|
||||
mangle = { };
|
||||
input: {
|
||||
function x() {
|
||||
class Foo {
|
||||
}
|
||||
var class1 = Foo
|
||||
var class2 = class Bar {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
class a { }
|
||||
var n = a
|
||||
var r = class a {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_name_can_be_preserved: {
|
||||
mangle = {
|
||||
keep_classnames: true
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
(class Baz { });
|
||||
class Foo {};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
(class Baz { });
|
||||
class Foo {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
classes_can_have_generators: {
|
||||
input: {
|
||||
class Foo {
|
||||
*bar() {}
|
||||
static *baz() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
class Foo {
|
||||
*bar() {}
|
||||
static *baz() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
classes_can_have_computed_generators: {
|
||||
input: {
|
||||
class C4 {
|
||||
*['constructor']() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
class C4 {
|
||||
*['constructor']() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
classes_can_have_computed_static: {
|
||||
input: {
|
||||
class C4 {
|
||||
static ['constructor']() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
class C4 {
|
||||
static ['constructor']() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_methods_and_getters_with_keep_quoted_props_enabled: {
|
||||
beautify = {
|
||||
quote_style: 3,
|
||||
keep_quoted_props: true,
|
||||
}
|
||||
input: {
|
||||
class clss {
|
||||
a() {}
|
||||
"b"() {}
|
||||
get c() { return "c"}
|
||||
get "d"() { return "d"}
|
||||
set e(a) { doSomething(a); }
|
||||
set 'f'(a) { doSomething(b); }
|
||||
static g() {}
|
||||
static "h"() {}
|
||||
}
|
||||
}
|
||||
expect_exact: 'class clss{a(){}"b"(){}get c(){return"c"}get"d"(){return"d"}set e(a){doSomething(a)}set\'f\'(a){doSomething(b)}static g(){}static"h"(){}}'
|
||||
}
|
||||
|
||||
new_target: {
|
||||
input: {
|
||||
new.target;
|
||||
new.target.name;
|
||||
}
|
||||
expect_exact: "new.target;new.target.name;"
|
||||
}
|
||||
|
||||
number_literals: {
|
||||
input: {
|
||||
0b1001;
|
||||
0B1001;
|
||||
0o11;
|
||||
0O11;
|
||||
}
|
||||
|
||||
expect: {
|
||||
9;
|
||||
9;
|
||||
9;
|
||||
9;
|
||||
}
|
||||
}
|
||||
|
||||
import_statement: {
|
||||
input: {
|
||||
import "mod-name";
|
||||
import Foo from "bar";
|
||||
import { Bar, Baz } from 'lel';
|
||||
import Bar, { Foo } from 'lel';
|
||||
import { Bar as kex, Baz as food } from 'lel';
|
||||
}
|
||||
expect_exact: "import\"mod-name\";import Foo from\"bar\";import{Bar,Baz}from\"lel\";import Bar,{Foo}from\"lel\";import{Bar as kex,Baz as food}from\"lel\";"
|
||||
}
|
||||
|
||||
export_statement: {
|
||||
input: {
|
||||
export default 1;
|
||||
export var foo = 4;
|
||||
export let foo = 6;
|
||||
export const foo = 6;
|
||||
export function foo() {};
|
||||
export class foo { };
|
||||
}
|
||||
expect_exact: "export default 1;export var foo=4;export let foo=6;export const foo=6;export function foo(){};export class foo{};"
|
||||
}
|
||||
|
||||
import_statement_mangling: {
|
||||
mangle = { toplevel: true };
|
||||
input: {
|
||||
import Foo from "foo";
|
||||
import Bar, {Food} from "lel";
|
||||
import {What as Whatever} from "lel";
|
||||
Foo();
|
||||
Bar();
|
||||
Food();
|
||||
Whatever();
|
||||
}
|
||||
expect: {
|
||||
import l from "foo";
|
||||
import e, {Food as o} from "lel";
|
||||
import {What as f} from "lel";
|
||||
l();
|
||||
e();
|
||||
o();
|
||||
f();
|
||||
}
|
||||
}
|
||||
|
||||
export_statement_mangling: {
|
||||
mangle = { };
|
||||
input: {
|
||||
export var foo = 6;
|
||||
export function bar() { }
|
||||
export class Baz { }
|
||||
bar(foo, Baz)
|
||||
}
|
||||
expect: {
|
||||
export var foo = 6;
|
||||
export function bar() { }
|
||||
export class Baz { }
|
||||
bar(foo, Baz)
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/mishoo/UglifyJS2/issues/1021
|
||||
regression_for_of_const: {
|
||||
input: {
|
||||
for (const x of y) {}
|
||||
for (const x in y) {}
|
||||
}
|
||||
expect: {
|
||||
for (const x of y);for (const x in y);
|
||||
}
|
||||
}
|
||||
|
||||
// Fabio: My patches accidentally caused a crash whenever
|
||||
// there's an extraneous set of parens around an object.
|
||||
regression_cannot_destructure: {
|
||||
input: {
|
||||
var x = ({ x : 3 });
|
||||
x(({ x: 3 }));
|
||||
}
|
||||
expect_exact: "var x={x:3};x({x:3});";
|
||||
}
|
||||
|
||||
regression_cannot_use_of: {
|
||||
input: {
|
||||
function of() {
|
||||
}
|
||||
var of = "is a valid variable name";
|
||||
of = { of: "is ok" };
|
||||
x.of;
|
||||
of: foo()
|
||||
}
|
||||
expect: {
|
||||
function of(){}
|
||||
var of="is a valid variable name";
|
||||
of={of:"is ok"};
|
||||
x.of;
|
||||
foo(); /* Label statement missing? No prob. */
|
||||
}
|
||||
}
|
||||
|
||||
fat_arrow_as_param: {
|
||||
input: {
|
||||
foo(x => x);
|
||||
foo(x => x, y => y);
|
||||
|
||||
foo(x => (x, x));
|
||||
foo(x => (x, x), y => (y, y));
|
||||
}
|
||||
expect_exact: "foo(x=>x);foo(x=>x,y=>y);foo(x=>(x,x));foo(x=>(x,x),y=>(y,y));"
|
||||
}
|
||||
85
test/compress/hoist.js
Normal file
85
test/compress/hoist.js
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
hoist_vars: {
|
||||
options = {
|
||||
hoist_vars: true
|
||||
}
|
||||
input: {
|
||||
function a() {
|
||||
bar();
|
||||
var var1;
|
||||
var var2;
|
||||
}
|
||||
function b(anArg) {
|
||||
bar();
|
||||
var var1;
|
||||
var anArg;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
var var1, var2; // Vars go up and are joined
|
||||
bar();
|
||||
}
|
||||
function b(anArg) {
|
||||
var var1;
|
||||
bar();
|
||||
// But vars named like arguments go away!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hoist_funs: {
|
||||
options = {
|
||||
hoist_funs: true
|
||||
}
|
||||
input: {
|
||||
function a() {
|
||||
bar();
|
||||
function foo() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
function foo() {} // Funs go up
|
||||
bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hoist_no_destructurings: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
hoist_funs: true
|
||||
}
|
||||
input: {
|
||||
function a([anArg]) {
|
||||
bar();
|
||||
var var1;
|
||||
var anArg; // Because anArg is already declared, this goes away!
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a([anArg]) {
|
||||
var var1;
|
||||
bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dont_hoist_var_destructurings: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
hoist_funs: true
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
// If foo is null or undefined, this should be an exception
|
||||
var {x,y} = foo;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
var {x,y} = foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
90
test/compress/hoist_vars.js
Normal file
90
test/compress/hoist_vars.js
Normal file
@@ -0,0 +1,90 @@
|
||||
statements: {
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a = 1;
|
||||
var b = 2;
|
||||
var c = 3;
|
||||
function g() {}
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
var a = 1, b = 2, c = 3;
|
||||
function g() {}
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
statements_funs: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a = 1;
|
||||
var b = 2;
|
||||
var c = 3;
|
||||
function g() {}
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
function g() {}
|
||||
var a = 1, b = 2, c = 3;
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sequences: {
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a = 1, b = 2;
|
||||
function g() {}
|
||||
var c = 3;
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
var c, a = 1, b = 2;
|
||||
function g() {}
|
||||
c = 3;
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sequences_funs: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a = 1, b = 2;
|
||||
function g() {}
|
||||
var c = 3;
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
function g() {}
|
||||
var a = 1, b = 2, c = 3;
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
80
test/compress/html_comments.js
Normal file
80
test/compress/html_comments.js
Normal file
@@ -0,0 +1,80 @@
|
||||
html_comment_in_expression: {
|
||||
input: {
|
||||
function f(a, b, x, y) { return a < !--b && x-- > y; }
|
||||
}
|
||||
expect_exact: "function f(a,b,x,y){return a< !--b&&x-- >y}";
|
||||
}
|
||||
|
||||
html_comment_in_less_than: {
|
||||
input: {
|
||||
function f(a, b) { return a < !--b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a< !--b}";
|
||||
}
|
||||
|
||||
html_comment_in_left_shift: {
|
||||
input: {
|
||||
function f(a, b) { return a << !--b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a<< !--b}";
|
||||
}
|
||||
|
||||
html_comment_in_right_shift: {
|
||||
input: {
|
||||
function f(a, b) { return a-- >> b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >>b}";
|
||||
}
|
||||
|
||||
html_comment_in_zero_fill_right_shift: {
|
||||
input: {
|
||||
function f(a, b) { return a-- >>> b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >>>b}";
|
||||
}
|
||||
|
||||
html_comment_in_greater_than: {
|
||||
input: {
|
||||
function f(a, b) { return a-- > b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >b}";
|
||||
}
|
||||
|
||||
html_comment_in_greater_than_or_equal: {
|
||||
input: {
|
||||
function f(a, b) { return a-- >= b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >=b}";
|
||||
}
|
||||
|
||||
html_comment_in_right_shift_assign: {
|
||||
input: {
|
||||
// Note: illegal javascript
|
||||
function f(a, b) { return a-- >>= b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >>=b}";
|
||||
}
|
||||
|
||||
html_comment_in_zero_fill_right_shift_assign: {
|
||||
input: {
|
||||
// Note: illegal javascript
|
||||
function f(a, b) { return a-- >>>= b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >>>=b}";
|
||||
}
|
||||
|
||||
html_comment_in_string_literal: {
|
||||
input: {
|
||||
function f() { return "<!--HTML-->comment in<!--string literal-->"; }
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e"}';
|
||||
}
|
||||
|
||||
html_comment_after_multiline_comment: {
|
||||
input: {
|
||||
var foo; /*
|
||||
*/--> var bar;
|
||||
var foobar;
|
||||
}
|
||||
expect_exact: "var foo;var foobar;"
|
||||
}
|
||||
304
test/compress/if_return.js
Normal file
304
test/compress/if_return.js
Normal file
@@ -0,0 +1,304 @@
|
||||
if_return_1: {
|
||||
options = {
|
||||
if_return : true,
|
||||
sequences : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects : true,
|
||||
dead_code : true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
if (x) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x){if(x)return!0}
|
||||
}
|
||||
}
|
||||
|
||||
if_return_2: {
|
||||
options = {
|
||||
if_return : true,
|
||||
sequences : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects : true,
|
||||
dead_code : true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y) {
|
||||
if (x)
|
||||
return 3;
|
||||
if (y)
|
||||
return c();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x,y){return x?3:y?c():void 0}
|
||||
}
|
||||
}
|
||||
|
||||
if_return_3: {
|
||||
options = {
|
||||
if_return : true,
|
||||
sequences : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects : true,
|
||||
dead_code : true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
a();
|
||||
if (x) {
|
||||
b();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x){if(a(),x)return b(),!1}
|
||||
}
|
||||
}
|
||||
|
||||
if_return_4: {
|
||||
options = {
|
||||
if_return : true,
|
||||
sequences : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects : true,
|
||||
dead_code : true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y) {
|
||||
a();
|
||||
if (x) return 3;
|
||||
b();
|
||||
if (y) return c();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x,y){return a(),x?3:(b(),y?c():void 0)}
|
||||
}
|
||||
}
|
||||
|
||||
if_return_5: {
|
||||
options = {
|
||||
if_return : true,
|
||||
sequences : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects : true,
|
||||
dead_code : true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
if (x)
|
||||
return;
|
||||
return 7;
|
||||
if (y)
|
||||
return j;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(){if(!x)return 7}
|
||||
}
|
||||
}
|
||||
|
||||
if_return_6: {
|
||||
options = {
|
||||
if_return : true,
|
||||
sequences : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects : true,
|
||||
dead_code : true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
return x ? true : void 0;
|
||||
return y;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
// suboptimal
|
||||
function f(x){return!!x||void 0}
|
||||
}
|
||||
}
|
||||
|
||||
if_return_7: {
|
||||
options = {
|
||||
if_return : true,
|
||||
sequences : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects : true,
|
||||
dead_code : true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
if (x) {
|
||||
return true;
|
||||
}
|
||||
foo();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x){if(x)return!0;foo(),bar()}
|
||||
}
|
||||
}
|
||||
|
||||
if_return_8: {
|
||||
options = {
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
side_effects : true,
|
||||
}
|
||||
input: {
|
||||
function f(e) {
|
||||
if (2 == e) return foo();
|
||||
if (3 == e) return bar();
|
||||
if (4 == e) return baz();
|
||||
fail(e);
|
||||
}
|
||||
|
||||
function g(e) {
|
||||
if (a(e)) return foo();
|
||||
if (b(e)) return bar();
|
||||
if (c(e)) return baz();
|
||||
fail(e);
|
||||
}
|
||||
|
||||
function h(e) {
|
||||
if (a(e)) return foo();
|
||||
else if (b(e)) return bar();
|
||||
else if (c(e)) return baz();
|
||||
else fail(e);
|
||||
}
|
||||
|
||||
function i(e) {
|
||||
if (a(e)) return foo();
|
||||
else if (b(e)) return bar();
|
||||
else if (c(e)) return baz();
|
||||
fail(e);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(e){return 2==e?foo():3==e?bar():4==e?baz():void fail(e)}
|
||||
function g(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
|
||||
function h(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
|
||||
function i(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1089: {
|
||||
options = {
|
||||
if_return : true,
|
||||
sequences : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects : true,
|
||||
dead_code : true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
var f = document.getElementById("fname");
|
||||
if (f.files[0].size > 12345) {
|
||||
alert("alert");
|
||||
f.focus();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
var f = document.getElementById("fname");
|
||||
if (f.files[0].size > 12345)
|
||||
return alert("alert"), f.focus(), !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1437: {
|
||||
options = {
|
||||
if_return : true,
|
||||
sequences : true,
|
||||
conditionals : false
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
if (a())
|
||||
return b();
|
||||
if (c())
|
||||
return d();
|
||||
else
|
||||
e();
|
||||
f();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
if (a())
|
||||
return b();
|
||||
if (c())
|
||||
return d();
|
||||
else
|
||||
e()
|
||||
f();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1437_conditionals: {
|
||||
options = {
|
||||
conditionals : true,
|
||||
if_return : true,
|
||||
sequences : true
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
if (a())
|
||||
return b();
|
||||
if (c())
|
||||
return d();
|
||||
else
|
||||
e();
|
||||
f();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
return a() ? b() : c() ? d() : (e(), f(), void 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
8
test/compress/issue-1001.js
Normal file
8
test/compress/issue-1001.js
Normal file
@@ -0,0 +1,8 @@
|
||||
parenthesis_strings_in_parenthesis: {
|
||||
input: {
|
||||
var foo = ('(');
|
||||
a(')');
|
||||
|
||||
}
|
||||
expect_exact: 'var foo="(";a(")");'
|
||||
}
|
||||
121
test/compress/issue-1034.js
Normal file
121
test/compress/issue-1034.js
Normal file
@@ -0,0 +1,121 @@
|
||||
non_hoisted_function_after_return: {
|
||||
options = {
|
||||
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
|
||||
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
||||
if_return: true, join_vars: true, cascade: true, side_effects: true
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
if (x) {
|
||||
return bar();
|
||||
not_called1();
|
||||
} else {
|
||||
return baz();
|
||||
not_called2();
|
||||
}
|
||||
function bar() { return 7; }
|
||||
return not_reached;
|
||||
function UnusedFunction() {}
|
||||
function baz() { return 8; }
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(x) {
|
||||
return x ? bar() : baz();
|
||||
function bar() { return 7 }
|
||||
function baz() { return 8 }
|
||||
}
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: Dropping unreachable code [test/compress/issue-1034.js:11,16]',
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:14,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:17,12]",
|
||||
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:18,21]"
|
||||
]
|
||||
}
|
||||
|
||||
non_hoisted_function_after_return_2a: {
|
||||
options = {
|
||||
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
|
||||
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
||||
if_return: true, join_vars: true, cascade: true, side_effects: true,
|
||||
collapse_vars: false, passes: 2
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
if (x) {
|
||||
return bar(1);
|
||||
var a = not_called(1);
|
||||
} else {
|
||||
return bar(2);
|
||||
var b = not_called(2);
|
||||
}
|
||||
var c = bar(3);
|
||||
function bar(x) { return 7 - x; }
|
||||
function nope() {}
|
||||
return b || c;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(x) {
|
||||
return bar(x ? 1 : 2);
|
||||
function bar(x) {
|
||||
return 7 - x;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_warnings: [
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:48,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:48,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:51,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]",
|
||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]",
|
||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:53,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]",
|
||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]",
|
||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]"
|
||||
]
|
||||
}
|
||||
|
||||
non_hoisted_function_after_return_2b: {
|
||||
options = {
|
||||
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
|
||||
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
||||
if_return: true, join_vars: true, cascade: true, side_effects: true,
|
||||
collapse_vars: false
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
if (x) {
|
||||
return bar(1);
|
||||
} else {
|
||||
return bar(2);
|
||||
var b;
|
||||
}
|
||||
var c = bar(3);
|
||||
function bar(x) {
|
||||
return 7 - x;
|
||||
}
|
||||
return b || c;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(x) {
|
||||
return bar(x ? 1 : 2);
|
||||
function bar(x) { return 7 - x; }
|
||||
}
|
||||
}
|
||||
expect_warnings: [
|
||||
// duplicate warnings no longer emitted
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:95,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:95,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]",
|
||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:95,20]",
|
||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:97,16]"
|
||||
]
|
||||
}
|
||||
|
||||
41
test/compress/issue-1041.js
Normal file
41
test/compress/issue-1041.js
Normal file
@@ -0,0 +1,41 @@
|
||||
const_declaration: {
|
||||
options = {
|
||||
evaluate: true
|
||||
};
|
||||
|
||||
input: {
|
||||
const goog = goog || {};
|
||||
}
|
||||
expect: {
|
||||
const goog = goog || {};
|
||||
}
|
||||
}
|
||||
|
||||
const_pragma: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
};
|
||||
|
||||
input: {
|
||||
/** @const */ var goog = goog || {};
|
||||
}
|
||||
expect: {
|
||||
var goog = goog || {};
|
||||
}
|
||||
}
|
||||
|
||||
// for completeness' sake
|
||||
not_const: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
};
|
||||
|
||||
input: {
|
||||
var goog = goog || {};
|
||||
}
|
||||
expect: {
|
||||
var goog = goog || {};
|
||||
}
|
||||
}
|
||||
30
test/compress/issue-1043.js
Normal file
30
test/compress/issue-1043.js
Normal file
@@ -0,0 +1,30 @@
|
||||
issue_1043: {
|
||||
options = {
|
||||
side_effects: true
|
||||
};
|
||||
|
||||
input: {
|
||||
function* range(start = 0, end = null, step = 1) {
|
||||
if (end == null) {
|
||||
end = start;
|
||||
start = 0;
|
||||
}
|
||||
|
||||
for (let i = start; i < end; i += step) {
|
||||
yield i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expect: {
|
||||
function* range(start = 0, end = null, step = 1) {
|
||||
if (null == end) {
|
||||
end = start;
|
||||
start = 0;
|
||||
}
|
||||
|
||||
for (let i = start; i < end; i += step)
|
||||
yield i;
|
||||
}
|
||||
}
|
||||
}
|
||||
9
test/compress/issue-1044.js
Normal file
9
test/compress/issue-1044.js
Normal file
@@ -0,0 +1,9 @@
|
||||
issue_1044: {
|
||||
options = { evaluate: true, conditionals: true };
|
||||
input: {
|
||||
const mixed = Base ? class extends Base {} : class {}
|
||||
}
|
||||
expect: {
|
||||
const mixed = Base ? class extends Base {} : class {}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
typeof_eq_undefined: {
|
||||
options = {
|
||||
comparisons: true
|
||||
};
|
||||
input: { a = typeof b.c != "undefined" }
|
||||
expect: { a = "undefined" != typeof b.c }
|
||||
}
|
||||
|
||||
typeof_eq_undefined_unsafe: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
unsafe: true
|
||||
};
|
||||
input: { a = typeof b.c != "undefined" }
|
||||
expect: { a = void 0 !== b.c }
|
||||
}
|
||||
|
||||
typeof_eq_undefined_unsafe2: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
unsafe: true
|
||||
};
|
||||
input: { a = "undefined" != typeof b.c }
|
||||
expect: { a = void 0 !== b.c }
|
||||
}
|
||||
96
test/compress/issue-1052.js
Normal file
96
test/compress/issue-1052.js
Normal file
@@ -0,0 +1,96 @@
|
||||
multiple_functions: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
input: {
|
||||
( function() {
|
||||
if ( !window ) {
|
||||
return;
|
||||
}
|
||||
|
||||
function f() {}
|
||||
function g() {}
|
||||
} )();
|
||||
}
|
||||
expect: {
|
||||
( function() {
|
||||
function f() {}
|
||||
function g() {}
|
||||
|
||||
// NOTE: other compression steps will reduce this
|
||||
// down to just `window`.
|
||||
if ( window );
|
||||
} )();
|
||||
}
|
||||
}
|
||||
|
||||
single_function: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
input: {
|
||||
( function() {
|
||||
if ( !window ) {
|
||||
return;
|
||||
}
|
||||
|
||||
function f() {}
|
||||
} )();
|
||||
}
|
||||
expect: {
|
||||
( function() {
|
||||
function f() {}
|
||||
|
||||
if ( window );
|
||||
} )();
|
||||
}
|
||||
}
|
||||
|
||||
deeply_nested: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
input: {
|
||||
( function() {
|
||||
if ( !window ) {
|
||||
return;
|
||||
}
|
||||
|
||||
function f() {}
|
||||
function g() {}
|
||||
|
||||
if ( !document ) {
|
||||
return;
|
||||
}
|
||||
|
||||
function h() {}
|
||||
} )();
|
||||
}
|
||||
expect: {
|
||||
( function() {
|
||||
function f() {}
|
||||
function g() {}
|
||||
|
||||
function h() {}
|
||||
|
||||
// NOTE: other compression steps will reduce this
|
||||
// down to just `window`.
|
||||
if ( window )
|
||||
if (document);
|
||||
} )();
|
||||
}
|
||||
}
|
||||
|
||||
not_hoisted_when_already_nested: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
input: {
|
||||
( function() {
|
||||
if ( !window ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( foo ) function f() {}
|
||||
|
||||
} )();
|
||||
}
|
||||
expect: {
|
||||
( function() {
|
||||
if ( window )
|
||||
if ( foo ) function f() {}
|
||||
} )();
|
||||
}
|
||||
}
|
||||
240
test/compress/issue-1105.js
Normal file
240
test/compress/issue-1105.js
Normal file
@@ -0,0 +1,240 @@
|
||||
with_in_global_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
var o = 42;
|
||||
with(o) {
|
||||
var foo = 'something'
|
||||
}
|
||||
doSomething(o);
|
||||
}
|
||||
expect: {
|
||||
var o=42;
|
||||
with(o)
|
||||
var foo = "something";
|
||||
doSomething(o);
|
||||
}
|
||||
}
|
||||
with_in_function_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function foo() {
|
||||
var o = 42;
|
||||
with(o) {
|
||||
var foo = "something"
|
||||
}
|
||||
doSomething(o);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
var o=42;
|
||||
with(o)
|
||||
var foo = "something";
|
||||
doSomething(o)
|
||||
}
|
||||
}
|
||||
}
|
||||
compress_with_with_in_other_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function foo() {
|
||||
var o = 42;
|
||||
with(o) {
|
||||
var foo = "something"
|
||||
}
|
||||
doSomething(o);
|
||||
}
|
||||
function bar() {
|
||||
var unused = 42;
|
||||
return something();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
var o = 42;
|
||||
with(o)
|
||||
var foo = "something";
|
||||
doSomething(o)
|
||||
}
|
||||
function bar() {
|
||||
return something()
|
||||
}
|
||||
}
|
||||
}
|
||||
with_using_existing_variable_outside_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var o = {};
|
||||
var unused = {}; // Doesn't get removed because upper scope uses with
|
||||
function foo() {
|
||||
with(o) {
|
||||
var foo = "something"
|
||||
}
|
||||
doSomething(o);
|
||||
}
|
||||
foo()
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
var o = {};
|
||||
var unused = {};
|
||||
function foo() {
|
||||
with(o)
|
||||
var foo = "something";
|
||||
doSomething(o)
|
||||
}
|
||||
foo()
|
||||
}
|
||||
}
|
||||
}
|
||||
check_drop_unused_in_peer_function: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function outer() {
|
||||
var o = {};
|
||||
var unused = {}; // should be kept
|
||||
function foo() { // should be kept
|
||||
function not_in_use() {
|
||||
var nested_unused = "foo"; // should be dropped
|
||||
return 24;
|
||||
}
|
||||
var unused = {}; // should be kept
|
||||
with (o) {
|
||||
var foo = "something";
|
||||
}
|
||||
doSomething(o);
|
||||
}
|
||||
function bar() {
|
||||
var unused = {}; // should be dropped
|
||||
doSomethingElse();
|
||||
}
|
||||
foo();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function outer() {
|
||||
var o = {};
|
||||
var unused = {}; // should be kept
|
||||
function foo() { // should be kept
|
||||
function not_in_use() {
|
||||
return 24;
|
||||
}
|
||||
var unused = {}; // should be kept
|
||||
with (o)
|
||||
var foo = "something";
|
||||
doSomething(o);
|
||||
}
|
||||
function bar() {
|
||||
doSomethingElse();
|
||||
}
|
||||
foo();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Infinity_not_in_with_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
var o = { Infinity: 'oInfinity' };
|
||||
var vInfinity = "Infinity";
|
||||
vInfinity = Infinity;
|
||||
}
|
||||
expect: {
|
||||
var o = { Infinity: 'oInfinity' }
|
||||
var vInfinity = "Infinity"
|
||||
vInfinity = 1/0
|
||||
}
|
||||
}
|
||||
|
||||
Infinity_in_with_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
var o = { Infinity: 'oInfinity' };
|
||||
var vInfinity = "Infinity";
|
||||
with (o) { vInfinity = Infinity; }
|
||||
}
|
||||
expect: {
|
||||
var o = { Infinity: 'oInfinity' }
|
||||
var vInfinity = "Infinity"
|
||||
with (o) vInfinity = Infinity
|
||||
}
|
||||
}
|
||||
|
||||
assorted_Infinity_NaN_undefined_in_with_scope: {
|
||||
options = {
|
||||
unused: true,
|
||||
evaluate: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
booleans: true,
|
||||
hoist_funs: true,
|
||||
keep_fargs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade: true,
|
||||
side_effects: true,
|
||||
sequences: false,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
undefined : 3,
|
||||
NaN : 4,
|
||||
Infinity : 5,
|
||||
}
|
||||
if (o) {
|
||||
f(undefined, void 0);
|
||||
f(NaN, 0/0);
|
||||
f(Infinity, 1/0);
|
||||
f(-Infinity, -(1/0));
|
||||
f(2 + 7 + undefined, 2 + 7 + void 0);
|
||||
}
|
||||
with (o) {
|
||||
f(undefined, void 0);
|
||||
f(NaN, 0/0);
|
||||
f(Infinity, 1/0);
|
||||
f(-Infinity, -(1/0));
|
||||
f(2 + 7 + undefined, 2 + 7 + void 0);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
undefined : 3,
|
||||
NaN : 4,
|
||||
Infinity : 5
|
||||
}
|
||||
if (o) {
|
||||
f(void 0, void 0);
|
||||
f(NaN, NaN);
|
||||
f(1/0, 1/0);
|
||||
f(-(1/0), -(1/0));
|
||||
f(NaN, NaN);
|
||||
}
|
||||
with (o) {
|
||||
f(undefined, void 0);
|
||||
f(NaN, 0/0);
|
||||
f(Infinity, 1/0);
|
||||
f(-Infinity, -(1/0));
|
||||
f(9 + undefined, 9 + void 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,3 +9,50 @@ keep_name_of_setter: {
|
||||
input: { a = { set foo () {} } }
|
||||
expect: { a = { set foo () {} } }
|
||||
}
|
||||
|
||||
setter_with_operator_keys: {
|
||||
input: {
|
||||
var tokenCodes = {
|
||||
get instanceof(){
|
||||
return test0;
|
||||
},
|
||||
set instanceof(value){
|
||||
test0 = value;
|
||||
},
|
||||
set typeof(value){
|
||||
test1 = value;
|
||||
},
|
||||
get typeof(){
|
||||
return test1;
|
||||
},
|
||||
set else(value){
|
||||
test2 = value;
|
||||
},
|
||||
get else(){
|
||||
return test2;
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var tokenCodes = {
|
||||
get instanceof(){
|
||||
return test0;
|
||||
},
|
||||
set instanceof(value){
|
||||
test0 = value;
|
||||
},
|
||||
set typeof(value){
|
||||
test1 = value;
|
||||
},
|
||||
get typeof(){
|
||||
return test1;
|
||||
},
|
||||
set else(value){
|
||||
test2 = value;
|
||||
},
|
||||
get else(){
|
||||
return test2;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
52
test/compress/issue-1202.js
Normal file
52
test/compress/issue-1202.js
Normal file
@@ -0,0 +1,52 @@
|
||||
mangle_keep_fnames_false: {
|
||||
options = {
|
||||
keep_fnames : true,
|
||||
keep_fargs : true,
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames : false,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function total() {
|
||||
return function n(a, b, c) {
|
||||
return a + b + c;
|
||||
};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function total() {
|
||||
return function t(n, r, u) {
|
||||
return n + r + u;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mangle_keep_fnames_true: {
|
||||
options = {
|
||||
keep_fnames : true,
|
||||
keep_fargs : true,
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames : true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function total() {
|
||||
return function n(a, b, c) {
|
||||
return a + b + c;
|
||||
};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function total() {
|
||||
return function n(t, r, u) {
|
||||
return t + r + u;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
76
test/compress/issue-1212.js
Normal file
76
test/compress/issue-1212.js
Normal file
@@ -0,0 +1,76 @@
|
||||
issue_1212_debug_false: {
|
||||
options = {
|
||||
global_defs : { DEBUG: false },
|
||||
sequences : true,
|
||||
properties : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
loops : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
keep_fargs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
side_effects : true,
|
||||
}
|
||||
input: {
|
||||
class foo {
|
||||
bar() {
|
||||
if (DEBUG)
|
||||
console.log("DEV");
|
||||
else
|
||||
console.log("PROD");
|
||||
}
|
||||
}
|
||||
new foo().bar();
|
||||
}
|
||||
expect: {
|
||||
class foo{
|
||||
bar() { console.log("PROD") }
|
||||
}
|
||||
(new foo).bar();
|
||||
}
|
||||
}
|
||||
|
||||
issue_1212_debug_true: {
|
||||
options = {
|
||||
global_defs : { DEBUG: true },
|
||||
sequences : true,
|
||||
properties : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
loops : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
keep_fargs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
side_effects : true,
|
||||
}
|
||||
input: {
|
||||
class foo {
|
||||
bar() {
|
||||
if (DEBUG)
|
||||
console.log("DEV");
|
||||
else
|
||||
console.log("PROD");
|
||||
}
|
||||
}
|
||||
new foo().bar();
|
||||
}
|
||||
expect: {
|
||||
class foo{
|
||||
bar() { console.log("DEV") }
|
||||
}
|
||||
(new foo).bar();
|
||||
}
|
||||
}
|
||||
|
||||
24
test/compress/issue-126.js
Normal file
24
test/compress/issue-126.js
Normal file
@@ -0,0 +1,24 @@
|
||||
concatenate_rhs_strings: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
foo(bar() + 123 + "Hello" + "World");
|
||||
foo(bar() + (123 + "Hello") + "World");
|
||||
foo((bar() + 123) + "Hello" + "World");
|
||||
foo(bar() + 123 + "Hello" + "World" + ("Foo" + "Bar"));
|
||||
foo("Foo" + "Bar" + bar() + 123 + "Hello" + "World" + ("Foo" + "Bar"));
|
||||
foo("Hello" + bar() + 123 + "World");
|
||||
foo(bar() + 'Foo' + (10 + parseInt('10')));
|
||||
}
|
||||
expect: {
|
||||
foo(bar() + 123 + "HelloWorld");
|
||||
foo(bar() + "123HelloWorld");
|
||||
foo((bar() + 123) + "HelloWorld");
|
||||
foo(bar() + 123 + "HelloWorldFooBar");
|
||||
foo("FooBar" + bar() + "123HelloWorldFooBar");
|
||||
foo("Hello" + bar() + "123World");
|
||||
foo(bar() + 'Foo' + (10 + parseInt('10')));
|
||||
}
|
||||
}
|
||||
176
test/compress/issue-1261.js
Normal file
176
test/compress/issue-1261.js
Normal file
@@ -0,0 +1,176 @@
|
||||
pure_function_calls: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
side_effects : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
negate_iife : true,
|
||||
}
|
||||
input: {
|
||||
// pure top-level IIFE will be dropped
|
||||
// @__PURE__ - comment
|
||||
(function() {
|
||||
console.log("iife0");
|
||||
})();
|
||||
|
||||
// pure top-level IIFE assigned to unreferenced var will not be dropped
|
||||
var iife1 = /*@__PURE__*/(function() {
|
||||
console.log("iife1");
|
||||
function iife1() {}
|
||||
return iife1;
|
||||
})();
|
||||
|
||||
(function(){
|
||||
// pure IIFE in function scope assigned to unreferenced var will be dropped
|
||||
var iife2 = /*#__PURE__*/(function() {
|
||||
console.log("iife2");
|
||||
function iife2() {}
|
||||
return iife2;
|
||||
})();
|
||||
})();
|
||||
|
||||
// comment #__PURE__ comment
|
||||
bar(), baz(), quux();
|
||||
a.b(), /* @__PURE__ */ c.d.e(), f.g();
|
||||
}
|
||||
expect: {
|
||||
var iife1 = function() {
|
||||
console.log("iife1");
|
||||
function iife1() {}
|
||||
return iife1;
|
||||
}();
|
||||
|
||||
baz(), quux();
|
||||
a.b(), f.g();
|
||||
}
|
||||
expect_warnings: [
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:17,8]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:17,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:30,37]",
|
||||
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:30,16]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:28,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:38,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:39,31]",
|
||||
]
|
||||
}
|
||||
|
||||
pure_function_calls_toplevel: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
side_effects : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
negate_iife : true,
|
||||
toplevel : true,
|
||||
}
|
||||
input: {
|
||||
// pure top-level IIFE will be dropped
|
||||
// @__PURE__ - comment
|
||||
(function() {
|
||||
console.log("iife0");
|
||||
})();
|
||||
|
||||
// pure top-level IIFE assigned to unreferenced var will be dropped
|
||||
var iife1 = /*@__PURE__*/(function() {
|
||||
console.log("iife1");
|
||||
function iife1() {}
|
||||
return iife1;
|
||||
})();
|
||||
|
||||
(function(){
|
||||
// pure IIFE in function scope assigned to unreferenced var will be dropped
|
||||
var iife2 = /*#__PURE__*/(function() {
|
||||
console.log("iife2");
|
||||
function iife2() {}
|
||||
return iife2;
|
||||
})();
|
||||
})();
|
||||
|
||||
// comment #__PURE__ comment
|
||||
bar(), baz(), quux();
|
||||
a.b(), /* @__PURE__ */ c.d.e(), f.g();
|
||||
}
|
||||
expect: {
|
||||
baz(), quux();
|
||||
a.b(), f.g();
|
||||
}
|
||||
expect_warnings: [
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:79,8]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:79,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:92,37]",
|
||||
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:92,16]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:90,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:101,31]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:84,33]",
|
||||
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:84,12]",
|
||||
]
|
||||
}
|
||||
|
||||
should_warn: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
/* @__PURE__ */(function(){x})(), void/* @__PURE__ */(function(){y})();
|
||||
/* @__PURE__ */(function(){x})() || true ? foo() : bar();
|
||||
true || /* @__PURE__ */(function(){y})() ? foo() : bar();
|
||||
/* @__PURE__ */(function(){x})() && false ? foo() : bar();
|
||||
false && /* @__PURE__ */(function(){y})() ? foo() : bar();
|
||||
/* @__PURE__ */(function(){x})() + "foo" ? bar() : baz();
|
||||
"foo" + /* @__PURE__ */(function(){y})() ? bar() : baz();
|
||||
/* @__PURE__ */(function(){x})() ? foo() : foo();
|
||||
[/* @__PURE__ */(function(){x})()] ? foo() : bar();
|
||||
!{ foo: /* @__PURE__ */(function(){x})() } ? bar() : baz();
|
||||
}
|
||||
expect: {
|
||||
foo();
|
||||
foo();
|
||||
bar();
|
||||
bar();
|
||||
bar();
|
||||
bar();
|
||||
foo();
|
||||
foo();
|
||||
baz();
|
||||
}
|
||||
expect_warnings: [
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,61]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,23]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:128,23]",
|
||||
"WARN: Boolean || always true [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:129,23]",
|
||||
"WARN: Boolean || always true [test/compress/issue-1261.js:130,8]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:130,8]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:132,8]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:132,8]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:134,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:134,31]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:134,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,24]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:136,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,31]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:137,8]",
|
||||
]
|
||||
}
|
||||
49
test/compress/issue-1275.js
Normal file
49
test/compress/issue-1275.js
Normal file
@@ -0,0 +1,49 @@
|
||||
string_plus_optimization: {
|
||||
options = {
|
||||
side_effects : true,
|
||||
evaluate : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
hoist_funs : true,
|
||||
};
|
||||
input: {
|
||||
function foo(anything) {
|
||||
function throwing_function() {
|
||||
throw "nope";
|
||||
}
|
||||
try {
|
||||
console.log('0' + throwing_function() ? "yes" : "no");
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
console.log('0' + anything ? "yes" : "no");
|
||||
console.log(anything + '0' ? "Yes" : "No");
|
||||
console.log('' + anything);
|
||||
console.log(anything + '');
|
||||
}
|
||||
foo();
|
||||
}
|
||||
expect: {
|
||||
function foo(anything) {
|
||||
function throwing_function() {
|
||||
throw "nope";
|
||||
}
|
||||
try {
|
||||
console.log((throwing_function(), "yes"));
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
console.log("yes");
|
||||
console.log("Yes");
|
||||
console.log('' + anything);
|
||||
console.log(anything + '');
|
||||
}
|
||||
foo();
|
||||
}
|
||||
}
|
||||
54
test/compress/issue-1321.js
Normal file
54
test/compress/issue-1321.js
Normal file
@@ -0,0 +1,54 @@
|
||||
issue_1321_no_debug: {
|
||||
mangle_props = {
|
||||
ignore_quoted: true
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
x.foo = 1;
|
||||
x["a"] = 2 * x.foo;
|
||||
console.log(x.foo, x["a"]);
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.b = 1;
|
||||
x["a"] = 2 * x.b;
|
||||
console.log(x.b, x["a"]);
|
||||
}
|
||||
}
|
||||
|
||||
issue_1321_debug: {
|
||||
mangle_props = {
|
||||
ignore_quoted: true,
|
||||
debug: ""
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
x.foo = 1;
|
||||
x["_$foo$_"] = 2 * x.foo;
|
||||
console.log(x.foo, x["_$foo$_"]);
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.a = 1;
|
||||
x["_$foo$_"] = 2 * x.a;
|
||||
console.log(x.a, x["_$foo$_"]);
|
||||
}
|
||||
}
|
||||
|
||||
issue_1321_with_quoted: {
|
||||
mangle_props = {
|
||||
ignore_quoted: false
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
x.foo = 1;
|
||||
x["a"] = 2 * x.foo;
|
||||
console.log(x.foo, x["a"]);
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.a = 1;
|
||||
x["b"] = 2 * x.a;
|
||||
console.log(x.a, x["b"]);
|
||||
}
|
||||
}
|
||||
151
test/compress/issue-1431.js
Normal file
151
test/compress/issue-1431.js
Normal file
@@ -0,0 +1,151 @@
|
||||
level_zero: {
|
||||
options = {
|
||||
keep_fnames: true
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames: true
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
function n(a) {
|
||||
return a * a;
|
||||
}
|
||||
return function() {
|
||||
return x;
|
||||
};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(r) {
|
||||
function n(n) {
|
||||
return n * n;
|
||||
}
|
||||
return function() {
|
||||
return r;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
level_one: {
|
||||
options = {
|
||||
keep_fnames: true
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames: true
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
return function() {
|
||||
function n(a) {
|
||||
return a * a;
|
||||
}
|
||||
return x(n);
|
||||
};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(r) {
|
||||
return function() {
|
||||
function n(n) {
|
||||
return n * n;
|
||||
}
|
||||
return r(n);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
level_two: {
|
||||
options = {
|
||||
keep_fnames: true
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames: true
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
return function() {
|
||||
function r(a) {
|
||||
return a * a;
|
||||
}
|
||||
return function() {
|
||||
function n(a) {
|
||||
return a * a;
|
||||
}
|
||||
return x(n);
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(t) {
|
||||
return function() {
|
||||
function r(n) {
|
||||
return n * n;
|
||||
}
|
||||
return function() {
|
||||
function n(n) {
|
||||
return n * n;
|
||||
}
|
||||
return t(n);
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
level_three: {
|
||||
options = {
|
||||
keep_fnames: true
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames: true
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
return function() {
|
||||
function r(a) {
|
||||
return a * a;
|
||||
}
|
||||
return [
|
||||
function() {
|
||||
function t(a) {
|
||||
return a * a;
|
||||
}
|
||||
return t;
|
||||
},
|
||||
function() {
|
||||
function n(a) {
|
||||
return a * a;
|
||||
}
|
||||
return x(n);
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(t) {
|
||||
return function() {
|
||||
function r(n) {
|
||||
return n * n;
|
||||
}
|
||||
return [
|
||||
function() {
|
||||
function t(n) {
|
||||
return n * n;
|
||||
}
|
||||
return t;
|
||||
},
|
||||
function() {
|
||||
function n(n) {
|
||||
return n * n;
|
||||
}
|
||||
return t(n);
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
69
test/compress/issue-1443.js
Normal file
69
test/compress/issue-1443.js
Normal file
@@ -0,0 +1,69 @@
|
||||
// tests assume that variable `undefined` not redefined and has `void 0` as value
|
||||
|
||||
unsafe_undefined: {
|
||||
options = {
|
||||
if_return: true,
|
||||
unsafe: true
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
function f(undefined) {
|
||||
return function() {
|
||||
if (a)
|
||||
return b;
|
||||
if (c)
|
||||
return d;
|
||||
};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(n) {
|
||||
return function() {
|
||||
if (a)
|
||||
return b;
|
||||
if (c)
|
||||
return d;
|
||||
else
|
||||
return n;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keep_fnames: {
|
||||
options = {
|
||||
if_return: true,
|
||||
unsafe: true
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames: true
|
||||
}
|
||||
input: {
|
||||
function f(undefined) {
|
||||
return function() {
|
||||
function n(a) {
|
||||
return a * a;
|
||||
}
|
||||
if (a)
|
||||
return b;
|
||||
if (c)
|
||||
return d;
|
||||
};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(r) {
|
||||
return function() {
|
||||
function n(n) {
|
||||
return n * n;
|
||||
}
|
||||
if (a)
|
||||
return b;
|
||||
if (c)
|
||||
return d;
|
||||
else
|
||||
return r;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
71
test/compress/issue-1446.js
Normal file
71
test/compress/issue-1446.js
Normal file
@@ -0,0 +1,71 @@
|
||||
typeof_eq_undefined: {
|
||||
options = {
|
||||
comparisons: true
|
||||
}
|
||||
input: {
|
||||
var a = typeof b != "undefined";
|
||||
b = typeof a != "undefined";
|
||||
var c = typeof d.e !== "undefined";
|
||||
var f = "undefined" === typeof g;
|
||||
g = "undefined" === typeof f;
|
||||
var h = "undefined" == typeof i.j;
|
||||
}
|
||||
expect: {
|
||||
var a = "undefined" != typeof b;
|
||||
b = void 0 !== a;
|
||||
var c = void 0 !== d.e;
|
||||
var f = "undefined" == typeof g;
|
||||
g = void 0 === f;
|
||||
var h = void 0 === i.j;
|
||||
}
|
||||
}
|
||||
|
||||
typeof_eq_undefined_ie8: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
screw_ie8: false
|
||||
}
|
||||
input: {
|
||||
var a = typeof b != "undefined";
|
||||
b = typeof a != "undefined";
|
||||
var c = typeof d.e !== "undefined";
|
||||
var f = "undefined" === typeof g;
|
||||
g = "undefined" === typeof f;
|
||||
var h = "undefined" == typeof i.j;
|
||||
}
|
||||
expect: {
|
||||
var a = "undefined" != typeof b;
|
||||
b = void 0 !== a;
|
||||
var c = "undefined" != typeof d.e;
|
||||
var f = "undefined" == typeof g;
|
||||
g = void 0 === f;
|
||||
var h = "undefined" == typeof i.j;
|
||||
}
|
||||
}
|
||||
|
||||
undefined_redefined: {
|
||||
options = {
|
||||
comparisons: true
|
||||
}
|
||||
input: {
|
||||
function f(undefined) {
|
||||
var n = 1;
|
||||
return typeof n == "undefined";
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(undefined){var n=1;return void 0===n}"
|
||||
}
|
||||
|
||||
undefined_redefined_mangle: {
|
||||
options = {
|
||||
comparisons: true
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
function f(undefined) {
|
||||
var n = 1;
|
||||
return typeof n == "undefined";
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(n){var r=1;return void 0===r}"
|
||||
}
|
||||
45
test/compress/issue-1447.js
Normal file
45
test/compress/issue-1447.js
Normal file
@@ -0,0 +1,45 @@
|
||||
else_with_empty_block: {
|
||||
options = {}
|
||||
input: {
|
||||
if (x)
|
||||
yes();
|
||||
else {
|
||||
}
|
||||
}
|
||||
expect_exact: "if(x)yes();"
|
||||
}
|
||||
|
||||
else_with_empty_statement: {
|
||||
options = {}
|
||||
input: {
|
||||
if (x)
|
||||
yes();
|
||||
else
|
||||
;
|
||||
}
|
||||
expect_exact: "if(x)yes();"
|
||||
}
|
||||
|
||||
conditional_false_stray_else_in_loop: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
comparisons : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
loops : true,
|
||||
side_effects : true,
|
||||
dead_code : true,
|
||||
hoist_vars : true,
|
||||
join_vars : true,
|
||||
if_return : true,
|
||||
cascade : true,
|
||||
conditionals : false,
|
||||
}
|
||||
input: {
|
||||
for (var i = 1; i <= 4; ++i) {
|
||||
if (i <= 2) continue;
|
||||
console.log(i);
|
||||
}
|
||||
}
|
||||
expect_exact: "for(var i=1;i<=4;++i)if(!(i<=2))console.log(i);"
|
||||
}
|
||||
34
test/compress/issue-203.js
Normal file
34
test/compress/issue-203.js
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
compress_new_function: {
|
||||
options = {
|
||||
unsafe: true
|
||||
}
|
||||
input: {
|
||||
new Function("aa, bb", 'return aa;');
|
||||
}
|
||||
expect: {
|
||||
Function("a", "b", "return a");
|
||||
}
|
||||
}
|
||||
|
||||
compress_new_function_with_destruct: {
|
||||
options = {
|
||||
unsafe: true,
|
||||
ecma: 6
|
||||
}
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
new Function("aa, [bb]", 'return aa;');
|
||||
new Function("aa, {bb}", 'return aa;');
|
||||
new Function("[[aa]], [{bb}]", 'return aa;');
|
||||
}
|
||||
expect: {
|
||||
Function("a", "[b]", "return a");
|
||||
Function("a", "{bb}", "return a");
|
||||
Function("[[a]]", "[{bb}]", 'return a');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
70
test/compress/issue-208.js
Normal file
70
test/compress/issue-208.js
Normal file
@@ -0,0 +1,70 @@
|
||||
do_not_update_lhs: {
|
||||
options = {
|
||||
global_defs: { DEBUG: 0 }
|
||||
}
|
||||
input: {
|
||||
DEBUG++;
|
||||
DEBUG += 1;
|
||||
DEBUG = 1;
|
||||
}
|
||||
expect: {
|
||||
DEBUG++;
|
||||
DEBUG += 1;
|
||||
DEBUG = 1;
|
||||
}
|
||||
}
|
||||
|
||||
do_update_rhs: {
|
||||
options = {
|
||||
global_defs: { DEBUG: 0 }
|
||||
}
|
||||
input: {
|
||||
MY_DEBUG = DEBUG;
|
||||
MY_DEBUG += DEBUG;
|
||||
}
|
||||
expect: {
|
||||
MY_DEBUG = 0;
|
||||
MY_DEBUG += 0;
|
||||
}
|
||||
}
|
||||
|
||||
mixed: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
global_defs: {
|
||||
DEBUG: 0,
|
||||
ENV: 1,
|
||||
FOO: 2,
|
||||
}
|
||||
}
|
||||
input: {
|
||||
const ENV = 3;
|
||||
var FOO = 4;
|
||||
f(ENV * 10);
|
||||
--FOO;
|
||||
DEBUG = 1;
|
||||
DEBUG++;
|
||||
DEBUG += 1;
|
||||
f(DEBUG);
|
||||
x = DEBUG;
|
||||
}
|
||||
expect: {
|
||||
const ENV = 3;
|
||||
var FOO = 4;
|
||||
f(10);
|
||||
--FOO;
|
||||
DEBUG = 1;
|
||||
DEBUG++;
|
||||
DEBUG += 1;
|
||||
f(0);
|
||||
x = 0;
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,14]',
|
||||
'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]',
|
||||
'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]',
|
||||
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]',
|
||||
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:46,8]',
|
||||
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:47,8]',
|
||||
]
|
||||
}
|
||||
11
test/compress/issue-267.js
Normal file
11
test/compress/issue-267.js
Normal file
@@ -0,0 +1,11 @@
|
||||
issue_267: {
|
||||
options = { comparisons: true };
|
||||
input: {
|
||||
x = a % b / b * c * 2;
|
||||
x = a % b * 2
|
||||
}
|
||||
expect: {
|
||||
x = a % b / b * c * 2;
|
||||
x = a % b * 2;
|
||||
}
|
||||
}
|
||||
66
test/compress/issue-269.js
Normal file
66
test/compress/issue-269.js
Normal file
@@ -0,0 +1,66 @@
|
||||
issue_269_1: {
|
||||
options = {unsafe: true};
|
||||
input: {
|
||||
f(
|
||||
String(x),
|
||||
Number(x),
|
||||
Boolean(x),
|
||||
|
||||
String(),
|
||||
Number(),
|
||||
Boolean()
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
f(
|
||||
x + '', +x, !!x,
|
||||
'', 0, false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
issue_269_dangers: {
|
||||
options = {unsafe: true};
|
||||
input: {
|
||||
f(
|
||||
String(x, x),
|
||||
Number(x, x),
|
||||
Boolean(x, x)
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
f(String(x, x), Number(x, x), Boolean(x, x));
|
||||
}
|
||||
}
|
||||
|
||||
issue_269_in_scope: {
|
||||
options = {unsafe: true};
|
||||
input: {
|
||||
var String, Number, Boolean;
|
||||
f(
|
||||
String(x),
|
||||
Number(x, x),
|
||||
Boolean(x)
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var String, Number, Boolean;
|
||||
f(String(x), Number(x, x), Boolean(x));
|
||||
}
|
||||
}
|
||||
|
||||
strings_concat: {
|
||||
options = {unsafe: true};
|
||||
input: {
|
||||
f(
|
||||
String(x + 'str'),
|
||||
String('str' + x)
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
f(
|
||||
x + 'str',
|
||||
'str' + x
|
||||
);
|
||||
}
|
||||
}
|
||||
25
test/compress/issue-597.js
Normal file
25
test/compress/issue-597.js
Normal file
@@ -0,0 +1,25 @@
|
||||
NaN_and_Infinity_must_have_parens: {
|
||||
options = {};
|
||||
input: {
|
||||
Infinity.toString();
|
||||
NaN.toString();
|
||||
}
|
||||
expect: {
|
||||
(1/0).toString();
|
||||
NaN.toString(); // transformation to 0/0 dropped
|
||||
}
|
||||
}
|
||||
|
||||
NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: {
|
||||
options = {};
|
||||
input: {
|
||||
var Infinity, NaN;
|
||||
Infinity.toString();
|
||||
NaN.toString();
|
||||
}
|
||||
expect: {
|
||||
var Infinity, NaN;
|
||||
Infinity.toString();
|
||||
NaN.toString();
|
||||
}
|
||||
}
|
||||
21
test/compress/issue-611.js
Normal file
21
test/compress/issue-611.js
Normal file
@@ -0,0 +1,21 @@
|
||||
issue_611: {
|
||||
options = {
|
||||
sequences: true,
|
||||
side_effects: true
|
||||
};
|
||||
input: {
|
||||
define(function() {
|
||||
function fn() {}
|
||||
if (fn()) {
|
||||
fn();
|
||||
return void 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
define(function() {
|
||||
function fn(){}
|
||||
if (fn()) return void fn();
|
||||
});
|
||||
}
|
||||
}
|
||||
22
test/compress/issue-637.js
Normal file
22
test/compress/issue-637.js
Normal file
@@ -0,0 +1,22 @@
|
||||
wrongly_optimized: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
booleans: true,
|
||||
evaluate: true
|
||||
};
|
||||
input: {
|
||||
function func() {
|
||||
foo();
|
||||
}
|
||||
if (func() || true) {
|
||||
bar();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function func() {
|
||||
foo();
|
||||
}
|
||||
// TODO: optimize to `func(), bar()`
|
||||
(func(), 0) || bar();
|
||||
}
|
||||
}
|
||||
37
test/compress/issue-747.js
Normal file
37
test/compress/issue-747.js
Normal file
@@ -0,0 +1,37 @@
|
||||
dont_reuse_prop: {
|
||||
mangle_props = {
|
||||
regex: /asd/
|
||||
};
|
||||
|
||||
input: {
|
||||
var obj = {};
|
||||
obj.a = 123;
|
||||
obj.asd = 256;
|
||||
console.log(obj.a);
|
||||
}
|
||||
expect: {
|
||||
var obj = {};
|
||||
obj.a = 123;
|
||||
obj.b = 256;
|
||||
console.log(obj.a);
|
||||
}
|
||||
}
|
||||
|
||||
unmangleable_props_should_always_be_reserved: {
|
||||
mangle_props = {
|
||||
regex: /asd/
|
||||
};
|
||||
|
||||
input: {
|
||||
var obj = {};
|
||||
obj.asd = 256;
|
||||
obj.a = 123;
|
||||
console.log(obj.a);
|
||||
}
|
||||
expect: {
|
||||
var obj = {};
|
||||
obj.b = 256;
|
||||
obj.a = 123;
|
||||
console.log(obj.a);
|
||||
}
|
||||
}
|
||||
29
test/compress/issue-751.js
Normal file
29
test/compress/issue-751.js
Normal file
@@ -0,0 +1,29 @@
|
||||
negate_booleans_1: {
|
||||
options = {
|
||||
comparisons: true
|
||||
};
|
||||
input: {
|
||||
var a = !a || !b || !c || !d || !e || !f;
|
||||
}
|
||||
expect: {
|
||||
var a = !(a && b && c && d && e && f);
|
||||
}
|
||||
}
|
||||
|
||||
negate_booleans_2: {
|
||||
options = {
|
||||
comparisons: true
|
||||
};
|
||||
input: {
|
||||
var match = !x && // should not touch this one
|
||||
(!z || c) &&
|
||||
(!k || d) &&
|
||||
the_stuff();
|
||||
}
|
||||
expect: {
|
||||
var match = !x &&
|
||||
(!z || c) &&
|
||||
(!k || d) &&
|
||||
the_stuff();
|
||||
}
|
||||
}
|
||||
27
test/compress/issue-782.js
Normal file
27
test/compress/issue-782.js
Normal file
@@ -0,0 +1,27 @@
|
||||
remove_redundant_sequence_items: {
|
||||
options = { side_effects: true };
|
||||
input: {
|
||||
(0, 1, eval)();
|
||||
(0, 1, logThis)();
|
||||
(0, 1, _decorators.logThis)();
|
||||
}
|
||||
expect: {
|
||||
(0, eval)();
|
||||
logThis();
|
||||
(0, _decorators.logThis)();
|
||||
}
|
||||
}
|
||||
|
||||
dont_remove_this_binding_sequence: {
|
||||
options = { side_effects: true };
|
||||
input: {
|
||||
(0, eval)();
|
||||
(0, logThis)();
|
||||
(0, _decorators.logThis)();
|
||||
}
|
||||
expect: {
|
||||
(0, eval)();
|
||||
logThis();
|
||||
(0, _decorators.logThis)();
|
||||
}
|
||||
}
|
||||
32
test/compress/issue-892.js
Normal file
32
test/compress/issue-892.js
Normal file
@@ -0,0 +1,32 @@
|
||||
dont_mangle_arguments: {
|
||||
mangle = {
|
||||
};
|
||||
options = {
|
||||
sequences : true,
|
||||
properties : true,
|
||||
dead_code : true,
|
||||
drop_debugger : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
loops : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
keep_fargs : true,
|
||||
keep_fnames : false,
|
||||
hoist_vars : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
side_effects : true,
|
||||
negate_iife : false
|
||||
};
|
||||
input: {
|
||||
(function(){
|
||||
var arguments = arguments, not_arguments = 9;
|
||||
console.log(not_arguments, arguments);
|
||||
})(5,6,7);
|
||||
}
|
||||
expect_exact: "(function(){var arguments=arguments,o=9;console.log(o,arguments)})(5,6,7);"
|
||||
}
|
||||
20
test/compress/issue-913.js
Normal file
20
test/compress/issue-913.js
Normal file
@@ -0,0 +1,20 @@
|
||||
keep_var_for_in: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
unused: true
|
||||
};
|
||||
input: {
|
||||
(function(obj){
|
||||
var foo = 5;
|
||||
for (var i in obj)
|
||||
return foo;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(obj){
|
||||
var i, foo = 5;
|
||||
for (i in obj)
|
||||
return foo;
|
||||
})();
|
||||
}
|
||||
}
|
||||
9
test/compress/issue-926.js
Normal file
9
test/compress/issue-926.js
Normal file
@@ -0,0 +1,9 @@
|
||||
template_strings: {
|
||||
input: {
|
||||
foo(
|
||||
`<span>${contents}</span>`,
|
||||
`<a href="${url}">${text}</a>`
|
||||
);
|
||||
}
|
||||
expect_exact: "foo(`<span>${contents}</span>`,`<a href=\"${url}\">${text}</a>`);"
|
||||
}
|
||||
96
test/compress/issue-973.js
Normal file
96
test/compress/issue-973.js
Normal file
@@ -0,0 +1,96 @@
|
||||
this_binding_conditionals: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
(1 && a)();
|
||||
(0 || a)();
|
||||
(0 || 1 && a)();
|
||||
(1 ? a : 0)();
|
||||
|
||||
(1 && a.b)();
|
||||
(0 || a.b)();
|
||||
(0 || 1 && a.b)();
|
||||
(1 ? a.b : 0)();
|
||||
|
||||
(1 && a[b])();
|
||||
(0 || a[b])();
|
||||
(0 || 1 && a[b])();
|
||||
(1 ? a[b] : 0)();
|
||||
|
||||
(1 && eval)();
|
||||
(0 || eval)();
|
||||
(0 || 1 && eval)();
|
||||
(1 ? eval : 0)();
|
||||
}
|
||||
expect: {
|
||||
a();
|
||||
a();
|
||||
a();
|
||||
a();
|
||||
|
||||
(0, a.b)();
|
||||
(0, a.b)();
|
||||
(0, a.b)();
|
||||
(0, a.b)();
|
||||
|
||||
(0, a[b])();
|
||||
(0, a[b])();
|
||||
(0, a[b])();
|
||||
(0, a[b])();
|
||||
|
||||
(0, eval)();
|
||||
(0, eval)();
|
||||
(0, eval)();
|
||||
(0, eval)();
|
||||
}
|
||||
}
|
||||
|
||||
this_binding_collapse_vars: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
};
|
||||
input: {
|
||||
var c = a; c();
|
||||
var d = a.b; d();
|
||||
var e = eval; e();
|
||||
}
|
||||
expect: {
|
||||
a();
|
||||
(0, a.b)();
|
||||
(0, eval)();
|
||||
}
|
||||
}
|
||||
|
||||
this_binding_side_effects: {
|
||||
options = {
|
||||
side_effects : true
|
||||
};
|
||||
input: {
|
||||
(function (foo) {
|
||||
(0, foo)();
|
||||
(0, foo.bar)();
|
||||
(0, eval)('console.log(foo);');
|
||||
}());
|
||||
(function (foo) {
|
||||
var eval = console;
|
||||
(0, foo)();
|
||||
(0, foo.bar)();
|
||||
(0, eval)('console.log(foo);');
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
(function (foo) {
|
||||
foo();
|
||||
(0, foo.bar)();
|
||||
(0, eval)('console.log(foo);');
|
||||
}());
|
||||
(function (foo) {
|
||||
var eval = console;
|
||||
foo();
|
||||
(0, foo.bar)();
|
||||
(0, eval)('console.log(foo);');
|
||||
}());
|
||||
}
|
||||
}
|
||||
88
test/compress/issue-976.js
Normal file
88
test/compress/issue-976.js
Normal file
@@ -0,0 +1,88 @@
|
||||
eval_collapse_vars: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:false, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
};
|
||||
input: {
|
||||
function f1() {
|
||||
var e = 7;
|
||||
var s = "abcdef";
|
||||
var i = 2;
|
||||
var eval = console.log.bind(console);
|
||||
var x = s.charAt(i++);
|
||||
var y = s.charAt(i++);
|
||||
var z = s.charAt(i++);
|
||||
eval(x, y, z, e);
|
||||
}
|
||||
function p1() { var a = foo(), b = bar(), eval = baz(); return a + b + eval; }
|
||||
function p2() { var a = foo(), b = bar(), eval = baz; return a + b + eval(); }
|
||||
(function f2(eval) {
|
||||
var a = 2;
|
||||
console.log(a - 5);
|
||||
eval("console.log(a);");
|
||||
})(eval);
|
||||
}
|
||||
expect: {
|
||||
function f1() {
|
||||
var e = 7,
|
||||
s = "abcdef",
|
||||
i = 2,
|
||||
eval = console.log.bind(console),
|
||||
x = s.charAt(i++),
|
||||
y = s.charAt(i++),
|
||||
z = s.charAt(i++);
|
||||
eval(x, y, z, e);
|
||||
}
|
||||
function p1() { return foo() + bar() + baz(); }
|
||||
function p2() { var a = foo(), b = bar(), eval = baz; return a + b + eval(); }
|
||||
(function f2(eval) {
|
||||
var a = 2;
|
||||
console.log(a - 5);
|
||||
eval("console.log(a);");
|
||||
})(eval);
|
||||
}
|
||||
}
|
||||
|
||||
eval_unused: {
|
||||
options = { unused: true, keep_fargs: false };
|
||||
input: {
|
||||
function f1(a, eval, c, d, e) {
|
||||
return a('c') + eval;
|
||||
}
|
||||
function f2(a, b, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
function f3(a, eval, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1(a, eval) {
|
||||
return a('c') + eval;
|
||||
}
|
||||
function f2(a, b, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
function f3(a, eval, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eval_mangle: {
|
||||
mangle = {
|
||||
};
|
||||
input: {
|
||||
function f1(a, eval, c, d, e) {
|
||||
return a('c') + eval;
|
||||
}
|
||||
function f2(a, b, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
function f3(a, eval, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f1(n,c,e,a,f){return n("c")+c}function f2(a,b,c,d,e){return a+eval("c")}function f3(a,eval,c,d,e){return a+eval("c")}'
|
||||
}
|
||||
89
test/compress/issue-979.js
Normal file
89
test/compress/issue-979.js
Normal file
@@ -0,0 +1,89 @@
|
||||
issue979_reported: {
|
||||
options = {
|
||||
sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
if (a == 1 || b == 2) {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
function f2() {
|
||||
if (!(a == 1 || b == 2)) {
|
||||
}
|
||||
else {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1() {
|
||||
1!=a&&2!=b||foo();
|
||||
}
|
||||
function f2() {
|
||||
1!=a&&2!=b||foo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue979_test_negated_is_best: {
|
||||
options = {
|
||||
sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
}
|
||||
input: {
|
||||
function f3() {
|
||||
if (a == 1 | b == 2) {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
function f4() {
|
||||
if (!(a == 1 | b == 2)) {
|
||||
}
|
||||
else {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
function f5() {
|
||||
if (a == 1 && b == 2) {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
function f6() {
|
||||
if (!(a == 1 && b == 2)) {
|
||||
}
|
||||
else {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
function f7() {
|
||||
if (a == 1 || b == 2) {
|
||||
foo();
|
||||
}
|
||||
else {
|
||||
return bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f3() {
|
||||
1==a|2==b&&foo();
|
||||
}
|
||||
function f4() {
|
||||
1==a|2==b&&foo();
|
||||
}
|
||||
function f5() {
|
||||
1==a&&2==b&&foo();
|
||||
}
|
||||
function f6() {
|
||||
1!=a||2!=b||foo();
|
||||
}
|
||||
function f7() {
|
||||
if(1!=a&&2!=b)return bar();foo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
40
test/compress/join-vars.js
Normal file
40
test/compress/join-vars.js
Normal file
@@ -0,0 +1,40 @@
|
||||
only_vars: {
|
||||
options = { join_vars: true };
|
||||
input: {
|
||||
let netmaskBinary = '';
|
||||
for (let i = 0; i < netmaskBits; ++i) {
|
||||
netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
let netmaskBinary = '';
|
||||
for (let i = 0; i < netmaskBits; ++i) netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
|
||||
issue_1079_with_vars: {
|
||||
options = { join_vars: true };
|
||||
input: {
|
||||
var netmaskBinary = '';
|
||||
for (var i = 0; i < netmaskBits; ++i) {
|
||||
netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (var netmaskBinary = '', i = 0; i < netmaskBits; ++i) netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
|
||||
issue_1079_with_mixed: {
|
||||
options = { join_vars: true };
|
||||
input: {
|
||||
var netmaskBinary = '';
|
||||
for (let i = 0; i < netmaskBits; ++i) {
|
||||
netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var netmaskBinary = ''
|
||||
for (let i = 0; i < netmaskBits; ++i) netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
@@ -121,3 +121,98 @@ drop_if_else_break_4: {
|
||||
for (; bar() && (x(), y(), foo());) baz(), z(), k();
|
||||
}
|
||||
}
|
||||
|
||||
parse_do_while_with_semicolon: {
|
||||
options = { loops: false };
|
||||
input: {
|
||||
do {
|
||||
x();
|
||||
} while (false);y()
|
||||
}
|
||||
expect: {
|
||||
do x(); while (false);y();
|
||||
}
|
||||
}
|
||||
|
||||
parse_do_while_without_semicolon: {
|
||||
options = { loops: false };
|
||||
input: {
|
||||
do {
|
||||
x();
|
||||
} while (false)y()
|
||||
}
|
||||
expect: {
|
||||
do x(); while (false);y();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
keep_collapse_const_in_own_block_scope: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
loops: true
|
||||
}
|
||||
input: {
|
||||
var i=2;
|
||||
const c=5;
|
||||
while(i--)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var i=2;
|
||||
const c=5;
|
||||
for(;i--;)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
}
|
||||
|
||||
keep_collapse_const_in_own_block_scope_2: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
loops: true
|
||||
}
|
||||
input: {
|
||||
const c=5;
|
||||
var i=2; // Moves to loop, while it did not in previous test
|
||||
while(i--)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
const c=5;
|
||||
for(var i=2;i--;)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
}
|
||||
|
||||
evaluate: {
|
||||
options = {
|
||||
loops: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
};
|
||||
input: {
|
||||
while (true) {
|
||||
a();
|
||||
}
|
||||
while (false) {
|
||||
b();
|
||||
}
|
||||
do {
|
||||
c();
|
||||
} while (true);
|
||||
do {
|
||||
d();
|
||||
} while (false);
|
||||
}
|
||||
expect: {
|
||||
for(;;)
|
||||
a();
|
||||
for(;;)
|
||||
c();
|
||||
d();
|
||||
}
|
||||
}
|
||||
|
||||
28
test/compress/max_line_len.js
Normal file
28
test/compress/max_line_len.js
Normal file
@@ -0,0 +1,28 @@
|
||||
too_short: {
|
||||
beautify = {
|
||||
max_line_len: 10,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return { c: 42, d: a(), e: "foo"};
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f(a){\nreturn{\nc:42,\nd:a(),\ne:"foo"}}'
|
||||
expect_warnings: [
|
||||
"WARN: Output exceeds 10 characters"
|
||||
]
|
||||
}
|
||||
|
||||
just_enough: {
|
||||
beautify = {
|
||||
max_line_len: 14,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return { c: 42, d: a(), e: "foo"};
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f(a){\nreturn{c:42,\nd:a(),e:"foo"}\n}'
|
||||
expect_warnings: [
|
||||
]
|
||||
}
|
||||
322
test/compress/negate-iife.js
Normal file
322
test/compress/negate-iife.js
Normal file
@@ -0,0 +1,322 @@
|
||||
negate_iife_1: {
|
||||
options = {
|
||||
negate_iife: true
|
||||
};
|
||||
input: {
|
||||
(function(){ stuff() })();
|
||||
}
|
||||
expect: {
|
||||
!function(){ stuff() }();
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_1_off: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
};
|
||||
input: {
|
||||
(function(){ stuff() })();
|
||||
}
|
||||
expect_exact: '(function(){stuff()})();'
|
||||
}
|
||||
|
||||
negate_iife_2: {
|
||||
options = {
|
||||
negate_iife: true
|
||||
};
|
||||
input: {
|
||||
(function(){ return {} })().x = 10; // should not transform this one
|
||||
}
|
||||
expect: {
|
||||
(function(){ return {} })().x = 10;
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_3: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
conditionals: true
|
||||
};
|
||||
input: {
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
}
|
||||
expect: {
|
||||
!function(){ return true }() ? console.log(false) : console.log(true);
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_3_off: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
conditionals: true,
|
||||
};
|
||||
input: {
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
}
|
||||
expect: {
|
||||
!function(){ return true }() ? console.log(false) : console.log(true);
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_4: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
conditionals: true,
|
||||
sequences: true
|
||||
};
|
||||
input: {
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
(function(){
|
||||
console.log("something");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
!function(){ return true }() ? console.log(false) : console.log(true), function(){
|
||||
console.log("something");
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
sequence_off: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
conditionals: true,
|
||||
sequences: true,
|
||||
passes: 2,
|
||||
};
|
||||
input: {
|
||||
function f() {
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
(function(){
|
||||
console.log("something");
|
||||
})();
|
||||
}
|
||||
function g() {
|
||||
(function(){
|
||||
console.log("something");
|
||||
})();
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
!function(){ return true }() ? console.log(false) : console.log(true), function(){
|
||||
console.log("something");
|
||||
}();
|
||||
}
|
||||
function g() {
|
||||
(function(){
|
||||
console.log("something");
|
||||
})(), function(){ return true }() ? console.log(true) : console.log(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_5: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
input: {
|
||||
if ((function(){ return true })()) {
|
||||
foo(true);
|
||||
} else {
|
||||
bar(false);
|
||||
}
|
||||
(function(){
|
||||
console.log("something");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
!function(){ return true }() ? bar(false) : foo(true), function(){
|
||||
console.log("something");
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_5_off: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
input: {
|
||||
if ((function(){ return true })()) {
|
||||
foo(true);
|
||||
} else {
|
||||
bar(false);
|
||||
}
|
||||
(function(){
|
||||
console.log("something");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
!function(){ return true }() ? bar(false) : foo(true), function(){
|
||||
console.log("something");
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_nested: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
input: {
|
||||
function Foo(f) {
|
||||
this.f = f;
|
||||
}
|
||||
new Foo(function() {
|
||||
(function(x) {
|
||||
(function(y) {
|
||||
console.log(y);
|
||||
})(x);
|
||||
})(7);
|
||||
}).f();
|
||||
}
|
||||
expect: {
|
||||
function Foo(f) {
|
||||
this.f = f;
|
||||
}
|
||||
new Foo(function() {
|
||||
!function(x) {
|
||||
!function(y) {
|
||||
console.log(y);
|
||||
}(x);
|
||||
}(7);
|
||||
}).f();
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_nested_off: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
input: {
|
||||
function Foo(f) {
|
||||
this.f = f;
|
||||
}
|
||||
new Foo(function() {
|
||||
(function(x) {
|
||||
(function(y) {
|
||||
console.log(y);
|
||||
})(x);
|
||||
})(7);
|
||||
}).f();
|
||||
}
|
||||
expect: {
|
||||
function Foo(f) {
|
||||
this.f = f;
|
||||
}
|
||||
new Foo(function() {
|
||||
(function(x) {
|
||||
(function(y) {
|
||||
console.log(y);
|
||||
})(x);
|
||||
})(7);
|
||||
}).f();
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_issue_1073: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
input: {
|
||||
new (function(a) {
|
||||
return function Foo() {
|
||||
this.x = a;
|
||||
console.log(this);
|
||||
};
|
||||
}(7))();
|
||||
}
|
||||
expect: {
|
||||
new (function(a) {
|
||||
return function Foo() {
|
||||
this.x = a,
|
||||
console.log(this);
|
||||
};
|
||||
}(7))();
|
||||
}
|
||||
}
|
||||
|
||||
issue_1254_negate_iife_false: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
return function() {
|
||||
console.log('test')
|
||||
};
|
||||
})()();
|
||||
}
|
||||
expect_exact: '(function(){return function(){console.log("test")}})()();'
|
||||
}
|
||||
|
||||
issue_1254_negate_iife_true: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
return function() {
|
||||
console.log('test')
|
||||
};
|
||||
})()();
|
||||
}
|
||||
expect_exact: '!function(){return function(){console.log("test")}}()();'
|
||||
}
|
||||
|
||||
issue_1254_negate_iife_nested: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
return function() {
|
||||
console.log('test')
|
||||
};
|
||||
})()()()()();
|
||||
}
|
||||
expect_exact: '!function(){return function(){console.log("test")}}()()()()();'
|
||||
}
|
||||
|
||||
issue_1288: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
conditionals: true,
|
||||
};
|
||||
input: {
|
||||
if (w) ;
|
||||
else {
|
||||
(function f() {})();
|
||||
}
|
||||
if (!x) {
|
||||
(function() {
|
||||
x = {};
|
||||
})();
|
||||
}
|
||||
if (y)
|
||||
(function() {})();
|
||||
else
|
||||
(function(z) {
|
||||
return z;
|
||||
})(0);
|
||||
}
|
||||
expect: {
|
||||
w || function f() {}();
|
||||
x || function() {
|
||||
x = {};
|
||||
}();
|
||||
y ? function() {}() : function(z) {
|
||||
return z;
|
||||
}(0);
|
||||
}
|
||||
}
|
||||
100
test/compress/new.js
Normal file
100
test/compress/new.js
Normal file
@@ -0,0 +1,100 @@
|
||||
new_statement: {
|
||||
input: {
|
||||
new x(1);
|
||||
new x(1)(2);
|
||||
new x(1)(2)(3);
|
||||
new new x(1);
|
||||
new new x(1)(2);
|
||||
new (new x(1))(2);
|
||||
(new new x(1))(2);
|
||||
}
|
||||
expect_exact: "new x(1);new x(1)(2);new x(1)(2)(3);new new x(1);new new x(1)(2);new new x(1)(2);(new new x(1))(2);"
|
||||
}
|
||||
|
||||
new_statements_2: {
|
||||
input: {
|
||||
new x;
|
||||
new new x;
|
||||
new new new x;
|
||||
new true;
|
||||
new (0);
|
||||
new (!0);
|
||||
new (bar = function(foo) {this.foo=foo;})(123);
|
||||
new (bar = function(foo) {this.foo=foo;})();
|
||||
}
|
||||
expect_exact: "new x;new(new x);new(new(new x));new true;new 0;new(!0);new(bar=function(foo){this.foo=foo})(123);new(bar=function(foo){this.foo=foo});"
|
||||
}
|
||||
|
||||
new_statements_3: {
|
||||
input: {
|
||||
new (function(foo){this.foo=foo;})(1);
|
||||
new (function(foo){this.foo=foo;})();
|
||||
new (function test(foo){this.foo=foo;})(1);
|
||||
new (function test(foo){this.foo=foo;})();
|
||||
}
|
||||
expect_exact: "new function(foo){this.foo=foo}(1);new function(foo){this.foo=foo};new function test(foo){this.foo=foo}(1);new function test(foo){this.foo=foo};"
|
||||
}
|
||||
|
||||
new_with_rewritten_true_value: {
|
||||
options = { booleans: true }
|
||||
input: {
|
||||
new true;
|
||||
}
|
||||
expect_exact: "new(!0);"
|
||||
}
|
||||
|
||||
new_with_many_parameters: {
|
||||
input: {
|
||||
new foo.bar("baz");
|
||||
new x(/123/, 456);
|
||||
}
|
||||
expect_exact: 'new foo.bar("baz");new x(/123/,456);'
|
||||
}
|
||||
|
||||
new_constructor_with_unary_arguments: {
|
||||
input: {
|
||||
new x();
|
||||
new x(-1);
|
||||
new x(-1, -2);
|
||||
new x(void 1, +2, -3, ~4, !5, --a, ++b, c--, d++, typeof e, delete f);
|
||||
new (-1); // should parse despite being invalid at runtime.
|
||||
new (-1)(); // should parse despite being invalid at runtime.
|
||||
new (-1)(-2); // should parse despite being invalid at runtime.
|
||||
}
|
||||
expect_exact: "new x;new x(-1);new x(-1,-2);new x(void 1,+2,-3,~4,!5,--a,++b,c--,d++,typeof e,delete f);new(-1);new(-1);new(-1)(-2);"
|
||||
}
|
||||
|
||||
call_with_unary_arguments: {
|
||||
input: {
|
||||
x();
|
||||
x(-1);
|
||||
x(-1, -2);
|
||||
x(void 1, +2, -3, ~4, !5, --a, ++b, c--, d++, typeof e, delete f);
|
||||
(-1)(); // should parse despite being invalid at runtime.
|
||||
(-1)(-2); // should parse despite being invalid at runtime.
|
||||
}
|
||||
expect_exact: "x();x(-1);x(-1,-2);x(void 1,+2,-3,~4,!5,--a,++b,c--,d++,typeof e,delete f);(-1)();(-1)(-2);"
|
||||
}
|
||||
|
||||
new_with_unary_prefix: {
|
||||
input: {
|
||||
var bar = (+new Date()).toString(32);
|
||||
}
|
||||
expect_exact: 'var bar=(+new Date).toString(32);';
|
||||
}
|
||||
|
||||
new_with_assignement_expression: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
new x(a = 5 * 2, b = [1, 2, 3], c = {a: "a", b: "b", cd: "c" + "d"});
|
||||
new y([a, b] = [3, 4]);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
new x(a = 10, b = [1, 2, 3], c = {a: "a", b: "b", cd: "cd"});
|
||||
new y([a, b] = [3, 4]);
|
||||
}
|
||||
}
|
||||
19
test/compress/numbers.js
Normal file
19
test/compress/numbers.js
Normal file
@@ -0,0 +1,19 @@
|
||||
hex_numbers_in_parentheses_for_prototype_functions: {
|
||||
input: {
|
||||
(-2);
|
||||
(-2).toFixed(0);
|
||||
|
||||
(2);
|
||||
(2).toFixed(0);
|
||||
|
||||
(0.2);
|
||||
(0.2).toFixed(0);
|
||||
|
||||
(0.00000002);
|
||||
(0.00000002).toFixed(0);
|
||||
|
||||
(1000000000000000128);
|
||||
(1000000000000000128).toFixed(0);
|
||||
}
|
||||
expect_exact: "-2;(-2).toFixed(0);2;2..toFixed(0);.2;.2.toFixed(0);2e-8;2e-8.toFixed(0);0xde0b6b3a7640080;(0xde0b6b3a7640080).toFixed(0);"
|
||||
}
|
||||
510
test/compress/object.js
Normal file
510
test/compress/object.js
Normal file
@@ -0,0 +1,510 @@
|
||||
getter_setter: {
|
||||
input: {
|
||||
var get = "bar";
|
||||
var a = {
|
||||
get,
|
||||
set: "foo",
|
||||
get bar() {
|
||||
return this.get;
|
||||
},
|
||||
get 5() {
|
||||
return "five";
|
||||
},
|
||||
get 0xf55() {
|
||||
return "f five five";
|
||||
},
|
||||
get "five"() {
|
||||
return 5;
|
||||
},
|
||||
set one(value) {
|
||||
this._one = value;
|
||||
},
|
||||
set 9(value) {
|
||||
this._nine = value;
|
||||
},
|
||||
set 0b1010(value) {
|
||||
this._ten = value;
|
||||
},
|
||||
set "eleven"(value) {
|
||||
this._eleven = value;
|
||||
}
|
||||
};
|
||||
var b = {
|
||||
get() { return "gift"; },
|
||||
set: function(code) { return "Storing code " + code; }
|
||||
};
|
||||
var c = {
|
||||
["get"]: "foo",
|
||||
["set"]: "bar"
|
||||
};
|
||||
var d = {
|
||||
get: "foo",
|
||||
set: "bar"
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var get = "bar";
|
||||
var a = {
|
||||
get,
|
||||
set: "foo",
|
||||
get bar() {
|
||||
return this.get;
|
||||
},
|
||||
get 5() {
|
||||
return "five";
|
||||
},
|
||||
get 0xf55() {
|
||||
return "f five five";
|
||||
},
|
||||
get "five"() {
|
||||
return 5;
|
||||
},
|
||||
set one(value) {
|
||||
this._one = value;
|
||||
},
|
||||
set 9(value) {
|
||||
this._nine = value;
|
||||
},
|
||||
set 0b1010(value) {
|
||||
this._ten = value;
|
||||
},
|
||||
set "eleven"(value) {
|
||||
this._eleven = value;
|
||||
}
|
||||
};
|
||||
var b = {
|
||||
get() { return "gift"; },
|
||||
set: function(code) { return "Storing code " + code; }
|
||||
};
|
||||
var c = {
|
||||
["get"]: "foo",
|
||||
["set"]: "bar"
|
||||
};
|
||||
var d = {
|
||||
get: "foo",
|
||||
set: "bar"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getter_setter_mangler: {
|
||||
mangle = {}
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
function f(get,set) {
|
||||
return {
|
||||
get,
|
||||
set,
|
||||
get g(){},
|
||||
set s(n){},
|
||||
c,
|
||||
a:1,
|
||||
m(){}
|
||||
};
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(n,t){return{get:n,set:t,get g(){},set s(n){},c,a:1,m(){}}}"
|
||||
}
|
||||
|
||||
use_shorthand_opportunity: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
var foo = 123;
|
||||
var obj = {foo: foo};
|
||||
}
|
||||
expect_exact: "var foo=123;var obj={foo};"
|
||||
}
|
||||
|
||||
computed_property_names: {
|
||||
input: {
|
||||
obj({ ["x" + "x"]: 6 });
|
||||
}
|
||||
expect_exact: 'obj({["x"+"x"]:6});'
|
||||
}
|
||||
|
||||
computed_property_names_evaluated_1: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
obj({
|
||||
[1 + 1]: 2,
|
||||
["x" + "x"]: 6
|
||||
});
|
||||
}
|
||||
expect_exact: 'obj({[2]:2,["xx"]:6});'
|
||||
}
|
||||
|
||||
computed_property_names_evaluated_2: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = something();
|
||||
|
||||
var obj = {
|
||||
[foo]() {
|
||||
return "blah";
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'var foo=something();var obj={[foo](){return"blah"}};'
|
||||
}
|
||||
|
||||
shorthand_properties: {
|
||||
mangle = true;
|
||||
input: (function() {
|
||||
var prop = 1;
|
||||
const value = {prop};
|
||||
return value;
|
||||
})();
|
||||
expect: (function() {
|
||||
var n = 1;
|
||||
const r = {prop:n};
|
||||
return r;
|
||||
})();
|
||||
}
|
||||
|
||||
concise_methods: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
x = {
|
||||
foo(a, b) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
y = {
|
||||
foo([{a}]) {
|
||||
return a;
|
||||
},
|
||||
bar(){}
|
||||
}
|
||||
}
|
||||
expect_exact: "x={foo(a,b){return x}};y={foo([{a}]){return a},bar(){}};"
|
||||
}
|
||||
|
||||
concise_methods_with_computed_property: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = {
|
||||
[Symbol.iterator]() {
|
||||
return { /* stuff */ }
|
||||
},
|
||||
[1 + 2]() {
|
||||
return 3;
|
||||
},
|
||||
["1" + "4"]() {
|
||||
return 14;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var foo = {
|
||||
[Symbol.iterator]() {
|
||||
return { /* stuff */ }
|
||||
},
|
||||
[3]() {
|
||||
return 3;
|
||||
},
|
||||
["14"]() {
|
||||
return 14;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
concise_methods_with_computed_property2: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = {
|
||||
[[1]](){
|
||||
return "success";
|
||||
}
|
||||
};
|
||||
doSomething(foo[[1]]());
|
||||
}
|
||||
expect_exact: {
|
||||
'var foo={[[1]](){return"success"}};doSomething(foo[[1]]());'
|
||||
}
|
||||
}
|
||||
|
||||
concise_methods_with_various_property_names: {
|
||||
input: {
|
||||
var get = "bar";
|
||||
var a = {
|
||||
bar() {
|
||||
return this.get;
|
||||
},
|
||||
5() {
|
||||
return "five";
|
||||
},
|
||||
0xf55() {
|
||||
return "f five five";
|
||||
},
|
||||
"five"() {
|
||||
return 5;
|
||||
},
|
||||
0b1010(value) {
|
||||
this._ten = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var get = "bar";
|
||||
var a = {
|
||||
bar() {
|
||||
return this.get;
|
||||
},
|
||||
5() {
|
||||
return "five";
|
||||
},
|
||||
0xf55() {
|
||||
return "f five five";
|
||||
},
|
||||
"five"() {
|
||||
return 5;
|
||||
},
|
||||
0b1010(value) {
|
||||
this._ten = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
concise_methods_and_mangle_props: {
|
||||
mangle_props = {
|
||||
regex: /_/
|
||||
};
|
||||
input: {
|
||||
function x() {
|
||||
obj = {
|
||||
_foo() { return 1; }
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
obj = {
|
||||
a() { return 1; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
concise_generators: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
x = {
|
||||
*foo(a, b) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
y = {
|
||||
*foo([{a}]) {
|
||||
yield a;
|
||||
},
|
||||
bar(){}
|
||||
}
|
||||
}
|
||||
expect_exact: "x={*foo(a,b){return x}};y={*foo([{a}]){yield a},bar(){}};"
|
||||
}
|
||||
|
||||
concise_methods_and_keyword_names: {
|
||||
input: {
|
||||
x = {
|
||||
catch() {},
|
||||
throw() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
x={catch(){},throw(){}};
|
||||
}
|
||||
}
|
||||
|
||||
getter_setter_with_computed_value: {
|
||||
input: {
|
||||
class C {
|
||||
get ['a']() {
|
||||
return 'A';
|
||||
}
|
||||
set ['a'](value) {
|
||||
do_something(a);
|
||||
}
|
||||
}
|
||||
var x = {
|
||||
get [a.b]() {
|
||||
return 42;
|
||||
}
|
||||
};
|
||||
class MyArray extends Array {
|
||||
get [Symbol.species]() {
|
||||
return Array;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'class C{get["a"](){return"A"}set["a"](value){do_something(a)}}var x={get[a.b](){return 42}};class MyArray extends Array{get[Symbol.species](){return Array}}'
|
||||
}
|
||||
|
||||
property_with_operator_value: {
|
||||
input: {
|
||||
var foo = {
|
||||
"*": 1,
|
||||
get "*"() {
|
||||
return 2;
|
||||
},
|
||||
*"*"() {
|
||||
return 3;
|
||||
},
|
||||
"%": 1,
|
||||
get "%"() {
|
||||
return 2;
|
||||
},
|
||||
*"%"() {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
class bar {
|
||||
get "*"() {
|
||||
return 1
|
||||
}
|
||||
*"*"() {
|
||||
return 2;
|
||||
}
|
||||
get "%"() {
|
||||
return 1
|
||||
}
|
||||
*"%"() {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'var foo={"*":1,get"*"(){return 2},*"*"(){return 3},"%":1,get"%"(){return 2},*"%"(){return 3}};class bar{get"*"(){return 1}*"*"(){return 2}get"%"(){return 1}*"%"(){return 2}}'
|
||||
}
|
||||
|
||||
property_with_unprintable: {
|
||||
input: {
|
||||
var foo = {
|
||||
"\x00\x01": "foo",
|
||||
get "\x00\x01"() {
|
||||
return "bar";
|
||||
},
|
||||
set "\x00\x01"(foo) {
|
||||
save(foo);
|
||||
},
|
||||
*"\x00\x01"() {
|
||||
return "foobar";
|
||||
}
|
||||
}
|
||||
class bar {
|
||||
get "\x00\x01"() {
|
||||
return "bar"
|
||||
}
|
||||
set "\x00\x01"(foo) {
|
||||
save(foo);
|
||||
}
|
||||
*"\x00\x01"() {
|
||||
return "foobar";
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'var foo={"\\0\x01":"foo",get"\\0\x01"(){return"bar"},set"\\0\x01"(foo){save(foo)},*"\\0\x01"(){return"foobar"}};class bar{get"\\0\x01"(){return"bar"}set"\\0\x01"(foo){save(foo)}*"\\0\x01"(){return"foobar"}}'
|
||||
}
|
||||
|
||||
property_with_unprintable_ascii_only: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
var foo = {
|
||||
"\x00\x01": "foo",
|
||||
get "\x00\x01"() {
|
||||
return "bar";
|
||||
},
|
||||
set "\x00\x01"(foo) {
|
||||
save(foo);
|
||||
},
|
||||
*"\x00\x01"() {
|
||||
return "foobar";
|
||||
}
|
||||
}
|
||||
class bar {
|
||||
get "\x00\x01"() {
|
||||
return "bar"
|
||||
}
|
||||
set "\x00\x01"(foo) {
|
||||
save(foo);
|
||||
}
|
||||
*"\x00\x01"() {
|
||||
return "foobar";
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'var foo={"\\0\\x01":"foo",get"\\0\\x01"(){return"bar"},set"\\0\\x01"(foo){save(foo)},*"\\0\\x01"(){return"foobar"}};class bar{get"\\0\\x01"(){return"bar"}set"\\0\\x01"(foo){save(foo)}*"\\0\\x01"(){return"foobar"}}'
|
||||
}
|
||||
|
||||
property_with_unprintable_ascii_only_static: {
|
||||
beautify = {
|
||||
ascii_only: true
|
||||
}
|
||||
input: {
|
||||
class foo {
|
||||
static get "\x02\x03"() {
|
||||
return "bar";
|
||||
}
|
||||
static set "\x04\x05"(foo) {
|
||||
save(foo);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'class foo{static get"\\x02\\x03"(){return"bar"}static set"\\x04\\x05"(foo){save(foo)}}'
|
||||
}
|
||||
|
||||
methods_and_getters_with_keep_quoted_props_enabled: {
|
||||
beautify = {
|
||||
quote_style: 3,
|
||||
keep_quoted_props: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
a() {},
|
||||
"b"() {},
|
||||
get c() { return "c"},
|
||||
get "d"() { return "d"},
|
||||
set e(a) { doSomething(a); },
|
||||
set f(a) { doSomething(b); }
|
||||
}
|
||||
}
|
||||
expect_exact: 'var obj={a(){},"b"(){},get c(){return"c"},get"d"(){return"d"},set e(a){doSomething(a)},set f(a){doSomething(b)}};'
|
||||
}
|
||||
|
||||
allow_assignments_to_property_values: {
|
||||
input: {
|
||||
var foo = {123: foo = 123} = {foo: "456"};
|
||||
}
|
||||
expect: {
|
||||
var foo = {123: foo = 123} = {foo: "456"};
|
||||
}
|
||||
}
|
||||
|
||||
variable_as_computed_property: {
|
||||
input: {
|
||||
function getLine(header) {
|
||||
return {
|
||||
[header]: {}
|
||||
};
|
||||
}
|
||||
}
|
||||
expect_exact: "function getLine(header){return{[header]:{}}}"
|
||||
}
|
||||
168
test/compress/parameters.js
Normal file
168
test/compress/parameters.js
Normal file
@@ -0,0 +1,168 @@
|
||||
arrow_functions: {
|
||||
input: {
|
||||
(a) => b; // 1 args
|
||||
(a, b) => c; // n args
|
||||
() => b; // 0 args
|
||||
(a) => (b) => c; // func returns func returns func
|
||||
(a) => ((b) => c); // So these parens are dropped
|
||||
() => (b,c) => d; // func returns func returns func
|
||||
a=>{return b;}
|
||||
a => 'lel'; // Dropping the parens
|
||||
}
|
||||
expect_exact: "a=>b;(a,b)=>c;()=>b;a=>b=>c;a=>b=>c;()=>(b,c)=>d;a=>{return b};a=>\"lel\";"
|
||||
}
|
||||
|
||||
regression_arrow_functions_and_hoist: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
hoist_funs: true
|
||||
}
|
||||
input: {
|
||||
(a) => b;
|
||||
}
|
||||
expect_exact: "a=>b;"
|
||||
}
|
||||
|
||||
regression_assign_arrow_functions: {
|
||||
input: {
|
||||
oninstall = e => false;
|
||||
oninstall = () => false;
|
||||
}
|
||||
expect: {
|
||||
oninstall=e=>false;
|
||||
oninstall=()=>false;
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_arguments_1: {
|
||||
input: {
|
||||
(function ( a ) { });
|
||||
(function ( [ a ] ) { });
|
||||
(function ( [ a, b ] ) { });
|
||||
(function ( [ [ a ] ] ) { });
|
||||
(function ( [ [ a, b ] ] ) { });
|
||||
(function ( [ a, [ b ] ] ) { });
|
||||
(function ( [ [ b ], a ] ) { });
|
||||
|
||||
(function ( { a } ) { });
|
||||
(function ( { a, b } ) { });
|
||||
|
||||
(function ( [ { a } ] ) { });
|
||||
(function ( [ { a, b } ] ) { });
|
||||
(function ( [ a, { b } ] ) { });
|
||||
(function ( [ { b }, a ] ) { });
|
||||
|
||||
( [ a ] ) => { };
|
||||
( [ a, b ] ) => { };
|
||||
|
||||
( { a } ) => { };
|
||||
( { a, b, c, d, e } ) => { };
|
||||
|
||||
( [ a ] ) => b;
|
||||
( [ a, b ] ) => c;
|
||||
|
||||
( { a } ) => b;
|
||||
( { a, b } ) => c;
|
||||
}
|
||||
expect: {
|
||||
(function(a){});
|
||||
(function([a]){});
|
||||
(function([a,b]){});
|
||||
(function([[a]]){});
|
||||
(function([[a,b]]){});
|
||||
(function([a,[b]]){});
|
||||
(function([[b],a]){});
|
||||
|
||||
(function({a}){});
|
||||
(function({a,b}){});
|
||||
|
||||
(function([{a}]){});
|
||||
(function([{a,b}]){});
|
||||
(function([a,{b}]){});
|
||||
(function([{b},a]){});
|
||||
|
||||
([a])=>{};
|
||||
([a,b])=>{};
|
||||
|
||||
({a})=>{};
|
||||
({a,b,c,d,e})=>{};
|
||||
|
||||
([a])=>b;
|
||||
([a,b])=>c;
|
||||
|
||||
({a})=>b;
|
||||
({a,b})=>c;
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_arguments_2: {
|
||||
input: {
|
||||
(function([]) {});
|
||||
(function({}) {});
|
||||
(function([,,,,,]) {});
|
||||
(function ([a, {b: c}]) {});
|
||||
(function ([...args]) {});
|
||||
(function ({x,}) {});
|
||||
class a { *method({ [thrower()]: x } = {}) {}};
|
||||
(function(a, b, c, d, [{e: [...f]}]){})(1, 2, 3, 4, [{e: [1, 2, 3]}]);
|
||||
}
|
||||
expect: {
|
||||
(function([]) {});
|
||||
(function({}) {});
|
||||
(function([,,,,,]) {});
|
||||
(function ([a, {b: c}]) {});
|
||||
(function ([...args]) {});
|
||||
(function ({x,}) {});
|
||||
class a { *method({ [thrower()]: x } = {}) {}};
|
||||
(function(a, b, c, d, [{e: [...f]}]){})(1, 2, 3, 4, [{e: [1, 2, 3]}]);
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_arguments_3: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
function fn3({x: {y: {z: {} = 42}}}) {}
|
||||
const { cover = (function () {}), xCover = (0, function() {}) } = {};
|
||||
let { cover = (function () {}), xCover = (0, function() {}) } = {};
|
||||
var { cover = (function () {}), xCover = (0, function() {}) } = {};
|
||||
}
|
||||
expect_exact: "function fn3({x:{y:{z:{}=42}}}){}const{cover=function(){},xCover=(0,function(){})}={};let{cover=function(){},xCover=(0,function(){})}={};var{cover=function(){},xCover=(0,function(){})}={};"
|
||||
}
|
||||
|
||||
default_arguments: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
function x(a = 6) { }
|
||||
function x(a = (6 + 5)) { }
|
||||
function x({ foo } = {}, [ bar ] = [ 1 ]) { }
|
||||
}
|
||||
expect_exact: "function x(a=6){}function x(a=6+5){}function x({foo}={},[bar]=[1]){}"
|
||||
}
|
||||
|
||||
default_values_in_destructurings: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
function x({a=(4), b}) {}
|
||||
function x([b, c=(12)]) {}
|
||||
var { x = (6), y } = x;
|
||||
var [ x, y = (6) ] = x;
|
||||
}
|
||||
expect_exact: "function x({a=4,b}){}function x([b,c=12]){}var{x=6,y}=x;var[x,y=6]=x;"
|
||||
}
|
||||
|
||||
accept_duplicated_parameters_in_non_strict_without_spread_or_default_assignment: {
|
||||
input: {
|
||||
function a(b, b){}
|
||||
function b({c: test, c: test}){}
|
||||
}
|
||||
expect: {
|
||||
function a(b, b){}
|
||||
function b({c: test, c: test}){}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@ keep_properties: {
|
||||
|
||||
dot_properties: {
|
||||
options = {
|
||||
properties: true
|
||||
properties: true,
|
||||
screw_ie8: false
|
||||
};
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
@@ -26,7 +27,7 @@ dot_properties: {
|
||||
a.foo = "bar";
|
||||
a["if"] = "if";
|
||||
a["*"] = "asterisk";
|
||||
a.\u0EB3 = "unicode";
|
||||
a["\u0EB3"] = "unicode";
|
||||
a[""] = "whitespace";
|
||||
a["1_1"] = "foo";
|
||||
}
|
||||
@@ -48,7 +49,510 @@ dot_properties_es5: {
|
||||
a.foo = "bar";
|
||||
a.if = "if";
|
||||
a["*"] = "asterisk";
|
||||
a.\u0EB3 = "unicode";
|
||||
a["\u0EB3"] = "unicode";
|
||||
a[""] = "whitespace";
|
||||
}
|
||||
}
|
||||
|
||||
sub_properties: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true
|
||||
};
|
||||
input: {
|
||||
a[0] = 0;
|
||||
a["0"] = 1;
|
||||
a[3.14] = 2;
|
||||
a["3" + ".14"] = 3;
|
||||
a["i" + "f"] = 4;
|
||||
a["foo" + " bar"] = 5;
|
||||
a[0 / 0] = 6;
|
||||
a[null] = 7;
|
||||
a[undefined] = 8;
|
||||
}
|
||||
expect: {
|
||||
a[0] = 0;
|
||||
a[0] = 1;
|
||||
a[3.14] = 2;
|
||||
a[3.14] = 3;
|
||||
a.if = 4;
|
||||
a["foo bar"] = 5;
|
||||
a[NaN] = 6;
|
||||
a[null] = 7;
|
||||
a[void 0] = 8;
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_array_length: {
|
||||
options = {
|
||||
properties: true,
|
||||
unsafe: true,
|
||||
evaluate: true
|
||||
};
|
||||
input: {
|
||||
a = [1, 2, 3].length;
|
||||
a = [1, 2, 3].join()["len" + "gth"];
|
||||
a = [1, 2, b].length;
|
||||
a = [1, 2, 3].join(b).length;
|
||||
}
|
||||
expect: {
|
||||
a = 3;
|
||||
a = 5;
|
||||
a = [1, 2, b].length;
|
||||
a = [1, 2, 3].join(b).length;
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_string_length: {
|
||||
options = {
|
||||
properties: true,
|
||||
unsafe: true,
|
||||
evaluate: true
|
||||
};
|
||||
input: {
|
||||
a = "foo".length;
|
||||
a = ("foo" + "bar")["len" + "gth"];
|
||||
a = b.length;
|
||||
a = ("foo" + b).length;
|
||||
}
|
||||
expect: {
|
||||
a = 3;
|
||||
a = 6;
|
||||
a = b.length;
|
||||
a = ("foo" + b).length;
|
||||
}
|
||||
}
|
||||
|
||||
mangle_properties: {
|
||||
mangle_props = {
|
||||
ignore_quoted: false
|
||||
};
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
x = {"bar": 10};
|
||||
a.run(x.bar, a.foo);
|
||||
a['run']({color: "blue", foo: "baz"});
|
||||
}
|
||||
expect: {
|
||||
a["a"] = "bar";
|
||||
a.b = "red";
|
||||
x = {c: 10};
|
||||
a.d(x.c, a.a);
|
||||
a['d']({b: "blue", a: "baz"});
|
||||
}
|
||||
}
|
||||
|
||||
mangle_unquoted_properties: {
|
||||
options = {
|
||||
properties: false
|
||||
}
|
||||
mangle_props = {
|
||||
ignore_quoted: true,
|
||||
reserved: []
|
||||
}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
quote_style: 3,
|
||||
keep_quoted_props: true,
|
||||
}
|
||||
input: {
|
||||
a.top = 1;
|
||||
function f1() {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
a.stuff = 2;
|
||||
x = {"bar": 10, size: 7};
|
||||
a.size = 9;
|
||||
}
|
||||
function f2() {
|
||||
a.foo = "bar";
|
||||
a['color'] = "red";
|
||||
x = {bar: 10, size: 7};
|
||||
a.size = 9;
|
||||
a.stuff = 3;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
a.a = 1;
|
||||
function f1() {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
a.b = 2;
|
||||
x = {"bar": 10, c: 7};
|
||||
a.c = 9;
|
||||
}
|
||||
function f2() {
|
||||
a.foo = "bar";
|
||||
a['color'] = "red";
|
||||
x = {bar: 10, c: 7};
|
||||
a.c = 9;
|
||||
a.b = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mangle_debug: {
|
||||
mangle_props = {
|
||||
debug: ""
|
||||
};
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
}
|
||||
expect: {
|
||||
a._$foo$_ = "bar";
|
||||
x = { _$baz$_: "ban" };
|
||||
}
|
||||
}
|
||||
|
||||
mangle_debug_true: {
|
||||
mangle_props = {
|
||||
debug: true
|
||||
};
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
}
|
||||
expect: {
|
||||
a._$foo$_ = "bar";
|
||||
x = { _$baz$_: "ban" };
|
||||
}
|
||||
}
|
||||
|
||||
mangle_debug_suffix: {
|
||||
mangle_props = {
|
||||
debug: "XYZ"
|
||||
};
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
}
|
||||
expect: {
|
||||
a._$foo$XYZ_ = "bar";
|
||||
x = { _$baz$XYZ_: "ban" };
|
||||
}
|
||||
}
|
||||
|
||||
mangle_debug_suffix_ignore_quoted: {
|
||||
options = {
|
||||
properties: false
|
||||
}
|
||||
mangle_props = {
|
||||
ignore_quoted: true,
|
||||
debug: "XYZ",
|
||||
reserved: []
|
||||
}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
quote_style: 3,
|
||||
keep_quoted_props: true,
|
||||
}
|
||||
input: {
|
||||
a.top = 1;
|
||||
function f1() {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
a.stuff = 2;
|
||||
x = {"bar": 10, size: 7};
|
||||
a.size = 9;
|
||||
}
|
||||
function f2() {
|
||||
a.foo = "bar";
|
||||
a['color'] = "red";
|
||||
x = {bar: 10, size: 7};
|
||||
a.size = 9;
|
||||
a.stuff = 3;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
a._$top$XYZ_ = 1;
|
||||
function f1() {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
a._$stuff$XYZ_ = 2;
|
||||
x = {"bar": 10, _$size$XYZ_: 7};
|
||||
a._$size$XYZ_ = 9;
|
||||
}
|
||||
function f2() {
|
||||
a.foo = "bar";
|
||||
a['color'] = "red";
|
||||
x = {bar: 10, _$size$XYZ_: 7};
|
||||
a._$size$XYZ_ = 9;
|
||||
a._$stuff$XYZ_ = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
first_256_chars_as_properties: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
// Note: some of these unicode character keys are not visible on github.com
|
||||
var o = {
|
||||
"\0":0,"":1,"":2,"":3,"":4,"":5,"":6,"":7,"\b":8,
|
||||
"\t":9,"\n":10,"\v":11,"\f":12,"\r":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,"0":48,"1":49,"2":50,"3":51,"4":52,"5":53,"6":54,"7":55,
|
||||
"8":56,"9":57,":":58,";":59,"<":60,"=":61,">":62,"?":63,"@":64,A:65,
|
||||
B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,
|
||||
O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,"[":91,
|
||||
"\\":92,"]":93,"^":94,_:95,"`":96,a:97,b:98,c:99,d:100,e:101,
|
||||
f:102,g:103,h:104,i:105,j:106,k:107,l:108,m:109,n:110,o:111,p:112,
|
||||
q:113,r:114,s:115,t:116,u:117,v:118,w:119,x:120,y:121,z:122,"{":123,
|
||||
"|":124,"}":125,"~":126,"":127,"":128,"":129,"":130,"":131,
|
||||
"":132,"
":133,"":134,"":135,"":136,"":137,"":138,"":139,
|
||||
"":140,"":141,"":142,"":143,"":144,"":145,"":146,"":147,
|
||||
"":148,"":149,"":150,"":151,"":152,"":153,"":154,"":155,
|
||||
"":156,"":157,"":158,"":159," ":160,"¡":161,"¢":162,"£":163,
|
||||
"¤":164,"¥":165,"¦":166,"§":167,"¨":168,"©":169,"ª":170,"«":171,
|
||||
"¬":172,"":173,"®":174,"¯":175,"°":176,"±":177,"²":178,"³":179,
|
||||
"´":180,"µ":181,"¶":182,"·":183,"¸":184,"¹":185,"º":186,"»":187,
|
||||
"¼":188,"½":189,"¾":190,"¿":191,"À":192,"Á":193,"Â":194,"Ã":195,
|
||||
"Ä":196,"Å":197,"Æ":198,"Ç":199,"È":200,"É":201,"Ê":202,"Ë":203,
|
||||
"Ì":204,"Í":205,"Î":206,"Ï":207,"Ð":208,"Ñ":209,"Ò":210,"Ó":211,
|
||||
"Ô":212,"Õ":213,"Ö":214,"×":215,"Ø":216,"Ù":217,"Ú":218,"Û":219,
|
||||
"Ü":220,"Ý":221,"Þ":222,"ß":223,"à":224,"á":225,"â":226,"ã":227,
|
||||
"ä":228,"å":229,"æ":230,"ç":231,"è":232,"é":233,"ê":234,"ë":235,
|
||||
"ì":236,"í":237,"î":238,"ï":239,"ð":240,"ñ":241,"ò":242,"ó":243,
|
||||
"ô":244,"õ":245,"ö":246,"÷":247,"ø":248,"ù":249,"ú":250,"û":251,
|
||||
"ü":252,"ý":253,"þ":254,"ÿ":255
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
"\0":0,"\x01":1,"\x02":2,"\x03":3,"\x04":4,"\x05":5,"\x06":6,
|
||||
"\x07":7,"\b":8,"\t":9,"\n":10,"\v":11,"\f":12,"\r":13,"\x0e":14,
|
||||
"\x0f":15,"\x10":16,"\x11":17,"\x12":18,"\x13":19,"\x14":20,"\x15":21,
|
||||
"\x16":22,"\x17":23,"\x18":24,"\x19":25,"\x1a":26,"\x1b":27,"\x1c":28,
|
||||
"\x1d":29,"\x1e":30,"\x1f":31," ":32,"!":33,'"':34,"#":35,$:36,
|
||||
"%":37,"&":38,"'":39,"(":40,")":41,"*":42,"+":43,",":44,"-":45,
|
||||
".":46,"/":47,0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,
|
||||
":":58,";":59,"<":60,"=":61,">":62,"?":63,"@":64,A:65,B:66,C:67,
|
||||
D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,
|
||||
Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,"[":91,"\\":92,
|
||||
"]":93,"^":94,_:95,"`":96,a:97,b:98,c:99,d:100,e:101,f:102,g:103,
|
||||
h:104,i:105,j:106,k:107,l:108,m:109,n:110,o:111,p:112,q:113,r:114,
|
||||
s:115,t:116,u:117,v:118,w:119,x:120,y:121,z:122,"{":123,"|":124,
|
||||
"}":125,"~":126,"\x7f":127,"\x80":128,"\x81":129,"\x82":130,"\x83":131,
|
||||
"\x84":132,"\x85":133,"\x86":134,"\x87":135,"\x88":136,"\x89":137,
|
||||
"\x8a":138,"\x8b":139,"\x8c":140,"\x8d":141,"\x8e":142,"\x8f":143,
|
||||
"\x90":144,"\x91":145,"\x92":146,"\x93":147,"\x94":148,"\x95":149,
|
||||
"\x96":150,"\x97":151,"\x98":152,"\x99":153,"\x9a":154,"\x9b":155,
|
||||
"\x9c":156,"\x9d":157,"\x9e":158,"\x9f":159,"\xa0":160,"\xa1":161,
|
||||
"\xa2":162,"\xa3":163,"\xa4":164,"\xa5":165,"\xa6":166,"\xa7":167,
|
||||
"\xa8":168,"\xa9":169,"\xaa":170,"\xab":171,"\xac":172,"\xad":173,
|
||||
"\xae":174,"\xaf":175,"\xb0":176,"\xb1":177,"\xb2":178,"\xb3":179,
|
||||
"\xb4":180,"\xb5":181,"\xb6":182,"\xb7":183,"\xb8":184,"\xb9":185,
|
||||
"\xba":186,"\xbb":187,"\xbc":188,"\xbd":189,"\xbe":190,"\xbf":191,
|
||||
"\xc0":192,"\xc1":193,"\xc2":194,"\xc3":195,"\xc4":196,"\xc5":197,
|
||||
"\xc6":198,"\xc7":199,"\xc8":200,"\xc9":201,"\xca":202,"\xcb":203,
|
||||
"\xcc":204,"\xcd":205,"\xce":206,"\xcf":207,"\xd0":208,"\xd1":209,
|
||||
"\xd2":210,"\xd3":211,"\xd4":212,"\xd5":213,"\xd6":214,"\xd7":215,
|
||||
"\xd8":216,"\xd9":217,"\xda":218,"\xdb":219,"\xdc":220,"\xdd":221,
|
||||
"\xde":222,"\xdf":223,"\xe0":224,"\xe1":225,"\xe2":226,"\xe3":227,
|
||||
"\xe4":228,"\xe5":229,"\xe6":230,"\xe7":231,"\xe8":232,"\xe9":233,
|
||||
"\xea":234,"\xeb":235,"\xec":236,"\xed":237,"\xee":238,"\xef":239,
|
||||
"\xf0":240,"\xf1":241,"\xf2":242,"\xf3":243,"\xf4":244,"\xf5":245,
|
||||
"\xf6":246,"\xf7":247,"\xf8":248,"\xf9":249,"\xfa":250,"\xfb":251,
|
||||
"\xfc":252,"\xfd":253,"\xfe":254,"\xff":255
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
first_256_unicode_chars_as_properties: {
|
||||
input: {
|
||||
var o = {
|
||||
"\u0000": 0, "\u0001": 1, "\u0002": 2, "\u0003": 3, "\u0004": 4, "\u0005": 5,
|
||||
"\u0006": 6, "\u0007": 7, "\u0008": 8, "\u0009": 9, "\u000A": 10, "\u000B": 11,
|
||||
"\u000C": 12, "\u000D": 13, "\u000E": 14, "\u000F": 15, "\u0010": 16, "\u0011": 17,
|
||||
"\u0012": 18, "\u0013": 19, "\u0014": 20, "\u0015": 21, "\u0016": 22, "\u0017": 23,
|
||||
"\u0018": 24, "\u0019": 25, "\u001A": 26, "\u001B": 27, "\u001C": 28, "\u001D": 29,
|
||||
"\u001E": 30, "\u001F": 31, "\u0020": 32, "\u0021": 33, "\u0022": 34, "\u0023": 35,
|
||||
"\u0024": 36, "\u0025": 37, "\u0026": 38, "\u0027": 39, "\u0028": 40, "\u0029": 41,
|
||||
"\u002A": 42, "\u002B": 43, "\u002C": 44, "\u002D": 45, "\u002E": 46, "\u002F": 47,
|
||||
"\u0030": 48, "\u0031": 49, "\u0032": 50, "\u0033": 51, "\u0034": 52, "\u0035": 53,
|
||||
"\u0036": 54, "\u0037": 55, "\u0038": 56, "\u0039": 57, "\u003A": 58, "\u003B": 59,
|
||||
"\u003C": 60, "\u003D": 61, "\u003E": 62, "\u003F": 63, "\u0040": 64, "\u0041": 65,
|
||||
"\u0042": 66, "\u0043": 67, "\u0044": 68, "\u0045": 69, "\u0046": 70, "\u0047": 71,
|
||||
"\u0048": 72, "\u0049": 73, "\u004A": 74, "\u004B": 75, "\u004C": 76, "\u004D": 77,
|
||||
"\u004E": 78, "\u004F": 79, "\u0050": 80, "\u0051": 81, "\u0052": 82, "\u0053": 83,
|
||||
"\u0054": 84, "\u0055": 85, "\u0056": 86, "\u0057": 87, "\u0058": 88, "\u0059": 89,
|
||||
"\u005A": 90, "\u005B": 91, "\u005C": 92, "\u005D": 93, "\u005E": 94, "\u005F": 95,
|
||||
"\u0060": 96, "\u0061": 97, "\u0062": 98, "\u0063": 99, "\u0064": 100, "\u0065": 101,
|
||||
"\u0066": 102, "\u0067": 103, "\u0068": 104, "\u0069": 105, "\u006A": 106, "\u006B": 107,
|
||||
"\u006C": 108, "\u006D": 109, "\u006E": 110, "\u006F": 111, "\u0070": 112, "\u0071": 113,
|
||||
"\u0072": 114, "\u0073": 115, "\u0074": 116, "\u0075": 117, "\u0076": 118, "\u0077": 119,
|
||||
"\u0078": 120, "\u0079": 121, "\u007A": 122, "\u007B": 123, "\u007C": 124, "\u007D": 125,
|
||||
"\u007E": 126, "\u007F": 127, "\u0080": 128, "\u0081": 129, "\u0082": 130, "\u0083": 131,
|
||||
"\u0084": 132, "\u0085": 133, "\u0086": 134, "\u0087": 135, "\u0088": 136, "\u0089": 137,
|
||||
"\u008A": 138, "\u008B": 139, "\u008C": 140, "\u008D": 141, "\u008E": 142, "\u008F": 143,
|
||||
"\u0090": 144, "\u0091": 145, "\u0092": 146, "\u0093": 147, "\u0094": 148, "\u0095": 149,
|
||||
"\u0096": 150, "\u0097": 151, "\u0098": 152, "\u0099": 153, "\u009A": 154, "\u009B": 155,
|
||||
"\u009C": 156, "\u009D": 157, "\u009E": 158, "\u009F": 159, "\u00A0": 160, "\u00A1": 161,
|
||||
"\u00A2": 162, "\u00A3": 163, "\u00A4": 164, "\u00A5": 165, "\u00A6": 166, "\u00A7": 167,
|
||||
"\u00A8": 168, "\u00A9": 169, "\u00AA": 170, "\u00AB": 171, "\u00AC": 172, "\u00AD": 173,
|
||||
"\u00AE": 174, "\u00AF": 175, "\u00B0": 176, "\u00B1": 177, "\u00B2": 178, "\u00B3": 179,
|
||||
"\u00B4": 180, "\u00B5": 181, "\u00B6": 182, "\u00B7": 183, "\u00B8": 184, "\u00B9": 185,
|
||||
"\u00BA": 186, "\u00BB": 187, "\u00BC": 188, "\u00BD": 189, "\u00BE": 190, "\u00BF": 191,
|
||||
"\u00C0": 192, "\u00C1": 193, "\u00C2": 194, "\u00C3": 195, "\u00C4": 196, "\u00C5": 197,
|
||||
"\u00C6": 198, "\u00C7": 199, "\u00C8": 200, "\u00C9": 201, "\u00CA": 202, "\u00CB": 203,
|
||||
"\u00CC": 204, "\u00CD": 205, "\u00CE": 206, "\u00CF": 207, "\u00D0": 208, "\u00D1": 209,
|
||||
"\u00D2": 210, "\u00D3": 211, "\u00D4": 212, "\u00D5": 213, "\u00D6": 214, "\u00D7": 215,
|
||||
"\u00D8": 216, "\u00D9": 217, "\u00DA": 218, "\u00DB": 219, "\u00DC": 220, "\u00DD": 221,
|
||||
"\u00DE": 222, "\u00DF": 223, "\u00E0": 224, "\u00E1": 225, "\u00E2": 226, "\u00E3": 227,
|
||||
"\u00E4": 228, "\u00E5": 229, "\u00E6": 230, "\u00E7": 231, "\u00E8": 232, "\u00E9": 233,
|
||||
"\u00EA": 234, "\u00EB": 235, "\u00EC": 236, "\u00ED": 237, "\u00EE": 238, "\u00EF": 239,
|
||||
"\u00F0": 240, "\u00F1": 241, "\u00F2": 242, "\u00F3": 243, "\u00F4": 244, "\u00F5": 245,
|
||||
"\u00F6": 246, "\u00F7": 247, "\u00F8": 248, "\u00F9": 249, "\u00FA": 250, "\u00FB": 251,
|
||||
"\u00FC": 252, "\u00FD": 253, "\u00FE": 254, "\u00FF": 255
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
"\0":0,"\x01":1,"\x02":2,"\x03":3,"\x04":4,"\x05":5,"\x06":6,
|
||||
"\x07":7,"\b":8,"\t":9,"\n":10,"\v":11,"\f":12,"\r":13,"\x0e":14,
|
||||
"\x0f":15,"\x10":16,"\x11":17,"\x12":18,"\x13":19,"\x14":20,"\x15":21,
|
||||
"\x16":22,"\x17":23,"\x18":24,"\x19":25,"\x1a":26,"\x1b":27,"\x1c":28,
|
||||
"\x1d":29,"\x1e":30,"\x1f":31," ":32,"!":33,'"':34,"#":35,$:36,
|
||||
"%":37,"&":38,"'":39,"(":40,")":41,"*":42,"+":43,",":44,"-":45,
|
||||
".":46,"/":47,0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,
|
||||
":":58,";":59,"<":60,"=":61,">":62,"?":63,"@":64,A:65,B:66,C:67,
|
||||
D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,
|
||||
Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,"[":91,"\\":92,
|
||||
"]":93,"^":94,_:95,"`":96,a:97,b:98,c:99,d:100,e:101,f:102,g:103,
|
||||
h:104,i:105,j:106,k:107,l:108,m:109,n:110,o:111,p:112,q:113,r:114,
|
||||
s:115,t:116,u:117,v:118,w:119,x:120,y:121,z:122,"{":123,"|":124,
|
||||
"}":125,"~":126,"\x7f":127,"\x80":128,"\x81":129,"\x82":130,"\x83":131,
|
||||
"\x84":132,"\x85":133,"\x86":134,"\x87":135,"\x88":136,"\x89":137,
|
||||
"\x8a":138,"\x8b":139,"\x8c":140,"\x8d":141,"\x8e":142,"\x8f":143,
|
||||
"\x90":144,"\x91":145,"\x92":146,"\x93":147,"\x94":148,"\x95":149,
|
||||
"\x96":150,"\x97":151,"\x98":152,"\x99":153,"\x9a":154,"\x9b":155,
|
||||
"\x9c":156,"\x9d":157,"\x9e":158,"\x9f":159,"\xa0":160,"\xa1":161,
|
||||
"\xa2":162,"\xa3":163,"\xa4":164,"\xa5":165,"\xa6":166,"\xa7":167,
|
||||
"\xa8":168,"\xa9":169,"\xaa":170,"\xab":171,"\xac":172,"\xad":173,
|
||||
"\xae":174,"\xaf":175,"\xb0":176,"\xb1":177,"\xb2":178,"\xb3":179,
|
||||
"\xb4":180,"\xb5":181,"\xb6":182,"\xb7":183,"\xb8":184,"\xb9":185,
|
||||
"\xba":186,"\xbb":187,"\xbc":188,"\xbd":189,"\xbe":190,"\xbf":191,
|
||||
"\xc0":192,"\xc1":193,"\xc2":194,"\xc3":195,"\xc4":196,"\xc5":197,
|
||||
"\xc6":198,"\xc7":199,"\xc8":200,"\xc9":201,"\xca":202,"\xcb":203,
|
||||
"\xcc":204,"\xcd":205,"\xce":206,"\xcf":207,"\xd0":208,"\xd1":209,
|
||||
"\xd2":210,"\xd3":211,"\xd4":212,"\xd5":213,"\xd6":214,"\xd7":215,
|
||||
"\xd8":216,"\xd9":217,"\xda":218,"\xdb":219,"\xdc":220,"\xdd":221,
|
||||
"\xde":222,"\xdf":223,"\xe0":224,"\xe1":225,"\xe2":226,"\xe3":227,
|
||||
"\xe4":228,"\xe5":229,"\xe6":230,"\xe7":231,"\xe8":232,"\xe9":233,
|
||||
"\xea":234,"\xeb":235,"\xec":236,"\xed":237,"\xee":238,"\xef":239,
|
||||
"\xf0":240,"\xf1":241,"\xf2":242,"\xf3":243,"\xf4":244,"\xf5":245,
|
||||
"\xf6":246,"\xf7":247,"\xf8":248,"\xf9":249,"\xfa":250,"\xfb":251,
|
||||
"\xfc":252,"\xfd":253,"\xfe":254,"\xff":255
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
first_256_hex_chars_as_properties: {
|
||||
input: {
|
||||
var o = {
|
||||
"\x00": 0, "\x01": 1, "\x02": 2, "\x03": 3, "\x04": 4, "\x05": 5,
|
||||
"\x06": 6, "\x07": 7, "\x08": 8, "\x09": 9, "\x0A": 10, "\x0B": 11,
|
||||
"\x0C": 12, "\x0D": 13, "\x0E": 14, "\x0F": 15, "\x10": 16, "\x11": 17,
|
||||
"\x12": 18, "\x13": 19, "\x14": 20, "\x15": 21, "\x16": 22, "\x17": 23,
|
||||
"\x18": 24, "\x19": 25, "\x1A": 26, "\x1B": 27, "\x1C": 28, "\x1D": 29,
|
||||
"\x1E": 30, "\x1F": 31, "\x20": 32, "\x21": 33, "\x22": 34, "\x23": 35,
|
||||
"\x24": 36, "\x25": 37, "\x26": 38, "\x27": 39, "\x28": 40, "\x29": 41,
|
||||
"\x2A": 42, "\x2B": 43, "\x2C": 44, "\x2D": 45, "\x2E": 46, "\x2F": 47,
|
||||
"\x30": 48, "\x31": 49, "\x32": 50, "\x33": 51, "\x34": 52, "\x35": 53,
|
||||
"\x36": 54, "\x37": 55, "\x38": 56, "\x39": 57, "\x3A": 58, "\x3B": 59,
|
||||
"\x3C": 60, "\x3D": 61, "\x3E": 62, "\x3F": 63, "\x40": 64, "\x41": 65,
|
||||
"\x42": 66, "\x43": 67, "\x44": 68, "\x45": 69, "\x46": 70, "\x47": 71,
|
||||
"\x48": 72, "\x49": 73, "\x4A": 74, "\x4B": 75, "\x4C": 76, "\x4D": 77,
|
||||
"\x4E": 78, "\x4F": 79, "\x50": 80, "\x51": 81, "\x52": 82, "\x53": 83,
|
||||
"\x54": 84, "\x55": 85, "\x56": 86, "\x57": 87, "\x58": 88, "\x59": 89,
|
||||
"\x5A": 90, "\x5B": 91, "\x5C": 92, "\x5D": 93, "\x5E": 94, "\x5F": 95,
|
||||
"\x60": 96, "\x61": 97, "\x62": 98, "\x63": 99, "\x64": 100, "\x65": 101,
|
||||
"\x66": 102, "\x67": 103, "\x68": 104, "\x69": 105, "\x6A": 106, "\x6B": 107,
|
||||
"\x6C": 108, "\x6D": 109, "\x6E": 110, "\x6F": 111, "\x70": 112, "\x71": 113,
|
||||
"\x72": 114, "\x73": 115, "\x74": 116, "\x75": 117, "\x76": 118, "\x77": 119,
|
||||
"\x78": 120, "\x79": 121, "\x7A": 122, "\x7B": 123, "\x7C": 124, "\x7D": 125,
|
||||
"\x7E": 126, "\x7F": 127, "\x80": 128, "\x81": 129, "\x82": 130, "\x83": 131,
|
||||
"\x84": 132, "\x85": 133, "\x86": 134, "\x87": 135, "\x88": 136, "\x89": 137,
|
||||
"\x8A": 138, "\x8B": 139, "\x8C": 140, "\x8D": 141, "\x8E": 142, "\x8F": 143,
|
||||
"\x90": 144, "\x91": 145, "\x92": 146, "\x93": 147, "\x94": 148, "\x95": 149,
|
||||
"\x96": 150, "\x97": 151, "\x98": 152, "\x99": 153, "\x9A": 154, "\x9B": 155,
|
||||
"\x9C": 156, "\x9D": 157, "\x9E": 158, "\x9F": 159, "\xA0": 160, "\xA1": 161,
|
||||
"\xA2": 162, "\xA3": 163, "\xA4": 164, "\xA5": 165, "\xA6": 166, "\xA7": 167,
|
||||
"\xA8": 168, "\xA9": 169, "\xAA": 170, "\xAB": 171, "\xAC": 172, "\xAD": 173,
|
||||
"\xAE": 174, "\xAF": 175, "\xB0": 176, "\xB1": 177, "\xB2": 178, "\xB3": 179,
|
||||
"\xB4": 180, "\xB5": 181, "\xB6": 182, "\xB7": 183, "\xB8": 184, "\xB9": 185,
|
||||
"\xBA": 186, "\xBB": 187, "\xBC": 188, "\xBD": 189, "\xBE": 190, "\xBF": 191,
|
||||
"\xC0": 192, "\xC1": 193, "\xC2": 194, "\xC3": 195, "\xC4": 196, "\xC5": 197,
|
||||
"\xC6": 198, "\xC7": 199, "\xC8": 200, "\xC9": 201, "\xCA": 202, "\xCB": 203,
|
||||
"\xCC": 204, "\xCD": 205, "\xCE": 206, "\xCF": 207, "\xD0": 208, "\xD1": 209,
|
||||
"\xD2": 210, "\xD3": 211, "\xD4": 212, "\xD5": 213, "\xD6": 214, "\xD7": 215,
|
||||
"\xD8": 216, "\xD9": 217, "\xDA": 218, "\xDB": 219, "\xDC": 220, "\xDD": 221,
|
||||
"\xDE": 222, "\xDF": 223, "\xE0": 224, "\xE1": 225, "\xE2": 226, "\xE3": 227,
|
||||
"\xE4": 228, "\xE5": 229, "\xE6": 230, "\xE7": 231, "\xE8": 232, "\xE9": 233,
|
||||
"\xEA": 234, "\xEB": 235, "\xEC": 236, "\xED": 237, "\xEE": 238, "\xEF": 239,
|
||||
"\xF0": 240, "\xF1": 241, "\xF2": 242, "\xF3": 243, "\xF4": 244, "\xF5": 245,
|
||||
"\xF6": 246, "\xF7": 247, "\xF8": 248, "\xF9": 249, "\xFA": 250, "\xFB": 251,
|
||||
"\xFC": 252, "\xFD": 253, "\xFE": 254, "\xFF": 255
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
"\0":0,"\x01":1,"\x02":2,"\x03":3,"\x04":4,"\x05":5,"\x06":6,
|
||||
"\x07":7,"\b":8,"\t":9,"\n":10,"\v":11,"\f":12,"\r":13,"\x0e":14,
|
||||
"\x0f":15,"\x10":16,"\x11":17,"\x12":18,"\x13":19,"\x14":20,"\x15":21,
|
||||
"\x16":22,"\x17":23,"\x18":24,"\x19":25,"\x1a":26,"\x1b":27,"\x1c":28,
|
||||
"\x1d":29,"\x1e":30,"\x1f":31," ":32,"!":33,'"':34,"#":35,$:36,
|
||||
"%":37,"&":38,"'":39,"(":40,")":41,"*":42,"+":43,",":44,"-":45,
|
||||
".":46,"/":47,0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,
|
||||
":":58,";":59,"<":60,"=":61,">":62,"?":63,"@":64,A:65,B:66,C:67,
|
||||
D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,
|
||||
Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,"[":91,"\\":92,
|
||||
"]":93,"^":94,_:95,"`":96,a:97,b:98,c:99,d:100,e:101,f:102,g:103,
|
||||
h:104,i:105,j:106,k:107,l:108,m:109,n:110,o:111,p:112,q:113,r:114,
|
||||
s:115,t:116,u:117,v:118,w:119,x:120,y:121,z:122,"{":123,"|":124,
|
||||
"}":125,"~":126,"\x7f":127,"\x80":128,"\x81":129,"\x82":130,"\x83":131,
|
||||
"\x84":132,"\x85":133,"\x86":134,"\x87":135,"\x88":136,"\x89":137,
|
||||
"\x8a":138,"\x8b":139,"\x8c":140,"\x8d":141,"\x8e":142,"\x8f":143,
|
||||
"\x90":144,"\x91":145,"\x92":146,"\x93":147,"\x94":148,"\x95":149,
|
||||
"\x96":150,"\x97":151,"\x98":152,"\x99":153,"\x9a":154,"\x9b":155,
|
||||
"\x9c":156,"\x9d":157,"\x9e":158,"\x9f":159,"\xa0":160,"\xa1":161,
|
||||
"\xa2":162,"\xa3":163,"\xa4":164,"\xa5":165,"\xa6":166,"\xa7":167,
|
||||
"\xa8":168,"\xa9":169,"\xaa":170,"\xab":171,"\xac":172,"\xad":173,
|
||||
"\xae":174,"\xaf":175,"\xb0":176,"\xb1":177,"\xb2":178,"\xb3":179,
|
||||
"\xb4":180,"\xb5":181,"\xb6":182,"\xb7":183,"\xb8":184,"\xb9":185,
|
||||
"\xba":186,"\xbb":187,"\xbc":188,"\xbd":189,"\xbe":190,"\xbf":191,
|
||||
"\xc0":192,"\xc1":193,"\xc2":194,"\xc3":195,"\xc4":196,"\xc5":197,
|
||||
"\xc6":198,"\xc7":199,"\xc8":200,"\xc9":201,"\xca":202,"\xcb":203,
|
||||
"\xcc":204,"\xcd":205,"\xce":206,"\xcf":207,"\xd0":208,"\xd1":209,
|
||||
"\xd2":210,"\xd3":211,"\xd4":212,"\xd5":213,"\xd6":214,"\xd7":215,
|
||||
"\xd8":216,"\xd9":217,"\xda":218,"\xdb":219,"\xdc":220,"\xdd":221,
|
||||
"\xde":222,"\xdf":223,"\xe0":224,"\xe1":225,"\xe2":226,"\xe3":227,
|
||||
"\xe4":228,"\xe5":229,"\xe6":230,"\xe7":231,"\xe8":232,"\xe9":233,
|
||||
"\xea":234,"\xeb":235,"\xec":236,"\xed":237,"\xee":238,"\xef":239,
|
||||
"\xf0":240,"\xf1":241,"\xf2":242,"\xf3":243,"\xf4":244,"\xf5":245,
|
||||
"\xf6":246,"\xf7":247,"\xf8":248,"\xf9":249,"\xfa":250,"\xfb":251,
|
||||
"\xfc":252,"\xfd":253,"\xfe":254,"\xff":255
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
native_prototype: {
|
||||
options = {
|
||||
unsafe_proto: true,
|
||||
}
|
||||
input: {
|
||||
Array.prototype.splice.apply(a, [1, 2, b, c]);
|
||||
Object.prototype.hasOwnProperty.call(d, "foo");
|
||||
String.prototype.indexOf.call(e, "bar");
|
||||
}
|
||||
expect: {
|
||||
[].splice.apply(a, [1, 2, b, c]);
|
||||
({}).hasOwnProperty.call(d, "foo");
|
||||
"".indexOf.call(e, "bar");
|
||||
}
|
||||
}
|
||||
|
||||
295
test/compress/pure_funcs.js
Normal file
295
test/compress/pure_funcs.js
Normal file
@@ -0,0 +1,295 @@
|
||||
array: {
|
||||
options = {
|
||||
pure_funcs: [ "Math.floor" ],
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
function f(b) {
|
||||
Math.floor(a / b);
|
||||
Math.floor(c / b);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
function f(b) {
|
||||
c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func: {
|
||||
options = {
|
||||
pure_funcs: function(node) {
|
||||
return !~node.args[0].print_to_string().indexOf("a");
|
||||
},
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
Math.floor(a / b);
|
||||
Math.floor(c / b);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a, b) {
|
||||
Math.floor(c / b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
side_effects: {
|
||||
options = {
|
||||
pure_funcs: [ "console.log" ],
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
console.log(a());
|
||||
console.log(b);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a, b) {
|
||||
a();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused: {
|
||||
options = {
|
||||
pure_funcs: [ "pure" ],
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo() {
|
||||
var u = pure(1);
|
||||
var x = pure(2);
|
||||
var y = pure(x);
|
||||
var z = pure(pure(side_effects()));
|
||||
return pure(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
side_effects();
|
||||
return pure(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
babel: {
|
||||
options = {
|
||||
pure_funcs: [ "_classCallCheck" ],
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function _classCallCheck(instance, Constructor) {
|
||||
if (!(instance instanceof Constructor))
|
||||
throw new TypeError("Cannot call a class as a function");
|
||||
}
|
||||
var Foo = function Foo() {
|
||||
_classCallCheck(this, Foo);
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
function _classCallCheck(instance, Constructor) {
|
||||
if (!(instance instanceof Constructor))
|
||||
throw new TypeError("Cannot call a class as a function");
|
||||
}
|
||||
var Foo = function() {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
conditional: {
|
||||
options = {
|
||||
pure_funcs: [ "pure" ],
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
pure(1 | a() ? 2 & b() : 7 ^ c());
|
||||
pure(1 | a() ? 2 & b() : 5);
|
||||
pure(1 | a() ? 4 : 7 ^ c());
|
||||
pure(1 | a() ? 4 : 5);
|
||||
pure(3 ? 2 & b() : 7 ^ c());
|
||||
pure(3 ? 2 & b() : 5);
|
||||
pure(3 ? 4 : 7 ^ c());
|
||||
pure(3 ? 4 : 5);
|
||||
}
|
||||
expect: {
|
||||
1 | a() ? b() : c();
|
||||
1 | a() && b();
|
||||
1 | a() || c();
|
||||
a();
|
||||
3 ? b() : c();
|
||||
3 && b();
|
||||
3 || c();
|
||||
}
|
||||
}
|
||||
|
||||
relational: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
}
|
||||
input: {
|
||||
foo() in foo();
|
||||
foo() instanceof bar();
|
||||
foo() < "bar";
|
||||
bar() > foo();
|
||||
bar() != bar();
|
||||
bar() !== "bar";
|
||||
"bar" == foo();
|
||||
"bar" === bar();
|
||||
"bar" >= "bar";
|
||||
}
|
||||
expect: {
|
||||
bar();
|
||||
bar();
|
||||
bar(), bar();
|
||||
bar();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
arithmetic: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
}
|
||||
input: {
|
||||
foo() + foo();
|
||||
foo() - bar();
|
||||
foo() * "bar";
|
||||
bar() / foo();
|
||||
bar() & bar();
|
||||
bar() | "bar";
|
||||
"bar" >> foo();
|
||||
"bar" << bar();
|
||||
"bar" >>> "bar";
|
||||
}
|
||||
expect: {
|
||||
bar();
|
||||
bar();
|
||||
bar(), bar();
|
||||
bar();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
boolean_and: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
}
|
||||
input: {
|
||||
foo() && foo();
|
||||
foo() && bar();
|
||||
foo() && "bar";
|
||||
bar() && foo();
|
||||
bar() && bar();
|
||||
bar() && "bar";
|
||||
"bar" && foo();
|
||||
"bar" && bar();
|
||||
"bar" && "bar";
|
||||
}
|
||||
expect: {
|
||||
foo() && bar();
|
||||
bar();
|
||||
bar() && bar();
|
||||
bar();
|
||||
"bar" && bar();
|
||||
}
|
||||
}
|
||||
|
||||
boolean_or: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
}
|
||||
input: {
|
||||
foo() || foo();
|
||||
foo() || bar();
|
||||
foo() || "bar";
|
||||
bar() || foo();
|
||||
bar() || bar();
|
||||
bar() || "bar";
|
||||
"bar" || foo();
|
||||
"bar" || bar();
|
||||
"bar" || "bar";
|
||||
}
|
||||
expect: {
|
||||
foo() || bar();
|
||||
bar();
|
||||
bar() || bar();
|
||||
bar();
|
||||
"bar" || bar();
|
||||
}
|
||||
}
|
||||
|
||||
assign: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
function f(b) {
|
||||
a = foo();
|
||||
b *= 4 + foo();
|
||||
c >>= 0 | foo();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
function f(b) {
|
||||
a = foo();
|
||||
b *= 4 + foo();
|
||||
c >>= 0 | foo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unary: {
|
||||
options = {
|
||||
pure_funcs: [ "foo" ],
|
||||
side_effects :true,
|
||||
}
|
||||
input: {
|
||||
typeof foo();
|
||||
typeof bar();
|
||||
typeof "bar";
|
||||
void foo();
|
||||
void bar();
|
||||
void "bar";
|
||||
delete a[foo()];
|
||||
delete a[bar()];
|
||||
delete a["bar"];
|
||||
a[foo()]++;
|
||||
a[bar()]++;
|
||||
a["bar"]++;
|
||||
--a[foo()];
|
||||
--a[bar()];
|
||||
--a["bar"];
|
||||
~foo();
|
||||
~bar();
|
||||
~"bar";
|
||||
}
|
||||
expect: {
|
||||
bar();
|
||||
bar();
|
||||
delete a[foo()];
|
||||
delete a[bar()];
|
||||
delete a["bar"];
|
||||
a[foo()]++;
|
||||
a[bar()]++;
|
||||
a["bar"]++;
|
||||
--a[foo()];
|
||||
--a[bar()];
|
||||
--a["bar"];
|
||||
bar();
|
||||
}
|
||||
}
|
||||
472
test/compress/reduce_vars.js
Normal file
472
test/compress/reduce_vars.js
Normal file
@@ -0,0 +1,472 @@
|
||||
reduce_vars: {
|
||||
options = {
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
global_defs : {
|
||||
C : 0
|
||||
},
|
||||
reduce_vars : true,
|
||||
unused : true
|
||||
}
|
||||
input: {
|
||||
var A = 1;
|
||||
(function f0() {
|
||||
var a = 2;
|
||||
console.log(a - 5);
|
||||
console.log(A - 5);
|
||||
})();
|
||||
(function f1() {
|
||||
var a = 2;
|
||||
console.log(a - 5);
|
||||
eval("console.log(a);");
|
||||
})();
|
||||
(function f2(eval) {
|
||||
var a = 2;
|
||||
console.log(a - 5);
|
||||
eval("console.log(a);");
|
||||
})(eval);
|
||||
(function f3() {
|
||||
var b = typeof C !== "undefined";
|
||||
var c = 4;
|
||||
if (b) {
|
||||
return 'yes';
|
||||
} else {
|
||||
return 'no';
|
||||
}
|
||||
})();
|
||||
console.log(A + 1);
|
||||
}
|
||||
expect: {
|
||||
var A = 1;
|
||||
(function() {
|
||||
console.log(-3);
|
||||
console.log(-4);
|
||||
})();
|
||||
(function f1() {
|
||||
var a = 2;
|
||||
console.log(-3);
|
||||
eval("console.log(a);");
|
||||
})();
|
||||
(function f2(eval) {
|
||||
var a = 2;
|
||||
console.log(-3);
|
||||
eval("console.log(a);");
|
||||
})(eval);
|
||||
(function() {
|
||||
return "yes";
|
||||
})();
|
||||
console.log(2);
|
||||
}
|
||||
}
|
||||
|
||||
modified: {
|
||||
options = {
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
unused : true
|
||||
}
|
||||
input: {
|
||||
function f0() {
|
||||
var a = 1, b = 2;
|
||||
b++;
|
||||
console.log(a + 1);
|
||||
console.log(b + 1);
|
||||
}
|
||||
|
||||
function f1() {
|
||||
var a = 1, b = 2;
|
||||
--b;
|
||||
console.log(a + 1);
|
||||
console.log(b + 1);
|
||||
}
|
||||
|
||||
function f2() {
|
||||
var a = 1, b = 2, c = 3;
|
||||
b = c;
|
||||
console.log(a + b);
|
||||
console.log(b + c);
|
||||
console.log(a + c);
|
||||
console.log(a + b + c);
|
||||
}
|
||||
|
||||
function f3() {
|
||||
var a = 1, b = 2, c = 3;
|
||||
b *= c;
|
||||
console.log(a + b);
|
||||
console.log(b + c);
|
||||
console.log(a + c);
|
||||
console.log(a + b + c);
|
||||
}
|
||||
|
||||
function f4() {
|
||||
var a = 1, b = 2, c = 3;
|
||||
if (a) {
|
||||
b = c;
|
||||
} else {
|
||||
c = b;
|
||||
}
|
||||
console.log(a + b);
|
||||
console.log(b + c);
|
||||
console.log(a + c);
|
||||
console.log(a + b + c);
|
||||
}
|
||||
|
||||
function f5(a) {
|
||||
B = a;
|
||||
console.log(A ? 'yes' : 'no');
|
||||
console.log(B ? 'yes' : 'no');
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f0() {
|
||||
var b = 2;
|
||||
b++;
|
||||
console.log(2);
|
||||
console.log(b + 1);
|
||||
}
|
||||
|
||||
function f1() {
|
||||
var b = 2;
|
||||
--b;
|
||||
console.log(2);
|
||||
console.log(b + 1);
|
||||
}
|
||||
|
||||
function f2() {
|
||||
var b = 2;
|
||||
b = 3;
|
||||
console.log(1 + b);
|
||||
console.log(b + 3);
|
||||
console.log(4);
|
||||
console.log(1 + b + 3);
|
||||
}
|
||||
|
||||
function f3() {
|
||||
var b = 2;
|
||||
b *= 3;
|
||||
console.log(1 + b);
|
||||
console.log(b + 3);
|
||||
console.log(4);
|
||||
console.log(1 + b + 3);
|
||||
}
|
||||
|
||||
function f4() {
|
||||
var b = 2, c = 3;
|
||||
b = c;
|
||||
console.log(1 + b);
|
||||
console.log(b + c);
|
||||
console.log(1 + c);
|
||||
console.log(1 + b + c);
|
||||
}
|
||||
|
||||
function f5(a) {
|
||||
B = a;
|
||||
console.log(A ? 'yes' : 'no');
|
||||
console.log(B ? 'yes' : 'no');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_evaluate: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
unsafe : true,
|
||||
unused : true
|
||||
}
|
||||
input: {
|
||||
function f0(){
|
||||
var a = {
|
||||
b:1
|
||||
};
|
||||
console.log(a.b + 3);
|
||||
}
|
||||
|
||||
function f1(){
|
||||
var a = {
|
||||
b:{
|
||||
c:1
|
||||
},
|
||||
d:2
|
||||
};
|
||||
console.log(a.b + 3, a.d + 4, a.b.c + 5, a.d.c + 6);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f0(){
|
||||
console.log(4);
|
||||
}
|
||||
|
||||
function f1(){
|
||||
var a = {
|
||||
b:{
|
||||
c:1
|
||||
},
|
||||
d:2
|
||||
};
|
||||
console.log(a.b + 3, 6, 6, 2..c + 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_evaluate_object: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
function f0(){
|
||||
var a = 1;
|
||||
var b = {};
|
||||
b[a] = 2;
|
||||
console.log(a + 3);
|
||||
}
|
||||
|
||||
function f1(){
|
||||
var a = {
|
||||
b:1
|
||||
};
|
||||
a.b = 2;
|
||||
console.log(a.b + 3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f0(){
|
||||
var a = 1;
|
||||
var b = {};
|
||||
b[1] = 2;
|
||||
console.log(4);
|
||||
}
|
||||
|
||||
function f1(){
|
||||
var a = {
|
||||
b:1
|
||||
};
|
||||
a.b = 2;
|
||||
console.log(a.b + 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_evaluate_array: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
unsafe : true
|
||||
}
|
||||
input: {
|
||||
function f0(){
|
||||
var a = 1;
|
||||
var b = [];
|
||||
b[a] = 2;
|
||||
console.log(a + 3);
|
||||
}
|
||||
|
||||
function f1(){
|
||||
var a = [1];
|
||||
a[2] = 3;
|
||||
console.log(a.length);
|
||||
}
|
||||
|
||||
function f2(){
|
||||
var a = [1];
|
||||
a.push(2);
|
||||
console.log(a.length);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f0(){
|
||||
var a = 1;
|
||||
var b = [];
|
||||
b[1] = 2;
|
||||
console.log(4);
|
||||
}
|
||||
|
||||
function f1(){
|
||||
var a = [1];
|
||||
a[2] = 3;
|
||||
console.log(a.length);
|
||||
}
|
||||
|
||||
function f2(){
|
||||
var a = [1];
|
||||
a.push(2);
|
||||
console.log(a.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_evaluate_equality: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
unsafe : true,
|
||||
unused : true
|
||||
}
|
||||
input: {
|
||||
function f0(){
|
||||
var a = {};
|
||||
console.log(a === a);
|
||||
}
|
||||
|
||||
function f1(){
|
||||
var a = [];
|
||||
console.log(a === a);
|
||||
}
|
||||
|
||||
function f2(){
|
||||
var a = {a:1, b:2};
|
||||
var b = a;
|
||||
var c = a;
|
||||
console.log(b === c);
|
||||
}
|
||||
|
||||
function f3(){
|
||||
var a = [1, 2, 3];
|
||||
var b = a;
|
||||
var c = a;
|
||||
console.log(b === c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f0(){
|
||||
console.log(true);
|
||||
}
|
||||
|
||||
function f1(){
|
||||
console.log(true);
|
||||
}
|
||||
|
||||
function f2(){
|
||||
console.log(true);
|
||||
}
|
||||
|
||||
function f3(){
|
||||
console.log(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
passes: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a = 1, b = 2, c = 3;
|
||||
if (a) {
|
||||
b = c;
|
||||
} else {
|
||||
c = b;
|
||||
}
|
||||
console.log(a + b);
|
||||
console.log(b + c);
|
||||
console.log(a + c);
|
||||
console.log(a + b + c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
var b = 2;
|
||||
b = 3;
|
||||
console.log(1 + b);
|
||||
console.log(b + 3);
|
||||
console.log(4);
|
||||
console.log(1 + b + 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iife: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
!function(a, b, c) {
|
||||
b++;
|
||||
console.log(a - 1, b * 1, c + 2);
|
||||
}(1, 2, 3);
|
||||
}
|
||||
expect: {
|
||||
!function(a, b, c) {
|
||||
b++;
|
||||
console.log(0, 1 * b, 5);
|
||||
}(1, 2, 3);
|
||||
}
|
||||
}
|
||||
|
||||
iife_new: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
var A = new function(a, b, c) {
|
||||
b++;
|
||||
console.log(a - 1, b * 1, c + 2);
|
||||
}(1, 2, 3);
|
||||
}
|
||||
expect: {
|
||||
var A = new function(a, b, c) {
|
||||
b++;
|
||||
console.log(0, 1 * b, 5);
|
||||
}(1, 2, 3);
|
||||
}
|
||||
}
|
||||
|
||||
multi_def: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
if (a)
|
||||
var b = 1;
|
||||
else
|
||||
var b = 2
|
||||
console.log(b + 1);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
if (a)
|
||||
var b = 1;
|
||||
else
|
||||
var b = 2
|
||||
console.log(b + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
multi_def_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
if (code == 16)
|
||||
var bitsLength = 2, bitsOffset = 3, what = len;
|
||||
else if (code == 17)
|
||||
var bitsLength = 3, bitsOffset = 3, what = (len = 0);
|
||||
else if (code == 18)
|
||||
var bitsLength = 7, bitsOffset = 11, what = (len = 0);
|
||||
var repeatLength = this.getBits(bitsLength) + bitsOffset;
|
||||
}
|
||||
expect: {
|
||||
if (16 == code)
|
||||
var bitsLength = 2, bitsOffset = 3, what = len;
|
||||
else if (17 == code)
|
||||
var bitsLength = 3, bitsOffset = 3, what = (len = 0);
|
||||
else if (18 == code)
|
||||
var bitsLength = 7, bitsOffset = 11, what = (len = 0);
|
||||
var repeatLength = this.getBits(bitsLength) + bitsOffset;
|
||||
}
|
||||
}
|
||||
124
test/compress/return_undefined.js
Normal file
124
test/compress/return_undefined.js
Normal file
@@ -0,0 +1,124 @@
|
||||
return_undefined: {
|
||||
options = {
|
||||
sequences : false,
|
||||
if_return : true,
|
||||
evaluate : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects : true,
|
||||
properties : true,
|
||||
drop_debugger : true,
|
||||
loops : true,
|
||||
hoist_funs : true,
|
||||
keep_fargs : true,
|
||||
keep_fnames : false,
|
||||
hoist_vars : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
negate_iife : true
|
||||
};
|
||||
input: {
|
||||
function f0() {
|
||||
}
|
||||
function f1() {
|
||||
return undefined;
|
||||
}
|
||||
function f2() {
|
||||
return void 0;
|
||||
}
|
||||
function f3() {
|
||||
return void 123;
|
||||
}
|
||||
function f4() {
|
||||
return;
|
||||
}
|
||||
function f5(a, b) {
|
||||
console.log(a, b);
|
||||
baz(a);
|
||||
return;
|
||||
}
|
||||
function f6(a, b) {
|
||||
console.log(a, b);
|
||||
if (a) {
|
||||
foo(b);
|
||||
baz(a);
|
||||
return a + b;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function f7(a, b) {
|
||||
console.log(a, b);
|
||||
if (a) {
|
||||
foo(b);
|
||||
baz(a);
|
||||
return void 0;
|
||||
}
|
||||
return a + b;
|
||||
}
|
||||
function f8(a, b) {
|
||||
foo(a);
|
||||
bar(b);
|
||||
return void 0;
|
||||
}
|
||||
function f9(a, b) {
|
||||
foo(a);
|
||||
bar(b);
|
||||
return undefined;
|
||||
}
|
||||
function f10() {
|
||||
return false;
|
||||
}
|
||||
function f11() {
|
||||
return null;
|
||||
}
|
||||
function f12() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f0() {}
|
||||
function f1() {}
|
||||
function f2() {}
|
||||
function f3() {}
|
||||
function f4() {}
|
||||
function f5(a, b) {
|
||||
console.log(a, b);
|
||||
baz(a);
|
||||
}
|
||||
function f6(a, b) {
|
||||
console.log(a, b);
|
||||
if (a) {
|
||||
foo(b);
|
||||
baz(a);
|
||||
return a + b;
|
||||
}
|
||||
}
|
||||
function f7(a, b) {
|
||||
console.log(a, b);
|
||||
if (!a)
|
||||
return a + b;
|
||||
foo(b);
|
||||
baz(a);
|
||||
}
|
||||
function f8(a, b) {
|
||||
foo(a);
|
||||
bar(b);
|
||||
}
|
||||
function f9(a, b) {
|
||||
foo(a);
|
||||
bar(b);
|
||||
}
|
||||
function f10() {
|
||||
return !1;
|
||||
}
|
||||
function f11() {
|
||||
return null;
|
||||
}
|
||||
function f12() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
134
test/compress/screw-ie8.js
Normal file
134
test/compress/screw-ie8.js
Normal file
@@ -0,0 +1,134 @@
|
||||
do_screw: {
|
||||
options = { screw_ie8: true };
|
||||
beautify = {
|
||||
screw_ie8: true,
|
||||
ascii_only: true
|
||||
};
|
||||
|
||||
input: f("\v");
|
||||
expect_exact: 'f("\\v");';
|
||||
}
|
||||
|
||||
dont_screw: {
|
||||
options = { screw_ie8: false };
|
||||
beautify = { screw_ie8: false, ascii_only: true };
|
||||
|
||||
input: f("\v");
|
||||
expect_exact: 'f("\\x0B");';
|
||||
}
|
||||
|
||||
do_screw_try_catch: {
|
||||
options = { screw_ie8: true };
|
||||
mangle = { screw_ie8: true };
|
||||
beautify = { screw_ie8: true };
|
||||
input: {
|
||||
good = function(e){
|
||||
return function(error){
|
||||
try{
|
||||
e()
|
||||
} catch(e) {
|
||||
error(e)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
good = function(n){
|
||||
return function(t){
|
||||
try{
|
||||
n()
|
||||
} catch(n) {
|
||||
t(n)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
dont_screw_try_catch: {
|
||||
// This test is known to generate incorrect code for screw_ie8=false.
|
||||
// Update expected result in the event this bug is ever fixed.
|
||||
options = { screw_ie8: false };
|
||||
mangle = { screw_ie8: false };
|
||||
beautify = { screw_ie8: false };
|
||||
input: {
|
||||
bad = function(e){
|
||||
return function(error){
|
||||
try{
|
||||
e()
|
||||
} catch(e) {
|
||||
error(e)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
bad = function(n){
|
||||
return function(n){
|
||||
try{
|
||||
t()
|
||||
} catch(t) {
|
||||
n(t)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
do_screw_try_catch_undefined: {
|
||||
options = { screw_ie8: true };
|
||||
mangle = { screw_ie8: true };
|
||||
beautify = { screw_ie8: true };
|
||||
input: {
|
||||
function a(b){
|
||||
try {
|
||||
throw 'Stuff';
|
||||
} catch (undefined) {
|
||||
console.log('caught: ' + undefined);
|
||||
}
|
||||
console.log('undefined is ' + undefined);
|
||||
return b === undefined;
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
function a(o){
|
||||
try{
|
||||
throw "Stuff"
|
||||
} catch (o) {
|
||||
console.log("caught: "+o)
|
||||
}
|
||||
console.log("undefined is " + void 0);
|
||||
return void 0===o
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dont_screw_try_catch_undefined: {
|
||||
// This test is known to generate incorrect code for screw_ie8=false.
|
||||
// Update expected result in the event this bug is ever fixed.
|
||||
options = { screw_ie8: false };
|
||||
mangle = { screw_ie8: false };
|
||||
beautify = { screw_ie8: false };
|
||||
input: {
|
||||
function a(b){
|
||||
try {
|
||||
throw 'Stuff';
|
||||
} catch (undefined) {
|
||||
console.log('caught: ' + undefined);
|
||||
}
|
||||
console.log('undefined is ' + undefined);
|
||||
return b === undefined;
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
function a(o){
|
||||
try{
|
||||
throw "Stuff"
|
||||
} catch (n) {
|
||||
console.log("caught: "+n)
|
||||
}
|
||||
console.log("undefined is " + n);
|
||||
return o === n
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,9 +91,11 @@ make_sequences_4: {
|
||||
lift_sequences_1: {
|
||||
options = { sequences: true };
|
||||
input: {
|
||||
var foo, x, y, bar;
|
||||
foo = !(x(), y(), bar());
|
||||
}
|
||||
expect: {
|
||||
var foo, x, y, bar;
|
||||
x(), y(), foo = !bar();
|
||||
}
|
||||
}
|
||||
@@ -101,19 +103,25 @@ lift_sequences_1: {
|
||||
lift_sequences_2: {
|
||||
options = { sequences: true, evaluate: true };
|
||||
input: {
|
||||
q = 1 + (foo(), bar(), 5) + 7 * (5 / (3 - (a(), (QW=ER), c(), 2))) - (x(), y(), 5);
|
||||
var foo, bar;
|
||||
foo.x = (foo = {}, 10);
|
||||
bar = (bar = {}, 10);
|
||||
}
|
||||
expect: {
|
||||
foo(), bar(), a(), QW = ER, c(), x(), y(), q = 36
|
||||
var foo, bar;
|
||||
foo.x = (foo = {}, 10),
|
||||
bar = {}, bar = 10;
|
||||
}
|
||||
}
|
||||
|
||||
lift_sequences_3: {
|
||||
options = { sequences: true, conditionals: true };
|
||||
input: {
|
||||
var x, foo, bar, baz;
|
||||
x = (foo(), bar(), baz()) ? 10 : 20;
|
||||
}
|
||||
expect: {
|
||||
var x, foo, bar, baz;
|
||||
foo(), bar(), x = baz() ? 10 : 20;
|
||||
}
|
||||
}
|
||||
@@ -121,9 +129,11 @@ lift_sequences_3: {
|
||||
lift_sequences_4: {
|
||||
options = { side_effects: true };
|
||||
input: {
|
||||
var x, foo, bar, baz;
|
||||
x = (foo, bar, baz);
|
||||
}
|
||||
expect: {
|
||||
var x, foo, bar, baz;
|
||||
x = baz;
|
||||
}
|
||||
}
|
||||
@@ -159,3 +169,85 @@ for_sequences: {
|
||||
for (y = 5; false;);
|
||||
}
|
||||
}
|
||||
|
||||
limit_1: {
|
||||
options = {
|
||||
sequences: 3,
|
||||
};
|
||||
input: {
|
||||
a;
|
||||
b;
|
||||
c;
|
||||
d;
|
||||
e;
|
||||
f;
|
||||
g;
|
||||
h;
|
||||
i;
|
||||
j;
|
||||
k;
|
||||
}
|
||||
expect: {
|
||||
a, b, c;
|
||||
d, e, f;
|
||||
g, h, i;
|
||||
j, k;
|
||||
}
|
||||
}
|
||||
|
||||
limit_2: {
|
||||
options = {
|
||||
sequences: 3,
|
||||
};
|
||||
input: {
|
||||
a, b;
|
||||
c, d;
|
||||
e, f;
|
||||
g, h;
|
||||
i, j;
|
||||
k;
|
||||
}
|
||||
expect: {
|
||||
a, b, c, d;
|
||||
e, f, g, h;
|
||||
i, j, k;
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_for: {
|
||||
options = {
|
||||
sequences: true,
|
||||
negate_iife: true,
|
||||
};
|
||||
input: {
|
||||
(function() {})();
|
||||
for (i = 0; i < 5; i++) console.log(i);
|
||||
|
||||
(function() {})();
|
||||
for (; i < 5; i++) console.log(i);
|
||||
}
|
||||
expect: {
|
||||
for (!function() {}(), i = 0; i < 5; i++) console.log(i);
|
||||
for (function() {}(); i < 5; i++) console.log(i);
|
||||
}
|
||||
}
|
||||
|
||||
iife: {
|
||||
options = {
|
||||
sequences: true,
|
||||
};
|
||||
input: {
|
||||
x = 42;
|
||||
(function a() {})();
|
||||
!function b() {}();
|
||||
~function c() {}();
|
||||
+function d() {}();
|
||||
-function e() {}();
|
||||
void function f() {}();
|
||||
typeof function g() {}();
|
||||
}
|
||||
expect: {
|
||||
x = 42, function a() {}(), function b() {}(), function c() {}(),
|
||||
function d() {}(), function e() {}(), function f() {}(), function g() {}()
|
||||
}
|
||||
}
|
||||
|
||||
10
test/compress/string-literal.js
Normal file
10
test/compress/string-literal.js
Normal file
@@ -0,0 +1,10 @@
|
||||
octal_escape_sequence: {
|
||||
input: {
|
||||
var boundaries = "\0\7\00\07\70\77\000\077\300\377";
|
||||
var border_check = "\400\700\0000\3000";
|
||||
}
|
||||
expect: {
|
||||
var boundaries = "\x00\x07\x00\x07\x38\x3f\x00\x3f\xc0\xff";
|
||||
var border_check = "\x20\x30\x38\x30\x00\x30\xc0\x30";
|
||||
}
|
||||
}
|
||||
9
test/compress/super.js
Normal file
9
test/compress/super.js
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
super_can_be_parsed: {
|
||||
input: {
|
||||
super(1,2);
|
||||
super.meth();
|
||||
}
|
||||
expect_exact: "super(1,2);super.meth();"
|
||||
}
|
||||
|
||||
379
test/compress/template-string.js
Normal file
379
test/compress/template-string.js
Normal file
@@ -0,0 +1,379 @@
|
||||
template_strings: {
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
``;
|
||||
`xx\`x`;
|
||||
`${ foo + 2 }`;
|
||||
` foo ${ bar + `baz ${ qux }` }`;
|
||||
}
|
||||
expect_exact: "``;`xx\\`x`;`${foo+2}`;` foo ${bar+`baz ${qux}`}`;";
|
||||
}
|
||||
|
||||
template_string_prefixes: {
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
String.raw`foo`;
|
||||
foo `bar`;
|
||||
}
|
||||
expect_exact: "String.raw`foo`;foo`bar`;";
|
||||
}
|
||||
|
||||
template_strings_ascii_only: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `foo
|
||||
bar
|
||||
ↂωↂ`;
|
||||
var bar = `\``;
|
||||
}
|
||||
expect_exact: "var foo=`foo\\n bar\\n \\u2182\\u03c9\\u2182`;var bar=`\\``;"
|
||||
}
|
||||
|
||||
template_strings_without_ascii_only: {
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `foo
|
||||
bar
|
||||
ↂωↂ`
|
||||
}
|
||||
expect_exact: "var foo=`foo\n bar\n ↂωↂ`;"
|
||||
}
|
||||
|
||||
template_string_with_constant_expression: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `${4 + 4} equals 4 + 4`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `8 equals 4 + 4`;
|
||||
}
|
||||
}
|
||||
|
||||
template_string_with_predefined_constants: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `This is ${undefined}`;
|
||||
var bar = `This is ${NaN}`;
|
||||
var baz = `This is ${null}`;
|
||||
var foofoo = `This is ${Infinity}`;
|
||||
var foobar = "This is ${1/0}";
|
||||
var foobaz = 'This is ${1/0}';
|
||||
var barfoo = "This is ${NaN}";
|
||||
var bazfoo = "This is ${null}";
|
||||
var bazbaz = `This is ${1/0}`;
|
||||
var barbar = `This is ${0/0}`;
|
||||
var barbar = "This is ${0/0}";
|
||||
var barber = 'This is ${0/0}';
|
||||
|
||||
var a = `${4**11}`; // 8 in template vs 7 chars - 4194304
|
||||
var b = `${4**12}`; // 8 in template vs 8 chars - 16777216
|
||||
var c = `${4**14}`; // 8 in template vs 9 chars - 268435456
|
||||
}
|
||||
expect: {
|
||||
var foo = `This is undefined`;
|
||||
var bar = `This is NaN`;
|
||||
var baz = `This is null`;
|
||||
var foofoo = `This is ${1/0}`;
|
||||
var foobar = "This is ${1/0}";
|
||||
var foobaz = 'This is ${1/0}';
|
||||
var barfoo = "This is ${NaN}";
|
||||
var bazfoo = "This is ${null}";
|
||||
var bazbaz = `This is ${1/0}`;
|
||||
var barbar = `This is NaN`;
|
||||
var barbar = "This is ${0/0}";
|
||||
var barber = 'This is ${0/0}';
|
||||
|
||||
var a = `4194304`;
|
||||
var b = `16777216`; // Potential for further concatentation
|
||||
var c = `${4**14}`; // Not worth converting
|
||||
}
|
||||
}
|
||||
|
||||
template_string_evaluate_with_many_segments: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello ${guest()}, welcome to ${location()}${"."}`;
|
||||
var bar = `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
|
||||
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
|
||||
var buzz = `${1}${foobar()}${2}${foobar()}${3}${foobar()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `Hello ${guest()}, welcome to ${location()}.`;
|
||||
var bar = `1234567890`;
|
||||
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
|
||||
var buzz = `1${foobar()}2${foobar()}3${foobar()}`;
|
||||
}
|
||||
}
|
||||
|
||||
template_string_with_many_segments: {
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello ${guest()}, welcome to ${location()}${"."}`;
|
||||
var bar = `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
|
||||
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
|
||||
var buzz = `${1}${foobar()}${2}${foobar()}${3}${foobar()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `Hello ${guest()}, welcome to ${location()}${"."}`;
|
||||
var bar = `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
|
||||
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
|
||||
var buzz = `${1}${foobar()}${2}${foobar()}${3}${foobar()}`;
|
||||
}
|
||||
}
|
||||
|
||||
template_string_to_normal_string: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 0
|
||||
}
|
||||
input: {
|
||||
var foo = `This is ${undefined}`;
|
||||
var bar = "Decimals " + `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `This is undefined`;
|
||||
var bar = "Decimals 1234567890";
|
||||
}
|
||||
}
|
||||
|
||||
template_concattenating_string: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 3 // Yes, keep quotes
|
||||
}
|
||||
input: {
|
||||
var foo = "Have a nice " + `day. ${`day. ` + `day.`}`;
|
||||
var bar = "Have a nice " + `${day()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = "Have a nice day. day. day.";
|
||||
var bar = "Have a nice " + `${day()}`;
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_nested_templates: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 0
|
||||
}
|
||||
input: {
|
||||
var baz = `${`${`${`foo`}`}`}`;
|
||||
}
|
||||
expect: {
|
||||
var baz = `foo`;
|
||||
}
|
||||
}
|
||||
|
||||
enforce_double_quotes: {
|
||||
beautify = {
|
||||
quote_style: 1
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${'world'}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${"world"}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
}
|
||||
|
||||
enforce_single_quotes: {
|
||||
beautify = {
|
||||
quote_style: 2
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${"world"}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${'world'}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
}
|
||||
|
||||
enforce_double_quotes_and_evaluate: {
|
||||
beautify = {
|
||||
quote_style: 1
|
||||
}
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${'world'}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello world`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
}
|
||||
|
||||
enforce_single_quotes_and_evaluate: {
|
||||
beautify = {
|
||||
quote_style: 2
|
||||
}
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${"world"}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello world`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
}
|
||||
|
||||
respect_inline_script: {
|
||||
beautify = {
|
||||
inline_script: true,
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `</script>${content}`;
|
||||
var bar = `<!--`;
|
||||
var baz = `-->`;
|
||||
}
|
||||
expect_exact: "var foo=`<\\/script>${content}`;var bar=`\\x3c!--`;var baz=`--\\x3e`;";
|
||||
}
|
||||
|
||||
do_not_optimize_tagged_template_1: {
|
||||
beautify = {
|
||||
quote_style: 0
|
||||
}
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = tag`Shall not be optimized. ${"But " + "this " + "is " + "fine."}`;
|
||||
var bar = tag`Don't even mind changing my quotes!`;
|
||||
}
|
||||
expect_exact:
|
||||
'var foo=tag`Shall not be optimized. ${"But this is fine."}`;var bar=tag`Don\'t even mind changing my quotes!`;';
|
||||
}
|
||||
|
||||
do_not_optimize_tagged_template_2: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = tag`test` + " something out";
|
||||
}
|
||||
expect_exact: 'var foo=tag`test`+" something out";';
|
||||
}
|
||||
|
||||
keep_raw_content_in_tagged_template: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = tag`\u0020\u{20}\u{00020}\x20\40\040 `;
|
||||
}
|
||||
expect_exact: "var foo=tag`\\u0020\\u{20}\\u{00020}\\x20\\40\\040 `;";
|
||||
}
|
||||
|
||||
allow_chained_templates: {
|
||||
input: {
|
||||
var foo = tag`a``b``c``d`;
|
||||
}
|
||||
expect: {
|
||||
var foo = tag`a``b``c``d`;
|
||||
}
|
||||
}
|
||||
|
||||
check_escaped_chars: {
|
||||
input: {
|
||||
var foo = `\u0020\u{20}\u{00020}\x20\40\040 `;
|
||||
}
|
||||
expect_exact: "var foo=` `;";
|
||||
}
|
||||
|
||||
escape_dollar_curly: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
console.log(`\$\{ beep \}`)
|
||||
console.log(`${1-0}\${2-0}$\{3-0}${4-0}`)
|
||||
console.log(`$${""}{not an expression}`)
|
||||
}
|
||||
expect_exact: "console.log(`\\${ beep }`);console.log(`1\\${2-0}\\${3-0}4`);console.log(`\\${not an expression}`);"
|
||||
}
|
||||
|
||||
template_starting_with_newline: {
|
||||
options = {
|
||||
dead_code: true
|
||||
}
|
||||
input: {
|
||||
function foo(e) {
|
||||
return `
|
||||
this is a template string!`;
|
||||
};
|
||||
} expect_exact: "function foo(e){return`\nthis is a template string!`}"
|
||||
}
|
||||
|
||||
template_with_newline: {
|
||||
options = {
|
||||
dead_code: true
|
||||
}
|
||||
input: {
|
||||
function foo(e) {
|
||||
return `yep,
|
||||
this is a template string!`;
|
||||
};
|
||||
} expect_exact: "function foo(e){return`yep,\nthis is a template string!`}"
|
||||
}
|
||||
|
||||
template_ending_with_newline: {
|
||||
options = {
|
||||
dead_code: true
|
||||
}
|
||||
input: {
|
||||
function foo(e) {
|
||||
return `this is a template string!
|
||||
`;
|
||||
};
|
||||
} expect_exact: "function foo(e){return`this is a template string!\n`}"
|
||||
}
|
||||
12
test/compress/try-catch.js
Normal file
12
test/compress/try-catch.js
Normal file
@@ -0,0 +1,12 @@
|
||||
catch_destructuring_with_sequence: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
throw {};
|
||||
} catch ({xCover = (0, function() {})} ) {
|
||||
}
|
||||
}
|
||||
expect_exact: "try{throw{}}catch({xCover=(0,function(){})}){}"
|
||||
}
|
||||
@@ -23,3 +23,28 @@ typeof_evaluation: {
|
||||
h='undefined';
|
||||
}
|
||||
}
|
||||
|
||||
typeof_in_boolean_context: {
|
||||
options = {
|
||||
booleans : true,
|
||||
evaluate : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
};
|
||||
input: {
|
||||
function f1(x) { return typeof x ? "yes" : "no"; }
|
||||
function f2() { return typeof g()? "Yes" : "No"; }
|
||||
typeof 0 ? foo() : bar();
|
||||
!typeof console.log(1);
|
||||
var a = !typeof console.log(2);
|
||||
if (typeof (1 + foo()));
|
||||
}
|
||||
expect: {
|
||||
function f1(x) { return "yes"; }
|
||||
function f2() { return g(), "Yes"; }
|
||||
foo();
|
||||
console.log(1);
|
||||
var a = !(console.log(2), !0);
|
||||
foo();
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user