Compare commits
748 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40ceddb48a | ||
|
|
7aa69117e1 | ||
|
|
bff7ad67bb | ||
|
|
c2334baa48 | ||
|
|
fb2b6c7c6f | ||
|
|
f5cbe19b75 | ||
|
|
b34fa11a13 | ||
|
|
320984c5f5 | ||
|
|
4365a51237 | ||
|
|
858e6c78a4 | ||
|
|
0b0296eb2a | ||
|
|
872270b149 | ||
|
|
b1c593a041 | ||
|
|
13be50a4a9 | ||
|
|
16cd5d57a5 | ||
|
|
834f9f3924 | ||
|
|
cf0951f726 | ||
|
|
852f78491a | ||
|
|
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 | ||
|
|
7f8d72d9d3 | ||
|
|
1eaa211e09 | ||
|
|
0610c020b1 | ||
|
|
0d7d4918eb | ||
|
|
48284844a4 | ||
|
|
ec2e5fa3a2 | ||
|
|
da17766ddd | ||
|
|
0913db8c84 | ||
|
|
5c7705fcad | ||
|
|
f6372483a0 | ||
|
|
98f330658f | ||
|
|
a7b3b0d3a5 | ||
|
|
0a35acbbe7 | ||
|
|
2a9989dd18 | ||
|
|
79b98a9fe8 | ||
|
|
057de570e6 | ||
|
|
557b3e412f | ||
|
|
8d74f34373 | ||
|
|
266ddd9639 | ||
|
|
e51c6ba380 | ||
|
|
6389e52305 | ||
|
|
e05510f3bc | ||
|
|
fc9804b909 | ||
|
|
4761d07e0b | ||
|
|
0111497fc9 | ||
|
|
7d8dea3b26 | ||
|
|
25fc02743a | ||
|
|
0bd8053524 | ||
|
|
1a78bbcd23 | ||
|
|
8430123e9d | ||
|
|
614db97cca | ||
|
|
d854523783 | ||
|
|
781f26eda1 | ||
|
|
37f4395cc0 | ||
|
|
de619ae5a6 | ||
|
|
86859f6d7e | ||
|
|
dcdcfe4d39 | ||
|
|
72306b9885 | ||
|
|
38756b1f26 | ||
|
|
85a09fc3b6 | ||
|
|
307b88d6cc | ||
|
|
fb049d3a81 | ||
|
|
67cca43358 | ||
|
|
642273c290 | ||
|
|
e8b23c7798 | ||
|
|
9edbe93df5 | ||
|
|
af37ecafe1 | ||
|
|
41a9329409 | ||
|
|
7eb52d2837 | ||
|
|
eb63fece2f | ||
|
|
2d8af8947e | ||
|
|
2650182f47 | ||
|
|
572b97b0bb | ||
|
|
698705a820 | ||
|
|
debc525fa1 | ||
|
|
5576e2737a | ||
|
|
b40d5de69c | ||
|
|
b7ef7840f3 | ||
|
|
85924bb32e | ||
|
|
a97690fc72 | ||
|
|
02c638209e | ||
|
|
030611b729 | ||
|
|
335b72df03 | ||
|
|
3a7d53f3cf | ||
|
|
9676167aac | ||
|
|
1840a0b282 | ||
|
|
ace8aaa0f4 | ||
|
|
0c003c92a8 | ||
|
|
85fbf86d7b | ||
|
|
aa82027a17 | ||
|
|
55c592dd43 | ||
|
|
fc1abd1c11 | ||
|
|
e645ba84cf | ||
|
|
6c99816855 | ||
|
|
2149bfb707 | ||
|
|
d7971ba0e4 | ||
|
|
5c4cfaa0a7 | ||
|
|
bb9c9707aa | ||
|
|
6c8e001fee | ||
|
|
9c53c7ada7 | ||
|
|
f99b7b630d | ||
|
|
ea31da2455 | ||
|
|
4d7746baf3 | ||
|
|
31d5825a86 | ||
|
|
8287ef6781 | ||
|
|
5cb5305cf3 | ||
|
|
00ad57e393 | ||
|
|
09d5707a8a | ||
|
|
1e390269d4 | ||
|
|
bc49dfd27a | ||
|
|
27eedbc302 | ||
|
|
5f464b41e2 | ||
|
|
bcc1318d4b | ||
|
|
a0e03c9df4 | ||
|
|
6641dcafb6 | ||
|
|
d2945744f2 | ||
|
|
35bc716625 | ||
|
|
f39fd3d583 | ||
|
|
65887d9a56 | ||
|
|
e9224ab444 | ||
|
|
4d9a085687 | ||
|
|
4fe630431c | ||
|
|
c55dd5ed74 | ||
|
|
e4fa4b109a | ||
|
|
4b4528ee05 | ||
|
|
187a0caf9d | ||
|
|
b5a7a231f7 | ||
|
|
3907a5e3b2 | ||
|
|
b434b75b36 | ||
|
|
c70d176f35 | ||
|
|
9317237372 | ||
|
|
98434258d0 | ||
|
|
45ddb9caeb | ||
|
|
9bcf702a6e | ||
|
|
f68de86a17 | ||
|
|
c3c7587796 | ||
|
|
07bb7262d0 | ||
|
|
21befe583f | ||
|
|
a9d4a6291b | ||
|
|
ee6c9fabb7 | ||
|
|
102d1b9137 | ||
|
|
294861ba96 | ||
|
|
11b0efdf84 | ||
|
|
5486b68850 | ||
|
|
bdd8e34f63 | ||
|
|
6547437725 | ||
|
|
9662228f6a | ||
|
|
31a9b05c96 | ||
|
|
63b01fe8f9 | ||
|
|
7a4ed9d200 | ||
|
|
d5c651a5e5 | ||
|
|
cdba43cfa4 | ||
|
|
a123e232b9 | ||
|
|
601780acc1 | ||
|
|
7c3fee9e31 | ||
|
|
929de2b0de | ||
|
|
12e6ad326c | ||
|
|
00c8d1d241 | ||
|
|
af2472d85e | ||
|
|
3eb9101918 | ||
|
|
0a38a688f9 | ||
|
|
f4c2ea37bf | ||
|
|
915f907186 | ||
|
|
799509e145 | ||
|
|
b5a7197ae5 | ||
|
|
1b703349cf | ||
|
|
4a7179ff91 | ||
|
|
f97da4294a | ||
|
|
918c17bd88 | ||
|
|
8b71c6559b | ||
|
|
26641f3fb2 | ||
|
|
ebe118dc79 | ||
|
|
70e5b6f15b | ||
|
|
57e0fafd5c | ||
|
|
8439c8ba98 | ||
|
|
5c4e470d43 | ||
|
|
6605d15783 | ||
|
|
ac8db977b9 | ||
|
|
88b77ddaa9 | ||
|
|
fe4e9f9d97 | ||
|
|
8c6af09ae0 | ||
|
|
6f3e35bb3f | ||
|
|
174404c0f3 | ||
|
|
60c4030a4d | ||
|
|
ac810dc07a | ||
|
|
0cabedc526 | ||
|
|
5cd26c005b | ||
|
|
bd99b00413 | ||
|
|
9e2f9f7910 | ||
|
|
e87c77ed41 | ||
|
|
774bda13cd | ||
|
|
15b5f70338 | ||
|
|
7f48d5b33c | ||
|
|
b6968b6bd2 | ||
|
|
08b80302eb | ||
|
|
645626ebe8 | ||
|
|
d895c09c70 | ||
|
|
08623aa6a7 | ||
|
|
c898a26117 | ||
|
|
619adb0308 | ||
|
|
7691bebea5 | ||
|
|
3c4346728e | ||
|
|
18d37ac761 | ||
|
|
63d35f8f6d | ||
|
|
7dbe961b2d | ||
|
|
94c4daaf9e | ||
|
|
37ee9de902 | ||
|
|
83db98ad3b | ||
|
|
bd0ae6569f | ||
|
|
841a661071 | ||
|
|
7491d07666 | ||
|
|
335e349314 | ||
|
|
2a88d07b3a | ||
|
|
a887cde9f2 | ||
|
|
b5623b19d4 | ||
|
|
6b2861e086 | ||
|
|
d5138f7467 | ||
|
|
eac67b2816 | ||
|
|
ce10072824 | ||
|
|
dff54a6552 | ||
|
|
1940fb682c | ||
|
|
17eef5a3c2 | ||
|
|
9f1f21b810 | ||
|
|
a8e67d157e | ||
|
|
e870c7db45 | ||
|
|
6500f8c52c | ||
|
|
4d2f7d83af | ||
|
|
99945fcd04 | ||
|
|
0d952ae43d | ||
|
|
593677d2ff | ||
|
|
c69294c449 | ||
|
|
2a06c7758e | ||
|
|
7ee1ec91a2 | ||
|
|
233fb62bd8 | ||
|
|
6637c267a5 | ||
|
|
99233c44cc | ||
|
|
33528002b4 | ||
|
|
20542a37a8 | ||
|
|
5fd12451f9 | ||
|
|
ba939ccd6c | ||
|
|
3a5f354846 | ||
|
|
fcde6109b0 | ||
|
|
e3bd223dac | ||
|
|
6c8db6eae1 | ||
|
|
3ff0b9e0c9 | ||
|
|
464a942a95 | ||
|
|
d7a4a4a462 | ||
|
|
759b3f7d6d | ||
|
|
958b6c2e57 | ||
|
|
ab15d676d7 | ||
|
|
66761d7ecf | ||
|
|
3afad58a93 | ||
|
|
170e8b519e | ||
|
|
f8684f418a | ||
|
|
881bda7f59 | ||
|
|
9854deb626 | ||
|
|
d6814050dd | ||
|
|
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 | ||
|
|
f652372c9a | ||
|
|
ad1fc3b71a | ||
|
|
2b40a5ac62 | ||
|
|
ca3388cf5a | ||
|
|
caa8896a8a | ||
|
|
d13aa3954d | ||
|
|
f64539fb76 | ||
|
|
d56ebd7d7b | ||
|
|
3edfe7d0ee | ||
|
|
7f77edadb3 | ||
|
|
a9511dfbe5 | ||
|
|
064e7aa1bb | ||
|
|
46814f88d9 | ||
|
|
4a19802d0c | ||
|
|
1e9f98aa51 | ||
|
|
11e24d53a1 | ||
|
|
0f509f8336 | ||
|
|
a6ed2c84ac | ||
|
|
a1958aad56 | ||
|
|
672699613e | ||
|
|
645d5bdbc5 | ||
|
|
9af2bbffde | ||
|
|
fcd544cc10 | ||
|
|
1e3bc0caa0 | ||
|
|
8227e8795b | ||
|
|
790b3bcdc6 | ||
|
|
d6e6458f68 | ||
|
|
a54b6703c0 | ||
|
|
8e6266136d | ||
|
|
5c22a1bdf5 | ||
|
|
9794ebf88c | ||
|
|
68394eed93 | ||
|
|
753b4b6cc8 | ||
|
|
a9c1b9f138 | ||
|
|
5af144522a | ||
|
|
483e0cadfb | ||
|
|
4b818056cf | ||
|
|
b956e5f1d9 | ||
|
|
37d7cb8565 | ||
|
|
2b8e206fec | ||
|
|
a869b854fa | ||
|
|
81f5efe39a | ||
|
|
69dde0462b | ||
|
|
7628bcac01 | ||
|
|
75f0bbe6e8 | ||
|
|
478bf4dbdd | ||
|
|
e0f67baf2d | ||
|
|
b14d3df3d2 | ||
|
|
24e58ee70c | ||
|
|
9b1a40dfc3 | ||
|
|
e4b078cff7 | ||
|
|
3bd7ca9961 | ||
|
|
f83aca65b7 | ||
|
|
aebafad41e | ||
|
|
26746ce316 | ||
|
|
dac6efb43d | ||
|
|
8880f4824c | ||
|
|
cb0c576bdd | ||
|
|
3a591c43fe | ||
|
|
db66eca958 | ||
|
|
f2767452e6 | ||
|
|
916faf0a48 | ||
|
|
f36e4e9a78 | ||
|
|
fdf8b5eb71 | ||
|
|
de7ec7f1b7 | ||
|
|
3c8a0bdff4 | ||
|
|
9e8ba27dcd | ||
|
|
719a8fd102 | ||
|
|
3a22e917de | ||
|
|
a9af2c9e62 | ||
|
|
31e99cebe7 | ||
|
|
a5b209470c | ||
|
|
e9a571b2a1 | ||
|
|
8bf83f42ea | ||
|
|
522566ea80 | ||
|
|
297af47c89 | ||
|
|
faa354f5ca | ||
|
|
1529ab965a | ||
|
|
605f330e69 | ||
|
|
f0909bdc8f | ||
|
|
c13e7e621d | ||
|
|
ad071f8017 | ||
|
|
c058d8b9cd | ||
|
|
1d8871a092 | ||
|
|
16953c2064 | ||
|
|
6b14f7c224 | ||
|
|
130c623be7 | ||
|
|
47c9895d59 | ||
|
|
ba403331c5 | ||
|
|
e82e89d1b0 | ||
|
|
83a4ebfedc | ||
|
|
9916d0e547 | ||
|
|
31c4a37e37 | ||
|
|
08219f0cee | ||
|
|
c4993e1e5c | ||
|
|
6064bea3db | ||
|
|
98978fc827 | ||
|
|
16430acc1f | ||
|
|
320c110b33 | ||
|
|
dbe33bbfc5 | ||
|
|
b5c3253b49 | ||
|
|
5cc90db7d0 | ||
|
|
f427e5efc7 | ||
|
|
e48802ad29 | ||
|
|
13c4dfcabd | ||
|
|
1abde9c8b0 | ||
|
|
4f555e2232 | ||
|
|
642ba2e92c | ||
|
|
089ac908b7 | ||
|
|
0d3fd2ef30 | ||
|
|
e98119496a | ||
|
|
bdfcbf496b | ||
|
|
dba8da4800 | ||
|
|
60c0f40250 | ||
|
|
e02771a5f2 | ||
|
|
f96f796f71 | ||
|
|
a9fa178f86 | ||
|
|
53355bdb24 | ||
|
|
f05c99d89f | ||
|
|
b49230ab8d | ||
|
|
78856a3dab | ||
|
|
1e5e13ed81 | ||
|
|
64270b9778 | ||
|
|
e312c5c2a7 | ||
|
|
1a5fd3e052 | ||
|
|
5a7e54cf72 | ||
|
|
39f8a62703 | ||
|
|
46be3f2bf1 | ||
|
|
258b46f4dc | ||
|
|
80da21dab4 | ||
|
|
bb0e4d7126 | ||
|
|
5276a4a873 | ||
|
|
a1ae0c8609 | ||
|
|
a90c1aeafe | ||
|
|
ff388a8d2d | ||
|
|
5346fb94bb | ||
|
|
a4f6d46118 | ||
|
|
7f5f4d60b7 | ||
|
|
ffccb233e5 | ||
|
|
fba0c1aafe | ||
|
|
774f2ded94 | ||
|
|
85af942d64 | ||
|
|
8413787efc | ||
|
|
dde57452aa | ||
|
|
cf409800be | ||
|
|
18270dd9f3 | ||
|
|
d4c25c571b | ||
|
|
5248b79506 | ||
|
|
abe0ebbf02 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.js text eol=lf
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1,3 @@
|
||||
/node_modules/
|
||||
/npm-debug.log
|
||||
tmp/
|
||||
|
||||
10
.travis.yml
Normal file
10
.travis.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
language: node_js
|
||||
before_install: "npm install -g npm"
|
||||
node_js:
|
||||
- "0.12"
|
||||
- "0.10"
|
||||
- "4"
|
||||
- "6"
|
||||
matrix:
|
||||
fast_finish: true
|
||||
sudo: false
|
||||
29
LICENSE
Normal file
29
LICENSE
Normal file
@@ -0,0 +1,29 @@
|
||||
UglifyJS is released under the BSD license:
|
||||
|
||||
Copyright 2012-2013 (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.
|
||||
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;
|
||||
}
|
||||
}
|
||||
631
bin/uglifyjs
Executable file
631
bin/uglifyjs
Executable file
@@ -0,0 +1,631 @@
|
||||
#! /usr/bin/env node
|
||||
// -*- js -*-
|
||||
|
||||
"use strict";
|
||||
|
||||
var UglifyJS = require("../tools/node");
|
||||
var sys = require("util");
|
||||
var yargs = require("yargs");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var async = require("async");
|
||||
var acorn;
|
||||
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\
|
||||
NOTE: by default there is no mangling/compression.\n\
|
||||
Without [options] it will simply parse input files and dump the AST\n\
|
||||
with whitespace and comments discarded. To achieve compression and\n\
|
||||
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-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", "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. \
|
||||
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.")
|
||||
.describe("r", "Reserved names to exclude from mangling.")
|
||||
.describe("c", "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.")
|
||||
.describe("d", "Global definitions")
|
||||
.describe("e", "Embed everything in a big function, with a configurable parameter/argument list.")
|
||||
|
||||
.describe("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:\n\
|
||||
- \"all\" to keep all comments\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).")
|
||||
.describe("self", "Build itself (UglifyJS2) as a library (implies --wrap=UglifyJS --export-all)")
|
||||
.describe("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.")
|
||||
.describe("export-all", "Only used when --wrap, this tells UglifyJS to add code to automatically export all globals.")
|
||||
.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")
|
||||
.alias("v", "verbose")
|
||||
.alias("b", "beautify")
|
||||
.alias("m", "mangle")
|
||||
.alias("c", "compress")
|
||||
.alias("d", "define")
|
||||
.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)
|
||||
|
||||
.argv
|
||||
;
|
||||
|
||||
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");
|
||||
print(json.name + ' ' + json.version);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (ARGS.ast_help) {
|
||||
var desc = UglifyJS.describe_ast();
|
||||
print(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (ARGS.h || ARGS.help) {
|
||||
print(yargs.help());
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (ARGS.acorn) {
|
||||
acorn = require("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.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,
|
||||
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 === "") {
|
||||
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) {
|
||||
print_error("WARN: Ignoring input files since --self was passed");
|
||||
}
|
||||
files = UglifyJS.FILES;
|
||||
if (!ARGS.wrap) ARGS.wrap = "UglifyJS";
|
||||
}
|
||||
|
||||
var ORIG_MAP = ARGS.in_source_map;
|
||||
|
||||
if (ORIG_MAP && ORIG_MAP != "inline") {
|
||||
ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
|
||||
if (files.length == 0) {
|
||||
print_error("INFO: Using file from the input source map: " + ORIG_MAP.file);
|
||||
files = [ ORIG_MAP.file ];
|
||||
}
|
||||
}
|
||||
|
||||
if (files.length == 0) {
|
||||
files = [ "-" ];
|
||||
}
|
||||
|
||||
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) {
|
||||
print_error("ERROR: can't read file: " + file);
|
||||
process.exit(1);
|
||||
}
|
||||
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);
|
||||
if (!TOPLEVEL) TOPLEVEL = program;
|
||||
else TOPLEVEL.body = TOPLEVEL.body.concat(program.body);
|
||||
}
|
||||
else if (ARGS.acorn) {
|
||||
TOPLEVEL = acorn.parse(code, {
|
||||
locations : true,
|
||||
sourceFile : file,
|
||||
program : TOPLEVEL
|
||||
});
|
||||
}
|
||||
else {
|
||||
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 != null) {
|
||||
TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all);
|
||||
}
|
||||
|
||||
if (ARGS.enclose != null) {
|
||||
var arg_parameter_list = ARGS.enclose;
|
||||
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);
|
||||
}
|
||||
|
||||
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(MANGLE || { screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||
if (ARGS.lint) {
|
||||
TOPLEVEL.scope_warnings();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (COMPRESS) {
|
||||
time_it("squeeze", function(){
|
||||
TOPLEVEL = compressor.compress(TOPLEVEL);
|
||||
});
|
||||
}
|
||||
|
||||
if (SCOPE_IS_NEEDED) {
|
||||
time_it("scope", function(){
|
||||
TOPLEVEL.figure_out_scope(MANGLE || { screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||
if (MANGLE && !TL_CACHE) {
|
||||
TOPLEVEL.compute_char_frequency(MANGLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (MANGLE) time_it("mangle", function(){
|
||||
TOPLEVEL.mangle_names(MANGLE);
|
||||
});
|
||||
|
||||
writeNameCache("vars", TL_CACHE);
|
||||
|
||||
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 (ARGS.dump_spidermonkey_ast) {
|
||||
print(JSON.stringify(TOPLEVEL.to_mozilla_ast(), null, 2));
|
||||
} else {
|
||||
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) {
|
||||
print_error(UglifyJS.string_template("Timing information (compressed {count} files):", {
|
||||
count: files.length
|
||||
}));
|
||||
for (var i in STATS) if (STATS.hasOwnProperty(i)) {
|
||||
print_error(UglifyJS.string_template("- {name}: {time}s", {
|
||||
name: i,
|
||||
time: (STATS[i] / 1000).toFixed(3)
|
||||
}));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* -----[ functions ]----- */
|
||||
|
||||
function normalize(o) {
|
||||
for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) {
|
||||
o[i.replace(/-/g, "_")] = o[i];
|
||||
delete o[i];
|
||||
}
|
||||
}
|
||||
|
||||
function getOptions(flag, constants) {
|
||||
var x = ARGS[flag];
|
||||
if (x == null || x === false) return null;
|
||||
var ret = {};
|
||||
if (x !== "") {
|
||||
if (Array.isArray(x)) x = x.map(function (v) { return "(" + v + ")"; }).join(", ");
|
||||
|
||||
var ast;
|
||||
try {
|
||||
ast = UglifyJS.parse(x, { expression: true });
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
||||
print_error("Error parsing arguments for flag `" + flag + "': " + x);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
ast.walk(new UglifyJS.TreeWalker(function(node){
|
||||
if (node instanceof UglifyJS.AST_Seq) return; // descend
|
||||
if (node instanceof UglifyJS.AST_Assign) {
|
||||
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
|
||||
}
|
||||
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);
|
||||
}));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function read_whole_file(filename, cb) {
|
||||
if (filename == "-") {
|
||||
var chunks = [];
|
||||
process.stdin.setEncoding('utf-8');
|
||||
process.stdin.on('data', function (chunk) {
|
||||
chunks.push(chunk);
|
||||
}).on('end', function () {
|
||||
cb(null, chunks.join(""));
|
||||
});
|
||||
process.openStdin();
|
||||
} else {
|
||||
fs.readFile(filename, "utf-8", 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();
|
||||
if (ARGS.stats) {
|
||||
var spent = new Date().getTime() - t1;
|
||||
if (STATS[name]) STATS[name] += spent;
|
||||
else STATS[name] = spent;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function print_error(msg) {
|
||||
console.error("%s", msg);
|
||||
}
|
||||
|
||||
function print(txt) {
|
||||
console.log("%s", txt);
|
||||
}
|
||||
359
bin/uglifyjs2
359
bin/uglifyjs2
@@ -1,359 +0,0 @@
|
||||
#! /usr/bin/env node
|
||||
// -*- js -*-
|
||||
|
||||
"use strict";
|
||||
|
||||
var UglifyJS = require("../tools/node");
|
||||
var sys = require("util");
|
||||
var optimist = require("optimist");
|
||||
var fs = require("fs");
|
||||
var acorn;
|
||||
var ARGS = optimist
|
||||
.usage("$0 input1.js [input2.js ...] [options]\n\
|
||||
Use a single dash to read input from the standard input.\
|
||||
\n\n\
|
||||
NOTE: by default there is no mangling/compression.\n\
|
||||
Without [options] it will simply parse input files and dump the AST\n\
|
||||
with whitespace and comments discarded. To achieve compression and\n\
|
||||
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("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
|
||||
.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.")
|
||||
.describe("o", "Output file (default STDOUT).")
|
||||
.describe("b", "Beautify output/specify output options.")
|
||||
.describe("m", "Mangle names/pass mangler options.")
|
||||
.describe("r", "Reserved names to exclude from mangling.")
|
||||
.describe("c", "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.")
|
||||
.describe("d", "Global definitions")
|
||||
|
||||
.describe("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:\n\
|
||||
- \"all\" to keep all comments\n\
|
||||
- a valid JS regexp (needs to start with a slash) to keep only comments that match.\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("stats", "Display operations run time on STDERR.")
|
||||
.describe("acorn", "Use Acorn for parsing.")
|
||||
.describe("spidermonkey", "Assume input fles are SpiderMonkey AST format (as JSON).")
|
||||
.describe("self", "Build itself (UglifyJS2) as a library (implies --wrap=UglifyJS --export-all)")
|
||||
.describe("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.")
|
||||
.describe("export-all", "Only used when --wrap, this tells UglifyJS to add code to automatically export all globals.")
|
||||
.describe("lint", "Display some scope warnings")
|
||||
.describe("v", "Verbose")
|
||||
|
||||
.alias("p", "prefix")
|
||||
.alias("o", "output")
|
||||
.alias("v", "verbose")
|
||||
.alias("b", "beautify")
|
||||
.alias("m", "mangle")
|
||||
.alias("c", "compress")
|
||||
.alias("d", "define")
|
||||
.alias("r", "reserved")
|
||||
|
||||
.string("source-map")
|
||||
.string("source-map-root")
|
||||
.string("b")
|
||||
.string("m")
|
||||
.string("c")
|
||||
.string("d")
|
||||
.string("comments")
|
||||
.string("wrap")
|
||||
.boolean("export-all")
|
||||
.boolean("self")
|
||||
.boolean("v")
|
||||
.boolean("stats")
|
||||
.boolean("acorn")
|
||||
.boolean("spidermonkey")
|
||||
.boolean("lint")
|
||||
|
||||
.wrap(80)
|
||||
|
||||
.argv
|
||||
;
|
||||
|
||||
normalize(ARGS);
|
||||
|
||||
if (ARGS.ast_help) {
|
||||
var desc = UglifyJS.describe_ast();
|
||||
sys.puts(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (ARGS.h || ARGS.help) {
|
||||
sys.puts(optimist.help());
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (ARGS.acorn) {
|
||||
acorn = require("acorn");
|
||||
}
|
||||
|
||||
var COMPRESS = getOptions("c", true);
|
||||
var MANGLE = getOptions("m", true);
|
||||
var BEAUTIFY = getOptions("b", true);
|
||||
|
||||
if (COMPRESS && ARGS.d) {
|
||||
COMPRESS.global_defs = getOptions("d");
|
||||
}
|
||||
|
||||
if (MANGLE && ARGS.r) {
|
||||
MANGLE.except = ARGS.r.replace(/^\s+|\s+$/g).split(/\s*,+\s*/);
|
||||
}
|
||||
|
||||
var OUTPUT_OPTIONS = {
|
||||
beautify: BEAUTIFY ? true : false
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var files = ARGS._.slice();
|
||||
|
||||
if (ARGS.self) {
|
||||
if (files.length > 0) {
|
||||
sys.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) {
|
||||
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);
|
||||
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));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
files.forEach(function(file) {
|
||||
var code = read_whole_file(file);
|
||||
if (ARGS.p != null) {
|
||||
file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/");
|
||||
}
|
||||
time_it("parse", function(){
|
||||
if (ARGS.spidermonkey) {
|
||||
var program = JSON.parse(code);
|
||||
if (!TOPLEVEL) TOPLEVEL = program;
|
||||
else TOPLEVEL.body = TOPLEVEL.body.concat(program.body);
|
||||
}
|
||||
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
|
||||
});
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
|
||||
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
|
||||
});
|
||||
|
||||
if (ARGS.wrap) {
|
||||
TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all);
|
||||
}
|
||||
|
||||
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint;
|
||||
|
||||
if (SCOPE_IS_NEEDED) {
|
||||
time_it("scope", function(){
|
||||
TOPLEVEL.figure_out_scope();
|
||||
if (ARGS.lint) {
|
||||
TOPLEVEL.scope_warnings();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (COMPRESS) {
|
||||
time_it("squeeze", function(){
|
||||
TOPLEVEL = TOPLEVEL.transform(compressor);
|
||||
});
|
||||
}
|
||||
|
||||
if (SCOPE_IS_NEEDED) {
|
||||
time_it("scope", function(){
|
||||
TOPLEVEL.figure_out_scope();
|
||||
if (MANGLE) {
|
||||
TOPLEVEL.compute_char_frequency();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (MANGLE) time_it("mangle", function(){
|
||||
TOPLEVEL.mangle_names(MANGLE);
|
||||
});
|
||||
time_it("generate", function(){
|
||||
TOPLEVEL.print(output);
|
||||
});
|
||||
|
||||
output = output.get();
|
||||
|
||||
if (SOURCE_MAP) {
|
||||
fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
|
||||
output += "\n//@ sourceMappingURL=" + ARGS.source_map;
|
||||
}
|
||||
|
||||
if (OUTPUT_FILE) {
|
||||
fs.writeFileSync(OUTPUT_FILE, output, "utf8");
|
||||
} else {
|
||||
sys.print(output);
|
||||
sys.error("\n");
|
||||
}
|
||||
|
||||
if (ARGS.stats) {
|
||||
sys.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", {
|
||||
name: i,
|
||||
time: (STATS[i] / 1000).toFixed(3)
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/* -----[ functions ]----- */
|
||||
|
||||
function normalize(o) {
|
||||
for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) {
|
||||
o[i.replace(/-/g, "_")] = o[i];
|
||||
delete o[i];
|
||||
}
|
||||
}
|
||||
|
||||
function getOptions(x, constants) {
|
||||
x = ARGS[x];
|
||||
if (!x) return null;
|
||||
var ret = {};
|
||||
if (x !== true) {
|
||||
var ast;
|
||||
try {
|
||||
ast = UglifyJS.parse(x);
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
||||
sys.error("Error parsing arguments in: " + 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 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);
|
||||
process.exit(1);
|
||||
}));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function read_whole_file(filename) {
|
||||
if (filename == "-") {
|
||||
// XXX: this sucks. How does one read the whole STDIN
|
||||
// synchronously?
|
||||
filename = "/dev/stdin";
|
||||
}
|
||||
try {
|
||||
return fs.readFileSync(filename, "utf8");
|
||||
} catch(ex) {
|
||||
sys.error("ERROR: can't read file: " + filename);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function time_it(name, cont) {
|
||||
var t1 = new Date().getTime();
|
||||
var ret = cont();
|
||||
if (ARGS.stats) {
|
||||
var spent = new Date().getTime() - t1;
|
||||
if (STATS[name]) STATS[name] += spent;
|
||||
else STATS[name] = spent;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
222
lib/ast.js
222
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_Statement) {
|
||||
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,7 @@ var AST_ForIn = DEFNODE("ForIn", "init name object", {
|
||||
this.body._walk(visitor);
|
||||
});
|
||||
}
|
||||
}, AST_StatementWithBody);
|
||||
}, AST_IterationStatement);
|
||||
|
||||
var AST_With = DEFNODE("With", "expression", {
|
||||
$documentation: "A `with` statement",
|
||||
@@ -285,11 +300,32 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
$propdoc: {
|
||||
globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
|
||||
},
|
||||
wrap_enclose: function(arg_parameter_pairs) {
|
||||
var self = this;
|
||||
var args = [];
|
||||
var parameters = [];
|
||||
|
||||
arg_parameter_pairs.forEach(function(pair) {
|
||||
var splitAt = pair.lastIndexOf(":");
|
||||
|
||||
args.push(pair.substr(0, splitAt));
|
||||
parameters.push(pair.substr(splitAt + 1));
|
||||
});
|
||||
|
||||
var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
|
||||
wrapped_tl = parse(wrapped_tl);
|
||||
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
|
||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
||||
return MAP.splice(self.body);
|
||||
}
|
||||
}));
|
||||
return wrapped_tl;
|
||||
},
|
||||
wrap_commonjs: function(name, export_all) {
|
||||
var self = this;
|
||||
var to_export = [];
|
||||
if (export_all) {
|
||||
self.figure_out_scope();
|
||||
var to_export = [];
|
||||
self.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_SymbolDeclaration && node.definition().global) {
|
||||
if (!find_if(function(n){ return n.name == node.name }, to_export))
|
||||
@@ -297,12 +333,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":
|
||||
@@ -337,14 +372,19 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
|
||||
_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. The `name` property is always null."
|
||||
}, AST_Lambda);
|
||||
|
||||
var AST_Function = DEFNODE("Function", null, {
|
||||
$documentation: "A function expression"
|
||||
}, AST_Lambda);
|
||||
@@ -469,12 +509,6 @@ 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: {
|
||||
@@ -501,9 +535,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);
|
||||
@@ -541,9 +576,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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -603,6 +639,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);
|
||||
@@ -703,9 +746,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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -717,9 +761,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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -727,7 +772,7 @@ 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",
|
||||
key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an arbitrary AST_Node.",
|
||||
value: "[AST_Node] property value. For setters and getters this is an AST_Function."
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
@@ -737,8 +782,11 @@ var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
||||
}
|
||||
});
|
||||
|
||||
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, {
|
||||
@@ -758,6 +806,10 @@ var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
|
||||
$documentation: "Base class for all symbols",
|
||||
});
|
||||
|
||||
var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
|
||||
$documentation: "The name of a property accessor (setter/getter function)"
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
|
||||
$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
|
||||
$propdoc: {
|
||||
@@ -792,7 +844,11 @@ var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
|
||||
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);
|
||||
|
||||
@@ -802,7 +858,7 @@ var AST_SymbolRef = DEFNODE("SymbolRef", null, {
|
||||
|
||||
var AST_LabelRef = DEFNODE("LabelRef", null, {
|
||||
$documentation: "Reference to a label symbol",
|
||||
}, AST_SymbolRef);
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_This = DEFNODE("This", null, {
|
||||
$documentation: "The `this` symbol",
|
||||
@@ -815,17 +871,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);
|
||||
|
||||
@@ -855,6 +913,11 @@ var AST_Undefined = DEFNODE("Undefined", null, {
|
||||
value: (function(){}())
|
||||
}, AST_Atom);
|
||||
|
||||
var AST_Hole = DEFNODE("Hole", null, {
|
||||
$documentation: "A hole in an array",
|
||||
value: (function(){}())
|
||||
}, AST_Atom);
|
||||
|
||||
var AST_Infinity = DEFNODE("Infinity", null, {
|
||||
$documentation: "The `Infinity` value",
|
||||
value: 1/0
|
||||
@@ -879,27 +942,36 @@ var AST_True = DEFNODE("True", null, {
|
||||
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;
|
||||
}
|
||||
this.stack.push(node);
|
||||
},
|
||||
pop: function() {
|
||||
return this.stack.pop();
|
||||
pop: function(node) {
|
||||
this.stack.pop();
|
||||
if (node instanceof AST_Lambda) {
|
||||
this.directives = Object.getPrototypeOf(this.directives);
|
||||
}
|
||||
},
|
||||
self: function() {
|
||||
return this.stack[this.stack.length - 1];
|
||||
@@ -911,6 +983,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) {
|
||||
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];
|
||||
@@ -931,21 +1015,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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
2429
lib/compress.js
2429
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,23 +217,20 @@
|
||||
}
|
||||
};
|
||||
|
||||
function From_Moz_Unary(M) {
|
||||
return new (M.prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
|
||||
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)({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
operator : M.operator,
|
||||
expression : from_moz(M.argument)
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
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");
|
||||
@@ -177,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;
|
||||
@@ -262,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)
|
||||
};
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
675
lib/output.js
675
lib/output.js
File diff suppressed because it is too large
Load Diff
466
lib/parse.js
466
lib/parse.js
@@ -46,7 +46,7 @@
|
||||
|
||||
var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with';
|
||||
var KEYWORDS_ATOM = 'false null true';
|
||||
var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile'
|
||||
var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield'
|
||||
+ " " + KEYWORDS_ATOM + " " + KEYWORDS;
|
||||
var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
|
||||
|
||||
@@ -59,7 +59,6 @@ var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
|
||||
|
||||
var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
|
||||
var RE_OCT_NUMBER = /^0[0-7]+$/;
|
||||
var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
|
||||
|
||||
var OPERATORS = makePredicate([
|
||||
"in",
|
||||
@@ -108,7 +107,9 @@ var OPERATORS = makePredicate([
|
||||
"||"
|
||||
]);
|
||||
|
||||
var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000"));
|
||||
var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\uFEFF"));
|
||||
|
||||
var NEWLINE_CHARS = makePredicate(characters("\n\r\u2028\u2029"));
|
||||
|
||||
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
|
||||
|
||||
@@ -120,7 +121,8 @@ var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
|
||||
|
||||
// regexps adapted from http://xregexp.com/plugins/#unicode
|
||||
var UNICODE = {
|
||||
letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),
|
||||
letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),
|
||||
digit: new RegExp("[\\u0030-\\u0039\\u0660-\\u0669\\u06F0-\\u06F9\\u07C0-\\u07C9\\u0966-\\u096F\\u09E6-\\u09EF\\u0A66-\\u0A6F\\u0AE6-\\u0AEF\\u0B66-\\u0B6F\\u0BE6-\\u0BEF\\u0C66-\\u0C6F\\u0CE6-\\u0CEF\\u0D66-\\u0D6F\\u0DE6-\\u0DEF\\u0E50-\\u0E59\\u0ED0-\\u0ED9\\u0F20-\\u0F29\\u1040-\\u1049\\u1090-\\u1099\\u17E0-\\u17E9\\u1810-\\u1819\\u1946-\\u194F\\u19D0-\\u19D9\\u1A80-\\u1A89\\u1A90-\\u1A99\\u1B50-\\u1B59\\u1BB0-\\u1BB9\\u1C40-\\u1C49\\u1C50-\\u1C59\\uA620-\\uA629\\uA8D0-\\uA8D9\\uA900-\\uA909\\uA9D0-\\uA9D9\\uA9F0-\\uA9F9\\uAA50-\\uAA59\\uABF0-\\uABF9\\uFF10-\\uFF19]"),
|
||||
non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"),
|
||||
space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"),
|
||||
connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
|
||||
@@ -133,13 +135,17 @@ function is_letter(code) {
|
||||
};
|
||||
|
||||
function is_digit(code) {
|
||||
return code >= 48 && code <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9
|
||||
return code >= 48 && code <= 57;
|
||||
};
|
||||
|
||||
function is_alphanumeric_char(code) {
|
||||
return is_digit(code) || is_letter(code);
|
||||
};
|
||||
|
||||
function is_unicode_digit(code) {
|
||||
return UNICODE.digit.test(String.fromCharCode(code));
|
||||
}
|
||||
|
||||
function is_unicode_combining_mark(ch) {
|
||||
return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
|
||||
};
|
||||
@@ -149,7 +155,7 @@ function is_unicode_connector_punctuation(ch) {
|
||||
};
|
||||
|
||||
function is_identifier(name) {
|
||||
return /^[a-z_$][a-z0-9_$]*$/i.test(name) && !RESERVED_WORDS(name);
|
||||
return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name);
|
||||
};
|
||||
|
||||
function is_identifier_start(code) {
|
||||
@@ -164,39 +170,39 @@ function is_identifier_char(ch) {
|
||||
|| code == 8205 // \u200d: zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
|
||||
|| is_unicode_combining_mark(ch)
|
||||
|| is_unicode_connector_punctuation(ch)
|
||||
|| is_unicode_digit(code)
|
||||
;
|
||||
};
|
||||
|
||||
function is_identifier_string(str){
|
||||
return /^[a-z_$][a-z0-9_$]*$/i.test(str);
|
||||
};
|
||||
|
||||
function parse_js_number(num) {
|
||||
if (RE_HEX_NUMBER.test(num)) {
|
||||
return parseInt(num.substr(2), 16);
|
||||
} else if (RE_OCT_NUMBER.test(num)) {
|
||||
return parseInt(num.substr(1), 8);
|
||||
} else if (RE_DEC_NUMBER.test(num)) {
|
||||
return parseFloat(num);
|
||||
} else {
|
||||
var val = parseFloat(num);
|
||||
if (val == num) return val;
|
||||
}
|
||||
};
|
||||
|
||||
function JS_Parse_Error(message, line, col, pos) {
|
||||
function JS_Parse_Error(message, filename, line, col, pos) {
|
||||
this.message = message;
|
||||
this.filename = filename;
|
||||
this.line = line;
|
||||
this.col = col;
|
||||
this.pos = pos;
|
||||
this.stack = new Error().stack;
|
||||
};
|
||||
|
||||
JS_Parse_Error.prototype.toString = function() {
|
||||
return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
|
||||
};
|
||||
JS_Parse_Error.prototype = Object.create(Error.prototype);
|
||||
JS_Parse_Error.prototype.constructor = JS_Parse_Error;
|
||||
JS_Parse_Error.prototype.name = "SyntaxError";
|
||||
configure_error_stack(JS_Parse_Error);
|
||||
|
||||
function js_error(message, filename, line, col, pos) {
|
||||
AST_Node.warn("ERROR: {message} [{file}:{line},{col}]", {
|
||||
message: message,
|
||||
file: filename,
|
||||
line: line,
|
||||
col: col
|
||||
});
|
||||
throw new JS_Parse_Error(message, line, col, pos);
|
||||
throw new JS_Parse_Error(message, filename, line, col, pos);
|
||||
};
|
||||
|
||||
function is_token(token, type, val) {
|
||||
@@ -205,10 +211,10 @@ function is_token(token, type, val) {
|
||||
|
||||
var EX_EOF = {};
|
||||
|
||||
function tokenizer($TEXT, filename) {
|
||||
function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
|
||||
var S = {
|
||||
text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ''),
|
||||
text : $TEXT,
|
||||
filename : filename,
|
||||
pos : 0,
|
||||
tokpos : 0,
|
||||
@@ -218,7 +224,9 @@ function tokenizer($TEXT, filename) {
|
||||
tokcol : 0,
|
||||
newline_before : false,
|
||||
regex_allowed : false,
|
||||
comments_before : []
|
||||
comments_before : [],
|
||||
directives : {},
|
||||
directive_stack : []
|
||||
};
|
||||
|
||||
function peek() { return S.text.charAt(S.pos); };
|
||||
@@ -227,16 +235,39 @@ function tokenizer($TEXT, filename) {
|
||||
var ch = S.text.charAt(S.pos++);
|
||||
if (signal_eof && !ch)
|
||||
throw EX_EOF;
|
||||
if (ch == "\n") {
|
||||
if (NEWLINE_CHARS(ch)) {
|
||||
S.newline_before = S.newline_before || !in_string;
|
||||
++S.line;
|
||||
S.col = 0;
|
||||
if (!in_string && ch == "\r" && peek() == "\n") {
|
||||
// treat a \r\n sequence as a single \n
|
||||
++S.pos;
|
||||
ch = "\n";
|
||||
}
|
||||
} else {
|
||||
++S.col;
|
||||
}
|
||||
return ch;
|
||||
};
|
||||
|
||||
function forward(i) {
|
||||
while (i-- > 0) next();
|
||||
};
|
||||
|
||||
function looking_at(str) {
|
||||
return S.text.substr(S.pos, str.length) == str;
|
||||
};
|
||||
|
||||
function find_eol() {
|
||||
var text = S.text;
|
||||
for (var i = S.pos, n = S.text.length; i < n; ++i) {
|
||||
var ch = text[i];
|
||||
if (NEWLINE_CHARS(ch))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
function find(what, signal_eof) {
|
||||
var pos = S.text.indexOf(what, S.pos);
|
||||
if (signal_eof && pos == -1) throw EX_EOF;
|
||||
@@ -249,20 +280,27 @@ function tokenizer($TEXT, filename) {
|
||||
S.tokpos = S.pos;
|
||||
};
|
||||
|
||||
var prev_was_dot = false;
|
||||
function token(type, value, is_comment) {
|
||||
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) ||
|
||||
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX(value)) ||
|
||||
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) ||
|
||||
(type == "punc" && PUNC_BEFORE_EXPRESSION(value)));
|
||||
prev_was_dot = (type == "punc" && value == ".");
|
||||
var ret = {
|
||||
type : type,
|
||||
value : value,
|
||||
line : S.tokline,
|
||||
col : S.tokcol,
|
||||
pos : S.tokpos,
|
||||
endpos : S.pos,
|
||||
nlb : S.newline_before,
|
||||
file : filename
|
||||
type : type,
|
||||
value : value,
|
||||
line : S.tokline,
|
||||
col : S.tokcol,
|
||||
pos : S.tokpos,
|
||||
endline : S.line,
|
||||
endcol : S.col,
|
||||
endpos : S.pos,
|
||||
nlb : S.newline_before,
|
||||
file : filename
|
||||
};
|
||||
if (/^(?:num|string|regexp)$/i.test(type)) {
|
||||
ret.raw = $TEXT.substring(ret.pos, ret.endpos);
|
||||
}
|
||||
if (!is_comment) {
|
||||
ret.comments_before = S.comments_before;
|
||||
S.comments_before = [];
|
||||
@@ -310,6 +348,9 @@ function tokenizer($TEXT, filename) {
|
||||
return is_alphanumeric_char(code);
|
||||
});
|
||||
if (prefix) num = prefix + num;
|
||||
if (RE_OCT_NUMBER.test(num) && next_token.has_directive("use strict")) {
|
||||
parse_error("Legacy octal literals are not allowed in strict mode");
|
||||
}
|
||||
var valid = parse_js_number(num);
|
||||
if (!isNaN(valid)) {
|
||||
return token("num", valid);
|
||||
@@ -327,14 +368,36 @@ function tokenizer($TEXT, filename) {
|
||||
case 98 : return "\b";
|
||||
case 118 : return "\u000b"; // \v
|
||||
case 102 : return "\f";
|
||||
case 48 : return "\0";
|
||||
case 120 : return String.fromCharCode(hex_bytes(2)); // \x
|
||||
case 117 : return String.fromCharCode(hex_bytes(4)); // \u
|
||||
case 10 : return ""; // newline
|
||||
default : return ch;
|
||||
case 13 : // \r
|
||||
if (peek() == "\n") { // DOS newline
|
||||
next(true, in_string);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
if (ch >= "0" && ch <= "7")
|
||||
return read_octal_escape_sequence(ch);
|
||||
return ch;
|
||||
};
|
||||
|
||||
function read_octal_escape_sequence(ch) {
|
||||
// Read
|
||||
var p = peek();
|
||||
if (p >= "0" && p <= "7") {
|
||||
ch += next(true);
|
||||
if (ch[0] <= "3" && (p = peek()) >= "0" && p <= "7")
|
||||
ch += next(true);
|
||||
}
|
||||
|
||||
// Parse
|
||||
if (ch === "0") return "\0";
|
||||
if (ch.length > 0 && next_token.has_directive("use strict"))
|
||||
parse_error("Legacy octal escape sequences are not allowed in strict mode");
|
||||
return String.fromCharCode(parseInt(ch, 8));
|
||||
}
|
||||
|
||||
function hex_bytes(n) {
|
||||
var num = 0;
|
||||
for (; n > 0; --n) {
|
||||
@@ -346,37 +409,23 @@ function tokenizer($TEXT, filename) {
|
||||
return num;
|
||||
};
|
||||
|
||||
var read_string = with_eof_error("Unterminated string constant", function(){
|
||||
var read_string = with_eof_error("Unterminated string constant", function(quote_char){
|
||||
var quote = next(), ret = "";
|
||||
for (;;) {
|
||||
var ch = next(true);
|
||||
if (ch == "\\") {
|
||||
// read OctalEscapeSequence (XXX: deprecated if "strict mode")
|
||||
// https://github.com/mishoo/UglifyJS/issues/178
|
||||
var octal_len = 0, first = null;
|
||||
ch = read_while(function(ch){
|
||||
if (ch >= "0" && ch <= "7") {
|
||||
if (!first) {
|
||||
first = ch;
|
||||
return ++octal_len;
|
||||
}
|
||||
else if (first <= "3" && octal_len <= 2) return ++octal_len;
|
||||
else if (first >= "4" && octal_len <= 1) return ++octal_len;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));
|
||||
else ch = read_escaped_char(true);
|
||||
}
|
||||
var ch = next(true, true);
|
||||
if (ch == "\\") ch = read_escaped_char(true);
|
||||
else if (NEWLINE_CHARS(ch)) parse_error("Unterminated string constant");
|
||||
else if (ch == quote) break;
|
||||
ret += ch;
|
||||
}
|
||||
return token("string", ret);
|
||||
var tok = token("string", ret);
|
||||
tok.quote = quote_char;
|
||||
return tok;
|
||||
});
|
||||
|
||||
function read_line_comment() {
|
||||
next();
|
||||
var i = find("\n"), ret;
|
||||
function skip_line_comment(type) {
|
||||
var regex_allowed = S.regex_allowed;
|
||||
var i = find_eol(), ret;
|
||||
if (i == -1) {
|
||||
ret = S.text.substr(S.pos);
|
||||
S.pos = S.text.length;
|
||||
@@ -384,22 +433,21 @@ function tokenizer($TEXT, filename) {
|
||||
ret = S.text.substring(S.pos, i);
|
||||
S.pos = i;
|
||||
}
|
||||
return token("comment1", ret, true);
|
||||
S.col = S.tokcol + (S.pos - S.tokpos);
|
||||
S.comments_before.push(token(type, ret, true));
|
||||
S.regex_allowed = regex_allowed;
|
||||
return next_token;
|
||||
};
|
||||
|
||||
var read_multiline_comment = with_eof_error("Unterminated multiline comment", function(){
|
||||
next();
|
||||
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){
|
||||
var regex_allowed = S.regex_allowed;
|
||||
var i = find("*/", true);
|
||||
var text = S.text.substring(S.pos, i);
|
||||
var a = text.split("\n"), n = a.length;
|
||||
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n');
|
||||
// update stream position
|
||||
S.pos = i + 2;
|
||||
S.line += n - 1;
|
||||
if (n > 1) S.col = a[n - 1].length;
|
||||
else S.col += a[n - 1].length;
|
||||
S.col += 2;
|
||||
S.newline_before = S.newline_before || text.indexOf("\n") >= 0;
|
||||
return token("comment2", text, true);
|
||||
forward(text.length /* doesn't count \r\n as 2 char while S.pos - i does */ + 2);
|
||||
S.comments_before.push(token("comment2", text, true));
|
||||
S.regex_allowed = regex_allowed;
|
||||
return next_token;
|
||||
});
|
||||
|
||||
function read_name() {
|
||||
@@ -427,7 +475,9 @@ function tokenizer($TEXT, filename) {
|
||||
|
||||
var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){
|
||||
var prev_backslash = false, ch, in_class = false;
|
||||
while ((ch = next(true))) if (prev_backslash) {
|
||||
while ((ch = next(true))) if (NEWLINE_CHARS(ch)) {
|
||||
parse_error("Unexpected line terminator");
|
||||
} else if (prev_backslash) {
|
||||
regexp += "\\" + ch;
|
||||
prev_backslash = false;
|
||||
} else if (ch == "[") {
|
||||
@@ -444,7 +494,11 @@ function tokenizer($TEXT, filename) {
|
||||
regexp += ch;
|
||||
}
|
||||
var mods = read_name();
|
||||
return token("regexp", new RegExp(regexp, mods));
|
||||
try {
|
||||
return token("regexp", new RegExp(regexp, mods));
|
||||
} catch(e) {
|
||||
parse_error(e.message);
|
||||
}
|
||||
});
|
||||
|
||||
function read_operator(prefix) {
|
||||
@@ -463,16 +517,13 @@ function tokenizer($TEXT, filename) {
|
||||
|
||||
function handle_slash() {
|
||||
next();
|
||||
var regex_allowed = S.regex_allowed;
|
||||
switch (peek()) {
|
||||
case "/":
|
||||
S.comments_before.push(read_line_comment());
|
||||
S.regex_allowed = regex_allowed;
|
||||
return next_token();
|
||||
next();
|
||||
return skip_line_comment("comment1");
|
||||
case "*":
|
||||
S.comments_before.push(read_multiline_comment());
|
||||
S.regex_allowed = regex_allowed;
|
||||
return next_token();
|
||||
next();
|
||||
return skip_multiline_comment();
|
||||
}
|
||||
return S.regex_allowed ? read_regexp("") : read_operator("/");
|
||||
};
|
||||
@@ -486,6 +537,7 @@ function tokenizer($TEXT, filename) {
|
||||
|
||||
function read_word() {
|
||||
var word = read_name();
|
||||
if (prev_was_dot) return token("name", word);
|
||||
return KEYWORDS_ATOM(word) ? token("atom", word)
|
||||
: !KEYWORDS(word) ? token("name", word)
|
||||
: OPERATORS(word) ? token("operator", word)
|
||||
@@ -506,20 +558,46 @@ function tokenizer($TEXT, filename) {
|
||||
function next_token(force_regexp) {
|
||||
if (force_regexp != null)
|
||||
return read_regexp(force_regexp);
|
||||
skip_whitespace();
|
||||
start_token();
|
||||
var ch = peek();
|
||||
if (!ch) return token("eof");
|
||||
var code = ch.charCodeAt(0);
|
||||
switch (code) {
|
||||
case 34: case 39: return read_string();
|
||||
case 46: return handle_dot();
|
||||
case 47: return handle_slash();
|
||||
for (;;) {
|
||||
skip_whitespace();
|
||||
start_token();
|
||||
if (html5_comments) {
|
||||
if (looking_at("<!--")) {
|
||||
forward(4);
|
||||
skip_line_comment("comment3");
|
||||
continue;
|
||||
}
|
||||
if (looking_at("-->") && S.newline_before) {
|
||||
forward(3);
|
||||
skip_line_comment("comment4");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
var ch = peek();
|
||||
if (!ch) return token("eof");
|
||||
var code = ch.charCodeAt(0);
|
||||
switch (code) {
|
||||
case 34: case 39: return read_string(ch);
|
||||
case 46: return handle_dot();
|
||||
case 47: {
|
||||
var tok = handle_slash();
|
||||
if (tok === next_token) continue;
|
||||
return tok;
|
||||
}
|
||||
}
|
||||
if (is_digit(code)) return read_num();
|
||||
if (PUNC_CHARS(ch)) return token("punc", next());
|
||||
if (OPERATOR_CHARS(ch)) return read_operator();
|
||||
if (code == 92 || is_identifier_start(code)) return read_word();
|
||||
if (shebang) {
|
||||
if (S.pos == 0 && looking_at("#!")) {
|
||||
forward(2);
|
||||
skip_line_comment("comment5");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (is_digit(code)) return read_num();
|
||||
if (PUNC_CHARS(ch)) return token("punc", next());
|
||||
if (OPERATOR_CHARS(ch)) return read_operator();
|
||||
if (code == 92 || is_identifier_start(code)) return read_word();
|
||||
parse_error("Unexpected character '" + ch + "'");
|
||||
};
|
||||
|
||||
@@ -528,6 +606,35 @@ function tokenizer($TEXT, filename) {
|
||||
return S;
|
||||
};
|
||||
|
||||
next_token.add_directive = function(directive) {
|
||||
S.directive_stack[S.directive_stack.length - 1].push(directive);
|
||||
|
||||
if (S.directives[directive] === undefined) {
|
||||
S.directives[directive] = 1;
|
||||
} else {
|
||||
S.directives[directive]++;
|
||||
}
|
||||
}
|
||||
|
||||
next_token.push_directives_stack = function() {
|
||||
S.directive_stack.push([]);
|
||||
}
|
||||
|
||||
next_token.pop_directives_stack = function() {
|
||||
var directives = S.directive_stack[S.directive_stack.length - 1];
|
||||
|
||||
for (var i = 0; i < directives.length; i++) {
|
||||
S.directives[directives[i]]--;
|
||||
}
|
||||
|
||||
S.directive_stack.pop();
|
||||
}
|
||||
|
||||
next_token.has_directive = function(directive) {
|
||||
return S.directives[directive] !== undefined &&
|
||||
S.directives[directive] > 0;
|
||||
}
|
||||
|
||||
return next_token;
|
||||
|
||||
};
|
||||
@@ -551,10 +658,10 @@ var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
|
||||
var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
|
||||
|
||||
var PRECEDENCE = (function(a, ret){
|
||||
for (var i = 0, n = 1; i < a.length; ++i, ++n) {
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
var b = a[i];
|
||||
for (var j = 0; j < b.length; ++j) {
|
||||
ret[b[j]] = n;
|
||||
ret[b[j]] = i + 1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@@ -583,13 +690,20 @@ var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "nam
|
||||
function parse($TEXT, options) {
|
||||
|
||||
options = defaults(options, {
|
||||
strict : false,
|
||||
filename : null,
|
||||
toplevel : null
|
||||
strict : false,
|
||||
filename : null,
|
||||
toplevel : null,
|
||||
expression : false,
|
||||
html5_comments : true,
|
||||
bare_returns : false,
|
||||
shebang : true,
|
||||
});
|
||||
|
||||
var S = {
|
||||
input : typeof $TEXT == "string" ? tokenizer($TEXT, options.filename) : $TEXT,
|
||||
input : (typeof $TEXT == "string"
|
||||
? tokenizer($TEXT, options.filename,
|
||||
options.html5_comments, options.shebang)
|
||||
: $TEXT),
|
||||
token : null,
|
||||
prev : null,
|
||||
peeked : null,
|
||||
@@ -659,9 +773,9 @@ function parse($TEXT, options) {
|
||||
);
|
||||
};
|
||||
|
||||
function semicolon() {
|
||||
function semicolon(optional) {
|
||||
if (is("punc", ";")) next();
|
||||
else if (!can_insert_semicolon()) unexpected();
|
||||
else if (!optional && !can_insert_semicolon()) unexpected();
|
||||
};
|
||||
|
||||
function parenthesised() {
|
||||
@@ -682,18 +796,35 @@ function parse($TEXT, options) {
|
||||
};
|
||||
};
|
||||
|
||||
var statement = embed_tokens(function() {
|
||||
var tmp;
|
||||
function handle_regexp() {
|
||||
if (is("operator", "/") || is("operator", "/=")) {
|
||||
S.peeked = null;
|
||||
S.token = S.input(S.token.value.substr(1)); // force regexp
|
||||
}
|
||||
};
|
||||
|
||||
var statement = embed_tokens(function() {
|
||||
var tmp;
|
||||
handle_regexp();
|
||||
switch (S.token.type) {
|
||||
case "string":
|
||||
var dir = false;
|
||||
if (S.in_directives === true) {
|
||||
if ((is_token(peek(), "punc", ";") || peek().nlb) && S.token.raw.indexOf("\\") === -1) {
|
||||
S.input.add_directive(S.token.value);
|
||||
} else {
|
||||
S.in_directives = false;
|
||||
}
|
||||
}
|
||||
var dir = S.in_directives, stat = simple_statement();
|
||||
// XXXv2: decide how to fix directives
|
||||
if (dir && stat.body instanceof AST_String && !is("punc", ","))
|
||||
return new AST_Directive({ value: stat.body.value });
|
||||
if (dir) {
|
||||
return new AST_Directive({
|
||||
start : stat.body.start,
|
||||
end : stat.body.end,
|
||||
quote : stat.body.quote,
|
||||
value : stat.body.value,
|
||||
});
|
||||
}
|
||||
return stat;
|
||||
case "num":
|
||||
case "regexp":
|
||||
@@ -718,6 +849,7 @@ function parse($TEXT, options) {
|
||||
case "(":
|
||||
return simple_statement();
|
||||
case ";":
|
||||
S.in_directives = false;
|
||||
next();
|
||||
return new AST_EmptyStatement();
|
||||
default:
|
||||
@@ -739,7 +871,7 @@ function parse($TEXT, options) {
|
||||
case "do":
|
||||
return new AST_Do({
|
||||
body : in_loop(statement),
|
||||
condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp)
|
||||
condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(true), tmp)
|
||||
});
|
||||
|
||||
case "while":
|
||||
@@ -752,13 +884,13 @@ function parse($TEXT, options) {
|
||||
return for_();
|
||||
|
||||
case "function":
|
||||
return function_(true);
|
||||
return function_(AST_Defun);
|
||||
|
||||
case "if":
|
||||
return if_();
|
||||
|
||||
case "return":
|
||||
if (S.in_function == 0)
|
||||
if (S.in_function == 0 && !options.bare_returns)
|
||||
croak("'return' outside of function");
|
||||
return new AST_Return({
|
||||
value: ( is("punc", ";")
|
||||
@@ -791,6 +923,9 @@ function parse($TEXT, options) {
|
||||
return tmp = const_(), semicolon(), tmp;
|
||||
|
||||
case "with":
|
||||
if (S.input.has_directive("use strict")) {
|
||||
croak("Strict mode may not include a with statement");
|
||||
}
|
||||
return new AST_With({
|
||||
expression : parenthesised(),
|
||||
body : statement()
|
||||
@@ -815,6 +950,18 @@ function parse($TEXT, options) {
|
||||
S.labels.push(label);
|
||||
var stat = statement();
|
||||
S.labels.pop();
|
||||
if (!(stat instanceof AST_IterationStatement)) {
|
||||
// check for `continue` that refers to this label.
|
||||
// those should be reported as syntax errors.
|
||||
// https://github.com/mishoo/UglifyJS2/issues/287
|
||||
label.references.forEach(function(ref){
|
||||
if (ref instanceof AST_Continue) {
|
||||
ref = ref.label.start;
|
||||
croak("Continue label `" + label.name + "` refers to non-IterationStatement.",
|
||||
ref.line, ref.col, ref.pos);
|
||||
}
|
||||
});
|
||||
}
|
||||
return new AST_LabeledStatement({ body: stat, label: label });
|
||||
};
|
||||
|
||||
@@ -823,18 +970,22 @@ function parse($TEXT, options) {
|
||||
};
|
||||
|
||||
function break_cont(type) {
|
||||
var label = null;
|
||||
var label = null, ldef;
|
||||
if (!can_insert_semicolon()) {
|
||||
label = as_symbol(AST_LabelRef, true);
|
||||
}
|
||||
if (label != null) {
|
||||
if (!find_if(function(l){ return l.name == label.name }, S.labels))
|
||||
ldef = find_if(function(l){ return l.name == label.name }, S.labels);
|
||||
if (!ldef)
|
||||
croak("Undefined label " + label.name);
|
||||
label.thedef = ldef;
|
||||
}
|
||||
else if (S.in_loop == 0)
|
||||
croak(type.TYPE + " not inside a loop or switch");
|
||||
semicolon();
|
||||
return new type({ label: label });
|
||||
var stat = new type({ label: label });
|
||||
if (ldef) ldef.references.push(stat);
|
||||
return stat;
|
||||
};
|
||||
|
||||
function for_() {
|
||||
@@ -880,14 +1031,12 @@ function parse($TEXT, options) {
|
||||
});
|
||||
};
|
||||
|
||||
var function_ = function(in_statement, ctor) {
|
||||
var name = is("name") ? as_symbol(in_statement
|
||||
? AST_SymbolDefun
|
||||
: AST_SymbolLambda) : null;
|
||||
var function_ = function(ctor) {
|
||||
var in_statement = ctor === AST_Defun;
|
||||
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
|
||||
if (in_statement && !name)
|
||||
unexpected();
|
||||
expect("(");
|
||||
if (!ctor) ctor = in_statement ? AST_Defun : AST_Function;
|
||||
return new ctor({
|
||||
name: name,
|
||||
argnames: (function(first, a){
|
||||
@@ -901,9 +1050,11 @@ function parse($TEXT, options) {
|
||||
body: (function(loop, labels){
|
||||
++S.in_function;
|
||||
S.in_directives = true;
|
||||
S.input.push_directives_stack();
|
||||
S.in_loop = 0;
|
||||
S.labels = [];
|
||||
var a = block_();
|
||||
S.input.pop_directives_stack();
|
||||
--S.in_function;
|
||||
S.in_loop = loop;
|
||||
S.labels = labels;
|
||||
@@ -1036,7 +1187,7 @@ function parse($TEXT, options) {
|
||||
});
|
||||
};
|
||||
|
||||
var new_ = function() {
|
||||
var new_ = function(allow_calls) {
|
||||
var start = S.token;
|
||||
expect_token("operator", "new");
|
||||
var newexp = expr_atom(false), args;
|
||||
@@ -1051,19 +1202,26 @@ function parse($TEXT, options) {
|
||||
expression : newexp,
|
||||
args : args,
|
||||
end : prev()
|
||||
}), true);
|
||||
}), allow_calls);
|
||||
};
|
||||
|
||||
function as_atom_node() {
|
||||
var tok = S.token, ret;
|
||||
switch (tok.type) {
|
||||
case "name":
|
||||
return as_symbol(AST_SymbolRef);
|
||||
case "keyword":
|
||||
ret = _make_symbol(AST_SymbolRef);
|
||||
break;
|
||||
case "num":
|
||||
ret = new AST_Number({ start: tok, end: tok, value: tok.value });
|
||||
break;
|
||||
case "string":
|
||||
ret = new AST_String({ start: tok, end: tok, value: tok.value });
|
||||
ret = new AST_String({
|
||||
start : tok,
|
||||
end : tok,
|
||||
value : tok.value,
|
||||
quote : tok.quote
|
||||
});
|
||||
break;
|
||||
case "regexp":
|
||||
ret = new AST_RegExp({ start: tok, end: tok, value: tok.value });
|
||||
@@ -1081,6 +1239,13 @@ function parse($TEXT, options) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "operator":
|
||||
if (!is_identifier_string(tok.value)) {
|
||||
croak("Invalid getter/setter name: " + tok.value,
|
||||
tok.line, tok.col, tok.pos);
|
||||
}
|
||||
ret = _make_symbol(AST_SymbolRef);
|
||||
break;
|
||||
}
|
||||
next();
|
||||
return ret;
|
||||
@@ -1088,7 +1253,7 @@ function parse($TEXT, options) {
|
||||
|
||||
var expr_atom = function(allow_calls) {
|
||||
if (is("operator", "new")) {
|
||||
return new_();
|
||||
return new_(allow_calls);
|
||||
}
|
||||
var start = S.token;
|
||||
if (is("punc")) {
|
||||
@@ -1109,7 +1274,7 @@ function parse($TEXT, options) {
|
||||
}
|
||||
if (is("keyword", "function")) {
|
||||
next();
|
||||
var func = function_(false);
|
||||
var func = function_(AST_Function);
|
||||
func.start = start;
|
||||
func.end = prev();
|
||||
return subscripts(func, allow_calls);
|
||||
@@ -1126,7 +1291,7 @@ function parse($TEXT, options) {
|
||||
if (first) first = false; else expect(",");
|
||||
if (allow_trailing_comma && is("punc", closing)) break;
|
||||
if (is("punc", ",") && allow_empty) {
|
||||
a.push(new AST_Undefined({ start: S.token, end: S.token }));
|
||||
a.push(new AST_Hole({ start: S.token, end: S.token }));
|
||||
} else {
|
||||
a.push(expression(false));
|
||||
}
|
||||
@@ -1142,6 +1307,10 @@ function parse($TEXT, options) {
|
||||
});
|
||||
});
|
||||
|
||||
var create_accessor = embed_tokens(function() {
|
||||
return function_(AST_Accessor);
|
||||
});
|
||||
|
||||
var object_ = embed_tokens(function() {
|
||||
expect("{");
|
||||
var first = true, a = [];
|
||||
@@ -1157,8 +1326,8 @@ function parse($TEXT, options) {
|
||||
if (name == "get") {
|
||||
a.push(new AST_ObjectGetter({
|
||||
start : start,
|
||||
key : name,
|
||||
value : function_(false, AST_Lambda),
|
||||
key : as_atom_node(),
|
||||
value : create_accessor(),
|
||||
end : prev()
|
||||
}));
|
||||
continue;
|
||||
@@ -1166,8 +1335,8 @@ function parse($TEXT, options) {
|
||||
if (name == "set") {
|
||||
a.push(new AST_ObjectSetter({
|
||||
start : start,
|
||||
key : name,
|
||||
value : function_(false, AST_Lambda),
|
||||
key : as_atom_node(),
|
||||
value : create_accessor(),
|
||||
end : prev()
|
||||
}));
|
||||
continue;
|
||||
@@ -1176,6 +1345,7 @@ function parse($TEXT, options) {
|
||||
expect(":");
|
||||
a.push(new AST_ObjectKeyVal({
|
||||
start : start,
|
||||
quote : start.quote,
|
||||
key : name,
|
||||
value : expression(false),
|
||||
end : prev()
|
||||
@@ -1215,17 +1385,21 @@ function parse($TEXT, options) {
|
||||
}
|
||||
};
|
||||
|
||||
function _make_symbol(type) {
|
||||
var name = S.token.value;
|
||||
return new (name == "this" ? AST_This : type)({
|
||||
name : String(name),
|
||||
start : S.token,
|
||||
end : S.token
|
||||
});
|
||||
};
|
||||
|
||||
function as_symbol(type, noerror) {
|
||||
if (!is("name")) {
|
||||
if (!noerror) croak("Name expected");
|
||||
return null;
|
||||
}
|
||||
var name = S.token.value;
|
||||
var sym = new (name == "this" ? AST_This : type)({
|
||||
name : String(S.token.value),
|
||||
start : S.token,
|
||||
end : S.token
|
||||
});
|
||||
var sym = _make_symbol(type);
|
||||
next();
|
||||
return sym;
|
||||
};
|
||||
@@ -1268,6 +1442,7 @@ function parse($TEXT, options) {
|
||||
var start = S.token;
|
||||
if (is("operator") && UNARY_PREFIX(start.value)) {
|
||||
next();
|
||||
handle_regexp();
|
||||
var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls));
|
||||
ex.start = start;
|
||||
ex.end = prev();
|
||||
@@ -1323,7 +1498,7 @@ function parse($TEXT, options) {
|
||||
condition : expr,
|
||||
consequent : yes,
|
||||
alternative : expression(false, no_in),
|
||||
end : peek()
|
||||
end : prev()
|
||||
});
|
||||
}
|
||||
return expr;
|
||||
@@ -1331,15 +1506,8 @@ function parse($TEXT, options) {
|
||||
|
||||
function is_assignable(expr) {
|
||||
if (!options.strict) return true;
|
||||
switch (expr[0]+"") {
|
||||
case "dot":
|
||||
case "sub":
|
||||
case "new":
|
||||
case "call":
|
||||
return true;
|
||||
case "name":
|
||||
return expr[1] != "this";
|
||||
}
|
||||
if (expr instanceof AST_This) return false;
|
||||
return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol);
|
||||
};
|
||||
|
||||
var maybe_assign = function(no_in) {
|
||||
@@ -1353,7 +1521,7 @@ function parse($TEXT, options) {
|
||||
left : left,
|
||||
operator : val,
|
||||
right : maybe_assign(no_in),
|
||||
end : peek()
|
||||
end : prev()
|
||||
});
|
||||
}
|
||||
croak("Invalid assignment");
|
||||
@@ -1383,11 +1551,17 @@ function parse($TEXT, options) {
|
||||
return ret;
|
||||
};
|
||||
|
||||
if (options.expression) {
|
||||
return expression(true);
|
||||
}
|
||||
|
||||
return (function(){
|
||||
var start = S.token;
|
||||
var body = [];
|
||||
S.input.push_directives_stack();
|
||||
while (!is("eof"))
|
||||
body.push(statement());
|
||||
S.input.pop_directives_stack();
|
||||
var end = prev();
|
||||
var toplevel = options.toplevel;
|
||||
if (toplevel) {
|
||||
|
||||
257
lib/propmangle.js
Normal file
257
lib/propmangle.js
Normal file
@@ -0,0 +1,257 @@
|
||||
/***********************************************************************
|
||||
|
||||
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() {
|
||||
var a = [];
|
||||
[ Object, Array, Function, Number,
|
||||
String, Boolean, Error, Math,
|
||||
Date, RegExp
|
||||
].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);
|
||||
}
|
||||
}));
|
||||
|
||||
// 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_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;
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
331
lib/scope.js
331
lib/scope.js
@@ -43,7 +43,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
function SymbolDef(scope, orig) {
|
||||
function SymbolDef(scope, index, orig) {
|
||||
this.name = orig.name;
|
||||
this.orig = [ orig ];
|
||||
this.scope = scope;
|
||||
@@ -51,79 +51,98 @@ function SymbolDef(scope, orig) {
|
||||
this.global = false;
|
||||
this.mangled_name = null;
|
||||
this.undeclared = false;
|
||||
this.constant = false;
|
||||
this.index = index;
|
||||
this.id = SymbolDef.next_id++;
|
||||
};
|
||||
|
||||
SymbolDef.next_id = 1;
|
||||
|
||||
SymbolDef.prototype = {
|
||||
unmangleable: function() {
|
||||
return this.global || this.undeclared || this.scope.uses_eval || this.scope.uses_with;
|
||||
unmangleable: function(options) {
|
||||
if (!options) options = {};
|
||||
|
||||
return (this.global && !options.toplevel)
|
||||
|| this.undeclared
|
||||
|| (!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));
|
||||
},
|
||||
mangle: function() {
|
||||
if (!this.mangled_name && !this.unmangleable())
|
||||
this.mangled_name = this.scope.next_mangled();
|
||||
mangle: function(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 (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda)
|
||||
s = s.parent_scope;
|
||||
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 = Object.create(null);
|
||||
var labels = new Dictionary();
|
||||
var defun = null;
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (options.screw_ie8 && node instanceof AST_Catch) {
|
||||
var save_scope = scope;
|
||||
scope = new AST_Scope(node);
|
||||
scope.init_scope_vars();
|
||||
scope.parent_scope = save_scope;
|
||||
descend();
|
||||
scope = save_scope;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Scope) {
|
||||
node.init_scope_vars();
|
||||
var save_scope = node.parent_scope = scope;
|
||||
scope = node;
|
||||
var save_defun = defun;
|
||||
var save_labels = labels;
|
||||
defun = scope = node;
|
||||
labels = new Dictionary();
|
||||
descend();
|
||||
scope = save_scope;
|
||||
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);
|
||||
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[l.name])
|
||||
throw new Error(string_template("Label {name} defined twice", l));
|
||||
labels[l.name] = l;
|
||||
descend();
|
||||
delete labels[l.name];
|
||||
return true; // no descend again
|
||||
}
|
||||
if (node instanceof AST_SymbolDeclaration) {
|
||||
node.init_scope_vars();
|
||||
}
|
||||
if (node instanceof AST_Symbol) {
|
||||
node.scope = scope;
|
||||
}
|
||||
if (node instanceof AST_Label) {
|
||||
node.thedef = node;
|
||||
node.init_scope_vars();
|
||||
node.references = [];
|
||||
}
|
||||
if (node instanceof AST_SymbolLambda) {
|
||||
//scope.def_function(node);
|
||||
//
|
||||
// https://github.com/mishoo/UglifyJS2/issues/24 — MSIE
|
||||
// leaks function expression names into the containing
|
||||
// scope. Don't like this fix but seems we can't do any
|
||||
// better. IE: please die. Please!
|
||||
(node.scope = scope.parent_scope).def_function(node);
|
||||
|
||||
node.init.push(tw.parent());
|
||||
defun.def_function(node);
|
||||
}
|
||||
else if (node instanceof AST_SymbolDefun) {
|
||||
// Careful here, the scope where this should be defined is
|
||||
@@ -131,27 +150,19 @@ 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);
|
||||
node.init.push(tw.parent());
|
||||
(node.scope = defun.parent_scope).def_function(node);
|
||||
}
|
||||
else if (node instanceof AST_SymbolVar
|
||||
|| node instanceof AST_SymbolConst) {
|
||||
var def = scope.def_variable(node);
|
||||
def.constant = node instanceof AST_SymbolConst;
|
||||
def = tw.parent();
|
||||
if (def.value) node.init.push(def);
|
||||
var def = defun.def_variable(node);
|
||||
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);
|
||||
}
|
||||
if (node instanceof AST_LabelRef) {
|
||||
var sym = labels[node.name];
|
||||
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,
|
||||
line: node.start.line,
|
||||
@@ -164,7 +175,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
||||
|
||||
// pass 2: find back references and eval
|
||||
var func = null;
|
||||
var globals = self.globals = Object.create(null);
|
||||
var globals = self.globals = new Dictionary();
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node instanceof AST_Lambda) {
|
||||
var prev_func = func;
|
||||
@@ -173,44 +184,52 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
||||
func = prev_func;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_LabelRef) {
|
||||
node.reference();
|
||||
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[name]) {
|
||||
g = globals[name];
|
||||
} else {
|
||||
g = new SymbolDef(self, node);
|
||||
g.undeclared = true;
|
||||
globals[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_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.directives = []; // contains the directives defined in this scope, i.e. "use strict"
|
||||
this.variables = Object.create(null); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
||||
this.functions = Object.create(null); // map name to AST_SymbolDefun (functions defined in this scope)
|
||||
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
|
||||
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
||||
this.parent_scope = null; // the parent scope
|
||||
@@ -218,90 +237,100 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(){
|
||||
this.cname = -1; // the current index for mangling functions/variables
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("strict", function(){
|
||||
return this.has_directive("use strict");
|
||||
});
|
||||
|
||||
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
|
||||
AST_Scope.prototype.init_scope_vars.call(this);
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
AST_SymbolDeclaration.DEFMETHOD("init_scope_vars", function(){
|
||||
this.init = [];
|
||||
});
|
||||
|
||||
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){
|
||||
if (name instanceof AST_Symbol) name = name.name;
|
||||
return this.variables[name]
|
||||
return this.variables.get(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){
|
||||
this.functions[symbol.name] = this.def_variable(symbol);
|
||||
this.functions.set(symbol.name, this.def_variable(symbol));
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("def_variable", function(symbol){
|
||||
var def;
|
||||
if (!this.variables[symbol.name]) {
|
||||
def = new SymbolDef(this, symbol);
|
||||
this.variables[symbol.name] = 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;
|
||||
} else {
|
||||
def = this.variables[symbol.name];
|
||||
def = this.variables.get(symbol.name);
|
||||
def.orig.push(symbol);
|
||||
}
|
||||
return symbol.thedef = def;
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("next_mangled", function(){
|
||||
var ext = this.enclosed, n = ext.length;
|
||||
AST_Scope.DEFMETHOD("next_mangled", function(options){
|
||||
var ext = this.enclosed;
|
||||
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.
|
||||
for (var i = n; --i >= 0;) {
|
||||
for (var i = ext.length; --i >= 0;) {
|
||||
var sym = ext[i];
|
||||
var name = sym.mangled_name || (sym.unmangleable() && sym.name);
|
||||
var name = sym.mangled_name || (sym.unmangleable(options) && sym.name);
|
||||
if (m == name) continue out;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
});
|
||||
|
||||
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(){
|
||||
return this.definition().unmangleable();
|
||||
AST_Symbol.DEFMETHOD("unmangleable", function(options){
|
||||
return this.definition().unmangleable(options);
|
||||
});
|
||||
|
||||
// property accessors are not mangleable
|
||||
AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){
|
||||
return true;
|
||||
});
|
||||
|
||||
// labels are always mangleable
|
||||
@@ -334,16 +363,38 @@ AST_Symbol.DEFMETHOD("global", function(){
|
||||
return this.definition().global;
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
options = defaults(options, {
|
||||
except : []
|
||||
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
||||
return defaults(options, {
|
||||
except : [],
|
||||
eval : false,
|
||||
sort : false, // Ignored. Flag retained for backwards compatibility.
|
||||
toplevel : false,
|
||||
screw_ie8 : true,
|
||||
keep_fnames : 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
|
||||
@@ -353,17 +404,13 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
return true; // don't descend again in TreeWalker
|
||||
}
|
||||
if (node instanceof AST_Scope) {
|
||||
var p = tw.parent();
|
||||
var is_setget = p instanceof AST_ObjectSetter || p instanceof AST_ObjectGetter;
|
||||
var a = node.variables;
|
||||
for (var i in a) {
|
||||
var symbol = a[i];
|
||||
if (!(is_setget && symbol instanceof AST_SymbolLambda)) {
|
||||
if (options.except.indexOf(symbol.name) < 0) {
|
||||
to_mangle.push(symbol);
|
||||
}
|
||||
var p = tw.parent(), a = [];
|
||||
node.variables.each(function(symbol){
|
||||
if (options.except.indexOf(symbol.name) < 0) {
|
||||
a.push(symbol);
|
||||
}
|
||||
}
|
||||
});
|
||||
to_mangle.push.apply(to_mangle, a);
|
||||
return;
|
||||
}
|
||||
if (node instanceof AST_Label) {
|
||||
@@ -372,12 +419,21 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
node.mangled_name = name;
|
||||
return true;
|
||||
}
|
||||
if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
|
||||
to_mangle.push(node.definition());
|
||||
return;
|
||||
}
|
||||
});
|
||||
this.walk(tw);
|
||||
to_mangle.forEach(function(def){ def.mangle(options) });
|
||||
|
||||
if (options.cache) {
|
||||
options.cache.cname = this.cname;
|
||||
}
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(){
|
||||
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
||||
options = this._default_mangler_options(options);
|
||||
var tw = new TreeWalker(function(node){
|
||||
if (node instanceof AST_Constant)
|
||||
base54.consider(node.print_to_string());
|
||||
@@ -435,7 +491,7 @@ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(){
|
||||
base54.consider("catch");
|
||||
else if (node instanceof AST_Finally)
|
||||
base54.consider("finally");
|
||||
else if (node instanceof AST_Symbol && node.unmangleable())
|
||||
else if (node instanceof AST_Symbol && node.unmangleable(options))
|
||||
base54.consider(node.name);
|
||||
else if (node instanceof AST_Unary || node instanceof AST_Binary)
|
||||
base54.consider(node.operator);
|
||||
@@ -473,7 +529,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;
|
||||
@@ -534,6 +592,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()); }
|
||||
};
|
||||
};
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
"use strict";
|
||||
|
||||
// Tree transformer helpers.
|
||||
// XXX: eventually I should refactor the compressor to use this infrastructure.
|
||||
|
||||
function TreeTransformer(before, after) {
|
||||
TreeWalker.call(this);
|
||||
@@ -65,13 +64,13 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
x = this;
|
||||
descend(x, tw);
|
||||
} else {
|
||||
tw.stack[tw.stack - 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;
|
||||
});
|
||||
};
|
||||
@@ -160,6 +159,7 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
});
|
||||
|
||||
_(AST_VarDef, function(self, tw){
|
||||
self.name = self.name.transform(tw);
|
||||
if (self.value) self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
|
||||
144
lib/utils.js
144
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);
|
||||
};
|
||||
@@ -162,7 +185,7 @@ function push_uniq(array, el) {
|
||||
|
||||
function string_template(text, props) {
|
||||
return text.replace(/\{(.+?)\}/g, function(str, p){
|
||||
return props[p];
|
||||
return props && props[p];
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -244,3 +276,85 @@ function makePredicate(words) {
|
||||
}
|
||||
return new Function("str", f);
|
||||
};
|
||||
|
||||
function all(array, predicate) {
|
||||
for (var i = array.length; --i >= 0;)
|
||||
if (!predicate(array[i]))
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
function Dictionary() {
|
||||
this._values = Object.create(null);
|
||||
this._size = 0;
|
||||
};
|
||||
Dictionary.prototype = {
|
||||
set: function(key, val) {
|
||||
if (!this.has(key)) ++this._size;
|
||||
this._values["$" + key] = val;
|
||||
return this;
|
||||
},
|
||||
add: function(key, val) {
|
||||
if (this.has(key)) {
|
||||
this.get(key).push(val);
|
||||
} else {
|
||||
this.set(key, [ val ]);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
get: function(key) { return this._values["$" + key] },
|
||||
del: function(key) {
|
||||
if (this.has(key)) {
|
||||
--this._size;
|
||||
delete this._values["$" + key];
|
||||
}
|
||||
return this;
|
||||
},
|
||||
has: function(key) { return ("$" + key) in this._values },
|
||||
each: function(f) {
|
||||
for (var i in this._values)
|
||||
f(this._values[i], i.substr(1));
|
||||
},
|
||||
size: function() {
|
||||
return this._size;
|
||||
},
|
||||
map: function(f) {
|
||||
var ret = [];
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
75
package.json
75
package.json
@@ -1,25 +1,54 @@
|
||||
{
|
||||
"name": "uglify-js2",
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"homepage": "http://lisperator.net/uglifyjs",
|
||||
"main": "tools/node.js",
|
||||
"version": "2.1.4",
|
||||
"engines": { "node" : ">=0.4.0" },
|
||||
"maintainers": [{
|
||||
"name": "Mihai Bazon",
|
||||
"email": "mihai.bazon@gmail.com",
|
||||
"web": "http://lisperator.net/"
|
||||
}],
|
||||
"repositories": [{
|
||||
"type": "git",
|
||||
"url": "https://github.com/mishoo/UglifyJS2.git"
|
||||
}],
|
||||
"dependencies": {
|
||||
"source-map" : "*",
|
||||
"optimist" : "*"
|
||||
},
|
||||
"bin": {
|
||||
"uglifyjs2" : "bin/uglifyjs2"
|
||||
},
|
||||
"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.4",
|
||||
"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;
|
||||
}])
|
||||
}
|
||||
}
|
||||
177
test/compress/arrays.js
Normal file
177
test/compress/arrays.js
Normal file
@@ -0,0 +1,177 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
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,126 @@ 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_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';
|
||||
}
|
||||
}
|
||||
|
||||
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,587 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
684
test/compress/evaluate.js
Normal file
684
test/compress/evaluate.js
Normal file
@@ -0,0 +1,684 @@
|
||||
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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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_object_accessor: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a = {
|
||||
get b() {},
|
||||
set b() {}
|
||||
};
|
||||
return {a:a};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
var a = {
|
||||
get b() {},
|
||||
set b() {}
|
||||
};
|
||||
return {a:a};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
);
|
||||
}
|
||||
}
|
||||
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]',
|
||||
]
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
71
test/compress/html_comments.js
Normal file
71
test/compress/html_comments.js
Normal file
@@ -0,0 +1,71 @@
|
||||
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"}';
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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 || {};
|
||||
}
|
||||
}
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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"]);
|
||||
}
|
||||
}
|
||||
48
test/compress/issue-143.js
Normal file
48
test/compress/issue-143.js
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* There was an incorrect sort behaviour documented in issue #143:
|
||||
* (x = f(…)) <= x → x >= (x = f(…))
|
||||
*
|
||||
* For example, let the equation be:
|
||||
* (a = parseInt('100')) <= a
|
||||
*
|
||||
* If a was an integer and has the value of 99,
|
||||
* (a = parseInt('100')) <= a → 100 <= 100 → true
|
||||
*
|
||||
* When transformed incorrectly:
|
||||
* a >= (a = parseInt('100')) → 99 >= 100 → false
|
||||
*/
|
||||
|
||||
tranformation_sort_order_equal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
};
|
||||
|
||||
input: { (a = parseInt('100')) == a }
|
||||
expect: { (a = parseInt('100')) == a }
|
||||
}
|
||||
|
||||
tranformation_sort_order_unequal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
};
|
||||
|
||||
input: { (a = parseInt('100')) != a }
|
||||
expect: { (a = parseInt('100')) != a }
|
||||
}
|
||||
|
||||
tranformation_sort_order_lesser_or_equal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
};
|
||||
|
||||
input: { (a = parseInt('100')) <= a }
|
||||
expect: { (a = parseInt('100')) <= a }
|
||||
}
|
||||
tranformation_sort_order_greater_or_equal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
};
|
||||
|
||||
input: { (a = parseInt('100')) >= a }
|
||||
expect: { (a = parseInt('100')) >= a }
|
||||
}
|
||||
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);"
|
||||
}
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
31
test/compress/issue-44.js
Normal file
31
test/compress/issue-44.js
Normal file
@@ -0,0 +1,31 @@
|
||||
issue_44_valid_ast_1: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function a(b) {
|
||||
for (var i = 0, e = b.qoo(); ; i++) {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a(b) {
|
||||
var i = 0;
|
||||
for (b.qoo(); ; i++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_44_valid_ast_2: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function a(b) {
|
||||
if (foo) for (var i = 0, e = b.qoo(); ; i++) {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a(b) {
|
||||
if (foo) {
|
||||
var i = 0;
|
||||
for (b.qoo(); ; i++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
test/compress/issue-59.js
Normal file
30
test/compress/issue-59.js
Normal file
@@ -0,0 +1,30 @@
|
||||
keep_continue: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true
|
||||
};
|
||||
input: {
|
||||
while (a) {
|
||||
if (b) {
|
||||
switch (true) {
|
||||
case c():
|
||||
d();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
f();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
while (a) {
|
||||
if (b) {
|
||||
switch (true) {
|
||||
case c():
|
||||
d();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
f();
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
})();
|
||||
}
|
||||
}
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
218
test/compress/loops.js
Normal file
218
test/compress/loops.js
Normal file
@@ -0,0 +1,218 @@
|
||||
while_becomes_for: {
|
||||
options = { loops: true };
|
||||
input: {
|
||||
while (foo()) bar();
|
||||
}
|
||||
expect: {
|
||||
for (; foo(); ) bar();
|
||||
}
|
||||
}
|
||||
|
||||
drop_if_break_1: {
|
||||
options = { loops: true };
|
||||
input: {
|
||||
for (;;)
|
||||
if (foo()) break;
|
||||
}
|
||||
expect: {
|
||||
for (; !foo(););
|
||||
}
|
||||
}
|
||||
|
||||
drop_if_break_2: {
|
||||
options = { loops: true };
|
||||
input: {
|
||||
for (;bar();)
|
||||
if (foo()) break;
|
||||
}
|
||||
expect: {
|
||||
for (; bar() && !foo(););
|
||||
}
|
||||
}
|
||||
|
||||
drop_if_break_3: {
|
||||
options = { loops: true };
|
||||
input: {
|
||||
for (;bar();) {
|
||||
if (foo()) break;
|
||||
stuff1();
|
||||
stuff2();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (; bar() && !foo();) {
|
||||
stuff1();
|
||||
stuff2();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drop_if_break_4: {
|
||||
options = { loops: true, sequences: true };
|
||||
input: {
|
||||
for (;bar();) {
|
||||
x();
|
||||
y();
|
||||
if (foo()) break;
|
||||
z();
|
||||
k();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (; bar() && (x(), y(), !foo());) z(), k();
|
||||
}
|
||||
}
|
||||
|
||||
drop_if_else_break_1: {
|
||||
options = { loops: true };
|
||||
input: {
|
||||
for (;;) if (foo()) bar(); else break;
|
||||
}
|
||||
expect: {
|
||||
for (; foo(); ) bar();
|
||||
}
|
||||
}
|
||||
|
||||
drop_if_else_break_2: {
|
||||
options = { loops: true };
|
||||
input: {
|
||||
for (;bar();) {
|
||||
if (foo()) baz();
|
||||
else break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (; bar() && foo();) baz();
|
||||
}
|
||||
}
|
||||
|
||||
drop_if_else_break_3: {
|
||||
options = { loops: true };
|
||||
input: {
|
||||
for (;bar();) {
|
||||
if (foo()) baz();
|
||||
else break;
|
||||
stuff1();
|
||||
stuff2();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (; bar() && foo();) {
|
||||
baz();
|
||||
stuff1();
|
||||
stuff2();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drop_if_else_break_4: {
|
||||
options = { loops: true, sequences: true };
|
||||
input: {
|
||||
for (;bar();) {
|
||||
x();
|
||||
y();
|
||||
if (foo()) baz();
|
||||
else break;
|
||||
z();
|
||||
k();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
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);
|
||||
}
|
||||
}
|
||||
84
test/compress/new.js
Normal file
84
test/compress/new.js
Normal file
@@ -0,0 +1,84 @@
|
||||
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);';
|
||||
}
|
||||
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);"
|
||||
}
|
||||
@@ -12,14 +12,546 @@ keep_properties: {
|
||||
|
||||
dot_properties: {
|
||||
options = {
|
||||
properties: true
|
||||
properties: true,
|
||||
screw_ie8: false
|
||||
};
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
a["if"] = "if";
|
||||
a["*"] = "asterisk";
|
||||
a["\u0EB3"] = "unicode";
|
||||
a[""] = "whitespace";
|
||||
a["1_1"] = "foo";
|
||||
}
|
||||
expect: {
|
||||
a.foo = "bar";
|
||||
a["if"] = "if";
|
||||
a["*"] = "asterisk";
|
||||
a["\u0EB3"] = "unicode";
|
||||
a[""] = "whitespace";
|
||||
a["1_1"] = "foo";
|
||||
}
|
||||
}
|
||||
|
||||
dot_properties_es5: {
|
||||
options = {
|
||||
properties: true,
|
||||
screw_ie8: true
|
||||
};
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
a["if"] = "if";
|
||||
a["*"] = "asterisk";
|
||||
a["\u0EB3"] = "unicode";
|
||||
a[""] = "whitespace";
|
||||
}
|
||||
expect: {
|
||||
a.foo = "bar";
|
||||
a.if = "if";
|
||||
a["*"] = "asterisk";
|
||||
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
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
591
test/compress/reduce_vars.js
Normal file
591
test/compress/reduce_vars.js
Normal file
@@ -0,0 +1,591 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
use_before_var: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(t);
|
||||
var t = 1;
|
||||
}
|
||||
expect: {
|
||||
console.log(t);
|
||||
var t = 1;
|
||||
}
|
||||
}
|
||||
|
||||
inner_var_if: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(){
|
||||
return 0;
|
||||
}
|
||||
if (f())
|
||||
var t = 1;
|
||||
if (!t)
|
||||
console.log(t);
|
||||
}
|
||||
expect: {
|
||||
function f(){
|
||||
return 0;
|
||||
}
|
||||
if (f())
|
||||
var t = 1;
|
||||
if (!t)
|
||||
console.log(t);
|
||||
}
|
||||
}
|
||||
|
||||
inner_var_label: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(){
|
||||
return 1;
|
||||
}
|
||||
l: {
|
||||
if (f()) break l;
|
||||
var t = 1;
|
||||
}
|
||||
console.log(t);
|
||||
}
|
||||
expect: {
|
||||
function f(){
|
||||
return 1;
|
||||
}
|
||||
l: {
|
||||
if (f()) break l;
|
||||
var t = 1;
|
||||
}
|
||||
console.log(t);
|
||||
}
|
||||
}
|
||||
|
||||
inner_var_for: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
x(a, b, d);
|
||||
for (var b = 2, c = 3; x(a, b, c, d); x(a, b, c, d)) {
|
||||
var d = 4, e = 5;
|
||||
x(a, b, c, d, e);
|
||||
}
|
||||
x(a, b, c, d, e)
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
x(1, b, d);
|
||||
for (var b = 2, c = 3; x(1, b, 3, d); x(1, b, 3, d)) {
|
||||
var d = 4, e = 5;
|
||||
x(1, b, 3, d, e);
|
||||
}
|
||||
x(1, b, 3, d, e);
|
||||
}
|
||||
}
|
||||
|
||||
inner_var_for_in: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1, b = 2;
|
||||
for (b in (function() {
|
||||
return x(a, b, c);
|
||||
})()) {
|
||||
var c = 3, d = 4;
|
||||
x(a, b, c, d);
|
||||
}
|
||||
x(a, b, c, d);
|
||||
}
|
||||
expect: {
|
||||
var a = 1, b = 2;
|
||||
for (b in (function() {
|
||||
return x(1, b, c);
|
||||
})()) {
|
||||
var c = 3, d = 4;
|
||||
x(1, b, c, d);
|
||||
}
|
||||
x(1, b, c, d);
|
||||
}
|
||||
}
|
||||
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,125 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
for_sequences: {
|
||||
options = { sequences: true };
|
||||
input: {
|
||||
// 1
|
||||
foo();
|
||||
bar();
|
||||
for (; false;);
|
||||
// 2
|
||||
foo();
|
||||
bar();
|
||||
for (x = 5; false;);
|
||||
// 3
|
||||
x = (foo in bar);
|
||||
for (; false;);
|
||||
// 4
|
||||
x = (foo in bar);
|
||||
for (y = 5; false;);
|
||||
}
|
||||
expect: {
|
||||
// 1
|
||||
for (foo(), bar(); false;);
|
||||
// 2
|
||||
for (foo(), bar(), x = 5; false;);
|
||||
// 3
|
||||
x = (foo in bar);
|
||||
for (; false;);
|
||||
// 4
|
||||
x = (foo in bar);
|
||||
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";
|
||||
}
|
||||
}
|
||||
260
test/compress/switch.js
Normal file
260
test/compress/switch.js
Normal file
@@ -0,0 +1,260 @@
|
||||
constant_switch_1: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
input: {
|
||||
switch (1+1) {
|
||||
case 1: foo(); break;
|
||||
case 1+1: bar(); break;
|
||||
case 1+1+1: baz(); break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
constant_switch_2: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
input: {
|
||||
switch (1) {
|
||||
case 1: foo();
|
||||
case 1+1: bar(); break;
|
||||
case 1+1+1: baz();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
foo();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
constant_switch_3: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
input: {
|
||||
switch (10) {
|
||||
case 1: foo();
|
||||
case 1+1: bar(); break;
|
||||
case 1+1+1: baz();
|
||||
default:
|
||||
def();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
def();
|
||||
}
|
||||
}
|
||||
|
||||
constant_switch_4: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
input: {
|
||||
switch (2) {
|
||||
case 1:
|
||||
x();
|
||||
if (foo) break;
|
||||
y();
|
||||
break;
|
||||
case 1+1:
|
||||
bar();
|
||||
default:
|
||||
def();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
bar();
|
||||
def();
|
||||
}
|
||||
}
|
||||
|
||||
constant_switch_5: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
input: {
|
||||
switch (1) {
|
||||
case 1:
|
||||
x();
|
||||
if (foo) break;
|
||||
y();
|
||||
break;
|
||||
case 1+1:
|
||||
bar();
|
||||
default:
|
||||
def();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
// the break inside the if ruins our job
|
||||
// we can still get rid of irrelevant cases.
|
||||
switch (1) {
|
||||
case 1:
|
||||
x();
|
||||
if (foo) break;
|
||||
y();
|
||||
}
|
||||
// XXX: we could optimize this better by inventing an outer
|
||||
// labeled block, but that's kinda tricky.
|
||||
}
|
||||
}
|
||||
|
||||
constant_switch_6: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
input: {
|
||||
OUT: {
|
||||
foo();
|
||||
switch (1) {
|
||||
case 1:
|
||||
x();
|
||||
if (foo) break OUT;
|
||||
y();
|
||||
case 1+1:
|
||||
bar();
|
||||
break;
|
||||
default:
|
||||
def();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
OUT: {
|
||||
foo();
|
||||
x();
|
||||
if (foo) break OUT;
|
||||
y();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constant_switch_7: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
input: {
|
||||
OUT: {
|
||||
foo();
|
||||
switch (1) {
|
||||
case 1:
|
||||
x();
|
||||
if (foo) break OUT;
|
||||
for (var x = 0; x < 10; x++) {
|
||||
if (x > 5) break; // this break refers to the for, not to the switch; thus it
|
||||
// shouldn't ruin our optimization
|
||||
console.log(x);
|
||||
}
|
||||
y();
|
||||
case 1+1:
|
||||
bar();
|
||||
break;
|
||||
default:
|
||||
def();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
OUT: {
|
||||
foo();
|
||||
x();
|
||||
if (foo) break OUT;
|
||||
for (var x = 0; x < 10; x++) {
|
||||
if (x > 5) break;
|
||||
console.log(x);
|
||||
}
|
||||
y();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constant_switch_8: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
input: {
|
||||
OUT: switch (1) {
|
||||
case 1:
|
||||
x();
|
||||
for (;;) break OUT;
|
||||
y();
|
||||
break;
|
||||
case 1+1:
|
||||
bar();
|
||||
default:
|
||||
def();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
OUT: {
|
||||
x();
|
||||
for (;;) break OUT;
|
||||
y();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constant_switch_9: {
|
||||
options = { dead_code: true, evaluate: true };
|
||||
input: {
|
||||
OUT: switch (1) {
|
||||
case 1:
|
||||
x();
|
||||
for (;;) if (foo) break OUT;
|
||||
y();
|
||||
case 1+1:
|
||||
bar();
|
||||
default:
|
||||
def();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
OUT: {
|
||||
x();
|
||||
for (;;) if (foo) break OUT;
|
||||
y();
|
||||
bar();
|
||||
def();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drop_default_1: {
|
||||
options = { dead_code: true };
|
||||
input: {
|
||||
switch (foo) {
|
||||
case 'bar': baz();
|
||||
default:
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
switch (foo) {
|
||||
case 'bar': baz();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drop_default_2: {
|
||||
options = { dead_code: true };
|
||||
input: {
|
||||
switch (foo) {
|
||||
case 'bar': baz(); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
switch (foo) {
|
||||
case 'bar': baz();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keep_default: {
|
||||
options = { dead_code: true };
|
||||
input: {
|
||||
switch (foo) {
|
||||
case 'bar': baz();
|
||||
default:
|
||||
something();
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
switch (foo) {
|
||||
case 'bar': baz();
|
||||
default:
|
||||
something();
|
||||
}
|
||||
}
|
||||
}
|
||||
50
test/compress/typeof.js
Normal file
50
test/compress/typeof.js
Normal file
@@ -0,0 +1,50 @@
|
||||
typeof_evaluation: {
|
||||
options = {
|
||||
evaluate: true
|
||||
};
|
||||
input: {
|
||||
a = typeof 1;
|
||||
b = typeof 'test';
|
||||
c = typeof [];
|
||||
d = typeof {};
|
||||
e = typeof /./;
|
||||
f = typeof false;
|
||||
g = typeof function(){};
|
||||
h = typeof undefined;
|
||||
}
|
||||
expect: {
|
||||
a='number';
|
||||
b='string';
|
||||
c=typeof[];
|
||||
d=typeof{};
|
||||
e=typeof/./;
|
||||
f='boolean';
|
||||
g='function';
|
||||
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();
|
||||
}
|
||||
}
|
||||
17
test/compress/unicode.js
Normal file
17
test/compress/unicode.js
Normal file
@@ -0,0 +1,17 @@
|
||||
unicode_parse_variables: {
|
||||
options = {};
|
||||
input: {
|
||||
var a = {};
|
||||
a.你好 = 456;
|
||||
|
||||
var ↂωↂ = 123;
|
||||
var l০ = 3; // 2nd char is a unicode digit
|
||||
}
|
||||
expect: {
|
||||
var a = {};
|
||||
a.你好 = 456;
|
||||
|
||||
var ↂωↂ = 123;
|
||||
var l০ = 3;
|
||||
}
|
||||
}
|
||||
48
test/compress/wrap_iife.js
Normal file
48
test/compress/wrap_iife.js
Normal file
@@ -0,0 +1,48 @@
|
||||
wrap_iife: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
}
|
||||
beautify = {
|
||||
wrap_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
return function() {
|
||||
console.log('test')
|
||||
};
|
||||
})()();
|
||||
}
|
||||
expect_exact: '(function(){return function(){console.log("test")}})()();'
|
||||
}
|
||||
|
||||
wrap_iife_in_expression: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
}
|
||||
beautify = {
|
||||
wrap_iife: true,
|
||||
}
|
||||
input: {
|
||||
foo = (function () {
|
||||
return bar();
|
||||
})();
|
||||
}
|
||||
expect_exact: 'foo=(function(){return bar()})();'
|
||||
}
|
||||
|
||||
wrap_iife_in_return_call: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
}
|
||||
beautify = {
|
||||
wrap_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
return (function() {
|
||||
console.log('test')
|
||||
})();
|
||||
})()();
|
||||
}
|
||||
expect_exact: '(function(){return(function(){console.log("test")})()})()();'
|
||||
}
|
||||
3
test/input/comments/filter.js
Normal file
3
test/input/comments/filter.js
Normal file
@@ -0,0 +1,3 @@
|
||||
// foo
|
||||
/*@preserve*/
|
||||
// bar
|
||||
1
test/input/global_defs/nested.js
Normal file
1
test/input/global_defs/nested.js
Normal file
@@ -0,0 +1 @@
|
||||
console.log(C.V, C.D);
|
||||
1
test/input/global_defs/simple.js
Normal file
1
test/input/global_defs/simple.js
Normal file
@@ -0,0 +1 @@
|
||||
console.log(D);
|
||||
1
test/input/invalid/eof.js
Normal file
1
test/input/invalid/eof.js
Normal file
@@ -0,0 +1 @@
|
||||
foo, bar(
|
||||
1
test/input/invalid/simple.js
Normal file
1
test/input/invalid/simple.js
Normal file
@@ -0,0 +1 @@
|
||||
function f(a{}
|
||||
1
test/input/invalid/tab.js
Normal file
1
test/input/invalid/tab.js
Normal file
@@ -0,0 +1 @@
|
||||
foo( xyz, 0abc);
|
||||
8
test/input/issue-1236/simple.js
Normal file
8
test/input/issue-1236/simple.js
Normal file
@@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
var foo = function foo(x) {
|
||||
return "foo " + x;
|
||||
};
|
||||
console.log(foo("bar"));
|
||||
|
||||
//# sourceMappingURL=simple.js.map
|
||||
8
test/input/issue-1236/simple.js.map
Normal file
8
test/input/issue-1236/simple.js.map
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["index.js"],
|
||||
"names": [],
|
||||
"mappings": ";;AAAA,IAAI,MAAM,SAAN,GAAM;AAAA,SAAK,SAAS,CAAd;AAAA,CAAV;AACA,QAAQ,GAAR,CAAY,IAAI,KAAJ,CAAZ",
|
||||
"file": "simple.js",
|
||||
"sourcesContent": ["let foo = x => \"foo \" + x;\nconsole.log(foo(\"bar\"));"]
|
||||
}
|
||||
4
test/input/issue-1242/bar.es5
Normal file
4
test/input/issue-1242/bar.es5
Normal file
@@ -0,0 +1,4 @@
|
||||
function bar(x) {
|
||||
var triple = x * (2 + 1);
|
||||
return triple;
|
||||
}
|
||||
4
test/input/issue-1242/baz.es5
Normal file
4
test/input/issue-1242/baz.es5
Normal file
@@ -0,0 +1,4 @@
|
||||
function baz(x) {
|
||||
var half = x / 2;
|
||||
return half;
|
||||
}
|
||||
5
test/input/issue-1242/foo.es5
Normal file
5
test/input/issue-1242/foo.es5
Normal file
@@ -0,0 +1,5 @@
|
||||
var print = console.log.bind(console);
|
||||
function foo(x) {
|
||||
var twice = x * 2;
|
||||
print('Foo:', twice);
|
||||
}
|
||||
4
test/input/issue-1242/qux.js
Normal file
4
test/input/issue-1242/qux.js
Normal file
@@ -0,0 +1,4 @@
|
||||
var a = bar(1+2);
|
||||
var b = baz(3+9);
|
||||
print('q' + 'u' + 'x', a, b);
|
||||
foo(5+6);
|
||||
7
test/input/issue-1323/sample.js
Normal file
7
test/input/issue-1323/sample.js
Normal file
@@ -0,0 +1,7 @@
|
||||
var bar = (function () {
|
||||
function foo (bar) {
|
||||
return bar;
|
||||
}
|
||||
|
||||
return foo;
|
||||
})();
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user