Compare commits
535 Commits
harmony-v3
...
v3.4.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a5277b391 | ||
|
|
d47547dc71 | ||
|
|
304db15a20 | ||
|
|
7cf72b8d66 | ||
|
|
cea685f8d9 | ||
|
|
8d4b5344f4 | ||
|
|
34a0ab6f2c | ||
|
|
bcebacbb9e | ||
|
|
018a5a750a | ||
|
|
b468103f26 | ||
|
|
66c126ffde | ||
|
|
fdee083465 | ||
|
|
5ffc17d4aa | ||
|
|
6aa750010f | ||
|
|
76df77c08c | ||
|
|
957d5537a8 | ||
|
|
88c8f4e363 | ||
|
|
ab36b9b10a | ||
|
|
28330913d8 | ||
|
|
766a4147d4 | ||
|
|
915c7e234d | ||
|
|
e54ddcbb8a | ||
|
|
9e19e63551 | ||
|
|
bce7ee5f6a | ||
|
|
b39043f3ab | ||
|
|
caf96acb08 | ||
|
|
c76749084b | ||
|
|
5843494ee2 | ||
|
|
efa21ae3e6 | ||
|
|
24d9633a35 | ||
|
|
7963b96681 | ||
|
|
8c62d854ce | ||
|
|
69931574e1 | ||
|
|
b5af8a1914 | ||
|
|
c14d09ba84 | ||
|
|
4fc39d8dad | ||
|
|
0b7c70f726 | ||
|
|
f72d3029dd | ||
|
|
1a0d6edc81 | ||
|
|
7b59b2f5b2 | ||
|
|
7bc7704edf | ||
|
|
14e712ee80 | ||
|
|
f83adcc995 | ||
|
|
df8a99439a | ||
|
|
6b91d12ec3 | ||
|
|
f37b91879f | ||
|
|
d835c72c80 | ||
|
|
c4cebb4b01 | ||
|
|
d51a00a450 | ||
|
|
fc0f168a0c | ||
|
|
a0ca595c2c | ||
|
|
1a314e9f60 | ||
|
|
6fcbd5e217 | ||
|
|
22cea023d1 | ||
|
|
70d4477e05 | ||
|
|
838f837379 | ||
|
|
82a8b6f612 | ||
|
|
69fc7ca8da | ||
|
|
0a79496e0a | ||
|
|
9e87edfc2e | ||
|
|
27211cf2d5 | ||
|
|
b5ce199711 | ||
|
|
c71ed91e63 | ||
|
|
f7545d0f1c | ||
|
|
59eecb6bf5 | ||
|
|
d83c6490ab | ||
|
|
7362f57966 | ||
|
|
eaa2c1f6af | ||
|
|
6a916523d4 | ||
|
|
ba7069d52b | ||
|
|
4dd7d0e39b | ||
|
|
90199d0a96 | ||
|
|
b82fd0ad41 | ||
|
|
183da16896 | ||
|
|
87857b0f1b | ||
|
|
e5f6a88233 | ||
|
|
8d0b00317e | ||
|
|
db49daf365 | ||
|
|
923deeff35 | ||
|
|
0b62a28b47 | ||
|
|
44116c6d2b | ||
|
|
b5bab254ce | ||
|
|
81603ecd15 | ||
|
|
e67553fa55 | ||
|
|
fcf542f262 | ||
|
|
8adfc29f91 | ||
|
|
02f47e1713 | ||
|
|
07f64d4050 | ||
|
|
6982a0554c | ||
|
|
fa3250199a | ||
|
|
06b9894c19 | ||
|
|
9f9db504d7 | ||
|
|
82ae95c334 | ||
|
|
9a5e2052c4 | ||
|
|
b1410be443 | ||
|
|
12985d86c2 | ||
|
|
49bfc6b555 | ||
|
|
d1c6bb8c7c | ||
|
|
5c169615a8 | ||
|
|
73d77f4f64 | ||
|
|
ccf0e2ef4f | ||
|
|
20ca0f5906 | ||
|
|
b29d435bb5 | ||
|
|
90585e29c2 | ||
|
|
d8fc281915 | ||
|
|
188c39e8d5 | ||
|
|
5429234138 | ||
|
|
b9f72a4a81 | ||
|
|
fc6ebd04a5 | ||
|
|
7e00a12741 | ||
|
|
10b3752b1e | ||
|
|
fe51a91395 | ||
|
|
951d87ca94 | ||
|
|
798fc21530 | ||
|
|
a75a046abb | ||
|
|
38f2b4579f | ||
|
|
56e2a369d0 | ||
|
|
0daa199fa8 | ||
|
|
73e98dcda4 | ||
|
|
36bca6934d | ||
|
|
ace5811691 | ||
|
|
ba7bad0dbd | ||
|
|
b8b2ac5230 | ||
|
|
ea2359381b | ||
|
|
52de64cf16 | ||
|
|
455790202a | ||
|
|
f40f5eb228 | ||
|
|
604caa09e7 | ||
|
|
29a71d3aae | ||
|
|
39a907bde3 | ||
|
|
70474310f3 | ||
|
|
b5f0f4f3a1 | ||
|
|
2905fd625a | ||
|
|
4facd94029 | ||
|
|
4b5993ff15 | ||
|
|
2351a672ea | ||
|
|
4a528c469c | ||
|
|
82d1ef0242 | ||
|
|
7fdd2082a6 | ||
|
|
e529f54e90 | ||
|
|
d626e9bf19 | ||
|
|
a2a9459684 | ||
|
|
a3dfeea144 | ||
|
|
d316fb139d | ||
|
|
83d8aa8b12 | ||
|
|
4f1c12b6fd | ||
|
|
d8e0e34354 | ||
|
|
0c4f315c02 | ||
|
|
0809699bdc | ||
|
|
2088e1c19d | ||
|
|
bf1d47180c | ||
|
|
0cfbd79aa1 | ||
|
|
d66d86f20b | ||
|
|
905325d3e2 | ||
|
|
dea0cc0662 | ||
|
|
d69d8007d6 | ||
|
|
c0b8f2a16d | ||
|
|
cb0257dbbf | ||
|
|
9637f51b68 | ||
|
|
3026bd8975 | ||
|
|
78a44d5ab0 | ||
|
|
7e13c0db40 | ||
|
|
e6a2e9e4d0 | ||
|
|
e773f03927 | ||
|
|
b16380d669 | ||
|
|
334b07a3db | ||
|
|
3cc1527f00 | ||
|
|
525a61fb55 | ||
|
|
c3a002ff97 | ||
|
|
fad6766a90 | ||
|
|
aa664dea0a | ||
|
|
102f994b9d | ||
|
|
2a4c68be4f | ||
|
|
541e6011af | ||
|
|
6fa3fbeae8 | ||
|
|
4eb4cb656c | ||
|
|
193612ac67 | ||
|
|
95cfce68ea | ||
|
|
ec4202590d | ||
|
|
5e2cd07d6f | ||
|
|
06166df999 | ||
|
|
e2dc9cf091 | ||
|
|
069df27bf1 | ||
|
|
3e7873217c | ||
|
|
e21bab7ce6 | ||
|
|
ac9a168fba | ||
|
|
81b64549ce | ||
|
|
082e004b87 | ||
|
|
983e69128b | ||
|
|
b335912e86 | ||
|
|
cc07f3b806 | ||
|
|
07e4b64f3a | ||
|
|
d3ce2bc9e7 | ||
|
|
cff3bf4914 | ||
|
|
79cfac77bd | ||
|
|
224c14d49d | ||
|
|
7857354d85 | ||
|
|
b4aef753e7 | ||
|
|
424173d311 | ||
|
|
ec7cd1dcf7 | ||
|
|
7def684730 | ||
|
|
10f961c27b | ||
|
|
b483678ca7 | ||
|
|
cbbe6fad60 | ||
|
|
f96929c031 | ||
|
|
2b6657e967 | ||
|
|
7c0c92943f | ||
|
|
62a66dfff4 | ||
|
|
2cab348341 | ||
|
|
460218a3f8 | ||
|
|
e49416e4aa | ||
|
|
d4d7d99b70 | ||
|
|
6a696d0a7b | ||
|
|
1c9e13f47d | ||
|
|
b757450cd8 | ||
|
|
23ec484806 | ||
|
|
f1e1bb419a | ||
|
|
6a0af85c8b | ||
|
|
09269be974 | ||
|
|
bf832cde16 | ||
|
|
2972d58dbb | ||
|
|
2e22d38a02 | ||
|
|
ce27bcd69a | ||
|
|
9336cc8247 | ||
|
|
9809567dfc | ||
|
|
1ee8be8d91 | ||
|
|
8430c2f9f8 | ||
|
|
659c8a7632 | ||
|
|
3564b4f20d | ||
|
|
3505a3604a | ||
|
|
9b1bc6c014 | ||
|
|
9f23185f2b | ||
|
|
b82feb9302 | ||
|
|
7f2a591c7e | ||
|
|
afbcebddf6 | ||
|
|
484e484571 | ||
|
|
6f3f21233f | ||
|
|
a6873a3859 | ||
|
|
7a6d452b54 | ||
|
|
9b58b54e2d | ||
|
|
c598a12af9 | ||
|
|
cfe3a98ce5 | ||
|
|
14778e049b | ||
|
|
446fb0198b | ||
|
|
7d3cddf9d6 | ||
|
|
6dead95eb3 | ||
|
|
cc931b3ad8 | ||
|
|
d838b4b52e | ||
|
|
2f3bddbaca | ||
|
|
673b071637 | ||
|
|
da82fa59a7 | ||
|
|
333792352e | ||
|
|
e2ec270b04 | ||
|
|
ed7a0a454e | ||
|
|
d819559a01 | ||
|
|
8ca49155a8 | ||
|
|
b95e3338d9 | ||
|
|
e40a0ee9c6 | ||
|
|
cb62bd98d3 | ||
|
|
f30790b11b | ||
|
|
5205dbcbf4 | ||
|
|
3ff625de7e | ||
|
|
4832bc5d88 | ||
|
|
7f342cb3e3 | ||
|
|
05e7d34ed4 | ||
|
|
86607156e3 | ||
|
|
0fe259e9c5 | ||
|
|
8701a99a15 | ||
|
|
1476c78b53 | ||
|
|
cb6a92892f | ||
|
|
f1556cb945 | ||
|
|
efffb81735 | ||
|
|
202f90ef8f | ||
|
|
c07ea17c01 | ||
|
|
edb4e3bd52 | ||
|
|
4113609dd4 | ||
|
|
7ac7b0872f | ||
|
|
86ae5881b7 | ||
|
|
fac003c64f | ||
|
|
2273655c17 | ||
|
|
01057cf76d | ||
|
|
032f096b7f | ||
|
|
4b334edf49 | ||
|
|
8ddcbc39e6 | ||
|
|
0b0eac1d5d | ||
|
|
b29fc8b27c | ||
|
|
5de369fa67 | ||
|
|
7918a50d52 | ||
|
|
21794c9b8d | ||
|
|
6c686ce593 | ||
|
|
db902af4c6 | ||
|
|
7d6907cb99 | ||
|
|
092d9affb8 | ||
|
|
8f681b1d17 | ||
|
|
90313875f7 | ||
|
|
3f18a61532 | ||
|
|
02a6ce07eb | ||
|
|
738fd52bc4 | ||
|
|
d18979bb23 | ||
|
|
8266993c6e | ||
|
|
9a137e8613 | ||
|
|
ef618332ea | ||
|
|
7f418978c9 | ||
|
|
04cc395c35 | ||
|
|
e008dc1bde | ||
|
|
ddf96cfda2 | ||
|
|
ebfd5c5c74 | ||
|
|
f2ad542679 | ||
|
|
c43118be4f | ||
|
|
93f3b2b114 | ||
|
|
bf000beae7 | ||
|
|
0e16d92786 | ||
|
|
2441827408 | ||
|
|
0aff037a35 | ||
|
|
74a2f53683 | ||
|
|
e20935c3f2 | ||
|
|
3e34f62a1c | ||
|
|
d21cb84696 | ||
|
|
3dd495ecdd | ||
|
|
b9f3ddfb30 | ||
|
|
77332a0315 | ||
|
|
85c56adbd1 | ||
|
|
8da3754e51 | ||
|
|
9a6b11f8e6 | ||
|
|
7ac6fdcc99 | ||
|
|
f6610baaa8 | ||
|
|
09b320e8a5 | ||
|
|
5a1e99d713 | ||
|
|
b762f2d6f4 | ||
|
|
172079a47f | ||
|
|
c58d3936a3 | ||
|
|
18302bf8e9 | ||
|
|
bc5047c1e7 | ||
|
|
206a54a746 | ||
|
|
32def5ebf5 | ||
|
|
ecc9f6b770 | ||
|
|
b37a68c84f | ||
|
|
c141ae6f8d | ||
|
|
97c464dbf5 | ||
|
|
3b28b915eb | ||
|
|
eb001dc1d9 | ||
|
|
aa9bdf416e | ||
|
|
8987780db6 | ||
|
|
30cfea2e7a | ||
|
|
f4e2fb9864 | ||
|
|
b80062c490 | ||
|
|
667fc4d08b | ||
|
|
6142117cdd | ||
|
|
ae28a24c7f | ||
|
|
ebe761cad0 | ||
|
|
fa7a7c5c5a | ||
|
|
557636f3b7 | ||
|
|
49fbe9c5ac | ||
|
|
2ac5086831 | ||
|
|
c6cfa04d10 | ||
|
|
346fa12e0e | ||
|
|
cda27b0970 | ||
|
|
3c74047368 | ||
|
|
94525d859f | ||
|
|
1127a2caf3 | ||
|
|
246d9d4e83 | ||
|
|
4c0b0177b6 | ||
|
|
38bfb73f06 | ||
|
|
bbedbf4ea0 | ||
|
|
2cfb5aa7da | ||
|
|
6c45101870 | ||
|
|
2c2fd89e34 | ||
|
|
f46281e2b7 | ||
|
|
25a18883f5 | ||
|
|
5b4b07e9a7 | ||
|
|
a8aa28a7a6 | ||
|
|
fe5a68f9d5 | ||
|
|
71e61153b1 | ||
|
|
c8b6f4733d | ||
|
|
a48f87abf2 | ||
|
|
2fd927a7cc | ||
|
|
8428326ea1 | ||
|
|
31f8209193 | ||
|
|
9b0f86f5a1 | ||
|
|
ee082ace1b | ||
|
|
ae67a49850 | ||
|
|
4178289c38 | ||
|
|
74ae16f9f8 | ||
|
|
1968203d83 | ||
|
|
86ea38a259 | ||
|
|
8a713e449f | ||
|
|
24aa07855b | ||
|
|
5fd723f143 | ||
|
|
516eaef50c | ||
|
|
4ae1fb3ed8 | ||
|
|
011123223b | ||
|
|
96439ca246 | ||
|
|
c927cea632 | ||
|
|
9f4b98f8e4 | ||
|
|
0f2ef3367c | ||
|
|
7e5b5cac97 | ||
|
|
c1346e06b7 | ||
|
|
0d2fe8e3ef | ||
|
|
f2b9c11e2a | ||
|
|
fe647b083e | ||
|
|
dfe4f6c6de | ||
|
|
a09c8ad666 | ||
|
|
ec598c351b | ||
|
|
eba0f93bc0 | ||
|
|
99800d4aa9 | ||
|
|
70d56c951a | ||
|
|
b810e2f8da | ||
|
|
1abe14296e | ||
|
|
6920e898d1 | ||
|
|
dd71639264 | ||
|
|
2dcc552ce0 | ||
|
|
55387e8fd0 | ||
|
|
7e3e9da860 | ||
|
|
00f509405b | ||
|
|
aceb0af36b | ||
|
|
4f0953f7e9 | ||
|
|
182a47bfb1 | ||
|
|
cd27f4ec38 | ||
|
|
8158b1bdcf | ||
|
|
aacf3edc68 | ||
|
|
8b89072190 | ||
|
|
395a17ccda | ||
|
|
3f355866cf | ||
|
|
71d52f147d | ||
|
|
eb7adaa6fc | ||
|
|
e5cf7972ea | ||
|
|
f81ff10a9b | ||
|
|
16d40915b4 | ||
|
|
e7c21e87e3 | ||
|
|
c4c2ef44d0 | ||
|
|
a845897758 | ||
|
|
32ea2c5530 | ||
|
|
bc61deeca9 | ||
|
|
6a5e74b44e | ||
|
|
54446341ee | ||
|
|
4e12a6f740 | ||
|
|
b35dfc2599 | ||
|
|
9e1da9235e | ||
|
|
a5ffe2c23f | ||
|
|
9282e7b0c6 | ||
|
|
5229cb2b1b | ||
|
|
458e3e15f0 | ||
|
|
c615a1e80a | ||
|
|
10a938cb79 | ||
|
|
4956ad311b | ||
|
|
145874e504 | ||
|
|
bd7be07c38 | ||
|
|
71ee91e716 | ||
|
|
4f70d2e28c | ||
|
|
4b6ca5e742 | ||
|
|
9306da3c58 | ||
|
|
1ac25fc032 | ||
|
|
5f046c724b | ||
|
|
af0262b7e5 | ||
|
|
6b3aeff1d8 | ||
|
|
20e4f8277f | ||
|
|
f3a487a368 | ||
|
|
2dde41615a | ||
|
|
8b69a3d18e | ||
|
|
d40950b741 | ||
|
|
7659ea1d2e | ||
|
|
bdeadffbf5 | ||
|
|
5e6f26445f | ||
|
|
f0a99125ee | ||
|
|
1e4de2e6d3 | ||
|
|
8b4dcd8f3e | ||
|
|
285401ced8 | ||
|
|
9db4c42380 | ||
|
|
94e5e00c03 | ||
|
|
dc6bcaa18e | ||
|
|
d58b184835 | ||
|
|
b3a57ff019 | ||
|
|
3d5bc08185 | ||
|
|
0692435f01 | ||
|
|
f67a6b0e43 | ||
|
|
343ea326c2 | ||
|
|
1c150c632f | ||
|
|
0a0f4f5591 | ||
|
|
931daa85bf | ||
|
|
00e4f7b3c1 | ||
|
|
11e63bc335 | ||
|
|
33405bb24b | ||
|
|
57dc4fb32f | ||
|
|
b85a358deb | ||
|
|
43697958f3 | ||
|
|
3f961bbba0 | ||
|
|
0a1e523cd5 | ||
|
|
4231f7323e | ||
|
|
da2de350c3 | ||
|
|
41beae4dd7 | ||
|
|
82db9188ac | ||
|
|
3dc9e140e4 | ||
|
|
fed0096556 | ||
|
|
2bdc8802dd | ||
|
|
5ef7cb372a | ||
|
|
4ad7b1dae4 | ||
|
|
9186859cb7 | ||
|
|
47c0713747 | ||
|
|
293c566d6c | ||
|
|
9c306406f1 | ||
|
|
9db0695b10 | ||
|
|
f2af093402 | ||
|
|
b9ad53d1ab | ||
|
|
b0eab71470 | ||
|
|
3493a182b2 | ||
|
|
27c5284d3d | ||
|
|
540220b91b | ||
|
|
84634da4b5 | ||
|
|
1743621889 | ||
|
|
f330ab743a | ||
|
|
4377e932ca | ||
|
|
bac14ba881 | ||
|
|
ec095ed647 | ||
|
|
17e73121fa | ||
|
|
f71e8fd948 | ||
|
|
3e62faa64f | ||
|
|
e9645e017f | ||
|
|
55b5f2a8aa | ||
|
|
4e0a22e5c8 | ||
|
|
1aa38051fb | ||
|
|
e62b879b48 | ||
|
|
c6c9f4f5a8 | ||
|
|
fec14379f6 | ||
|
|
79131cd647 | ||
|
|
c3f14a1481 | ||
|
|
7b13159cda | ||
|
|
95094b9c22 | ||
|
|
1ff8e9dd38 | ||
|
|
78309a293d | ||
|
|
695e182d59 | ||
|
|
dc33facfcb | ||
|
|
c70fb60384 | ||
|
|
793d61499b | ||
|
|
a277fe168d | ||
|
|
7d3b941e6e |
19
.github/ISSUE_TEMPLATE.md
vendored
19
.github/ISSUE_TEMPLATE.md
vendored
@@ -2,19 +2,24 @@
|
||||
|
||||
<!-- Note: sub-optimal but correct code is not a bug -->
|
||||
|
||||
**ES5 or ES6+ input?**
|
||||
|
||||
<!-- Note: for ES6 see: https://github.com/mishoo/UglifyJS2/tree/harmony#harmony -->
|
||||
|
||||
**Uglify version (`uglifyjs -V`)**
|
||||
|
||||
**JavaScript input** <!-- ideally as small as possible -->
|
||||
**JavaScript input**
|
||||
|
||||
<!--
|
||||
A complete parsable JS program exhibiting the issue with
|
||||
UglifyJS alone - without third party tools or libraries.
|
||||
Ideally the input should be as small as possible.
|
||||
Post a link to a gist if necessary.
|
||||
|
||||
Issues without a reproducible test case will be closed.
|
||||
-->
|
||||
|
||||
**The `uglifyjs` CLI command executed or `minify()` options used.**
|
||||
|
||||
**JavaScript output or error produced.**
|
||||
|
||||
<!--
|
||||
Note: `uglify-js` only supports ES5.
|
||||
Those wishing to minify ES6 should use `uglify-es`.
|
||||
Note: `uglify-js` only supports JavaScript.
|
||||
Those wishing to minify ES6+ should transpile first.
|
||||
-->
|
||||
|
||||
39
.travis.yml
39
.travis.yml
@@ -1,11 +1,34 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.10"
|
||||
- "0.12"
|
||||
- "4"
|
||||
- "6"
|
||||
env:
|
||||
- UGLIFYJS_TEST_ALL=1
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- libstdc++-4.9-dev
|
||||
cache:
|
||||
directories: tmp
|
||||
language: generic
|
||||
matrix:
|
||||
fast_finish: true
|
||||
sudo: false
|
||||
env:
|
||||
global:
|
||||
- UGLIFYJS_TEST_ALL=1
|
||||
matrix:
|
||||
- NODEJS_VER=node/0.10
|
||||
- NODEJS_VER=node/0.12
|
||||
- NODEJS_VER=node/4
|
||||
- NODEJS_VER=node/6
|
||||
- NODEJS_VER=node/8
|
||||
- NODEJS_VER=node/latest
|
||||
before_install:
|
||||
- git clone --branch v1.4.2 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
|
||||
- . ~/.nvs/nvs.sh
|
||||
- nvs --version
|
||||
install:
|
||||
- nvs add $NODEJS_VER
|
||||
- nvs use $NODEJS_VER
|
||||
- node --version
|
||||
- npm --version --no-update-notifier
|
||||
- npm install --no-optional --no-save --no-update-notifier
|
||||
script:
|
||||
- npm test --no-update-notifier
|
||||
|
||||
61
CONTRIBUTING.md
Normal file
61
CONTRIBUTING.md
Normal file
@@ -0,0 +1,61 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
## Documentation
|
||||
|
||||
Every new feature and API change should be accompanied by a README additon.
|
||||
|
||||
## Testing
|
||||
|
||||
All features and bugs should have tests that verify the fix. You can run all
|
||||
tests using `npm test`.
|
||||
|
||||
The most common type of test are tests that verify input and output of the
|
||||
Uglify transforms. These tests exist in `test/compress`. New tests can be added
|
||||
either to an existing file or in a new file `issue-xxx.js`.
|
||||
|
||||
Tests that cannot be expressed as a simple AST can be found in `test/mocha`.
|
||||
|
||||
## Code style
|
||||
|
||||
- File encoding must be `UTF-8`.
|
||||
- `LF` is always used as a line ending.
|
||||
- Statements end with semicolons.
|
||||
- Indentation uses 4 spaces, switch `case` 2 spaces.
|
||||
- Identifiers use `snake_case`.
|
||||
- Strings use double quotes (`"`).
|
||||
- Use a trailing comma for multiline array and object literals to minimize diffs.
|
||||
- The Uglify code only uses ES5, even in the `harmony` branch.
|
||||
- Line length should be at most 80 cols, except when it is easier to read a
|
||||
longer line.
|
||||
- If both sides of a comparison are of the same type, `==` and `!=` are used.
|
||||
- Multiline conditions place `&&` and `||` first on the line.
|
||||
|
||||
**Example feature**
|
||||
|
||||
```js
|
||||
OPT(AST_Debugger, function(self, compressor) {
|
||||
if (compressor.option("drop_debugger"))
|
||||
return make_node(AST_EmptyStatement, self);
|
||||
return self;
|
||||
});
|
||||
```
|
||||
|
||||
**Example test case**
|
||||
|
||||
```js
|
||||
drop_debugger: {
|
||||
options = {
|
||||
drop_debugger: true,
|
||||
}
|
||||
input: {
|
||||
debugger;
|
||||
if (foo) debugger;
|
||||
}
|
||||
expect: {
|
||||
if (foo);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
UglifyJS is released under the BSD license:
|
||||
|
||||
Copyright 2012-2013 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
Copyright 2012-2018 (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
|
||||
|
||||
513
README.md
513
README.md
@@ -6,9 +6,8 @@ UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
|
||||
#### Note:
|
||||
- **`uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage) that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
|
||||
- **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
|
||||
- `uglify-js` only supports ECMAScript 5 (ES5).
|
||||
- Those wishing to minify
|
||||
ES2015+ (ES6+) should use the `npm` package [**uglify-es**](https://github.com/mishoo/UglifyJS2/tree/harmony).
|
||||
- `uglify-js` only supports JavaScript (ECMAScript 5).
|
||||
- To minify ECMAScript 2015 or above, transpile using tools like [Babel](https://babeljs.io/).
|
||||
|
||||
Install
|
||||
-------
|
||||
@@ -45,6 +44,7 @@ a double dash to prevent input files being used as option arguments:
|
||||
|
||||
```
|
||||
-h, --help Print usage information.
|
||||
`--help options` for details on available options.
|
||||
-V, --version Print version number.
|
||||
-p, --parse <options> Specify parser options:
|
||||
`acorn` Use Acorn for parsing.
|
||||
@@ -69,7 +69,7 @@ a double dash to prevent input files being used as option arguments:
|
||||
`debug` Add debug prefix and suffix.
|
||||
`domprops` Mangle property names that overlaps
|
||||
with DOM properties.
|
||||
`keep_quoted` Only mangle unquoted properies.
|
||||
`keep_quoted` Only mangle unquoted properties.
|
||||
`regex` Only mangle matched property names.
|
||||
`reserved` List of names that should not be mangled.
|
||||
-b, --beautify [options] Beautify output/specify output options:
|
||||
@@ -104,13 +104,15 @@ a double dash to prevent input files being used as option arguments:
|
||||
sequences.
|
||||
--config-file <file> Read `minify()` options from JSON file.
|
||||
-d, --define <expr>[=value] Global definitions.
|
||||
-e, --enclose [arg[:value]] Embed everything in a big function, with configurable
|
||||
argument(s) & value(s).
|
||||
--ie8 Support non-standard Internet Explorer 8.
|
||||
Equivalent to setting `ie8: true` in `minify()`
|
||||
for `compress`, `mangle` and `output` options.
|
||||
By default UglifyJS will not try to be IE-proof.
|
||||
--keep-fnames Do not mangle/drop function names. Useful for
|
||||
code relying on Function.prototype.name.
|
||||
--name-cache File to hold mangled name mappings.
|
||||
--name-cache <file> File to hold mangled name mappings.
|
||||
--self Build UglifyJS as a library (implies --wrap UglifyJS)
|
||||
--source-map [options] Enable source map/specify source map options:
|
||||
`base` Path to compute relative paths from input files.
|
||||
@@ -118,7 +120,8 @@ a double dash to prevent input files being used as option arguments:
|
||||
JS that was generated from some other original
|
||||
code. Specify "inline" if the source map is
|
||||
included within the sources.
|
||||
`filename` Name and/or location of the output source.
|
||||
`filename` Filename and/or location of the output source
|
||||
(sets `file` attribute in source map).
|
||||
`includeSources` Pass this flag if you want to include
|
||||
the content of source files in the
|
||||
source map as sourcesContent property.
|
||||
@@ -126,7 +129,7 @@ a double dash to prevent input files being used as option arguments:
|
||||
the source map.
|
||||
`url` If specified, path to the source map to append in
|
||||
`//# sourceMappingURL`.
|
||||
--stats Display operations run time on STDERR.
|
||||
--timings Display operations run time on STDERR.
|
||||
--toplevel Compress and/or mangle variables in top level scope.
|
||||
--verbose Print diagnostic messages.
|
||||
--warn Print warning messages.
|
||||
@@ -149,19 +152,21 @@ debugging your compressed JavaScript. To get a source map, pass
|
||||
|
||||
Additional options:
|
||||
|
||||
- `--source-map filename=<NAME>` to specify the name of the source map.
|
||||
- `--source-map "filename='<NAME>'"` to specify the name of the source map. The value of
|
||||
`filename` is only used to set `file` attribute (see [the spec][sm-spec])
|
||||
in source map file.
|
||||
|
||||
- `--source-map root=<URL>` to pass the URL where the original files can be found.
|
||||
- `--source-map "root='<URL>'"` to pass the URL where the original files can be found.
|
||||
|
||||
- `--source-map "url='<URL>'"` to specify the URL where the source map can be found.
|
||||
Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
|
||||
`//# sourceMappingURL=` directive.
|
||||
|
||||
- `--source-map url=<URL>` to specify the URL where the source map can be found.
|
||||
|
||||
For example:
|
||||
|
||||
uglifyjs js/file1.js js/file2.js \
|
||||
-o foo.min.js -c -m \
|
||||
--source-map root="http://foo.com/src",url=foo.min.js.map
|
||||
--source-map "root='http://foo.com/src',url='foo.min.js.map'"
|
||||
|
||||
The above will compress and mangle `file1.js` and `file2.js`, will drop the
|
||||
output in `foo.min.js` and the source map in `foo.min.js.map`. The source
|
||||
@@ -180,8 +185,8 @@ CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →
|
||||
compressed JS by mapping every token in the compiled JS to its original
|
||||
location.
|
||||
|
||||
To use this feature pass `--source-map content="/path/to/input/source.map"`
|
||||
or `--source-map content=inline` if the source map is included inline with
|
||||
To use this feature pass `--source-map "content='/path/to/input/source.map'"`
|
||||
or `--source-map "content=inline"` if the source map is included inline with
|
||||
the sources.
|
||||
|
||||
## CLI compress options
|
||||
@@ -202,40 +207,68 @@ Example:
|
||||
To enable the mangler you need to pass `--mangle` (`-m`). The following
|
||||
(comma-separated) options are supported:
|
||||
|
||||
- `toplevel` — mangle names declared in the top level scope (disabled by
|
||||
default).
|
||||
- `toplevel` (default `false`) -- mangle names declared in the top level scope.
|
||||
|
||||
- `eval` — mangle names visible in scopes where `eval` or `with` are used
|
||||
(disabled by default).
|
||||
- `eval` (default `false`) -- mangle names visible in scopes where `eval` or `with` are used.
|
||||
|
||||
When mangling is enabled but you want to prevent certain names from being
|
||||
mangled, you can declare those names with `--mangle reserved` — pass a
|
||||
comma-separated list of names. For example:
|
||||
|
||||
uglifyjs ... -m reserved=[$,require,exports]
|
||||
uglifyjs ... -m reserved=['$','require','exports']
|
||||
|
||||
to prevent the `require`, `exports` and `$` names from being changed.
|
||||
|
||||
### CLI mangling property names (`--mangle-props`)
|
||||
|
||||
**Note:** this will probably break your code. Mangling property names is a
|
||||
separate step, different from variable name mangling. Pass
|
||||
`--mangle-props`. It will mangle all properties that are seen in some
|
||||
object literal, or that are assigned to. For example:
|
||||
**Note:** THIS WILL PROBABLY BREAK YOUR CODE. Mangling property names
|
||||
is a separate step, different from variable name mangling. Pass
|
||||
`--mangle-props` to enable it. It will mangle all properties in the
|
||||
input code with the exception of built in DOM properties and properties
|
||||
in core JavaScript classes. For example:
|
||||
|
||||
```javascript
|
||||
// example.js
|
||||
var x = {
|
||||
foo: 1
|
||||
baz_: 0,
|
||||
foo_: 1,
|
||||
calc: function() {
|
||||
return this.foo_ + this.baz_;
|
||||
}
|
||||
};
|
||||
|
||||
x.bar = 2;
|
||||
x["baz"] = 3;
|
||||
x[condition ? "moo" : "boo"] = 4;
|
||||
console.log(x.something());
|
||||
x.bar_ = 2;
|
||||
x["baz_"] = 3;
|
||||
console.log(x.calc());
|
||||
```
|
||||
Mangle all properties (except for JavaScript `builtins`):
|
||||
```bash
|
||||
$ uglifyjs example.js -c -m --mangle-props
|
||||
```
|
||||
```javascript
|
||||
var x={o:0,_:1,l:function(){return this._+this.o}};x.t=2,x.o=3,console.log(x.l());
|
||||
```
|
||||
Mangle all properties except for `reserved` properties:
|
||||
```bash
|
||||
$ uglifyjs example.js -c -m --mangle-props reserved=[foo_,bar_]
|
||||
```
|
||||
```javascript
|
||||
var x={o:0,foo_:1,_:function(){return this.foo_+this.o}};x.bar_=2,x.o=3,console.log(x._());
|
||||
```
|
||||
Mangle all properties matching a `regex`:
|
||||
```bash
|
||||
$ uglifyjs example.js -c -m --mangle-props regex=/_$/
|
||||
```
|
||||
```javascript
|
||||
var x={o:0,_:1,calc:function(){return this._+this.o}};x.l=2,x.o=3,console.log(x.calc());
|
||||
```
|
||||
|
||||
In the above code, `foo`, `bar`, `baz`, `moo` and `boo` will be replaced
|
||||
with single characters, while `something()` will be left as is.
|
||||
Combining mangle properties options:
|
||||
```bash
|
||||
$ uglifyjs example.js -c -m --mangle-props regex=/_$/,reserved=[bar_]
|
||||
```
|
||||
```javascript
|
||||
var x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log(x.calc());
|
||||
```
|
||||
|
||||
In order for this to be of any use, we avoid mangling standard JS names by
|
||||
default (`--mangle-props builtins` to override).
|
||||
@@ -244,7 +277,7 @@ A default exclusion file is provided in `tools/domprops.json` which should
|
||||
cover most standard JS and DOM properties defined in various browsers. Pass
|
||||
`--mangle-props domprops` to disable this feature.
|
||||
|
||||
You can also use a regular expression to define which property names should be
|
||||
A regular expression can be used to define which property names should be
|
||||
mangled. For example, `--mangle-props regex=/^_/` will only mangle property
|
||||
names that start with an underscore.
|
||||
|
||||
@@ -272,9 +305,20 @@ Using quoted property name (`o["foo"]`) reserves the property name (`foo`)
|
||||
so that it is not mangled throughout the entire script even when used in an
|
||||
unquoted style (`o.foo`). Example:
|
||||
|
||||
```javascript
|
||||
// stuff.js
|
||||
var o = {
|
||||
"foo": 1,
|
||||
bar: 3
|
||||
};
|
||||
o.foo += o.bar;
|
||||
console.log(o.foo);
|
||||
```
|
||||
```bash
|
||||
$ echo 'var o={"foo":1, bar:3}; o.foo += o.bar; console.log(o.foo);' | uglifyjs --mangle-props keep_quoted -mc
|
||||
var o={foo:1,a:3};o.foo+=o.a,console.log(o.foo);
|
||||
$ uglifyjs stuff.js --mangle-props keep_quoted -c -m
|
||||
```
|
||||
```javascript
|
||||
var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
|
||||
```
|
||||
|
||||
### Debugging property name mangling
|
||||
@@ -285,6 +329,13 @@ would mangle to `o._$foo$_` with this option. This allows property mangling
|
||||
of a large codebase while still being able to debug the code and identify
|
||||
where mangling is breaking things.
|
||||
|
||||
```bash
|
||||
$ uglifyjs stuff.js --mangle-props debug -c -m
|
||||
```
|
||||
```javascript
|
||||
var o={_$foo$_:1,_$bar$_:3};o._$foo$_+=o._$bar$_,console.log(o._$foo$_);
|
||||
```
|
||||
|
||||
You can also pass a custom suffix using `--mangle-props debug=XYZ`. This would then
|
||||
mangle `o.foo` to `o._$foo$XYZ_`. You can change this each time you compile a
|
||||
script to identify how a property got mangled. One technique is to pass a
|
||||
@@ -334,7 +385,47 @@ var code = {
|
||||
var options = { toplevel: true };
|
||||
var result = UglifyJS.minify(code, options);
|
||||
console.log(result.code);
|
||||
// console.log(function(n,o){return n+o}(3,7));
|
||||
// console.log(3+7);
|
||||
```
|
||||
|
||||
The `nameCache` option:
|
||||
```javascript
|
||||
var options = {
|
||||
mangle: {
|
||||
toplevel: true,
|
||||
},
|
||||
nameCache: {}
|
||||
};
|
||||
var result1 = UglifyJS.minify({
|
||||
"file1.js": "function add(first, second) { return first + second; }"
|
||||
}, options);
|
||||
var result2 = UglifyJS.minify({
|
||||
"file2.js": "console.log(add(1 + 2, 3 + 4));"
|
||||
}, options);
|
||||
console.log(result1.code);
|
||||
// function n(n,r){return n+r}
|
||||
console.log(result2.code);
|
||||
// console.log(n(3,7));
|
||||
```
|
||||
|
||||
You may persist the name cache to the file system in the following way:
|
||||
```javascript
|
||||
var cacheFileName = "/tmp/cache.json";
|
||||
var options = {
|
||||
mangle: {
|
||||
properties: true,
|
||||
},
|
||||
nameCache: JSON.parse(fs.readFileSync(cacheFileName, "utf8"))
|
||||
};
|
||||
fs.writeFileSync("part1.js", UglifyJS.minify({
|
||||
"file1.js": fs.readFileSync("file1.js", "utf8"),
|
||||
"file2.js": fs.readFileSync("file2.js", "utf8")
|
||||
}, options).code, "utf8");
|
||||
fs.writeFileSync("part2.js", UglifyJS.minify({
|
||||
"file3.js": fs.readFileSync("file3.js", "utf8"),
|
||||
"file4.js": fs.readFileSync("file4.js", "utf8")
|
||||
}, options).code, "utf8");
|
||||
fs.writeFileSync(cacheFileName, JSON.stringify(options.nameCache), "utf8");
|
||||
```
|
||||
|
||||
An example of a combination of `minify()` options:
|
||||
@@ -412,13 +503,22 @@ if (result.error) throw result.error;
|
||||
- `toplevel` (default `false`) - set to `true` if you wish to enable top level
|
||||
variable and function name mangling and to drop unused variables and functions.
|
||||
|
||||
- `nameCache` (default `null`) - pass an empty object `{}` or a previously
|
||||
used `nameCache` object if you wish to cache mangled variable and
|
||||
property names across multiple invocations of `minify()`. Note: this is
|
||||
a read/write property. `minify()` will read the name cache state of this
|
||||
object and update it during minification so that it may be
|
||||
reused or externally persisted by the user.
|
||||
|
||||
- `ie8` (default `false`) - set to `true` to support IE8.
|
||||
|
||||
- `keep_fnames` (default: `false`) - pass `true` to prevent discarding or mangling
|
||||
of function names. Useful for code relying on `Function.prototype.name`.
|
||||
|
||||
## Minify options structure
|
||||
|
||||
```javascript
|
||||
{
|
||||
warnings: false,
|
||||
parse: {
|
||||
// parse options
|
||||
},
|
||||
@@ -438,8 +538,10 @@ if (result.error) throw result.error;
|
||||
sourceMap: {
|
||||
// source map options
|
||||
},
|
||||
nameCache: null, // or specify a name cache object
|
||||
toplevel: false,
|
||||
ie8: false,
|
||||
warnings: false,
|
||||
}
|
||||
```
|
||||
|
||||
@@ -493,102 +595,95 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
## Parse options
|
||||
|
||||
- `bare_returns` (default `false`) -- support top level `return` statements
|
||||
|
||||
- `html5_comments` (default `true`)
|
||||
|
||||
- `shebang` (default `true`) -- support `#!command` as the first line
|
||||
|
||||
## Compress options
|
||||
|
||||
- `sequences` (default: true) -- join consecutive simple statements using the
|
||||
comma operator. May be set to a positive integer to specify the maximum number
|
||||
of consecutive comma sequences that will be generated. If this option is set to
|
||||
`true` then the default `sequences` limit is `200`. Set option to `false` or `0`
|
||||
to disable. The smallest `sequences` length is `2`. A `sequences` value of `1`
|
||||
is grandfathered to be equivalent to `true` and as such means `200`. On rare
|
||||
occasions the default sequences limit leads to very slow compress times in which
|
||||
case a value of `20` or less is recommended.
|
||||
- `arguments` (default: `true`) -- replace `arguments[index]` with function
|
||||
parameter name whenever possible.
|
||||
|
||||
- `properties` -- rewrite property access using the dot notation, for
|
||||
example `foo["bar"] → foo.bar`
|
||||
- `booleans` (default: `true`) -- various optimizations for boolean context,
|
||||
for example `!!a ? b : c → a ? b : c`
|
||||
|
||||
- `dead_code` -- remove unreachable code
|
||||
- `collapse_vars` (default: `true`) -- Collapse single-use non-constant variables,
|
||||
side effects permitting.
|
||||
|
||||
- `drop_debugger` -- remove `debugger;` statements
|
||||
- `comparisons` (default: `true`) -- apply certain optimizations to binary nodes,
|
||||
e.g. `!(a <= b) → a > b`, attempts to negate binary nodes, e.g.
|
||||
`a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
|
||||
|
||||
- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below)
|
||||
|
||||
- `unsafe_comps` (default: false) -- Reverse `<` and `<=` to `>` and `>=` to
|
||||
allow improved compression. This might be unsafe when an at least one of two
|
||||
operands is an object with computed values due the use of methods like `get`,
|
||||
or `valueOf`. This could cause change in execution order after operands in the
|
||||
comparison are switching. Compression only works if both `comparisons` and
|
||||
`unsafe_comps` are both set to true.
|
||||
|
||||
- `unsafe_math` (default: false) -- optimize numerical expressions like
|
||||
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
||||
|
||||
- `unsafe_proto` (default: false) -- optimize expressions like
|
||||
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
||||
|
||||
- `unsafe_regexp` (default: false) -- enable substitutions of variables with
|
||||
`RegExp` values the same way as if they are constants.
|
||||
|
||||
- `conditionals` -- apply optimizations for `if`-s and conditional
|
||||
- `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional
|
||||
expressions
|
||||
|
||||
- `comparisons` -- apply certain optimizations to binary nodes, for example:
|
||||
`!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary
|
||||
nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
|
||||
- `dead_code` (default: `true`) -- remove unreachable code
|
||||
|
||||
- `evaluate` -- attempt to evaluate constant expressions
|
||||
- `directives` (default: `true`) -- remove redundant or non-standard directives
|
||||
|
||||
- `booleans` -- various optimizations for boolean context, for example `!!a
|
||||
? b : c → a ? b : c`
|
||||
- `drop_console` (default: `false`) -- Pass `true` to discard calls to
|
||||
`console.*` functions. If you wish to drop a specific function call
|
||||
such as `console.info` and/or retain side effects from function arguments
|
||||
after dropping the function call then use `pure_funcs` instead.
|
||||
|
||||
- `loops` -- optimizations for `do`, `while` and `for` loops when we can
|
||||
statically determine the condition
|
||||
- `drop_debugger` (default: `true`) -- remove `debugger;` statements
|
||||
|
||||
- `unused` -- drop unreferenced functions and variables (simple direct variable
|
||||
assignments do not count as references unless set to `"keep_assign"`)
|
||||
- `evaluate` (default: `true`) -- attempt to evaluate constant expressions
|
||||
|
||||
- `toplevel` -- drop unreferenced functions (`"funcs"`) and/or variables (`"vars"`)
|
||||
in the top level scope (`false` by default, `true` to drop both unreferenced
|
||||
functions and variables)
|
||||
- `expression` (default: `false`) -- Pass `true` to preserve completion values
|
||||
from terminal statements without `return`, e.g. in bookmarklets.
|
||||
|
||||
- `top_retain` -- prevent specific toplevel functions and variables from `unused`
|
||||
removal (can be array, comma-separated, RegExp or function. Implies `toplevel`)
|
||||
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
|
||||
|
||||
- `hoist_funs` -- hoist function declarations
|
||||
- `hoist_funs` (default: `false`) -- hoist function declarations
|
||||
|
||||
- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`
|
||||
- `hoist_props` (default: `true`) -- hoist properties from constant object and
|
||||
array literals into regular variables subject to a set of constraints. For example:
|
||||
`var o={p:1, q:2}; f(o.p, o.q);` is converted to `f(1, 2);`. Note: `hoist_props`
|
||||
works best with `mangle` enabled, the `compress` option `passes` set to `2` or higher,
|
||||
and the `compress` option `toplevel` enabled.
|
||||
|
||||
- `hoist_vars` (default: `false`) -- hoist `var` declarations (this is `false`
|
||||
by default because it seems to increase the size of the output in general)
|
||||
|
||||
- `if_return` -- optimizations for if/return and if/continue
|
||||
- `if_return` (default: `true`) -- optimizations for if/return and if/continue
|
||||
|
||||
- `join_vars` -- join consecutive `var` statements
|
||||
- `inline` (default: `true`) -- inline calls to function with simple/`return` statement:
|
||||
- `false` -- same as `0`
|
||||
- `0` -- disabled inlining
|
||||
- `1` -- inline simple functions
|
||||
- `2` -- inline functions with arguments
|
||||
- `3` -- inline functions with arguments and variables
|
||||
- `true` -- same as `3`
|
||||
|
||||
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
||||
and `x = something(), x` into `x = something()`
|
||||
- `join_vars` (default: `true`) -- join consecutive `var` statements
|
||||
|
||||
- `collapse_vars` -- Collapse single-use non-constant variables - side
|
||||
effects permitting.
|
||||
- `keep_fargs` (default: `true`) -- Prevents the compressor from discarding unused
|
||||
function arguments. You need this for code which relies on `Function.length`.
|
||||
|
||||
- `reduce_vars` -- Improve optimization on variables assigned with and
|
||||
used as constant values.
|
||||
- `keep_fnames` (default: `false`) -- Pass `true` to prevent the
|
||||
compressor from discarding function names. Useful for code relying on
|
||||
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
|
||||
|
||||
- `warnings` -- display warnings when dropping unreachable code or unused
|
||||
declarations etc.
|
||||
- `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
|
||||
being compressed into `1/0`, which may cause performance issues on Chrome.
|
||||
|
||||
- `negate_iife` -- negate "Immediately-Called Function Expressions"
|
||||
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops
|
||||
when we can statically determine the condition.
|
||||
|
||||
- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
|
||||
where the return value is discarded, to avoid the parens that the
|
||||
code generator would insert.
|
||||
|
||||
- `pure_getters` -- the default is `false`. If you pass `true` for
|
||||
this, UglifyJS will assume that object property access
|
||||
(e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
|
||||
Specify `"strict"` to treat `foo.bar` as side-effect-free only when
|
||||
`foo` is certain to not throw, i.e. not `null` or `undefined`.
|
||||
- `passes` (default: `1`) -- The maximum number of times to run compress.
|
||||
In some cases more than one pass leads to further compressed code. Keep in
|
||||
mind more passes will take more time.
|
||||
|
||||
- `pure_funcs` -- default `null`. You can pass an array of names and
|
||||
- `properties` (default: `true`) -- rewrite property access using the dot notation, for
|
||||
example `foo["bar"] → foo.bar`
|
||||
|
||||
- `pure_funcs` (default: `null`) -- You can pass an array of names and
|
||||
UglifyJS will assume that those functions do not produce side
|
||||
effects. DANGER: will not check if the name is redefined in scope.
|
||||
An example case here, for instance `var q = Math.floor(a/b)`. If
|
||||
@@ -597,49 +692,93 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
pass `pure_funcs: [ 'Math.floor' ]` to let it know that this
|
||||
function won't produce any side effect, in which case the whole
|
||||
statement would get discarded. The current implementation adds some
|
||||
overhead (compression will be slower).
|
||||
overhead (compression will be slower). Make sure symbols under `pure_funcs`
|
||||
are also under `mangle.reserved` to avoid mangling.
|
||||
|
||||
- `drop_console` -- default `false`. Pass `true` to discard calls to
|
||||
`console.*` functions. If you wish to drop a specific function call
|
||||
such as `console.info` and/or retain side effects from function arguments
|
||||
after dropping the function call then use `pure_funcs` instead.
|
||||
- `pure_getters` (default: `"strict"`) -- If you pass `true` for
|
||||
this, UglifyJS will assume that object property access
|
||||
(e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
|
||||
Specify `"strict"` to treat `foo.bar` as side-effect-free only when
|
||||
`foo` is certain to not throw, i.e. not `null` or `undefined`.
|
||||
|
||||
- `expression` -- default `false`. Pass `true` to preserve completion values
|
||||
from terminal statements without `return`, e.g. in bookmarklets.
|
||||
- `reduce_funcs` (default: `true`) -- Allows single-use functions to be
|
||||
inlined as function expressions when permissible allowing further
|
||||
optimization. Enabled by default. Option depends on `reduce_vars`
|
||||
being enabled. Some code runs faster in the Chrome V8 engine if this
|
||||
option is disabled. Does not negatively impact other major browsers.
|
||||
|
||||
- `keep_fargs` -- default `true`. Prevents the
|
||||
compressor from discarding unused function arguments. You need this
|
||||
for code which relies on `Function.length`.
|
||||
- `reduce_vars` (default: `true`) -- Improve optimization on variables assigned with and
|
||||
used as constant values.
|
||||
|
||||
- `keep_fnames` -- default `false`. Pass `true` to prevent the
|
||||
compressor from discarding function names. Useful for code relying on
|
||||
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
|
||||
- `sequences` (default: `true`) -- join consecutive simple statements using the
|
||||
comma operator. May be set to a positive integer to specify the maximum number
|
||||
of consecutive comma sequences that will be generated. If this option is set to
|
||||
`true` then the default `sequences` limit is `200`. Set option to `false` or `0`
|
||||
to disable. The smallest `sequences` length is `2`. A `sequences` value of `1`
|
||||
is grandfathered to be equivalent to `true` and as such means `200`. On rare
|
||||
occasions the default sequences limit leads to very slow compress times in which
|
||||
case a value of `20` or less is recommended.
|
||||
|
||||
- `passes` -- default `1`. Number of times to run compress with a maximum of 3.
|
||||
In some cases more than one pass leads to further compressed code. Keep in
|
||||
mind more passes will take more time.
|
||||
|
||||
- `keep_infinity` -- default `false`. Pass `true` to prevent `Infinity` from
|
||||
being compressed into `1/0`, which may cause performance issues on Chrome.
|
||||
|
||||
- `side_effects` -- default `true`. Pass `false` to disable potentially dropping
|
||||
- `side_effects` (default: `true`) -- Pass `false` to disable potentially dropping
|
||||
functions marked as "pure". A function call is marked as "pure" if a comment
|
||||
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
|
||||
example: `/*@__PURE__*/foo();`
|
||||
|
||||
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
|
||||
|
||||
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
|
||||
variables (`"vars"`) in the top level scope (`false` by default, `true` to drop
|
||||
both unreferenced functions and variables)
|
||||
|
||||
- `top_retain` (default: `null`) -- prevent specific toplevel functions and
|
||||
variables from `unused` removal (can be array, comma-separated, RegExp or
|
||||
function. Implies `toplevel`)
|
||||
|
||||
- `typeofs` (default: `true`) -- Transforms `typeof foo == "undefined"` into
|
||||
`foo === void 0`. Note: recommend to set this value to `false` for IE10 and
|
||||
earlier versions due to known issues.
|
||||
|
||||
- `unsafe` (default: `false`) -- apply "unsafe" transformations (discussion below)
|
||||
|
||||
- `unsafe_comps` (default: `false`) -- compress expressions like `a <= b` assuming
|
||||
none of the operands can be (coerced to) `NaN`.
|
||||
|
||||
- `unsafe_Function` (default: `false`) -- compress and mangle `Function(args, code)`
|
||||
when both `args` and `code` are string literals.
|
||||
|
||||
- `unsafe_math` (default: `false`) -- optimize numerical expressions like
|
||||
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
||||
|
||||
- `unsafe_proto` (default: `false`) -- optimize expressions like
|
||||
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
||||
|
||||
- `unsafe_regexp` (default: `false`) -- enable substitutions of variables with
|
||||
`RegExp` values the same way as if they are constants.
|
||||
|
||||
- `unsafe_undefined` (default: `false`) -- substitute `void 0` if there is a
|
||||
variable named `undefined` in scope (variable name will be mangled, typically
|
||||
reduced to a single character)
|
||||
|
||||
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
|
||||
direct variable assignments do not count as references unless set to `"keep_assign"`)
|
||||
|
||||
- `warnings` (default: `false`) -- display warnings when dropping unreachable
|
||||
code or unused declarations etc.
|
||||
|
||||
## Mangle options
|
||||
|
||||
- `reserved` - pass an array of identifiers that should be excluded from mangling
|
||||
- `eval` (default `false`) -- Pass `true` to mangle names visible in scopes
|
||||
where `eval` or `with` are used.
|
||||
|
||||
- `toplevel` — mangle names declared in the top level scope (disabled by
|
||||
default).
|
||||
- `keep_fnames` (default `false`) -- Pass `true` to not mangle function names.
|
||||
Useful for code relying on `Function.prototype.name`. See also: the `keep_fnames`
|
||||
[compress option](#compress-options).
|
||||
|
||||
- `eval` — mangle names visible in scopes where eval or with are used
|
||||
(disabled by default).
|
||||
- `reserved` (default `[]`) -- Pass an array of identifiers that should be
|
||||
excluded from mangling. Example: `["foo", "bar"]`.
|
||||
|
||||
- `keep_fnames` -- default `false`. Pass `true` to not mangle
|
||||
function names. Useful for code relying on `Function.prototype.name`.
|
||||
See also: the `keep_fnames` [compress option](#compress-options).
|
||||
- `toplevel` (default `false`) -- Pass `true` to mangle names declared in the
|
||||
top level scope.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -665,10 +804,19 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
|
||||
|
||||
### Mangle properties options
|
||||
|
||||
- `regex` — Pass a RegExp to only mangle certain names
|
||||
- `keep_quoted` — Only mangle unquoted property names
|
||||
- `debug` — Mangle names with the original name still present. Defaults to `false`.
|
||||
Pass an empty string to enable, or a non-empty string to set the suffix.
|
||||
- `builtins` (default: `false`) -- Use `true` to allow the mangling of builtin
|
||||
DOM properties. Not recommended to override this setting.
|
||||
|
||||
- `debug` (default: `false`) -— Mangle names with the original name still present.
|
||||
Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
|
||||
|
||||
- `keep_quoted` (default: `false`) -— Only mangle unquoted property names.
|
||||
|
||||
- `regex` (default: `null`) -— Pass a RegExp literal to only mangle property
|
||||
names matching the regular expression.
|
||||
|
||||
- `reserved` (default: `[]`) -- Do not mangle property names listed in the
|
||||
`reserved` array.
|
||||
|
||||
## Output options
|
||||
|
||||
@@ -678,48 +826,67 @@ can pass additional arguments that control the code output:
|
||||
|
||||
- `ascii_only` (default `false`) -- escape Unicode characters in strings and
|
||||
regexps (affects directives with non-ascii characters becoming invalid)
|
||||
|
||||
- `beautify` (default `true`) -- whether to actually beautify the output.
|
||||
Passing `-b` will set this to true, but you might need to pass `-b` even
|
||||
when you want to generate minified code, in order to specify additional
|
||||
arguments, so you can use `-b beautify=false` to override it.
|
||||
- `bracketize` (default `false`) -- always insert brackets in `if`, `for`,
|
||||
|
||||
- `braces` (default `false`) -- always insert braces in `if`, `for`,
|
||||
`do`, `while` or `with` statements, even if their body is a single
|
||||
statement.
|
||||
|
||||
- `comments` (default `false`) -- pass `true` or `"all"` to preserve all
|
||||
comments, `"some"` to preserve some comments, a regular expression string
|
||||
(e.g. `/^!/`) or a function.
|
||||
- `indent_level` (default 4)
|
||||
- `indent_start` (default 0) -- prefix all lines by that many spaces
|
||||
- `inline_script` (default `false`) -- escape the slash in occurrences of
|
||||
`</script` in strings
|
||||
|
||||
- `indent_level` (default `4`)
|
||||
|
||||
- `indent_start` (default `0`) -- prefix all lines by that many spaces
|
||||
|
||||
- `inline_script` (default `true`) -- escape HTML comments and the slash in
|
||||
occurrences of `</script>` in strings
|
||||
|
||||
- `keep_quoted_props` (default `false`) -- when turned on, prevents stripping
|
||||
quotes from property names in object literals.
|
||||
|
||||
- `max_line_len` (default `false`) -- maximum line length (for uglified code)
|
||||
|
||||
- `preamble` (default `null`) -- when passed it must be a string and
|
||||
it will be prepended to the output literally. The source map will
|
||||
adjust for this text. Can be used to insert a comment containing
|
||||
licensing information, for example.
|
||||
- `preserve_line` (default `false`) -- pass `true` to preserve lines, but it
|
||||
only works if `beautify` is set to `false`.
|
||||
|
||||
- `preserve_line` (default `false`) -- pass `true` to retain line numbering on
|
||||
a best effort basis.
|
||||
|
||||
- `quote_keys` (default `false`) -- pass `true` to quote all keys in literal
|
||||
objects
|
||||
|
||||
- `quote_style` (default `0`) -- preferred quote style for strings (affects
|
||||
quoted property names and directives as well):
|
||||
- `0` -- prefers double quotes, switches to single quotes when there are
|
||||
more double quotes in the string itself.
|
||||
more double quotes in the string itself. `0` is best for gzip size.
|
||||
- `1` -- always use single quotes
|
||||
- `2` -- always use double quotes
|
||||
- `3` -- always use the original quotes
|
||||
|
||||
- `semicolons` (default `true`) -- separate statements with semicolons. If
|
||||
you pass `false` then whenever possible we will use a newline instead of a
|
||||
semicolon, leading to more readable output of uglified code (size before
|
||||
gzip could be smaller; size after gzip insignificantly larger).
|
||||
|
||||
- `shebang` (default `true`) -- preserve shebang `#!` in preamble (bash scripts)
|
||||
- `width` (default 80) -- only takes effect when beautification is on, this
|
||||
|
||||
- `webkit` (default `false`) -- enable workarounds for WebKit bugs.
|
||||
PhantomJS users should set this option to `true`.
|
||||
|
||||
- `width` (default `80`) -- only takes effect when beautification is on, this
|
||||
specifies an (orientative) line width that the beautifier will try to
|
||||
obey. It refers to the width of the line text (excluding indentation).
|
||||
It doesn't work very well currently, but it does make the code generated
|
||||
by UglifyJS more readable.
|
||||
|
||||
- `wrap_iife` (default `false`) -- pass `true` to wrap immediately invoked
|
||||
function expressions. See
|
||||
[#640](https://github.com/mishoo/UglifyJS2/issues/640) for more details.
|
||||
@@ -765,10 +932,6 @@ when this flag is on:
|
||||
- `new Object()` → `{}`
|
||||
- `String(exp)` or `exp.toString()` → `"" + exp`
|
||||
- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
|
||||
- `typeof foo == "undefined"` → `foo === void 0`
|
||||
- `void 0` → `undefined` (if there is a variable named "undefined" in
|
||||
scope; we do it because the variable name will be mangled, typically
|
||||
reduced to a single character)
|
||||
|
||||
### Conditional compilation
|
||||
|
||||
@@ -885,8 +1048,9 @@ var result = UglifyJS.minify(ast, {
|
||||
### Working with Uglify AST
|
||||
|
||||
Transversal and transformation of the native AST can be performed through
|
||||
[`TreeWalker`](http://lisperator.net/uglifyjs/walk) and
|
||||
[`TreeTransformer`](http://lisperator.net/uglifyjs/transform) respectively.
|
||||
[`TreeWalker`](https://github.com/mishoo/UglifyJS2/blob/master/lib/ast.js) and
|
||||
[`TreeTransformer`](https://github.com/mishoo/UglifyJS2/blob/master/lib/transform.js)
|
||||
respectively.
|
||||
|
||||
### ESTree / SpiderMonkey AST
|
||||
|
||||
@@ -918,3 +1082,54 @@ in total it's a bit more than just using UglifyJS's own parser.
|
||||
|
||||
[acorn]: https://github.com/ternjs/acorn
|
||||
[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k
|
||||
|
||||
### Uglify Fast Minify Mode
|
||||
|
||||
It's not well known, but whitespace removal and symbol mangling accounts
|
||||
for 95% of the size reduction in minified code for most JavaScript - not
|
||||
elaborate code transforms. One can simply disable `compress` to speed up
|
||||
Uglify builds by 3 to 4 times. In this fast `mangle`-only mode Uglify has
|
||||
comparable minify speeds and gzip sizes to
|
||||
[`butternut`](https://www.npmjs.com/package/butternut):
|
||||
|
||||
| d3.js | minify size | gzip size | minify time (seconds) |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| original | 451,131 | 108,733 | - |
|
||||
| uglify-js@3.0.24 mangle=false, compress=false | 316,600 | 85,245 | 0.70 |
|
||||
| uglify-js@3.0.24 mangle=true, compress=false | 220,216 | 72,730 | 1.13 |
|
||||
| butternut@0.4.6 | 217,568 | 72,738 | 1.41 |
|
||||
| uglify-js@3.0.24 mangle=true, compress=true | 212,511 | 71,560 | 3.36 |
|
||||
| babili@0.1.4 | 210,713 | 72,140 | 12.64 |
|
||||
|
||||
To enable fast minify mode from the CLI use:
|
||||
```
|
||||
uglifyjs file.js -m
|
||||
```
|
||||
To enable fast minify mode with the API use:
|
||||
```js
|
||||
UglifyJS.minify(code, { compress: false, mangle: true });
|
||||
```
|
||||
|
||||
#### Source maps and debugging
|
||||
|
||||
Various `compress` transforms that simplify, rearrange, inline and remove code
|
||||
are known to have an adverse effect on debugging with source maps. This is
|
||||
expected as code is optimized and mappings are often simply not possible as
|
||||
some code no longer exists. For highest fidelity in source map debugging
|
||||
disable the Uglify `compress` option and just use `mangle`.
|
||||
|
||||
### Compiler assumptions
|
||||
|
||||
To allow for better optimizations, the compiler makes various assumptions:
|
||||
|
||||
- `.toString()` and `.valueOf()` don't have side effects, and for built-in
|
||||
objects they have not been overridden.
|
||||
- `undefined`, `NaN` and `Infinity` have not been externally redefined.
|
||||
- `arguments.callee`, `arguments.caller` and `Function.prototype.caller` are not used.
|
||||
- The code doesn't expect the contents of `Function.prototype.toString()` or
|
||||
`Error.prototype.stack` to be anything in particular.
|
||||
- Getting and setting properties on a plain object does not cause other side effects
|
||||
(using `.watch()` or `Proxy`).
|
||||
- Object properties can be added, removed and modified (not prevented with
|
||||
`Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
|
||||
`Object.preventExtensions()` or `Object.seal()`).
|
||||
|
||||
39
appveyor.yml
39
appveyor.yml
@@ -1,24 +1,25 @@
|
||||
environment:
|
||||
UGLIFYJS_TEST_ALL: 1
|
||||
matrix:
|
||||
- nodejs_version: "0.10"
|
||||
- nodejs_version: "0.12"
|
||||
- nodejs_version: "4.0"
|
||||
- nodejs_version: "6.0"
|
||||
|
||||
- NODEJS_VER: node/0.10
|
||||
- NODEJS_VER: node/0.12
|
||||
- NODEJS_VER: node/4
|
||||
- NODEJS_VER: node/6
|
||||
- NODEJS_VER: node/8
|
||||
- NODEJS_VER: node/latest
|
||||
install:
|
||||
- git clone --branch v1.4.2 --depth 1 https://github.com/jasongin/nvs.git %LOCALAPPDATA%\nvs
|
||||
- set PATH=%LOCALAPPDATA%\nvs;%PATH%
|
||||
- nvs --version
|
||||
- nvs add %NODEJS_VER%
|
||||
- nvs use %NODEJS_VER%
|
||||
- node --version
|
||||
- npm --version --no-update-notifier
|
||||
- npm install --no-optional --no-save --no-update-notifier
|
||||
build: off
|
||||
cache:
|
||||
- tmp
|
||||
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
|
||||
- npm test --no-update-notifier
|
||||
|
||||
181
bin/uglifyjs
181
bin/uglifyjs
@@ -3,11 +3,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
// workaround for tty output truncation upon process.exit()
|
||||
[process.stdout, process.stderr].forEach(function(stream){
|
||||
if (stream._handle && stream._handle.setBlocking)
|
||||
stream._handle.setBlocking(true);
|
||||
});
|
||||
require("../tools/exit");
|
||||
|
||||
var fs = require("fs");
|
||||
var info = require("../package.json");
|
||||
@@ -15,30 +11,44 @@ var path = require("path");
|
||||
var program = require("commander");
|
||||
var UglifyJS = require("../tools/node");
|
||||
|
||||
var skip_keys = [ "cname", "enclosed", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
|
||||
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
|
||||
var files = {};
|
||||
var options = {
|
||||
compress: false,
|
||||
mangle: false
|
||||
};
|
||||
program.version(info.name + ' ' + info.version);
|
||||
program.version(info.name + " " + info.version);
|
||||
program.parseArgv = program.parse;
|
||||
program.parse = undefined;
|
||||
program.option("-p, --parse <options>", "Specify parser options.", parse_js("parse", true));
|
||||
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js("compress", true));
|
||||
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js("mangle", true));
|
||||
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js("mangle-props", true));
|
||||
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js("beautify", true));
|
||||
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
|
||||
else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
|
||||
var text = [];
|
||||
var options = UglifyJS.default_options();
|
||||
for (var option in options) {
|
||||
text.push("--" + (option == "output" ? "beautify" : option == "sourceMap" ? "source-map" : option) + " options:");
|
||||
text.push(format_object(options[option]));
|
||||
text.push("");
|
||||
}
|
||||
return text.join("\n");
|
||||
};
|
||||
program.option("-p, --parse <options>", "Specify parser options.", parse_js());
|
||||
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js());
|
||||
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
|
||||
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
|
||||
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
|
||||
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
||||
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
||||
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
||||
program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define"));
|
||||
program.option("-e, --enclose [arg[,...][:value[,...]]]", "Embed everything in a big function, with configurable argument(s) & value(s).");
|
||||
program.option("--ie8", "Support non-standard Internet Explorer 8.");
|
||||
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
|
||||
program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
||||
program.option("--rename", "Force symbol expansion.");
|
||||
program.option("--no-rename", "Disable symbol expansion.");
|
||||
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
||||
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_source_map());
|
||||
program.option("--stats", "Display operations run time on STDERR.")
|
||||
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_js());
|
||||
program.option("--timings", "Display operations run time on STDERR.");
|
||||
program.option("--toplevel", "Compress and/or mangle variables in toplevel scope.");
|
||||
program.option("--verbose", "Print diagnostic messages.");
|
||||
program.option("--warn", "Print warning messages.");
|
||||
@@ -52,6 +62,7 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
||||
}
|
||||
[
|
||||
"compress",
|
||||
"enclose",
|
||||
"ie8",
|
||||
"mangle",
|
||||
"sourceMap",
|
||||
@@ -89,23 +100,14 @@ if (program.mangleProps) {
|
||||
if (typeof program.mangleProps != "object") program.mangleProps = {};
|
||||
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
|
||||
require("../tools/domprops").forEach(function(name) {
|
||||
UglifyJS._push_uniq(program.mangleProps.reserved, name);
|
||||
UglifyJS.push_uniq(program.mangleProps.reserved, name);
|
||||
});
|
||||
}
|
||||
if (typeof options.mangle != "object") options.mangle = {};
|
||||
options.mangle.properties = program.mangleProps;
|
||||
}
|
||||
var cache;
|
||||
if (program.nameCache) {
|
||||
cache = JSON.parse(read_file(program.nameCache, "{}"));
|
||||
if (options.mangle) {
|
||||
if (typeof options.mangle != "object") options.mangle = {};
|
||||
options.mangle.cache = to_cache("vars");
|
||||
if (options.mangle.properties) {
|
||||
if (typeof options.mangle.properties != "object") options.mangle.properties = {};
|
||||
options.mangle.properties.cache = to_cache("props");
|
||||
}
|
||||
}
|
||||
options.nameCache = JSON.parse(read_file(program.nameCache, "{}"));
|
||||
}
|
||||
if (program.output == "ast") {
|
||||
options.output = {
|
||||
@@ -114,12 +116,17 @@ if (program.output == "ast") {
|
||||
};
|
||||
}
|
||||
if (program.parse) {
|
||||
if (program.parse.acorn || program.parse.spidermonkey) {
|
||||
if (program.sourceMap) fatal("ERROR: inline source map only works with built-in parser");
|
||||
} else {
|
||||
if (!program.parse.acorn && !program.parse.spidermonkey) {
|
||||
options.parse = program.parse;
|
||||
} else if (program.sourceMap && program.sourceMap.content == "inline") {
|
||||
fatal("ERROR: inline source map only works with built-in parser");
|
||||
}
|
||||
}
|
||||
if (~program.rawArgs.indexOf("--rename")) {
|
||||
options.rename = true;
|
||||
} else if (!program.rename) {
|
||||
options.rename = false;
|
||||
}
|
||||
var convert_path = function(name) {
|
||||
return name;
|
||||
};
|
||||
@@ -139,7 +146,7 @@ if (program.verbose) {
|
||||
}
|
||||
if (program.self) {
|
||||
if (program.args.length) {
|
||||
console.error("WARN: Ignoring input files since --self was passed");
|
||||
print_error("WARN: Ignoring input files since --self was passed");
|
||||
}
|
||||
if (!options.wrap) options.wrap = "UglifyJS";
|
||||
simple_glob(UglifyJS.FILES).forEach(function(name) {
|
||||
@@ -169,9 +176,14 @@ function convert_ast(fn) {
|
||||
|
||||
function run() {
|
||||
UglifyJS.AST_Node.warn_function = function(msg) {
|
||||
console.error("WARN:", msg);
|
||||
print_error("WARN: " + msg);
|
||||
};
|
||||
if (program.stats) program.stats = Date.now();
|
||||
var content = program.sourceMap && program.sourceMap.content;
|
||||
if (content && content != "inline") {
|
||||
print_error("INFO: Using input source map: " + content);
|
||||
options.sourceMap.content = read_file(content, content);
|
||||
}
|
||||
if (program.timings) options.timings = true;
|
||||
try {
|
||||
if (program.parse) {
|
||||
if (program.parse.acorn) {
|
||||
@@ -198,7 +210,7 @@ function run() {
|
||||
if (result.error) {
|
||||
var ex = result.error;
|
||||
if (ex.name == "SyntaxError") {
|
||||
console.error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
|
||||
print_error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
|
||||
var col = ex.col;
|
||||
var lines = files[ex.filename].split(/\r?\n/);
|
||||
var line = lines[ex.line - 1];
|
||||
@@ -207,21 +219,35 @@ function run() {
|
||||
col = line.length;
|
||||
}
|
||||
if (line) {
|
||||
if (col > 40) {
|
||||
line = line.slice(col - 40);
|
||||
col = 40;
|
||||
var limit = 70;
|
||||
if (col > limit) {
|
||||
line = line.slice(col - limit);
|
||||
col = limit;
|
||||
}
|
||||
console.error(line.slice(0, 80));
|
||||
console.error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
||||
print_error(line.slice(0, 80));
|
||||
print_error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
||||
}
|
||||
}
|
||||
if (ex.defs) {
|
||||
console.error("Supported options:");
|
||||
console.error(ex.defs);
|
||||
print_error("Supported options:");
|
||||
print_error(format_object(ex.defs));
|
||||
}
|
||||
fatal(ex);
|
||||
} else if (program.output == "ast") {
|
||||
console.log(JSON.stringify(result.ast, function(key, value) {
|
||||
if (!options.compress && !options.mangle) {
|
||||
result.ast.figure_out_scope({});
|
||||
}
|
||||
print(JSON.stringify(result.ast, function(key, value) {
|
||||
if (value) switch (key) {
|
||||
case "thedef":
|
||||
return symdef(value);
|
||||
case "enclosed":
|
||||
return value.length ? value.map(symdef) : undefined;
|
||||
case "variables":
|
||||
case "functions":
|
||||
case "globals":
|
||||
return value.size() ? value.map(symdef) : undefined;
|
||||
}
|
||||
if (skip_key(key)) return;
|
||||
if (value instanceof UglifyJS.AST_Token) return;
|
||||
if (value instanceof UglifyJS.Dictionary) return;
|
||||
@@ -237,7 +263,7 @@ function run() {
|
||||
return value;
|
||||
}, 2));
|
||||
} else if (program.output == "spidermonkey") {
|
||||
console.log(JSON.stringify(UglifyJS.minify(result.code, {
|
||||
print(JSON.stringify(UglifyJS.minify(result.code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
@@ -251,19 +277,19 @@ function run() {
|
||||
fs.writeFileSync(program.output + ".map", result.map);
|
||||
}
|
||||
} else {
|
||||
console.log(result.code);
|
||||
print(result.code);
|
||||
}
|
||||
if (program.nameCache) {
|
||||
fs.writeFileSync(program.nameCache, JSON.stringify(cache, function(key, value) {
|
||||
return value instanceof UglifyJS.Dictionary ? value.toObject() : value;
|
||||
}));
|
||||
fs.writeFileSync(program.nameCache, JSON.stringify(options.nameCache));
|
||||
}
|
||||
if (result.timings) for (var phase in result.timings) {
|
||||
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
|
||||
}
|
||||
if (program.stats) console.error("Elapsed:", Date.now() - program.stats);
|
||||
}
|
||||
|
||||
function fatal(message) {
|
||||
if (message instanceof Error) message = message.stack.replace(/^\S*?Error:/, "ERROR:")
|
||||
console.error(message);
|
||||
print_error(message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -307,7 +333,7 @@ function read_file(path, default_value) {
|
||||
}
|
||||
}
|
||||
|
||||
function parse_js(flag, constants) {
|
||||
function parse_js(flag) {
|
||||
return function(value, options) {
|
||||
options = options || {};
|
||||
try {
|
||||
@@ -325,7 +351,7 @@ function parse_js(flag, constants) {
|
||||
if (node instanceof UglifyJS.AST_Assign) {
|
||||
var name = node.left.print_to_string();
|
||||
var value = node.right;
|
||||
if (!constants) {
|
||||
if (flag) {
|
||||
options[name] = value;
|
||||
} else if (value instanceof UglifyJS.AST_Array) {
|
||||
options[name] = value.elements.map(to_string);
|
||||
@@ -348,37 +374,44 @@ function parse_js(flag, constants) {
|
||||
}
|
||||
}));
|
||||
} catch(ex) {
|
||||
if (flag) {
|
||||
fatal("Error parsing arguments for '" + flag + "': " + value);
|
||||
} else {
|
||||
options[value] = null;
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
function parse_source_map() {
|
||||
var parse = parse_js("sourceMap", true);
|
||||
return function(value, options) {
|
||||
var hasContent = options && options.sourceMap && "content" in options.sourceMap;
|
||||
var settings = parse(value, options);
|
||||
if (!hasContent && settings.content && settings.content != "inline") {
|
||||
console.error("INFO: Using input source map:", settings.content);
|
||||
settings.content = read_file(settings.content, settings.content);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
||||
function to_cache(key) {
|
||||
if (cache[key]) {
|
||||
cache[key].props = UglifyJS.Dictionary.fromObject(cache[key].props);
|
||||
} else {
|
||||
cache[key] = {
|
||||
cname: -1,
|
||||
props: new UglifyJS.Dictionary()
|
||||
};
|
||||
}
|
||||
return cache[key];
|
||||
}
|
||||
|
||||
function skip_key(key) {
|
||||
return skip_keys.indexOf(key) >= 0;
|
||||
}
|
||||
|
||||
function symdef(def) {
|
||||
var ret = (1e6 + def.id) + " " + def.name;
|
||||
if (def.mangled_name) ret += " " + def.mangled_name;
|
||||
return ret;
|
||||
}
|
||||
|
||||
function format_object(obj) {
|
||||
var lines = [];
|
||||
var padding = "";
|
||||
Object.keys(obj).map(function(name) {
|
||||
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
|
||||
return [ name, JSON.stringify(obj[name]) ];
|
||||
}).forEach(function(tokens) {
|
||||
lines.push(" " + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
||||
});
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
function print_error(msg) {
|
||||
process.stderr.write(msg);
|
||||
process.stderr.write("\n");
|
||||
}
|
||||
|
||||
function print(txt) {
|
||||
process.stdout.write(txt);
|
||||
process.stdout.write("\n");
|
||||
}
|
||||
|
||||
186
lib/ast.js
186
lib/ast.js
@@ -44,21 +44,21 @@
|
||||
"use strict";
|
||||
|
||||
function DEFNODE(type, props, methods, base) {
|
||||
if (arguments.length < 4) base = AST_Node;
|
||||
if (!props) props = [];
|
||||
else props = props.split(/\s+/);
|
||||
if (typeof base === "undefined") base = AST_Node;
|
||||
props = props ? props.split(/\s+/) : [];
|
||||
var self_props = props;
|
||||
if (base && base.PROPS)
|
||||
props = props.concat(base.PROPS);
|
||||
var code = "return function AST_" + type + "(props){ if (props) { ";
|
||||
for (var i = props.length; --i >= 0;) {
|
||||
code += "this." + props[i] + " = props." + props[i] + ";";
|
||||
}
|
||||
if (base && base.PROPS) props = props.concat(base.PROPS);
|
||||
var code = [
|
||||
"return function AST_", type, "(props){",
|
||||
"if(props){",
|
||||
];
|
||||
props.forEach(function(prop) {
|
||||
code.push("this.", prop, "=props.", prop, ";");
|
||||
});
|
||||
var proto = base && new base;
|
||||
if (proto && proto.initialize || (methods && methods.initialize))
|
||||
code += "this.initialize();";
|
||||
code += "}}";
|
||||
var ctor = new Function(code)();
|
||||
if (proto && proto.initialize || methods && methods.initialize) code.push("this.initialize();");
|
||||
code.push("}}");
|
||||
var ctor = new Function(code.join(""))();
|
||||
if (proto) {
|
||||
ctor.prototype = proto;
|
||||
ctor.BASE = base;
|
||||
@@ -71,11 +71,11 @@ function DEFNODE(type, props, methods, base) {
|
||||
if (type) {
|
||||
ctor.prototype.TYPE = ctor.TYPE = type;
|
||||
}
|
||||
if (methods) for (i in methods) if (HOP(methods, i)) {
|
||||
if (/^\$/.test(i)) {
|
||||
ctor[i.substr(1)] = methods[i];
|
||||
if (methods) for (var name in methods) if (HOP(methods, name)) {
|
||||
if (/^\$/.test(name)) {
|
||||
ctor[name.substr(1)] = methods[name];
|
||||
} else {
|
||||
ctor.prototype[i] = methods[i];
|
||||
ctor.prototype[name] = methods[name];
|
||||
}
|
||||
}
|
||||
ctor.DEFMETHOD = function(name, method) {
|
||||
@@ -85,9 +85,9 @@ function DEFNODE(type, props, methods, base) {
|
||||
exports["AST_" + type] = ctor;
|
||||
}
|
||||
return ctor;
|
||||
};
|
||||
}
|
||||
|
||||
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file raw", {
|
||||
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before comments_after file raw", {
|
||||
}, null);
|
||||
|
||||
var AST_Node = DEFNODE("Node", "start end", {
|
||||
@@ -118,10 +118,8 @@ var AST_Node = DEFNODE("Node", "start end", {
|
||||
}
|
||||
}, null);
|
||||
|
||||
AST_Node.warn_function = null;
|
||||
AST_Node.warn = function(txt, props) {
|
||||
if (AST_Node.warn_function)
|
||||
AST_Node.warn_function(string_template(txt, props));
|
||||
if (AST_Node.warn_function) AST_Node.warn_function(string_template(txt, props));
|
||||
};
|
||||
|
||||
/* -----[ statements ]----- */
|
||||
@@ -134,11 +132,10 @@ var AST_Debugger = DEFNODE("Debugger", null, {
|
||||
$documentation: "Represents a debugger statement",
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_Directive = DEFNODE("Directive", "value scope quote", {
|
||||
var AST_Directive = DEFNODE("Directive", "value 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",
|
||||
quote: "[string] the original quote character"
|
||||
},
|
||||
}, AST_Statement);
|
||||
@@ -159,14 +156,13 @@ function walk_body(node, visitor) {
|
||||
var body = node.body;
|
||||
if (body instanceof AST_Statement) {
|
||||
body._walk(visitor);
|
||||
} else body.forEach(function(node) {
|
||||
node._walk(visitor);
|
||||
});
|
||||
}
|
||||
else for (var i = 0, len = body.length; i < len; i++) {
|
||||
body[i]._walk(visitor);
|
||||
}
|
||||
};
|
||||
|
||||
var AST_Block = DEFNODE("Block", "body", {
|
||||
$documentation: "A body of statements (usually bracketed)",
|
||||
$documentation: "A body of statements (usually braced)",
|
||||
$propdoc: {
|
||||
body: "[AST_Statement*] an array of statements"
|
||||
},
|
||||
@@ -209,8 +205,7 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
|
||||
var label = node.label;
|
||||
var def = this.label;
|
||||
node.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_LoopControl
|
||||
&& node.label && node.label.thedef === def) {
|
||||
if (node instanceof AST_LoopControl && node.label && node.label.thedef === def) {
|
||||
node.label.thedef = label;
|
||||
label.references.push(node);
|
||||
}
|
||||
@@ -268,11 +263,10 @@ var AST_For = DEFNODE("For", "init condition step", {
|
||||
}
|
||||
}, AST_IterationStatement);
|
||||
|
||||
var AST_ForIn = DEFNODE("ForIn", "init name object", {
|
||||
var AST_ForIn = DEFNODE("ForIn", "init object", {
|
||||
$documentation: "A `for ... in` statement",
|
||||
$propdoc: {
|
||||
init: "[AST_Node] the `for/in` initialization code",
|
||||
name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
|
||||
object: "[AST_Node] the object that we're looping through"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
@@ -299,10 +293,9 @@ var AST_With = DEFNODE("With", "expression", {
|
||||
|
||||
/* -----[ scope and functions ]----- */
|
||||
|
||||
var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
|
||||
var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent_scope enclosed cname", {
|
||||
$documentation: "Base class for all statements introducing a lexical scope",
|
||||
$propdoc: {
|
||||
directives: "[string*/S] an array of directives declared in this scope",
|
||||
variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
|
||||
functions: "[Object/S] like `variables`, but only lists function declarations",
|
||||
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
||||
@@ -311,6 +304,16 @@ var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_
|
||||
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
|
||||
cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
|
||||
},
|
||||
clone: function(deep) {
|
||||
var node = this._clone(deep);
|
||||
if (this.variables) node.variables = this.variables.clone();
|
||||
if (this.functions) node.functions = this.functions.clone();
|
||||
if (this.enclosed) node.enclosed = this.enclosed.slice();
|
||||
return node;
|
||||
},
|
||||
pinned: function() {
|
||||
return this.uses_eval || this.uses_with;
|
||||
}
|
||||
}, AST_Block);
|
||||
|
||||
var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
@@ -322,12 +325,29 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
var body = this.body;
|
||||
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
|
||||
wrapped_tl = parse(wrapped_tl);
|
||||
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
|
||||
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function(node) {
|
||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
||||
return MAP.splice(body);
|
||||
}
|
||||
}));
|
||||
return wrapped_tl;
|
||||
},
|
||||
wrap_enclose: function(args_values) {
|
||||
if (typeof args_values != "string") args_values = "";
|
||||
var index = args_values.indexOf(":");
|
||||
if (index < 0) index = args_values.length;
|
||||
var body = this.body;
|
||||
return parse([
|
||||
"(function(",
|
||||
args_values.slice(0, index),
|
||||
'){"$ORIG"})(',
|
||||
args_values.slice(index + 1),
|
||||
")"
|
||||
].join("")).transform(new TreeTransformer(function(node) {
|
||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
||||
return MAP.splice(body);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}, AST_Scope);
|
||||
|
||||
@@ -341,10 +361,9 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
if (this.name) this.name._walk(visitor);
|
||||
var argnames = this.argnames;
|
||||
for (var i = 0, len = argnames.length; i < len; i++) {
|
||||
argnames[i]._walk(visitor);
|
||||
}
|
||||
this.argnames.forEach(function(argname) {
|
||||
argname._walk(visitor);
|
||||
});
|
||||
walk_body(this, visitor);
|
||||
});
|
||||
}
|
||||
@@ -354,11 +373,11 @@ 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, {
|
||||
var AST_Function = DEFNODE("Function", "inlined", {
|
||||
$documentation: "A function expression"
|
||||
}, AST_Lambda);
|
||||
|
||||
var AST_Defun = DEFNODE("Defun", null, {
|
||||
var AST_Defun = DEFNODE("Defun", "inlined", {
|
||||
$documentation: "A function definition"
|
||||
}, AST_Lambda);
|
||||
|
||||
@@ -504,10 +523,9 @@ var AST_Definitions = DEFNODE("Definitions", "definitions", {
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
var definitions = this.definitions;
|
||||
for (var i = 0, len = definitions.length; i < len; i++) {
|
||||
definitions[i]._walk(visitor);
|
||||
}
|
||||
this.definitions.forEach(function(defn) {
|
||||
defn._walk(visitor);
|
||||
});
|
||||
});
|
||||
}
|
||||
}, AST_Statement);
|
||||
@@ -540,11 +558,10 @@ var AST_Call = DEFNODE("Call", "expression args", {
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
var args = this.args;
|
||||
for (var i = 0, len = args.length; i < len; i++) {
|
||||
args[i]._walk(visitor);
|
||||
}
|
||||
this.expression._walk(visitor);
|
||||
this.args.forEach(function(node) {
|
||||
node._walk(visitor);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -659,10 +676,9 @@ var AST_Array = DEFNODE("Array", "elements", {
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
var elements = this.elements;
|
||||
for (var i = 0, len = elements.length; i < len; i++) {
|
||||
elements[i]._walk(visitor);
|
||||
}
|
||||
this.elements.forEach(function(element) {
|
||||
element._walk(visitor);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -674,10 +690,9 @@ var AST_Object = DEFNODE("Object", "properties", {
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
var properties = this.properties;
|
||||
for (var i = 0, len = properties.length; i < len; i++) {
|
||||
properties[i]._walk(visitor);
|
||||
}
|
||||
this.properties.forEach(function(prop) {
|
||||
prop._walk(visitor);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -685,8 +700,8 @@ 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 converted to a string for ObjectKeyVal. For setters and getters this is an AST_SymbolAccessor.",
|
||||
value: "[AST_Node] property value. For setters and getters this is an AST_Accessor."
|
||||
key: "[string|AST_SymbolAccessor] property name. For ObjectKeyVal this is a string. For getters and setters this is an AST_SymbolAccessor.",
|
||||
value: "[AST_Node] property value. For getters and setters this is an AST_Accessor."
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
@@ -816,12 +831,12 @@ var AST_NaN = DEFNODE("NaN", null, {
|
||||
|
||||
var AST_Undefined = DEFNODE("Undefined", null, {
|
||||
$documentation: "The `undefined` value",
|
||||
value: (function(){}())
|
||||
value: function(){}()
|
||||
}, AST_Atom);
|
||||
|
||||
var AST_Hole = DEFNODE("Hole", null, {
|
||||
$documentation: "A hole in an array",
|
||||
value: (function(){}())
|
||||
value: function(){}()
|
||||
}, AST_Atom);
|
||||
|
||||
var AST_Infinity = DEFNODE("Infinity", null, {
|
||||
@@ -849,7 +864,7 @@ function TreeWalker(callback) {
|
||||
this.visit = callback;
|
||||
this.stack = [];
|
||||
this.directives = Object.create(null);
|
||||
};
|
||||
}
|
||||
TreeWalker.prototype = {
|
||||
_visit: function(node, descend) {
|
||||
this.push(node);
|
||||
@@ -859,7 +874,7 @@ TreeWalker.prototype = {
|
||||
if (!ret && descend) {
|
||||
descend.call(node);
|
||||
}
|
||||
this.pop(node);
|
||||
this.pop();
|
||||
return ret;
|
||||
},
|
||||
parent: function(n) {
|
||||
@@ -873,9 +888,8 @@ TreeWalker.prototype = {
|
||||
}
|
||||
this.stack.push(node);
|
||||
},
|
||||
pop: function(node) {
|
||||
this.stack.pop();
|
||||
if (node instanceof AST_Lambda) {
|
||||
pop: function() {
|
||||
if (this.stack.pop() instanceof AST_Lambda) {
|
||||
this.directives = Object.getPrototypeOf(this.directives);
|
||||
}
|
||||
},
|
||||
@@ -901,24 +915,6 @@ TreeWalker.prototype = {
|
||||
}
|
||||
}
|
||||
},
|
||||
in_boolean_context: function() {
|
||||
var stack = this.stack;
|
||||
var i = stack.length, self = stack[--i];
|
||||
while (i > 0) {
|
||||
var p = stack[--i];
|
||||
if ((p instanceof AST_If && p.condition === self) ||
|
||||
(p instanceof AST_Conditional && p.condition === self) ||
|
||||
(p instanceof AST_DWLoop && p.condition === self) ||
|
||||
(p instanceof AST_For && p.condition === self) ||
|
||||
(p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))
|
||||
return false;
|
||||
self = p;
|
||||
}
|
||||
},
|
||||
loopcontrol_target: function(node) {
|
||||
var stack = this.stack;
|
||||
if (node.label) for (var i = stack.length; --i >= 0;) {
|
||||
@@ -931,5 +927,25 @@ TreeWalker.prototype = {
|
||||
|| node instanceof AST_Break && x instanceof AST_Switch)
|
||||
return x;
|
||||
}
|
||||
},
|
||||
in_boolean_context: function() {
|
||||
var self = this.self();
|
||||
for (var i = 0, p; p = this.parent(i); i++) {
|
||||
if (p instanceof AST_SimpleStatement
|
||||
|| p instanceof AST_Conditional && p.condition === self
|
||||
|| p instanceof AST_DWLoop && p.condition === self
|
||||
|| p instanceof AST_For && p.condition === self
|
||||
|| p instanceof AST_If && p.condition === self
|
||||
|| p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
|
||||
return true;
|
||||
}
|
||||
if (p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")
|
||||
|| p instanceof AST_Conditional
|
||||
|| p.tail_node() === self) {
|
||||
self = p;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
4999
lib/compress.js
4999
lib/compress.js
File diff suppressed because it is too large
Load Diff
140
lib/minify.js
140
lib/minify.js
@@ -7,15 +7,23 @@ var to_base64 = typeof btoa == "undefined" ? function(str) {
|
||||
return new Buffer(str).toString("base64");
|
||||
} : btoa;
|
||||
|
||||
function read_source_map(code) {
|
||||
function read_source_map(name, code) {
|
||||
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
|
||||
if (!match) {
|
||||
AST_Node.warn("inline source map not found");
|
||||
AST_Node.warn("inline source map not found: " + name);
|
||||
return null;
|
||||
}
|
||||
return to_ascii(match[2]);
|
||||
}
|
||||
|
||||
function parse_source_map(content) {
|
||||
try {
|
||||
return JSON.parse(content);
|
||||
} catch (ex) {
|
||||
throw new Error("invalid input source map: " + content);
|
||||
}
|
||||
}
|
||||
|
||||
function set_shorthand(name, options, keys) {
|
||||
if (options[name]) {
|
||||
keys.forEach(function(key) {
|
||||
@@ -27,31 +35,54 @@ function set_shorthand(name, options, keys) {
|
||||
}
|
||||
}
|
||||
|
||||
function init_cache(cache) {
|
||||
if (!cache) return;
|
||||
if (!("props" in cache)) {
|
||||
cache.props = new Dictionary();
|
||||
} else if (!(cache.props instanceof Dictionary)) {
|
||||
cache.props = Dictionary.fromObject(cache.props);
|
||||
}
|
||||
}
|
||||
|
||||
function to_json(cache) {
|
||||
return {
|
||||
props: cache.props.toObject()
|
||||
};
|
||||
}
|
||||
|
||||
function minify(files, options) {
|
||||
var warn_function = AST_Node.warn_function;
|
||||
try {
|
||||
if (typeof files == "string") {
|
||||
files = [ files ];
|
||||
}
|
||||
options = defaults(options, {
|
||||
compress: {},
|
||||
enclose: false,
|
||||
ie8: false,
|
||||
keep_fnames: false,
|
||||
mangle: {},
|
||||
nameCache: null,
|
||||
output: {},
|
||||
parse: {},
|
||||
rename: undefined,
|
||||
sourceMap: false,
|
||||
timings: false,
|
||||
toplevel: false,
|
||||
warnings: false,
|
||||
wrap: false,
|
||||
}, true);
|
||||
var timings = options.timings && {
|
||||
start: Date.now()
|
||||
};
|
||||
if (options.rename === undefined) {
|
||||
options.rename = options.compress && options.mangle;
|
||||
}
|
||||
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
|
||||
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("warnings", options, [ "compress" ]);
|
||||
var quoted_props;
|
||||
if (options.mangle) {
|
||||
options.mangle = defaults(options.mangle, {
|
||||
cache: null,
|
||||
cache: options.nameCache && (options.nameCache.vars || {}),
|
||||
eval: false,
|
||||
ie8: false,
|
||||
keep_fnames: false,
|
||||
@@ -59,6 +90,21 @@ function minify(files, options) {
|
||||
reserved: [],
|
||||
toplevel: false,
|
||||
}, true);
|
||||
if (options.mangle.properties) {
|
||||
if (typeof options.mangle.properties != "object") {
|
||||
options.mangle.properties = {};
|
||||
}
|
||||
if (options.mangle.properties.keep_quoted) {
|
||||
quoted_props = options.mangle.properties.reserved;
|
||||
if (!Array.isArray(quoted_props)) quoted_props = [];
|
||||
options.mangle.properties.reserved = quoted_props;
|
||||
}
|
||||
if (options.nameCache && !("cache" in options.mangle.properties)) {
|
||||
options.mangle.properties.cache = options.nameCache.props || {};
|
||||
}
|
||||
}
|
||||
init_cache(options.mangle.cache);
|
||||
init_cache(options.mangle.properties.cache);
|
||||
}
|
||||
if (options.sourceMap) {
|
||||
options.sourceMap = defaults(options.sourceMap, {
|
||||
@@ -75,57 +121,84 @@ function minify(files, options) {
|
||||
warnings.push(warning);
|
||||
};
|
||||
}
|
||||
var toplevel;
|
||||
if (timings) timings.parse = Date.now();
|
||||
var source_maps, toplevel;
|
||||
if (files instanceof AST_Toplevel) {
|
||||
toplevel = files;
|
||||
} else {
|
||||
if (typeof files == "string") {
|
||||
files = [ files ];
|
||||
}
|
||||
options.parse = options.parse || {};
|
||||
options.parse.toplevel = null;
|
||||
for (var name in files) {
|
||||
var source_map_content = options.sourceMap && options.sourceMap.content;
|
||||
if (typeof source_map_content == "string" && source_map_content != "inline") {
|
||||
source_map_content = parse_source_map(source_map_content);
|
||||
}
|
||||
source_maps = source_map_content && Object.create(null);
|
||||
for (var name in files) if (HOP(files, name)) {
|
||||
options.parse.filename = name;
|
||||
options.parse.toplevel = parse(files[name], options.parse);
|
||||
if (options.sourceMap && options.sourceMap.content == "inline") {
|
||||
if (Object.keys(files).length > 1)
|
||||
throw new Error("inline source map only works with singular input");
|
||||
options.sourceMap.content = read_source_map(files[name]);
|
||||
if (source_maps) {
|
||||
if (source_map_content == "inline") {
|
||||
var inlined_content = read_source_map(name, files[name]);
|
||||
if (inlined_content) {
|
||||
source_maps[name] = parse_source_map(inlined_content);
|
||||
}
|
||||
} else {
|
||||
source_maps[name] = source_map_content;
|
||||
}
|
||||
}
|
||||
}
|
||||
toplevel = options.parse.toplevel;
|
||||
}
|
||||
if (quoted_props) {
|
||||
reserve_quoted_keys(toplevel, quoted_props);
|
||||
}
|
||||
if (options.wrap) {
|
||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||
}
|
||||
if (options.compress) {
|
||||
toplevel.figure_out_scope(options.mangle);
|
||||
toplevel = new Compressor(options.compress).compress(toplevel);
|
||||
if (options.enclose) {
|
||||
toplevel = toplevel.wrap_enclose(options.enclose);
|
||||
}
|
||||
if (options.mangle) {
|
||||
if (timings) timings.rename = Date.now();
|
||||
if (options.rename) {
|
||||
toplevel.figure_out_scope(options.mangle);
|
||||
base54.reset();
|
||||
toplevel.expand_names(options.mangle);
|
||||
}
|
||||
if (timings) timings.compress = Date.now();
|
||||
if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
|
||||
if (timings) timings.scope = Date.now();
|
||||
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
||||
if (timings) timings.mangle = Date.now();
|
||||
if (options.mangle) {
|
||||
toplevel.compute_char_frequency(options.mangle);
|
||||
toplevel.mangle_names(options.mangle);
|
||||
if (options.mangle.properties) {
|
||||
}
|
||||
if (timings) timings.properties = Date.now();
|
||||
if (options.mangle && options.mangle.properties) {
|
||||
toplevel = mangle_properties(toplevel, options.mangle.properties);
|
||||
}
|
||||
}
|
||||
if (timings) timings.output = Date.now();
|
||||
var result = {};
|
||||
if (options.output.ast) {
|
||||
result.ast = toplevel;
|
||||
}
|
||||
if (!HOP(options.output, "code") || options.output.code) {
|
||||
if (options.sourceMap) {
|
||||
if (typeof options.sourceMap.content == "string") {
|
||||
options.sourceMap.content = JSON.parse(options.sourceMap.content);
|
||||
}
|
||||
options.output.source_map = SourceMap({
|
||||
file: options.sourceMap.filename,
|
||||
orig: options.sourceMap.content,
|
||||
orig: source_maps,
|
||||
root: options.sourceMap.root
|
||||
});
|
||||
if (options.sourceMap.includeSources) {
|
||||
for (var name in files) {
|
||||
if (files instanceof AST_Toplevel) {
|
||||
throw new Error("original source content unavailable");
|
||||
} else for (var name in files) if (HOP(files, name)) {
|
||||
options.output.source_map.get().setSourceContent(name, files[name]);
|
||||
}
|
||||
} else {
|
||||
options.output.source_map.get()._sourcesContents = null;
|
||||
}
|
||||
}
|
||||
delete options.output.ast;
|
||||
@@ -142,6 +215,25 @@ function minify(files, options) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.nameCache && options.mangle) {
|
||||
if (options.mangle.cache) options.nameCache.vars = to_json(options.mangle.cache);
|
||||
if (options.mangle.properties && options.mangle.properties.cache) {
|
||||
options.nameCache.props = to_json(options.mangle.properties.cache);
|
||||
}
|
||||
}
|
||||
if (timings) {
|
||||
timings.end = Date.now();
|
||||
result.timings = {
|
||||
parse: 1e-3 * (timings.rename - timings.parse),
|
||||
rename: 1e-3 * (timings.compress - timings.rename),
|
||||
compress: 1e-3 * (timings.scope - timings.compress),
|
||||
scope: 1e-3 * (timings.mangle - timings.scope),
|
||||
mangle: 1e-3 * (timings.properties - timings.mangle),
|
||||
properties: 1e-3 * (timings.output - timings.properties),
|
||||
output: 1e-3 * (timings.end - timings.output),
|
||||
total: 1e-3 * (timings.end - timings.start)
|
||||
}
|
||||
}
|
||||
if (warnings.length) {
|
||||
result.warnings = warnings;
|
||||
}
|
||||
|
||||
@@ -44,10 +44,8 @@
|
||||
"use strict";
|
||||
|
||||
(function() {
|
||||
|
||||
var normalize_directives = function(body) {
|
||||
function normalize_directives(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({
|
||||
@@ -59,9 +57,8 @@
|
||||
in_directive = false;
|
||||
}
|
||||
}
|
||||
|
||||
return body;
|
||||
};
|
||||
}
|
||||
|
||||
var MOZ_TO_ME = {
|
||||
Program: function(M) {
|
||||
@@ -180,6 +177,17 @@
|
||||
end : my_end_token(M)
|
||||
};
|
||||
if (val === null) return new AST_Null(args);
|
||||
var rx = M.regex;
|
||||
if (rx && rx.pattern) {
|
||||
// RegExpLiteral as per ESTree AST spec
|
||||
args.value = new RegExp(rx.pattern, rx.flags);
|
||||
args.value.raw_source = rx.pattern;
|
||||
return new AST_RegExp(args);
|
||||
} else if (rx) {
|
||||
// support legacy RegExp
|
||||
args.value = M.regex && M.raw ? M.raw : val;
|
||||
return new AST_RegExp(args);
|
||||
}
|
||||
switch (typeof val) {
|
||||
case "string":
|
||||
args.value = val;
|
||||
@@ -189,16 +197,6 @@
|
||||
return new AST_Number(args);
|
||||
case "boolean":
|
||||
return new (val ? AST_True : AST_False)(args);
|
||||
default:
|
||||
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);
|
||||
}
|
||||
},
|
||||
Identifier: function(M) {
|
||||
@@ -410,14 +408,15 @@
|
||||
});
|
||||
|
||||
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
|
||||
var value = M.value;
|
||||
var flags = M.value.toString().match(/[gimuy]*$/)[0];
|
||||
var value = "/" + M.value.raw_source + "/" + flags;
|
||||
return {
|
||||
type: "Literal",
|
||||
value: value,
|
||||
raw: value.toString(),
|
||||
raw: value,
|
||||
regex: {
|
||||
pattern: value.source,
|
||||
flags: value.toString().match(/[gimuy]*$/)[0]
|
||||
pattern: M.value.raw_source,
|
||||
flags: flags
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -478,7 +477,7 @@
|
||||
endpos : range ? range[0] : moznode.start,
|
||||
raw : raw_token(moznode),
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function my_end_token(moznode) {
|
||||
var loc = moznode.loc, end = loc && loc.end;
|
||||
@@ -493,7 +492,7 @@
|
||||
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";
|
||||
@@ -548,7 +547,7 @@
|
||||
);
|
||||
MOZ_TO_ME[moztype] = moz_to_me;
|
||||
def_to_moz(mytype, me_to_moz);
|
||||
};
|
||||
}
|
||||
|
||||
var FROM_MOZ_STACK = null;
|
||||
|
||||
@@ -557,13 +556,28 @@
|
||||
var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
|
||||
FROM_MOZ_STACK.pop();
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
AST_Node.from_mozilla_ast = function(node) {
|
||||
var save_stack = FROM_MOZ_STACK;
|
||||
FROM_MOZ_STACK = [];
|
||||
var ast = from_moz(node);
|
||||
FROM_MOZ_STACK = save_stack;
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_LabelRef) {
|
||||
for (var level = 0, parent; parent = this.parent(level); level++) {
|
||||
if (parent instanceof AST_Scope) break;
|
||||
if (parent instanceof AST_LabeledStatement && parent.label.name == node.name) {
|
||||
node.thedef = parent.label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!node.thedef) {
|
||||
var s = node.start;
|
||||
js_error("Undefined label " + node.name, s.file, s.line, s.col, s.pos);
|
||||
}
|
||||
}
|
||||
}));
|
||||
return ast;
|
||||
};
|
||||
|
||||
@@ -583,24 +597,24 @@
|
||||
}
|
||||
}
|
||||
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)
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function to_moz_scope(type, node) {
|
||||
var body = node.body.map(to_moz);
|
||||
@@ -611,5 +625,5 @@
|
||||
type: type,
|
||||
body: body
|
||||
};
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
705
lib/output.js
705
lib/output.js
File diff suppressed because it is too large
Load Diff
353
lib/parse.js
353
lib/parse.js
@@ -115,8 +115,6 @@ var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,;:"));
|
||||
|
||||
var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
|
||||
|
||||
var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
|
||||
|
||||
/* -----[ Tokenizer ]----- */
|
||||
|
||||
// regexps adapted from http://xregexp.com/plugins/#unicode
|
||||
@@ -132,15 +130,27 @@ function is_letter(code) {
|
||||
return (code >= 97 && code <= 122)
|
||||
|| (code >= 65 && code <= 90)
|
||||
|| (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code)));
|
||||
};
|
||||
}
|
||||
|
||||
function is_surrogate_pair_head(code) {
|
||||
if (typeof code == "string")
|
||||
code = code.charCodeAt(0);
|
||||
return code >= 0xd800 && code <= 0xdbff;
|
||||
}
|
||||
|
||||
function is_surrogate_pair_tail(code) {
|
||||
if (typeof code == "string")
|
||||
code = code.charCodeAt(0);
|
||||
return code >= 0xdc00 && code <= 0xdfff;
|
||||
}
|
||||
|
||||
function is_digit(code) {
|
||||
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));
|
||||
@@ -148,19 +158,19 @@ function is_unicode_digit(code) {
|
||||
|
||||
function is_unicode_combining_mark(ch) {
|
||||
return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
|
||||
};
|
||||
}
|
||||
|
||||
function is_unicode_connector_punctuation(ch) {
|
||||
return UNICODE.connector_punctuation.test(ch);
|
||||
};
|
||||
}
|
||||
|
||||
function is_identifier(name) {
|
||||
return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name);
|
||||
};
|
||||
return !RESERVED_WORDS[name] && /^[a-z_$][a-z0-9_$]*$/i.test(name);
|
||||
}
|
||||
|
||||
function is_identifier_start(code) {
|
||||
return code == 36 || code == 95 || is_letter(code);
|
||||
};
|
||||
}
|
||||
|
||||
function is_identifier_char(ch) {
|
||||
var code = ch.charCodeAt(0);
|
||||
@@ -172,11 +182,11 @@ function is_identifier_char(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)) {
|
||||
@@ -187,7 +197,7 @@ function parse_js_number(num) {
|
||||
var val = parseFloat(num);
|
||||
if (val == num) return val;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function JS_Parse_Error(message, filename, line, col, pos) {
|
||||
this.message = message;
|
||||
@@ -195,7 +205,7 @@ function JS_Parse_Error(message, filename, line, col, pos) {
|
||||
this.line = line;
|
||||
this.col = col;
|
||||
this.pos = pos;
|
||||
};
|
||||
}
|
||||
JS_Parse_Error.prototype = Object.create(Error.prototype);
|
||||
JS_Parse_Error.prototype.constructor = JS_Parse_Error;
|
||||
JS_Parse_Error.prototype.name = "SyntaxError";
|
||||
@@ -203,11 +213,11 @@ configure_error_stack(JS_Parse_Error);
|
||||
|
||||
function js_error(message, filename, line, col, pos) {
|
||||
throw new JS_Parse_Error(message, filename, line, col, pos);
|
||||
};
|
||||
}
|
||||
|
||||
function is_token(token, type, val) {
|
||||
return token.type == type && (val == null || token.value == val);
|
||||
};
|
||||
}
|
||||
|
||||
var EX_EOF = {};
|
||||
|
||||
@@ -229,13 +239,15 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
directive_stack : []
|
||||
};
|
||||
|
||||
function peek() { return S.text.charAt(S.pos); };
|
||||
function peek() {
|
||||
return S.text.charAt(S.pos);
|
||||
}
|
||||
|
||||
function next(signal_eof, in_string) {
|
||||
var ch = S.text.charAt(S.pos++);
|
||||
if (signal_eof && !ch)
|
||||
throw EX_EOF;
|
||||
if (NEWLINE_CHARS(ch)) {
|
||||
if (NEWLINE_CHARS[ch]) {
|
||||
S.newline_before = S.newline_before || !in_string;
|
||||
++S.line;
|
||||
S.col = 0;
|
||||
@@ -248,43 +260,43 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
++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))
|
||||
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;
|
||||
return pos;
|
||||
};
|
||||
}
|
||||
|
||||
function start_token() {
|
||||
S.tokline = S.line;
|
||||
S.tokcol = S.col;
|
||||
S.tokpos = S.pos;
|
||||
};
|
||||
}
|
||||
|
||||
var prev_was_dot = false;
|
||||
function token(type, value, is_comment) {
|
||||
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX(value)) ||
|
||||
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) ||
|
||||
(type == "punc" && PUNC_BEFORE_EXPRESSION(value)));
|
||||
S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) ||
|
||||
(type == "keyword" && KEYWORDS_BEFORE_EXPRESSION[value]) ||
|
||||
(type == "punc" && PUNC_BEFORE_EXPRESSION[value]));
|
||||
if (type == "punc" && value == ".") {
|
||||
prev_was_dot = true;
|
||||
} else if (!is_comment) {
|
||||
@@ -307,31 +319,27 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
}
|
||||
if (!is_comment) {
|
||||
ret.comments_before = S.comments_before;
|
||||
S.comments_before = [];
|
||||
// make note of any newlines in the comments that came before
|
||||
for (var i = 0, len = ret.comments_before.length; i < len; i++) {
|
||||
ret.nlb = ret.nlb || ret.comments_before[i].nlb;
|
||||
}
|
||||
ret.comments_after = S.comments_before = [];
|
||||
}
|
||||
S.newline_before = false;
|
||||
return new AST_Token(ret);
|
||||
};
|
||||
}
|
||||
|
||||
function skip_whitespace() {
|
||||
while (WHITESPACE_CHARS(peek()))
|
||||
while (WHITESPACE_CHARS[peek()])
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
function read_while(pred) {
|
||||
var ret = "", ch, i = 0;
|
||||
while ((ch = peek()) && pred(ch, i++))
|
||||
ret += next();
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
function parse_error(err) {
|
||||
js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
|
||||
};
|
||||
}
|
||||
|
||||
function read_num(prefix) {
|
||||
var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
|
||||
@@ -361,7 +369,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
} else {
|
||||
parse_error("Invalid syntax: " + num);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function read_escaped_char(in_string) {
|
||||
var ch = next(true, in_string);
|
||||
@@ -384,7 +392,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
if (ch >= "0" && ch <= "7")
|
||||
return read_octal_escape_sequence(ch);
|
||||
return ch;
|
||||
};
|
||||
}
|
||||
|
||||
function read_octal_escape_sequence(ch) {
|
||||
// Read
|
||||
@@ -411,14 +419,14 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
num = (num << 4) | digit;
|
||||
}
|
||||
return num;
|
||||
};
|
||||
}
|
||||
|
||||
var read_string = with_eof_error("Unterminated string constant", function(quote_char) {
|
||||
var quote = next(), ret = "";
|
||||
for (;;) {
|
||||
var ch = next(true, true);
|
||||
if (ch == "\\") ch = read_escaped_char(true);
|
||||
else if (NEWLINE_CHARS(ch)) parse_error("Unterminated string constant");
|
||||
else if (NEWLINE_CHARS[ch]) parse_error("Unterminated string constant");
|
||||
else if (ch == quote) break;
|
||||
ret += ch;
|
||||
}
|
||||
@@ -441,7 +449,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
S.comments_before.push(token(type, ret, true));
|
||||
S.regex_allowed = regex_allowed;
|
||||
return next_token;
|
||||
};
|
||||
}
|
||||
|
||||
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
|
||||
var regex_allowed = S.regex_allowed;
|
||||
@@ -470,16 +478,16 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
backslash = false;
|
||||
}
|
||||
}
|
||||
if (KEYWORDS(name) && escaped) {
|
||||
if (KEYWORDS[name] && escaped) {
|
||||
hex = name.charCodeAt(0).toString(16).toUpperCase();
|
||||
name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
|
||||
}
|
||||
return name;
|
||||
};
|
||||
}
|
||||
|
||||
var read_regexp = with_eof_error("Unterminated regular expression", function(source) {
|
||||
var prev_backslash = false, ch, in_class = false;
|
||||
while ((ch = next(true))) if (NEWLINE_CHARS(ch)) {
|
||||
while ((ch = next(true))) if (NEWLINE_CHARS[ch]) {
|
||||
parse_error("Unexpected line terminator");
|
||||
} else if (prev_backslash) {
|
||||
source += "\\" + ch;
|
||||
@@ -511,15 +519,15 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
function grow(op) {
|
||||
if (!peek()) return op;
|
||||
var bigger = op + peek();
|
||||
if (OPERATORS(bigger)) {
|
||||
if (OPERATORS[bigger]) {
|
||||
next();
|
||||
return grow(bigger);
|
||||
} else {
|
||||
return op;
|
||||
}
|
||||
};
|
||||
}
|
||||
return token("operator", grow(prefix || next()));
|
||||
};
|
||||
}
|
||||
|
||||
function handle_slash() {
|
||||
next();
|
||||
@@ -532,23 +540,23 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
return skip_multiline_comment();
|
||||
}
|
||||
return S.regex_allowed ? read_regexp("") : read_operator("/");
|
||||
};
|
||||
}
|
||||
|
||||
function handle_dot() {
|
||||
next();
|
||||
return is_digit(peek().charCodeAt(0))
|
||||
? read_num(".")
|
||||
: token("punc", ".");
|
||||
};
|
||||
}
|
||||
|
||||
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)
|
||||
return KEYWORDS_ATOM[word] ? token("atom", word)
|
||||
: !KEYWORDS[word] ? token("name", word)
|
||||
: OPERATORS[word] ? token("operator", word)
|
||||
: token("keyword", word);
|
||||
};
|
||||
}
|
||||
|
||||
function with_eof_error(eof_error, cont) {
|
||||
return function(x) {
|
||||
@@ -559,7 +567,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
else throw ex;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function next_token(force_regexp) {
|
||||
if (force_regexp != null)
|
||||
@@ -597,13 +605,13 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
}
|
||||
}
|
||||
if (is_digit(code)) return read_num();
|
||||
if (PUNC_CHARS(ch)) return token("punc", next());
|
||||
if (OPERATOR_CHARS(ch)) return read_operator();
|
||||
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();
|
||||
break;
|
||||
}
|
||||
parse_error("Unexpected character '" + ch + "'");
|
||||
};
|
||||
}
|
||||
|
||||
next_token.context = function(nc) {
|
||||
if (nc) S = nc;
|
||||
@@ -639,8 +647,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
}
|
||||
|
||||
return next_token;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/* -----[ Parser (constants) ]----- */
|
||||
|
||||
@@ -660,7 +667,7 @@ var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
|
||||
|
||||
var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
|
||||
|
||||
var PRECEDENCE = (function(a, ret){
|
||||
var PRECEDENCE = function(a, ret) {
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
var b = a[i];
|
||||
for (var j = 0; j < b.length; ++j) {
|
||||
@@ -668,8 +675,7 @@ var PRECEDENCE = (function(a, ret){
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
})(
|
||||
[
|
||||
}([
|
||||
["||"],
|
||||
["&&"],
|
||||
["|"],
|
||||
@@ -680,18 +686,13 @@ var PRECEDENCE = (function(a, ret){
|
||||
[">>", "<<", ">>>"],
|
||||
["+", "-"],
|
||||
["*", "/", "%"]
|
||||
],
|
||||
{}
|
||||
);
|
||||
], {});
|
||||
|
||||
var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
|
||||
|
||||
var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
|
||||
var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "string", "regexp", "name" ]);
|
||||
|
||||
/* -----[ Parser ]----- */
|
||||
|
||||
function parse($TEXT, options) {
|
||||
|
||||
options = defaults(options, {
|
||||
bare_returns : false,
|
||||
expression : false,
|
||||
@@ -700,7 +701,7 @@ function parse($TEXT, options) {
|
||||
shebang : true,
|
||||
strict : false,
|
||||
toplevel : null,
|
||||
});
|
||||
}, true);
|
||||
|
||||
var S = {
|
||||
input : (typeof $TEXT == "string"
|
||||
@@ -720,9 +721,11 @@ function parse($TEXT, options) {
|
||||
|
||||
function is(type, value) {
|
||||
return is_token(S.token, type, value);
|
||||
};
|
||||
}
|
||||
|
||||
function peek() { return S.peeked || (S.peeked = S.input()); };
|
||||
function peek() {
|
||||
return S.peeked || (S.peeked = S.input());
|
||||
}
|
||||
|
||||
function next() {
|
||||
S.prev = S.token;
|
||||
@@ -736,11 +739,11 @@ function parse($TEXT, options) {
|
||||
S.token.type == "string" || is("punc", ";")
|
||||
);
|
||||
return S.token;
|
||||
};
|
||||
}
|
||||
|
||||
function prev() {
|
||||
return S.prev;
|
||||
};
|
||||
}
|
||||
|
||||
function croak(msg, line, col, pos) {
|
||||
var ctx = S.input.context();
|
||||
@@ -749,74 +752,81 @@ function parse($TEXT, options) {
|
||||
line != null ? line : ctx.tokline,
|
||||
col != null ? col : ctx.tokcol,
|
||||
pos != null ? pos : ctx.tokpos);
|
||||
};
|
||||
}
|
||||
|
||||
function token_error(token, msg) {
|
||||
croak(msg, token.line, token.col);
|
||||
};
|
||||
}
|
||||
|
||||
function unexpected(token) {
|
||||
if (token == null)
|
||||
token = S.token;
|
||||
token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
|
||||
};
|
||||
}
|
||||
|
||||
function expect_token(type, val) {
|
||||
if (is(type, val)) {
|
||||
return next();
|
||||
}
|
||||
token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
|
||||
};
|
||||
}
|
||||
|
||||
function expect(punc) { return expect_token("punc", punc); };
|
||||
function expect(punc) {
|
||||
return expect_token("punc", punc);
|
||||
}
|
||||
|
||||
function has_newline_before(token) {
|
||||
return token.nlb || !all(token.comments_before, function(comment) {
|
||||
return !comment.nlb;
|
||||
});
|
||||
}
|
||||
|
||||
function can_insert_semicolon() {
|
||||
return !options.strict && (
|
||||
S.token.nlb || is("eof") || is("punc", "}")
|
||||
);
|
||||
};
|
||||
return !options.strict
|
||||
&& (is("eof") || is("punc", "}") || has_newline_before(S.token));
|
||||
}
|
||||
|
||||
function semicolon(optional) {
|
||||
if (is("punc", ";")) next();
|
||||
else if (!optional && !can_insert_semicolon()) unexpected();
|
||||
};
|
||||
}
|
||||
|
||||
function parenthesised() {
|
||||
expect("(");
|
||||
var exp = expression(true);
|
||||
expect(")");
|
||||
return exp;
|
||||
};
|
||||
}
|
||||
|
||||
function embed_tokens(parser) {
|
||||
return function() {
|
||||
var start = S.token;
|
||||
var expr = parser();
|
||||
var expr = parser.apply(null, arguments);
|
||||
var end = prev();
|
||||
expr.start = start;
|
||||
expr.end = end;
|
||||
return expr;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
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 statement = embed_tokens(function(strict_defun) {
|
||||
handle_regexp();
|
||||
switch (S.token.type) {
|
||||
case "string":
|
||||
if (S.in_directives) {
|
||||
var token = peek();
|
||||
if (S.token.raw.indexOf("\\") == -1
|
||||
&& (token.nlb
|
||||
|| is_token(token, "eof")
|
||||
|| is_token(token, "punc", ";")
|
||||
|| is_token(token, "punc", "}"))) {
|
||||
&& (is_token(token, "punc", ";")
|
||||
|| is_token(token, "punc", "}")
|
||||
|| has_newline_before(token)
|
||||
|| is_token(token, "eof"))) {
|
||||
S.input.add_directive(S.token.value);
|
||||
} else {
|
||||
S.in_directives = false;
|
||||
@@ -892,6 +902,9 @@ function parse($TEXT, options) {
|
||||
return for_();
|
||||
|
||||
case "function":
|
||||
if (!strict_defun && S.input.has_directive("use strict")) {
|
||||
croak("In strict mode code, functions can only be declared at top level or immediately within another function.");
|
||||
}
|
||||
next();
|
||||
return function_(AST_Defun);
|
||||
|
||||
@@ -923,7 +936,7 @@ function parse($TEXT, options) {
|
||||
|
||||
case "throw":
|
||||
next();
|
||||
if (S.token.nlb)
|
||||
if (has_newline_before(S.token))
|
||||
croak("Illegal newline after 'throw'");
|
||||
var value = expression(true);
|
||||
semicolon();
|
||||
@@ -957,7 +970,9 @@ function parse($TEXT, options) {
|
||||
|
||||
function labeled_statement() {
|
||||
var label = as_symbol(AST_Label);
|
||||
if (find_if(function(l){ return l.name == label.name }, S.labels)) {
|
||||
if (!all(S.labels, function(l) {
|
||||
return l.name != label.name;
|
||||
})) {
|
||||
// ECMA-262, 12.12: An ECMAScript program is considered
|
||||
// syntactically incorrect if it contains a
|
||||
// LabelledStatement that is enclosed by a
|
||||
@@ -981,11 +996,11 @@ function parse($TEXT, options) {
|
||||
});
|
||||
}
|
||||
return new AST_LabeledStatement({ body: stat, label: label });
|
||||
};
|
||||
}
|
||||
|
||||
function simple_statement(tmp) {
|
||||
return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) });
|
||||
};
|
||||
}
|
||||
|
||||
function break_cont(type) {
|
||||
var label = null, ldef;
|
||||
@@ -993,18 +1008,17 @@ function parse($TEXT, options) {
|
||||
label = as_symbol(AST_LabelRef, true);
|
||||
}
|
||||
if (label != null) {
|
||||
ldef = find_if(function(l){ return l.name == label.name }, S.labels);
|
||||
if (!ldef)
|
||||
croak("Undefined label " + label.name);
|
||||
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");
|
||||
} else if (S.in_loop == 0) croak(type.TYPE + " not inside a loop or switch");
|
||||
semicolon();
|
||||
var stat = new type({ label: label });
|
||||
if (ldef) ldef.references.push(stat);
|
||||
return stat;
|
||||
};
|
||||
}
|
||||
|
||||
function for_() {
|
||||
expect("(");
|
||||
@@ -1014,14 +1028,18 @@ function parse($TEXT, options) {
|
||||
? (next(), var_(true))
|
||||
: expression(true, true);
|
||||
if (is("operator", "in")) {
|
||||
if (init instanceof AST_Var && init.definitions.length > 1)
|
||||
croak("Only one variable declaration allowed in for..in loop");
|
||||
if (init instanceof AST_Var) {
|
||||
if (init.definitions.length > 1)
|
||||
croak("Only one variable declaration allowed in for..in loop", init.start.line, init.start.col, init.start.pos);
|
||||
} else if (!is_assignable(init)) {
|
||||
croak("Invalid left-hand side in for..in loop", init.start.line, init.start.col, init.start.pos);
|
||||
}
|
||||
next();
|
||||
return for_in(init);
|
||||
}
|
||||
}
|
||||
return regular_for(init);
|
||||
};
|
||||
}
|
||||
|
||||
function regular_for(init) {
|
||||
expect(";");
|
||||
@@ -1035,25 +1053,25 @@ function parse($TEXT, options) {
|
||||
step : step,
|
||||
body : in_loop(statement)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function for_in(init) {
|
||||
var lhs = init instanceof AST_Var ? init.definitions[0].name : null;
|
||||
var obj = expression(true);
|
||||
expect(")");
|
||||
return new AST_ForIn({
|
||||
init : init,
|
||||
name : lhs,
|
||||
object : obj,
|
||||
body : in_loop(statement)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
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();
|
||||
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
|
||||
unexpected(prev());
|
||||
expect("(");
|
||||
var argnames = [];
|
||||
for (var first = true; !is("punc", ")");) {
|
||||
@@ -1068,7 +1086,7 @@ function parse($TEXT, options) {
|
||||
S.input.push_directives_stack();
|
||||
S.in_loop = 0;
|
||||
S.labels = [];
|
||||
var body = block_();
|
||||
var body = block_(true);
|
||||
if (S.input.has_directive("use strict")) {
|
||||
if (name) strict_verify_symbol(name);
|
||||
argnames.forEach(strict_verify_symbol);
|
||||
@@ -1095,18 +1113,18 @@ function parse($TEXT, options) {
|
||||
body : body,
|
||||
alternative : belse
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function block_() {
|
||||
function block_(strict_defun) {
|
||||
expect("{");
|
||||
var a = [];
|
||||
while (!is("punc", "}")) {
|
||||
if (is("eof")) unexpected();
|
||||
a.push(statement());
|
||||
a.push(statement(strict_defun));
|
||||
}
|
||||
next();
|
||||
return a;
|
||||
};
|
||||
}
|
||||
|
||||
function switch_body_() {
|
||||
expect("{");
|
||||
@@ -1141,7 +1159,7 @@ function parse($TEXT, options) {
|
||||
if (branch) branch.end = prev();
|
||||
next();
|
||||
return a;
|
||||
};
|
||||
}
|
||||
|
||||
function try_() {
|
||||
var body = block_(), bcatch = null, bfinally = null;
|
||||
@@ -1174,7 +1192,7 @@ function parse($TEXT, options) {
|
||||
bcatch : bcatch,
|
||||
bfinally : bfinally
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function vardefs(no_in) {
|
||||
var a = [];
|
||||
@@ -1190,7 +1208,7 @@ function parse($TEXT, options) {
|
||||
next();
|
||||
}
|
||||
return a;
|
||||
};
|
||||
}
|
||||
|
||||
var var_ = function(no_in) {
|
||||
return new AST_Var({
|
||||
@@ -1210,19 +1228,20 @@ function parse($TEXT, options) {
|
||||
} else {
|
||||
args = [];
|
||||
}
|
||||
return subscripts(new AST_New({
|
||||
var call = new AST_New({
|
||||
start : start,
|
||||
expression : newexp,
|
||||
args : args,
|
||||
end : prev()
|
||||
}), allow_calls);
|
||||
});
|
||||
mark_pure(call);
|
||||
return subscripts(call, allow_calls);
|
||||
};
|
||||
|
||||
function as_atom_node() {
|
||||
var tok = S.token, ret;
|
||||
switch (tok.type) {
|
||||
case "name":
|
||||
case "keyword":
|
||||
ret = _make_symbol(AST_SymbolRef);
|
||||
break;
|
||||
case "num":
|
||||
@@ -1252,17 +1271,10 @@ 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;
|
||||
};
|
||||
}
|
||||
|
||||
var expr_atom = function(allow_calls) {
|
||||
if (is("operator", "new")) {
|
||||
@@ -1274,9 +1286,26 @@ function parse($TEXT, options) {
|
||||
case "(":
|
||||
next();
|
||||
var ex = expression(true);
|
||||
var len = start.comments_before.length;
|
||||
[].unshift.apply(ex.start.comments_before, start.comments_before);
|
||||
start.comments_before = ex.start.comments_before;
|
||||
start.comments_before_length = len;
|
||||
if (len == 0 && start.comments_before.length > 0) {
|
||||
var comment = start.comments_before[0];
|
||||
if (!comment.nlb) {
|
||||
comment.nlb = start.nlb;
|
||||
start.nlb = false;
|
||||
}
|
||||
}
|
||||
start.comments_after = ex.start.comments_after;
|
||||
ex.start = start;
|
||||
ex.end = S.token;
|
||||
expect(")");
|
||||
var end = prev();
|
||||
end.comments_before = ex.end.comments_before;
|
||||
[].push.apply(ex.end.comments_after, end.comments_after);
|
||||
end.comments_after = ex.end.comments_after;
|
||||
ex.end = end;
|
||||
if (ex instanceof AST_Call) mark_pure(ex);
|
||||
return subscripts(ex, allow_calls);
|
||||
case "[":
|
||||
return subscripts(array_(), allow_calls);
|
||||
@@ -1311,7 +1340,7 @@ function parse($TEXT, options) {
|
||||
}
|
||||
next();
|
||||
return a;
|
||||
};
|
||||
}
|
||||
|
||||
var array_ = embed_tokens(function() {
|
||||
expect("[");
|
||||
@@ -1338,7 +1367,7 @@ function parse($TEXT, options) {
|
||||
if (type == "name" && !is("punc", ":")) {
|
||||
var key = new AST_SymbolAccessor({
|
||||
start: S.token,
|
||||
name: as_property_name(),
|
||||
name: "" + as_property_name(),
|
||||
end: prev()
|
||||
});
|
||||
if (name == "get") {
|
||||
@@ -1364,7 +1393,7 @@ function parse($TEXT, options) {
|
||||
a.push(new AST_ObjectKeyVal({
|
||||
start : start,
|
||||
quote : start.quote,
|
||||
key : name,
|
||||
key : "" + name,
|
||||
value : expression(false),
|
||||
end : prev()
|
||||
}));
|
||||
@@ -1377,7 +1406,7 @@ function parse($TEXT, options) {
|
||||
var tmp = S.token;
|
||||
switch (tmp.type) {
|
||||
case "operator":
|
||||
if (!KEYWORDS(tmp.value)) unexpected();
|
||||
if (!KEYWORDS[tmp.value]) unexpected();
|
||||
case "num":
|
||||
case "string":
|
||||
case "name":
|
||||
@@ -1388,14 +1417,14 @@ function parse($TEXT, options) {
|
||||
default:
|
||||
unexpected();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function as_name() {
|
||||
var tmp = S.token;
|
||||
if (tmp.type != "name") unexpected();
|
||||
next();
|
||||
return tmp.value;
|
||||
};
|
||||
}
|
||||
|
||||
function _make_symbol(type) {
|
||||
var name = S.token.value;
|
||||
@@ -1404,7 +1433,7 @@ function parse($TEXT, options) {
|
||||
start : S.token,
|
||||
end : S.token
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function strict_verify_symbol(sym) {
|
||||
if (sym.name == "arguments" || sym.name == "eval")
|
||||
@@ -1422,7 +1451,20 @@ function parse($TEXT, options) {
|
||||
}
|
||||
next();
|
||||
return sym;
|
||||
};
|
||||
}
|
||||
|
||||
function mark_pure(call) {
|
||||
var start = call.start;
|
||||
var comments = start.comments_before;
|
||||
var i = HOP(start, "comments_before_length") ? start.comments_before_length : comments.length;
|
||||
while (--i >= 0) {
|
||||
var comment = comments[i];
|
||||
if (/[@#]__PURE__/.test(comment.value)) {
|
||||
call.pure = comment;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var subscripts = function(expr, allow_calls) {
|
||||
var start = expr.start;
|
||||
@@ -1448,19 +1490,21 @@ function parse($TEXT, options) {
|
||||
}
|
||||
if (allow_calls && is("punc", "(")) {
|
||||
next();
|
||||
return subscripts(new AST_Call({
|
||||
var call = new AST_Call({
|
||||
start : start,
|
||||
expression : expr,
|
||||
args : expr_list(")"),
|
||||
end : prev()
|
||||
}), true);
|
||||
});
|
||||
mark_pure(call);
|
||||
return subscripts(call, true);
|
||||
}
|
||||
return expr;
|
||||
};
|
||||
|
||||
var maybe_unary = function(allow_calls) {
|
||||
var start = S.token;
|
||||
if (is("operator") && UNARY_PREFIX(start.value)) {
|
||||
if (is("operator") && UNARY_PREFIX[start.value]) {
|
||||
next();
|
||||
handle_regexp();
|
||||
var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls));
|
||||
@@ -1469,7 +1513,7 @@ function parse($TEXT, options) {
|
||||
return ex;
|
||||
}
|
||||
var val = expr_atom(allow_calls);
|
||||
while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
|
||||
while (is("operator") && UNARY_POSTFIX[S.token.value] && !has_newline_before(S.token)) {
|
||||
val = make_unary(AST_UnaryPostfix, S.token, val);
|
||||
val.start = start;
|
||||
val.end = S.token;
|
||||
@@ -1492,7 +1536,7 @@ function parse($TEXT, options) {
|
||||
break;
|
||||
}
|
||||
return new ctor({ operator: op, expression: expr });
|
||||
};
|
||||
}
|
||||
|
||||
var expr_op = function(left, min_prec, no_in) {
|
||||
var op = is("operator") ? S.token.value : null;
|
||||
@@ -1514,7 +1558,7 @@ function parse($TEXT, options) {
|
||||
|
||||
function expr_ops(no_in) {
|
||||
return expr_op(maybe_unary(true), 0, no_in);
|
||||
};
|
||||
}
|
||||
|
||||
var maybe_conditional = function(no_in) {
|
||||
var start = S.token;
|
||||
@@ -1536,12 +1580,12 @@ function parse($TEXT, options) {
|
||||
|
||||
function is_assignable(expr) {
|
||||
return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef;
|
||||
};
|
||||
}
|
||||
|
||||
var maybe_assign = function(no_in) {
|
||||
var start = S.token;
|
||||
var left = maybe_conditional(no_in), val = S.token.value;
|
||||
if (is("operator") && ASSIGNMENT(val)) {
|
||||
if (is("operator") && ASSIGNMENT[val]) {
|
||||
if (is_assignable(left)) {
|
||||
next();
|
||||
return new AST_Assign({
|
||||
@@ -1578,18 +1622,18 @@ function parse($TEXT, options) {
|
||||
var ret = cont();
|
||||
--S.in_loop;
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
if (options.expression) {
|
||||
return expression(true);
|
||||
}
|
||||
|
||||
return (function(){
|
||||
return function() {
|
||||
var start = S.token;
|
||||
var body = [];
|
||||
S.input.push_directives_stack();
|
||||
while (!is("eof"))
|
||||
body.push(statement());
|
||||
body.push(statement(true));
|
||||
S.input.pop_directives_stack();
|
||||
var end = prev();
|
||||
var toplevel = options.toplevel;
|
||||
@@ -1600,6 +1644,5 @@ function parse($TEXT, options) {
|
||||
toplevel = new AST_Toplevel({ start: start, body: body, end: end });
|
||||
}
|
||||
return toplevel;
|
||||
})();
|
||||
|
||||
};
|
||||
}();
|
||||
}
|
||||
|
||||
@@ -53,20 +53,57 @@ function find_builtins(reserved) {
|
||||
"-Infinity",
|
||||
"undefined",
|
||||
].forEach(add);
|
||||
[ Object, Array, Function, Number,
|
||||
String, Boolean, Error, Math,
|
||||
Date, RegExp
|
||||
[
|
||||
Array,
|
||||
Boolean,
|
||||
Date,
|
||||
Error,
|
||||
Function,
|
||||
Math,
|
||||
Number,
|
||||
Object,
|
||||
RegExp,
|
||||
String,
|
||||
].forEach(function(ctor) {
|
||||
Object.getOwnPropertyNames(ctor).map(add);
|
||||
if (ctor.prototype) {
|
||||
Object.getOwnPropertyNames(ctor.prototype).map(add);
|
||||
}
|
||||
});
|
||||
|
||||
function add(name) {
|
||||
push_uniq(reserved, name);
|
||||
}
|
||||
}
|
||||
|
||||
function reserve_quoted_keys(ast, reserved) {
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_ObjectKeyVal && node.quote) {
|
||||
add(node.key);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, add);
|
||||
}
|
||||
}));
|
||||
|
||||
function add(name) {
|
||||
push_uniq(reserved, name);
|
||||
}
|
||||
}
|
||||
|
||||
function addStrings(node, add) {
|
||||
node.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Sequence) {
|
||||
addStrings(node.tail_node(), add);
|
||||
} else if (node instanceof AST_String) {
|
||||
add(node.value);
|
||||
} else if (node instanceof AST_Conditional) {
|
||||
addStrings(node.consequent, add);
|
||||
addStrings(node.alternative, add);
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
function mangle_properties(ast, options) {
|
||||
options = defaults(options, {
|
||||
builtins: false,
|
||||
@@ -76,81 +113,67 @@ function mangle_properties(ast, options) {
|
||||
only_cache: false,
|
||||
regex: null,
|
||||
reserved: null,
|
||||
});
|
||||
}, true);
|
||||
|
||||
var reserved = options.reserved || [];
|
||||
var reserved = options.reserved;
|
||||
if (!Array.isArray(reserved)) reserved = [];
|
||||
if (!options.builtins) find_builtins(reserved);
|
||||
|
||||
var cache = options.cache;
|
||||
if (cache == null) {
|
||||
cache = {
|
||||
cname: -1,
|
||||
props: new Dictionary()
|
||||
};
|
||||
var cname = -1;
|
||||
var cache;
|
||||
if (options.cache) {
|
||||
cache = options.cache.props;
|
||||
cache.each(function(mangled_name) {
|
||||
push_uniq(reserved, mangled_name);
|
||||
});
|
||||
} else {
|
||||
cache = new Dictionary();
|
||||
}
|
||||
|
||||
var regex = options.regex;
|
||||
var keep_quoted = options.keep_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 debug_suffix;
|
||||
if (debug) debug_suffix = options.debug === true ? "" : options.debug;
|
||||
|
||||
var names_to_mangle = [];
|
||||
var unmangleable = [];
|
||||
var to_keep = {};
|
||||
|
||||
// step 1: find candidates to mangle
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
add(node.key, keep_quoted && node.quote);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
add(node.key);
|
||||
} else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter, since KeyVal is handled above
|
||||
add(node.key.name);
|
||||
}
|
||||
else if (node instanceof AST_Dot) {
|
||||
} else if (node instanceof AST_Dot) {
|
||||
add(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, keep_quoted);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, add);
|
||||
} else if (node instanceof AST_Call
|
||||
&& node.expression.print_to_string() == "Object.defineProperty") {
|
||||
addStrings(node.args[1], add);
|
||||
}
|
||||
}));
|
||||
|
||||
// step 2: transform the tree, renaming properties
|
||||
return ast.transform(new TreeTransformer(function(node) {
|
||||
if (node instanceof AST_ObjectKeyVal) {
|
||||
if (!(keep_quoted && node.quote))
|
||||
node.key = mangle(node.key);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
} else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter
|
||||
node.key.name = mangle(node.key.name);
|
||||
}
|
||||
else if (node instanceof AST_Dot) {
|
||||
} else if (node instanceof AST_Dot) {
|
||||
node.property = mangle(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
if (!keep_quoted)
|
||||
} else if (!options.keep_quoted && node instanceof AST_Sub) {
|
||||
node.property = mangleStrings(node.property);
|
||||
} else if (node instanceof AST_Call
|
||||
&& node.expression.print_to_string() == "Object.defineProperty") {
|
||||
node.args[1] = mangleStrings(node.args[1]);
|
||||
}
|
||||
// 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
|
||||
@@ -158,102 +181,50 @@ function mangle_properties(ast, options) {
|
||||
function can_mangle(name) {
|
||||
if (unmangleable.indexOf(name) >= 0) return false;
|
||||
if (reserved.indexOf(name) >= 0) return false;
|
||||
if (options.only_cache) {
|
||||
return cache.props.has(name);
|
||||
}
|
||||
if (options.only_cache) return cache.has(name);
|
||||
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function should_mangle(name) {
|
||||
if (keep_quoted && name in to_keep) 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;
|
||||
return cache.has(name) || names_to_mangle.indexOf(name) >= 0;
|
||||
}
|
||||
|
||||
function add(name, keep) {
|
||||
if (keep) {
|
||||
to_keep[name] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (can_mangle(name))
|
||||
push_uniq(names_to_mangle, name);
|
||||
|
||||
if (!should_mangle(name)) {
|
||||
push_uniq(unmangleable, name);
|
||||
}
|
||||
function add(name) {
|
||||
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);
|
||||
var mangled = cache.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) && !(keep_quoted && debug_mangled in to_keep)) {
|
||||
mangled = debug_mangled;
|
||||
var debug_mangled = "_$" + name + "$" + debug_suffix + "_";
|
||||
if (can_mangle(debug_mangled)) 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 `to_keep` set
|
||||
// (filled with quoted properties when `keep_quoted` is 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) || keep_quoted && mangled in to_keep);
|
||||
}
|
||||
|
||||
cache.props.set(name, mangled);
|
||||
if (!mangled) do {
|
||||
mangled = base54(++cname);
|
||||
} while (!can_mangle(mangled));
|
||||
cache.set(name, mangled);
|
||||
}
|
||||
return mangled;
|
||||
}
|
||||
|
||||
function addStrings(node, keep) {
|
||||
var out = {};
|
||||
try {
|
||||
(function walk(node){
|
||||
node.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_Sequence) {
|
||||
walk(node.expressions[node.expressions.length - 1]);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_String) {
|
||||
add(node.value, keep);
|
||||
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_Sequence) {
|
||||
var last = node.expressions.length - 1;
|
||||
node.expressions[last] = mangleStrings(node.expressions[last]);
|
||||
}
|
||||
else if (node instanceof AST_String) {
|
||||
} else if (node instanceof AST_String) {
|
||||
node.value = mangle(node.value);
|
||||
}
|
||||
else if (node instanceof AST_Conditional) {
|
||||
} else if (node instanceof AST_Conditional) {
|
||||
node.consequent = mangleStrings(node.consequent);
|
||||
node.alternative = mangleStrings(node.alternative);
|
||||
}
|
||||
|
||||
540
lib/scope.js
540
lib/scope.js
@@ -43,17 +43,19 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
function SymbolDef(scope, index, orig) {
|
||||
function SymbolDef(scope, orig, init) {
|
||||
this.name = orig.name;
|
||||
this.orig = [ orig ];
|
||||
this.init = init;
|
||||
this.eliminated = 0;
|
||||
this.scope = scope;
|
||||
this.references = [];
|
||||
this.replaced = 0;
|
||||
this.global = false;
|
||||
this.mangled_name = null;
|
||||
this.undeclared = false;
|
||||
this.index = index;
|
||||
this.id = SymbolDef.next_id++;
|
||||
};
|
||||
}
|
||||
|
||||
SymbolDef.next_id = 1;
|
||||
|
||||
@@ -61,32 +63,31 @@ SymbolDef.prototype = {
|
||||
unmangleable: function(options) {
|
||||
if (!options) options = {};
|
||||
|
||||
return (this.global && !options.toplevel)
|
||||
return this.global && !options.toplevel
|
||||
|| this.undeclared
|
||||
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|
||||
|| (options.keep_fnames
|
||||
|| !options.eval && this.scope.pinned()
|
||||
|| options.keep_fnames
|
||||
&& (this.orig[0] instanceof AST_SymbolLambda
|
||||
|| this.orig[0] instanceof AST_SymbolDefun));
|
||||
|| this.orig[0] instanceof AST_SymbolDefun);
|
||||
},
|
||||
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;
|
||||
var sym = this.orig[0];
|
||||
if (options.ie8 && sym instanceof AST_SymbolLambda)
|
||||
s = s.parent_scope;
|
||||
} else if (!this.mangled_name && !this.unmangleable(options)) {
|
||||
var def;
|
||||
if (this.defun && (def = this.defun.variables.get(this.name))) {
|
||||
if (def = this.redefined()) {
|
||||
this.mangled_name = def.mangled_name || def.name;
|
||||
} else
|
||||
this.mangled_name = s.next_mangled(options, this);
|
||||
} else {
|
||||
this.mangled_name = next_mangled_name(this.scope, options, this);
|
||||
}
|
||||
if (this.global && cache) {
|
||||
cache.set(this.name, this.mangled_name);
|
||||
}
|
||||
}
|
||||
},
|
||||
redefined: function() {
|
||||
return this.defun && this.defun.variables.get(this.name);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -99,7 +100,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
// pass 1: setup scope chaining and handle definitions
|
||||
var self = this;
|
||||
var scope = self.parent_scope = null;
|
||||
var labels = new Dictionary();
|
||||
var defun = null;
|
||||
var tw = new TreeWalker(function(node, descend) {
|
||||
if (node instanceof AST_Catch) {
|
||||
@@ -114,28 +114,14 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
node.init_scope_vars(scope);
|
||||
var save_scope = scope;
|
||||
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_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
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_With) {
|
||||
for (var s = scope; s; s = s.parent_scope)
|
||||
s.uses_with = true;
|
||||
for (var s = scope; s; s = s.parent_scope) s.uses_with = true;
|
||||
return;
|
||||
}
|
||||
if (node instanceof AST_Symbol) {
|
||||
@@ -145,56 +131,34 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
node.thedef = node;
|
||||
node.references = [];
|
||||
}
|
||||
if (node instanceof AST_SymbolLambda) {
|
||||
defun.def_function(node);
|
||||
}
|
||||
else if (node instanceof AST_SymbolDefun) {
|
||||
// Careful here, the scope where this should be defined is
|
||||
// the parent scope. The reason is that we enter a new
|
||||
// scope when we encounter the AST_Defun node (which is
|
||||
// instanceof AST_Scope) but we get to the symbol a bit
|
||||
// later.
|
||||
(node.scope = defun.parent_scope).def_function(node);
|
||||
}
|
||||
else if (node instanceof AST_SymbolVar) {
|
||||
defun.def_variable(node);
|
||||
if (node instanceof AST_SymbolDefun) {
|
||||
// This should be defined in the parent scope, as we encounter the
|
||||
// AST_Defun node before getting to its AST_Symbol.
|
||||
(node.scope = defun.parent_scope.resolve()).def_function(node, defun);
|
||||
} else if (node instanceof AST_SymbolLambda) {
|
||||
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
|
||||
if (options.ie8) def.defun = defun.parent_scope.resolve();
|
||||
} else if (node instanceof AST_SymbolVar) {
|
||||
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
|
||||
if (defun !== scope) {
|
||||
node.mark_enclosed(options);
|
||||
var def = scope.find_variable(node);
|
||||
if (node.thedef !== def) {
|
||||
node.thedef = def;
|
||||
}
|
||||
node.reference(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node instanceof AST_SymbolCatch) {
|
||||
} else if (node instanceof AST_SymbolCatch) {
|
||||
scope.def_variable(node).defun = defun;
|
||||
}
|
||||
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,
|
||||
col: node.start.col
|
||||
}));
|
||||
node.thedef = sym;
|
||||
}
|
||||
});
|
||||
self.walk(tw);
|
||||
|
||||
// pass 2: find back references and eval
|
||||
var func = null;
|
||||
var globals = self.globals = new Dictionary();
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node instanceof AST_Lambda) {
|
||||
var prev_func = func;
|
||||
func = node;
|
||||
descend();
|
||||
func = prev_func;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_LoopControl && node.label) {
|
||||
node.label.thedef.references.push(node);
|
||||
self.globals = new Dictionary();
|
||||
var tw = new TreeWalker(function(node) {
|
||||
if (node instanceof AST_LoopControl) {
|
||||
if (node.label) node.label.thedef.references.push(node);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
@@ -205,39 +169,53 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
}
|
||||
}
|
||||
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);
|
||||
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
|
||||
sym.scope.uses_arguments = true;
|
||||
}
|
||||
node.thedef = sym;
|
||||
node.reference(options);
|
||||
return true;
|
||||
}
|
||||
// ensure mangling works if catch reuses a scope variable
|
||||
if (node instanceof AST_SymbolCatch) {
|
||||
var def = node.definition().redefined();
|
||||
if (def) for (var s = node.scope; s; s = s.parent_scope) {
|
||||
push_uniq(s.enclosed, def);
|
||||
if (s === def.scope) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
self.walk(tw);
|
||||
|
||||
// pass 3: fix up any scoping issue with IE8
|
||||
if (options.ie8) {
|
||||
self.walk(new TreeWalker(function(node, descend) {
|
||||
if (options.ie8) self.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_SymbolCatch) {
|
||||
redefine(node, node.thedef.defun);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolLambda) {
|
||||
var def = node.thedef;
|
||||
if (def.orig.length == 1) {
|
||||
redefine(node, node.scope.parent_scope);
|
||||
node.thedef.init = def.init;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
|
||||
function redefine(node, scope) {
|
||||
var name = node.name;
|
||||
var refs = node.thedef.references;
|
||||
var scope = node.thedef.defun;
|
||||
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
|
||||
refs.forEach(function(ref) {
|
||||
ref.thedef = def;
|
||||
ref.reference(options);
|
||||
});
|
||||
node.thedef = def;
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
if (options.cache) {
|
||||
this.cname = options.cache.cname;
|
||||
node.reference(options);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -246,7 +224,7 @@ AST_Toplevel.DEFMETHOD("def_global", function(node){
|
||||
if (globals.has(name)) {
|
||||
return globals.get(name);
|
||||
} else {
|
||||
var g = new SymbolDef(this, globals.size(), node);
|
||||
var g = new SymbolDef(this, node);
|
||||
g.undeclared = true;
|
||||
g.global = true;
|
||||
globals.set(name, g);
|
||||
@@ -276,8 +254,7 @@ AST_Lambda.DEFMETHOD("init_scope_vars", function(){
|
||||
|
||||
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
|
||||
var def = this.definition();
|
||||
var s = this.scope;
|
||||
while (s) {
|
||||
for (var s = this.scope; s; s = s.parent_scope) {
|
||||
push_uniq(s.enclosed, def);
|
||||
if (options.keep_fnames) {
|
||||
s.functions.each(function(d) {
|
||||
@@ -285,7 +262,6 @@ AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
|
||||
});
|
||||
}
|
||||
if (s === def.scope) break;
|
||||
s = s.parent_scope;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -300,86 +276,98 @@ AST_Scope.DEFMETHOD("find_variable", function(name){
|
||||
|| (this.parent_scope && this.parent_scope.find_variable(name));
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("def_function", function(symbol){
|
||||
this.functions.set(symbol.name, this.def_variable(symbol));
|
||||
AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
|
||||
var def = this.def_variable(symbol, init);
|
||||
if (!def.init || def.init instanceof AST_Defun) def.init = init;
|
||||
this.functions.set(symbol.name, def);
|
||||
return def;
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("def_variable", function(symbol){
|
||||
var def;
|
||||
if (!this.variables.has(symbol.name)) {
|
||||
def = new SymbolDef(this, this.variables.size(), symbol);
|
||||
AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
|
||||
var def = this.variables.get(symbol.name);
|
||||
if (def) {
|
||||
def.orig.push(symbol);
|
||||
if (def.init && (def.scope !== symbol.scope || def.init instanceof AST_Function)) {
|
||||
def.init = init;
|
||||
}
|
||||
} else {
|
||||
def = new SymbolDef(this, symbol, init);
|
||||
this.variables.set(symbol.name, def);
|
||||
def.global = !this.parent_scope;
|
||||
} else {
|
||||
def = this.variables.get(symbol.name);
|
||||
def.orig.push(symbol);
|
||||
}
|
||||
return symbol.thedef = def;
|
||||
});
|
||||
|
||||
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 reserved from mangling.
|
||||
if (options.reserved.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 = ext.length; --i >= 0;) {
|
||||
var sym = ext[i];
|
||||
var name = sym.mangled_name || (sym.unmangleable(options) && sym.name);
|
||||
if (m == name) continue out;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
AST_Lambda.DEFMETHOD("resolve", return_this);
|
||||
AST_Scope.DEFMETHOD("resolve", function() {
|
||||
return this.parent_scope;
|
||||
});
|
||||
AST_Toplevel.DEFMETHOD("resolve", return_this);
|
||||
|
||||
AST_Function.DEFMETHOD("next_mangled", function(options, def){
|
||||
function names_in_use(scope, options) {
|
||||
var names = scope.names_in_use;
|
||||
if (!names) {
|
||||
scope.names_in_use = names = Object.create(scope.mangled_names || null);
|
||||
scope.cname_holes = [];
|
||||
scope.enclosed.forEach(function(def) {
|
||||
if (def.unmangleable(options)) names[def.name] = true;
|
||||
});
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
function next_mangled_name(scope, options, def) {
|
||||
var in_use = names_in_use(scope, options);
|
||||
var holes = scope.cname_holes;
|
||||
var names = Object.create(null);
|
||||
// #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();
|
||||
|
||||
if (scope instanceof AST_Function && scope.name && def.orig[0] instanceof AST_SymbolFunarg) {
|
||||
var tricky_def = scope.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)
|
||||
names[tricky_def.mangled_name || tricky_def.name] = true;
|
||||
}
|
||||
var scopes = [ scope ];
|
||||
def.references.forEach(function(sym) {
|
||||
var scope = sym.scope;
|
||||
do {
|
||||
if (scopes.indexOf(scope) < 0) {
|
||||
for (var name in names_in_use(scope, options)) {
|
||||
names[name] = true;
|
||||
}
|
||||
scopes.push(scope);
|
||||
} else break;
|
||||
} while (scope = scope.parent_scope);
|
||||
});
|
||||
var name;
|
||||
for (var i = 0, len = holes.length; i < len; i++) {
|
||||
name = base54(holes[i]);
|
||||
if (names[name]) continue;
|
||||
holes.splice(i, 1);
|
||||
scope.names_in_use[name] = true;
|
||||
return name;
|
||||
}
|
||||
while (true) {
|
||||
name = base54(++scope.cname);
|
||||
if (in_use[name] || !is_identifier(name) || options.reserved.has[name]) continue;
|
||||
if (!names[name]) break;
|
||||
holes.push(scope.cname);
|
||||
}
|
||||
scope.names_in_use[name] = true;
|
||||
return name;
|
||||
}
|
||||
});
|
||||
|
||||
AST_Symbol.DEFMETHOD("unmangleable", function(options) {
|
||||
return this.definition().unmangleable(options);
|
||||
var def = this.definition();
|
||||
return !def || def.unmangleable(options);
|
||||
});
|
||||
|
||||
// labels are always mangleable
|
||||
AST_Label.DEFMETHOD("unmangleable", function(){
|
||||
return false;
|
||||
});
|
||||
AST_Label.DEFMETHOD("unmangleable", return_false);
|
||||
|
||||
AST_Symbol.DEFMETHOD("unreferenced", function() {
|
||||
return this.definition().references.length == 0
|
||||
&& !(this.scope.uses_eval || this.scope.uses_with);
|
||||
});
|
||||
|
||||
AST_Symbol.DEFMETHOD("undeclared", function(){
|
||||
return this.definition().undeclared;
|
||||
});
|
||||
|
||||
AST_LabelRef.DEFMETHOD("undeclared", function(){
|
||||
return false;
|
||||
});
|
||||
|
||||
AST_Label.DEFMETHOD("undeclared", function(){
|
||||
return false;
|
||||
return !this.definition().references.length && !this.scope.pinned();
|
||||
});
|
||||
|
||||
AST_Symbol.DEFMETHOD("definition", function() {
|
||||
@@ -390,177 +378,227 @@ AST_Symbol.DEFMETHOD("global", function(){
|
||||
return this.definition().global;
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
||||
return defaults(options, {
|
||||
function _default_mangler_options(options) {
|
||||
options = defaults(options, {
|
||||
eval : false,
|
||||
ie8 : false,
|
||||
keep_fnames : false,
|
||||
reserved : [],
|
||||
toplevel : false,
|
||||
});
|
||||
});
|
||||
if (!Array.isArray(options.reserved)) options.reserved = [];
|
||||
// Never mangle arguments
|
||||
push_uniq(options.reserved, "arguments");
|
||||
options.reserved.has = makePredicate(options.reserved);
|
||||
return options;
|
||||
}
|
||||
|
||||
AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
|
||||
options = this._default_mangler_options(options);
|
||||
|
||||
// Never mangle arguments
|
||||
options.reserved.push('arguments');
|
||||
options = _default_mangler_options(options);
|
||||
|
||||
// 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.reserved.indexOf(symbol.name) < 0) {
|
||||
to_mangle.push(symbol);
|
||||
}
|
||||
if (options.cache && options.cache.props) {
|
||||
var mangled_names = this.mangled_names = Object.create(null);
|
||||
options.cache.props.each(function(mangled_name) {
|
||||
mangled_names[mangled_name] = true;
|
||||
});
|
||||
}
|
||||
|
||||
var redefined = [];
|
||||
var tw = new TreeWalker(function(node, descend) {
|
||||
if (node instanceof AST_LabeledStatement) {
|
||||
// lname is incremented when we get to the AST_Label
|
||||
var save_nesting = lname;
|
||||
descend();
|
||||
lname = save_nesting;
|
||||
return true; // don't descend again in TreeWalker
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Scope) {
|
||||
var p = tw.parent(), a = [];
|
||||
node.variables.each(function(symbol){
|
||||
if (options.reserved.indexOf(symbol.name) < 0) {
|
||||
a.push(symbol);
|
||||
descend();
|
||||
if (options.cache && node instanceof AST_Toplevel) {
|
||||
node.globals.each(mangle);
|
||||
}
|
||||
});
|
||||
to_mangle.push.apply(to_mangle, a);
|
||||
return;
|
||||
node.variables.each(mangle);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Label) {
|
||||
var name;
|
||||
do name = base54(++lname); while (!is_identifier(name));
|
||||
do {
|
||||
name = base54(++lname);
|
||||
} while (!is_identifier(name));
|
||||
node.mangled_name = name;
|
||||
return true;
|
||||
}
|
||||
if (!options.ie8 && node instanceof AST_SymbolCatch) {
|
||||
to_mangle.push(node.definition());
|
||||
return;
|
||||
if (!options.ie8 && node instanceof AST_Catch) {
|
||||
var def = node.argname.definition();
|
||||
var redef = def.redefined();
|
||||
if (redef) {
|
||||
redefined.push(def);
|
||||
reference(node.argname);
|
||||
def.references.forEach(reference);
|
||||
}
|
||||
descend();
|
||||
if (!redef) mangle(def);
|
||||
return true;
|
||||
}
|
||||
|
||||
function reference(sym) {
|
||||
sym.thedef = redef;
|
||||
sym.reference(options);
|
||||
sym.thedef = def;
|
||||
}
|
||||
});
|
||||
this.walk(tw);
|
||||
to_mangle.forEach(function(def){ def.mangle(options) });
|
||||
redefined.forEach(mangle);
|
||||
|
||||
if (options.cache) {
|
||||
options.cache.cname = this.cname;
|
||||
function mangle(def) {
|
||||
if (options.reserved.has[def.name]) return;
|
||||
def.mangle(options);
|
||||
}
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
||||
var cache = options.cache && options.cache.props;
|
||||
var avoid = Object.create(null);
|
||||
options.reserved.forEach(to_avoid);
|
||||
this.globals.each(add_def);
|
||||
this.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Scope) node.variables.each(add_def);
|
||||
if (node instanceof AST_SymbolCatch) add_def(node.definition());
|
||||
}));
|
||||
return avoid;
|
||||
|
||||
function to_avoid(name) {
|
||||
avoid[name] = true;
|
||||
}
|
||||
|
||||
function add_def(def) {
|
||||
var name = def.name;
|
||||
if (def.global && cache && cache.has(name)) name = cache.get(name);
|
||||
else if (!def.unmangleable(options)) return;
|
||||
to_avoid(name);
|
||||
}
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
||||
base54.reset();
|
||||
base54.sort();
|
||||
options = _default_mangler_options(options);
|
||||
var avoid = this.find_colliding_names(options);
|
||||
var cname = 0;
|
||||
this.globals.each(rename);
|
||||
this.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Scope) node.variables.each(rename);
|
||||
if (node instanceof AST_SymbolCatch) rename(node.definition());
|
||||
}));
|
||||
|
||||
function next_name() {
|
||||
var name;
|
||||
do {
|
||||
name = base54(cname++);
|
||||
} while (avoid[name] || !is_identifier(name));
|
||||
return name;
|
||||
}
|
||||
|
||||
function rename(def) {
|
||||
if (def.global && options.cache) return;
|
||||
if (def.unmangleable(options)) return;
|
||||
if (options.reserved.has[def.name]) return;
|
||||
var d = def.redefined();
|
||||
def.name = d ? d.name : next_name();
|
||||
def.orig.forEach(function(sym) {
|
||||
sym.name = def.name;
|
||||
});
|
||||
def.references.forEach(function(sym) {
|
||||
sym.name = def.name;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
AST_Node.DEFMETHOD("tail_node", return_this);
|
||||
AST_Sequence.DEFMETHOD("tail_node", function() {
|
||||
return this.expressions[this.expressions.length - 1];
|
||||
});
|
||||
|
||||
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());
|
||||
else if (node instanceof AST_Return)
|
||||
base54.consider("return");
|
||||
else if (node instanceof AST_Throw)
|
||||
base54.consider("throw");
|
||||
else if (node instanceof AST_Continue)
|
||||
base54.consider("continue");
|
||||
else if (node instanceof AST_Break)
|
||||
base54.consider("break");
|
||||
else if (node instanceof AST_Debugger)
|
||||
base54.consider("debugger");
|
||||
else if (node instanceof AST_Directive)
|
||||
base54.consider(node.value);
|
||||
else if (node instanceof AST_While)
|
||||
base54.consider("while");
|
||||
else if (node instanceof AST_Do)
|
||||
base54.consider("do while");
|
||||
else if (node instanceof AST_If) {
|
||||
base54.consider("if");
|
||||
if (node.alternative) base54.consider("else");
|
||||
options = _default_mangler_options(options);
|
||||
base54.reset();
|
||||
try {
|
||||
AST_Node.prototype.print = function(stream, force_parens) {
|
||||
this._print(stream, force_parens);
|
||||
if (this instanceof AST_Symbol && !this.unmangleable(options)) {
|
||||
base54.consider(this.name, -1);
|
||||
} else if (options.properties) {
|
||||
if (this instanceof AST_Dot) {
|
||||
base54.consider(this.property, -1);
|
||||
} else if (this instanceof AST_Sub) {
|
||||
skip_string(this.property);
|
||||
}
|
||||
}
|
||||
};
|
||||
base54.consider(this.print_to_string(), 1);
|
||||
} finally {
|
||||
AST_Node.prototype.print = AST_Node.prototype._print;
|
||||
}
|
||||
else if (node instanceof AST_Var)
|
||||
base54.consider("var");
|
||||
else if (node instanceof AST_Lambda)
|
||||
base54.consider("function");
|
||||
else if (node instanceof AST_For)
|
||||
base54.consider("for");
|
||||
else if (node instanceof AST_ForIn)
|
||||
base54.consider("for in");
|
||||
else if (node instanceof AST_Switch)
|
||||
base54.consider("switch");
|
||||
else if (node instanceof AST_Case)
|
||||
base54.consider("case");
|
||||
else if (node instanceof AST_Default)
|
||||
base54.consider("default");
|
||||
else if (node instanceof AST_With)
|
||||
base54.consider("with");
|
||||
else if (node instanceof AST_ObjectSetter)
|
||||
base54.consider("set" + node.key);
|
||||
else if (node instanceof AST_ObjectGetter)
|
||||
base54.consider("get" + node.key);
|
||||
else if (node instanceof AST_ObjectKeyVal)
|
||||
base54.consider(node.key);
|
||||
else if (node instanceof AST_New)
|
||||
base54.consider("new");
|
||||
else if (node instanceof AST_This)
|
||||
base54.consider("this");
|
||||
else if (node instanceof AST_Try)
|
||||
base54.consider("try");
|
||||
else if (node instanceof AST_Catch)
|
||||
base54.consider("catch");
|
||||
else if (node instanceof AST_Finally)
|
||||
base54.consider("finally");
|
||||
else if (node instanceof AST_Symbol && node.unmangleable(options))
|
||||
base54.consider(node.name);
|
||||
else if (node instanceof AST_Unary || node instanceof AST_Binary)
|
||||
base54.consider(node.operator);
|
||||
else if (node instanceof AST_Dot)
|
||||
base54.consider(node.property);
|
||||
});
|
||||
this.walk(tw);
|
||||
base54.sort();
|
||||
|
||||
function skip_string(node) {
|
||||
if (node instanceof AST_String) {
|
||||
base54.consider(node.value, -1);
|
||||
} else if (node instanceof AST_Conditional) {
|
||||
skip_string(node.consequent);
|
||||
skip_string(node.alternative);
|
||||
} else if (node instanceof AST_Sequence) {
|
||||
skip_string(node.tail_node());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var base54 = (function() {
|
||||
var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
|
||||
var freq = Object.create(null);
|
||||
function init(chars) {
|
||||
var array = [];
|
||||
for (var i = 0, len = chars.length; i < len; i++) {
|
||||
var ch = chars[i];
|
||||
array.push(ch);
|
||||
freq[ch] = -1e-2 * i;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
var digits = init("0123456789");
|
||||
var leading = init("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_");
|
||||
var chars, frequency;
|
||||
function reset() {
|
||||
frequency = Object.create(null);
|
||||
chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
|
||||
chars.forEach(function(ch){ frequency[ch] = 0 });
|
||||
frequency = Object.create(freq);
|
||||
}
|
||||
base54.consider = function(str){
|
||||
base54.consider = function(str, delta) {
|
||||
for (var i = str.length; --i >= 0;) {
|
||||
var code = str.charCodeAt(i);
|
||||
if (code in frequency) ++frequency[code];
|
||||
frequency[str[i]] += delta;
|
||||
}
|
||||
};
|
||||
base54.sort = function() {
|
||||
chars = mergeSort(chars, function(a, b){
|
||||
if (is_digit(a) && !is_digit(b)) return 1;
|
||||
if (is_digit(b) && !is_digit(a)) return -1;
|
||||
function compare(a, b) {
|
||||
return frequency[b] - frequency[a];
|
||||
});
|
||||
}
|
||||
base54.sort = function() {
|
||||
chars = leading.sort(compare).concat(digits.sort(compare));
|
||||
};
|
||||
base54.reset = reset;
|
||||
reset();
|
||||
base54.get = function(){ return chars };
|
||||
base54.freq = function(){ return frequency };
|
||||
function base54(num) {
|
||||
var ret = "", base = 54;
|
||||
num++;
|
||||
do {
|
||||
num--;
|
||||
ret += String.fromCharCode(chars[num % base]);
|
||||
ret += chars[num % base];
|
||||
num = Math.floor(num / base);
|
||||
base = 64;
|
||||
} while (num > 0);
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
return base54;
|
||||
})();
|
||||
|
||||
@@ -49,49 +49,56 @@ function SourceMap(options) {
|
||||
file: null,
|
||||
root: null,
|
||||
orig: null,
|
||||
|
||||
orig_line_diff: 0,
|
||||
dest_line_diff: 0,
|
||||
});
|
||||
}, true);
|
||||
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);
|
||||
}
|
||||
var maps = options.orig && Object.create(null);
|
||||
if (maps) for (var source in options.orig) {
|
||||
var map = new MOZ_SourceMap.SourceMapConsumer(options.orig[source]);
|
||||
if (Array.isArray(options.orig[source].sources)) {
|
||||
map._sources.toArray().forEach(function(source) {
|
||||
var sourceContent = 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({
|
||||
maps[source] = map;
|
||||
}
|
||||
return {
|
||||
add: function(source, gen_line, gen_col, orig_line, orig_col, name) {
|
||||
var map = maps && maps[source];
|
||||
if (map) {
|
||||
var info = map.originalPositionFor({
|
||||
line: orig_line,
|
||||
column: orig_col
|
||||
});
|
||||
if (info.source === null) {
|
||||
return;
|
||||
}
|
||||
if (info.source === null) return;
|
||||
source = info.source;
|
||||
orig_line = info.line;
|
||||
orig_col = info.column;
|
||||
name = info.name || name;
|
||||
}
|
||||
generator.addMapping({
|
||||
generated : { line: gen_line + options.dest_line_diff, column: gen_col },
|
||||
original : { line: orig_line + options.orig_line_diff, column: orig_col },
|
||||
name: name,
|
||||
source: source,
|
||||
name : name
|
||||
generated: {
|
||||
line: gen_line + options.dest_line_diff,
|
||||
column: gen_col
|
||||
},
|
||||
original: {
|
||||
line: orig_line + options.orig_line_diff,
|
||||
column: orig_col
|
||||
}
|
||||
});
|
||||
},
|
||||
get: function() {
|
||||
return generator;
|
||||
},
|
||||
toString: function() {
|
||||
return JSON.stringify(generator.toJSON());
|
||||
}
|
||||
};
|
||||
return {
|
||||
add : add,
|
||||
get : function() { return generator },
|
||||
toString : function() { return JSON.stringify(generator.toJSON()); }
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
134
lib/transform.js
134
lib/transform.js
@@ -43,8 +43,6 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tree transformer helpers.
|
||||
|
||||
function TreeTransformer(before, after) {
|
||||
TreeWalker.call(this);
|
||||
this.before = before;
|
||||
@@ -52,166 +50,136 @@ function TreeTransformer(before, after) {
|
||||
}
|
||||
TreeTransformer.prototype = new TreeWalker;
|
||||
|
||||
(function(undefined){
|
||||
|
||||
function _(node, descend) {
|
||||
node.DEFMETHOD("transform", function(tw, in_list){
|
||||
var x, y;
|
||||
tw.push(this);
|
||||
if (tw.before) x = tw.before(this, descend, in_list);
|
||||
if (x === undefined) {
|
||||
if (!tw.after) {
|
||||
x = this;
|
||||
descend(x, tw);
|
||||
} else {
|
||||
tw.stack[tw.stack.length - 1] = x = this;
|
||||
descend(x, tw);
|
||||
y = tw.after(x, in_list);
|
||||
if (y !== undefined) x = y;
|
||||
}
|
||||
}
|
||||
tw.pop(this);
|
||||
return x;
|
||||
});
|
||||
};
|
||||
|
||||
(function(DEF) {
|
||||
function do_list(list, tw) {
|
||||
return MAP(list, function(node) {
|
||||
return node.transform(tw, true);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
_(AST_Node, noop);
|
||||
|
||||
_(AST_LabeledStatement, function(self, tw){
|
||||
DEF(AST_Node, noop);
|
||||
DEF(AST_LabeledStatement, function(self, tw) {
|
||||
self.label = self.label.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_SimpleStatement, function(self, tw){
|
||||
DEF(AST_SimpleStatement, function(self, tw) {
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Block, function(self, tw){
|
||||
DEF(AST_Block, function(self, tw) {
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
|
||||
_(AST_DWLoop, function(self, tw){
|
||||
DEF(AST_Do, function(self, tw) {
|
||||
self.body = self.body.transform(tw);
|
||||
self.condition = self.condition.transform(tw);
|
||||
});
|
||||
DEF(AST_While, function(self, tw) {
|
||||
self.condition = self.condition.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_For, function(self, tw){
|
||||
DEF(AST_For, function(self, tw) {
|
||||
if (self.init) self.init = self.init.transform(tw);
|
||||
if (self.condition) self.condition = self.condition.transform(tw);
|
||||
if (self.step) self.step = self.step.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_ForIn, function(self, tw){
|
||||
DEF(AST_ForIn, function(self, tw) {
|
||||
self.init = self.init.transform(tw);
|
||||
self.object = self.object.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_With, function(self, tw){
|
||||
DEF(AST_With, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Exit, function(self, tw){
|
||||
DEF(AST_Exit, function(self, tw) {
|
||||
if (self.value) self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_LoopControl, function(self, tw){
|
||||
DEF(AST_LoopControl, function(self, tw) {
|
||||
if (self.label) self.label = self.label.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_If, function(self, tw){
|
||||
DEF(AST_If, function(self, tw) {
|
||||
self.condition = self.condition.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
if (self.alternative) self.alternative = self.alternative.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Switch, function(self, tw){
|
||||
DEF(AST_Switch, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
|
||||
_(AST_Case, function(self, tw){
|
||||
DEF(AST_Case, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
|
||||
_(AST_Try, function(self, tw){
|
||||
DEF(AST_Try, function(self, tw) {
|
||||
self.body = do_list(self.body, tw);
|
||||
if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
|
||||
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Catch, function(self, tw){
|
||||
DEF(AST_Catch, function(self, tw) {
|
||||
self.argname = self.argname.transform(tw);
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
|
||||
_(AST_Definitions, function(self, tw){
|
||||
DEF(AST_Definitions, function(self, tw) {
|
||||
self.definitions = do_list(self.definitions, tw);
|
||||
});
|
||||
|
||||
_(AST_VarDef, function(self, tw){
|
||||
DEF(AST_VarDef, function(self, tw) {
|
||||
self.name = self.name.transform(tw);
|
||||
if (self.value) self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Lambda, function(self, tw){
|
||||
DEF(AST_Lambda, function(self, tw) {
|
||||
if (self.name) self.name = self.name.transform(tw);
|
||||
self.argnames = do_list(self.argnames, tw);
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
|
||||
_(AST_Call, function(self, tw){
|
||||
DEF(AST_Call, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
self.args = do_list(self.args, tw);
|
||||
});
|
||||
|
||||
_(AST_Sequence, function(self, tw){
|
||||
DEF(AST_Sequence, function(self, tw) {
|
||||
self.expressions = do_list(self.expressions, tw);
|
||||
});
|
||||
|
||||
_(AST_Dot, function(self, tw){
|
||||
DEF(AST_Dot, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Sub, function(self, tw){
|
||||
DEF(AST_Sub, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
self.property = self.property.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Unary, function(self, tw){
|
||||
DEF(AST_Unary, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Binary, function(self, tw){
|
||||
DEF(AST_Binary, function(self, tw) {
|
||||
self.left = self.left.transform(tw);
|
||||
self.right = self.right.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Conditional, function(self, tw){
|
||||
DEF(AST_Conditional, function(self, tw) {
|
||||
self.condition = self.condition.transform(tw);
|
||||
self.consequent = self.consequent.transform(tw);
|
||||
self.alternative = self.alternative.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Array, function(self, tw){
|
||||
DEF(AST_Array, function(self, tw) {
|
||||
self.elements = do_list(self.elements, tw);
|
||||
});
|
||||
|
||||
_(AST_Object, function(self, tw){
|
||||
DEF(AST_Object, function(self, tw) {
|
||||
self.properties = do_list(self.properties, tw);
|
||||
});
|
||||
|
||||
_(AST_ObjectProperty, function(self, tw){
|
||||
DEF(AST_ObjectProperty, function(self, tw) {
|
||||
self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
})();
|
||||
})(function(node, descend) {
|
||||
node.DEFMETHOD("transform", function(tw, in_list) {
|
||||
var x, y;
|
||||
tw.push(this);
|
||||
if (tw.before) x = tw.before(this, descend, in_list);
|
||||
if (typeof x === "undefined") {
|
||||
x = this;
|
||||
descend(x, tw);
|
||||
if (tw.after) {
|
||||
y = tw.after(x, in_list);
|
||||
if (typeof y !== "undefined") x = y;
|
||||
}
|
||||
}
|
||||
tw.pop();
|
||||
return x;
|
||||
});
|
||||
});
|
||||
|
||||
191
lib/utils.js
191
lib/utils.js
@@ -43,40 +43,25 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
function array_to_hash(a) {
|
||||
var ret = Object.create(null);
|
||||
for (var i = 0; i < a.length; ++i)
|
||||
ret[a[i]] = true;
|
||||
return ret;
|
||||
};
|
||||
|
||||
function slice(a, start) {
|
||||
return Array.prototype.slice.call(a, start || 0);
|
||||
};
|
||||
|
||||
function characters(str) {
|
||||
return str.split("");
|
||||
};
|
||||
}
|
||||
|
||||
function member(name, array) {
|
||||
return array.indexOf(name) >= 0;
|
||||
};
|
||||
}
|
||||
|
||||
function find_if(func, array) {
|
||||
for (var i = 0, n = array.length; i < n; ++i) {
|
||||
if (func(array[i]))
|
||||
return array[i];
|
||||
for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i];
|
||||
}
|
||||
};
|
||||
|
||||
function repeat_string(str, i) {
|
||||
if (i <= 0) return "";
|
||||
if (i == 1) return str;
|
||||
var d = repeat_string(str, i >> 1);
|
||||
d += d;
|
||||
if (i & 1) d += str;
|
||||
return d;
|
||||
};
|
||||
return i & 1 ? d + str : d;
|
||||
}
|
||||
|
||||
function configure_error_stack(fn) {
|
||||
Object.defineProperty(fn.prototype, "stack", {
|
||||
@@ -95,27 +80,23 @@ function configure_error_stack(fn) {
|
||||
function DefaultsError(msg, defs) {
|
||||
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 = {};
|
||||
if (args === true) args = {};
|
||||
var ret = args || {};
|
||||
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i))
|
||||
DefaultsError.croak("`" + i + "` is not a supported option", defs);
|
||||
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
|
||||
throw new DefaultsError("`" + 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) {
|
||||
var count = 0;
|
||||
@@ -124,7 +105,7 @@ function merge(obj, ext) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
};
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
function return_false() { return false; }
|
||||
@@ -155,8 +136,8 @@ var MAP = (function(){
|
||||
}
|
||||
}
|
||||
return is_last;
|
||||
};
|
||||
if (a instanceof Array) {
|
||||
}
|
||||
if (Array.isArray(a)) {
|
||||
if (backwards) {
|
||||
for (i = a.length; --i >= 0;) if (doit()) break;
|
||||
ret.reverse();
|
||||
@@ -169,127 +150,52 @@ var MAP = (function(){
|
||||
for (i in a) if (HOP(a, i)) if (doit()) break;
|
||||
}
|
||||
return top.concat(ret);
|
||||
};
|
||||
}
|
||||
MAP.at_top = function(val) { return new AtTop(val) };
|
||||
MAP.splice = function(val) { return new Splice(val) };
|
||||
MAP.last = function(val) { return new Last(val) };
|
||||
var skip = MAP.skip = {};
|
||||
function AtTop(val) { this.v = val };
|
||||
function Splice(val) { this.v = val };
|
||||
function Last(val) { this.v = val };
|
||||
function AtTop(val) { this.v = val }
|
||||
function Splice(val) { this.v = val }
|
||||
function Last(val) { this.v = val }
|
||||
return MAP;
|
||||
})();
|
||||
|
||||
function push_uniq(array, el) {
|
||||
if (array.indexOf(el) < 0)
|
||||
array.push(el);
|
||||
};
|
||||
if (array.indexOf(el) < 0) return array.push(el);
|
||||
}
|
||||
|
||||
function string_template(text, props) {
|
||||
return text.replace(/\{(.+?)\}/g, function(str, p) {
|
||||
return props && props[p];
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function remove(array, el) {
|
||||
for (var i = array.length; --i >= 0;) {
|
||||
if (array[i] === el) array.splice(i, 1);
|
||||
var index = array.indexOf(el);
|
||||
if (index >= 0) array.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
function mergeSort(array, cmp) {
|
||||
if (array.length < 2) return array.slice();
|
||||
function merge(a, b) {
|
||||
var r = [], ai = 0, bi = 0, i = 0;
|
||||
while (ai < a.length && bi < b.length) {
|
||||
cmp(a[ai], b[bi]) <= 0
|
||||
? r[i++] = a[ai++]
|
||||
: r[i++] = b[bi++];
|
||||
}
|
||||
if (ai < a.length) r.push.apply(r, a.slice(ai));
|
||||
if (bi < b.length) r.push.apply(r, b.slice(bi));
|
||||
return r;
|
||||
};
|
||||
function _ms(a) {
|
||||
if (a.length <= 1)
|
||||
return a;
|
||||
var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
|
||||
left = _ms(left);
|
||||
right = _ms(right);
|
||||
return merge(left, right);
|
||||
};
|
||||
return _ms(array);
|
||||
};
|
||||
|
||||
function set_difference(a, b) {
|
||||
return a.filter(function(el){
|
||||
return b.indexOf(el) < 0;
|
||||
});
|
||||
};
|
||||
|
||||
function set_intersection(a, b) {
|
||||
return a.filter(function(el){
|
||||
return b.indexOf(el) >= 0;
|
||||
});
|
||||
};
|
||||
|
||||
// this function is taken from Acorn [1], written by Marijn Haverbeke
|
||||
// [1] https://github.com/marijnh/acorn
|
||||
function makePredicate(words) {
|
||||
if (!(words instanceof Array)) words = words.split(" ");
|
||||
var f = "", cats = [];
|
||||
out: for (var i = 0; i < words.length; ++i) {
|
||||
for (var j = 0; j < cats.length; ++j)
|
||||
if (cats[j][0].length == words[i].length) {
|
||||
cats[j].push(words[i]);
|
||||
continue out;
|
||||
}
|
||||
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;
|
||||
if (!Array.isArray(words)) words = words.split(" ");
|
||||
var map = Object.create(null);
|
||||
words.forEach(function(word) {
|
||||
map[word] = true;
|
||||
});
|
||||
return map;
|
||||
}
|
||||
function compareTo(arr) {
|
||||
if (arr.length == 1) return f += "return str === " + quote(arr[0]) + ";";
|
||||
f += "switch(str){";
|
||||
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
|
||||
// switch first dispatches on the lengths, to save on comparisons.
|
||||
if (cats.length > 3) {
|
||||
cats.sort(function(a, b) {return b.length - a.length;});
|
||||
f += "switch(str.length){";
|
||||
for (var i = 0; i < cats.length; ++i) {
|
||||
var cat = cats[i];
|
||||
f += "case " + cat[0].length + ":";
|
||||
compareTo(cat);
|
||||
}
|
||||
f += "}";
|
||||
// Otherwise, simply generate a flat `switch` statement.
|
||||
} else {
|
||||
compareTo(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;
|
||||
@@ -326,6 +232,13 @@ Dictionary.prototype = {
|
||||
ret.push(f(this._values[i], i.substr(1)));
|
||||
return ret;
|
||||
},
|
||||
clone: function() {
|
||||
var ret = new Dictionary();
|
||||
for (var i in this._values)
|
||||
ret._values[i] = this._values[i];
|
||||
ret._size = this._size;
|
||||
return ret;
|
||||
},
|
||||
toObject: function() { return this._values }
|
||||
};
|
||||
Dictionary.fromObject = function(obj) {
|
||||
@@ -343,20 +256,22 @@ function HOP(obj, prop) {
|
||||
// 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_Sequence && p.expressions[0] === 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 {
|
||||
for (var i = 0, p; p = stack.parent(i++); node = p) {
|
||||
if (p.TYPE == "Call") {
|
||||
if (p.expression === node) continue;
|
||||
} else if (p instanceof AST_Binary) {
|
||||
if (p.left === node) continue;
|
||||
} else if (p instanceof AST_Conditional) {
|
||||
if (p.condition === node) continue;
|
||||
} else if (p instanceof AST_PropAccess) {
|
||||
if (p.expression === node) continue;
|
||||
} else if (p instanceof AST_Sequence) {
|
||||
if (p.expressions[0] === node) continue;
|
||||
} else if (p instanceof AST_Statement) {
|
||||
return p.body === node;
|
||||
} else if (p instanceof AST_UnaryPostfix) {
|
||||
if (p.expression === node) continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
46
package.json
46
package.json
@@ -1,23 +1,17 @@
|
||||
{
|
||||
"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": "3.0.11",
|
||||
"version": "3.4.6",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
"maintainers": [
|
||||
"Alex Lam <alexlamsl@gmail.com>",
|
||||
"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"
|
||||
},
|
||||
"repository": "mishoo/UglifyJS2",
|
||||
"main": "tools/node.js",
|
||||
"bin": {
|
||||
"uglifyjs": "bin/uglifyjs"
|
||||
@@ -29,16 +23,38 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "~2.9.0",
|
||||
"source-map": "~0.5.1"
|
||||
"commander": "~2.16.0",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "~5.0.3",
|
||||
"mocha": "~2.3.4",
|
||||
"semver": "~5.3.0"
|
||||
"acorn": "~5.7.1",
|
||||
"semver": "~5.5.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test/run-tests.js"
|
||||
},
|
||||
"keywords": ["uglify", "uglify-js", "minify", "minifier", "es5"]
|
||||
"keywords": [
|
||||
"cli",
|
||||
"compress",
|
||||
"compressor",
|
||||
"ecma",
|
||||
"ecmascript",
|
||||
"es",
|
||||
"es5",
|
||||
"javascript",
|
||||
"js",
|
||||
"jsmin",
|
||||
"min",
|
||||
"minification",
|
||||
"minifier",
|
||||
"minify",
|
||||
"optimize",
|
||||
"optimizer",
|
||||
"pack",
|
||||
"packer",
|
||||
"parse",
|
||||
"parser",
|
||||
"uglifier",
|
||||
"uglify"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
"use strict";
|
||||
|
||||
var createHash = require("crypto").createHash;
|
||||
var fetch = require("./fetch");
|
||||
var fork = require("child_process").fork;
|
||||
var zlib = require("zlib");
|
||||
var args = process.argv.slice(2);
|
||||
if (!args.length) {
|
||||
args.push("-mc");
|
||||
}
|
||||
args.push("--stats");
|
||||
args.push("--timings");
|
||||
var urls = [
|
||||
"https://code.jquery.com/jquery-3.2.1.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js",
|
||||
@@ -19,28 +21,29 @@ var urls = [
|
||||
"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",
|
||||
"https://raw.githubusercontent.com/kangax/html-minifier/v3.5.7/dist/htmlminifier.js",
|
||||
];
|
||||
var results = {};
|
||||
var remaining = 2 * urls.length;
|
||||
function done() {
|
||||
if (!--remaining) {
|
||||
var failures = [];
|
||||
var sum = { input: 0, output: 0, gzip: 0 };
|
||||
urls.forEach(function(url) {
|
||||
var info = results[url];
|
||||
console.log();
|
||||
console.log(url);
|
||||
var elapsed = 0;
|
||||
console.log(info.log.replace(/Elapsed: ([0-9]+)\s*/g, function(match, time) {
|
||||
elapsed += 1e-3 * parseInt(time);
|
||||
return "";
|
||||
}));
|
||||
console.log("Run-time:", elapsed.toFixed(3), "s");
|
||||
console.log(info.log);
|
||||
console.log("Original:", info.input, "bytes");
|
||||
console.log("Uglified:", info.output, "bytes");
|
||||
console.log("GZipped: ", info.gzip, "bytes");
|
||||
console.log("SHA1 sum:", info.sha1);
|
||||
if (info.code) {
|
||||
failures.push(url);
|
||||
}
|
||||
sum.input += info.input;
|
||||
sum.output += info.output;
|
||||
sum.gzip += info.gzip;
|
||||
});
|
||||
if (failures.length) {
|
||||
console.error("Benchmark failed:");
|
||||
@@ -48,6 +51,13 @@ function done() {
|
||||
console.error(url);
|
||||
});
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log();
|
||||
console.log("Subtotal");
|
||||
console.log();
|
||||
console.log("Original:", sum.input, "bytes");
|
||||
console.log("Uglified:", sum.output, "bytes");
|
||||
console.log("GZipped: ", sum.gzip, "bytes");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,15 +65,21 @@ urls.forEach(function(url) {
|
||||
results[url] = {
|
||||
input: 0,
|
||||
output: 0,
|
||||
gzip: 0,
|
||||
log: ""
|
||||
};
|
||||
require(url.slice(0, url.indexOf(":"))).get(url, function(res) {
|
||||
fetch(url, function(err, res) {
|
||||
if (err) throw err;
|
||||
var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
|
||||
res.on("data", function(data) {
|
||||
results[url].input += data.length;
|
||||
}).pipe(uglifyjs.stdin);
|
||||
uglifyjs.stdout.on("data", function(data) {
|
||||
results[url].output += data.length;
|
||||
}).pipe(zlib.createGzip({
|
||||
level: zlib.Z_BEST_COMPRESSION
|
||||
})).on("data", function(data) {
|
||||
results[url].gzip += data.length;
|
||||
}).pipe(createHash("sha1")).on("data", function(data) {
|
||||
results[url].sha1 = data.toString("hex");
|
||||
done();
|
||||
|
||||
239
test/compress/arguments.js
Normal file
239
test/compress/arguments.js
Normal file
@@ -0,0 +1,239 @@
|
||||
replace_index: {
|
||||
options = {
|
||||
arguments: true,
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var arguments = [];
|
||||
console.log(arguments[0]);
|
||||
(function() {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function(a, b) {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function(arguments) {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function() {
|
||||
var arguments;
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect: {
|
||||
var arguments = [];
|
||||
console.log(arguments[0]);
|
||||
(function() {
|
||||
console.log(arguments[1], arguments[1], arguments.foo);
|
||||
})("bar", 42);
|
||||
(function(a, b) {
|
||||
console.log(b, b, arguments.foo);
|
||||
})("bar", 42);
|
||||
(function(arguments) {
|
||||
console.log(arguments[1], arguments[1], arguments.foo);
|
||||
})("bar", 42);
|
||||
(function() {
|
||||
var arguments;
|
||||
console.log(arguments[1], arguments[1], arguments.foo);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect_stdout: [
|
||||
"undefined",
|
||||
"42 42 undefined",
|
||||
"42 42 undefined",
|
||||
"a a undefined",
|
||||
"42 42 undefined",
|
||||
]
|
||||
}
|
||||
|
||||
replace_index_strict: {
|
||||
options = {
|
||||
arguments: true,
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
(function() {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function(a, b) {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
(function() {
|
||||
console.log(arguments[1], arguments[1], arguments.foo);
|
||||
})("bar", 42);
|
||||
(function(a, b) {
|
||||
console.log(b, b, arguments.foo);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect_stdout: [
|
||||
"42 42 undefined",
|
||||
"42 42 undefined",
|
||||
]
|
||||
}
|
||||
|
||||
replace_index_keep_fargs: {
|
||||
options = {
|
||||
arguments: true,
|
||||
evaluate: true,
|
||||
keep_fargs: false,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var arguments = [];
|
||||
console.log(arguments[0]);
|
||||
(function() {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function(a, b) {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function(arguments) {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function() {
|
||||
var arguments;
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect: {
|
||||
var arguments = [];
|
||||
console.log(arguments[0]);
|
||||
(function(argument_0, argument_1) {
|
||||
console.log(argument_1, argument_1, arguments.foo);
|
||||
})("bar", 42);
|
||||
(function(a, b) {
|
||||
console.log(b, b, arguments.foo);
|
||||
})("bar", 42);
|
||||
(function(arguments) {
|
||||
console.log(arguments[1], arguments[1], arguments.foo);
|
||||
})("bar", 42);
|
||||
(function() {
|
||||
var arguments;
|
||||
console.log(arguments[1], arguments[1], arguments.foo);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect_stdout: [
|
||||
"undefined",
|
||||
"42 42 undefined",
|
||||
"42 42 undefined",
|
||||
"a a undefined",
|
||||
"42 42 undefined",
|
||||
]
|
||||
}
|
||||
|
||||
replace_index_keep_fargs_strict: {
|
||||
options = {
|
||||
arguments: true,
|
||||
evaluate: true,
|
||||
keep_fargs: false,
|
||||
properties: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
(function() {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
(function(a, b) {
|
||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
(function(argument_0, argument_1) {
|
||||
console.log(argument_1, argument_1, arguments.foo);
|
||||
})("bar", 42);
|
||||
(function(a, b) {
|
||||
console.log(b, b, arguments.foo);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect_stdout: [
|
||||
"42 42 undefined",
|
||||
"42 42 undefined",
|
||||
]
|
||||
}
|
||||
|
||||
modified: {
|
||||
options = {
|
||||
arguments: true,
|
||||
}
|
||||
input: {
|
||||
(function(a, b) {
|
||||
var c = arguments[0];
|
||||
var d = arguments[1];
|
||||
var a = "foo";
|
||||
b++;
|
||||
arguments[0] = "moo";
|
||||
arguments[1] *= 2;
|
||||
console.log(a, b, c, d, arguments[0], arguments[1]);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect: {
|
||||
(function(a, b) {
|
||||
var c = a;
|
||||
var d = b;
|
||||
var a = "foo";
|
||||
b++;
|
||||
a = "moo";
|
||||
b *= 2;
|
||||
console.log(a, b, c, d, a, b);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect_stdout: "moo 86 bar 42 moo 86"
|
||||
}
|
||||
|
||||
modified_strict: {
|
||||
options = {
|
||||
arguments: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
(function(a, b) {
|
||||
var c = arguments[0];
|
||||
var d = arguments[1];
|
||||
var a = "foo";
|
||||
b++;
|
||||
arguments[0] = "moo";
|
||||
arguments[1] *= 2;
|
||||
console.log(a, b, c, d, arguments[0], arguments[1]);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
(function(a, b) {
|
||||
var c = arguments[0];
|
||||
var d = arguments[1];
|
||||
var a = "foo";
|
||||
b++;
|
||||
arguments[0] = "moo";
|
||||
arguments[1] *= 2;
|
||||
console.log(a, b, c, d, arguments[0], arguments[1]);
|
||||
})("bar", 42);
|
||||
}
|
||||
expect_stdout: "foo 43 bar 42 moo 84"
|
||||
}
|
||||
|
||||
duplicate_argname: {
|
||||
options = {
|
||||
arguments: true,
|
||||
}
|
||||
input: {
|
||||
(function(a, b, a) {
|
||||
console.log(a, b, arguments[0], arguments[1], arguments[2]);
|
||||
})("foo", 42, "bar");
|
||||
}
|
||||
expect: {
|
||||
(function(a, b, a) {
|
||||
console.log(a, b, arguments[0], b, a);
|
||||
})("foo", 42, "bar");
|
||||
}
|
||||
expect_stdout: "bar 42 foo 42 bar"
|
||||
}
|
||||
@@ -15,9 +15,9 @@ holes_and_undefined: {
|
||||
|
||||
constant_join: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
evaluate : true
|
||||
};
|
||||
}
|
||||
input: {
|
||||
var a = [ "foo", "bar", "baz" ].join("");
|
||||
var a1 = [ "foo", "bar", "baz" ].join();
|
||||
@@ -64,9 +64,9 @@ constant_join: {
|
||||
|
||||
constant_join_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
evaluate : true
|
||||
};
|
||||
}
|
||||
input: {
|
||||
var a = [ "foo", "bar", boo(), "baz", "x", "y" ].join("");
|
||||
var b = [ "foo", "bar", boo(), "baz", "x", "y" ].join("-");
|
||||
@@ -93,9 +93,9 @@ constant_join_2: {
|
||||
|
||||
constant_join_3: {
|
||||
options = {
|
||||
unsafe: true,
|
||||
evaluate: true,
|
||||
};
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var a = [ null ].join();
|
||||
var b = [ , ].join();
|
||||
@@ -128,50 +128,114 @@ constant_join_3: {
|
||||
|
||||
for_loop: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
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]);
|
||||
var b = 0;
|
||||
for (var i = 0; i < a.length; i++)
|
||||
b += a[i];
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
function f1() {
|
||||
var a = [1, 2, 3];
|
||||
for (var i = 0, len = a.length; i < len; i++) {
|
||||
console.log(a[i]);
|
||||
var b = 0;
|
||||
for (var i = 0, len = a.length; i < len; i++)
|
||||
b += a[i];
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
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]++;
|
||||
return a[2];
|
||||
}
|
||||
console.log(f0(), f1(), f2());
|
||||
}
|
||||
expect: {
|
||||
function f0() {
|
||||
var a = [1, 2, 3];
|
||||
var b = 0;
|
||||
for (var i = 0; i < 3; i++)
|
||||
b += a[i];
|
||||
return b;
|
||||
}
|
||||
function f1() {
|
||||
var a = [1, 2, 3];
|
||||
var b = 0;
|
||||
for (var i = 0; i < 3; i++)
|
||||
b += a[i];
|
||||
return b;
|
||||
}
|
||||
function f2() {
|
||||
var a = [1, 2, 3];
|
||||
for (var i = 0; i < a.length; i++)
|
||||
a[i]++;
|
||||
return a[2];
|
||||
}
|
||||
console.log(f0(), f1(), f2());
|
||||
}
|
||||
expect_stdout: "6 6 4"
|
||||
}
|
||||
|
||||
index: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = [ 1, 2 ];
|
||||
console.log(a[0], a[1]);
|
||||
}
|
||||
expect: {
|
||||
console.log(1, 2);
|
||||
}
|
||||
expect_stdout: "1 2"
|
||||
}
|
||||
|
||||
length: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = [ 1, 2 ];
|
||||
console.log(a.length);
|
||||
}
|
||||
expect: {
|
||||
console.log(2);
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
index_length: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = [ 1, 2 ];
|
||||
console.log(a[0], a.length);
|
||||
}
|
||||
expect: {
|
||||
console.log(1, 2);
|
||||
}
|
||||
expect_stdout: "1 2"
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ ascii_only_true: {
|
||||
"\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\'}'
|
||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\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: {
|
||||
@@ -31,5 +31,5 @@ ascii_only_false: {
|
||||
"\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\'}'
|
||||
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\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\'}'
|
||||
}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
asm_mixed: {
|
||||
options = {
|
||||
sequences : true,
|
||||
properties : true,
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: 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,
|
||||
keep_fargs: true,
|
||||
keep_fnames: false,
|
||||
loops: true,
|
||||
negate_iife: true,
|
||||
properties: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
negate_iife : true
|
||||
};
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
// adapted from http://asmjs.org/spec/latest/
|
||||
function asm_GeometricMean(stdlib, foreign, buffer) {
|
||||
@@ -104,3 +103,65 @@ asm_mixed: {
|
||||
}
|
||||
}
|
||||
|
||||
asm_toplevel: {
|
||||
options = {}
|
||||
input: {
|
||||
"use asm";
|
||||
0.0;
|
||||
function f() {
|
||||
0.0;
|
||||
(function(){
|
||||
0.0;
|
||||
});
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '"use asm";0.0;function f(){0.0;(function(){0.0})}0.0;'
|
||||
}
|
||||
|
||||
asm_function_expression: {
|
||||
options = {}
|
||||
input: {
|
||||
0.0;
|
||||
var a = function() {
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
function f() {
|
||||
0.0;
|
||||
return function(){
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '0;var a=function(){"use asm";0.0};function f(){0;return function(){"use asm";0.0};0}0;'
|
||||
}
|
||||
|
||||
asm_nested_functions: {
|
||||
options = {}
|
||||
input: {
|
||||
0.0;
|
||||
function a() {
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
function b() {
|
||||
0.0;
|
||||
function c(){
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
function d(){
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,62 +1,42 @@
|
||||
keep_comparisons: {
|
||||
comparisons: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
unsafe_comps: false
|
||||
}
|
||||
input: {
|
||||
var obj1 = {
|
||||
valueOf: function() {triggeredFirst();}
|
||||
}
|
||||
var obj2 = {
|
||||
valueOf: function() {triggeredSecond();}
|
||||
}
|
||||
var obj1, obj2;
|
||||
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 obj1, obj2;
|
||||
var result1 = obj1 <= obj2;
|
||||
var result2 = obj1 < obj2;
|
||||
var result3 = obj1 >= obj2;
|
||||
var result4 = obj1 > obj2;
|
||||
var result3 = obj2 <= obj1;
|
||||
var result4 = obj2 < obj1;
|
||||
}
|
||||
}
|
||||
|
||||
keep_comparisons_with_unsafe_comps: {
|
||||
unsafe_comps: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
unsafe_comps: true
|
||||
conditionals: 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;
|
||||
var obj1, obj2;
|
||||
obj1 <= obj2 ? f1() : g1();
|
||||
obj1 < obj2 ? f2() : g2();
|
||||
obj1 >= obj2 ? f3() : g3();
|
||||
obj1 > obj2 ? f4() : g4();
|
||||
}
|
||||
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;
|
||||
var obj1, obj2;
|
||||
obj2 < obj1 ? g1() : f1();
|
||||
obj1 < obj2 ? f2() : g2();
|
||||
obj1 < obj2 ? g3() : f3();
|
||||
obj2 < obj1 ? f4() : g4();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,3 +54,272 @@ dont_change_in_or_instanceof_expressions: {
|
||||
null instanceof null;
|
||||
}
|
||||
}
|
||||
|
||||
self_comparison_1: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
a === a;
|
||||
a !== b;
|
||||
b.c === a.c;
|
||||
b.c !== b.c;
|
||||
}
|
||||
expect: {
|
||||
a == a;
|
||||
a !== b;
|
||||
b.c === a.c;
|
||||
b.c != b.c;
|
||||
}
|
||||
}
|
||||
|
||||
self_comparison_2: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
function f() {}
|
||||
var o = {};
|
||||
console.log(f != f, o === o);
|
||||
}
|
||||
expect: {
|
||||
function f() {}
|
||||
var o = {};
|
||||
console.log(false, true);
|
||||
}
|
||||
expect_stdout: "false true"
|
||||
}
|
||||
|
||||
issue_2857_1: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
function f1(a) {
|
||||
a === undefined || a === null;
|
||||
a === undefined || a !== null;
|
||||
a !== undefined || a === null;
|
||||
a !== undefined || a !== null;
|
||||
a === undefined && a === null;
|
||||
a === undefined && a !== null;
|
||||
a !== undefined && a === null;
|
||||
a !== undefined && a !== null;
|
||||
}
|
||||
function f2(a) {
|
||||
a === null || a === undefined;
|
||||
a === null || a !== undefined;
|
||||
a !== null || a === undefined;
|
||||
a !== null || a !== undefined;
|
||||
a === null && a === undefined;
|
||||
a === null && a !== undefined;
|
||||
a !== null && a === undefined;
|
||||
a !== null && a !== undefined;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1(a) {
|
||||
null == a;
|
||||
void 0 === a || null !== a;
|
||||
void 0 !== a || null === a;
|
||||
void 0 !== a || null !== a;
|
||||
void 0 === a && null === a;
|
||||
void 0 === a && null !== a;
|
||||
void 0 !== a && null === a;
|
||||
null != a;
|
||||
}
|
||||
function f2(a) {
|
||||
null == a;
|
||||
null === a || void 0 !== a;
|
||||
null !== a || void 0 === a;
|
||||
null !== a || void 0 !== a;
|
||||
null === a && void 0 === a;
|
||||
null === a && void 0 !== a;
|
||||
null !== a && void 0 === a;
|
||||
null != a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2857_2: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, p) {
|
||||
a === undefined || a === null || p;
|
||||
a === undefined || a !== null || p;
|
||||
a !== undefined || a === null || p;
|
||||
a !== undefined || a !== null || p;
|
||||
a === undefined && a === null || p;
|
||||
a === undefined && a !== null || p;
|
||||
a !== undefined && a === null || p;
|
||||
a !== undefined && a !== null || p;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a, p) {
|
||||
null == a || p;
|
||||
void 0 === a || null !== a || p;
|
||||
void 0 !== a || null === a || p;
|
||||
void 0 !== a || null !== a || p;
|
||||
void 0 === a && null === a || p;
|
||||
void 0 === a && null !== a || p;
|
||||
void 0 !== a && null === a || p;
|
||||
null != a || p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2857_3: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, p) {
|
||||
a === undefined || a === null && p;
|
||||
a === undefined || a !== null && p;
|
||||
a !== undefined || a === null && p;
|
||||
a !== undefined || a !== null && p;
|
||||
a === undefined && a === null && p;
|
||||
a === undefined && a !== null && p;
|
||||
a !== undefined && a === null && p;
|
||||
a !== undefined && a !== null && p;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a, p) {
|
||||
void 0 === a || null === a && p;
|
||||
void 0 === a || null !== a && p;
|
||||
void 0 !== a || null === a && p;
|
||||
void 0 !== a || null !== a && p;
|
||||
void 0 === a && null === a && p;
|
||||
void 0 === a && null !== a && p;
|
||||
void 0 !== a && null === a && p;
|
||||
null != a && p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2857_4: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, p) {
|
||||
p || a === undefined || a === null;
|
||||
p || a === undefined || a !== null;
|
||||
p || a !== undefined || a === null;
|
||||
p || a !== undefined || a !== null;
|
||||
p || a === undefined && a === null;
|
||||
p || a === undefined && a !== null;
|
||||
p || a !== undefined && a === null;
|
||||
p || a !== undefined && a !== null;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a, p) {
|
||||
p || null == a;
|
||||
p || void 0 === a || null !== a;
|
||||
p || void 0 !== a || null === a;
|
||||
p || void 0 !== a || null !== a;
|
||||
p || void 0 === a && null === a;
|
||||
p || void 0 === a && null !== a;
|
||||
p || void 0 !== a && null === a;
|
||||
p || null != a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2857_5: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, p) {
|
||||
p && a === undefined || a === null;
|
||||
p && a === undefined || a !== null;
|
||||
p && a !== undefined || a === null;
|
||||
p && a !== undefined || a !== null;
|
||||
p && a === undefined && a === null;
|
||||
p && a === undefined && a !== null;
|
||||
p && a !== undefined && a === null;
|
||||
p && a !== undefined && a !== null;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a, p) {
|
||||
p && void 0 === a || null === a;
|
||||
p && void 0 === a || null !== a;
|
||||
p && void 0 !== a || null === a;
|
||||
p && void 0 !== a || null !== a;
|
||||
p && void 0 === a && null === a;
|
||||
p && void 0 === a && null !== a;
|
||||
p && void 0 !== a && null === a;
|
||||
p && null != a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2857_6: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
if (({}).b === undefined || {}.b === null)
|
||||
return a.b !== undefined && a.b !== null;
|
||||
}
|
||||
console.log(f({
|
||||
a: [ null ],
|
||||
get b() {
|
||||
return this.a.shift();
|
||||
}
|
||||
}));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
if (null == {}.b)
|
||||
return void 0 !== a.b && null !== a.b;
|
||||
}
|
||||
console.log(f({
|
||||
a: [ null ],
|
||||
get b() {
|
||||
return this.a.shift();
|
||||
}
|
||||
}));
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
is_boolean_unsafe: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(/foo/.test("bar") === [].isPrototypeOf({}));
|
||||
}
|
||||
expect: {
|
||||
console.log(/foo/.test("bar") == [].isPrototypeOf({}));
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
is_number_unsafe: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(Math.acos(42) !== "foo".charCodeAt(4));
|
||||
}
|
||||
expect: {
|
||||
console.log(Math.acos(42) != "foo".charCodeAt(4));
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
concat_1: {
|
||||
options = {
|
||||
evaluate: true
|
||||
};
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var a = "foo" + "bar" + x() + "moo" + "foo" + y() + "x" + "y" + "z" + q();
|
||||
var b = "foo" + 1 + x() + 2 + "boo";
|
||||
@@ -21,12 +21,12 @@ concat_1: {
|
||||
var c = 1 + x() + 2 + "boo";
|
||||
var d = 1 + x() + 2 + 3 + "boo";
|
||||
var e = 1 + x() + 2 + "X3boo";
|
||||
var f = "\x00360\08\0";
|
||||
var f = "\x00360\x008\0";
|
||||
}
|
||||
}
|
||||
|
||||
concat_2: {
|
||||
options = {};
|
||||
options = {}
|
||||
input: {
|
||||
console.log(
|
||||
1 + (2 + 3),
|
||||
@@ -55,7 +55,7 @@ concat_2: {
|
||||
}
|
||||
|
||||
concat_3: {
|
||||
options = {};
|
||||
options = {}
|
||||
input: {
|
||||
console.log(
|
||||
1 + 2 + (3 + 4 + 5),
|
||||
@@ -84,7 +84,7 @@ concat_3: {
|
||||
}
|
||||
|
||||
concat_4: {
|
||||
options = {};
|
||||
options = {}
|
||||
input: {
|
||||
console.log(
|
||||
1 + "2" + (3 + 4 + 5),
|
||||
@@ -113,7 +113,7 @@ concat_4: {
|
||||
}
|
||||
|
||||
concat_5: {
|
||||
options = {};
|
||||
options = {}
|
||||
input: {
|
||||
console.log(
|
||||
"1" + 2 + (3 + 4 + 5),
|
||||
@@ -142,7 +142,7 @@ concat_5: {
|
||||
}
|
||||
|
||||
concat_6: {
|
||||
options = {};
|
||||
options = {}
|
||||
input: {
|
||||
console.log(
|
||||
"1" + "2" + (3 + 4 + 5),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
ifs_1: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
if (foo) bar();
|
||||
if (!foo); else bar();
|
||||
@@ -18,8 +18,8 @@ ifs_1: {
|
||||
|
||||
ifs_2: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
if (foo) {
|
||||
x();
|
||||
@@ -47,12 +47,12 @@ ifs_2: {
|
||||
|
||||
ifs_3_should_warn: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
booleans : true,
|
||||
side_effects: true,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
var x, y;
|
||||
if (x && !(x + "1") && y) { // 1
|
||||
@@ -78,8 +78,8 @@ ifs_3_should_warn: {
|
||||
|
||||
ifs_4: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
if (foo && bar) {
|
||||
x(foo)[10].bar.baz = something();
|
||||
@@ -95,10 +95,10 @@ ifs_4: {
|
||||
|
||||
ifs_5: {
|
||||
options = {
|
||||
if_return: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
};
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
if (foo) return;
|
||||
@@ -132,9 +132,9 @@ ifs_5: {
|
||||
|
||||
ifs_6: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
comparisons: true
|
||||
};
|
||||
}
|
||||
input: {
|
||||
var x, y;
|
||||
if (!foo && !bar && !baz && !boo) {
|
||||
@@ -163,50 +163,54 @@ ifs_6: {
|
||||
|
||||
cond_1: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var do_something; // if undeclared it's assumed to have side-effects
|
||||
if (some_condition()) {
|
||||
function foo(do_something, some_condition) {
|
||||
if (some_condition) {
|
||||
do_something(x);
|
||||
} else {
|
||||
do_something(y);
|
||||
}
|
||||
if (some_condition()) {
|
||||
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);
|
||||
function foo(do_something, some_condition) {
|
||||
do_something(some_condition ? x : y);
|
||||
some_condition ? side_effects(x) : side_effects(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cond_2: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var x, FooBar;
|
||||
if (some_condition()) {
|
||||
function foo(x, FooBar, some_condition) {
|
||||
if (some_condition) {
|
||||
x = new FooBar(1);
|
||||
} else {
|
||||
x = new FooBar(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var x, FooBar;
|
||||
x = new FooBar(some_condition() ? 1 : 2);
|
||||
function foo(x, FooBar, some_condition) {
|
||||
x = new FooBar(some_condition ? 1 : 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cond_3: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var FooBar;
|
||||
if (some_condition()) {
|
||||
@@ -223,8 +227,8 @@ cond_3: {
|
||||
|
||||
cond_4: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var do_something;
|
||||
if (some_condition()) {
|
||||
@@ -247,8 +251,8 @@ cond_4: {
|
||||
|
||||
cond_5: {
|
||||
options = {
|
||||
conditionals: true
|
||||
};
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
if (some_condition()) {
|
||||
if (some_other_condition()) {
|
||||
@@ -277,7 +281,7 @@ cond_7: {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
var x, y, z, a, b;
|
||||
// compress these
|
||||
@@ -328,7 +332,7 @@ cond_7: {
|
||||
x = 'foo';
|
||||
x = 'foo';
|
||||
x = (condition(), 20);
|
||||
x = z ? 'fuji' : (condition(), 'fuji');
|
||||
x = (z || condition(), 'fuji');
|
||||
x = (condition(), 'foobar');
|
||||
x = y ? a : b;
|
||||
x = y ? 'foo' : 'fo';
|
||||
@@ -338,8 +342,8 @@ cond_7: {
|
||||
cond_7_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true
|
||||
};
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var x;
|
||||
// access to global should be assumed to have side effects
|
||||
@@ -357,10 +361,10 @@ cond_7_1: {
|
||||
|
||||
cond_8: {
|
||||
options = {
|
||||
booleans: false,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
booleans : false
|
||||
};
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
// compress these
|
||||
@@ -441,10 +445,10 @@ cond_8: {
|
||||
|
||||
cond_8b: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
booleans : true
|
||||
};
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
// compress these
|
||||
@@ -524,10 +528,10 @@ cond_8b: {
|
||||
|
||||
cond_8c: {
|
||||
options = {
|
||||
booleans: false,
|
||||
conditionals: true,
|
||||
evaluate: false,
|
||||
booleans : false
|
||||
};
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
// compress these
|
||||
@@ -605,11 +609,59 @@ cond_8c: {
|
||||
}
|
||||
}
|
||||
|
||||
cond_9: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y) {
|
||||
g() ? x(1) : x(2);
|
||||
x ? (y || x)() : (y || x)();
|
||||
x ? y(a, b) : y(d, b, c);
|
||||
x ? y(a, b, c) : y(a, b, c);
|
||||
x ? y(a, b, c) : y(a, b, f);
|
||||
x ? y(a, b, c) : y(a, e, c);
|
||||
x ? y(a, b, c) : y(a, e, f);
|
||||
x ? y(a, b, c) : y(d, b, c);
|
||||
x ? y(a, b, c) : y(d, b, f);
|
||||
x ? y(a, b, c) : y(d, e, c);
|
||||
x ? y(a, b, c) : y(d, e, f);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x, y) {
|
||||
g() ? x(1) : x(2);
|
||||
x, (y || x)();
|
||||
x ? y(a, b) : y(d, b, c);
|
||||
x, y(a, b, c);
|
||||
y(a, b, x ? c : f);
|
||||
y(a, x ? b : e, c);
|
||||
x ? y(a, b, c) : y(a, e, f);
|
||||
y(x ? a : d, b, c);
|
||||
x ? y(a, b, c) : y(d, b, f);
|
||||
x ? y(a, b, c) : y(d, e, c);
|
||||
x ? y(a, b, c) : y(d, e, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
booleans: true,
|
||||
collapse_vars: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: true,
|
||||
loops: true,
|
||||
properties: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1() { return a == b ? true : x; }
|
||||
@@ -635,9 +687,21 @@ ternary_boolean_consequent: {
|
||||
|
||||
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
|
||||
booleans: true,
|
||||
collapse_vars: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: true,
|
||||
loops: true,
|
||||
properties: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1() { return a == b ? x : true; }
|
||||
@@ -663,10 +727,11 @@ ternary_boolean_alternative: {
|
||||
|
||||
trivial_boolean_ternary_expressions : {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
booleans : true
|
||||
};
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
f('foo' in m ? true : false);
|
||||
f('foo' in m ? false : true);
|
||||
@@ -737,11 +802,11 @@ trivial_boolean_ternary_expressions : {
|
||||
|
||||
issue_1154: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
booleans : true,
|
||||
side_effects: true,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
function f1(x) { return x ? -1 : -1; }
|
||||
function f2(x) { return x ? +2 : +2; }
|
||||
@@ -1015,3 +1080,215 @@ delete_conditional_2: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2535_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
passes: 2,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
if (true || x()) y();
|
||||
if (true && x()) y();
|
||||
if (x() || true) y();
|
||||
if (x() && true) y();
|
||||
if (false || x()) y();
|
||||
if (false && x()) y();
|
||||
if (x() || false) y();
|
||||
if (x() && false) y();
|
||||
}
|
||||
expect: {
|
||||
y();
|
||||
x() && y();
|
||||
(x(), 1) && y();
|
||||
x() && y();
|
||||
x() && y();
|
||||
x() && y();
|
||||
(x(), 0) && y();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2535_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function x() {}
|
||||
function y() {
|
||||
return "foo";
|
||||
}
|
||||
console.log((x() || true) || y());
|
||||
console.log((y() || true) || x());
|
||||
console.log((x() || true) && y());
|
||||
console.log((y() || true) && x());
|
||||
console.log((x() && true) || y());
|
||||
console.log((y() && true) || x());
|
||||
console.log((x() && true) && y());
|
||||
console.log((y() && true) && x());
|
||||
console.log((x() || false) || y());
|
||||
console.log((y() || false) || x());
|
||||
console.log((x() || false) && y());
|
||||
console.log((y() || false) && x());
|
||||
console.log((x() && false) || y());
|
||||
console.log((y() && false) || x());
|
||||
console.log((x() && false) && y());
|
||||
console.log((y() && false) && x());
|
||||
}
|
||||
expect: {
|
||||
function x() {}
|
||||
function y() {
|
||||
return "foo";
|
||||
}
|
||||
console.log(x() || !0);
|
||||
console.log(y() || !0);
|
||||
console.log((x(), y()));
|
||||
console.log((y(), x()));
|
||||
console.log(!!x() || y());
|
||||
console.log(!!y() || x());
|
||||
console.log(x() && y());
|
||||
console.log(y() && x());
|
||||
console.log(x() || y());
|
||||
console.log(y() || x());
|
||||
console.log(!!x() && y());
|
||||
console.log(!!y() && x());
|
||||
console.log((x(), y()));
|
||||
console.log((y(), x()));
|
||||
console.log(x() && !1);
|
||||
console.log(y() && !1);
|
||||
}
|
||||
expect_stdout: [
|
||||
"true",
|
||||
"foo",
|
||||
"foo",
|
||||
"undefined",
|
||||
"foo",
|
||||
"true",
|
||||
"undefined",
|
||||
"undefined",
|
||||
"foo",
|
||||
"foo",
|
||||
"false",
|
||||
"undefined",
|
||||
"foo",
|
||||
"undefined",
|
||||
"undefined",
|
||||
"false",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2560: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function log(x) {
|
||||
console.log(x);
|
||||
}
|
||||
function foo() {
|
||||
return log;
|
||||
}
|
||||
function bar() {
|
||||
if (x !== (x = foo())) {
|
||||
x(1);
|
||||
} else {
|
||||
x(2);
|
||||
}
|
||||
}
|
||||
var x = function() {
|
||||
console.log("init");
|
||||
};
|
||||
bar();
|
||||
bar();
|
||||
}
|
||||
expect: {
|
||||
function log(x) {
|
||||
console.log(x);
|
||||
}
|
||||
function bar() {
|
||||
x !== (x = log) ? x(1) : x(2);
|
||||
}
|
||||
var x = function() {
|
||||
console.log("init");
|
||||
};
|
||||
bar();
|
||||
bar();
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
hoist_decl: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
join_vars: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
if (x()) {
|
||||
var a;
|
||||
y();
|
||||
} else {
|
||||
z();
|
||||
var b;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a, b;
|
||||
x() ? y() : z();
|
||||
}
|
||||
}
|
||||
|
||||
to_and_or: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var values = [
|
||||
0,
|
||||
null,
|
||||
true,
|
||||
"foo",
|
||||
false,
|
||||
-1 / 0,
|
||||
void 0,
|
||||
];
|
||||
values.forEach(function(x) {
|
||||
values.forEach(function(y) {
|
||||
values.forEach(function(z) {
|
||||
console.log(x ? y || z : z);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var values = [
|
||||
0,
|
||||
null,
|
||||
true,
|
||||
"foo",
|
||||
false,
|
||||
-1 / 0,
|
||||
void 0,
|
||||
];
|
||||
values.forEach(function(x) {
|
||||
values.forEach(function(y) {
|
||||
values.forEach(function(z) {
|
||||
console.log(x && y || z);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
dead_code_1: {
|
||||
options = {
|
||||
dead_code: true
|
||||
};
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
a();
|
||||
@@ -25,13 +25,13 @@ dead_code_1: {
|
||||
|
||||
dead_code_2_should_warn: {
|
||||
options = {
|
||||
dead_code: true
|
||||
};
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
g();
|
||||
x = 10;
|
||||
throw "foo";
|
||||
throw new Error("foo");
|
||||
// completely discarding the `if` would introduce some
|
||||
// bugs. UglifyJS v1 doesn't deal with this issue; in v2
|
||||
// we copy any declarations to the upper scope.
|
||||
@@ -46,27 +46,31 @@ dead_code_2_should_warn: {
|
||||
})();
|
||||
}
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
g();
|
||||
x = 10;
|
||||
throw "foo";
|
||||
throw new Error("foo");
|
||||
var x;
|
||||
function g(){};
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: "<=4"
|
||||
}
|
||||
|
||||
dead_code_constant_boolean_should_warn_more: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
side_effects: true,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
while (!((foo && bar) || (x + "0"))) {
|
||||
console.log("unreachable");
|
||||
@@ -78,16 +82,19 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
foo();
|
||||
var moo;
|
||||
}
|
||||
bar();
|
||||
}
|
||||
expect: {
|
||||
var foo;
|
||||
function bar() {}
|
||||
// nothing for the while
|
||||
// as for the for, it should keep:
|
||||
var x = 10, y;
|
||||
var moo;
|
||||
var x = 10, y;
|
||||
bar();
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: "<=4"
|
||||
}
|
||||
|
||||
try_catch_finally: {
|
||||
@@ -95,6 +102,8 @@ try_catch_finally: {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
passes: 2,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
@@ -147,3 +156,789 @@ accessor: {
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Array.isArray;
|
||||
Boolean;
|
||||
console.log;
|
||||
Date;
|
||||
decodeURI;
|
||||
decodeURIComponent;
|
||||
encodeURI;
|
||||
encodeURIComponent;
|
||||
Error.name;
|
||||
escape;
|
||||
eval;
|
||||
EvalError;
|
||||
Function.length;
|
||||
isFinite;
|
||||
isNaN;
|
||||
JSON;
|
||||
Math.random;
|
||||
Number.isNaN;
|
||||
parseFloat;
|
||||
parseInt;
|
||||
RegExp;
|
||||
Object.defineProperty;
|
||||
String.fromCharCode;
|
||||
RangeError;
|
||||
ReferenceError;
|
||||
SyntaxError;
|
||||
TypeError;
|
||||
unescape;
|
||||
URIError;
|
||||
}
|
||||
expect: {}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
global_timeout_and_interval_symbols: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
// These global symbols do not exist in the test sandbox
|
||||
// and must be tested separately.
|
||||
clearInterval;
|
||||
clearTimeout;
|
||||
setInterval;
|
||||
setTimeout;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2233_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var RegExp;
|
||||
Array.isArray;
|
||||
RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Math.sin;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2233_3: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var RegExp;
|
||||
Array.isArray;
|
||||
RegExp;
|
||||
UndeclaredGlobal;
|
||||
function foo() {
|
||||
var Number;
|
||||
AnotherUndeclaredGlobal;
|
||||
Math.sin;
|
||||
Number.isNaN;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
UndeclaredGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
global_fns: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
Boolean(1, 2);
|
||||
decodeURI(1, 2);
|
||||
decodeURIComponent(1, 2);
|
||||
Date(1, 2);
|
||||
encodeURI(1, 2);
|
||||
encodeURIComponent(1, 2);
|
||||
Error(1, 2);
|
||||
escape(1, 2);
|
||||
EvalError(1, 2);
|
||||
isFinite(1, 2);
|
||||
isNaN(1, 2);
|
||||
Number(1, 2);
|
||||
Object(1, 2);
|
||||
parseFloat(1, 2);
|
||||
parseInt(1, 2);
|
||||
RangeError(1, 2);
|
||||
ReferenceError(1, 2);
|
||||
String(1, 2);
|
||||
SyntaxError(1, 2);
|
||||
TypeError(1, 2);
|
||||
unescape(1, 2);
|
||||
URIError(1, 2);
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
Function(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
RegExp(1, 2);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
try {
|
||||
Array(NaN);
|
||||
} catch (e) {
|
||||
console.log(e.name);
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"SyntaxError",
|
||||
"SyntaxError",
|
||||
"RangeError",
|
||||
]
|
||||
}
|
||||
|
||||
collapse_vars_assignment: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
dead_code: true,
|
||||
passes: 2,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f0(c) {
|
||||
var a = 3 / c;
|
||||
return a = a;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f0(c) {
|
||||
return 3 / c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collapse_vars_lvalues_drop_assign: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
dead_code: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f0(x) { var i = ++x; return x += i; }
|
||||
function f1(x) { var a = (x -= 3); return x += a; }
|
||||
function f2(x) { var z = x, a = ++z; return z += a; }
|
||||
}
|
||||
expect: {
|
||||
function f0(x) { var i = ++x; return x + i; }
|
||||
function f1(x) { var a = (x -= 3); return x + a; }
|
||||
function f2(x) { var z = x, a = ++z; return z + a; }
|
||||
}
|
||||
}
|
||||
|
||||
collapse_vars_misc1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
dead_code: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f10(x) { var a = 5, b = 3; return a += b; }
|
||||
function f11(x) { var a = 5, b = 3; return a += --b; }
|
||||
}
|
||||
expect: {
|
||||
function f10(x) { return 5 + 3; }
|
||||
function f11(x) { var b = 3; return 5 + --b; }
|
||||
}
|
||||
}
|
||||
|
||||
return_assignment: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1(a, b, c) {
|
||||
return a = x(), b = y(), b = a && (c >>= 5);
|
||||
}
|
||||
function f2() {
|
||||
return e = x();
|
||||
}
|
||||
function f3(e) {
|
||||
return e = x();
|
||||
}
|
||||
function f4() {
|
||||
var e;
|
||||
return e = x();
|
||||
}
|
||||
function f5(a) {
|
||||
try {
|
||||
return a = x();
|
||||
} catch (b) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f6(a) {
|
||||
try {
|
||||
return a = x();
|
||||
} finally {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function y() {
|
||||
console.log("y");
|
||||
}
|
||||
function test(inc) {
|
||||
var counter = 0;
|
||||
x = function() {
|
||||
counter += inc;
|
||||
if (inc < 0) throw counter;
|
||||
return counter;
|
||||
};
|
||||
[ f1, f2, f3, f4, f5, f6 ].forEach(function(f, i) {
|
||||
e = null;
|
||||
try {
|
||||
i += 1;
|
||||
console.log("result " + f(10 * i, 100 * i, 1000 * i));
|
||||
} catch (x) {
|
||||
console.log("caught " + x);
|
||||
}
|
||||
if (null !== e) console.log("e: " + e);
|
||||
});
|
||||
}
|
||||
var x, e;
|
||||
test(1);
|
||||
test(-1);
|
||||
}
|
||||
expect: {
|
||||
function f1(a, b, c) {
|
||||
return a = x(), y(), a && (c >> 5);
|
||||
}
|
||||
function f2() {
|
||||
return e = x();
|
||||
}
|
||||
function f3(e) {
|
||||
return x();
|
||||
}
|
||||
function f4() {
|
||||
return x();
|
||||
}
|
||||
function f5(a) {
|
||||
try {
|
||||
return x();
|
||||
} catch (b) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f6(a) {
|
||||
try {
|
||||
return a = x();
|
||||
} finally {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function y() {
|
||||
console.log("y");
|
||||
}
|
||||
function test(inc) {
|
||||
var counter = 0;
|
||||
x = function() {
|
||||
counter += inc;
|
||||
if (inc < 0) throw counter;
|
||||
return counter;
|
||||
};
|
||||
[ f1, f2, f3, f4, f5, f6 ].forEach(function(f, i) {
|
||||
e = null;
|
||||
try {
|
||||
i += 1;
|
||||
console.log("result " + f(10 * i, 100 * i, 1000 * i));
|
||||
} catch (x) {
|
||||
console.log("caught " + x);
|
||||
}
|
||||
if (null !== e) console.log("e: " + e);
|
||||
});
|
||||
}
|
||||
var x, e;
|
||||
test(1);
|
||||
test(-1);
|
||||
}
|
||||
expect_stdout: [
|
||||
"y",
|
||||
"result 31",
|
||||
"result 2",
|
||||
"e: 2",
|
||||
"result 3",
|
||||
"result 4",
|
||||
"result 5",
|
||||
"6",
|
||||
"result 6",
|
||||
"caught -1",
|
||||
"caught -2",
|
||||
"caught -3",
|
||||
"caught -4",
|
||||
"50",
|
||||
"result undefined",
|
||||
"60",
|
||||
"caught -6",
|
||||
]
|
||||
}
|
||||
|
||||
throw_assignment: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
throw a = x();
|
||||
}
|
||||
function f2(a) {
|
||||
throw a = x();
|
||||
}
|
||||
function f3() {
|
||||
var a;
|
||||
throw a = x();
|
||||
}
|
||||
function f4() {
|
||||
try {
|
||||
throw a = x();
|
||||
} catch (b) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f5(a) {
|
||||
try {
|
||||
throw a = x();
|
||||
} catch (b) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f6() {
|
||||
var a;
|
||||
try {
|
||||
throw a = x();
|
||||
} catch (b) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f7() {
|
||||
try {
|
||||
throw a = x();
|
||||
} finally {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f8(a) {
|
||||
try {
|
||||
throw a = x();
|
||||
} finally {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f9() {
|
||||
var a;
|
||||
try {
|
||||
throw a = x();
|
||||
} finally {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function test(inc) {
|
||||
var counter = 0;
|
||||
x = function() {
|
||||
counter += inc;
|
||||
if (inc < 0) throw counter;
|
||||
return counter;
|
||||
};
|
||||
[ f1, f2, f3, f4, f5, f6, f7, f8, f9 ].forEach(function(f, i) {
|
||||
a = null;
|
||||
try {
|
||||
f(10 * (1 + i));
|
||||
} catch (x) {
|
||||
console.log("caught " + x);
|
||||
}
|
||||
if (null !== a) console.log("a: " + a);
|
||||
});
|
||||
}
|
||||
var x, a;
|
||||
test(1);
|
||||
test(-1);
|
||||
}
|
||||
expect: {
|
||||
function f1() {
|
||||
throw a = x();
|
||||
}
|
||||
function f2(a) {
|
||||
throw x();
|
||||
}
|
||||
function f3() {
|
||||
throw x();
|
||||
}
|
||||
function f4() {
|
||||
try {
|
||||
throw a = x();
|
||||
} catch (b) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f5(a) {
|
||||
try {
|
||||
throw a = x();
|
||||
} catch (b) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f6() {
|
||||
var a;
|
||||
try {
|
||||
throw a = x();
|
||||
} catch (b) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f7() {
|
||||
try {
|
||||
throw a = x();
|
||||
} finally {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f8(a) {
|
||||
try {
|
||||
throw a = x();
|
||||
} finally {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function f9() {
|
||||
var a;
|
||||
try {
|
||||
throw a = x();
|
||||
} finally {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
function test(inc) {
|
||||
var counter = 0;
|
||||
x = function() {
|
||||
counter += inc;
|
||||
if (inc < 0) throw counter;
|
||||
return counter;
|
||||
};
|
||||
[ f1, f2, f3, f4, f5, f6, f7, f8, f9 ].forEach(function(f, i) {
|
||||
a = null;
|
||||
try {
|
||||
f(10 * (1 + i));
|
||||
} catch (x) {
|
||||
console.log("caught " + x);
|
||||
}
|
||||
if (null !== a) console.log("a: " + a);
|
||||
});
|
||||
}
|
||||
var x, a;
|
||||
test(1);
|
||||
test(-1);
|
||||
}
|
||||
expect_stdout: [
|
||||
"caught 1",
|
||||
"a: 1",
|
||||
"caught 2",
|
||||
"caught 3",
|
||||
"4",
|
||||
"a: 4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"caught 7",
|
||||
"a: 7",
|
||||
"8",
|
||||
"caught 8",
|
||||
"9",
|
||||
"caught 9",
|
||||
"caught -1",
|
||||
"caught -2",
|
||||
"caught -3",
|
||||
"null",
|
||||
"50",
|
||||
"undefined",
|
||||
"null",
|
||||
"caught -7",
|
||||
"80",
|
||||
"caught -8",
|
||||
"undefined",
|
||||
"caught -9",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2597: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
function f(b) {
|
||||
try {
|
||||
try {
|
||||
throw "foo";
|
||||
} catch (e) {
|
||||
return b = true;
|
||||
}
|
||||
} finally {
|
||||
b && (a = "PASS");
|
||||
}
|
||||
}
|
||||
var a = "FAIL";
|
||||
f();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
function f(b) {
|
||||
try {
|
||||
try {
|
||||
throw "foo";
|
||||
} catch (e) {
|
||||
return b = true;
|
||||
}
|
||||
} finally {
|
||||
b && (a = "PASS");
|
||||
}
|
||||
}
|
||||
var a = "FAIL";
|
||||
f();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2666: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return a = {
|
||||
p: function() {
|
||||
return a;
|
||||
}
|
||||
};
|
||||
}
|
||||
console.log(typeof f().p());
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
return a = {
|
||||
p: function() {
|
||||
return a;
|
||||
}
|
||||
};
|
||||
}
|
||||
console.log(typeof f().p());
|
||||
}
|
||||
expect_stdout: "object"
|
||||
}
|
||||
|
||||
issue_2692: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
reduce_vars: false,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return a = g;
|
||||
function g() {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
console.log(typeof f()());
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
return a = g;
|
||||
function g() {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
console.log(typeof f()());
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_2701: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
inline: false,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
return a = function() {
|
||||
return function() {
|
||||
return a;
|
||||
};
|
||||
}();
|
||||
}
|
||||
console.log(typeof f()());
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
return a = function() {
|
||||
return function() {
|
||||
return a;
|
||||
};
|
||||
}();
|
||||
}
|
||||
console.log(typeof f()());
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_2749: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
inline: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 2, c = "PASS";
|
||||
while (a--)
|
||||
(function() {
|
||||
return b ? c = "FAIL" : b = 1;
|
||||
try {
|
||||
} catch (b) {
|
||||
var b;
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var a = 2, c = "PASS";
|
||||
while (a--)
|
||||
b = void 0, b ? c = "FAIL" : b = 1;
|
||||
var b;
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
unsafe_builtin: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
(!w).constructor(x);
|
||||
Math.abs(y);
|
||||
[ 1, 2, z ].valueOf();
|
||||
}
|
||||
expect: {
|
||||
w, x;
|
||||
y;
|
||||
z;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2860_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
return a ^= 1;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
return 1 ^ a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_2860_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
return a ^= 1;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_2929: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
try {
|
||||
return null.p = a = 1;
|
||||
} catch (e) {
|
||||
return a ? "PASS" : "FAIL";
|
||||
}
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
try {
|
||||
return null.p = a = 1;
|
||||
} catch (e) {
|
||||
return a ? "PASS" : "FAIL";
|
||||
}
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
keep_debugger: {
|
||||
options = {
|
||||
drop_debugger: false
|
||||
};
|
||||
drop_debugger: false,
|
||||
}
|
||||
input: {
|
||||
debugger;
|
||||
}
|
||||
@@ -12,8 +12,8 @@ keep_debugger: {
|
||||
|
||||
drop_debugger: {
|
||||
options = {
|
||||
drop_debugger: true
|
||||
};
|
||||
drop_debugger: true,
|
||||
}
|
||||
input: {
|
||||
debugger;
|
||||
if (foo) debugger;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
drop_console_1: {
|
||||
options = {};
|
||||
options = {}
|
||||
input: {
|
||||
console.log('foo');
|
||||
console.log.apply(console, arguments);
|
||||
@@ -11,7 +11,9 @@ drop_console_1: {
|
||||
}
|
||||
|
||||
drop_console_2: {
|
||||
options = { drop_console: true };
|
||||
options = {
|
||||
drop_console: true,
|
||||
}
|
||||
input: {
|
||||
console.log('foo');
|
||||
console.log.apply(console, arguments);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
and: {
|
||||
options = {
|
||||
evaluate: true
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
@@ -76,7 +77,8 @@ and: {
|
||||
|
||||
or: {
|
||||
options = {
|
||||
evaluate: true
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
@@ -158,7 +160,8 @@ or: {
|
||||
|
||||
unary_prefix: {
|
||||
options = {
|
||||
evaluate: true
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
a = !0 && b;
|
||||
@@ -183,7 +186,9 @@ unary_prefix: {
|
||||
}
|
||||
|
||||
negative_zero: {
|
||||
options = { evaluate: true }
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
-"",
|
||||
@@ -204,7 +209,9 @@ negative_zero: {
|
||||
}
|
||||
|
||||
positive_zero: {
|
||||
options = { evaluate: true }
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
+"",
|
||||
@@ -227,7 +234,7 @@ positive_zero: {
|
||||
unsafe_constant: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -251,21 +258,26 @@ unsafe_constant: {
|
||||
unsafe_object: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var o = { a: 1 };
|
||||
console.log(
|
||||
({a:1}) + 1,
|
||||
({a:1}).a + 1,
|
||||
({a:1}).b + 1,
|
||||
({a:1}).a.b + 1
|
||||
o + 1,
|
||||
o.a + 1,
|
||||
o.b + 1,
|
||||
o.a.b + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var o = { a: 1 };
|
||||
console.log(
|
||||
({a:1}) + 1,
|
||||
o + 1,
|
||||
2,
|
||||
({a:1}).b + 1,
|
||||
o.b + 1,
|
||||
1..b + 1
|
||||
);
|
||||
}
|
||||
@@ -275,21 +287,26 @@ unsafe_object: {
|
||||
unsafe_object_nested: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var o = { a: { b: 1 } };
|
||||
console.log(
|
||||
({a:{b:1}}) + 1,
|
||||
({a:{b:1}}).a + 1,
|
||||
({a:{b:1}}).b + 1,
|
||||
({a:{b:1}}).a.b + 1
|
||||
o + 1,
|
||||
o.a + 1,
|
||||
o.b + 1,
|
||||
o.a.b + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var o = { a: { b: 1 } };
|
||||
console.log(
|
||||
({a:{b:1}}) + 1,
|
||||
({a:{b:1}}).a + 1,
|
||||
({a:{b:1}}).b + 1,
|
||||
o + 1,
|
||||
o.a + 1,
|
||||
o.b + 1,
|
||||
2
|
||||
);
|
||||
}
|
||||
@@ -299,20 +316,25 @@ unsafe_object_nested: {
|
||||
unsafe_object_complex: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var o = { a: { b: 1 }, b: 1 };
|
||||
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
|
||||
o + 1,
|
||||
o.a + 1,
|
||||
o.b + 1,
|
||||
o.a.b + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var o = { a: { b: 1 }, b: 1 };
|
||||
console.log(
|
||||
({a:{b:1},b:1}) + 1,
|
||||
({a:{b:1},b:1}).a + 1,
|
||||
o + 1,
|
||||
o.a + 1,
|
||||
2,
|
||||
2
|
||||
);
|
||||
@@ -323,21 +345,26 @@ unsafe_object_complex: {
|
||||
unsafe_object_repeated: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var o = { a: { b: 1 }, a: 1 };
|
||||
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
|
||||
o + 1,
|
||||
o.a + 1,
|
||||
o.b + 1,
|
||||
o.a.b + 1
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var o = { a: { b: 1 }, a: 1 };
|
||||
console.log(
|
||||
({a:{b:1},a:1}) + 1,
|
||||
o + 1,
|
||||
2,
|
||||
({a:{b:1},a:1}).b + 1,
|
||||
o.b + 1,
|
||||
1..b + 1
|
||||
);
|
||||
}
|
||||
@@ -347,6 +374,7 @@ unsafe_object_repeated: {
|
||||
unsafe_object_accessor: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
@@ -370,10 +398,11 @@ unsafe_object_accessor: {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_function: {
|
||||
prop_function: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -386,9 +415,9 @@ unsafe_function: {
|
||||
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
|
||||
({b:1}) + 1,
|
||||
function(){} + 1,
|
||||
2
|
||||
);
|
||||
}
|
||||
expect_stdout: true
|
||||
@@ -397,7 +426,7 @@ unsafe_function: {
|
||||
unsafe_integer_key: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -425,7 +454,7 @@ unsafe_integer_key: {
|
||||
unsafe_integer_key_complex: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -453,7 +482,7 @@ unsafe_integer_key_complex: {
|
||||
unsafe_float_key: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -481,7 +510,7 @@ unsafe_float_key: {
|
||||
unsafe_float_key_complex: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -509,7 +538,7 @@ unsafe_float_key_complex: {
|
||||
unsafe_array: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -545,7 +574,7 @@ unsafe_array: {
|
||||
unsafe_string: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -573,7 +602,7 @@ unsafe_string: {
|
||||
unsafe_array_bad_index: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -595,7 +624,7 @@ unsafe_array_bad_index: {
|
||||
unsafe_string_bad_index: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -614,10 +643,11 @@ unsafe_string_bad_index: {
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
unsafe_prototype_function: {
|
||||
prototype_function: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = ({valueOf: 0}) < 1;
|
||||
@@ -636,14 +666,16 @@ unsafe_prototype_function: {
|
||||
var d = ({toString: 0}) + "";
|
||||
var e = (({valueOf: 0}) + "")[2];
|
||||
var f = (({toString: 0}) + "")[2];
|
||||
var g = ({valueOf: 0}).valueOf();
|
||||
var h = "" + ({toString: 0});
|
||||
var g = 0();
|
||||
var h = 0();
|
||||
}
|
||||
}
|
||||
|
||||
call_args: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
@@ -665,7 +697,9 @@ call_args: {
|
||||
call_args_drop_param: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
keep_fargs: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -715,7 +749,7 @@ in_boolean_context: {
|
||||
!b("foo"),
|
||||
!b([1, 2]),
|
||||
!b(/foo/),
|
||||
![1, foo()],
|
||||
(foo(), !1),
|
||||
(foo(), !1)
|
||||
);
|
||||
}
|
||||
@@ -725,7 +759,7 @@ in_boolean_context: {
|
||||
unsafe_charAt: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -753,7 +787,7 @@ unsafe_charAt: {
|
||||
unsafe_charAt_bad_index: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -775,18 +809,20 @@ unsafe_charAt_bad_index: {
|
||||
unsafe_charAt_noop: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe : true
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
s.charAt(0),
|
||||
"string".charAt(x)
|
||||
"string".charAt(x),
|
||||
(typeof x).charAt()
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
s.charAt(0),
|
||||
"string".charAt(x)
|
||||
"string".charAt(x),
|
||||
(typeof x)[0]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -994,6 +1030,7 @@ Infinity_NaN_undefined_LHS: {
|
||||
issue_1964_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unsafe_regexp: false,
|
||||
unused: true,
|
||||
@@ -1001,6 +1038,7 @@ issue_1964_1: {
|
||||
input: {
|
||||
function f() {
|
||||
var long_variable_name = /\s/;
|
||||
console.log(long_variable_name.source);
|
||||
return "a b c".split(long_variable_name)[1];
|
||||
}
|
||||
console.log(f());
|
||||
@@ -1008,16 +1046,21 @@ issue_1964_1: {
|
||||
expect: {
|
||||
function f() {
|
||||
var long_variable_name = /\s/;
|
||||
console.log(long_variable_name.source);
|
||||
return "a b c".split(long_variable_name)[1];
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect_stdout: "b"
|
||||
expect_stdout: [
|
||||
"\\s",
|
||||
"b",
|
||||
]
|
||||
}
|
||||
|
||||
issue_1964_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unsafe_regexp: true,
|
||||
unused: true,
|
||||
@@ -1025,15 +1068,545 @@ issue_1964_2: {
|
||||
input: {
|
||||
function f() {
|
||||
var long_variable_name = /\s/;
|
||||
console.log(long_variable_name.source);
|
||||
return "a b c".split(long_variable_name)[1];
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
console.log(/\s/.source);
|
||||
return "a b c".split(/\s/)[1];
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect_stdout: "b"
|
||||
expect_stdout: [
|
||||
"\\s",
|
||||
"b",
|
||||
]
|
||||
}
|
||||
|
||||
array_slice_index: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log([1,2,3].slice(1)[1]);
|
||||
}
|
||||
expect: {
|
||||
console.log(3);
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
|
||||
string_charCodeAt: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log("foo".charCodeAt("bar".length));
|
||||
}
|
||||
expect: {
|
||||
console.log(NaN);
|
||||
}
|
||||
expect_stdout: "NaN"
|
||||
}
|
||||
|
||||
issue_2207_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(String.fromCharCode(65));
|
||||
console.log(Math.max(3, 6, 2, 7, 3, 4));
|
||||
console.log(Math.cos(1.2345));
|
||||
console.log(Math.cos(1.2345) - Math.sin(4.321));
|
||||
console.log(Math.pow(Math.PI, Math.E - Math.LN10));
|
||||
}
|
||||
expect: {
|
||||
console.log("A");
|
||||
console.log(7);
|
||||
console.log(Math.cos(1.2345));
|
||||
console.log(1.2543732512566947);
|
||||
console.log(1.6093984514472044);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2207_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(Math.E);
|
||||
console.log(Math.LN10);
|
||||
console.log(Math.LN2);
|
||||
console.log(Math.LOG2E);
|
||||
console.log(Math.LOG10E);
|
||||
console.log(Math.PI);
|
||||
console.log(Math.SQRT1_2);
|
||||
console.log(Math.SQRT2);
|
||||
}
|
||||
expect: {
|
||||
console.log(Math.E);
|
||||
console.log(Math.LN10);
|
||||
console.log(Math.LN2);
|
||||
console.log(Math.LOG2E);
|
||||
console.log(Math.LOG10E);
|
||||
console.log(Math.PI);
|
||||
console.log(Math.SQRT1_2);
|
||||
console.log(Math.SQRT2);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2207_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(Number.MAX_VALUE);
|
||||
console.log(Number.MIN_VALUE);
|
||||
console.log(Number.NaN);
|
||||
console.log(Number.NEGATIVE_INFINITY);
|
||||
console.log(Number.POSITIVE_INFINITY);
|
||||
}
|
||||
expect: {
|
||||
console.log(Number.MAX_VALUE);
|
||||
console.log(5e-324);
|
||||
console.log(NaN);
|
||||
console.log(-1/0);
|
||||
console.log(1/0);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2231_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(Object.keys(void 0));
|
||||
}
|
||||
expect: {
|
||||
console.log(Object.keys(void 0));
|
||||
}
|
||||
expect_stdout: true
|
||||
expect_warnings: [
|
||||
"WARN: Error evaluating Object.keys(void 0) [test/compress/evaluate.js:1,20]",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2231_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(Object.getOwnPropertyNames(null));
|
||||
}
|
||||
expect: {
|
||||
console.log(Object.getOwnPropertyNames(null));
|
||||
}
|
||||
expect_stdout: true
|
||||
expect_warnings: [
|
||||
"WARN: Error evaluating Object.getOwnPropertyNames(null) [test/compress/evaluate.js:1,20]",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2231_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(Object.keys({ foo: "bar" })[0]);
|
||||
}
|
||||
expect: {
|
||||
console.log("foo");
|
||||
}
|
||||
expect_stdout: "foo"
|
||||
}
|
||||
|
||||
self_comparison_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = { n: NaN };
|
||||
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n);
|
||||
}
|
||||
expect: {
|
||||
console.log(false, false, true, true, "number");
|
||||
}
|
||||
expect_stdout: "false false true true 'number'"
|
||||
}
|
||||
|
||||
self_comparison_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = { n: NaN };
|
||||
console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n);
|
||||
}
|
||||
expect: {
|
||||
console.log(false, false, true, true, "number");
|
||||
}
|
||||
expect_stdout: "false false true true 'number'"
|
||||
}
|
||||
|
||||
issue_2535_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
if ((x() || true) || y()) z();
|
||||
if ((x() || true) && y()) z();
|
||||
if ((x() && true) || y()) z();
|
||||
if ((x() && true) && y()) z();
|
||||
if ((x() || false) || y()) z();
|
||||
if ((x() || false) && y()) z();
|
||||
if ((x() && false) || y()) z();
|
||||
if ((x() && false) && y()) z();
|
||||
}
|
||||
expect: {
|
||||
if (x(), 1) z();
|
||||
if (x(), y()) z();
|
||||
if (x() || y()) z();
|
||||
if (x() && y()) z();
|
||||
if (x() || y()) z();
|
||||
if (x() && y()) z();
|
||||
if (x(), y()) z();
|
||||
if (x(), 0) z();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2535_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(x() || true) || y();
|
||||
(x() || true) && y();
|
||||
(x() && true) || y();
|
||||
(x() && true) && y();
|
||||
(x() || false) || y();
|
||||
(x() || false) && y();
|
||||
(x() && false) || y();
|
||||
(x() && false) && y();
|
||||
}
|
||||
expect: {
|
||||
x(),
|
||||
x(), y(),
|
||||
x() || y(),
|
||||
x() && y(),
|
||||
x() || y(),
|
||||
x() && y(),
|
||||
x(), y(),
|
||||
x();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2535_3: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(Object(1) && 1 && 2);
|
||||
console.log(Object(1) && true && 1 && 2 && Object(2));
|
||||
console.log(Object(1) && true && 1 && null && 2 && Object(2));
|
||||
console.log(2 == Object(1) || 0 || void 0 || null);
|
||||
console.log(2 == Object(1) || 0 || void 0 || null || Object(2));
|
||||
console.log(2 == Object(1) || 0 || void 0 || "ok" || null || Object(2));
|
||||
}
|
||||
expect: {
|
||||
console.log(Object(1) && 2);
|
||||
console.log(Object(1) && Object(2));
|
||||
console.log(Object(1) && null);
|
||||
console.log(2 == Object(1) || null);
|
||||
console.log(2 == Object(1) || Object(2));
|
||||
console.log(2 == Object(1) || "ok");
|
||||
}
|
||||
expect_stdout: true
|
||||
expect_warnings: [
|
||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1,20]",
|
||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:2,20]",
|
||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:3,20]",
|
||||
"WARN: Condition left of && always false [test/compress/evaluate.js:3,20]",
|
||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:4,20]",
|
||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:5,20]",
|
||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:6,20]",
|
||||
"WARN: Condition left of || always true [test/compress/evaluate.js:6,20]",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2822: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log([ function() {}, "PASS", "FAIL" ][1]);
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
string_case: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log("İ".toLowerCase().charCodeAt(0));
|
||||
console.log("I".toLowerCase().charCodeAt(0));
|
||||
console.log("Ş".toLowerCase().charCodeAt(0));
|
||||
console.log("Ğ".toLowerCase().charCodeAt(0));
|
||||
console.log("Ü".toLowerCase().charCodeAt(0));
|
||||
console.log("Ö".toLowerCase().charCodeAt(0));
|
||||
console.log("Ç".toLowerCase().charCodeAt(0));
|
||||
console.log("i".toUpperCase().charCodeAt(0));
|
||||
console.log("ı".toUpperCase().charCodeAt(0));
|
||||
console.log("ş".toUpperCase().charCodeAt(0));
|
||||
console.log("ğ".toUpperCase().charCodeAt(0));
|
||||
console.log("ü".toUpperCase().charCodeAt(0));
|
||||
console.log("ö".toUpperCase().charCodeAt(0));
|
||||
console.log("ç".toUpperCase().charCodeAt(0));
|
||||
}
|
||||
expect: {
|
||||
console.log(105);
|
||||
console.log(105);
|
||||
console.log(351);
|
||||
console.log(287);
|
||||
console.log(252);
|
||||
console.log(246);
|
||||
console.log(231);
|
||||
console.log(73);
|
||||
console.log(73);
|
||||
console.log(350);
|
||||
console.log(286);
|
||||
console.log(220);
|
||||
console.log(214);
|
||||
console.log(199);
|
||||
}
|
||||
expect_stdout: [
|
||||
"105",
|
||||
"105",
|
||||
"351",
|
||||
"287",
|
||||
"252",
|
||||
"246",
|
||||
"231",
|
||||
"73",
|
||||
"73",
|
||||
"350",
|
||||
"286",
|
||||
"220",
|
||||
"214",
|
||||
"199",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2916_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var c = "PASS";
|
||||
(function(a, b) {
|
||||
(function(d) {
|
||||
d[0] = 1;
|
||||
})(b);
|
||||
a == b && (c = "FAIL");
|
||||
})("", []);
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = "PASS";
|
||||
(function(a, b) {
|
||||
(function(d) {
|
||||
d[0] = 1;
|
||||
})(b);
|
||||
a == b && (c = "FAIL");
|
||||
})("", []);
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2916_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var c = "FAIL";
|
||||
(function(b) {
|
||||
(function(d) {
|
||||
d[0] = 1;
|
||||
})(b);
|
||||
+b && (c = "PASS");
|
||||
})([]);
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = "FAIL";
|
||||
(function(b) {
|
||||
b[0] = 1;
|
||||
+b && (c = "PASS");
|
||||
})([]);
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2919: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log([ function() {} ].toString());
|
||||
}
|
||||
expect: {
|
||||
console.log("function(){}");
|
||||
}
|
||||
}
|
||||
|
||||
issue_2926_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
(function f(a) {
|
||||
console.log(f.name.length, f.length);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function f(a) {
|
||||
console.log(1, 1);
|
||||
})();
|
||||
}
|
||||
expect_stdout: "1 1"
|
||||
}
|
||||
|
||||
issue_2926_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof function() {}.valueOf());
|
||||
}
|
||||
expect: {
|
||||
console.log("function");
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_2968: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var c = "FAIL";
|
||||
(function() {
|
||||
(function(a, b) {
|
||||
a <<= 0;
|
||||
a && (a[(c = "PASS", 0 >>> (b += 1))] = 0);
|
||||
})(42, -42);
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = "FAIL";
|
||||
(function() {
|
||||
b = -(a = 42),
|
||||
void ((a <<= 0) && (a[(c = "PASS", 0 >>> (b += 1))] = 0));
|
||||
var a, b;
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
truthy_conditionals: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
if (a = {}) x();
|
||||
(b = /foo/) && y();
|
||||
(c = function() {}) || z();
|
||||
}
|
||||
expect: {
|
||||
a = {}, x();
|
||||
b = /foo/, y();
|
||||
c = function() {};
|
||||
}
|
||||
}
|
||||
|
||||
truthy_loops: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
while ([]) x();
|
||||
do {
|
||||
y();
|
||||
} while(a = {});
|
||||
}
|
||||
expect: {
|
||||
for (;;) {
|
||||
[];
|
||||
x();
|
||||
}
|
||||
for (;;) {
|
||||
y();
|
||||
a = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@ must_replace: {
|
||||
options = {
|
||||
global_defs: {
|
||||
D: "foo bar",
|
||||
}
|
||||
},
|
||||
}
|
||||
input: {
|
||||
console.log(D);
|
||||
@@ -37,6 +37,7 @@ object: {
|
||||
VALUE: 42,
|
||||
},
|
||||
},
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
@@ -140,9 +141,8 @@ mixed: {
|
||||
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]',
|
||||
"WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:4,22]",
|
||||
"WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:7,8]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -174,3 +174,45 @@ issue_1986: {
|
||||
console.log(42);
|
||||
}
|
||||
}
|
||||
|
||||
issue_2167: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
global_defs: {
|
||||
"@isDevMode": "function(){}",
|
||||
},
|
||||
passes: 2,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
if (isDevMode()) {
|
||||
greetOverlord();
|
||||
}
|
||||
doWork();
|
||||
}
|
||||
expect: {
|
||||
doWork();
|
||||
}
|
||||
}
|
||||
|
||||
issue_3217: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
global_defs: {
|
||||
"@o": "{fn:function(){var a=42;console.log(a)}}",
|
||||
},
|
||||
inline: true,
|
||||
properties: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
o.fn();
|
||||
}
|
||||
expect: {
|
||||
console.log(42);
|
||||
}
|
||||
}
|
||||
|
||||
864
test/compress/hoist_props.js
Normal file
864
test/compress/hoist_props.js
Normal file
@@ -0,0 +1,864 @@
|
||||
issue_2377_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
foo: 1,
|
||||
bar: 2,
|
||||
square: function(x) {
|
||||
return x * x;
|
||||
},
|
||||
cube: function(x) {
|
||||
return x * x * x;
|
||||
},
|
||||
};
|
||||
console.log(obj.foo, obj.cube(3));
|
||||
}
|
||||
expect: {
|
||||
var obj_foo = 1, obj_cube = function(x) {
|
||||
return x * x * x;
|
||||
};
|
||||
console.log(obj_foo, obj_cube(3));
|
||||
}
|
||||
expect_stdout: "1 27"
|
||||
}
|
||||
|
||||
issue_2377_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
foo: 1,
|
||||
bar: 2,
|
||||
square: function(x) {
|
||||
return x * x;
|
||||
},
|
||||
cube: function(x) {
|
||||
return x * x * x;
|
||||
},
|
||||
};
|
||||
console.log(obj.foo, obj.cube(3));
|
||||
}
|
||||
expect: {
|
||||
console.log(1, (x = 3, x * x * x));
|
||||
var x;
|
||||
}
|
||||
expect_stdout: "1 27"
|
||||
}
|
||||
|
||||
issue_2377_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
passes: 4,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
foo: 1,
|
||||
bar: 2,
|
||||
square: function(x) {
|
||||
return x * x;
|
||||
},
|
||||
cube: function(x) {
|
||||
return x * x * x;
|
||||
},
|
||||
};
|
||||
console.log(obj.foo, obj.cube(3));
|
||||
}
|
||||
expect: {
|
||||
console.log(1, 27);
|
||||
}
|
||||
expect_stdout: "1 27"
|
||||
}
|
||||
|
||||
direct_access_1: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0;
|
||||
var obj = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
};
|
||||
for (var k in obj) a++;
|
||||
console.log(a, obj.a);
|
||||
}
|
||||
expect: {
|
||||
var a = 0;
|
||||
var obj = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
};
|
||||
for (var k in obj) a++;
|
||||
console.log(a, obj.a);
|
||||
}
|
||||
expect_stdout: "2 1"
|
||||
}
|
||||
|
||||
direct_access_2: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = { a: 1 };
|
||||
var f = function(k) {
|
||||
if (o[k]) return "PASS";
|
||||
};
|
||||
console.log(f("a"));
|
||||
}
|
||||
expect: {
|
||||
var o = { a: 1 };
|
||||
console.log(function(k) {
|
||||
if (o[k]) return "PASS";
|
||||
}("a"));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
direct_access_3: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = { a: 1 };
|
||||
o.b;
|
||||
console.log(o.a);
|
||||
}
|
||||
expect: {
|
||||
var o = { a: 1 };
|
||||
o.b;
|
||||
console.log(o.a);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
single_use: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
bar: function() {
|
||||
return 42;
|
||||
},
|
||||
};
|
||||
console.log(obj.bar());
|
||||
}
|
||||
expect: {
|
||||
console.log({
|
||||
bar: function() {
|
||||
return 42;
|
||||
},
|
||||
}.bar());
|
||||
}
|
||||
}
|
||||
|
||||
name_collision_1: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var obj_foo = 1;
|
||||
var obj_bar = 2;
|
||||
function f() {
|
||||
var obj = {
|
||||
foo: 3,
|
||||
bar: 4,
|
||||
"b-r": 5,
|
||||
"b+r": 6,
|
||||
"b!r": 7,
|
||||
};
|
||||
console.log(obj_foo, obj.foo, obj.bar, obj["b-r"], obj["b+r"], obj["b!r"]);
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
var obj_foo = 1;
|
||||
var obj_bar = 2;
|
||||
function f() {
|
||||
var obj_foo$0 = 3,
|
||||
obj_bar = 4,
|
||||
obj_b_r = 5,
|
||||
obj_b_r$0 = 6,
|
||||
obj_b_r$1 = 7;
|
||||
console.log(obj_foo, obj_foo$0, obj_bar, obj_b_r, obj_b_r$0, obj_b_r$1);
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect_stdout: "1 3 4 5 6 7"
|
||||
}
|
||||
|
||||
name_collision_2: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
p: 1,
|
||||
"+": function(x) {
|
||||
return x;
|
||||
},
|
||||
"-": function(x) {
|
||||
return x + 1;
|
||||
}
|
||||
}, o__$0 = 2, o__$1 = 3;
|
||||
console.log(o.p === o.p, o["+"](4), o["-"](5), o__$0, o__$1);
|
||||
}
|
||||
expect: {
|
||||
var o_p = 1,
|
||||
o__ = function(x) {
|
||||
return x;
|
||||
},
|
||||
o__$2 = function(x) {
|
||||
return x + 1;
|
||||
},
|
||||
o__$0 = 2,
|
||||
o__$1 = 3;
|
||||
console.log(o_p === o_p, o__(4), o__$2(5), o__$0, o__$1);
|
||||
}
|
||||
expect_stdout: "true 4 6 2 3"
|
||||
}
|
||||
|
||||
name_collision_3: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
p: 1,
|
||||
"+": function(x) {
|
||||
return x;
|
||||
},
|
||||
"-": function(x) {
|
||||
return x + 1;
|
||||
}
|
||||
}, o__$0 = 2, o__$1 = 3;
|
||||
console.log(o.p === o.p, o["+"](4), o["-"](5));
|
||||
}
|
||||
expect: {
|
||||
var o_p = 1,
|
||||
o__ = function(x) {
|
||||
return x;
|
||||
},
|
||||
o__$2 = function(x) {
|
||||
return x + 1;
|
||||
},
|
||||
o__$0 = 2,
|
||||
o__$1 = 3;
|
||||
console.log(o_p === o_p, o__(4), o__$2(5));
|
||||
}
|
||||
expect_stdout: "true 4 6"
|
||||
}
|
||||
|
||||
contains_this_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
u: function() {
|
||||
return this === this;
|
||||
},
|
||||
p: 1
|
||||
};
|
||||
console.log(o.p, o.p);
|
||||
}
|
||||
expect: {
|
||||
console.log(1, 1);
|
||||
}
|
||||
expect_stdout: "1 1"
|
||||
}
|
||||
|
||||
contains_this_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
u: function() {
|
||||
return this === this;
|
||||
},
|
||||
p: 1
|
||||
};
|
||||
console.log(o.p, o.p, o.u);
|
||||
}
|
||||
expect: {
|
||||
console.log(1, 1, function() {
|
||||
return this === this;
|
||||
});
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
contains_this_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
u: function() {
|
||||
return this === this;
|
||||
},
|
||||
p: 1
|
||||
};
|
||||
console.log(o.p, o.p, o.u());
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
u: function() {
|
||||
return this === this;
|
||||
},
|
||||
p: 1
|
||||
};
|
||||
console.log(o.p, o.p, o.u());
|
||||
}
|
||||
expect_stdout: "1 1 true"
|
||||
}
|
||||
|
||||
new_this: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
f: function(a) {
|
||||
this.b = a;
|
||||
}
|
||||
};
|
||||
console.log(new o.f(o.a).b, o.b);
|
||||
}
|
||||
expect: {
|
||||
console.log(new function(a) {
|
||||
this.b = a;
|
||||
}(1).b, 2);
|
||||
}
|
||||
expect_stdout: "1 2"
|
||||
}
|
||||
|
||||
issue_2473_1: {
|
||||
options = {
|
||||
hoist_props: false,
|
||||
reduce_vars: true,
|
||||
top_retain: [
|
||||
"x",
|
||||
"y"
|
||||
],
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
var y = [];
|
||||
var z = {};
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
var y = [];
|
||||
}
|
||||
}
|
||||
|
||||
issue_2473_2: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
top_retain: [
|
||||
"x",
|
||||
"y"
|
||||
],
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
var y = [];
|
||||
var z = {};
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
var y = [];
|
||||
}
|
||||
}
|
||||
|
||||
issue_2473_3: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
top_retain: "o",
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
};
|
||||
console.log(o.a, o.b);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
};
|
||||
console.log(o.a, o.b);
|
||||
}
|
||||
expect_stdout: "1 2"
|
||||
}
|
||||
|
||||
issue_2473_4: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
top_retain: "o",
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
};
|
||||
console.log(o.a, o.b);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var o_a = 1, o_b = 2;
|
||||
console.log(o_a, o_b);
|
||||
})();
|
||||
}
|
||||
expect_stdout: "1 2"
|
||||
}
|
||||
|
||||
issue_2508_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
a: [ 1 ],
|
||||
f: function(x) {
|
||||
console.log(x);
|
||||
}
|
||||
};
|
||||
o.f(o.a);
|
||||
}
|
||||
expect: {
|
||||
(function(x) {
|
||||
console.log(x);
|
||||
})([ 1 ]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2508_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
a: { b: 2 },
|
||||
f: function(x) {
|
||||
console.log(x);
|
||||
}
|
||||
};
|
||||
o.f(o.a);
|
||||
}
|
||||
expect: {
|
||||
(function(x) {
|
||||
console.log(x);
|
||||
})({ b: 2 });
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2508_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
a: [ o ],
|
||||
f: function(x) {
|
||||
console.log(x);
|
||||
}
|
||||
};
|
||||
o.f(o.a);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
a: [ o ],
|
||||
f: function(x) {
|
||||
console.log(x);
|
||||
}
|
||||
};
|
||||
o.f(o.a);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2508_4: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
a: { b: o },
|
||||
f: function(x) {
|
||||
console.log(x);
|
||||
}
|
||||
};
|
||||
o.f(o.a);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
a: { b: o },
|
||||
f: function(x) {
|
||||
console.log(x);
|
||||
}
|
||||
};
|
||||
o.f(o.a);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2508_5: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
f: function(x) {
|
||||
console.log(x);
|
||||
}
|
||||
};
|
||||
o.f(o.f);
|
||||
}
|
||||
expect: {
|
||||
var o_f = function(x) {
|
||||
console.log(x);
|
||||
};
|
||||
o_f(o_f);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2519: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function testFunc() {
|
||||
var dimensions = {
|
||||
minX: 5,
|
||||
maxX: 6,
|
||||
};
|
||||
var scale = 1;
|
||||
var d = {
|
||||
x: (dimensions.maxX + dimensions.minX) / 2,
|
||||
};
|
||||
return d.x * scale;
|
||||
}
|
||||
console.log(testFunc());
|
||||
}
|
||||
expect: {
|
||||
function testFunc() {
|
||||
return 1 * ((6 + 5) / 2);
|
||||
}
|
||||
console.log(testFunc());
|
||||
}
|
||||
expect_stdout: "5.5"
|
||||
}
|
||||
|
||||
undefined_key: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
join_vars: true,
|
||||
passes: 4,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a, o = {};
|
||||
o[a] = 1;
|
||||
o.b = 2;
|
||||
console.log(o[a] + o.b);
|
||||
}
|
||||
expect: {
|
||||
console.log(3);
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
|
||||
issue_3021: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1, b = 2;
|
||||
(function() {
|
||||
b = a;
|
||||
if (a++ + b--)
|
||||
return 1;
|
||||
return;
|
||||
var b = {};
|
||||
})();
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = 1, b = 2;
|
||||
(function() {
|
||||
b = a;
|
||||
if (a++ + b--)
|
||||
return 1;
|
||||
return;
|
||||
var b = {};
|
||||
})();
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "2 2"
|
||||
}
|
||||
|
||||
issue_3046: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
do {
|
||||
var b = {
|
||||
c: a++
|
||||
};
|
||||
} while (b.c && a);
|
||||
return a;
|
||||
}(0));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
do {
|
||||
var b_c = a++;
|
||||
} while (b_c && a);
|
||||
return a;
|
||||
}(0));
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3071_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
var obj = {};
|
||||
obj.one = 1;
|
||||
obj.two = 2;
|
||||
console.log(obj.one);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3071_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
obj = {};
|
||||
obj.one = 1;
|
||||
obj.two = 2;
|
||||
console.log(obj.one);
|
||||
var obj;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3071_2_toplevel: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
obj = {};
|
||||
obj.one = 1;
|
||||
obj.two = 2;
|
||||
console.log(obj.one);
|
||||
var obj;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3071_3: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
var c = 0;
|
||||
(function(a, b) {
|
||||
(function f(o) {
|
||||
var n = 2;
|
||||
while (--b + (o = {
|
||||
p: c++,
|
||||
}) && --n > 0);
|
||||
})();
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = 0;
|
||||
(function(a, b) {
|
||||
(function f(o) {
|
||||
var n = 2;
|
||||
while (--b + (o = {
|
||||
p: c++,
|
||||
}) && --n > 0);
|
||||
})();
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
@@ -88,3 +88,24 @@ sequences_funs: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2295: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
function foo(o) {
|
||||
var a = o.a;
|
||||
if (a) return a;
|
||||
var a = 1;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(o) {
|
||||
var a = o.a;
|
||||
if (a) return a;
|
||||
a = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
863
test/compress/ie8.js
Normal file
863
test/compress/ie8.js
Normal file
@@ -0,0 +1,863 @@
|
||||
do_screw: {
|
||||
options = {
|
||||
ie8: false,
|
||||
}
|
||||
beautify = {
|
||||
ie8: false,
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
f("\v");
|
||||
}
|
||||
expect_exact: 'f("\\v");'
|
||||
}
|
||||
|
||||
dont_screw: {
|
||||
options = {
|
||||
ie8: true,
|
||||
}
|
||||
beautify = {
|
||||
ie8: true,
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
f("\v");
|
||||
}
|
||||
expect_exact: 'f("\\x0B");'
|
||||
}
|
||||
|
||||
do_screw_constants: {
|
||||
options = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
f(undefined, Infinity);
|
||||
}
|
||||
expect_exact: "f(void 0,1/0);"
|
||||
}
|
||||
|
||||
dont_screw_constants: {
|
||||
options = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
f(undefined, Infinity);
|
||||
}
|
||||
expect_exact: "f(undefined,Infinity);"
|
||||
}
|
||||
|
||||
do_screw_try_catch: {
|
||||
options = {
|
||||
ie8: false,
|
||||
}
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
beautify = {
|
||||
ie8: false,
|
||||
}
|
||||
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: {
|
||||
options = {
|
||||
ie8: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
beautify = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
bad = function(e){
|
||||
return function(error){
|
||||
try{
|
||||
e()
|
||||
} catch(e) {
|
||||
error(e)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
bad = function(t){
|
||||
return function(n){
|
||||
try{
|
||||
t()
|
||||
} catch(t) {
|
||||
n(t)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
do_screw_try_catch_undefined: {
|
||||
options = {
|
||||
ie8: false,
|
||||
}
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
beautify = {
|
||||
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 (o) {
|
||||
console.log("caught: "+o)
|
||||
}
|
||||
console.log("undefined is " + void 0);
|
||||
return void 0===o
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dont_screw_try_catch_undefined: {
|
||||
options = {
|
||||
ie8: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
beautify = {
|
||||
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(n){
|
||||
try{
|
||||
throw "Stuff"
|
||||
} catch (undefined) {
|
||||
console.log("caught: " + undefined)
|
||||
}
|
||||
console.log("undefined is " + undefined);
|
||||
return n === undefined
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
reduce_vars: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
ie8: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a;
|
||||
try {
|
||||
x();
|
||||
} catch (a) {
|
||||
y();
|
||||
}
|
||||
alert(a);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
var t;
|
||||
try {
|
||||
x();
|
||||
} catch (t) {
|
||||
y();
|
||||
}
|
||||
alert(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1586_1: {
|
||||
options = {
|
||||
ie8: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
try {
|
||||
x();
|
||||
} catch (err) {
|
||||
console.log(err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(){try{x()}catch(c){console.log(c.message)}}"
|
||||
}
|
||||
|
||||
issue_1586_2: {
|
||||
options = {
|
||||
ie8: false,
|
||||
}
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
try {
|
||||
x();
|
||||
} catch (err) {
|
||||
console.log(err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(){try{x()}catch(c){console.log(c.message)}}"
|
||||
}
|
||||
|
||||
issue_2120_1: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
"aaaaaaaa";
|
||||
var a = 1, b = "FAIL";
|
||||
try {
|
||||
throw 1;
|
||||
} catch (c) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (a) {
|
||||
if (c) b = "PASS";
|
||||
}
|
||||
}
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
"aaaaaaaa";
|
||||
var a = 1, b = "FAIL";
|
||||
try {
|
||||
throw 1;
|
||||
} catch (t) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (a) {
|
||||
if (t) b = "PASS";
|
||||
}
|
||||
}
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2120_2: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
"aaaaaaaa";
|
||||
var a = 1, b = "FAIL";
|
||||
try {
|
||||
throw 1;
|
||||
} catch (c) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (a) {
|
||||
if (c) b = "PASS";
|
||||
}
|
||||
}
|
||||
console.log(b);
|
||||
}
|
||||
expect: {
|
||||
"aaaaaaaa";
|
||||
var a = 1, b = "FAIL";
|
||||
try {
|
||||
throw 1;
|
||||
} catch (c) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (a) {
|
||||
if (c) b = "PASS";
|
||||
}
|
||||
}
|
||||
console.log(b);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2254_1: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
"eeeeee";
|
||||
try {
|
||||
console.log(f("PASS"));
|
||||
} catch (e) {}
|
||||
function f(s) {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (e) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"eeeeee";
|
||||
try {
|
||||
console.log(f("PASS"));
|
||||
} catch (e) {}
|
||||
function f(t) {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (e) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2254_2: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
"eeeeee";
|
||||
try {
|
||||
console.log(f("PASS"));
|
||||
} catch (e) {}
|
||||
function f(s) {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (e) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"eeeeee";
|
||||
try {
|
||||
console.log(f("PASS"));
|
||||
} catch (e) {}
|
||||
function f(t) {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (e) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_24_1: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
console.log(typeof function f(){} === typeof a ? "FAIL" : "PASS");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(o) {
|
||||
console.log(typeof function o(){} === typeof o ? "FAIL" : "PASS");
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_24_2: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
console.log(typeof function f(){} === typeof a ? "FAIL" : "PASS");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(o) {
|
||||
console.log(typeof function n(){} === typeof o ? "FAIL" : "PASS");
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2976_1: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
console.log(function f() {
|
||||
var a;
|
||||
return a === f ? "FAIL" : "PASS";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function n() {
|
||||
var o;
|
||||
return o === n ? "FAIL" : "PASS";
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2976_2: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f() {
|
||||
var a;
|
||||
return a === f ? "FAIL" : "PASS";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function f() {
|
||||
var n;
|
||||
return n === f ? "FAIL" : "PASS";
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2976_3: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f() {
|
||||
var a;
|
||||
return a === f ? "FAIL" : "PASS";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function o() {
|
||||
var n;
|
||||
return n === o ? "FAIL" : "PASS";
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3035: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
var c = "FAIL";
|
||||
(function(a) {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (b) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (a) {
|
||||
b && (c = "PASS");
|
||||
}
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = "FAIL";
|
||||
(function(o) {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (t) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (o) {
|
||||
t && (c = "PASS");
|
||||
}
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3035_ie8: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
var c = "FAIL";
|
||||
(function(a) {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (b) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (a) {
|
||||
b && (c = "PASS");
|
||||
}
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = "FAIL";
|
||||
(function(t) {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (o) {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (t) {
|
||||
o && (c = "PASS");
|
||||
}
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3197_1: {
|
||||
options = {
|
||||
ie8: false,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
var window = {};
|
||||
!function() {
|
||||
function Foo() {
|
||||
console.log(this instanceof Foo);
|
||||
}
|
||||
window.Foo = Foo;
|
||||
}();
|
||||
new window.Foo();
|
||||
}
|
||||
expect: {
|
||||
var window = {};
|
||||
window.Foo = function o() {
|
||||
console.log(this instanceof o);
|
||||
};
|
||||
new window.Foo();
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
issue_3197_1_ie8: {
|
||||
options = {
|
||||
ie8: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
var window = {};
|
||||
!function() {
|
||||
function Foo() {
|
||||
console.log(this instanceof Foo);
|
||||
}
|
||||
window.Foo = Foo;
|
||||
}();
|
||||
new window.Foo();
|
||||
}
|
||||
expect: {
|
||||
var window = {};
|
||||
window.Foo = function Foo() {
|
||||
console.log(this instanceof Foo);
|
||||
};
|
||||
new window.Foo();
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
issue_3197_2: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
var f = function f() {
|
||||
console.log(this instanceof f);
|
||||
};
|
||||
new f(a);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(n) {
|
||||
var o = function n() {
|
||||
console.log(this instanceof n);
|
||||
};
|
||||
new o(n);
|
||||
})();
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
issue_3197_2_ie8: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
var f = function f() {
|
||||
console.log(this instanceof f);
|
||||
};
|
||||
new f(a);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(n) {
|
||||
var o = function o() {
|
||||
console.log(this instanceof o);
|
||||
};
|
||||
new o(n);
|
||||
})();
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
issue_3206_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
ie8: false,
|
||||
reduce_vars: true,
|
||||
typeofs: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var foo = function bar() {};
|
||||
var baz = function moo() {};
|
||||
return "function" == typeof bar;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
return "function" == typeof bar;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "false"
|
||||
}
|
||||
|
||||
issue_3206_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
ie8: true,
|
||||
reduce_vars: true,
|
||||
typeofs: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var foo = function bar() {};
|
||||
var baz = function moo() {};
|
||||
return "function" == typeof bar;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
(function bar() {});
|
||||
return "function" == typeof bar;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "false"
|
||||
}
|
||||
|
||||
issue_3215_1: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
console.log(function foo() {
|
||||
var bar = function bar(name) {
|
||||
return "PASS";
|
||||
};
|
||||
try {
|
||||
"moo";
|
||||
} catch (e) {
|
||||
bar = function bar(name) {
|
||||
return "FAIL";
|
||||
};
|
||||
}
|
||||
return bar;
|
||||
}()());
|
||||
}
|
||||
expect: {
|
||||
console.log(function n() {
|
||||
var o = function n(o) {
|
||||
return "PASS";
|
||||
};
|
||||
try {
|
||||
"moo";
|
||||
} catch (n) {
|
||||
o = function n(o) {
|
||||
return "FAIL";
|
||||
};
|
||||
}
|
||||
return o;
|
||||
}()());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3215_2: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function foo() {
|
||||
var bar = function bar(name) {
|
||||
return "PASS";
|
||||
};
|
||||
try {
|
||||
"moo";
|
||||
} catch (e) {
|
||||
bar = function bar(name) {
|
||||
return "FAIL";
|
||||
};
|
||||
}
|
||||
return bar;
|
||||
}()());
|
||||
}
|
||||
expect: {
|
||||
console.log(function foo() {
|
||||
var o = function o(n) {
|
||||
return "PASS";
|
||||
};
|
||||
try {
|
||||
"moo";
|
||||
} catch (n) {
|
||||
o = function o(n) {
|
||||
return "FAIL";
|
||||
};
|
||||
}
|
||||
return o;
|
||||
}()());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3215_3: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
console.log(function foo() {
|
||||
var bar = function bar(name) {
|
||||
return "FAIL";
|
||||
};
|
||||
try {
|
||||
moo;
|
||||
} catch (e) {
|
||||
bar = function bar(name) {
|
||||
return "PASS";
|
||||
};
|
||||
}
|
||||
return bar;
|
||||
}()());
|
||||
}
|
||||
expect: {
|
||||
console.log(function n() {
|
||||
var o = function n(o) {
|
||||
return "FAIL";
|
||||
};
|
||||
try {
|
||||
moo;
|
||||
} catch (n) {
|
||||
o = function n(o) {
|
||||
return "PASS";
|
||||
};
|
||||
}
|
||||
return o;
|
||||
}()());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_3215_4: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function foo() {
|
||||
var bar = function bar(name) {
|
||||
return "FAIL";
|
||||
};
|
||||
try {
|
||||
moo;
|
||||
} catch (e) {
|
||||
bar = function bar(name) {
|
||||
return "PASS";
|
||||
};
|
||||
}
|
||||
return bar;
|
||||
}()());
|
||||
}
|
||||
expect: {
|
||||
console.log(function foo() {
|
||||
var o = function o(n) {
|
||||
return "FAIL";
|
||||
};
|
||||
try {
|
||||
moo;
|
||||
} catch (n) {
|
||||
o = function o(n) {
|
||||
return "PASS";
|
||||
};
|
||||
}
|
||||
return o;
|
||||
}()());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
if_return_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects: true,
|
||||
dead_code : true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
@@ -24,15 +24,15 @@ if_return_1: {
|
||||
|
||||
if_return_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects: true,
|
||||
dead_code : true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y) {
|
||||
@@ -49,15 +49,15 @@ if_return_2: {
|
||||
|
||||
if_return_3: {
|
||||
options = {
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects: true,
|
||||
dead_code : true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
@@ -75,15 +75,15 @@ if_return_3: {
|
||||
|
||||
if_return_4: {
|
||||
options = {
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects: true,
|
||||
dead_code : true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y) {
|
||||
@@ -100,15 +100,15 @@ if_return_4: {
|
||||
|
||||
if_return_5: {
|
||||
options = {
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects: true,
|
||||
dead_code : true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
@@ -126,15 +126,15 @@ if_return_5: {
|
||||
|
||||
if_return_6: {
|
||||
options = {
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects: true,
|
||||
dead_code : true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
@@ -150,15 +150,15 @@ if_return_6: {
|
||||
|
||||
if_return_7: {
|
||||
options = {
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects: true,
|
||||
dead_code : true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
@@ -176,9 +176,9 @@ if_return_7: {
|
||||
|
||||
if_return_8: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
@@ -220,15 +220,15 @@ if_return_8: {
|
||||
|
||||
issue_1089: {
|
||||
options = {
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
unused : true,
|
||||
side_effects: true,
|
||||
dead_code : true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
@@ -243,7 +243,7 @@ issue_1089: {
|
||||
expect: {
|
||||
function x() {
|
||||
var f = document.getElementById("fname");
|
||||
if (f.files[0].size > 12345)
|
||||
if (12345 < f.files[0].size)
|
||||
return alert("alert"), f.focus(), !1;
|
||||
}
|
||||
}
|
||||
@@ -251,9 +251,9 @@ issue_1089: {
|
||||
|
||||
issue_1437: {
|
||||
options = {
|
||||
conditionals: false,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals : false
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
@@ -283,7 +283,7 @@ issue_1437_conditionals: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
sequences : true
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
@@ -307,6 +307,8 @@ issue_512: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function a() {
|
||||
@@ -324,3 +326,73 @@ issue_512: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if_var_return: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a;
|
||||
return;
|
||||
var b;
|
||||
}
|
||||
function g() {
|
||||
var a;
|
||||
if (u()) {
|
||||
var b;
|
||||
return v();
|
||||
var c;
|
||||
}
|
||||
var d;
|
||||
if (w()) {
|
||||
var e;
|
||||
return x();
|
||||
var f;
|
||||
} else {
|
||||
var g;
|
||||
y();
|
||||
var h;
|
||||
}
|
||||
var i;
|
||||
z();
|
||||
var j;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
var a, b;
|
||||
}
|
||||
function g() {
|
||||
var a, b, c, d, e, f, g, h, i, j;
|
||||
return u() ? v() : w() ? x() : (y(), z(), void 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if_if_return_return: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
if (a) {
|
||||
if (b)
|
||||
return b;
|
||||
return;
|
||||
}
|
||||
g();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a, b) {
|
||||
if (a)
|
||||
return b || void 0;
|
||||
g();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
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
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: true,
|
||||
loops: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
@@ -27,19 +36,30 @@ non_hoisted_function_after_return: {
|
||||
}
|
||||
}
|
||||
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]"
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
|
||||
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:11,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, warnings: "verbose"
|
||||
booleans: true,
|
||||
collapse_vars: false,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
warnings: "verbose",
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
@@ -65,26 +85,37 @@ non_hoisted_function_after_return_2a: {
|
||||
}
|
||||
}
|
||||
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]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:4,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
|
||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]",
|
||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
|
||||
"WARN: pass 0: last_count: Infinity, count: 37",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
|
||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
|
||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
|
||||
"WARN: pass 1: last_count: 37, count: 18",
|
||||
]
|
||||
}
|
||||
|
||||
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
|
||||
booleans: true,
|
||||
collapse_vars: false,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: true,
|
||||
loops: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
@@ -108,11 +139,174 @@ non_hoisted_function_after_return_2b: {
|
||||
}
|
||||
}
|
||||
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 unreachable code [test/compress/issue-1034.js:6,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:6,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]",
|
||||
]
|
||||
}
|
||||
|
||||
non_hoisted_function_after_return_strict: {
|
||||
options = {
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: true,
|
||||
loops: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
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; }
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function foo(x) {
|
||||
return x ? bar() : baz();
|
||||
function bar() { return 7 }
|
||||
function baz() { return 8 }
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect_stdout: "8 7"
|
||||
expect_warnings: [
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:5,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:11,12]",
|
||||
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:12,21]",
|
||||
]
|
||||
}
|
||||
|
||||
non_hoisted_function_after_return_2a_strict: {
|
||||
options = {
|
||||
booleans: true,
|
||||
collapse_vars: false,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
warnings: "verbose",
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
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;
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function foo(x) {
|
||||
return bar(x ? 1 : 2);
|
||||
function bar(x) {
|
||||
return 7 - x;
|
||||
}
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect_stdout: "5 6"
|
||||
expect_warnings: [
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:5,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:5,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,16]",
|
||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]",
|
||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]",
|
||||
"WARN: pass 0: last_count: Infinity, count: 48",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
|
||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
|
||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
|
||||
"WARN: pass 1: last_count: 48, count: 29",
|
||||
]
|
||||
}
|
||||
|
||||
non_hoisted_function_after_return_2b_strict: {
|
||||
options = {
|
||||
booleans: true,
|
||||
collapse_vars: false,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: true,
|
||||
loops: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
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;
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function foo(x) {
|
||||
return bar(x ? 1 : 2);
|
||||
function bar(x) { return 7 - x; }
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect_stdout: "5 6"
|
||||
expect_warnings: [
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
const_pragma: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
};
|
||||
}
|
||||
|
||||
input: {
|
||||
/** @const */ var goog = goog || {};
|
||||
@@ -16,8 +17,9 @@ const_pragma: {
|
||||
not_const: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
};
|
||||
}
|
||||
|
||||
input: {
|
||||
var goog = goog || {};
|
||||
|
||||
@@ -1,90 +1,91 @@
|
||||
multiple_functions: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
}
|
||||
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 );
|
||||
function f() {}
|
||||
function g() {}
|
||||
} )();
|
||||
}
|
||||
}
|
||||
|
||||
single_function: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
( function() {
|
||||
if ( !window ) {
|
||||
return;
|
||||
}
|
||||
|
||||
function f() {}
|
||||
} )();
|
||||
}
|
||||
expect: {
|
||||
( function() {
|
||||
function f() {}
|
||||
|
||||
if ( window );
|
||||
function f() {}
|
||||
} )();
|
||||
}
|
||||
}
|
||||
|
||||
deeply_nested: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
}
|
||||
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);
|
||||
function f() {}
|
||||
function g() {}
|
||||
function h() {}
|
||||
} )();
|
||||
}
|
||||
}
|
||||
|
||||
not_hoisted_when_already_nested: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
( function() {
|
||||
if ( !window ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( foo ) function f() {}
|
||||
|
||||
} )();
|
||||
}
|
||||
expect: {
|
||||
@@ -94,3 +95,70 @@ not_hoisted_when_already_nested: {
|
||||
} )();
|
||||
}
|
||||
}
|
||||
|
||||
defun_if_return: {
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
function e() {
|
||||
function f() {}
|
||||
if (!window) return;
|
||||
else function g() {}
|
||||
function h() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function e() {
|
||||
function f() {}
|
||||
if (window) function g() {}
|
||||
function h() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defun_hoist_funs: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
function e() {
|
||||
function f() {}
|
||||
if (!window) return;
|
||||
else function g() {}
|
||||
function h() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function e() {
|
||||
function f() {}
|
||||
function g() {}
|
||||
function h() {}
|
||||
if (window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defun_else_if_return: {
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
function e() {
|
||||
function f() {}
|
||||
if (window) function g() {}
|
||||
else return;
|
||||
function h() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function e() {
|
||||
function f() {}
|
||||
if (window) function g() {}
|
||||
function h() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
with_in_global_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = 42;
|
||||
@@ -18,7 +18,7 @@ with_in_global_scope: {
|
||||
}
|
||||
with_in_function_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo() {
|
||||
@@ -40,7 +40,7 @@ with_in_function_scope: {
|
||||
}
|
||||
compress_with_with_in_other_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo() {
|
||||
@@ -69,7 +69,7 @@ compress_with_with_in_other_scope: {
|
||||
}
|
||||
with_using_existing_variable_outside_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
@@ -99,7 +99,7 @@ with_using_existing_variable_outside_scope: {
|
||||
}
|
||||
check_drop_unused_in_peer_function: {
|
||||
options = {
|
||||
unused: true
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function outer() {
|
||||
@@ -148,7 +148,7 @@ check_drop_unused_in_peer_function: {
|
||||
|
||||
Infinity_not_in_with_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = { Infinity: 'oInfinity' };
|
||||
@@ -164,7 +164,7 @@ Infinity_not_in_with_scope: {
|
||||
|
||||
Infinity_in_with_scope: {
|
||||
options = {
|
||||
unused: true
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = { Infinity: 'oInfinity' };
|
||||
@@ -180,20 +180,19 @@ Infinity_in_with_scope: {
|
||||
|
||||
assorted_Infinity_NaN_undefined_in_with_scope: {
|
||||
options = {
|
||||
unused: true,
|
||||
evaluate: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: true,
|
||||
keep_fargs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade: true,
|
||||
side_effects: true,
|
||||
sequences: false,
|
||||
keep_fargs: true,
|
||||
keep_infinity: false,
|
||||
sequences: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var f = console.log;
|
||||
@@ -243,20 +242,19 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
|
||||
|
||||
assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: {
|
||||
options = {
|
||||
unused: true,
|
||||
evaluate: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: true,
|
||||
keep_fargs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade: true,
|
||||
side_effects: true,
|
||||
sequences: false,
|
||||
keep_fargs: true,
|
||||
keep_infinity: true,
|
||||
sequences: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var f = console.log;
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
keep_name_of_getter: {
|
||||
options = { unused: true };
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: { a = { get foo () {} } }
|
||||
expect: { a = { get foo () {} } }
|
||||
}
|
||||
|
||||
keep_name_of_setter: {
|
||||
options = { unused: true };
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: { a = { set foo () {} } }
|
||||
expect: { a = { set foo () {} } }
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
mangle_keep_fnames_false: {
|
||||
options = {
|
||||
keep_fnames : true,
|
||||
keep_fargs: true,
|
||||
keep_fnames: true,
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames : false,
|
||||
@@ -26,8 +26,8 @@ mangle_keep_fnames_false: {
|
||||
|
||||
mangle_keep_fnames_true: {
|
||||
options = {
|
||||
keep_fnames : true,
|
||||
keep_fargs: true,
|
||||
keep_fnames: true,
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames : true,
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
pure_function_calls: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
side_effects : true,
|
||||
booleans: true,
|
||||
unused : true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade : true,
|
||||
negate_iife: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
// pure top-level IIFE will be dropped
|
||||
@@ -49,29 +48,28 @@ pure_function_calls: {
|
||||
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]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]",
|
||||
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:25,31]",
|
||||
]
|
||||
}
|
||||
|
||||
pure_function_calls_toplevel: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
side_effects : true,
|
||||
booleans: true,
|
||||
unused : true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade : true,
|
||||
negate_iife: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
// pure top-level IIFE will be dropped
|
||||
@@ -96,6 +94,13 @@ pure_function_calls_toplevel: {
|
||||
})();
|
||||
})();
|
||||
|
||||
// pure top-level calls will be dropped regardless of the leading comments position
|
||||
var MyClass = /*#__PURE__*//*@class*/(function(){
|
||||
function MyClass() {}
|
||||
MyClass.prototype.method = function() {};
|
||||
return MyClass;
|
||||
})();
|
||||
|
||||
// comment #__PURE__ comment
|
||||
bar(), baz(), quux();
|
||||
a.b(), /* @__PURE__ */ c.d.e(), f.g();
|
||||
@@ -105,15 +110,17 @@ pure_function_calls_toplevel: {
|
||||
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]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]",
|
||||
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:31,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:32,31]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,33]",
|
||||
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:8,12]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,45]",
|
||||
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:24,12]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -148,29 +155,29 @@ should_warn: {
|
||||
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: Condition left of || 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: Condition left of && 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]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,61]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,23]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:1,23]",
|
||||
"WARN: Boolean || always true [test/compress/issue-1261.js:2,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:2,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:2,23]",
|
||||
"WARN: Condition left of || always true [test/compress/issue-1261.js:3,8]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:3,8]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:4,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:4,23]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:4,23]",
|
||||
"WARN: Condition left of && always false [test/compress/issue-1261.js:5,8]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:5,8]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:6,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:6,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:6,23]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:7,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:7,31]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:7,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:9,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:9,24]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:10,31]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:10,8]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
string_plus_optimization: {
|
||||
options = {
|
||||
side_effects : true,
|
||||
evaluate : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
booleans: true,
|
||||
unused : true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade : true,
|
||||
hoist_funs : true,
|
||||
};
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo(anything) {
|
||||
function throwing_function() {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
issue_1321_no_debug: {
|
||||
mangle_props = {
|
||||
keep_quoted: true
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
@@ -10,17 +12,19 @@ issue_1321_no_debug: {
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.b = 1;
|
||||
x["a"] = 2 * x.b;
|
||||
console.log(x.b, x["a"]);
|
||||
x.x = 1;
|
||||
x["a"] = 2 * x.x;
|
||||
console.log(x.x, x["a"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1321_debug: {
|
||||
mangle_props = {
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: "",
|
||||
keep_quoted: true,
|
||||
debug: ""
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
@@ -30,16 +34,18 @@ issue_1321_debug: {
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.a = 1;
|
||||
x["_$foo$_"] = 2 * x.a;
|
||||
console.log(x.a, x["_$foo$_"]);
|
||||
x.x = 1;
|
||||
x["_$foo$_"] = 2 * x.x;
|
||||
console.log(x.x, x["_$foo$_"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1321_with_quoted: {
|
||||
mangle_props = {
|
||||
keep_quoted: false
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: false,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
@@ -49,9 +55,9 @@ issue_1321_with_quoted: {
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.a = 1;
|
||||
x["b"] = 2 * x.a;
|
||||
console.log(x.a, x["b"]);
|
||||
x.x = 1;
|
||||
x["o"] = 2 * x.x;
|
||||
console.log(x.x, x["o"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
tranformation_sort_order_equal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
};
|
||||
}
|
||||
|
||||
input: { (a = parseInt('100')) == a }
|
||||
expect: { (a = parseInt('100')) == a }
|
||||
@@ -24,7 +24,7 @@ tranformation_sort_order_equal: {
|
||||
tranformation_sort_order_unequal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
};
|
||||
}
|
||||
|
||||
input: { (a = parseInt('100')) != a }
|
||||
expect: { (a = parseInt('100')) != a }
|
||||
@@ -33,7 +33,7 @@ tranformation_sort_order_unequal: {
|
||||
tranformation_sort_order_lesser_or_equal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
};
|
||||
}
|
||||
|
||||
input: { (a = parseInt('100')) <= a }
|
||||
expect: { (a = parseInt('100')) <= a }
|
||||
@@ -41,7 +41,7 @@ tranformation_sort_order_lesser_or_equal: {
|
||||
tranformation_sort_order_greater_or_equal: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
};
|
||||
}
|
||||
|
||||
input: { (a = parseInt('100')) >= a }
|
||||
expect: { (a = parseInt('100')) >= a }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
level_zero: {
|
||||
options = {
|
||||
keep_fnames: true
|
||||
keep_fnames: true,
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames: true
|
||||
@@ -29,7 +29,7 @@ level_zero: {
|
||||
|
||||
level_one: {
|
||||
options = {
|
||||
keep_fnames: true
|
||||
keep_fnames: true,
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames: true
|
||||
@@ -58,7 +58,7 @@ level_one: {
|
||||
|
||||
level_two: {
|
||||
options = {
|
||||
keep_fnames: true
|
||||
keep_fnames: true,
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames: true
|
||||
@@ -97,7 +97,7 @@ level_two: {
|
||||
|
||||
level_three: {
|
||||
options = {
|
||||
keep_fnames: true
|
||||
keep_fnames: true,
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames: true
|
||||
|
||||
@@ -4,7 +4,7 @@ unsafe_undefined: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
unsafe: true
|
||||
unsafe_undefined: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
@@ -30,7 +30,7 @@ keep_fnames: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
unsafe: true
|
||||
unsafe_undefined: true,
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames: true
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
typeof_eq_undefined: {
|
||||
options = {
|
||||
comparisons: true
|
||||
comparisons: true,
|
||||
typeofs: true,
|
||||
}
|
||||
input: {
|
||||
var a = typeof b != "undefined";
|
||||
@@ -24,6 +25,7 @@ typeof_eq_undefined_ie8: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
ie8: true,
|
||||
typeofs: true,
|
||||
}
|
||||
input: {
|
||||
var a = typeof b != "undefined";
|
||||
@@ -45,7 +47,8 @@ typeof_eq_undefined_ie8: {
|
||||
|
||||
undefined_redefined: {
|
||||
options = {
|
||||
comparisons: true
|
||||
comparisons: true,
|
||||
typeofs: true,
|
||||
}
|
||||
input: {
|
||||
function f(undefined) {
|
||||
@@ -58,7 +61,8 @@ undefined_redefined: {
|
||||
|
||||
undefined_redefined_mangle: {
|
||||
options = {
|
||||
comparisons: true
|
||||
comparisons: true,
|
||||
typeofs: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
|
||||
@@ -22,18 +22,17 @@ else_with_empty_statement: {
|
||||
|
||||
conditional_false_stray_else_in_loop: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
comparisons : true,
|
||||
booleans: true,
|
||||
unused : true,
|
||||
comparisons: true,
|
||||
conditionals: false,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_vars: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
loops: true,
|
||||
side_effects: true,
|
||||
dead_code : true,
|
||||
hoist_vars : true,
|
||||
join_vars : true,
|
||||
if_return : true,
|
||||
cascade : true,
|
||||
conditionals : false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
for (var i = 1; i <= 4; ++i) {
|
||||
|
||||
@@ -61,7 +61,7 @@ unsafe_undefined: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
unsafe: true,
|
||||
unsafe_undefined: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
|
||||
@@ -2,6 +2,7 @@ chained_evaluation_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -28,6 +29,7 @@ chained_evaluation_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
issue_1639_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
cascade: true,
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
@@ -26,7 +26,7 @@ issue_1639_1: {
|
||||
}
|
||||
expect: {
|
||||
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
|
||||
if (--b, !1) var ignore = 0;
|
||||
if (--b, 0) var ignore = 0;
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: true
|
||||
@@ -35,7 +35,7 @@ issue_1639_1: {
|
||||
issue_1639_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
cascade: true,
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
@@ -57,7 +57,7 @@ issue_1639_2: {
|
||||
expect: {
|
||||
var a = 100, b = 10;
|
||||
function f19() {
|
||||
++a, 1;
|
||||
++a, 0;
|
||||
}
|
||||
f19(),
|
||||
console.log(a, b);
|
||||
@@ -68,7 +68,7 @@ issue_1639_2: {
|
||||
issue_1639_3: {
|
||||
options = {
|
||||
booleans: true,
|
||||
cascade: true,
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
sequences: true,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
f7: {
|
||||
options = {
|
||||
booleans: true,
|
||||
cascade: true,
|
||||
collapse_vars: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
@@ -15,6 +14,7 @@ f7: {
|
||||
negate_iife: true,
|
||||
passes: 3,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -38,7 +38,7 @@ f7: {
|
||||
"var b = 10;",
|
||||
"",
|
||||
"!function() {",
|
||||
" for (;b = 100, !1; ) ;",
|
||||
" b = 100;",
|
||||
"}(), console.log(100, b);",
|
||||
]
|
||||
expect_stdout: true
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
side_effects_catch: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -34,6 +35,7 @@ side_effects_catch: {
|
||||
|
||||
side_effects_else: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -62,6 +64,7 @@ side_effects_else: {
|
||||
|
||||
side_effects_finally: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -98,6 +101,7 @@ side_effects_finally: {
|
||||
|
||||
side_effects_label: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -130,6 +134,7 @@ side_effects_label: {
|
||||
|
||||
side_effects_switch: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
|
||||
@@ -104,7 +104,7 @@ mangle_catch_toplevel: {
|
||||
}
|
||||
console.log(a);
|
||||
}
|
||||
expect_exact: 'var o="FAIL";try{throw 1}catch(c){o="PASS"}console.log(o);'
|
||||
expect_exact: 'var c="FAIL";try{throw 1}catch(o){c="PASS"}console.log(c);'
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ mangle_catch_var_toplevel: {
|
||||
}
|
||||
console.log(a);
|
||||
}
|
||||
expect_exact: 'var o="FAIL";try{throw 1}catch(r){var o="PASS"}console.log(o);'
|
||||
expect_exact: 'var r="FAIL";try{throw 1}catch(o){var r="PASS"}console.log(r);'
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -345,3 +345,95 @@ mangle_catch_redef_2_ie8_toplevel: {
|
||||
expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
mangle_catch_redef_3: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
var o = "PASS";
|
||||
try {
|
||||
throw 0;
|
||||
} catch (o) {
|
||||
(function() {
|
||||
function f() {
|
||||
o = "FAIL";
|
||||
}
|
||||
f(), f();
|
||||
})();
|
||||
}
|
||||
console.log(o);
|
||||
}
|
||||
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
mangle_catch_redef_3_toplevel: {
|
||||
mangle = {
|
||||
ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var o = "PASS";
|
||||
try {
|
||||
throw 0;
|
||||
} catch (o) {
|
||||
(function() {
|
||||
function f() {
|
||||
o = "FAIL";
|
||||
}
|
||||
f(), f();
|
||||
})();
|
||||
}
|
||||
console.log(o);
|
||||
}
|
||||
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
mangle_catch_redef_ie8_3: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
var o = "PASS";
|
||||
try {
|
||||
throw 0;
|
||||
} catch (o) {
|
||||
(function() {
|
||||
function f() {
|
||||
o = "FAIL";
|
||||
}
|
||||
f(), f();
|
||||
})();
|
||||
}
|
||||
console.log(o);
|
||||
}
|
||||
expect_exact: 'var o="PASS";try{throw 0}catch(o){(function(){function c(){o="FAIL"}c(),c()})()}console.log(o);'
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
mangle_catch_redef_3_ie8_toplevel: {
|
||||
mangle = {
|
||||
ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var o = "PASS";
|
||||
try {
|
||||
throw 0;
|
||||
} catch (o) {
|
||||
(function() {
|
||||
function f() {
|
||||
o = "FAIL";
|
||||
}
|
||||
f(), f();
|
||||
})();
|
||||
}
|
||||
console.log(o);
|
||||
}
|
||||
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ function_iife_catch: {
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect_exact: "function f(o){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();"
|
||||
expect_exact: "function f(o){!function(){try{throw 0}catch(o){var c=1;console.log(o,c)}}()}f();"
|
||||
expect_stdout: "0 1"
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ function_iife_catch_ie8: {
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect_exact: "function f(o){!function(){try{throw 0}catch(o){var c=1;console.log(o,c)}}()}f();"
|
||||
expect_exact: "function f(c){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();"
|
||||
expect_stdout: "0 1"
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ function_catch_catch: {
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect_exact: "var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();"
|
||||
expect_exact: "var o=0;function f(){try{throw 1}catch(o){try{throw 2}catch(c){var c=3;console.log(c)}}console.log(c)}f();"
|
||||
expect_stdout: [
|
||||
"3",
|
||||
"undefined",
|
||||
|
||||
@@ -7,7 +7,7 @@ case_1: {
|
||||
input: {
|
||||
var a = 0, b = 1;
|
||||
switch (true) {
|
||||
case a, true:
|
||||
case a || true:
|
||||
default:
|
||||
b = 2;
|
||||
case true:
|
||||
@@ -17,7 +17,7 @@ case_1: {
|
||||
expect: {
|
||||
var a = 0, b = 1;
|
||||
switch (true) {
|
||||
case a, true:
|
||||
case a || true:
|
||||
b = 2;
|
||||
}
|
||||
console.log(a, b);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
mangle_props: {
|
||||
mangle_props = {}
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
undefined: 1,
|
||||
@@ -54,10 +56,12 @@ mangle_props: {
|
||||
}
|
||||
|
||||
numeric_literal: {
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
mangle_props = {}
|
||||
input: {
|
||||
var obj = {
|
||||
0: 0,
|
||||
@@ -80,19 +84,19 @@ numeric_literal: {
|
||||
' 0: 0,',
|
||||
' "-0": 1,',
|
||||
' 42: 2,',
|
||||
' "42": 3,',
|
||||
' 42: 3,',
|
||||
' 37: 4,',
|
||||
' a: 5,',
|
||||
' o: 5,',
|
||||
' 1e42: 6,',
|
||||
' b: 7,',
|
||||
' "1e+42": 8',
|
||||
' 1e42: 8',
|
||||
'};',
|
||||
'',
|
||||
'console.log(obj[-0], obj[-""], obj["-0"]);',
|
||||
'',
|
||||
'console.log(obj[42], obj["42"]);',
|
||||
'',
|
||||
'console.log(obj[37], obj["a"], obj[37], obj["37"]);',
|
||||
'console.log(obj[37], obj["o"], obj[37], obj["37"]);',
|
||||
'',
|
||||
'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
|
||||
]
|
||||
@@ -105,7 +109,9 @@ numeric_literal: {
|
||||
}
|
||||
|
||||
identifier: {
|
||||
mangle_props = {}
|
||||
mangle = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
abstract: 1,
|
||||
@@ -173,32 +179,32 @@ identifier: {
|
||||
}
|
||||
expect: {
|
||||
var obj = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3,
|
||||
d: 4,
|
||||
e: 5,
|
||||
f: 6,
|
||||
g: 7,
|
||||
h: 8,
|
||||
i: 9,
|
||||
j: 10,
|
||||
k: 11,
|
||||
l: 12,
|
||||
m: 13,
|
||||
n: 14,
|
||||
o: 15,
|
||||
p: 16,
|
||||
q: 17,
|
||||
r: 18,
|
||||
s: 19,
|
||||
t: 20,
|
||||
u: 21,
|
||||
v: 22,
|
||||
w: 23,
|
||||
x: 24,
|
||||
y: 25,
|
||||
z: 26,
|
||||
e: 1,
|
||||
t: 2,
|
||||
n: 3,
|
||||
a: 4,
|
||||
i: 5,
|
||||
o: 6,
|
||||
r: 7,
|
||||
l: 8,
|
||||
s: 9,
|
||||
c: 10,
|
||||
f: 11,
|
||||
u: 12,
|
||||
d: 13,
|
||||
h: 14,
|
||||
p: 15,
|
||||
b: 16,
|
||||
v: 17,
|
||||
w: 18,
|
||||
y: 19,
|
||||
g: 20,
|
||||
m: 21,
|
||||
k: 22,
|
||||
x: 23,
|
||||
j: 24,
|
||||
z: 25,
|
||||
q: 26,
|
||||
A: 27,
|
||||
B: 28,
|
||||
C: 29,
|
||||
@@ -229,11 +235,11 @@ identifier: {
|
||||
Z: 54,
|
||||
$: 55,
|
||||
_: 56,
|
||||
aa: 57,
|
||||
ba: 58,
|
||||
ca: 59,
|
||||
da: 60,
|
||||
ea: 61,
|
||||
ee: 57,
|
||||
te: 58,
|
||||
ne: 59,
|
||||
ae: 60,
|
||||
ie: 61,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
unary_prefix: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
iife_for: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -26,6 +27,7 @@ iife_for: {
|
||||
iife_for_in: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -51,6 +53,7 @@ iife_for_in: {
|
||||
iife_do: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -80,6 +83,7 @@ iife_do: {
|
||||
iife_while: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -121,8 +125,8 @@ label_do: {
|
||||
|
||||
label_while: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
@@ -130,5 +134,5 @@ label_while: {
|
||||
L: while (0) continue L;
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(){L:;}"
|
||||
expect_exact: "function f(){L:0}"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
do_not_update_lhs: {
|
||||
options = {
|
||||
global_defs: { DEBUG: 0 }
|
||||
global_defs: {
|
||||
DEBUG: 0,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
DEBUG++;
|
||||
@@ -16,7 +18,9 @@ do_not_update_lhs: {
|
||||
|
||||
do_update_rhs: {
|
||||
options = {
|
||||
global_defs: { DEBUG: 0 }
|
||||
global_defs: {
|
||||
DEBUG: 0,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
MY_DEBUG = DEBUG;
|
||||
@@ -35,7 +39,7 @@ mixed: {
|
||||
DEBUG: 0,
|
||||
ENV: 1,
|
||||
FOO: 2,
|
||||
}
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var ENV = 3;
|
||||
@@ -60,11 +64,11 @@ mixed: {
|
||||
x = 0;
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,12]',
|
||||
'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]',
|
||||
"WARN: global_defs ENV redefined [test/compress/issue-208.js:1,12]",
|
||||
"WARN: global_defs FOO redefined [test/compress/issue-208.js:2,12]",
|
||||
"WARN: global_defs FOO redefined [test/compress/issue-208.js:4,10]",
|
||||
"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:5,8]",
|
||||
"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:6,8]",
|
||||
"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:7,8]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
return_with_no_value_in_if_body: {
|
||||
options = { conditionals: true };
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
function foo(bar) {
|
||||
if (bar) {
|
||||
|
||||
33
test/compress/issue-2652.js
Normal file
33
test/compress/issue-2652.js
Normal file
@@ -0,0 +1,33 @@
|
||||
insert_semicolon: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
comments: "all",
|
||||
}
|
||||
input: {
|
||||
var a
|
||||
/* foo */ var b
|
||||
}
|
||||
expect_exact: [
|
||||
"var a",
|
||||
"/* foo */;",
|
||||
"",
|
||||
"var b;",
|
||||
]
|
||||
}
|
||||
|
||||
unary_postfix: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
comments: "all",
|
||||
}
|
||||
input: {
|
||||
a
|
||||
/* foo */++b
|
||||
}
|
||||
expect_exact: [
|
||||
"a",
|
||||
"/* foo */;",
|
||||
"",
|
||||
"++b;",
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
issue_267: {
|
||||
options = { comparisons: true };
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
x = a % b / b * c * 2;
|
||||
x = a % b * 2
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
issue_269_1: {
|
||||
options = {unsafe: true};
|
||||
options = {
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
f(
|
||||
String(x),
|
||||
@@ -20,7 +22,9 @@ issue_269_1: {
|
||||
}
|
||||
|
||||
issue_269_dangers: {
|
||||
options = {unsafe: true};
|
||||
options = {
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
f(
|
||||
String(x, x),
|
||||
@@ -34,7 +38,9 @@ issue_269_dangers: {
|
||||
}
|
||||
|
||||
issue_269_in_scope: {
|
||||
options = {unsafe: true};
|
||||
options = {
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var String, Number, Boolean;
|
||||
f(
|
||||
@@ -50,7 +56,9 @@ issue_269_in_scope: {
|
||||
}
|
||||
|
||||
strings_concat: {
|
||||
options = {unsafe: true};
|
||||
options = {
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
f(
|
||||
String(x + 'str'),
|
||||
@@ -64,3 +72,27 @@ strings_concat: {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
regexp: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
RegExp("foo");
|
||||
RegExp("bar", "ig");
|
||||
RegExp(foo);
|
||||
RegExp("bar", ig);
|
||||
RegExp("should", "fail");
|
||||
}
|
||||
expect: {
|
||||
/foo/;
|
||||
/bar/ig;
|
||||
RegExp(foo);
|
||||
RegExp("bar", ig);
|
||||
RegExp("should", "fail");
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:5,2]',
|
||||
]
|
||||
}
|
||||
|
||||
32
test/compress/issue-2719.js
Normal file
32
test/compress/issue-2719.js
Normal file
@@ -0,0 +1,32 @@
|
||||
warn: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return g();
|
||||
}
|
||||
function g() {
|
||||
return g["call" + "er"].arguments;
|
||||
}
|
||||
// 3
|
||||
console.log(f(1, 2, 3).length);
|
||||
}
|
||||
expect: {
|
||||
// TypeError: Cannot read property 'arguments' of null
|
||||
console.log(function g() {
|
||||
return g.caller.arguments;
|
||||
}().length);
|
||||
}
|
||||
expect_warnings: [
|
||||
"WARN: Function.protoype.caller not supported [test/compress/issue-2719.js:5,19]",
|
||||
"WARN: Function.protoype.arguments not supported [test/compress/issue-2719.js:5,19]",
|
||||
]
|
||||
}
|
||||
498
test/compress/issue-281.js
Normal file
498
test/compress/issue-281.js
Normal file
@@ -0,0 +1,498 @@
|
||||
collapse_vars_constants: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1(x) {
|
||||
var a = 4, b = x.prop, c = 5, d = sideeffect1(), e = sideeffect2();
|
||||
return b + (function() { return d - a * e - c; })();
|
||||
}
|
||||
function f2(x) {
|
||||
var a = 4, b = x.prop, c = 5, not_used = sideeffect1(), e = sideeffect2();
|
||||
return b + (function() { return -a * e - c; })();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1(x) {
|
||||
var b = x.prop, d = sideeffect1(), e = sideeffect2();
|
||||
return b + (d - 4 * e - 5);
|
||||
}
|
||||
function f2(x) {
|
||||
var b = x.prop;
|
||||
sideeffect1();
|
||||
return b + (-4 * sideeffect2() - 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modified: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f5(b) {
|
||||
var a = function() {
|
||||
return b;
|
||||
}();
|
||||
return b++ + a;
|
||||
}
|
||||
console.log(f5(1));
|
||||
}
|
||||
expect: {
|
||||
function f5(b) {
|
||||
var a = b;
|
||||
return b++ + a;
|
||||
}
|
||||
console.log(f5(1));
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
ref_scope: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var a = 1, b = 2, c = 3;
|
||||
var a = c++, b = b /= a;
|
||||
return function() {
|
||||
return a;
|
||||
}() + b;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var a = 1, b = 2, c = 3;
|
||||
b = b /= a = c++;
|
||||
return a + b;
|
||||
}());
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
safe_undefined: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
inline: true,
|
||||
unsafe: false,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
var a, c;
|
||||
console.log(function(undefined) {
|
||||
return function() {
|
||||
if (a)
|
||||
return b;
|
||||
if (c)
|
||||
return d;
|
||||
};
|
||||
}(1)());
|
||||
}
|
||||
expect: {
|
||||
var a, c;
|
||||
console.log(a ? b : c ? d : void 0);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
negate_iife_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
expression: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||
}
|
||||
expect: {
|
||||
t ? console.log(true) : console.log(false);
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_3_off: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
expression: true,
|
||||
inline: true,
|
||||
negate_iife: false,
|
||||
}
|
||||
input: {
|
||||
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||
}
|
||||
expect: {
|
||||
t ? console.log(true) : console.log(false);
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_4: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
expression: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||
(function(){
|
||||
console.log("something");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
t ? console.log(true) : console.log(false), void console.log("something");
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_5: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
expression: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
if ((function(){ return t })()) {
|
||||
foo(true);
|
||||
} else {
|
||||
bar(false);
|
||||
}
|
||||
(function(){
|
||||
console.log("something");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
t ? foo(true) : bar(false), void console.log("something");
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_5_off: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
expression: true,
|
||||
inline: true,
|
||||
negate_iife: false,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
if ((function(){ return t })()) {
|
||||
foo(true);
|
||||
} else {
|
||||
bar(false);
|
||||
}
|
||||
(function(){
|
||||
console.log("something");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
t ? foo(true) : bar(false), void console.log("something");
|
||||
}
|
||||
}
|
||||
|
||||
issue_1254_negate_iife_true: {
|
||||
options = {
|
||||
expression: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
return function() {
|
||||
console.log('test')
|
||||
};
|
||||
})()();
|
||||
}
|
||||
expect_exact: 'void console.log("test");'
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1254_negate_iife_nested: {
|
||||
options = {
|
||||
expression: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
return function() {
|
||||
console.log('test')
|
||||
};
|
||||
})()()()()();
|
||||
}
|
||||
expect_exact: '(void console.log("test"))()()();'
|
||||
}
|
||||
|
||||
negate_iife_issue_1073: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
new (function(a) {
|
||||
return function Foo() {
|
||||
this.x = a;
|
||||
console.log(this);
|
||||
};
|
||||
}(7))();
|
||||
}
|
||||
expect: {
|
||||
new function() {
|
||||
this.x = 7,
|
||||
console.log(this);
|
||||
}();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1288_side_effects: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
if (w) ;
|
||||
else {
|
||||
(function f() {})();
|
||||
}
|
||||
if (!x) {
|
||||
(function() {
|
||||
x = {};
|
||||
})();
|
||||
}
|
||||
if (y)
|
||||
(function() {})();
|
||||
else
|
||||
(function(z) {
|
||||
return z;
|
||||
})(0);
|
||||
}
|
||||
expect: {
|
||||
w;
|
||||
x || (x = {});
|
||||
y;
|
||||
}
|
||||
}
|
||||
|
||||
inner_var_for_in_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
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: {
|
||||
function f() {
|
||||
var a = 1, b = 2;
|
||||
for (b in x(1, b, c)) {
|
||||
var c = 3, d = 4;
|
||||
x(1, b, c, d);
|
||||
}
|
||||
x(1, b, c, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1595_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function f(a) {
|
||||
return g(a + 1);
|
||||
})(2);
|
||||
}
|
||||
expect: {
|
||||
g(3);
|
||||
}
|
||||
}
|
||||
|
||||
issue_1758: {
|
||||
options = {
|
||||
inline: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(c) {
|
||||
var undefined = 42;
|
||||
return function() {
|
||||
c--;
|
||||
c--, c.toString();
|
||||
return;
|
||||
}();
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function(c) {
|
||||
var undefined = 42;
|
||||
return c--, c--, void c.toString();
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
wrap_iife: {
|
||||
options = {
|
||||
inline: true,
|
||||
negate_iife: false,
|
||||
}
|
||||
beautify = {
|
||||
wrap_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
return function() {
|
||||
console.log('test')
|
||||
};
|
||||
})()();
|
||||
}
|
||||
expect_exact: 'void console.log("test");'
|
||||
}
|
||||
|
||||
wrap_iife_in_expression: {
|
||||
options = {
|
||||
inline: true,
|
||||
negate_iife: false,
|
||||
}
|
||||
beautify = {
|
||||
wrap_iife: true,
|
||||
}
|
||||
input: {
|
||||
foo = (function() {
|
||||
return bar();
|
||||
})();
|
||||
}
|
||||
expect_exact: 'foo=bar();'
|
||||
}
|
||||
|
||||
wrap_iife_in_return_call: {
|
||||
options = {
|
||||
inline: true,
|
||||
negate_iife: false,
|
||||
}
|
||||
beautify = {
|
||||
wrap_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
return (function() {
|
||||
console.log('test')
|
||||
})();
|
||||
})()();
|
||||
}
|
||||
expect_exact: '(void console.log("test"))();'
|
||||
}
|
||||
|
||||
pure_annotation_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
/*@__PURE__*/(function() {
|
||||
console.log("hello");
|
||||
}());
|
||||
}
|
||||
expect_exact: ""
|
||||
}
|
||||
|
||||
pure_annotation_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
/*@__PURE__*/(function(n) {
|
||||
console.log("hello", n);
|
||||
}(42));
|
||||
}
|
||||
expect_exact: ""
|
||||
}
|
||||
|
||||
drop_fargs: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
keep_fargs: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
!function(a_1) {
|
||||
a++;
|
||||
}(a++ + (a && a.var));
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
++a && a.var, a++;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
|
||||
keep_fargs: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
keep_fargs: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
!function(a_1) {
|
||||
a++;
|
||||
}(a++ + (a && a.var));
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
++a && a.var, a++;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
37
test/compress/issue-2871.js
Normal file
37
test/compress/issue-2871.js
Normal file
@@ -0,0 +1,37 @@
|
||||
comparison_with_undefined: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
a == undefined;
|
||||
a != undefined;
|
||||
a === undefined;
|
||||
a !== undefined;
|
||||
|
||||
undefined == a;
|
||||
undefined != a;
|
||||
undefined === a;
|
||||
undefined !== a;
|
||||
|
||||
void 0 == a;
|
||||
void 0 != a;
|
||||
void 0 === a;
|
||||
void 0 !== a;
|
||||
}
|
||||
expect: {
|
||||
null == a;
|
||||
null != a;
|
||||
void 0 === a;
|
||||
void 0 !== a;
|
||||
|
||||
null == a;
|
||||
null != a;
|
||||
void 0 === a;
|
||||
void 0 !== a;
|
||||
|
||||
null == a;
|
||||
null != a;
|
||||
void 0 === a;
|
||||
void 0 !== a;
|
||||
}
|
||||
}
|
||||
21
test/compress/issue-2989.js
Normal file
21
test/compress/issue-2989.js
Normal file
@@ -0,0 +1,21 @@
|
||||
inline_script_off: {
|
||||
beautify = {
|
||||
inline_script: false,
|
||||
}
|
||||
input: {
|
||||
console.log("</sCrIpT>");
|
||||
}
|
||||
expect_exact: 'console.log("</sCrIpT>");'
|
||||
expect_stdout: "</sCrIpT>"
|
||||
}
|
||||
|
||||
inline_script_on: {
|
||||
beautify = {
|
||||
inline_script: true,
|
||||
}
|
||||
input: {
|
||||
console.log("</sCrIpT>");
|
||||
}
|
||||
expect_exact: 'console.log("<\\/sCrIpT>");'
|
||||
expect_stdout: "</sCrIpT>"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
collapse: {
|
||||
options = {
|
||||
cascade: true,
|
||||
collapse_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -41,7 +41,7 @@ collapse: {
|
||||
return void 0 !== ('function' === typeof b ? b() : b) && c();
|
||||
}
|
||||
function f2(b) {
|
||||
return b = c(), 'stirng' == typeof ('function' === typeof b ? b() : b) && d();
|
||||
return 'stirng' == typeof ('function' === typeof (b = c()) ? b() : b) && d();
|
||||
}
|
||||
function f3(c) {
|
||||
var a;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
issue_44_valid_ast_1: {
|
||||
options = { unused: true };
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function a(b) {
|
||||
for (var i = 0, e = b.qoo(); ; i++) {}
|
||||
@@ -14,7 +16,9 @@ issue_44_valid_ast_1: {
|
||||
}
|
||||
|
||||
issue_44_valid_ast_2: {
|
||||
options = { unused: true };
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function a(b) {
|
||||
if (foo) for (var i = 0, e = b.qoo(); ; i++) {}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
keep_continue: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true
|
||||
};
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
while (a) {
|
||||
if (b) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
NaN_and_Infinity_must_have_parens: {
|
||||
options = {};
|
||||
options = {}
|
||||
input: {
|
||||
Infinity.toString();
|
||||
NaN.toString();
|
||||
@@ -11,7 +11,7 @@ NaN_and_Infinity_must_have_parens: {
|
||||
}
|
||||
|
||||
NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: {
|
||||
options = {};
|
||||
options = {}
|
||||
input: {
|
||||
var Infinity, NaN;
|
||||
Infinity.toString();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
issue_611: {
|
||||
options = {
|
||||
sequences: true,
|
||||
side_effects: true
|
||||
};
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
define(function() {
|
||||
function fn() {}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
wrongly_optimized: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
booleans: true,
|
||||
evaluate: true
|
||||
};
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
function func() {
|
||||
foo();
|
||||
@@ -17,6 +17,6 @@ wrongly_optimized: {
|
||||
foo();
|
||||
}
|
||||
// TODO: optimize to `func(), bar()`
|
||||
(func(), 0) || bar();
|
||||
(func(), 1) && bar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ drop_value: {
|
||||
|
||||
wrongly_optimized: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
expression: true,
|
||||
}
|
||||
@@ -100,7 +100,7 @@ wrongly_optimized: {
|
||||
foo();
|
||||
}
|
||||
// TODO: optimize to `func(), bar()`
|
||||
if (func(), !0) bar();
|
||||
if (func(), 1) bar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ negate_iife_5_off: {
|
||||
expression: true,
|
||||
negate_iife: false,
|
||||
sequences: true,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
if ((function(){ return t })()) {
|
||||
foo(true);
|
||||
@@ -248,7 +248,9 @@ issue_1254_negate_iife_nested: {
|
||||
conditional: {
|
||||
options = {
|
||||
expression: true,
|
||||
pure_funcs: [ "pure" ],
|
||||
pure_funcs: [
|
||||
"pure"
|
||||
],
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
|
||||
@@ -1,37 +1,45 @@
|
||||
dont_reuse_prop: {
|
||||
mangle_props = {
|
||||
regex: /asd/
|
||||
};
|
||||
|
||||
mangle = {
|
||||
properties: {
|
||||
regex: /asd/,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
"aaaaaaaaaabbbbb";
|
||||
var obj = {};
|
||||
obj.a = 123;
|
||||
obj.asd = 256;
|
||||
console.log(obj.a);
|
||||
}
|
||||
expect: {
|
||||
"aaaaaaaaaabbbbb";
|
||||
var obj = {};
|
||||
obj.a = 123;
|
||||
obj.b = 256;
|
||||
console.log(obj.a);
|
||||
}
|
||||
expect_stdout: "123"
|
||||
}
|
||||
|
||||
unmangleable_props_should_always_be_reserved: {
|
||||
mangle_props = {
|
||||
regex: /asd/
|
||||
};
|
||||
|
||||
mangle = {
|
||||
properties: {
|
||||
regex: /asd/,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
"aaaaaaaaaabbbbb";
|
||||
var obj = {};
|
||||
obj.asd = 256;
|
||||
obj.a = 123;
|
||||
console.log(obj.a);
|
||||
}
|
||||
expect: {
|
||||
"aaaaaaaaaabbbbb";
|
||||
var obj = {};
|
||||
obj.b = 256;
|
||||
obj.a = 123;
|
||||
console.log(obj.a);
|
||||
}
|
||||
expect_stdout: "123"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
negate_booleans_1: {
|
||||
options = {
|
||||
comparisons: true
|
||||
};
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
var a = !a || !b || !c || !d || !e || !f;
|
||||
}
|
||||
@@ -12,8 +12,8 @@ negate_booleans_1: {
|
||||
|
||||
negate_booleans_2: {
|
||||
options = {
|
||||
comparisons: true
|
||||
};
|
||||
comparisons: true,
|
||||
}
|
||||
input: {
|
||||
var match = !x && // should not touch this one
|
||||
(!z || c) &&
|
||||
|
||||
@@ -1,11 +1,31 @@
|
||||
remove_redundant_sequence_items: {
|
||||
options = { side_effects: true };
|
||||
remove_sequence: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(0, 1, eval)();
|
||||
(0, 1, logThis)();
|
||||
(0, 1, _decorators.logThis)();
|
||||
}
|
||||
expect: {
|
||||
eval();
|
||||
logThis();
|
||||
(0, _decorators.logThis)();
|
||||
}
|
||||
}
|
||||
|
||||
remove_redundant_sequence_items: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
(0, 1, eval)();
|
||||
(0, 1, logThis)();
|
||||
(0, 1, _decorators.logThis)();
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
(0, eval)();
|
||||
logThis();
|
||||
(0, _decorators.logThis)();
|
||||
@@ -13,13 +33,17 @@ remove_redundant_sequence_items: {
|
||||
}
|
||||
|
||||
dont_remove_this_binding_sequence: {
|
||||
options = { side_effects: true };
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
(0, eval)();
|
||||
(0, logThis)();
|
||||
(0, _decorators.logThis)();
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
(0, eval)();
|
||||
logThis();
|
||||
(0, _decorators.logThis)();
|
||||
|
||||
@@ -2,26 +2,25 @@ dont_mangle_arguments: {
|
||||
mangle = {
|
||||
};
|
||||
options = {
|
||||
sequences : true,
|
||||
properties : true,
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: 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,
|
||||
keep_fargs: true,
|
||||
keep_fnames: false,
|
||||
loops: true,
|
||||
negate_iife: false,
|
||||
properties: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
negate_iife : false
|
||||
};
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(){
|
||||
var arguments = arguments, not_arguments = 9;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
keep_var_for_in: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
unused: true
|
||||
};
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(obj){
|
||||
var foo = 5;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
this_binding_conditionals: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true
|
||||
};
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
(1 && a)();
|
||||
(0 || a)();
|
||||
(0 || 1 && a)();
|
||||
@@ -25,6 +27,7 @@ this_binding_conditionals: {
|
||||
(1 ? eval : 0)();
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
a();
|
||||
a();
|
||||
a();
|
||||
@@ -51,13 +54,16 @@ this_binding_collapse_vars: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
};
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
var c = a; c();
|
||||
var d = a.b; d();
|
||||
var e = eval; e();
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
a();
|
||||
(0, a.b)();
|
||||
(0, eval)();
|
||||
@@ -66,32 +72,89 @@ this_binding_collapse_vars: {
|
||||
|
||||
this_binding_side_effects: {
|
||||
options = {
|
||||
side_effects : true
|
||||
};
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(function(foo) {
|
||||
(0, foo)();
|
||||
(0, foo.bar)();
|
||||
(0, eval)('console.log(foo);');
|
||||
(0, eval)("console.log(foo);");
|
||||
}());
|
||||
(function(foo) {
|
||||
"use strict";
|
||||
(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);');
|
||||
(0, eval)("console.log(foo);");
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
(function(foo) {
|
||||
foo();
|
||||
(0, foo.bar)();
|
||||
(0, eval)('console.log(foo);');
|
||||
eval("console.log(foo);");
|
||||
}());
|
||||
(function(foo) {
|
||||
"use strict";
|
||||
foo();
|
||||
(0, foo.bar)();
|
||||
(0, eval)("console.log(foo);");
|
||||
}());
|
||||
(function(foo) {
|
||||
var eval = console;
|
||||
foo();
|
||||
(0, foo.bar)();
|
||||
(0, eval)('console.log(foo);');
|
||||
eval("console.log(foo);");
|
||||
}());
|
||||
}
|
||||
}
|
||||
|
||||
this_binding_sequences: {
|
||||
options = {
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(typeof function() {
|
||||
return eval("this");
|
||||
}());
|
||||
console.log(typeof function() {
|
||||
"use strict";
|
||||
return eval("this");
|
||||
}());
|
||||
console.log(typeof function() {
|
||||
return (0, eval)("this");
|
||||
}());
|
||||
console.log(typeof function() {
|
||||
"use strict";
|
||||
return (0, eval)("this");
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(typeof function() {
|
||||
return eval("this");
|
||||
}()),
|
||||
console.log(typeof function() {
|
||||
"use strict";
|
||||
return eval("this");
|
||||
}()),
|
||||
console.log(typeof function() {
|
||||
return eval("this");
|
||||
}()),
|
||||
console.log(typeof function() {
|
||||
"use strict";
|
||||
return (0, eval)("this");
|
||||
}());
|
||||
}
|
||||
expect_stdout: [
|
||||
"object",
|
||||
"undefined",
|
||||
"object",
|
||||
"object",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
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
|
||||
};
|
||||
booleans: true,
|
||||
collapse_vars: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: true,
|
||||
loops: true,
|
||||
properties: true,
|
||||
sequences: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
var e = 7;
|
||||
@@ -46,7 +58,10 @@ eval_collapse_vars: {
|
||||
}
|
||||
|
||||
eval_unused: {
|
||||
options = { unused: true, keep_fargs: false };
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1(a, eval, c, d, e) {
|
||||
return a('c') + eval;
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
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
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: true,
|
||||
loops: true,
|
||||
properties: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
@@ -30,9 +41,20 @@ issue979_reported: {
|
||||
|
||||
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
|
||||
booleans: true,
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
keep_fargs: true,
|
||||
loops: true,
|
||||
properties: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f3() {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
labels_1: {
|
||||
options = { if_return: true, conditionals: true, dead_code: true };
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
out: {
|
||||
if (foo) break out;
|
||||
@@ -13,7 +17,11 @@ labels_1: {
|
||||
}
|
||||
|
||||
labels_2: {
|
||||
options = { if_return: true, conditionals: true, dead_code: true };
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
out: {
|
||||
if (foo) print("stuff");
|
||||
@@ -30,7 +38,11 @@ labels_2: {
|
||||
}
|
||||
|
||||
labels_3: {
|
||||
options = { if_return: true, conditionals: true, dead_code: true };
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
for (var i = 0; i < 5; ++i) {
|
||||
if (i < 3) continue;
|
||||
@@ -45,7 +57,11 @@ labels_3: {
|
||||
}
|
||||
|
||||
labels_4: {
|
||||
options = { if_return: true, conditionals: true, dead_code: true };
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
out: for (var i = 0; i < 5; ++i) {
|
||||
if (i < 3) continue out;
|
||||
@@ -60,7 +76,11 @@ labels_4: {
|
||||
}
|
||||
|
||||
labels_5: {
|
||||
options = { if_return: true, conditionals: true, dead_code: true };
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
}
|
||||
// should keep the break-s in the following
|
||||
input: {
|
||||
while (foo) {
|
||||
@@ -92,7 +112,11 @@ labels_6: {
|
||||
}
|
||||
|
||||
labels_7: {
|
||||
options = { if_return: true, conditionals: true, dead_code: true };
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
while (foo) {
|
||||
x();
|
||||
@@ -109,7 +133,11 @@ labels_7: {
|
||||
}
|
||||
|
||||
labels_8: {
|
||||
options = { if_return: true, conditionals: true, dead_code: true };
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
while (foo) {
|
||||
x();
|
||||
@@ -127,7 +155,11 @@ labels_8: {
|
||||
}
|
||||
|
||||
labels_9: {
|
||||
options = { if_return: true, conditionals: true, dead_code: true };
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
out: while (foo) {
|
||||
x();
|
||||
@@ -146,7 +178,11 @@ labels_9: {
|
||||
}
|
||||
|
||||
labels_10: {
|
||||
options = { if_return: true, conditionals: true, dead_code: true };
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
out: while (foo) {
|
||||
x();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
while_becomes_for: {
|
||||
options = { loops: true };
|
||||
options = {
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
while (foo()) bar();
|
||||
}
|
||||
@@ -9,7 +11,9 @@ while_becomes_for: {
|
||||
}
|
||||
|
||||
drop_if_break_1: {
|
||||
options = { loops: true };
|
||||
options = {
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
for (;;)
|
||||
if (foo()) break;
|
||||
@@ -20,7 +24,9 @@ drop_if_break_1: {
|
||||
}
|
||||
|
||||
drop_if_break_2: {
|
||||
options = { loops: true };
|
||||
options = {
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
for (;bar();)
|
||||
if (foo()) break;
|
||||
@@ -31,7 +37,9 @@ drop_if_break_2: {
|
||||
}
|
||||
|
||||
drop_if_break_3: {
|
||||
options = { loops: true };
|
||||
options = {
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
for (;bar();) {
|
||||
if (foo()) break;
|
||||
@@ -48,7 +56,10 @@ drop_if_break_3: {
|
||||
}
|
||||
|
||||
drop_if_break_4: {
|
||||
options = { loops: true, sequences: true };
|
||||
options = {
|
||||
loops: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
for (;bar();) {
|
||||
x();
|
||||
@@ -64,7 +75,9 @@ drop_if_break_4: {
|
||||
}
|
||||
|
||||
drop_if_else_break_1: {
|
||||
options = { loops: true };
|
||||
options = {
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
for (;;) if (foo()) bar(); else break;
|
||||
}
|
||||
@@ -74,7 +87,9 @@ drop_if_else_break_1: {
|
||||
}
|
||||
|
||||
drop_if_else_break_2: {
|
||||
options = { loops: true };
|
||||
options = {
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
for (;bar();) {
|
||||
if (foo()) baz();
|
||||
@@ -87,7 +102,9 @@ drop_if_else_break_2: {
|
||||
}
|
||||
|
||||
drop_if_else_break_3: {
|
||||
options = { loops: true };
|
||||
options = {
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
for (;bar();) {
|
||||
if (foo()) baz();
|
||||
@@ -106,7 +123,10 @@ drop_if_else_break_3: {
|
||||
}
|
||||
|
||||
drop_if_else_break_4: {
|
||||
options = { loops: true, sequences: true };
|
||||
options = {
|
||||
loops: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
for (;bar();) {
|
||||
x();
|
||||
@@ -123,7 +143,9 @@ drop_if_else_break_4: {
|
||||
}
|
||||
|
||||
parse_do_while_with_semicolon: {
|
||||
options = { loops: false };
|
||||
options = {
|
||||
loops: false,
|
||||
}
|
||||
input: {
|
||||
do {
|
||||
x();
|
||||
@@ -135,7 +157,9 @@ parse_do_while_with_semicolon: {
|
||||
}
|
||||
|
||||
parse_do_while_without_semicolon: {
|
||||
options = { loops: false };
|
||||
options = {
|
||||
loops: false,
|
||||
}
|
||||
input: {
|
||||
do {
|
||||
x();
|
||||
@@ -148,10 +172,12 @@ parse_do_while_without_semicolon: {
|
||||
|
||||
evaluate: {
|
||||
options = {
|
||||
loops: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
};
|
||||
loops: true,
|
||||
passes: 2,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
while (true) {
|
||||
a();
|
||||
@@ -292,10 +318,10 @@ issue_186_beautify_ie8: {
|
||||
]
|
||||
}
|
||||
|
||||
issue_186_bracketize: {
|
||||
issue_186_braces: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
bracketize: true,
|
||||
braces: true,
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
@@ -312,10 +338,10 @@ issue_186_bracketize: {
|
||||
expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else{bar()}'
|
||||
}
|
||||
|
||||
issue_186_bracketize_ie8: {
|
||||
issue_186_braces_ie8: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
bracketize: true,
|
||||
braces: true,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
@@ -332,10 +358,10 @@ issue_186_bracketize_ie8: {
|
||||
expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else{bar()}'
|
||||
}
|
||||
|
||||
issue_186_beautify_bracketize: {
|
||||
issue_186_beautify_braces: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
bracketize: true,
|
||||
braces: true,
|
||||
ie8: false,
|
||||
}
|
||||
input: {
|
||||
@@ -364,10 +390,10 @@ issue_186_beautify_bracketize: {
|
||||
]
|
||||
}
|
||||
|
||||
issue_186_beautify_bracketize_ie8: {
|
||||
issue_186_beautify_braces_ie8: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
bracketize: true,
|
||||
braces: true,
|
||||
ie8: true,
|
||||
}
|
||||
input: {
|
||||
@@ -436,3 +462,187 @@ do_switch: {
|
||||
} while (false);
|
||||
}
|
||||
}
|
||||
|
||||
in_parenthesis_1: {
|
||||
input: {
|
||||
for (("foo" in {});0;);
|
||||
}
|
||||
expect_exact: 'for(("foo"in{});0;);'
|
||||
}
|
||||
|
||||
in_parenthesis_2: {
|
||||
input: {
|
||||
for ((function(){ "foo" in {}; });0;);
|
||||
}
|
||||
expect_exact: 'for(function(){"foo"in{}};0;);'
|
||||
}
|
||||
|
||||
init_side_effects: {
|
||||
options = {
|
||||
loops: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
for (function() {}(), i = 0; i < 5; i++) console.log(i);
|
||||
for (function() {}(); i < 10; i++) console.log(i);
|
||||
}
|
||||
expect: {
|
||||
for (i = 0; i < 5; i++) console.log(i);
|
||||
for (; i < 10; i++) console.log(i);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_condition: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
for (var a = 0, b = 5; (a += 1, 3) - 3 && b > 0; b--) {
|
||||
var c = function() {
|
||||
b--;
|
||||
}(a++);
|
||||
}
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var c;
|
||||
var a = 0, b = 5;
|
||||
a += 1, 0,
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_2740_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
for (; ; ) break;
|
||||
for (a(); ; ) break;
|
||||
for (; b(); ) break;
|
||||
for (c(); d(); ) break;
|
||||
for (; ; e()) break;
|
||||
for (f(); ; g()) break;
|
||||
for (; h(); i()) break;
|
||||
for (j(); k(); l()) break;
|
||||
}
|
||||
expect: {
|
||||
a();
|
||||
b();
|
||||
c();
|
||||
d();
|
||||
f();
|
||||
h();
|
||||
j();
|
||||
k();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2740_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
}
|
||||
input: {
|
||||
L1: while (x()) {
|
||||
break L1;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
x();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2740_3: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
L1: for (var x = 0; x < 3; x++) {
|
||||
L2: for (var y = 0; y < 2; y++) {
|
||||
break L1;
|
||||
}
|
||||
}
|
||||
console.log(x, y);
|
||||
}
|
||||
expect: {
|
||||
L1: for (var x = 0; x < 3; x++)
|
||||
for (var y = 0; y < 2; y++)
|
||||
break L1;
|
||||
console.log(x, y);
|
||||
}
|
||||
expect_stdout: "0 0"
|
||||
}
|
||||
|
||||
issue_2740_4: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
}
|
||||
input: {
|
||||
L1: for (var x = 0; x < 3; x++) {
|
||||
L2: for (var y = 0; y < 2; y++) {
|
||||
break L2;
|
||||
}
|
||||
}
|
||||
console.log(x, y);
|
||||
}
|
||||
expect: {
|
||||
for (var x = 0; x < 3; x++) {
|
||||
var y = 0;
|
||||
y < 2;
|
||||
}
|
||||
console.log(x, y);
|
||||
}
|
||||
expect_stdout: "3 0"
|
||||
}
|
||||
|
||||
issue_2740_5: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
}
|
||||
input: {
|
||||
L1: for (var x = 0; x < 3; x++) {
|
||||
break L1;
|
||||
L2: for (var y = 0; y < 2; y++) {
|
||||
break L2;
|
||||
}
|
||||
}
|
||||
console.log(x, y);
|
||||
}
|
||||
expect: {
|
||||
var x = 0;
|
||||
x < 3;
|
||||
var y;
|
||||
console.log(x,y);
|
||||
}
|
||||
expect_stdout: "0 undefined"
|
||||
}
|
||||
|
||||
issue_2904: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
do {
|
||||
console.log(a);
|
||||
} while (--a);
|
||||
}
|
||||
expect: {
|
||||
for (var a = 1; console.log(a), --a;);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@ too_short: {
|
||||
}
|
||||
}
|
||||
expect_exact: [
|
||||
'function f(a){',
|
||||
'return{',
|
||||
'c:42,',
|
||||
'd:a(),',
|
||||
'e:"foo"}}',
|
||||
"function f(",
|
||||
"a){return{",
|
||||
"c:42,d:a(",
|
||||
'),e:"foo"}',
|
||||
"}",
|
||||
]
|
||||
expect_warnings: [
|
||||
"WARN: Output exceeds 10 characters"
|
||||
"WARN: Output exceeds 10 characters",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -29,11 +29,25 @@ just_enough: {
|
||||
}
|
||||
}
|
||||
expect_exact: [
|
||||
'function f(a){',
|
||||
'return{c:42,',
|
||||
"function f(a){",
|
||||
"return{c:42,",
|
||||
'd:a(),e:"foo"}',
|
||||
'}',
|
||||
]
|
||||
expect_warnings: [
|
||||
"}",
|
||||
]
|
||||
expect_warnings: []
|
||||
}
|
||||
|
||||
issue_304: {
|
||||
beautify = {
|
||||
max_line_len: 10,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 0, c = 0, d = 0, e = 0;
|
||||
}
|
||||
expect_exact: [
|
||||
"var a=0,",
|
||||
"b=0,c=0,",
|
||||
"d=0,e=0;",
|
||||
]
|
||||
expect_warnings: []
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
negate_iife_1: {
|
||||
options = {
|
||||
negate_iife: true
|
||||
};
|
||||
negate_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function(){ stuff() })();
|
||||
}
|
||||
@@ -13,7 +13,7 @@ negate_iife_1: {
|
||||
negate_iife_1_off: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
(function(){ stuff() })();
|
||||
}
|
||||
@@ -22,8 +22,9 @@ negate_iife_1_off: {
|
||||
|
||||
negate_iife_2: {
|
||||
options = {
|
||||
negate_iife: true
|
||||
};
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function(){ return {} })().x = 10;
|
||||
}
|
||||
@@ -32,6 +33,7 @@ negate_iife_2: {
|
||||
|
||||
negate_iife_2_side_effects: {
|
||||
options = {
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
side_effects: true,
|
||||
}
|
||||
@@ -43,9 +45,9 @@ negate_iife_2_side_effects: {
|
||||
|
||||
negate_iife_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
negate_iife: true,
|
||||
conditionals: true
|
||||
};
|
||||
}
|
||||
input: {
|
||||
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||
}
|
||||
@@ -58,13 +60,14 @@ negate_iife_3_evaluate: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
}
|
||||
input: {
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
}
|
||||
expect: {
|
||||
console.log(true);
|
||||
true, console.log(true);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
@@ -85,9 +88,9 @@ negate_iife_3_side_effects: {
|
||||
|
||||
negate_iife_3_off: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
conditionals: true,
|
||||
};
|
||||
negate_iife: false,
|
||||
}
|
||||
input: {
|
||||
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||
}
|
||||
@@ -100,23 +103,24 @@ negate_iife_3_off_evaluate: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
negate_iife: false,
|
||||
}
|
||||
input: {
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
}
|
||||
expect: {
|
||||
console.log(true);
|
||||
true, console.log(true);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
negate_iife_4: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
conditionals: true,
|
||||
sequences: true
|
||||
};
|
||||
negate_iife: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||
(function(){
|
||||
@@ -132,11 +136,11 @@ negate_iife_4: {
|
||||
|
||||
sequence_off: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
conditionals: true,
|
||||
sequences: true,
|
||||
negate_iife: false,
|
||||
passes: 2,
|
||||
};
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||
@@ -167,10 +171,10 @@ sequence_off: {
|
||||
|
||||
negate_iife_5: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
negate_iife: true,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
if ((function(){ return t })()) {
|
||||
foo(true);
|
||||
@@ -190,10 +194,10 @@ negate_iife_5: {
|
||||
|
||||
negate_iife_5_off: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
negate_iife: false,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
if ((function(){ return t })()) {
|
||||
foo(true);
|
||||
@@ -213,10 +217,10 @@ negate_iife_5_off: {
|
||||
|
||||
negate_iife_nested: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
negate_iife: true,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
function Foo(f) {
|
||||
this.f = f;
|
||||
@@ -246,10 +250,10 @@ negate_iife_nested: {
|
||||
|
||||
negate_iife_nested_off: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
negate_iife: false,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
function Foo(f) {
|
||||
this.f = f;
|
||||
@@ -279,10 +283,10 @@ negate_iife_nested_off: {
|
||||
|
||||
negate_iife_issue_1073: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
negate_iife: true,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
new (function(a) {
|
||||
return function Foo() {
|
||||
@@ -352,7 +356,7 @@ issue_1288: {
|
||||
conditionals: true,
|
||||
negate_iife: true,
|
||||
side_effects: false,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
if (w) ;
|
||||
else {
|
||||
|
||||
@@ -36,7 +36,9 @@ new_statements_3: {
|
||||
}
|
||||
|
||||
new_with_rewritten_true_value: {
|
||||
options = { booleans: true }
|
||||
options = {
|
||||
booleans: true,
|
||||
}
|
||||
input: {
|
||||
new true;
|
||||
}
|
||||
@@ -82,3 +84,19 @@ new_with_unary_prefix: {
|
||||
}
|
||||
expect_exact: 'var bar=(+new Date).toString(32);';
|
||||
}
|
||||
|
||||
dot_parenthesis_1: {
|
||||
input: {
|
||||
console.log(new (Math.random().constructor) instanceof Number);
|
||||
}
|
||||
expect_exact: "console.log(new(Math.random().constructor)instanceof Number);"
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
dot_parenthesis_2: {
|
||||
input: {
|
||||
console.log(typeof new function(){Math.random()}.constructor);
|
||||
}
|
||||
expect_exact: "console.log(typeof new function(){Math.random()}.constructor);"
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
eval_let: {
|
||||
eval_let_6: {
|
||||
input: {
|
||||
eval("let a;");
|
||||
console.log();
|
||||
@@ -10,3 +10,29 @@ eval_let: {
|
||||
expect_stdout: ""
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
eval_let_4: {
|
||||
input: {
|
||||
eval("let a;");
|
||||
console.log();
|
||||
}
|
||||
expect: {
|
||||
eval("let a;");
|
||||
console.log();
|
||||
}
|
||||
expect_stdout: SyntaxError("Block-scoped declarations (let, const, function, class) not yet supported outside strict mode")
|
||||
node_version: "4"
|
||||
}
|
||||
|
||||
eval_let_0: {
|
||||
input: {
|
||||
eval("let a;");
|
||||
console.log();
|
||||
}
|
||||
expect: {
|
||||
eval("let a;");
|
||||
console.log();
|
||||
}
|
||||
expect_stdout: SyntaxError("Unexpected identifier")
|
||||
node_version: "<=0.12"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
hex_numbers_in_parentheses_for_prototype_functions: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
(-2);
|
||||
(-2).toFixed(0);
|
||||
|
||||
@@ -9,13 +13,37 @@ hex_numbers_in_parentheses_for_prototype_functions: {
|
||||
(0.2);
|
||||
(0.2).toFixed(0);
|
||||
|
||||
(2.34e20);
|
||||
(2.34e20).toFixed(0);
|
||||
|
||||
(0.00000002);
|
||||
(0.00000002).toFixed(0);
|
||||
|
||||
(1000000000000000128);
|
||||
(1000000000000000128).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);"
|
||||
}
|
||||
expect_exact: [
|
||||
"function f() {",
|
||||
" -2;",
|
||||
" (-2).toFixed(0);",
|
||||
" 2;",
|
||||
" 2..toFixed(0);",
|
||||
" .2;",
|
||||
" .2.toFixed(0);",
|
||||
" 234e18;",
|
||||
" 234e18.toFixed(0);",
|
||||
" 2e-8;",
|
||||
" 2e-8.toFixed(0);",
|
||||
" 0xde0b6b3a7640080;",
|
||||
" (0xde0b6b3a7640080).toFixed(0);",
|
||||
" -0xde0b6b3a7640080;",
|
||||
" (-0xde0b6b3a7640080).toFixed(0);",
|
||||
"}",
|
||||
]
|
||||
}
|
||||
|
||||
comparisons: {
|
||||
|
||||
181
test/compress/preserve_line.js
Normal file
181
test/compress/preserve_line.js
Normal file
@@ -0,0 +1,181 @@
|
||||
return_1: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
preserve_line: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f() {
|
||||
return (
|
||||
f.toString() != 42
|
||||
);
|
||||
}());
|
||||
}
|
||||
expect_exact: [
|
||||
"console.log(function f(){",
|
||||
"",
|
||||
"return 42!=f.toString()}());",
|
||||
]
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
return_2: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
preserve_line: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f() {
|
||||
return (
|
||||
f.toString() != 42
|
||||
);
|
||||
}());
|
||||
}
|
||||
expect_exact: [
|
||||
"console.log(function f() {",
|
||||
"",
|
||||
" return 42 != f.toString();",
|
||||
"}());",
|
||||
]
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
return_3: {
|
||||
options = {}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
preserve_line: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f() {
|
||||
return (
|
||||
f.toString() != 42
|
||||
);
|
||||
}());
|
||||
}
|
||||
expect_exact: [
|
||||
"console.log(function f(){",
|
||||
"",
|
||||
"return 42!=f.toString()}());",
|
||||
]
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
return_4: {
|
||||
options = {}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
preserve_line: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function f() {
|
||||
return (
|
||||
f.toString() != 42
|
||||
);
|
||||
}());
|
||||
}
|
||||
expect_exact: [
|
||||
"console.log(function f() {",
|
||||
"",
|
||||
" return 42 != f.toString();",
|
||||
"}());",
|
||||
]
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
return_5: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
preserve_line: true,
|
||||
}
|
||||
input: {
|
||||
_is_selected = function(tags, slug) {
|
||||
var ref;
|
||||
return (ref = _.find(tags, {
|
||||
slug: slug
|
||||
})) != null ? ref.selected : void 0;
|
||||
};
|
||||
}
|
||||
expect_exact: [
|
||||
"_is_selected=function(tags,slug){",
|
||||
"var ref",
|
||||
"",
|
||||
"",
|
||||
";return null!=(ref=_.find(tags,{slug:slug}))?ref.selected:void 0};",
|
||||
]
|
||||
}
|
||||
|
||||
return_6: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
preserve_line: true,
|
||||
}
|
||||
input: {
|
||||
_is_selected = function(tags, slug) {
|
||||
var ref;
|
||||
return (ref = _.find(tags, {
|
||||
slug: slug
|
||||
})) != null ? ref.selected : void 0;
|
||||
};
|
||||
}
|
||||
expect_exact: [
|
||||
"_is_selected = function(tags, slug) {",
|
||||
" var ref;",
|
||||
"",
|
||||
"",
|
||||
" return null != (ref = _.find(tags, {",
|
||||
" slug: slug",
|
||||
" })) ? ref.selected : void 0;",
|
||||
"};",
|
||||
]
|
||||
}
|
||||
|
||||
return_7: {
|
||||
options = {}
|
||||
mangle = {}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
preserve_line: true,
|
||||
}
|
||||
input: {
|
||||
_is_selected = function(tags, slug) {
|
||||
var ref;
|
||||
return (ref = _.find(tags, {
|
||||
slug: slug
|
||||
})) != null ? ref.selected : void 0;
|
||||
};
|
||||
}
|
||||
expect_exact: [
|
||||
"_is_selected=function(e,l){",
|
||||
"var n",
|
||||
"",
|
||||
"",
|
||||
";return null!=(n=_.find(e,{slug:l}))?n.selected:void 0};",
|
||||
]
|
||||
}
|
||||
|
||||
return_8: {
|
||||
options = {}
|
||||
mangle = {}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
preserve_line: true,
|
||||
}
|
||||
input: {
|
||||
_is_selected = function(tags, slug) {
|
||||
var ref;
|
||||
return (ref = _.find(tags, {
|
||||
slug: slug
|
||||
})) != null ? ref.selected : void 0;
|
||||
};
|
||||
}
|
||||
expect_exact: [
|
||||
"_is_selected = function(e, l) {",
|
||||
" var n;",
|
||||
"",
|
||||
"",
|
||||
" return null != (n = _.find(e, {",
|
||||
" slug: l",
|
||||
" })) ? n.selected : void 0;",
|
||||
"};",
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -293,3 +293,352 @@ unary: {
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2629_1: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
beautify = {
|
||||
comments: "all",
|
||||
}
|
||||
input: {
|
||||
/*@__PURE__*/ a();
|
||||
/*@__PURE__*/ (b());
|
||||
(/*@__PURE__*/ c)();
|
||||
(/*@__PURE__*/ d());
|
||||
}
|
||||
expect_exact: [
|
||||
"/* */c();",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2629_2: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
beautify = {
|
||||
comments: "all",
|
||||
}
|
||||
input: {
|
||||
/*@__PURE__*/ a(1)(2)(3);
|
||||
/*@__PURE__*/ (b(1))(2)(3);
|
||||
/*@__PURE__*/ (c(1)(2))(3);
|
||||
/*@__PURE__*/ (d(1)(2)(3));
|
||||
(/*@__PURE__*/ e)(1)(2)(3);
|
||||
(/*@__PURE__*/ f(1))(2)(3);
|
||||
(/*@__PURE__*/ g(1)(2))(3);
|
||||
(/*@__PURE__*/ h(1)(2)(3));
|
||||
}
|
||||
expect_exact: [
|
||||
"/* */e(1)(2)(3);",
|
||||
"/* */f(1)(2)(3);",
|
||||
"/* */g(1)(2)(3);",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2629_3: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
beautify = {
|
||||
comments: "all",
|
||||
}
|
||||
input: {
|
||||
/*@__PURE__*/ a.x(1).y(2).z(3);
|
||||
/*@__PURE__*/ (b.x)(1).y(2).z(3);
|
||||
/*@__PURE__*/ (c.x(1)).y(2).z(3);
|
||||
/*@__PURE__*/ (d.x(1).y)(2).z(3);
|
||||
/*@__PURE__*/ (e.x(1).y(2)).z(3);
|
||||
/*@__PURE__*/ (f.x(1).y(2).z)(3);
|
||||
/*@__PURE__*/ (g.x(1).y(2).z(3));
|
||||
(/*@__PURE__*/ h).x(1).y(2).z(3);
|
||||
(/*@__PURE__*/ i.x)(1).y(2).z(3);
|
||||
(/*@__PURE__*/ j.x(1)).y(2).z(3);
|
||||
(/*@__PURE__*/ k.x(1).y)(2).z(3);
|
||||
(/*@__PURE__*/ l.x(1).y(2)).z(3);
|
||||
(/*@__PURE__*/ m.x(1).y(2).z)(3);
|
||||
(/*@__PURE__*/ n.x(1).y(2).z(3));
|
||||
}
|
||||
expect_exact: [
|
||||
"/* */h.x(1).y(2).z(3);",
|
||||
"/* */i.x(1).y(2).z(3);",
|
||||
"/* */j.x(1).y(2).z(3);",
|
||||
"/* */k.x(1).y(2).z(3);",
|
||||
"/* */l.x(1).y(2).z(3);",
|
||||
"/* */m.x(1).y(2).z(3);",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2629_4: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(/*@__PURE__*/ x(), y());
|
||||
(w(), /*@__PURE__*/ x(), y());
|
||||
}
|
||||
expect: {
|
||||
y();
|
||||
w(), y();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2629_5: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
[ /*@__PURE__*/ x() ];
|
||||
[ /*@__PURE__*/ x(), y() ];
|
||||
[ w(), /*@__PURE__*/ x(), y() ];
|
||||
}
|
||||
expect: {
|
||||
y();
|
||||
w(), y();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2638: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
beautify = {
|
||||
comments: "all",
|
||||
}
|
||||
input: {
|
||||
/*@__PURE__*/(g() || h())(x(), y());
|
||||
(/*@__PURE__*/ (a() || b()))(c(), d());
|
||||
}
|
||||
expect_exact: [
|
||||
"/* */x(),y();",
|
||||
"/* */(a()||b())(c(),d());",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2705_1: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
beautify = {
|
||||
comments: "all",
|
||||
}
|
||||
input: {
|
||||
/*@__PURE__*/ new a();
|
||||
/*@__PURE__*/ (new b());
|
||||
new (/*@__PURE__*/ c)();
|
||||
(/*@__PURE__*/ new d());
|
||||
}
|
||||
expect_exact: [
|
||||
"new/* */c;",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2705_2: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
beautify = {
|
||||
comments: "all",
|
||||
}
|
||||
input: {
|
||||
/*@__PURE__*/ new a(1)(2)(3);
|
||||
/*@__PURE__*/ new (b(1))(2)(3);
|
||||
/*@__PURE__*/ new (c(1)(2))(3);
|
||||
/*@__PURE__*/ new (d(1)(2)(3));
|
||||
new (/*@__PURE__*/ e)(1)(2)(3);
|
||||
(/*@__PURE__*/ new f(1))(2)(3);
|
||||
(/*@__PURE__*/ new g(1)(2))(3);
|
||||
(/*@__PURE__*/ new h(1)(2)(3));
|
||||
}
|
||||
expect_exact: [
|
||||
"new/* */e(1)(2)(3);",
|
||||
"/* */new f(1)(2)(3);",
|
||||
"/* */new g(1)(2)(3);",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2705_3: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
beautify = {
|
||||
comments: "all",
|
||||
}
|
||||
input: {
|
||||
/*@__PURE__*/ new a.x(1).y(2).z(3);
|
||||
/*@__PURE__*/ new (b.x)(1).y(2).z(3);
|
||||
/*@__PURE__*/ new (c.x(1)).y(2).z(3);
|
||||
/*@__PURE__*/ new (d.x(1).y)(2).z(3);
|
||||
/*@__PURE__*/ new (e.x(1).y(2)).z(3);
|
||||
/*@__PURE__*/ new (f.x(1).y(2).z)(3);
|
||||
/*@__PURE__*/ new (g.x(1).y(2).z(3));
|
||||
new (/*@__PURE__*/ h).x(1).y(2).z(3);
|
||||
/* */ new (/*@__PURE__*/ i.x)(1).y(2).z(3);
|
||||
(/*@__PURE__*/ new j.x(1)).y(2).z(3);
|
||||
(/*@__PURE__*/ new k.x(1).y)(2).z(3);
|
||||
(/*@__PURE__*/ new l.x(1).y(2)).z(3);
|
||||
(/*@__PURE__*/ new m.x(1).y(2).z)(3);
|
||||
(/*@__PURE__*/ new n.x(1).y(2).z(3));
|
||||
}
|
||||
expect_exact: [
|
||||
"new/* */h.x(1).y(2).z(3);",
|
||||
"/* */new/* */i.x(1).y(2).z(3);",
|
||||
"/* */new j.x(1).y(2).z(3);",
|
||||
"/* */new k.x(1).y(2).z(3);",
|
||||
"/* */new l.x(1).y(2).z(3);",
|
||||
"/* */new m.x(1).y(2).z(3);",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2705_4: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(/*@__PURE__*/ new x(), y());
|
||||
(w(), /*@__PURE__*/ new x(), y());
|
||||
}
|
||||
expect: {
|
||||
y();
|
||||
w(), y();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2705_5: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
[ /*@__PURE__*/ new x() ];
|
||||
[ /*@__PURE__*/ new x(), y() ];
|
||||
[ w(), /*@__PURE__*/ new x(), y() ];
|
||||
}
|
||||
expect: {
|
||||
y();
|
||||
w(), y();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2705_6: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
beautify = {
|
||||
comments: "all",
|
||||
}
|
||||
input: {
|
||||
/*@__PURE__*/new (g() || h())(x(), y());
|
||||
/* */ new (/*@__PURE__*/ (a() || b()))(c(), d());
|
||||
}
|
||||
expect_exact: [
|
||||
"/* */x(),y();",
|
||||
"/* */new(/* */a()||b())(c(),d());",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3065_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
pure_funcs: [ "pureFunc" ],
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function modifyWrapper(a, f, wrapper) {
|
||||
wrapper.a = a;
|
||||
wrapper.f = f;
|
||||
return wrapper;
|
||||
}
|
||||
function pureFunc(fun) {
|
||||
return modifyWrapper(1, fun, function(a) {
|
||||
return fun(a);
|
||||
});
|
||||
}
|
||||
var unused = pureFunc(function(x) {
|
||||
return x;
|
||||
});
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_3065_2: {
|
||||
rename = true
|
||||
options = {
|
||||
inline: true,
|
||||
pure_funcs: [ "pureFunc" ],
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
reserved: [ "pureFunc" ],
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
function modifyWrapper(a, f, wrapper) {
|
||||
wrapper.a = a;
|
||||
wrapper.f = f;
|
||||
return wrapper;
|
||||
}
|
||||
function pureFunc(fun) {
|
||||
return modifyWrapper(1, fun, function(a) {
|
||||
return fun(a);
|
||||
});
|
||||
}
|
||||
var unused = pureFunc(function(x) {
|
||||
return x;
|
||||
});
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_3065_3: {
|
||||
options = {
|
||||
pure_funcs: [ "debug" ],
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function debug(msg) {
|
||||
console.log(msg);
|
||||
}
|
||||
debug(function() {
|
||||
console.log("PASS");
|
||||
return "FAIL";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
console.log("PASS");
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
issue_3065_4: {
|
||||
options = {
|
||||
pure_funcs: [ "debug" ],
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var debug = function(msg) {
|
||||
console.log(msg);
|
||||
};
|
||||
debug(function() {
|
||||
console.log("PASS");
|
||||
return "FAIL";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
console.log("PASS");
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user