Compare commits
484 Commits
v3.0.21
...
harmony-v3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d535daa2c7 | ||
|
|
0a9cdb6c73 | ||
|
|
3ae34177a6 | ||
|
|
086cb33163 | ||
|
|
2fd927a7cc | ||
|
|
8428326ea1 | ||
|
|
6371e2ee63 | ||
|
|
6ab73c7bd5 | ||
|
|
31f8209193 | ||
|
|
9b0f86f5a1 | ||
|
|
ee082ace1b | ||
|
|
ae67a49850 | ||
|
|
4178289c38 | ||
|
|
74ae16f9f8 | ||
|
|
1968203d83 | ||
|
|
2848596280 | ||
|
|
86ea38a259 | ||
|
|
8a713e449f | ||
|
|
7d9a8596a9 | ||
|
|
24aa07855b | ||
|
|
5fd723f143 | ||
|
|
516eaef50c | ||
|
|
4ae1fb3ed8 | ||
|
|
011123223b | ||
|
|
44352eb26a | ||
|
|
9f1c72ae28 | ||
|
|
c60fa67827 | ||
|
|
96439ca246 | ||
|
|
f9c57dfee0 | ||
|
|
c927cea632 | ||
|
|
9f4b98f8e4 | ||
|
|
0f2ef3367c | ||
|
|
6bf5fea008 | ||
|
|
7e5b5cac97 | ||
|
|
c1346e06b7 | ||
|
|
0d2fe8e3ef | ||
|
|
f2b9c11e2a | ||
|
|
b6a7ca292e | ||
|
|
fe647b083e | ||
|
|
a89f126db6 | ||
|
|
d8ee2de95c | ||
|
|
58a5608b66 | ||
|
|
f496ac5c85 | ||
|
|
dfe4f6c6de | ||
|
|
a09c8ad666 | ||
|
|
ec598c351b | ||
|
|
f79f737fb2 | ||
|
|
eba0f93bc0 | ||
|
|
99800d4aa9 | ||
|
|
70d56c951a | ||
|
|
b810e2f8da | ||
|
|
1abe14296e | ||
|
|
336b1add4f | ||
|
|
873755b35c | ||
|
|
744032755d | ||
|
|
4fac8076b8 | ||
|
|
6920e898d1 | ||
|
|
dd71639264 | ||
|
|
2dcc552ce0 | ||
|
|
a020d2ead3 | ||
|
|
68645b28d3 | ||
|
|
aaa8212837 | ||
|
|
bd84007cf4 | ||
|
|
55387e8fd0 | ||
|
|
1241600013 | ||
|
|
7e3e9da860 | ||
|
|
a784717fe2 | ||
|
|
00f509405b | ||
|
|
e8235657e4 | ||
|
|
c46b9f361a | ||
|
|
3b0b4d6abf | ||
|
|
d73500e8d1 | ||
|
|
aceb0af36b | ||
|
|
4f0953f7e9 | ||
|
|
182a47bfb1 | ||
|
|
d8685f528d | ||
|
|
8891495789 | ||
|
|
cd27f4ec38 | ||
|
|
8158b1bdcf | ||
|
|
aacf3edc68 | ||
|
|
8b89072190 | ||
|
|
395a17ccda | ||
|
|
3f355866cf | ||
|
|
2779a29a86 | ||
|
|
71d52f147d | ||
|
|
eb7adaa6fc | ||
|
|
e5cf7972ea | ||
|
|
067d52b6ba | ||
|
|
e0e009ace2 | ||
|
|
f81ff10a9b | ||
|
|
ae0f117da6 | ||
|
|
a5461e0adc | ||
|
|
16d40915b4 | ||
|
|
2bf8216e50 | ||
|
|
2ed3f8db44 | ||
|
|
4700c14855 | ||
|
|
e7c21e87e3 | ||
|
|
f54ab16843 | ||
|
|
69cb459c16 | ||
|
|
1eae8f2dcc | ||
|
|
c4c2ef44d0 | ||
|
|
a845897758 | ||
|
|
d600c78d7b | ||
|
|
32ea2c5530 | ||
|
|
d3df2f985d | ||
|
|
69861824b5 | ||
|
|
1e0c7d2bc5 | ||
|
|
98b850580b | ||
|
|
29011ea60a | ||
|
|
77d18be073 | ||
|
|
bc61deeca9 | ||
|
|
6a5e74b44e | ||
|
|
54446341ee | ||
|
|
91f8b57b3e | ||
|
|
3a2b737c42 | ||
|
|
4e12a6f740 | ||
|
|
b35dfc2599 | ||
|
|
9e1da9235e | ||
|
|
a5ffe2c23f | ||
|
|
9282e7b0c6 | ||
|
|
5229cb2b1b | ||
|
|
458e3e15f0 | ||
|
|
c615a1e80a | ||
|
|
10a938cb79 | ||
|
|
0f4278148d | ||
|
|
4956ad311b | ||
|
|
145874e504 | ||
|
|
f30375052b | ||
|
|
3e1a8598bf | ||
|
|
ef63de6968 | ||
|
|
2539fb8096 | ||
|
|
a556dd2dcb | ||
|
|
bd7be07c38 | ||
|
|
71ee91e716 | ||
|
|
e7334b4048 | ||
|
|
4f70d2e28c | ||
|
|
4b6ca5e742 | ||
|
|
f5c46db738 | ||
|
|
9306da3c58 | ||
|
|
1ac25fc032 | ||
|
|
fdbb1d09ef | ||
|
|
5f046c724b | ||
|
|
af0262b7e5 | ||
|
|
6b3aeff1d8 | ||
|
|
20e4f8277f | ||
|
|
f3a487a368 | ||
|
|
33ad0d258c | ||
|
|
5ea1da2d42 | ||
|
|
e77b6d525c | ||
|
|
2dde41615a | ||
|
|
8b69a3d18e | ||
|
|
d40950b741 | ||
|
|
a9eecd844f | ||
|
|
ed3032e52a | ||
|
|
7659ea1d2e | ||
|
|
52cc21d999 | ||
|
|
a938fe5e1f | ||
|
|
07a5a57336 | ||
|
|
bdeadffbf5 | ||
|
|
945db924fc | ||
|
|
087bce508a | ||
|
|
fc7e33453f | ||
|
|
d052394621 | ||
|
|
4d5aeeddfb | ||
|
|
ad139aa34d | ||
|
|
26be15f111 | ||
|
|
179f33f08a | ||
|
|
d260fe9018 | ||
|
|
96f9b8cba3 | ||
|
|
11afa816e3 | ||
|
|
49f3de8397 | ||
|
|
94f93ad82d | ||
|
|
d1f085bce7 | ||
|
|
7b95b63ca1 | ||
|
|
137e4c4753 | ||
|
|
b163b13a0b | ||
|
|
402954bdf3 | ||
|
|
f5931866e0 | ||
|
|
471db8a717 | ||
|
|
8ba9e4e0da | ||
|
|
71556d00b5 | ||
|
|
8709753bfb | ||
|
|
db877e8729 | ||
|
|
11923e3ae8 | ||
|
|
62d1fbf645 | ||
|
|
849ba79dee | ||
|
|
a298bcce02 | ||
|
|
daaf1273fa | ||
|
|
3fa862ce19 | ||
|
|
370f2cc906 | ||
|
|
78cf35f89c | ||
|
|
100e18305d | ||
|
|
7cc03d4d40 | ||
|
|
c28056d7ed | ||
|
|
8af362ed57 | ||
|
|
68138f2281 | ||
|
|
a7971f4e34 | ||
|
|
82fefc5d29 | ||
|
|
753932b302 | ||
|
|
1edbd6556f | ||
|
|
888a321417 | ||
|
|
ee5c03f7f1 | ||
|
|
0cb75089f0 | ||
|
|
a1647ee0c5 | ||
|
|
c814060b4a | ||
|
|
303293e4aa | ||
|
|
23265ac253 | ||
|
|
0cc6dedccc | ||
|
|
ec63588496 | ||
|
|
c2e471e3ad | ||
|
|
ee23a84e14 | ||
|
|
520da57fdc | ||
|
|
e5e0ce0b42 | ||
|
|
94d2aeee89 | ||
|
|
aa835eb0f6 | ||
|
|
39d4d7e20a | ||
|
|
02811ce35e | ||
|
|
c988e5f4d6 | ||
|
|
075b648bb1 | ||
|
|
37e549ff4f | ||
|
|
7bcb442e4c | ||
|
|
a658cd84a5 | ||
|
|
5b22334f3b | ||
|
|
a3053c537a | ||
|
|
d6f77a6352 | ||
|
|
a2172e1a99 | ||
|
|
9a074c2637 | ||
|
|
02b14528fa | ||
|
|
3db2001633 | ||
|
|
aaba482e48 | ||
|
|
5f29fced0a | ||
|
|
b1b918e6d6 | ||
|
|
ebb469e4cd | ||
|
|
c22d26b483 | ||
|
|
f751e64d49 | ||
|
|
60c56a24b9 | ||
|
|
01f23cf5a1 | ||
|
|
99fb3e8f0d | ||
|
|
756c9aa7dc | ||
|
|
07d6bfd707 | ||
|
|
81243c4e71 | ||
|
|
cd6e849555 | ||
|
|
91de285166 | ||
|
|
4d8f289eb0 | ||
|
|
945ba64160 | ||
|
|
c699200398 | ||
|
|
daf44f2b21 | ||
|
|
fcd90db30d | ||
|
|
e2888bdc43 | ||
|
|
fb50b7b627 | ||
|
|
9d59c693c2 | ||
|
|
6ddb5bd94d | ||
|
|
eda49605c5 | ||
|
|
1e9ef17e32 | ||
|
|
222100ea4c | ||
|
|
93db48a317 | ||
|
|
2944e3df7d | ||
|
|
e0ae8da089 | ||
|
|
81f1311b24 | ||
|
|
2433bb4e52 | ||
|
|
3fac29a017 | ||
|
|
b4c18f6b83 | ||
|
|
73d6438773 | ||
|
|
5c6316a37d | ||
|
|
278577f3cb | ||
|
|
0d8597e904 | ||
|
|
c20bb99a62 | ||
|
|
2377171200 | ||
|
|
603d92effc | ||
|
|
17f0cc359f | ||
|
|
35bae3fcd0 | ||
|
|
4614b5b46e | ||
|
|
2f93058c6e | ||
|
|
a729c43e87 | ||
|
|
66e9039350 | ||
|
|
d717bf9ce8 | ||
|
|
5dea52266b | ||
|
|
fccefbeaca | ||
|
|
1e2b0aaa04 | ||
|
|
6a54de79b5 | ||
|
|
9e2290b29c | ||
|
|
97d0fc271d | ||
|
|
7906033e82 | ||
|
|
4bf21ce5c1 | ||
|
|
44d6b47bdc | ||
|
|
129e449c8e | ||
|
|
75c3c8963f | ||
|
|
d26b7522d9 | ||
|
|
2fd86d3cb0 | ||
|
|
8f7ab602e2 | ||
|
|
1dd339f95e | ||
|
|
c7063c1f38 | ||
|
|
f4a12b34f2 | ||
|
|
5d5c7934a5 | ||
|
|
8f4b45f4f8 | ||
|
|
952e2656eb | ||
|
|
240383a314 | ||
|
|
250b782b1e | ||
|
|
3c2b3aeddb | ||
|
|
aa605495f8 | ||
|
|
33a26d456b | ||
|
|
49d9ac1c43 | ||
|
|
c8e61448cb | ||
|
|
f704e9b65c | ||
|
|
0b77d861a8 | ||
|
|
e27dab7e7c | ||
|
|
80f3ad3ce0 | ||
|
|
22f7af205d | ||
|
|
8a7a4749c7 | ||
|
|
514fc68f4f | ||
|
|
478aaab469 | ||
|
|
ab217539e9 | ||
|
|
a942dc07c4 | ||
|
|
a0eaff750d | ||
|
|
57777b6cfa | ||
|
|
8d205f7f39 | ||
|
|
bc9bfd15a2 | ||
|
|
9fc1c4b3b5 | ||
|
|
c59bf5e8d8 | ||
|
|
d2d3a6e065 | ||
|
|
7755733716 | ||
|
|
b3a987b0df | ||
|
|
88a338f29e | ||
|
|
07734b000a | ||
|
|
85c1cba760 | ||
|
|
4bd31607f6 | ||
|
|
4728bc73ad | ||
|
|
52ce9a333c | ||
|
|
abbeb266b5 | ||
|
|
b11c5151bc | ||
|
|
962b1f3d40 | ||
|
|
3ee46e91e8 | ||
|
|
ee26e7f11b | ||
|
|
937f534392 | ||
|
|
1b2c02c944 | ||
|
|
0aa526e72c | ||
|
|
c2112d5886 | ||
|
|
5f6825f9ec | ||
|
|
7e80a979a7 | ||
|
|
b7bb706150 | ||
|
|
32c2cc33bb | ||
|
|
947b8750e8 | ||
|
|
88f6ff38d1 | ||
|
|
4198095a9c | ||
|
|
13ed445607 | ||
|
|
1db50c3b16 | ||
|
|
7f6b5d662b | ||
|
|
1c15d0db45 | ||
|
|
67461666dc | ||
|
|
45d81f881b | ||
|
|
8c7d23dfb1 | ||
|
|
7fa0dbdeb9 | ||
|
|
c644c1292d | ||
|
|
d224d71b8d | ||
|
|
27d3669800 | ||
|
|
110a1ac885 | ||
|
|
3f8fc3a316 | ||
|
|
88384cf351 | ||
|
|
72a9d799b6 | ||
|
|
766fafda8b | ||
|
|
842ac27efb | ||
|
|
0af42d1831 | ||
|
|
ff7f6139ba | ||
|
|
0db7caf13b | ||
|
|
d9bc6f303c | ||
|
|
6fd9b338dd | ||
|
|
d8d4e71b9e | ||
|
|
fb2f8d1a51 | ||
|
|
54a783ba84 | ||
|
|
63c432f4fa | ||
|
|
07785d0003 | ||
|
|
6eaeb19a4a | ||
|
|
2246c79318 | ||
|
|
dda58244b6 | ||
|
|
ca04508cd1 | ||
|
|
6b03b800b3 | ||
|
|
f9cab7ad61 | ||
|
|
0a3d780327 | ||
|
|
b0555a123a | ||
|
|
fa29344781 | ||
|
|
dcfc514c38 | ||
|
|
8ad8d7b717 | ||
|
|
0357e5923f | ||
|
|
f63803e3e3 | ||
|
|
63be1f3a4d | ||
|
|
e36e07fa77 | ||
|
|
d1b4f61f93 | ||
|
|
5b893c8ec3 | ||
|
|
8571a08a93 | ||
|
|
68cc14f846 | ||
|
|
f94497d1d6 | ||
|
|
eaf3911c31 | ||
|
|
91cdb93e57 | ||
|
|
634f231b78 | ||
|
|
6702cae918 | ||
|
|
6d2f77c180 | ||
|
|
accca2445f | ||
|
|
0bc4f6edb4 | ||
|
|
ce84a706a3 | ||
|
|
86b5248837 | ||
|
|
59e1601fb8 | ||
|
|
d35a9e7839 | ||
|
|
0465bd270d | ||
|
|
6780d0906c | ||
|
|
0b303379c0 | ||
|
|
d7ec2ecc12 | ||
|
|
2827fa8699 | ||
|
|
c80ec625ec | ||
|
|
5e78f20f1c | ||
|
|
1f75232062 | ||
|
|
028ff64e9a | ||
|
|
7a8cffd631 | ||
|
|
5b553aafe2 | ||
|
|
084437bc6d | ||
|
|
1cd9a2df9a | ||
|
|
7f3dbb6df7 | ||
|
|
e4d73d8b7c | ||
|
|
8220dbbea0 | ||
|
|
59e999597e | ||
|
|
cbcb3ac44e | ||
|
|
f07ab4666f | ||
|
|
a800356ad0 | ||
|
|
e076abdbf2 | ||
|
|
425613b0d2 | ||
|
|
69da8e53e0 | ||
|
|
bb6b3a773a | ||
|
|
364d20f8fb | ||
|
|
392ac4ff31 | ||
|
|
9ffed2bea6 | ||
|
|
5f7cb6939c | ||
|
|
64e7a00399 | ||
|
|
c99eaae360 | ||
|
|
34213ea2f8 | ||
|
|
da8c428a07 | ||
|
|
0d8dea9538 | ||
|
|
2babe737e0 | ||
|
|
2cce61c564 | ||
|
|
246ec416c0 | ||
|
|
6be9c752d5 | ||
|
|
76ed083e47 | ||
|
|
b31918bbf0 | ||
|
|
b14496c742 | ||
|
|
991fa99655 | ||
|
|
3d7f73114d | ||
|
|
dde9e293df | ||
|
|
34685a6f55 | ||
|
|
9812c826e0 | ||
|
|
2fac2bbfe4 | ||
|
|
242c61be94 | ||
|
|
e1cb1a0e3c | ||
|
|
af22b9c657 | ||
|
|
adee5023c0 | ||
|
|
7ee8f3512e | ||
|
|
dc5db9b6ca | ||
|
|
079aaa0d48 | ||
|
|
d4f17f29ae | ||
|
|
e99bc914ca | ||
|
|
025d34bfa2 | ||
|
|
c44c2d6c21 | ||
|
|
824ecfb8a2 | ||
|
|
ceebc466b9 | ||
|
|
35b31bdd4e | ||
|
|
c8b82583d2 | ||
|
|
9f9179ba1a | ||
|
|
872231a0ca | ||
|
|
36420183fd | ||
|
|
a8f8aa518b | ||
|
|
4c12cccff9 | ||
|
|
dcce4e5c66 | ||
|
|
56c0b834d6 | ||
|
|
6f864402d3 | ||
|
|
8909e9e1cb | ||
|
|
e80ed38772 | ||
|
|
9863f0efa3 | ||
|
|
e8664e63ef | ||
|
|
ddd30eeaaa | ||
|
|
a68953c491 | ||
|
|
fa5c4f2d03 | ||
|
|
9d7d365c2b | ||
|
|
ad344c5be3 | ||
|
|
96b89e34a3 | ||
|
|
4644becb9b | ||
|
|
f7460166dd | ||
|
|
32f76f7ff8 |
9
.github/ISSUE_TEMPLATE.md
vendored
9
.github/ISSUE_TEMPLATE.md
vendored
@@ -8,7 +8,14 @@
|
||||
|
||||
**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.
|
||||
-->
|
||||
|
||||
**The `uglifyjs` CLI command executed or `minify()` options used.**
|
||||
|
||||
|
||||
424
README.md
424
README.md
@@ -1,14 +1,11 @@
|
||||
UglifyJS 3
|
||||
==========
|
||||
uglify-es
|
||||
=========
|
||||
|
||||
UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
|
||||
A JavaScript parser, mangler/compressor and beautifier toolkit for ES6+.
|
||||
|
||||
#### 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-es` is API/CLI compatible with `uglify-js@3`.**
|
||||
- **`uglify-es` is not backwards compatible with `uglify-js@2`.**
|
||||
|
||||
Install
|
||||
-------
|
||||
@@ -18,11 +15,11 @@ First make sure you have installed the latest version of [node.js](http://nodejs
|
||||
|
||||
From NPM for use as a command line app:
|
||||
|
||||
npm install uglify-js -g
|
||||
npm install uglify-es -g
|
||||
|
||||
From NPM for programmatic use:
|
||||
|
||||
npm install uglify-js
|
||||
npm install uglify-es
|
||||
|
||||
# Command line usage
|
||||
|
||||
@@ -105,13 +102,14 @@ 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.
|
||||
--ecma <version> Specify ECMAScript release: 5, 6, 7 or 8.
|
||||
--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.
|
||||
@@ -150,19 +148,19 @@ 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.
|
||||
|
||||
- `--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
|
||||
@@ -181,8 +179,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
|
||||
@@ -203,17 +201,15 @@ 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.
|
||||
|
||||
@@ -223,7 +219,7 @@ to prevent the `require`, `exports` and `$` names from being changed.
|
||||
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:
|
||||
in core JavaScript classes. For example:
|
||||
|
||||
```javascript
|
||||
// example.js
|
||||
@@ -238,7 +234,7 @@ x.bar_ = 2;
|
||||
x["baz_"] = 3;
|
||||
console.log(x.calc());
|
||||
```
|
||||
Mangle all properties (except for javascript `builtins`):
|
||||
Mangle all properties (except for JavaScript `builtins`):
|
||||
```bash
|
||||
$ uglifyjs example.js -c -m --mangle-props
|
||||
```
|
||||
@@ -347,7 +343,7 @@ identify mistakes like writing mangled keys to storage.
|
||||
Assuming installation via NPM, you can load UglifyJS in your application
|
||||
like this:
|
||||
```javascript
|
||||
var UglifyJS = require("uglify-js");
|
||||
var UglifyJS = require("uglify-es");
|
||||
```
|
||||
|
||||
There is a single high level function, **`minify(code, options)`**,
|
||||
@@ -383,7 +379,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:
|
||||
@@ -436,6 +472,9 @@ if (result.error) throw result.error;
|
||||
|
||||
## Minify options
|
||||
|
||||
- `ecma` (default `undefined`) - pass `5`, `6`, `7` or `8` to override `parse`,
|
||||
`compress` and `output` options.
|
||||
|
||||
- `warnings` (default `false`) — pass `true` to return compressor warnings
|
||||
in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
|
||||
|
||||
@@ -461,13 +500,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
|
||||
},
|
||||
@@ -487,8 +535,11 @@ if (result.error) throw result.error;
|
||||
sourceMap: {
|
||||
// source map options
|
||||
},
|
||||
ecma: 5, // specify one of: 5, 6, 7 or 8
|
||||
nameCache: null, // or specify a name cache object
|
||||
toplevel: false,
|
||||
ie8: false,
|
||||
warnings: false,
|
||||
}
|
||||
```
|
||||
|
||||
@@ -542,107 +593,103 @@ 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
|
||||
|
||||
- `ecma` (default: `8`) -- specify one of `5`, `6`, `7` or `8`. Note: this setting
|
||||
is not presently enforced except for ES8 optional trailing commas in function
|
||||
parameter lists and calls with `ecma` `8`.
|
||||
|
||||
- `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.
|
||||
- `arrows` (default: `true`) -- Converts `()=>{return x}` to `()=>x`. Class
|
||||
and object literal methods will also be converted to arrow expressions if
|
||||
the resultant code is shorter: `m(){return x}` becomes `m:()=>x`.
|
||||
This transform requires that the `ecma` compress option is set to `6` or greater.
|
||||
|
||||
- `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
|
||||
- `cascade` (default: `true`) -- small optimization for sequences, transform `x, x` into `x`
|
||||
and `x = something(), x` into `x = something()`
|
||||
|
||||
- `drop_debugger` -- remove `debugger;` statements
|
||||
- `collapse_vars` (default: `true`) -- Collapse single-use non-constant variables - side
|
||||
effects permitting.
|
||||
|
||||
- `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_Func` (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.
|
||||
|
||||
- `conditionals` -- apply optimizations for `if`-s and conditional
|
||||
expressions
|
||||
|
||||
- `comparisons` -- apply certain optimizations to binary nodes, for example:
|
||||
- `comparisons` (default: `true`) -- 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.
|
||||
|
||||
- `evaluate` -- attempt to evaluate constant expressions
|
||||
- `computed_props` (default: `true`) -- Transforms constant computed properties
|
||||
into regular ones: `{["computed"]: 1}` is converted to `{computed: 1}`.
|
||||
|
||||
- `booleans` -- various optimizations for boolean context, for example `!!a
|
||||
? b : c → a ? b : c`
|
||||
- `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional
|
||||
expressions
|
||||
|
||||
- `loops` -- optimizations for `do`, `while` and `for` loops when we can
|
||||
statically determine the condition
|
||||
- `dead_code` (default: `true`) -- remove unreachable code
|
||||
|
||||
- `unused` -- drop unreferenced functions and variables (simple direct variable
|
||||
assignments do not count as references unless set to `"keep_assign"`)
|
||||
- `drop_console` (default: `false`) -- 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.
|
||||
|
||||
- `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)
|
||||
- `drop_debugger` (default: `true`) -- remove `debugger;` statements
|
||||
|
||||
- `top_retain` -- prevent specific toplevel functions and variables from `unused`
|
||||
removal (can be array, comma-separated, RegExp or function. Implies `toplevel`)
|
||||
- `ecma` (default: `5`) -- Pass `6` or greater to enable `compress` options that
|
||||
will transform ES5 code into smaller ES6+ equivalent forms.
|
||||
|
||||
- `hoist_funs` -- hoist function declarations
|
||||
- `evaluate` (default: `true`) -- attempt to evaluate constant expressions
|
||||
|
||||
- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false`
|
||||
- `expression` (default: `false`) -- default `false`. Pass `true` to preserve completion values
|
||||
from terminal statements without `return`, e.g. in bookmarklets.
|
||||
|
||||
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
|
||||
|
||||
- `hoist_funs` (default: `true`) -- hoist function declarations
|
||||
|
||||
- `hoist_props` (default: `false`) -- 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
|
||||
|
||||
- `inline` -- embed simple functions
|
||||
- `inline` (default: `true`) -- embed simple functions
|
||||
|
||||
- `join_vars` -- join consecutive `var` statements
|
||||
- `join_vars` (default: `true`) -- join consecutive `var` statements
|
||||
|
||||
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
||||
and `x = something(), x` into `x = something()`
|
||||
- `keep_fargs` (default: `true`) -- default `true`. Prevents the
|
||||
compressor from discarding unused function arguments. You need this
|
||||
for code which relies on `Function.length`.
|
||||
|
||||
- `collapse_vars` -- Collapse single-use non-constant variables - side
|
||||
effects permitting.
|
||||
- `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).
|
||||
|
||||
- `reduce_vars` -- Improve optimization on variables assigned with and
|
||||
used as constant values.
|
||||
- `keep_infinity` (default: `false`) -- default `false`. Pass `true` to prevent `Infinity` from
|
||||
being compressed into `1/0`, which may cause performance issues on Chrome.
|
||||
|
||||
- `warnings` -- display warnings when dropping unreachable code or unused
|
||||
declarations etc.
|
||||
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops when we can
|
||||
statically determine the condition
|
||||
|
||||
- `negate_iife` -- negate "Immediately-Called Function Expressions"
|
||||
- `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
|
||||
@@ -653,48 +700,102 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
statement would get discarded. The current implementation adds some
|
||||
overhead (compression will be slower).
|
||||
|
||||
- `drop_console` -- default `false`. Pass `true` to discard calls to
|
||||
`console.*` functions. If you wish to drop a specific function call
|
||||
such as `console.info` and/or retain side effects from function arguments
|
||||
after dropping the function call then use `pure_funcs` instead.
|
||||
- `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_vars` (default: `true`) -- Improve optimization on variables assigned with and
|
||||
used as constant values.
|
||||
|
||||
- `keep_fargs` -- default `true`. Prevents the
|
||||
compressor from discarding unused function arguments. You need this
|
||||
for code which relies on `Function.length`.
|
||||
- `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.
|
||||
|
||||
- `keep_fnames` -- default `false`. Pass `true` to prevent the
|
||||
compressor from discarding function names. Useful for code relying on
|
||||
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
|
||||
|
||||
- `passes` -- default `1`. Number of times to run compress 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`) -- 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`) -- 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_arrows` (default: `false`) -- Convert ES5 style anonymous function
|
||||
expressions to arrow functions if the function body does not reference `this`.
|
||||
Note: it is not always safe to perform this conversion if code relies on the
|
||||
the function having a `prototype`, which arrow functions lack.
|
||||
This transform requires that the `ecma` compress option is set to `6` or greater.
|
||||
|
||||
- `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_Func` (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_methods` (default: false) -- Converts `{ m: function(){} }` to
|
||||
`{ m(){} }`. `ecma` must be set to `6` or greater to enable this transform.
|
||||
If `unsafe_methods` is a RegExp then key/value pairs with keys matching the
|
||||
RegExp will be converted to concise methods.
|
||||
Note: if enabled there is a risk of getting a "`<method name>` is not a
|
||||
constructor" TypeError should any code try to `new` the former function.
|
||||
|
||||
- `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.
|
||||
|
||||
- `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
|
||||
|
||||
- `eval` (default `false`). Pass `true` to mangle names visible in scopes
|
||||
where `eval` or `with` are used.
|
||||
|
||||
- `keep_classnames` (default `false`). Pass `true` to not mangle class names.
|
||||
|
||||
- `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).
|
||||
|
||||
- `reserved` (default `[]`). Pass an array of identifiers that should be
|
||||
excluded from mangling. Example: `["foo", "bar"]`.
|
||||
|
||||
- `toplevel` (default `false`). Pass `true` to mangle names declared in the
|
||||
top level scope.
|
||||
|
||||
- `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` (default `false`). Pass `true` to mangle names visible in scopes
|
||||
where `eval` or `with` are used.
|
||||
- `safari10` (default `false`). Pass `true` to work around the Safari 10 loop
|
||||
iterator [bug](https://bugs.webkit.org/show_bug.cgi?id=171041)
|
||||
"Cannot declare a let variable twice".
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -720,16 +821,20 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
|
||||
|
||||
### Mangle properties options
|
||||
|
||||
- `reserved` (default: `[]`) -- Do not mangle property names listed in the
|
||||
`reserved` array.
|
||||
- `regex` (default: `null`) -— Pass a RegExp literal to only mangle property
|
||||
names matching the regular expression.
|
||||
- `keep_quoted` (default: `false`) -— Only mangle unquoted property names.
|
||||
- `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.
|
||||
- `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
|
||||
|
||||
The code generator tries to output shortest code possible by default. In
|
||||
@@ -738,31 +843,50 @@ 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`,
|
||||
`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
|
||||
|
||||
- `ecma` (default `5`) -- set output printing mode. Set `ecma` to `6` or
|
||||
greater to emit shorthand object properties - i.e.: `{a}` instead of `{a: a}`.
|
||||
The `ecma` option will only change the output in direct control of the
|
||||
beautifier. Non-compatible features in the abstract syntax tree will still
|
||||
be output as is. For example: an `ecma` setting of `5` will **not** convert
|
||||
ES6+ code to ES5.
|
||||
|
||||
- `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
|
||||
|
||||
- `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`.
|
||||
|
||||
- `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
|
||||
@@ -770,16 +894,20 @@ can pass additional arguments that control the code output:
|
||||
- `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
|
||||
|
||||
- `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.
|
||||
@@ -825,7 +953,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)
|
||||
@@ -978,3 +1105,30 @@ 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 });
|
||||
```
|
||||
|
||||
54
bin/uglifyjs
54
bin/uglifyjs
@@ -35,15 +35,16 @@ else if (process.argv.indexOf("options") >= 0) program.helpInformation = functio
|
||||
}
|
||||
return text.join("\n");
|
||||
};
|
||||
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));
|
||||
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("--ecma <version>", "Specify ECMAScript release: 5, 6, 7 or 8.");
|
||||
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.");
|
||||
@@ -73,6 +74,10 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
||||
options[name] = program[name];
|
||||
}
|
||||
});
|
||||
if ("ecma" in program) {
|
||||
if (program.ecma != (program.ecma | 0)) fatal("ERROR: ecma must be an integer");
|
||||
options.ecma = program.ecma | 0;
|
||||
}
|
||||
if (program.beautify) {
|
||||
options.output = typeof program.beautify == "object" ? program.beautify : {};
|
||||
if (!("beautify" in options.output)) {
|
||||
@@ -106,17 +111,8 @@ if (program.mangleProps) {
|
||||
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 = {
|
||||
@@ -266,9 +262,7 @@ function run() {
|
||||
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");
|
||||
@@ -321,7 +315,7 @@ function read_file(path, default_value) {
|
||||
}
|
||||
}
|
||||
|
||||
function parse_js(flag, constants) {
|
||||
function parse_js(flag) {
|
||||
return function(value, options) {
|
||||
options = options || {};
|
||||
try {
|
||||
@@ -339,7 +333,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);
|
||||
@@ -362,14 +356,18 @@ function parse_js(flag, constants) {
|
||||
}
|
||||
}));
|
||||
} catch(ex) {
|
||||
options[value] = null;
|
||||
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);
|
||||
var parse = parse_js();
|
||||
return function(value, options) {
|
||||
var hasContent = options && "content" in options;
|
||||
var settings = parse(value, options);
|
||||
@@ -381,18 +379,6 @@ function parse_source_map() {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
354
lib/ast.js
354
lib/ast.js
@@ -134,11 +134,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);
|
||||
@@ -157,7 +156,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
|
||||
|
||||
function walk_body(node, visitor) {
|
||||
var body = node.body;
|
||||
if (body instanceof AST_Statement) {
|
||||
if (body instanceof AST_Node) {
|
||||
body._walk(visitor);
|
||||
}
|
||||
else for (var i = 0, len = body.length; i < len; i++) {
|
||||
@@ -284,6 +283,10 @@ var AST_ForIn = DEFNODE("ForIn", "init name object", {
|
||||
}
|
||||
}, AST_IterationStatement);
|
||||
|
||||
var AST_ForOf = DEFNODE("ForOf", null, {
|
||||
$documentation: "A `for ... of` statement",
|
||||
}, AST_ForIn);
|
||||
|
||||
var AST_With = DEFNODE("With", "expression", {
|
||||
$documentation: "A `with` statement",
|
||||
$propdoc: {
|
||||
@@ -299,10 +302,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 +313,13 @@ var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_
|
||||
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
|
||||
cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
|
||||
},
|
||||
get_defun_scope: function () {
|
||||
var self = this;
|
||||
while (self.is_block_scope() && self.parent_scope) {
|
||||
self = self.parent_scope;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
}, AST_Block);
|
||||
|
||||
var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
@@ -331,12 +340,38 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||
}
|
||||
}, AST_Scope);
|
||||
|
||||
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
|
||||
var AST_Expansion = DEFNODE("Expansion", "expression", {
|
||||
$documentation: "An expandible argument, such as ...rest, a splat, such as [1,2,...all], or an expansion in a variable declaration, such as var [first, ...rest] = list",
|
||||
$propdoc: {
|
||||
expression: "[AST_Node] the thing to be expanded"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
var self = this;
|
||||
return visitor._visit(this, function(){
|
||||
self.expression.walk(visitor);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments is_generator async", {
|
||||
$documentation: "Base class for functions",
|
||||
$propdoc: {
|
||||
name: "[AST_SymbolDeclaration?] the name of this function",
|
||||
argnames: "[AST_SymbolFunarg*] array of function arguments",
|
||||
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
|
||||
argnames: "[AST_SymbolFunarg|AST_Destructuring|AST_Expansion|AST_DefaultAssign*] array of function arguments, destructurings, or expanding arguments",
|
||||
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array",
|
||||
is_generator: "[boolean] is this a generator method",
|
||||
async: "[boolean] is this method async",
|
||||
},
|
||||
args_as_names: function () {
|
||||
var out = [];
|
||||
for (var i = 0; i < this.argnames.length; i++) {
|
||||
if (this.argnames[i] instanceof AST_Destructuring) {
|
||||
out = out.concat(this.argnames[i].all_symbols());
|
||||
} else {
|
||||
out.push(this.argnames[i]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
@@ -358,10 +393,76 @@ var AST_Function = DEFNODE("Function", null, {
|
||||
$documentation: "A function expression"
|
||||
}, AST_Lambda);
|
||||
|
||||
var AST_Arrow = DEFNODE("Arrow", null, {
|
||||
$documentation: "An ES6 Arrow function ((a) => b)"
|
||||
}, AST_Lambda);
|
||||
|
||||
var AST_Defun = DEFNODE("Defun", null, {
|
||||
$documentation: "A function definition"
|
||||
}, AST_Lambda);
|
||||
|
||||
/* -----[ DESTRUCTURING ]----- */
|
||||
var AST_Destructuring = DEFNODE("Destructuring", "names is_array", {
|
||||
$documentation: "A destructuring of several names. Used in destructuring assignment and with destructuring function argument names",
|
||||
$propdoc: {
|
||||
"names": "[AST_Node*] Array of properties or elements",
|
||||
"is_array": "[Boolean] Whether the destructuring represents an object or array"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.names.forEach(function(name){
|
||||
name._walk(visitor);
|
||||
});
|
||||
});
|
||||
},
|
||||
all_symbols: function() {
|
||||
var out = [];
|
||||
this.walk(new TreeWalker(function (node) {
|
||||
if (node instanceof AST_Symbol) {
|
||||
out.push(node);
|
||||
}
|
||||
if (node instanceof AST_Expansion) {
|
||||
out.push(node.expression);
|
||||
}
|
||||
}));
|
||||
return out;
|
||||
}
|
||||
});
|
||||
|
||||
var AST_PrefixedTemplateString = DEFNODE("PrefixedTemplateString", "template_string prefix", {
|
||||
$documentation: "A templatestring with a prefix, such as String.raw`foobarbaz`",
|
||||
$propdoc: {
|
||||
template_string: "[AST_TemplateString] The template string",
|
||||
prefix: "[AST_SymbolRef|AST_PropAccess] The prefix, which can be a symbol such as `foo` or a dotted expression such as `String.raw`."
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
this.prefix._walk(visitor);
|
||||
this.template_string._walk(visitor);
|
||||
}
|
||||
})
|
||||
|
||||
var AST_TemplateString = DEFNODE("TemplateString", "segments", {
|
||||
$documentation: "A template string literal",
|
||||
$propdoc: {
|
||||
segments: "[AST_Node*] One or more segments, starting with AST_TemplateSegment. AST_Node may follow AST_TemplateSegment, but each AST_Node must be followed by AST_TemplateSegment."
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.segments.forEach(function(seg){
|
||||
seg._walk(visitor);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var AST_TemplateSegment = DEFNODE("TemplateSegment", "value raw", {
|
||||
$documentation: "A segment of a template string literal",
|
||||
$propdoc: {
|
||||
value: "Content of the segment",
|
||||
raw: "Raw content of the segment"
|
||||
}
|
||||
});
|
||||
|
||||
/* -----[ JUMPS ]----- */
|
||||
|
||||
var AST_Jump = DEFNODE("Jump", null, {
|
||||
@@ -481,7 +582,7 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
|
||||
var AST_Catch = DEFNODE("Catch", "argname", {
|
||||
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
|
||||
$propdoc: {
|
||||
argname: "[AST_SymbolCatch] symbol for the exception"
|
||||
argname: "[AST_SymbolCatch|AST_Destructuring|AST_Expansion|AST_DefaultAssign] symbol for the exception"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
@@ -495,10 +596,10 @@ var AST_Finally = DEFNODE("Finally", null, {
|
||||
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
|
||||
}, AST_Block);
|
||||
|
||||
/* -----[ VAR ]----- */
|
||||
/* -----[ VAR/CONST ]----- */
|
||||
|
||||
var AST_Definitions = DEFNODE("Definitions", "definitions", {
|
||||
$documentation: "Base class for `var` nodes (variable declarations/initializations)",
|
||||
$documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
|
||||
$propdoc: {
|
||||
definitions: "[AST_VarDef*] array of variable definitions"
|
||||
},
|
||||
@@ -516,10 +617,83 @@ var AST_Var = DEFNODE("Var", null, {
|
||||
$documentation: "A `var` statement"
|
||||
}, AST_Definitions);
|
||||
|
||||
var AST_Let = DEFNODE("Let", null, {
|
||||
$documentation: "A `let` statement"
|
||||
}, AST_Definitions);
|
||||
|
||||
var AST_Const = DEFNODE("Const", null, {
|
||||
$documentation: "A `const` statement"
|
||||
}, AST_Definitions);
|
||||
|
||||
var AST_NameMapping = DEFNODE("NameMapping", "foreign_name name", {
|
||||
$documentation: "The part of the export/import statement that declare names from a module.",
|
||||
$propdoc: {
|
||||
foreign_name: "[AST_SymbolExportForeign|AST_SymbolImportForeign] The name being exported/imported (as specified in the module)",
|
||||
name: "[AST_SymbolExport|AST_SymbolImport] The name as it is visible to this module."
|
||||
},
|
||||
_walk: function (visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
this.foreign_name._walk(visitor);
|
||||
this.name._walk(visitor);
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
var AST_Import = DEFNODE("Import", "imported_name imported_names module_name", {
|
||||
$documentation: "An `import` statement",
|
||||
$propdoc: {
|
||||
imported_name: "[AST_SymbolImport] The name of the variable holding the module's default export.",
|
||||
imported_names: "[AST_NameMapping*] The names of non-default imported variables",
|
||||
module_name: "[AST_String] String literal describing where this module came from",
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function() {
|
||||
if (this.imported_name) {
|
||||
this.imported_name._walk(visitor);
|
||||
}
|
||||
if (this.imported_names) {
|
||||
this.imported_names.forEach(function(name_import) {
|
||||
name_import._walk(visitor);
|
||||
});
|
||||
}
|
||||
this.module_name._walk(visitor);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var AST_Export = DEFNODE("Export", "exported_definition exported_value is_default exported_names module_name", {
|
||||
$documentation: "An `export` statement",
|
||||
$propdoc: {
|
||||
exported_definition: "[AST_Defun|AST_Definitions|AST_DefClass?] An exported definition",
|
||||
exported_value: "[AST_Node?] An exported value",
|
||||
exported_names: "[AST_NameMapping*?] List of exported names",
|
||||
module_name: "[AST_String?] Name of the file to load exports from",
|
||||
is_default: "[Boolean] Whether this is the default exported value of this module"
|
||||
},
|
||||
_walk: function (visitor) {
|
||||
visitor._visit(this, function () {
|
||||
if (this.exported_definition) {
|
||||
this.exported_definition._walk(visitor);
|
||||
}
|
||||
if (this.exported_value) {
|
||||
this.exported_value._walk(visitor);
|
||||
}
|
||||
if (this.exported_names) {
|
||||
this.exported_names.forEach(function(name_export) {
|
||||
name_export._walk(visitor);
|
||||
});
|
||||
}
|
||||
if (this.module_name) {
|
||||
this.module_name._walk(visitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
||||
$propdoc: {
|
||||
name: "[AST_SymbolVar] name of the variable",
|
||||
name: "[AST_Destructuring|AST_SymbolConst|AST_SymbolLet|AST_SymbolVar] name of the variable",
|
||||
value: "[AST_Node?] initializer, or null of there's no initializer"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
@@ -650,6 +824,10 @@ var AST_Assign = DEFNODE("Assign", null, {
|
||||
$documentation: "An assignment expression — `a = b + 5`",
|
||||
}, AST_Binary);
|
||||
|
||||
var AST_DefaultAssign = DEFNODE("DefaultAssign", null, {
|
||||
$documentation: "A default assignment expression like in `(a = 3) => a`"
|
||||
}, AST_Binary);
|
||||
|
||||
/* -----[ LITERALS ]----- */
|
||||
|
||||
var AST_Array = DEFNODE("Array", "elements", {
|
||||
@@ -685,11 +863,13 @@ 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.",
|
||||
key: "[string|AST_Node] the property name converted to a string for ObjectKeyVal. For setters, getters and computed property this is an arbitrary AST_Node",
|
||||
value: "[AST_Node] property value. For setters and getters this is an AST_Accessor."
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
if (this.key instanceof AST_Node)
|
||||
this.key._walk(visitor);
|
||||
this.value._walk(visitor);
|
||||
});
|
||||
}
|
||||
@@ -702,35 +882,95 @@ var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", "quote", {
|
||||
}
|
||||
}, AST_ObjectProperty);
|
||||
|
||||
var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
|
||||
var AST_ObjectSetter = DEFNODE("ObjectSetter", "quote static", {
|
||||
$propdoc: {
|
||||
quote: "[string|undefined] the original quote character, if any",
|
||||
static: "[boolean] whether this is a static setter (classes only)"
|
||||
},
|
||||
$documentation: "An object setter property",
|
||||
}, AST_ObjectProperty);
|
||||
|
||||
var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
|
||||
var AST_ObjectGetter = DEFNODE("ObjectGetter", "quote static", {
|
||||
$propdoc: {
|
||||
quote: "[string|undefined] the original quote character, if any",
|
||||
static: "[boolean] whether this is a static getter (classes only)"
|
||||
},
|
||||
$documentation: "An object getter property",
|
||||
}, AST_ObjectProperty);
|
||||
|
||||
var AST_ConciseMethod = DEFNODE("ConciseMethod", "quote static is_generator async", {
|
||||
$propdoc: {
|
||||
quote: "[string|undefined] the original quote character, if any",
|
||||
static: "[boolean] is this method static (classes only)",
|
||||
is_generator: "[boolean] is this a generator method",
|
||||
async: "[boolean] is this method async",
|
||||
},
|
||||
$documentation: "An ES6 concise method inside an object or class"
|
||||
}, AST_ObjectProperty);
|
||||
|
||||
var AST_Class = DEFNODE("Class", "name extends properties", {
|
||||
$propdoc: {
|
||||
name: "[AST_SymbolClass|AST_SymbolDefClass?] optional class name.",
|
||||
extends: "[AST_Node]? optional parent class",
|
||||
properties: "[AST_ObjectProperty*] array of properties"
|
||||
},
|
||||
$documentation: "An ES6 class",
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
if (this.name) {
|
||||
this.name._walk(visitor);
|
||||
}
|
||||
if (this.extends) {
|
||||
this.extends._walk(visitor);
|
||||
}
|
||||
this.properties.forEach(function(prop){
|
||||
prop._walk(visitor);
|
||||
});
|
||||
});
|
||||
},
|
||||
}, AST_Scope);
|
||||
|
||||
var AST_DefClass = DEFNODE("DefClass", null, {
|
||||
$documentation: "A class definition",
|
||||
}, AST_Class);
|
||||
|
||||
var AST_ClassExpression = DEFNODE("ClassExpression", null, {
|
||||
$documentation: "A class expression."
|
||||
}, AST_Class);
|
||||
|
||||
var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
|
||||
$propdoc: {
|
||||
name: "[string] name of this symbol",
|
||||
scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
|
||||
thedef: "[SymbolDef/S] the definition of this symbol"
|
||||
},
|
||||
$documentation: "Base class for all symbols",
|
||||
$documentation: "Base class for all symbols"
|
||||
});
|
||||
|
||||
var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
|
||||
$documentation: "The name of a property accessor (setter/getter function)"
|
||||
}, AST_Symbol);
|
||||
var AST_NewTarget = DEFNODE("NewTarget", null, {
|
||||
$documentation: "A reference to new.target"
|
||||
});
|
||||
|
||||
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
|
||||
$documentation: "A declaration symbol (symbol in var, function name or argument, symbol in catch)",
|
||||
$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolVar = DEFNODE("SymbolVar", null, {
|
||||
$documentation: "Symbol defining a variable",
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolBlockDeclaration = DEFNODE("SymbolBlockDeclaration", null, {
|
||||
$documentation: "Base class for block-scoped declaration symbols"
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolConst = DEFNODE("SymbolConst", null, {
|
||||
$documentation: "A constant declaration"
|
||||
}, AST_SymbolBlockDeclaration);
|
||||
|
||||
var AST_SymbolLet = DEFNODE("SymbolLet", null, {
|
||||
$documentation: "A block-scoped `let` declaration"
|
||||
}, AST_SymbolBlockDeclaration);
|
||||
|
||||
var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
|
||||
$documentation: "Symbol naming a function argument",
|
||||
}, AST_SymbolVar);
|
||||
@@ -739,13 +979,33 @@ var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
|
||||
$documentation: "Symbol defining a function",
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolMethod = DEFNODE("SymbolMethod", null, {
|
||||
$documentation: "Symbol in an object defining a method",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
|
||||
$documentation: "Symbol naming a function expression",
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolDefClass = DEFNODE("SymbolDefClass", null, {
|
||||
$documentation: "Symbol naming a class's name in a class declaration. Lexically scoped to its containing scope, and accessible within the class."
|
||||
}, AST_SymbolBlockDeclaration);
|
||||
|
||||
var AST_SymbolClass = DEFNODE("SymbolClass", null, {
|
||||
$documentation: "Symbol naming a class's name. Lexically scoped to the class."
|
||||
}, AST_SymbolDeclaration);
|
||||
|
||||
var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
|
||||
$documentation: "Symbol naming the exception in catch",
|
||||
}, AST_SymbolDeclaration);
|
||||
}, AST_SymbolBlockDeclaration);
|
||||
|
||||
var AST_SymbolImport = DEFNODE("SymbolImport", null, {
|
||||
$documentation: "Symbol referring to an imported name",
|
||||
}, AST_SymbolBlockDeclaration);
|
||||
|
||||
var AST_SymbolImportForeign = DEFNODE("SymbolImportForeign", null, {
|
||||
$documentation: "A symbol imported from a module, but it is defined in the other module, and its real name is irrelevant for this module's purposes",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_Label = DEFNODE("Label", "references", {
|
||||
$documentation: "Symbol naming a label (declaration)",
|
||||
@@ -762,6 +1022,14 @@ var AST_SymbolRef = DEFNODE("SymbolRef", null, {
|
||||
$documentation: "Reference to some symbol (not definition/declaration)",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolExport = DEFNODE("SymbolExport", null, {
|
||||
$documentation: "Symbol referring to a name to export",
|
||||
}, AST_SymbolRef);
|
||||
|
||||
var AST_SymbolExportForeign = DEFNODE("SymbolExportForeign", null, {
|
||||
$documentation: "A symbol exported from this module, but it is used in the other module, and its real name is irrelevant for this module's purposes",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_LabelRef = DEFNODE("LabelRef", null, {
|
||||
$documentation: "Reference to a label symbol",
|
||||
}, AST_Symbol);
|
||||
@@ -770,6 +1038,10 @@ var AST_This = DEFNODE("This", null, {
|
||||
$documentation: "The `this` symbol",
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_Super = DEFNODE("Super", null, {
|
||||
$documentation: "The `super` symbol",
|
||||
}, AST_This);
|
||||
|
||||
var AST_Constant = DEFNODE("Constant", null, {
|
||||
$documentation: "Base class for all constants",
|
||||
getValue: function() {
|
||||
@@ -843,6 +1115,31 @@ var AST_True = DEFNODE("True", null, {
|
||||
value: true
|
||||
}, AST_Boolean);
|
||||
|
||||
var AST_Await = DEFNODE("Await", "expression", {
|
||||
$documentation: "An `await` statement",
|
||||
$propdoc: {
|
||||
expression: "[AST_Node] the mandatory expression being awaited",
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.expression._walk(visitor);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var AST_Yield = DEFNODE("Yield", "expression is_star", {
|
||||
$documentation: "A `yield` statement",
|
||||
$propdoc: {
|
||||
expression: "[AST_Node?] the value returned or thrown by this statement; could be null (representing undefined) but only when is_star is set to false",
|
||||
is_star: "[Boolean] Whether this is a yield or yield* statement"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, this.expression && function(){
|
||||
this.expression._walk(visitor);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/* -----[ TreeWalker ]----- */
|
||||
|
||||
function TreeWalker(callback) {
|
||||
@@ -859,7 +1156,7 @@ TreeWalker.prototype = {
|
||||
if (!ret && descend) {
|
||||
descend.call(node);
|
||||
}
|
||||
this.pop(node);
|
||||
this.pop();
|
||||
return ret;
|
||||
},
|
||||
parent: function(n) {
|
||||
@@ -870,12 +1167,17 @@ TreeWalker.prototype = {
|
||||
this.directives = Object.create(this.directives);
|
||||
} else if (node instanceof AST_Directive && !this.directives[node.value]) {
|
||||
this.directives[node.value] = node;
|
||||
} else if (node instanceof AST_Class) {
|
||||
this.directives = Object.create(this.directives);
|
||||
if (!this.directives["use strict"]) {
|
||||
this.directives["use strict"] = node;
|
||||
}
|
||||
}
|
||||
this.stack.push(node);
|
||||
},
|
||||
pop: function(node) {
|
||||
this.stack.pop();
|
||||
if (node instanceof AST_Lambda) {
|
||||
pop: function() {
|
||||
var node = this.stack.pop();
|
||||
if (node instanceof AST_Lambda || node instanceof AST_Class) {
|
||||
this.directives = Object.getPrototypeOf(this.directives);
|
||||
}
|
||||
},
|
||||
@@ -893,7 +1195,7 @@ TreeWalker.prototype = {
|
||||
var dir = this.directives[type];
|
||||
if (dir) return dir;
|
||||
var node = this.stack[this.stack.length - 1];
|
||||
if (node instanceof AST_Scope) {
|
||||
if (node instanceof AST_Scope && node.body) {
|
||||
for (var i = 0; i < node.body.length; ++i) {
|
||||
var st = node.body[i];
|
||||
if (!(st instanceof AST_Directive)) break;
|
||||
|
||||
1689
lib/compress.js
1689
lib/compress.js
File diff suppressed because it is too large
Load Diff
@@ -27,14 +27,33 @@ function set_shorthand(name, options, keys) {
|
||||
}
|
||||
}
|
||||
|
||||
function init_cache(cache) {
|
||||
if (!cache) return;
|
||||
if (!("cname" in cache)) cache.cname = -1;
|
||||
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 {
|
||||
cname: cache.cname,
|
||||
props: cache.props.toObject()
|
||||
};
|
||||
}
|
||||
|
||||
function minify(files, options) {
|
||||
var warn_function = AST_Node.warn_function;
|
||||
try {
|
||||
options = defaults(options, {
|
||||
compress: {},
|
||||
ecma: undefined,
|
||||
ie8: false,
|
||||
keep_fnames: false,
|
||||
mangle: {},
|
||||
nameCache: null,
|
||||
output: {},
|
||||
parse: {},
|
||||
sourceMap: false,
|
||||
@@ -46,20 +65,39 @@ function minify(files, options) {
|
||||
var timings = options.timings && {
|
||||
start: Date.now()
|
||||
};
|
||||
set_shorthand("ecma", options, [ "parse", "compress", "output" ]);
|
||||
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_classnames: false,
|
||||
keep_fnames: false,
|
||||
properties: false,
|
||||
reserved: [],
|
||||
safari10: false,
|
||||
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, {
|
||||
@@ -97,6 +135,9 @@ function minify(files, options) {
|
||||
}
|
||||
toplevel = options.parse.toplevel;
|
||||
}
|
||||
if (quoted_props) {
|
||||
reserve_quoted_keys(toplevel, quoted_props);
|
||||
}
|
||||
if (options.wrap) {
|
||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||
}
|
||||
@@ -153,6 +194,12 @@ 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 = {
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
value : from_moz(M.value)
|
||||
};
|
||||
if (M.kind == "init") return new AST_ObjectKeyVal(args);
|
||||
args.key = new AST_SymbolAccessor({
|
||||
args.key = new AST_SymbolMethod({
|
||||
name: args.key
|
||||
});
|
||||
args.value = new AST_Accessor(args.value);
|
||||
@@ -168,7 +168,7 @@
|
||||
});
|
||||
},
|
||||
VariableDeclaration: function(M) {
|
||||
return new AST_Var({
|
||||
return new (M.kind === "const" ? AST_Const : AST_Var)({
|
||||
start : my_start_token(M),
|
||||
end : my_end_token(M),
|
||||
definitions : M.declarations.map(from_moz)
|
||||
@@ -204,7 +204,7 @@
|
||||
Identifier: function(M) {
|
||||
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
|
||||
return new ( p.type == "LabeledStatement" ? AST_Label
|
||||
: p.type == "VariableDeclarator" && p.id === M ? AST_SymbolVar
|
||||
: p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
|
||||
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
|
||||
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
|
||||
: p.type == "CatchClause" ? AST_SymbolCatch
|
||||
@@ -324,7 +324,7 @@
|
||||
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
|
||||
return {
|
||||
type: "VariableDeclaration",
|
||||
kind: "var",
|
||||
kind: M instanceof AST_Const ? "const" : "var",
|
||||
declarations: M.definitions.map(to_moz)
|
||||
};
|
||||
});
|
||||
@@ -381,7 +381,7 @@
|
||||
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
|
||||
var key = {
|
||||
type: "Literal",
|
||||
value: M.key instanceof AST_SymbolAccessor ? M.key.name : M.key
|
||||
value: M.key instanceof AST_SymbolMethod ? M.key.name : M.key
|
||||
};
|
||||
var kind;
|
||||
if (M instanceof AST_ObjectKeyVal) {
|
||||
|
||||
538
lib/output.js
538
lib/output.js
@@ -57,6 +57,7 @@ function OutputStream(options) {
|
||||
beautify : false,
|
||||
bracketize : false,
|
||||
comments : false,
|
||||
ecma : 5,
|
||||
ie8 : false,
|
||||
indent_level : 4,
|
||||
indent_start : 0,
|
||||
@@ -69,12 +70,16 @@ function OutputStream(options) {
|
||||
quote_style : 0,
|
||||
semicolons : true,
|
||||
shebang : true,
|
||||
shorthand : undefined,
|
||||
source_map : null,
|
||||
webkit : false,
|
||||
width : 80,
|
||||
wrap_iife : false,
|
||||
}, true);
|
||||
|
||||
if (options.shorthand === undefined)
|
||||
options.shorthand = options.ecma > 5;
|
||||
|
||||
// Convert comment option to RegExp if neccessary and set up comments filter
|
||||
var comment_filter = return_false; // Default case, throw all comments away
|
||||
if (options.comments) {
|
||||
@@ -109,7 +114,13 @@ function OutputStream(options) {
|
||||
var current_pos = 0;
|
||||
var OUTPUT = "";
|
||||
|
||||
function to_ascii(str, identifier) {
|
||||
var to_utf8 = options.ascii_only ? function(str, identifier) {
|
||||
if (options.ecma >= 6) {
|
||||
str = str.replace(/[\ud800-\udbff][\udc00-\udfff]/g, function(ch) {
|
||||
var code = get_full_char_code(ch, 0).toString(16);
|
||||
return "\\u{" + code + "}";
|
||||
});
|
||||
}
|
||||
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
|
||||
var code = ch.charCodeAt(0).toString(16);
|
||||
if (code.length <= 2 && !identifier) {
|
||||
@@ -120,6 +131,12 @@ function OutputStream(options) {
|
||||
return "\\u" + code;
|
||||
}
|
||||
});
|
||||
} : function(str) {
|
||||
return str.replace(/[\ud800-\udbff](?![\udc00-\udfff])/g, function(ch) {
|
||||
return "\\u" + ch.charCodeAt(0).toString(16);
|
||||
}).replace(/(^|[^\ud800-\udbff])([\udc00-\udfff])/g, function(match, prefix, ch) {
|
||||
return prefix + "\\u" + ch.charCodeAt(0).toString(16);
|
||||
});
|
||||
};
|
||||
|
||||
function make_string(str, quote) {
|
||||
@@ -140,7 +157,7 @@ function OutputStream(options) {
|
||||
case "\u2029": return "\\u2029";
|
||||
case "\ufeff": return "\\ufeff";
|
||||
case "\0":
|
||||
return /[0-7]/.test(str.charAt(i+1)) ? "\\x00" : "\\0";
|
||||
return /[0-9]/.test(get_full_char(str, i+1)) ? "\\x00" : "\\0";
|
||||
}
|
||||
return s;
|
||||
});
|
||||
@@ -150,7 +167,11 @@ function OutputStream(options) {
|
||||
function quote_double() {
|
||||
return '"' + str.replace(/\x22/g, '\\"') + '"';
|
||||
}
|
||||
if (options.ascii_only) str = to_ascii(str);
|
||||
function quote_template() {
|
||||
return '`' + str.replace(/`/g, '\\`') + '`';
|
||||
}
|
||||
str = to_utf8(str);
|
||||
if (quote === "`") return quote_template();
|
||||
switch (options.quote_style) {
|
||||
case 1:
|
||||
return quote_single();
|
||||
@@ -175,8 +196,7 @@ function OutputStream(options) {
|
||||
|
||||
function make_name(name) {
|
||||
name = name.toString();
|
||||
if (options.ascii_only)
|
||||
name = to_ascii(name, true);
|
||||
name = to_utf8(name, true);
|
||||
return name;
|
||||
};
|
||||
|
||||
@@ -242,12 +262,12 @@ function OutputStream(options) {
|
||||
}
|
||||
} : noop;
|
||||
|
||||
var requireSemicolonChars = makePredicate("( [ + * / - , .");
|
||||
var requireSemicolonChars = makePredicate("( [ + * / - , . `");
|
||||
|
||||
function print(str) {
|
||||
str = String(str);
|
||||
var ch = str.charAt(0);
|
||||
var prev = last.charAt(last.length - 1);
|
||||
var ch = get_full_char(str, 0);
|
||||
var prev = get_full_char(last, last.length - 1);
|
||||
if (might_need_semicolon) {
|
||||
might_need_semicolon = false;
|
||||
|
||||
@@ -323,6 +343,10 @@ function OutputStream(options) {
|
||||
last = str;
|
||||
};
|
||||
|
||||
var star = function(){
|
||||
print("*");
|
||||
}
|
||||
|
||||
var space = options.beautify ? function() {
|
||||
print(" ");
|
||||
} : function() {
|
||||
@@ -427,13 +451,14 @@ function OutputStream(options) {
|
||||
should_break : function() { return options.width && this.current_width() >= options.width },
|
||||
newline : newline,
|
||||
print : print,
|
||||
star : star,
|
||||
space : space,
|
||||
comma : comma,
|
||||
colon : colon,
|
||||
last : function() { return last },
|
||||
semicolon : semicolon,
|
||||
force_semicolon : force_semicolon,
|
||||
to_ascii : to_ascii,
|
||||
to_utf8 : to_utf8,
|
||||
print_name : function(name) { print(make_name(name)) },
|
||||
print_string : function(str, quote, escape_directive) {
|
||||
var encoded = encode_string(str, quote);
|
||||
@@ -446,6 +471,10 @@ function OutputStream(options) {
|
||||
}
|
||||
print(encoded);
|
||||
},
|
||||
print_template_string_chars: function(str) {
|
||||
var encoded = encode_string(str, '`').replace(/\${/g, "\\${");
|
||||
return print(encoded.substr(1, encoded.length - 2));
|
||||
},
|
||||
encode_string : encode_string,
|
||||
next_indent : next_indent,
|
||||
with_indent : with_indent,
|
||||
@@ -477,13 +506,17 @@ function OutputStream(options) {
|
||||
nodetype.DEFMETHOD("_codegen", generator);
|
||||
};
|
||||
|
||||
var use_asm = false;
|
||||
var in_directive = false;
|
||||
var active_scope = null;
|
||||
var use_asm = null;
|
||||
|
||||
AST_Node.DEFMETHOD("print", function(stream, force_parens){
|
||||
var self = this, generator = self._codegen, prev_use_asm = use_asm;
|
||||
if (self instanceof AST_Directive && self.value == "use asm" && stream.parent() instanceof AST_Scope) {
|
||||
use_asm = true;
|
||||
var self = this, generator = self._codegen;
|
||||
if (self instanceof AST_Scope) {
|
||||
active_scope = self;
|
||||
}
|
||||
else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
|
||||
use_asm = active_scope;
|
||||
}
|
||||
function doit() {
|
||||
self.add_comments(stream);
|
||||
@@ -497,8 +530,8 @@ function OutputStream(options) {
|
||||
doit();
|
||||
}
|
||||
stream.pop_node();
|
||||
if (self instanceof AST_Scope) {
|
||||
use_asm = prev_use_asm;
|
||||
if (self === use_asm) {
|
||||
use_asm = null;
|
||||
}
|
||||
});
|
||||
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
||||
@@ -614,6 +647,15 @@ function OutputStream(options) {
|
||||
return false;
|
||||
});
|
||||
|
||||
PARENS(AST_Arrow, function(output){
|
||||
var p = output.parent();
|
||||
return p instanceof AST_PropAccess && p.expression === this;
|
||||
});
|
||||
|
||||
PARENS(AST_ClassExpression, function(output){
|
||||
return output.parent() instanceof AST_SimpleStatement;
|
||||
});
|
||||
|
||||
// same goes for an object literal, because otherwise it would be
|
||||
// interpreted as a block of code.
|
||||
PARENS(AST_Object, function(output){
|
||||
@@ -621,6 +663,18 @@ function OutputStream(options) {
|
||||
});
|
||||
|
||||
PARENS(AST_Unary, function(output){
|
||||
var p = output.parent();
|
||||
return p instanceof AST_PropAccess && p.expression === this
|
||||
|| p instanceof AST_Call && p.expression === this
|
||||
|| p instanceof AST_Binary
|
||||
&& p.operator === "**"
|
||||
&& this instanceof AST_UnaryPrefix
|
||||
&& p.left === this
|
||||
&& this.operator !== "++"
|
||||
&& this.operator !== "--";
|
||||
});
|
||||
|
||||
PARENS(AST_Await, function(output){
|
||||
var p = output.parent();
|
||||
return p instanceof AST_PropAccess && p.expression === this
|
||||
|| p instanceof AST_Call && p.expression === this;
|
||||
@@ -628,15 +682,18 @@ function OutputStream(options) {
|
||||
|
||||
PARENS(AST_Sequence, function(output){
|
||||
var p = output.parent();
|
||||
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|
||||
|| p instanceof AST_Unary // !(foo, bar, baz)
|
||||
|| p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
|
||||
|| p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4
|
||||
|| p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
|
||||
|| p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|
||||
|| p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
|
||||
|| p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
|
||||
* ==> 20 (side effect, set a := 10 and b := 20) */
|
||||
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|
||||
|| p instanceof AST_Unary // !(foo, bar, baz)
|
||||
|| p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
|
||||
|| p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4
|
||||
|| p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
|
||||
|| p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|
||||
|| p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
|
||||
|| p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
|
||||
* ==> 20 (side effect, set a := 10 and b := 20) */
|
||||
|| p instanceof AST_Arrow // x => (x, x)
|
||||
|| p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
|
||||
|| p instanceof AST_Expansion // [...(a, b)]
|
||||
;
|
||||
});
|
||||
|
||||
@@ -663,6 +720,24 @@ function OutputStream(options) {
|
||||
}
|
||||
});
|
||||
|
||||
PARENS(AST_Yield, function(output){
|
||||
var p = output.parent();
|
||||
// (yield 1) + (yield 2)
|
||||
// a = yield 3
|
||||
if (p instanceof AST_Binary && p.operator !== "=")
|
||||
return true;
|
||||
// (yield 1) ? yield 2 : yield 3
|
||||
if (p instanceof AST_Conditional && p.condition === this)
|
||||
return true;
|
||||
// -(yield 4)
|
||||
if (p instanceof AST_Unary)
|
||||
return true;
|
||||
// (yield x).foo
|
||||
// (yield x)['foo']
|
||||
if (p instanceof AST_PropAccess && p.expression === this)
|
||||
return true;
|
||||
});
|
||||
|
||||
PARENS(AST_PropAccess, function(output){
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_New && p.expression === this) {
|
||||
@@ -672,14 +747,15 @@ function OutputStream(options) {
|
||||
// parens around it too, otherwise the call will be
|
||||
// interpreted as passing the arguments to the upper New
|
||||
// expression.
|
||||
try {
|
||||
this.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_Call) throw p;
|
||||
}));
|
||||
} catch(ex) {
|
||||
if (ex !== p) throw ex;
|
||||
return true;
|
||||
}
|
||||
var parens = false;
|
||||
this.walk(new TreeWalker(function(node) {
|
||||
if (parens || node instanceof AST_Scope) return true;
|
||||
if (node instanceof AST_Call) {
|
||||
parens = true;
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
return parens;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -732,6 +808,9 @@ function OutputStream(options) {
|
||||
// (a = foo)["prop"] —or— (a = foo).prop
|
||||
if (p instanceof AST_PropAccess && p.expression === this)
|
||||
return true;
|
||||
// ({a, b} = {a: 1, b: 2}), a destructuring assignment
|
||||
if (this instanceof AST_Assign && this.left instanceof AST_Destructuring && this.left.is_array === false)
|
||||
return true;
|
||||
});
|
||||
|
||||
/* -----[ PRINTERS ]----- */
|
||||
@@ -740,6 +819,26 @@ function OutputStream(options) {
|
||||
output.print_string(self.value, self.quote);
|
||||
output.semicolon();
|
||||
});
|
||||
|
||||
DEFPRINT(AST_Expansion, function (self, output) {
|
||||
output.print('...');
|
||||
self.expression.print(output);
|
||||
});
|
||||
|
||||
DEFPRINT(AST_Destructuring, function (self, output) {
|
||||
output.print(self.is_array ? "[" : "{");
|
||||
var len = self.names.length;
|
||||
self.names.forEach(function (name, i) {
|
||||
if (i > 0) output.comma();
|
||||
name.print(output);
|
||||
// If the final element is a hole, we need to make sure it
|
||||
// doesn't look like a trailing comma, by inserting an actual
|
||||
// trailing comma.
|
||||
if (i == len - 1 && name instanceof AST_Hole) output.comma();
|
||||
});
|
||||
output.print(self.is_array ? "]" : "}");
|
||||
});
|
||||
|
||||
DEFPRINT(AST_Debugger, function(self, output){
|
||||
output.print("debugger");
|
||||
output.semicolon();
|
||||
@@ -864,7 +963,11 @@ function OutputStream(options) {
|
||||
output.with_parens(function(){
|
||||
self.init.print(output);
|
||||
output.space();
|
||||
output.print("in");
|
||||
if (self instanceof AST_ForOf) {
|
||||
output.print("of");
|
||||
} else {
|
||||
output.print("in");
|
||||
}
|
||||
output.space();
|
||||
self.object.print(output);
|
||||
});
|
||||
@@ -885,11 +988,24 @@ function OutputStream(options) {
|
||||
AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){
|
||||
var self = this;
|
||||
if (!nokeyword) {
|
||||
if (self.async) {
|
||||
output.print("async");
|
||||
output.space();
|
||||
}
|
||||
output.print("function");
|
||||
if (self.is_generator) {
|
||||
output.star();
|
||||
}
|
||||
if (self.name) {
|
||||
output.space();
|
||||
}
|
||||
}
|
||||
if (self.name) {
|
||||
output.space();
|
||||
if (self.name instanceof AST_Symbol) {
|
||||
self.name.print(output);
|
||||
} else if (nokeyword && self.name instanceof AST_Node) {
|
||||
output.with_square(function() {
|
||||
self.name.print(output); // Computed method name
|
||||
});
|
||||
}
|
||||
output.with_parens(function(){
|
||||
self.argnames.forEach(function(arg, i){
|
||||
@@ -904,6 +1020,60 @@ function OutputStream(options) {
|
||||
self._do_print(output);
|
||||
});
|
||||
|
||||
DEFPRINT(AST_PrefixedTemplateString, function(self, output) {
|
||||
self.prefix.print(output);
|
||||
self.template_string.print(output);
|
||||
});
|
||||
DEFPRINT(AST_TemplateString, function(self, output) {
|
||||
var is_tagged = output.parent() instanceof AST_PrefixedTemplateString;
|
||||
|
||||
output.print("`");
|
||||
for (var i = 0; i < self.segments.length; i++) {
|
||||
if (!(self.segments[i] instanceof AST_TemplateSegment)) {
|
||||
output.print("${");
|
||||
self.segments[i].print(output);
|
||||
output.print("}");
|
||||
} else if (is_tagged) {
|
||||
output.print(self.segments[i].raw);
|
||||
} else {
|
||||
output.print_template_string_chars(self.segments[i].value);
|
||||
}
|
||||
}
|
||||
output.print("`");
|
||||
});
|
||||
|
||||
AST_Arrow.DEFMETHOD("_do_print", function(output){
|
||||
var self = this;
|
||||
var parent = output.parent();
|
||||
var needs_parens = parent instanceof AST_Binary ||
|
||||
parent instanceof AST_Unary ||
|
||||
(parent instanceof AST_Call && self === parent.expression);
|
||||
if (needs_parens) { output.print("(") }
|
||||
if (self.async) {
|
||||
output.print("async");
|
||||
output.space();
|
||||
}
|
||||
if (self.argnames.length === 1 && self.argnames[0] instanceof AST_Symbol) {
|
||||
self.argnames[0].print(output);
|
||||
} else {
|
||||
output.with_parens(function(){
|
||||
self.argnames.forEach(function(arg, i){
|
||||
if (i) output.comma();
|
||||
arg.print(output);
|
||||
});
|
||||
});
|
||||
}
|
||||
output.space();
|
||||
output.print('=>');
|
||||
output.space();
|
||||
if (self.body instanceof AST_Node) {
|
||||
self.body.print(output);
|
||||
} else {
|
||||
print_bracketed(self.body, output);
|
||||
}
|
||||
if (needs_parens) { output.print(")") }
|
||||
});
|
||||
|
||||
/* -----[ exits ]----- */
|
||||
AST_Exit.DEFMETHOD("_do_print", function(output, kind){
|
||||
output.print(kind);
|
||||
@@ -920,6 +1090,33 @@ function OutputStream(options) {
|
||||
self._do_print(output, "throw");
|
||||
});
|
||||
|
||||
/* -----[ yield ]----- */
|
||||
|
||||
DEFPRINT(AST_Yield, function(self, output){
|
||||
var star = self.is_star ? "*" : "";
|
||||
output.print("yield" + star);
|
||||
if (self.expression) {
|
||||
output.space();
|
||||
self.expression.print(output);
|
||||
}
|
||||
});
|
||||
|
||||
DEFPRINT(AST_Await, function(self, output){
|
||||
output.print("await");
|
||||
output.space();
|
||||
var e = self.expression;
|
||||
var parens = !(
|
||||
e instanceof AST_Call
|
||||
|| e instanceof AST_SymbolRef
|
||||
|| e instanceof AST_PropAccess
|
||||
|| e instanceof AST_Unary
|
||||
|| e instanceof AST_Constant
|
||||
);
|
||||
if (parens) output.print("(");
|
||||
self.expression.print(output);
|
||||
if (parens) output.print(")");
|
||||
});
|
||||
|
||||
/* -----[ loop control ]----- */
|
||||
AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){
|
||||
output.print(kind);
|
||||
@@ -1068,24 +1265,124 @@ function OutputStream(options) {
|
||||
if (!avoid_semicolon)
|
||||
output.semicolon();
|
||||
});
|
||||
DEFPRINT(AST_Let, function(self, output){
|
||||
self._do_print(output, "let");
|
||||
});
|
||||
DEFPRINT(AST_Var, function(self, output){
|
||||
self._do_print(output, "var");
|
||||
});
|
||||
DEFPRINT(AST_Const, function(self, output){
|
||||
self._do_print(output, "const");
|
||||
});
|
||||
DEFPRINT(AST_Import, function(self, output) {
|
||||
output.print("import");
|
||||
output.space();
|
||||
if (self.imported_name) {
|
||||
self.imported_name.print(output);
|
||||
}
|
||||
if (self.imported_name && self.imported_names) {
|
||||
output.print(",");
|
||||
output.space();
|
||||
}
|
||||
if (self.imported_names) {
|
||||
if (self.imported_names.length === 1 && self.imported_names[0].foreign_name.name === "*") {
|
||||
self.imported_names[0].print(output);
|
||||
} else {
|
||||
output.print("{");
|
||||
self.imported_names.forEach(function (name_import, i) {
|
||||
output.space();
|
||||
name_import.print(output);
|
||||
if (i < self.imported_names.length - 1) {
|
||||
output.print(",");
|
||||
}
|
||||
});
|
||||
output.space();
|
||||
output.print("}");
|
||||
}
|
||||
}
|
||||
if (self.imported_name || self.imported_names) {
|
||||
output.space();
|
||||
output.print("from")
|
||||
output.space();
|
||||
}
|
||||
self.module_name.print(output);
|
||||
output.semicolon();
|
||||
});
|
||||
|
||||
DEFPRINT(AST_NameMapping, function(self, output) {
|
||||
var is_import = output.parent() instanceof AST_Import;
|
||||
var definition = self.name.definition();
|
||||
var names_are_different =
|
||||
(definition && definition.mangled_name || self.name.name) !==
|
||||
self.foreign_name.name;
|
||||
if (names_are_different) {
|
||||
if (is_import) {
|
||||
output.print(self.foreign_name.name);
|
||||
} else {
|
||||
self.name.print(output);
|
||||
}
|
||||
output.space();
|
||||
output.print("as");
|
||||
output.space();
|
||||
if (is_import) {
|
||||
self.name.print(output);
|
||||
} else {
|
||||
output.print(self.foreign_name.name);
|
||||
}
|
||||
} else {
|
||||
self.name.print(output);
|
||||
}
|
||||
});
|
||||
|
||||
DEFPRINT(AST_Export, function(self, output) {
|
||||
output.print("export");
|
||||
output.space();
|
||||
if (self.is_default) {
|
||||
output.print("default");
|
||||
output.space();
|
||||
}
|
||||
if (self.exported_names) {
|
||||
if (self.exported_names.length === 1 && self.exported_names[0].name.name === "*") {
|
||||
self.exported_names[0].print(output);
|
||||
} else {
|
||||
output.print("{");
|
||||
self.exported_names.forEach(function(name_export, i) {
|
||||
output.space();
|
||||
name_export.print(output);
|
||||
if (i < self.exported_names.length - 1) {
|
||||
output.print(",");
|
||||
}
|
||||
});
|
||||
output.space();
|
||||
output.print("}");
|
||||
}
|
||||
}
|
||||
else if (self.exported_value) {
|
||||
self.exported_value.print(output);
|
||||
} else if (self.exported_definition) {
|
||||
self.exported_definition.print(output);
|
||||
}
|
||||
if (self.module_name) {
|
||||
output.space();
|
||||
output.print("from");
|
||||
output.space();
|
||||
self.module_name.print(output);
|
||||
}
|
||||
output.semicolon();
|
||||
});
|
||||
|
||||
function parenthesize_for_noin(node, output, noin) {
|
||||
if (!noin) node.print(output);
|
||||
else try {
|
||||
// need to take some precautions here:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/60
|
||||
node.walk(new TreeWalker(function(node){
|
||||
if (node instanceof AST_Binary && node.operator == "in")
|
||||
throw output;
|
||||
}));
|
||||
node.print(output);
|
||||
} catch(ex) {
|
||||
if (ex !== output) throw ex;
|
||||
node.print(output, true);
|
||||
}
|
||||
var parens = false;
|
||||
// need to take some precautions here:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/60
|
||||
if (noin) node.walk(new TreeWalker(function(node) {
|
||||
if (parens || node instanceof AST_Scope) return true;
|
||||
if (node instanceof AST_Binary && node.operator == "in") {
|
||||
parens = true;
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
node.print(output, parens);
|
||||
};
|
||||
|
||||
DEFPRINT(AST_VarDef, function(self, output){
|
||||
@@ -1105,6 +1402,9 @@ function OutputStream(options) {
|
||||
self.expression.print(output);
|
||||
if (self instanceof AST_New && !need_constructor_parens(self, output))
|
||||
return;
|
||||
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
|
||||
output.add_mapping(self.start);
|
||||
}
|
||||
output.with_parens(function(){
|
||||
self.args.forEach(function(expr, i){
|
||||
if (i) output.comma();
|
||||
@@ -1144,15 +1444,23 @@ function OutputStream(options) {
|
||||
DEFPRINT(AST_Dot, function(self, output){
|
||||
var expr = self.expression;
|
||||
expr.print(output);
|
||||
if (expr instanceof AST_Number && expr.getValue() >= 0) {
|
||||
if (!/[xa-f.)]/i.test(output.last())) {
|
||||
output.print(".");
|
||||
var prop = self.property;
|
||||
if (output.option("ie8") && RESERVED_WORDS(prop)) {
|
||||
output.print("[");
|
||||
output.add_mapping(self.end);
|
||||
output.print_string(prop);
|
||||
output.print("]");
|
||||
} else {
|
||||
if (expr instanceof AST_Number && expr.getValue() >= 0) {
|
||||
if (!/[xa-f.)]/i.test(output.last())) {
|
||||
output.print(".");
|
||||
}
|
||||
}
|
||||
output.print(".");
|
||||
// the name after dot would be mapped about here.
|
||||
output.add_mapping(self.end);
|
||||
output.print_name(prop);
|
||||
}
|
||||
output.print(".");
|
||||
// the name after dot would be mapped about here.
|
||||
output.add_mapping(self.end);
|
||||
output.print_name(self.property);
|
||||
});
|
||||
DEFPRINT(AST_Sub, function(self, output){
|
||||
self.expression.print(output);
|
||||
@@ -1243,6 +1551,48 @@ function OutputStream(options) {
|
||||
});
|
||||
else output.print("{}");
|
||||
});
|
||||
DEFPRINT(AST_Class, function(self, output){
|
||||
output.print("class");
|
||||
output.space();
|
||||
if (self.name) {
|
||||
self.name.print(output);
|
||||
output.space();
|
||||
}
|
||||
if (self.extends) {
|
||||
var parens = (
|
||||
!(self.extends instanceof AST_SymbolRef)
|
||||
&& !(self.extends instanceof AST_PropAccess)
|
||||
&& !(self.extends instanceof AST_ClassExpression)
|
||||
&& !(self.extends instanceof AST_Function)
|
||||
);
|
||||
output.print("extends");
|
||||
if (parens) {
|
||||
output.print("(");
|
||||
} else {
|
||||
output.space();
|
||||
}
|
||||
self.extends.print(output);
|
||||
if (parens) {
|
||||
output.print(")");
|
||||
} else {
|
||||
output.space();
|
||||
}
|
||||
}
|
||||
if (self.properties.length > 0) output.with_block(function(){
|
||||
self.properties.forEach(function(prop, i){
|
||||
if (i) {
|
||||
output.newline();
|
||||
}
|
||||
output.indent();
|
||||
prop.print(output);
|
||||
});
|
||||
output.newline();
|
||||
});
|
||||
else output.print("{}");
|
||||
});
|
||||
DEFPRINT(AST_NewTarget, function(self, output) {
|
||||
output.print("new.target");
|
||||
});
|
||||
|
||||
function print_property_name(key, quote, output) {
|
||||
if (output.option("quote_keys")) {
|
||||
@@ -1264,15 +1614,60 @@ function OutputStream(options) {
|
||||
}
|
||||
|
||||
DEFPRINT(AST_ObjectKeyVal, function(self, output){
|
||||
print_property_name(self.key, self.quote, output);
|
||||
output.colon();
|
||||
self.value.print(output);
|
||||
function get_name(self) {
|
||||
var def = self.definition();
|
||||
return def ? def.mangled_name || def.name : self.name;
|
||||
}
|
||||
|
||||
var allowShortHand = output.option("shorthand");
|
||||
if (allowShortHand &&
|
||||
self.value instanceof AST_Symbol &&
|
||||
is_identifier_string(self.key) &&
|
||||
get_name(self.value) === self.key
|
||||
) {
|
||||
print_property_name(self.key, self.quote, output);
|
||||
|
||||
} else if (allowShortHand &&
|
||||
self.value instanceof AST_DefaultAssign &&
|
||||
self.value.left instanceof AST_Symbol &&
|
||||
is_identifier_string(self.key) &&
|
||||
get_name(self.value.left) === self.key
|
||||
) {
|
||||
print_property_name(self.key, self.quote, output);
|
||||
output.space();
|
||||
output.print("=");
|
||||
output.space();
|
||||
self.value.right.print(output);
|
||||
} else {
|
||||
if (!(self.key instanceof AST_Node)) {
|
||||
print_property_name(self.key, self.quote, output);
|
||||
} else {
|
||||
output.with_square(function() {
|
||||
self.key.print(output);
|
||||
});
|
||||
}
|
||||
output.colon();
|
||||
self.value.print(output);
|
||||
}
|
||||
});
|
||||
AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) {
|
||||
output.print(type);
|
||||
output.space();
|
||||
print_property_name(this.key.name, this.quote, output);
|
||||
this.value._do_print(output, true);
|
||||
var self = this;
|
||||
if (self.static) {
|
||||
output.print("static");
|
||||
output.space();
|
||||
}
|
||||
if (type) {
|
||||
output.print(type);
|
||||
output.space();
|
||||
}
|
||||
if (self.key instanceof AST_SymbolMethod) {
|
||||
print_property_name(self.key.name, self.quote, output);
|
||||
} else {
|
||||
output.with_square(function() {
|
||||
self.key.print(output);
|
||||
});
|
||||
}
|
||||
self.value._do_print(output, true);
|
||||
});
|
||||
DEFPRINT(AST_ObjectSetter, function(self, output){
|
||||
self._print_getter_setter("set", output);
|
||||
@@ -1280,14 +1675,23 @@ function OutputStream(options) {
|
||||
DEFPRINT(AST_ObjectGetter, function(self, output){
|
||||
self._print_getter_setter("get", output);
|
||||
});
|
||||
DEFPRINT(AST_Symbol, function(self, output){
|
||||
var def = self.definition();
|
||||
output.print_name(def ? def.mangled_name || def.name : self.name);
|
||||
DEFPRINT(AST_ConciseMethod, function(self, output){
|
||||
self._print_getter_setter(self.is_generator && "*" || self.async && "async", output);
|
||||
});
|
||||
AST_Symbol.DEFMETHOD("_do_print", function(output){
|
||||
var def = this.definition();
|
||||
output.print_name(def ? def.mangled_name || def.name : this.name);
|
||||
});
|
||||
DEFPRINT(AST_Symbol, function (self, output) {
|
||||
self._do_print(output);
|
||||
});
|
||||
DEFPRINT(AST_Hole, noop);
|
||||
DEFPRINT(AST_This, function(self, output){
|
||||
output.print("this");
|
||||
});
|
||||
DEFPRINT(AST_Super, function(self, output){
|
||||
output.print("super");
|
||||
});
|
||||
DEFPRINT(AST_Constant, function(self, output){
|
||||
output.print(self.getValue());
|
||||
});
|
||||
@@ -1308,9 +1712,7 @@ function OutputStream(options) {
|
||||
if (regexp.raw_source) {
|
||||
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
||||
}
|
||||
if (output.option("ascii_only")) {
|
||||
str = output.to_ascii(str);
|
||||
}
|
||||
str = output.to_utf8(str);
|
||||
output.print(str);
|
||||
var p = output.parent();
|
||||
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
|
||||
|
||||
1620
lib/parse.js
1620
lib/parse.js
File diff suppressed because one or more lines are too long
@@ -44,6 +44,16 @@
|
||||
"use strict";
|
||||
|
||||
function find_builtins(reserved) {
|
||||
|
||||
// Compatibility fix for some standard defined globals not defined on every js environment
|
||||
var new_globals = ["Symbol", "Map", "Promise", "Proxy", "Reflect", "Set", "WeakMap", "WeakSet"];
|
||||
var objects = {};
|
||||
var global_ref = typeof global === "object" ? global : self;
|
||||
|
||||
new_globals.forEach(function (new_global) {
|
||||
objects[new_global] = global_ref[new_global] || new Function();
|
||||
});
|
||||
|
||||
// NaN will be included due to Number.NaN
|
||||
[
|
||||
"null",
|
||||
@@ -55,7 +65,15 @@ function find_builtins(reserved) {
|
||||
].forEach(add);
|
||||
[ Object, Array, Function, Number,
|
||||
String, Boolean, Error, Math,
|
||||
Date, RegExp
|
||||
Date, RegExp, objects.Symbol, ArrayBuffer,
|
||||
DataView, decodeURI, decodeURIComponent,
|
||||
encodeURI, encodeURIComponent, eval, EvalError,
|
||||
Float32Array, Float64Array, Int8Array, Int16Array,
|
||||
Int32Array, isFinite, isNaN, JSON, objects.Map, parseFloat,
|
||||
parseInt, objects.Promise, objects.Proxy, RangeError, ReferenceError,
|
||||
objects.Reflect, objects.Set, SyntaxError, TypeError, Uint8Array,
|
||||
Uint8ClampedArray, Uint16Array, Uint32Array, URIError,
|
||||
objects.WeakMap, objects.WeakSet
|
||||
].forEach(function(ctor){
|
||||
Object.getOwnPropertyNames(ctor).map(add);
|
||||
if (ctor.prototype) {
|
||||
@@ -67,6 +85,36 @@ function find_builtins(reserved) {
|
||||
}
|
||||
}
|
||||
|
||||
function reserve_quoted_keys(ast, reserved) {
|
||||
function add(name) {
|
||||
push_uniq(reserved, name);
|
||||
}
|
||||
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_ObjectKeyVal && node.quote) {
|
||||
add(node.key);
|
||||
} else if (node instanceof AST_ObjectProperty && node.quote) {
|
||||
add(node.key.name);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, add);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
function addStrings(node, add) {
|
||||
node.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Sequence) {
|
||||
addStrings(node.expressions[node.expressions.length - 1], 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,7 +124,7 @@ function mangle_properties(ast, options) {
|
||||
only_cache: false,
|
||||
regex: null,
|
||||
reserved: null,
|
||||
});
|
||||
}, true);
|
||||
|
||||
var reserved = options.reserved;
|
||||
if (!Array.isArray(reserved)) reserved = [];
|
||||
@@ -91,7 +139,6 @@ function mangle_properties(ast, options) {
|
||||
}
|
||||
|
||||
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'
|
||||
@@ -104,12 +151,11 @@ function mangle_properties(ast, options) {
|
||||
|
||||
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);
|
||||
add(node.key);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter, since KeyVal is handled above
|
||||
@@ -119,15 +165,14 @@ function mangle_properties(ast, options) {
|
||||
add(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, keep_quoted);
|
||||
addStrings(node.property, 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);
|
||||
node.key = mangle(node.key);
|
||||
}
|
||||
else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter
|
||||
@@ -136,22 +181,9 @@ function mangle_properties(ast, options) {
|
||||
else if (node instanceof AST_Dot) {
|
||||
node.property = mangle(node.property);
|
||||
}
|
||||
else if (node instanceof AST_Sub) {
|
||||
if (!keep_quoted)
|
||||
node.property = mangleStrings(node.property);
|
||||
else if (!options.keep_quoted && node instanceof AST_Sub) {
|
||||
node.property = mangleStrings(node.property);
|
||||
}
|
||||
// else if (node instanceof AST_String) {
|
||||
// if (should_mangle(node.value)) {
|
||||
// AST_Node.warn(
|
||||
// "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
|
||||
// file : node.start.file,
|
||||
// line : node.start.line,
|
||||
// col : node.start.col,
|
||||
// prop : node.value
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
}));
|
||||
|
||||
// only function declarations after this line
|
||||
@@ -167,19 +199,13 @@ function mangle_properties(ast, options) {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function add(name, keep) {
|
||||
if (keep) {
|
||||
to_keep[name] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
function add(name) {
|
||||
if (can_mangle(name))
|
||||
push_uniq(names_to_mangle, name);
|
||||
|
||||
@@ -199,19 +225,16 @@ function mangle_properties(ast, options) {
|
||||
// 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)) {
|
||||
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);
|
||||
} while (!can_mangle(mangled));
|
||||
}
|
||||
|
||||
cache.props.set(name, mangled);
|
||||
@@ -219,32 +242,6 @@ function mangle_properties(ast, options) {
|
||||
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) {
|
||||
|
||||
140
lib/scope.js
140
lib/scope.js
@@ -49,6 +49,7 @@ function SymbolDef(scope, index, orig) {
|
||||
this.scope = scope;
|
||||
this.references = [];
|
||||
this.global = false;
|
||||
this.export = false;
|
||||
this.mangled_name = null;
|
||||
this.undeclared = false;
|
||||
this.index = index;
|
||||
@@ -62,11 +63,16 @@ SymbolDef.prototype = {
|
||||
if (!options) options = {};
|
||||
|
||||
return (this.global && !options.toplevel)
|
||||
|| this.export
|
||||
|| this.undeclared
|
||||
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|
||||
|| (options.keep_fnames
|
||||
&& (this.orig[0] instanceof AST_SymbolLambda
|
||||
|| this.orig[0] instanceof AST_SymbolDefun));
|
||||
|| this.orig[0] instanceof AST_SymbolDefun))
|
||||
|| this.orig[0] instanceof AST_SymbolMethod
|
||||
|| (options.keep_classnames
|
||||
&& (this.orig[0] instanceof AST_SymbolClass
|
||||
|| this.orig[0] instanceof AST_SymbolDefClass));
|
||||
},
|
||||
mangle: function(options) {
|
||||
var cache = options.cache && options.cache.props;
|
||||
@@ -97,6 +103,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
options = defaults(options, {
|
||||
cache: null,
|
||||
ie8: false,
|
||||
safari10: false,
|
||||
});
|
||||
|
||||
// pass 1: setup scope chaining and handle definitions
|
||||
@@ -104,15 +111,33 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
var scope = self.parent_scope = null;
|
||||
var labels = new Dictionary();
|
||||
var defun = null;
|
||||
var in_destructuring = null;
|
||||
var for_scopes = [];
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node instanceof AST_Catch) {
|
||||
if (node.is_block_scope()) {
|
||||
var save_scope = scope;
|
||||
scope = new AST_Scope(node);
|
||||
node.block_scope = scope = new AST_Scope(node);
|
||||
scope.init_scope_vars(save_scope);
|
||||
if (!(node instanceof AST_Scope)) {
|
||||
scope.uses_with = save_scope.uses_with;
|
||||
scope.uses_eval = save_scope.uses_eval;
|
||||
scope.directives = save_scope.directives;
|
||||
}
|
||||
if (options.safari10) {
|
||||
if (node instanceof AST_For || node instanceof AST_ForIn) {
|
||||
for_scopes.push(scope);
|
||||
}
|
||||
}
|
||||
descend();
|
||||
scope = save_scope;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Destructuring) {
|
||||
in_destructuring = node; // These don't nest
|
||||
descend();
|
||||
in_destructuring = null;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Scope) {
|
||||
node.init_scope_vars(scope);
|
||||
var save_scope = scope;
|
||||
@@ -157,10 +182,44 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
// 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);
|
||||
var parent_lambda = defun.parent_scope;
|
||||
while (parent_lambda.is_block_scope()) {
|
||||
parent_lambda = parent_lambda.parent_scope;
|
||||
}
|
||||
mark_export((node.scope = parent_lambda).def_function(node), 1);
|
||||
}
|
||||
else if (node instanceof AST_SymbolVar) {
|
||||
defun.def_variable(node);
|
||||
else if (node instanceof AST_SymbolClass) {
|
||||
mark_export(defun.def_variable(node), 1);
|
||||
}
|
||||
else if (node instanceof AST_SymbolImport) {
|
||||
scope.def_variable(node);
|
||||
}
|
||||
else if (node instanceof AST_SymbolDefClass) {
|
||||
// This deals with the name of the class being available
|
||||
// inside the class.
|
||||
mark_export((node.scope = defun.parent_scope).def_function(node), 1);
|
||||
}
|
||||
else if (node instanceof AST_SymbolVar
|
||||
|| node instanceof AST_SymbolLet
|
||||
|| node instanceof AST_SymbolConst) {
|
||||
var def = ((node instanceof AST_SymbolBlockDeclaration) ? scope : defun).def_variable(node);
|
||||
if (!all(def.orig, function(sym) {
|
||||
if (sym === node) return true;
|
||||
if (node instanceof AST_SymbolBlockDeclaration) {
|
||||
return sym instanceof AST_SymbolLambda;
|
||||
}
|
||||
return !(sym instanceof AST_SymbolLet || sym instanceof AST_SymbolConst);
|
||||
})) {
|
||||
js_error(
|
||||
node.name + " redeclared",
|
||||
node.start.file,
|
||||
node.start.line,
|
||||
node.start.col,
|
||||
node.start.pos
|
||||
);
|
||||
}
|
||||
if (!(node instanceof AST_SymbolFunarg)) mark_export(def, 2);
|
||||
def.destructuring = in_destructuring;
|
||||
if (defun !== scope) {
|
||||
node.mark_enclosed(options);
|
||||
var def = scope.find_variable(node);
|
||||
@@ -182,6 +241,26 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
}));
|
||||
node.thedef = sym;
|
||||
}
|
||||
if (!(scope instanceof AST_Toplevel) && (node instanceof AST_Export || node instanceof AST_Import)) {
|
||||
js_error(
|
||||
node.TYPE + " statement may only appear at top level",
|
||||
node.start.file,
|
||||
node.start.line,
|
||||
node.start.col,
|
||||
node.start.pos
|
||||
);
|
||||
}
|
||||
|
||||
function mark_export(def, level) {
|
||||
if (in_destructuring) {
|
||||
var i = 0;
|
||||
do {
|
||||
level++;
|
||||
} while (tw.parent(i++) !== in_destructuring);
|
||||
}
|
||||
var node = tw.parent(level);
|
||||
def.export = node instanceof AST_Export;
|
||||
}
|
||||
});
|
||||
self.walk(tw);
|
||||
|
||||
@@ -199,8 +278,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
s.uses_eval = true;
|
||||
}
|
||||
}
|
||||
var sym = node.scope.find_variable(name);
|
||||
if (!sym) {
|
||||
var sym;
|
||||
if (tw.parent() instanceof AST_NameMapping && tw.parent(1).module_name
|
||||
|| !(sym = node.scope.find_variable(name))) {
|
||||
sym = self.def_global(node);
|
||||
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
|
||||
sym.scope.uses_arguments = true;
|
||||
@@ -235,11 +315,25 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
ref.reference(options);
|
||||
});
|
||||
node.thedef = def;
|
||||
node.reference(options);
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// pass 4: add symbol definitions to loop scopes
|
||||
// Safari/Webkit bug workaround - loop init let variable shadowing argument.
|
||||
// https://github.com/mishoo/UglifyJS2/issues/1753
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=171041
|
||||
if (options.safari10) {
|
||||
for (var i = 0; i < for_scopes.length; i++) {
|
||||
var scope = for_scopes[i];
|
||||
scope.parent_scope.variables.each(function(def) {
|
||||
push_uniq(scope.enclosed, def);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (options.cache) {
|
||||
this.cname = options.cache.cname;
|
||||
}
|
||||
@@ -268,6 +362,14 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){
|
||||
this.cname = -1; // the current index for mangling functions/variables
|
||||
});
|
||||
|
||||
AST_Node.DEFMETHOD("is_block_scope", return_false);
|
||||
AST_Class.DEFMETHOD("is_block_scope", return_false);
|
||||
AST_Lambda.DEFMETHOD("is_block_scope", return_false);
|
||||
AST_Toplevel.DEFMETHOD("is_block_scope", return_false);
|
||||
AST_SwitchBranch.DEFMETHOD("is_block_scope", return_false);
|
||||
AST_Block.DEFMETHOD("is_block_scope", return_true);
|
||||
AST_IterationStatement.DEFMETHOD("is_block_scope", return_true);
|
||||
|
||||
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
|
||||
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
|
||||
this.uses_arguments = false;
|
||||
@@ -305,7 +407,9 @@ AST_Scope.DEFMETHOD("find_variable", function(name){
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("def_function", function(symbol){
|
||||
this.functions.set(symbol.name, this.def_variable(symbol));
|
||||
var def = this.def_variable(symbol);
|
||||
this.functions.set(symbol.name, def);
|
||||
return def;
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("def_variable", function(symbol){
|
||||
@@ -373,14 +477,6 @@ AST_Symbol.DEFMETHOD("unreferenced", function(){
|
||||
&& !(this.scope.uses_eval || this.scope.uses_with);
|
||||
});
|
||||
|
||||
AST_Symbol.DEFMETHOD("undeclared", function(){
|
||||
return this.definition().undeclared;
|
||||
});
|
||||
|
||||
AST_LabelRef.DEFMETHOD("undeclared", return_false);
|
||||
|
||||
AST_Label.DEFMETHOD("undeclared", return_false);
|
||||
|
||||
AST_Symbol.DEFMETHOD("definition", function(){
|
||||
return this.thedef;
|
||||
});
|
||||
@@ -393,6 +489,7 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
||||
options = defaults(options, {
|
||||
eval : false,
|
||||
ie8 : false,
|
||||
keep_classnames: false,
|
||||
keep_fnames : false,
|
||||
reserved : [],
|
||||
toplevel : false,
|
||||
@@ -446,13 +543,18 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
node.mangled_name = name;
|
||||
return true;
|
||||
}
|
||||
if (!options.ie8 && node instanceof AST_SymbolCatch) {
|
||||
var mangle_with_block_scope =
|
||||
(!options.ie8 && node instanceof AST_SymbolCatch) ||
|
||||
node instanceof AST_SymbolBlockDeclaration;
|
||||
if (mangle_with_block_scope && options.reserved.indexOf(node.name) < 0) {
|
||||
to_mangle.push(node.definition());
|
||||
return;
|
||||
}
|
||||
});
|
||||
this.walk(tw);
|
||||
to_mangle.forEach(function(def){ def.mangle(options) });
|
||||
to_mangle.forEach(function(def){
|
||||
def.mangle(options);
|
||||
});
|
||||
|
||||
if (options.cache) {
|
||||
options.cache.cname = this.cname;
|
||||
|
||||
@@ -70,7 +70,7 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
if (y !== undefined) x = y;
|
||||
}
|
||||
}
|
||||
tw.pop(this);
|
||||
tw.pop();
|
||||
return x;
|
||||
});
|
||||
};
|
||||
@@ -163,10 +163,18 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
if (self.value) self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Destructuring, function(self, tw) {
|
||||
self.names = do_list(self.names, tw);
|
||||
});
|
||||
|
||||
_(AST_Lambda, function(self, tw){
|
||||
if (self.name) self.name = self.name.transform(tw);
|
||||
self.argnames = do_list(self.argnames, tw);
|
||||
self.body = do_list(self.body, tw);
|
||||
if (self.body instanceof AST_Node) {
|
||||
self.body = self.body.transform(tw);
|
||||
} else {
|
||||
self.body = do_list(self.body, tw);
|
||||
}
|
||||
});
|
||||
|
||||
_(AST_Call, function(self, tw){
|
||||
@@ -187,6 +195,14 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
self.property = self.property.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Yield, function(self, tw){
|
||||
if (self.expression) self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Await, function(self, tw){
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Unary, function(self, tw){
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
@@ -211,7 +227,46 @@ TreeTransformer.prototype = new TreeWalker;
|
||||
});
|
||||
|
||||
_(AST_ObjectProperty, function(self, tw){
|
||||
if (self.key instanceof AST_Node) {
|
||||
self.key = self.key.transform(tw);
|
||||
}
|
||||
self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Class, function(self, tw){
|
||||
if (self.name) self.name = self.name.transform(tw);
|
||||
if (self.extends) self.extends = self.extends.transform(tw);
|
||||
self.properties = do_list(self.properties, tw);
|
||||
});
|
||||
|
||||
_(AST_Expansion, function(self, tw){
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_NameMapping, function(self, tw) {
|
||||
self.foreign_name = self.foreign_name.transform(tw);
|
||||
self.name = self.name.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Import, function(self, tw) {
|
||||
if (self.imported_name) self.imported_name = self.imported_name.transform(tw);
|
||||
if (self.imported_names) do_list(self.imported_names, tw);
|
||||
self.module_name = self.module_name.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_Export, function(self, tw) {
|
||||
if (self.exported_definition) self.exported_definition = self.exported_definition.transform(tw);
|
||||
if (self.exported_value) self.exported_value = self.exported_value.transform(tw);
|
||||
if (self.exported_names) do_list(self.exported_names, tw);
|
||||
if (self.module_name) self.module_name = self.module_name.transform(tw);
|
||||
});
|
||||
|
||||
_(AST_TemplateString, function(self, tw) {
|
||||
self.segments = do_list(self.segments, tw);
|
||||
});
|
||||
|
||||
_(AST_PrefixedTemplateString, function(self, tw) {
|
||||
self.template_string = self.template_string.transform(tw);
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
42
package.json
42
package.json
@@ -1,20 +1,17 @@
|
||||
{
|
||||
"name": "uglify-js",
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"homepage": "http://lisperator.net/uglifyjs",
|
||||
"name": "uglify-es",
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit for ES6+",
|
||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.0.21",
|
||||
"version": "3.1.6",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
"maintainers": [
|
||||
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mishoo/UglifyJS2.git"
|
||||
},
|
||||
"repository": "git+https://github.com/mishoo/UglifyJS2.git#harmony",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mishoo/UglifyJS2/issues"
|
||||
},
|
||||
@@ -29,16 +26,33 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "~2.9.0",
|
||||
"source-map": "~0.5.1"
|
||||
"commander": "~2.11.0",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "~5.0.3",
|
||||
"mocha": "~2.3.4",
|
||||
"semver": "~5.3.0"
|
||||
"acorn": "~5.1.1",
|
||||
"mocha": "~3.5.1",
|
||||
"semver": "~5.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test/run-tests.js"
|
||||
},
|
||||
"keywords": ["uglify", "uglify-js", "minify", "minifier", "es5"]
|
||||
"keywords": [
|
||||
"uglify",
|
||||
"uglify-es",
|
||||
"uglify-js",
|
||||
"minify",
|
||||
"minifier",
|
||||
"javascript",
|
||||
"ecmascript",
|
||||
"es5",
|
||||
"es6",
|
||||
"es7",
|
||||
"es8",
|
||||
"es2015",
|
||||
"es2016",
|
||||
"es2017",
|
||||
"async",
|
||||
"await"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
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");
|
||||
@@ -33,6 +34,7 @@ function done() {
|
||||
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);
|
||||
@@ -51,6 +53,7 @@ urls.forEach(function(url) {
|
||||
results[url] = {
|
||||
input: 0,
|
||||
output: 0,
|
||||
gzip: 0,
|
||||
log: ""
|
||||
};
|
||||
fetch(url, function(err, res) {
|
||||
@@ -61,6 +64,10 @@ urls.forEach(function(url) {
|
||||
}).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();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// NOTE trailing comma doesn't contribute to length of an array
|
||||
// That also means the array changes length if previous element is a hole too and got cut off
|
||||
holes_and_undefined: {
|
||||
input: {
|
||||
w = [1,,];
|
||||
@@ -91,6 +93,79 @@ constant_join_2: {
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_variable_as_last_element: {
|
||||
input: {
|
||||
var values = [4, 5, 6];
|
||||
var a = [1, 2, 3, ...values];
|
||||
}
|
||||
expect: {
|
||||
var values = [4, 5, 6];
|
||||
var a = [1, 2, 3, ...values];
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_variable_in_middle: {
|
||||
input: {
|
||||
var values = [4, 5, 6];
|
||||
var a = [1, 2, 3, ...values, 7,,,];
|
||||
}
|
||||
expect: {
|
||||
var values = [4, 5, 6];
|
||||
var a = [1, 2, 3, ...values, 7,,,];
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_variable_at_front: {
|
||||
input: {
|
||||
var values = [1, 2, 3];
|
||||
var a = [...values, 4, 5, 6];
|
||||
}
|
||||
expect: {
|
||||
var values = [1, 2, 3];
|
||||
var a = [...values, 4, 5, 6];
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_variable_at_front_after_elisions: {
|
||||
input: {
|
||||
var values = [1, 2, 3];
|
||||
var a = [,,,...values, 4, 5, 6];
|
||||
}
|
||||
expect: {
|
||||
var values = [1, 2, 3];
|
||||
var a = [,,,...values, 4, 5, 6];
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_array_at_end: {
|
||||
input: {
|
||||
var a = [1, 2, ...[4, 5, 6]];
|
||||
}
|
||||
expect: {
|
||||
var a = [1, 2, ...[4, 5, 6]];
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_logical_expression_at_end: {
|
||||
options = { evaluate: true }
|
||||
input: {
|
||||
var a = [1, 2, 3, ...[2+2]]
|
||||
}
|
||||
expect: {
|
||||
var a = [1, 2, 3, ...[4]]
|
||||
}
|
||||
}
|
||||
|
||||
spread_with_logical_expression_at_middle: {
|
||||
options = { evaluate: true }
|
||||
input: {
|
||||
var a = [1, 1, ...[1+1, 1+2, 2+3], 8]
|
||||
}
|
||||
expect: {
|
||||
var a = [1, 1, ...[2, 3, 5], 8]
|
||||
}
|
||||
}
|
||||
|
||||
constant_join_3: {
|
||||
options = {
|
||||
unsafe: true,
|
||||
@@ -128,50 +203,110 @@ constant_join_3: {
|
||||
|
||||
for_loop: {
|
||||
options = {
|
||||
unsafe : true,
|
||||
unused : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
unused: 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_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_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_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"
|
||||
}
|
||||
|
||||
661
test/compress/arrow.js
Normal file
661
test/compress/arrow.js
Normal file
@@ -0,0 +1,661 @@
|
||||
arrow_functions_without_body: {
|
||||
input: {
|
||||
var a1 = () => 42;
|
||||
var a2 = (p) => p;
|
||||
var a3 = p => p;
|
||||
var a4 = (...p) => p;
|
||||
var a5 = (b, c) => b + c;
|
||||
var a6 = (b, ...c) => b + c[0];
|
||||
var a7 = (...b) => b.join();
|
||||
}
|
||||
expect: {
|
||||
var a1 = () => 42;
|
||||
var a2 = (p) => p;
|
||||
var a3 = p => p;
|
||||
var a4 = (...p) => p;
|
||||
var a5 = (b, c) => b + c;
|
||||
var a6 = (b, ...c) => b + c[0];
|
||||
var a7 = (...b) => b.join();
|
||||
}
|
||||
}
|
||||
|
||||
arrow_functions_with_body: {
|
||||
input: {
|
||||
var a1 = () => {
|
||||
var a = 42 * Math.random();
|
||||
return a;
|
||||
};
|
||||
var a2 = (p) => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a3 = p => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a4 = (...p) => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a5 = (b, c) => {
|
||||
var result = b * c + b / c;
|
||||
return result
|
||||
};
|
||||
var a6 = (b, ...c) => {
|
||||
var result = b;
|
||||
for (var i = 0; i < c.length; i++)
|
||||
result += c[i];
|
||||
return result
|
||||
};
|
||||
var a7 = (...b) => {
|
||||
b.join();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a1 = () => {
|
||||
var a = 42 * Math.random();
|
||||
return a;
|
||||
};
|
||||
var a2 = (p) => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a3 = p => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a4 = (...p) => {
|
||||
var a = Math.random() * p;
|
||||
return a;
|
||||
};
|
||||
var a5 = (b, c) => {
|
||||
var result = b * c + b / c;
|
||||
return result
|
||||
};
|
||||
var a6 = (b, ...c) => {
|
||||
var result = b;
|
||||
for (var i = 0; i < c.length; i++)
|
||||
result += c[i];
|
||||
return result
|
||||
};
|
||||
var a7 = (...b) => {
|
||||
b.join();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
arrow_function_with_single_parameter_with_default: {
|
||||
input: {
|
||||
var foo = (a = 0) => doSomething(a);
|
||||
}
|
||||
expect_exact: "var foo=(a=0)=>doSomething(a);"
|
||||
}
|
||||
|
||||
arrow_binding_pattern: {
|
||||
input: {
|
||||
var foo = ([]) => "foo";
|
||||
var bar = ({}) => "bar";
|
||||
var with_default = (foo = "default") => foo;
|
||||
var object_with_default = ({foo = "default", bar: baz = "default"}) => foo;
|
||||
var array_after_spread = (...[foo]) => foo;
|
||||
var array_after_spread = (...{foo}) => foo;
|
||||
var computed = ({ [compute()]: x }) => {};
|
||||
var array_hole = ([, , ...x] = [1, 2]) => {};
|
||||
var object_trailing_elision = ({foo,}) => {};
|
||||
var spread_empty_array = (...[]) => "foo";
|
||||
var spread_empty_object = (...{}) => "foo";
|
||||
}
|
||||
expect: {
|
||||
var foo = ([]) => "foo";
|
||||
var bar = ({}) => "bar";
|
||||
var with_default = (foo = "default") => foo;
|
||||
var object_with_default = ({foo = "default", bar: baz = "default"}) => foo;
|
||||
var array_after_spread = (...[foo]) => foo;
|
||||
var array_after_spread = (...{foo}) => foo;
|
||||
var computed = ({ [compute()]: x }) => {};
|
||||
var array_hole = ([, , ...x] = [1, 2]) => {};
|
||||
var object_trailing_elision = ({foo,}) => {};
|
||||
var spread_empty_array = (...[]) => "foo";
|
||||
var spread_empty_object = (...{}) => "foo";
|
||||
}
|
||||
}
|
||||
|
||||
arrow_binding_pattern_strict: {
|
||||
input: {
|
||||
var foo = ([,]) => "foo";
|
||||
}
|
||||
expect_exact: 'var foo=([,])=>"foo";'
|
||||
}
|
||||
|
||||
arrow_with_regexp: {
|
||||
input: {
|
||||
num => /\d{11,14}/.test( num )
|
||||
}
|
||||
expect: {
|
||||
num => /\d{11,14}/.test( num )
|
||||
}
|
||||
}
|
||||
|
||||
arrow_unused: {
|
||||
options = {
|
||||
toplevel: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
top => dog;
|
||||
let fn = a => { console.log(a * a); };
|
||||
let u = (x, y) => x - y + g;
|
||||
(() => { console.log("0"); })();
|
||||
!function(x) {
|
||||
(() => { console.log("1"); })();
|
||||
let unused = x => { console.log(x); };
|
||||
let baz = e => e + e;
|
||||
console.log(baz(x));
|
||||
}(1);
|
||||
fn(3);
|
||||
}
|
||||
expect: {
|
||||
let fn = a => { console.log(a * a); };
|
||||
let u = (x, y) => x - y + g;
|
||||
(() => { console.log("0"); })();
|
||||
!function(x) {
|
||||
(() => { console.log("1"); })();
|
||||
let baz = e => e + e;
|
||||
console.log(baz(x));
|
||||
}(1);
|
||||
fn(3);
|
||||
}
|
||||
expect_stdout: [ "0", "1", "2", "9" ]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
arrow_unused_toplevel: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
top => dog;
|
||||
let fn = a => { console.log(a * a); };
|
||||
let u = (x, y) => x - y + g;
|
||||
(() => { console.log("0"); })();
|
||||
!function(x) {
|
||||
(() => { console.log("1"); })();
|
||||
let unused = x => { console.log(x); };
|
||||
let baz = e => e + e;
|
||||
console.log(baz(x));
|
||||
}(1);
|
||||
fn(3);
|
||||
}
|
||||
expect: {
|
||||
let fn = a => { console.log(a * a); };
|
||||
(() => { console.log("0"); })();
|
||||
!function(x) {
|
||||
(() => { console.log("1"); })();
|
||||
let baz = e => e + e;
|
||||
console.log(baz(x));
|
||||
}(1);
|
||||
fn(3);
|
||||
}
|
||||
expect_stdout: [ "0", "1", "2", "9" ]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
no_leading_parentheses: {
|
||||
input: {
|
||||
(x,y) => x(y);
|
||||
async (x,y) => await x(y);
|
||||
}
|
||||
expect_exact: "(x,y)=>x(y);async(x,y)=>await x(y);"
|
||||
}
|
||||
|
||||
async_identifiers: {
|
||||
options = {
|
||||
unsafe_arrows: true,
|
||||
ecma: 6,
|
||||
}
|
||||
input: {
|
||||
var async = function(x){ console.log("async", x); };
|
||||
var await = function(x){ console.log("await", x); };
|
||||
async(1);
|
||||
await(2);
|
||||
}
|
||||
expect: {
|
||||
var async = x => { console.log("async", x); };
|
||||
var await = x => { console.log("await", x); };
|
||||
async(1);
|
||||
await(2);
|
||||
}
|
||||
expect_stdout: [
|
||||
"async 1",
|
||||
"await 2",
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
async_function_expression: {
|
||||
options = {
|
||||
unsafe_arrows: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var named = async function foo() {
|
||||
await bar(1 + 0) + (2 + 0);
|
||||
}
|
||||
var anon = async function() {
|
||||
await (1 + 0) + bar(2 + 0);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var named = async function foo() {
|
||||
await bar(1);
|
||||
};
|
||||
var anon = async () => {
|
||||
await 1, bar(2);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
issue_27: {
|
||||
options = {
|
||||
unsafe_arrows: true,
|
||||
collapse_vars: true,
|
||||
ecma: 6,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function(jQuery) {
|
||||
var $;
|
||||
$ = jQuery;
|
||||
$("body").addClass("foo");
|
||||
})(jQuery);
|
||||
}
|
||||
expect: {
|
||||
(jQuery => {
|
||||
jQuery("body").addClass("foo");
|
||||
})(jQuery);
|
||||
}
|
||||
}
|
||||
|
||||
issue_2105_1: {
|
||||
options = {
|
||||
unsafe_arrows: true,
|
||||
collapse_vars: true,
|
||||
ecma: 6,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe_methods: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function(factory) {
|
||||
factory();
|
||||
}( function() {
|
||||
return function(fn) {
|
||||
fn()().prop();
|
||||
}( function() {
|
||||
function bar() {
|
||||
var quux = function() {
|
||||
console.log("PASS");
|
||||
}, foo = function() {
|
||||
console.log;
|
||||
quux();
|
||||
};
|
||||
return { prop: foo };
|
||||
}
|
||||
return bar;
|
||||
} );
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
(() => {
|
||||
var quux = () => {
|
||||
console.log("PASS");
|
||||
};
|
||||
return {
|
||||
prop() {
|
||||
console.log;
|
||||
quux();
|
||||
}
|
||||
};
|
||||
})().prop();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_2105_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
((factory) => {
|
||||
factory();
|
||||
})( () => {
|
||||
return ((fn) => {
|
||||
fn()().prop();
|
||||
})( () => {
|
||||
let bar = () => {
|
||||
var quux = () => {
|
||||
console.log("PASS");
|
||||
}, foo = () => {
|
||||
console.log;
|
||||
quux();
|
||||
};
|
||||
return { prop: foo };
|
||||
};
|
||||
return bar;
|
||||
} );
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
(() => {
|
||||
var quux = () => {
|
||||
console.log("PASS");
|
||||
};
|
||||
return {
|
||||
prop: () => {
|
||||
console.log;
|
||||
quux();
|
||||
}
|
||||
};
|
||||
})().prop();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2136_2: {
|
||||
options = {
|
||||
arrows: true,
|
||||
collapse_vars: true,
|
||||
ecma: 6,
|
||||
inline: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
console.log(x);
|
||||
}
|
||||
!function(a, ...b) {
|
||||
f(b[0]);
|
||||
}(1, 2, 3);
|
||||
}
|
||||
expect: {
|
||||
function f(x) {
|
||||
console.log(x);
|
||||
}
|
||||
f([2,3][0]);
|
||||
}
|
||||
expect_stdout: "2"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2136_3: {
|
||||
options = {
|
||||
arrows: true,
|
||||
collapse_vars: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
console.log(x);
|
||||
}
|
||||
!function(a, ...b) {
|
||||
f(b[0]);
|
||||
}(1, 2, 3);
|
||||
}
|
||||
expect: {
|
||||
console.log(2);
|
||||
}
|
||||
expect_stdout: "2"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
call_args: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
const a = 1;
|
||||
console.log(a);
|
||||
+function(a) {
|
||||
return a;
|
||||
}(a);
|
||||
}
|
||||
expect: {
|
||||
const a = 1;
|
||||
console.log(1);
|
||||
+(1, 1);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
call_args_drop_param: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
const a = 1;
|
||||
console.log(a);
|
||||
+function(a) {
|
||||
return a;
|
||||
}(a, b);
|
||||
}
|
||||
expect: {
|
||||
const a = 1;
|
||||
console.log(1);
|
||||
+(b, 1);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_485_crashing_1530: {
|
||||
options = {
|
||||
arrows: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
}
|
||||
input: {
|
||||
(function(a) {
|
||||
if (true) return;
|
||||
var b = 42;
|
||||
})(this);
|
||||
}
|
||||
expect: {
|
||||
this, void 0;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2084: {
|
||||
options = {
|
||||
unsafe_arrows: true,
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var c = 0;
|
||||
!function() {
|
||||
!function(c) {
|
||||
c = 1 + c;
|
||||
var c = 0;
|
||||
function f14(a_1) {
|
||||
if (c = 1 + c, 0 !== 23..toString())
|
||||
c = 1 + c, a_1 && (a_1[0] = 0);
|
||||
}
|
||||
f14();
|
||||
}(-1);
|
||||
}();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = 0;
|
||||
((c) => {
|
||||
c = 1 + c,
|
||||
c = 1 + (c = 0),
|
||||
0 !== 23..toString() && (c = 1 + c);
|
||||
})(-1),
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
export_default_object_expression: {
|
||||
options = {
|
||||
arrows: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
export default {
|
||||
foo: 1 + 2,
|
||||
bar() { return 4; },
|
||||
get baz() { return this.foo; },
|
||||
};
|
||||
}
|
||||
expect_exact: "export default{foo:3,bar:()=>4,get baz(){return this.foo}};"
|
||||
}
|
||||
|
||||
concise_methods_with_computed_property2: {
|
||||
options = {
|
||||
arrows: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var foo = {
|
||||
[[1]](v) {
|
||||
return v;
|
||||
}
|
||||
};
|
||||
console.log(foo[[1]]("PASS"));
|
||||
}
|
||||
expect_exact: 'var foo={[[1]]:v=>v};console.log(foo[[1]]("PASS"));'
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
async_object_literal: {
|
||||
options = {
|
||||
arrows: true,
|
||||
unsafe_arrows: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
async a() {
|
||||
return await foo(1 + 0);
|
||||
},
|
||||
anon: async function() {
|
||||
return await foo(2 + 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var obj = {
|
||||
a: async () => await foo(1),
|
||||
anon: async () => await foo(2)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
issue_2271: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
unsafe_arrows: false,
|
||||
}
|
||||
input: {
|
||||
var Foo = function() {};
|
||||
Foo.prototype.set = function(value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
Foo.prototype.print = function() {
|
||||
console.log(this.value);
|
||||
}
|
||||
new Foo().set("PASS").print();
|
||||
}
|
||||
expect: {
|
||||
var Foo = function() {};
|
||||
Foo.prototype.set = function(value) {
|
||||
this.value = value;
|
||||
return this;
|
||||
}
|
||||
Foo.prototype.print = function() {
|
||||
console.log(this.value);
|
||||
}
|
||||
new Foo().set("PASS").print();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
concise_method_with_super: {
|
||||
options = {
|
||||
arrows: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
f: "FAIL",
|
||||
g() {
|
||||
return super.f;
|
||||
}
|
||||
}
|
||||
Object.setPrototypeOf(o, { f: "PASS" });
|
||||
console.log(o.g());
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
f: "FAIL",
|
||||
g() {
|
||||
return super.f;
|
||||
}
|
||||
}
|
||||
Object.setPrototypeOf(o, { f: "PASS" });
|
||||
console.log(o.g());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
@@ -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\'}'
|
||||
}
|
||||
|
||||
@@ -104,3 +104,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;'
|
||||
}
|
||||
|
||||
294
test/compress/async.js
Normal file
294
test/compress/async.js
Normal file
@@ -0,0 +1,294 @@
|
||||
await_precedence: {
|
||||
input: {
|
||||
async function f1() { await x + y; }
|
||||
async function f2() { await (x + y); }
|
||||
}
|
||||
expect_exact: "async function f1(){await x+y}async function f2(){await(x+y)}"
|
||||
}
|
||||
|
||||
await_precedence_prop: {
|
||||
input: {
|
||||
async function f1(){ return (await foo()).bar; }
|
||||
async function f2(){ return (await foo().bar); }
|
||||
}
|
||||
expect_exact: "async function f1(){return(await foo()).bar}async function f2(){return await foo().bar}"
|
||||
}
|
||||
|
||||
await_precedence_call: {
|
||||
input: {
|
||||
async function f3(){ return (await foo())(); }
|
||||
async function f4(){ return await (foo()()); }
|
||||
}
|
||||
expect_exact: "async function f3(){return(await foo())()}async function f4(){return await foo()()}"
|
||||
}
|
||||
|
||||
async_function_declaration: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
async function f0() {}
|
||||
async function f1() { await x + y; }
|
||||
async function f2() { await (x + y); }
|
||||
async function f3() { await x + await y; }
|
||||
async function f4() { await (x + await y); }
|
||||
async function f5() { await x; await y; }
|
||||
async function f6() { await x, await y; }
|
||||
}
|
||||
expect: {
|
||||
async function f0() {}
|
||||
async function f1() { await x, y; }
|
||||
async function f2() { await (x + y); }
|
||||
async function f3() { await x, await y; }
|
||||
async function f4() { await (x + await y); }
|
||||
async function f5() { await x; await y; }
|
||||
async function f6() { await x, await y; }
|
||||
}
|
||||
}
|
||||
|
||||
async_function_expression: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var named = async function foo() {
|
||||
await bar(1 + 0) + (2 + 0);
|
||||
}
|
||||
var anon = async function() {
|
||||
await (1 + 0) + bar(2 + 0);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var named = async function() {
|
||||
await bar(1);
|
||||
};
|
||||
var anon = async function() {
|
||||
await 1, bar(2);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async_class: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
class Foo {
|
||||
async m1() {
|
||||
return await foo(1 + 2);
|
||||
}
|
||||
static async m2() {
|
||||
return await foo(3 + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
class Foo {
|
||||
async m1() {
|
||||
return await foo(3);
|
||||
}
|
||||
static async m2() {
|
||||
return await foo(7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async_object_literal: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
async a() {
|
||||
await foo(1 + 0);
|
||||
},
|
||||
anon: async function(){
|
||||
await foo(2 + 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var obj = {
|
||||
async a() {
|
||||
await foo(1);
|
||||
},
|
||||
anon: async function() {
|
||||
await foo(2);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async_export: {
|
||||
input: {
|
||||
export async function run() {};
|
||||
export default async function def() {};
|
||||
}
|
||||
expect: {
|
||||
export async function run() {};
|
||||
export default async function def() {};
|
||||
}
|
||||
}
|
||||
|
||||
async_inline: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(async function(){ return await 3; })();
|
||||
(async function(x){ await console.log(x); })(4);
|
||||
|
||||
function echo(x) { return x; }
|
||||
echo( async function(){ return await 1; }() );
|
||||
echo( async function(x){ await console.log(x); }(2) );
|
||||
|
||||
function top() { console.log("top"); }
|
||||
top();
|
||||
|
||||
async function async_top() { console.log("async_top"); }
|
||||
async_top();
|
||||
}
|
||||
expect: {
|
||||
!async function(){await 3}();
|
||||
!async function(x){await console.log(4)}();
|
||||
|
||||
function echo(x){return x}
|
||||
echo(async function(){return await 1}());
|
||||
echo(async function(x){await console.log(2)}());
|
||||
|
||||
console.log("top");
|
||||
|
||||
!async function(){console.log("async_top")}();
|
||||
}
|
||||
expect_stdout: [
|
||||
"4",
|
||||
"2",
|
||||
"top",
|
||||
"async_top",
|
||||
]
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
async_identifiers: {
|
||||
input: {
|
||||
var async = function(x){ console.log("async", x); };
|
||||
var await = function(x){ console.log("await", x); };
|
||||
async(1);
|
||||
await(2);
|
||||
}
|
||||
expect: {
|
||||
var async = function(x){ console.log("async", x); };
|
||||
var await = function(x){ console.log("await", x); };
|
||||
async(1);
|
||||
await(2);
|
||||
}
|
||||
expect_stdout: [
|
||||
"async 1",
|
||||
"await 2",
|
||||
]
|
||||
}
|
||||
|
||||
async_shorthand_property: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
function print(o) { console.log(o.async + " " + o.await); }
|
||||
var async = "Async", await = "Await";
|
||||
|
||||
print({ async });
|
||||
print({ await });
|
||||
print({ async, await });
|
||||
print({ await, async });
|
||||
|
||||
print({ async: async });
|
||||
print({ await: await });
|
||||
print({ async: async, await: await });
|
||||
print({ await: await, async: async });
|
||||
}
|
||||
expect: {
|
||||
function a(a) { console.log(a.async + " " + a.await); }
|
||||
var n = "Async", c = "Await";
|
||||
|
||||
a({ async: n });
|
||||
a({ await: c });
|
||||
a({ async: n, await: c });
|
||||
a({ await: c, async: n });
|
||||
|
||||
a({ async: n });
|
||||
a({ await: c });
|
||||
a({ async: n, await: c });
|
||||
a({ await: c, async: n });
|
||||
}
|
||||
expect_stdout: [
|
||||
"Async undefined",
|
||||
"undefined Await",
|
||||
"Async Await",
|
||||
"Async Await",
|
||||
"Async undefined",
|
||||
"undefined Await",
|
||||
"Async Await",
|
||||
"Async Await",
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
async_arrow: {
|
||||
input: {
|
||||
let a1 = async x => await foo(x);
|
||||
let a2 = async () => await bar();
|
||||
let a3 = async (x) => await baz(x);
|
||||
let a4 = async (x, y) => { await far(x, y); }
|
||||
let a5 = async ({x = [1], y: z = 2}) => { await wow(x, z); }
|
||||
}
|
||||
expect: {
|
||||
let a1 = async x => await foo(x);
|
||||
let a2 = async () => await bar();
|
||||
let a3 = async (x) => await baz(x);
|
||||
let a4 = async (x, y) => { await far(x, y); }
|
||||
let a5 = async ({x = [1], y: z = 2}) => { await wow(x, z); }
|
||||
}
|
||||
}
|
||||
|
||||
async_arrow_wait: {
|
||||
input: {
|
||||
var a = async (x, y) => await x(y);
|
||||
}
|
||||
expect_exact: "var a=async(x,y)=>await x(y);"
|
||||
}
|
||||
|
||||
async_arrow_iife: {
|
||||
input: {
|
||||
(async () => {
|
||||
await fetch({});
|
||||
})();
|
||||
}
|
||||
expect_exact: "(async()=>{await fetch({})})();"
|
||||
}
|
||||
|
||||
async_arrow_iife_negate_iife: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
}
|
||||
input: {
|
||||
(async () => {
|
||||
await fetch();
|
||||
})();
|
||||
(() => {
|
||||
plain();
|
||||
})();
|
||||
}
|
||||
expect_exact: "(async()=>{await fetch()})();(()=>{plain()})();"
|
||||
}
|
||||
191
test/compress/block-scope.js
Normal file
191
test/compress/block-scope.js
Normal file
@@ -0,0 +1,191 @@
|
||||
|
||||
let_statement: {
|
||||
input: {
|
||||
let x = 6;
|
||||
}
|
||||
expect_exact: "let x=6;"
|
||||
}
|
||||
|
||||
do_not_hoist_let: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
};
|
||||
input: {
|
||||
function x() {
|
||||
if (FOO) {
|
||||
let let1;
|
||||
let let2;
|
||||
var var1;
|
||||
var var2;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
var var1, var2;
|
||||
if (FOO) {
|
||||
let let1;
|
||||
let let2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_not_remove_anon_blocks_if_they_have_decls: {
|
||||
input: {
|
||||
function x() {
|
||||
{
|
||||
let x;
|
||||
}
|
||||
{
|
||||
var x;
|
||||
}
|
||||
{
|
||||
const y;
|
||||
class Zee {};
|
||||
}
|
||||
}
|
||||
{
|
||||
let y;
|
||||
}
|
||||
{
|
||||
var y;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x(){
|
||||
{
|
||||
let x
|
||||
}
|
||||
var x;
|
||||
{
|
||||
const y;
|
||||
class Zee {}
|
||||
}
|
||||
}
|
||||
{
|
||||
let y
|
||||
}
|
||||
var y;
|
||||
}
|
||||
}
|
||||
|
||||
remove_unused_in_global_block: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
{
|
||||
let x;
|
||||
const y;
|
||||
class Zee {};
|
||||
var w;
|
||||
}
|
||||
let ex;
|
||||
const why;
|
||||
class Zed {};
|
||||
var wut;
|
||||
console.log(x, y, Zee);
|
||||
}
|
||||
expect: {
|
||||
var w;
|
||||
let ex;
|
||||
const why;
|
||||
class Zed {};
|
||||
var wut;
|
||||
console.log(x, y, Zee);
|
||||
}
|
||||
}
|
||||
|
||||
regression_block_scope_resolves: {
|
||||
mangle = { };
|
||||
options = {
|
||||
dead_code: false
|
||||
};
|
||||
input: {
|
||||
(function () {
|
||||
if (1) {
|
||||
let x;
|
||||
const y = 1;
|
||||
class Zee {};
|
||||
}
|
||||
if (1) {
|
||||
let ex;
|
||||
const why = 2;
|
||||
class Zi {};
|
||||
}
|
||||
console.log(typeof x, typeof y, typeof Zee, typeof ex, typeof why, typeof Zi);
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
(function () {
|
||||
if (1) {
|
||||
let e;
|
||||
const o = 1;
|
||||
class t {};
|
||||
}
|
||||
if (1) {
|
||||
let e;
|
||||
const o = 2;
|
||||
class t {};
|
||||
}
|
||||
console.log(typeof x, typeof y, typeof Zee, typeof ex, typeof why, typeof Zi);
|
||||
}());
|
||||
}
|
||||
expect_stdout: "undefined undefined undefined undefined undefined undefined"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
switch_block_scope_mangler: {
|
||||
mangle = {}
|
||||
input: {
|
||||
var fn = function(code) {
|
||||
switch (code) {
|
||||
case 1:
|
||||
let apple = code + 1;
|
||||
let dog = code + 4;
|
||||
console.log(apple, dog);
|
||||
break;
|
||||
case 2:
|
||||
let banana = code + 2;
|
||||
console.log(banana);
|
||||
break;
|
||||
default:
|
||||
let cat = code + 3;
|
||||
console.log(cat);
|
||||
}
|
||||
};
|
||||
fn(1);
|
||||
fn(2);
|
||||
fn(3);
|
||||
}
|
||||
expect: {
|
||||
var fn = function(e) {
|
||||
switch (e) {
|
||||
case 1:
|
||||
let l = e + 1
|
||||
let o = e + 4;
|
||||
console.log(l, o);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
let n = e + 2;
|
||||
console.log(n);
|
||||
break;
|
||||
|
||||
default:
|
||||
let c = e + 3;
|
||||
console.log(c);
|
||||
}
|
||||
};
|
||||
fn(1);
|
||||
fn(2);
|
||||
fn(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"2 5",
|
||||
"4",
|
||||
"6",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
@@ -47,3 +47,142 @@ keep_some_blocks: {
|
||||
} else stuff();
|
||||
}
|
||||
}
|
||||
|
||||
issue_1664: {
|
||||
input: {
|
||||
var a = 1;
|
||||
function f() {
|
||||
if (undefined) a = 2;
|
||||
{
|
||||
function undefined() {}
|
||||
undefined();
|
||||
}
|
||||
}
|
||||
f();
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
function f() {
|
||||
if (undefined) a = 2;
|
||||
{
|
||||
function undefined() {}
|
||||
undefined();
|
||||
}
|
||||
}
|
||||
f();
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_1672_for: {
|
||||
input: {
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
for (; console.log("FAIL");) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
for (; console.log("FAIL");) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_1672_for_strict: {
|
||||
input: {
|
||||
"use strict";
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
for (; console.log("FAIL");) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
for (; console.log("FAIL");) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_1672_if: {
|
||||
input: {
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
if (console.log("FAIL")) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
if (console.log("FAIL")) function xxx() {}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_1672_if_strict: {
|
||||
input: {
|
||||
"use strict";
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
if (console.log("FAIL")) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
switch (function() {
|
||||
return xxx;
|
||||
}) {
|
||||
case xxx:
|
||||
if (console.log("FAIL")) {
|
||||
function xxx() {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -73,4 +73,41 @@ dont_change_in_or_instanceof_expressions: {
|
||||
1 instanceof 1;
|
||||
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_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"
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ 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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
166
test/compress/const.js
Normal file
166
test/compress/const.js
Normal file
@@ -0,0 +1,166 @@
|
||||
issue_1191: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function foo(rot) {
|
||||
const rotTol = 5;
|
||||
if (rot < -rotTol || rot > rotTol)
|
||||
bar();
|
||||
baz();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(rot) {
|
||||
(rot < -5 || rot > 5) && bar();
|
||||
baz();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1194: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function f1() {const a = "X"; return a + a;}
|
||||
function f2() {const aa = "X"; return aa + aa;}
|
||||
function f3() {const aaa = "X"; return aaa + aaa;}
|
||||
}
|
||||
expect: {
|
||||
function f1(){return"XX"}
|
||||
function f2(){return"XX"}
|
||||
function f3(){return"XX"}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1396: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function foo(a) {
|
||||
const VALUE = 1;
|
||||
console.log(2 | VALUE);
|
||||
console.log(VALUE + 1);
|
||||
console.log(VALUE);
|
||||
console.log(a & VALUE);
|
||||
}
|
||||
function bar() {
|
||||
const s = "01234567890123456789";
|
||||
console.log(s + s + s + s + s);
|
||||
|
||||
const CONSTANT = "abc";
|
||||
console.log(CONSTANT + CONSTANT + CONSTANT + CONSTANT + CONSTANT);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(a) {
|
||||
console.log(3);
|
||||
console.log(2);
|
||||
console.log(1);
|
||||
console.log(1 & a);
|
||||
}
|
||||
function bar() {
|
||||
const s = "01234567890123456789";
|
||||
console.log(s + s + s + s + s);
|
||||
|
||||
console.log("abcabcabcabcabc");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_regexp_literal: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
}
|
||||
input: {
|
||||
function f(){ var a = /b/; }
|
||||
}
|
||||
expect: {
|
||||
function f(){}
|
||||
}
|
||||
}
|
||||
|
||||
regexp_literal_not_const: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
(function(){
|
||||
var result;
|
||||
const s = 'acdabcdeabbb';
|
||||
const REGEXP_LITERAL = /ab*/g;
|
||||
while (result = REGEXP_LITERAL.exec(s)) {
|
||||
console.log(result[0]);
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var result;
|
||||
const REGEXP_LITERAL = /ab*/g;
|
||||
while (result = REGEXP_LITERAL.exec("acdabcdeabbb")) console.log(result[0]);
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
@@ -54,12 +54,12 @@ dead_code_2_should_warn: {
|
||||
x = 10;
|
||||
throw new Error("foo");
|
||||
var x;
|
||||
function g(){};
|
||||
var g;
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: "<=4"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
dead_code_2_should_warn_strict: {
|
||||
@@ -126,7 +126,7 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
}
|
||||
expect: {
|
||||
var foo;
|
||||
function bar() {}
|
||||
var bar;
|
||||
// nothing for the while
|
||||
// as for the for, it should keep:
|
||||
var x = 10, y;
|
||||
@@ -134,7 +134,7 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
bar();
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: "<=4"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
dead_code_constant_boolean_should_warn_more_strict: {
|
||||
@@ -173,6 +173,153 @@ dead_code_constant_boolean_should_warn_more_strict: {
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
dead_code_block_decls_die: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
booleans : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
if (0) {
|
||||
let foo = 6;
|
||||
const bar = 12;
|
||||
class Baz {};
|
||||
var qux;
|
||||
}
|
||||
console.log(foo, bar, Baz);
|
||||
}
|
||||
expect: {
|
||||
var qux;
|
||||
console.log(foo, bar, Baz);
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_const_declaration: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
const CONST_FOO = false;
|
||||
if (CONST_FOO) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
const CONST_FOO = !1;
|
||||
var moo;
|
||||
var bar;
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_const_annotation: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
toplevel : true,
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
/** @const */ var CONST_FOO_ANN = false;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
var CONST_FOO_ANN = !1;
|
||||
var moo;
|
||||
var bar;
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_const_annotation_regex: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
// @constraint this shouldn't be a constant
|
||||
var CONST_FOO_ANN = false;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("reachable");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
var CONST_FOO_ANN = !1;
|
||||
CONST_FOO_ANN && console.log('reachable');
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_const_annotation_complex_scope: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
toplevel : true,
|
||||
};
|
||||
input: {
|
||||
var unused_var;
|
||||
/** @const */ var test = 'test';
|
||||
// @const
|
||||
var CONST_FOO_ANN = false;
|
||||
var unused_var_2;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
if (test === 'test') {
|
||||
var beef = 'good';
|
||||
/** @const */ var meat = 'beef';
|
||||
var pork = 'bad';
|
||||
if (meat === 'pork') {
|
||||
console.log('also unreachable');
|
||||
} else if (pork === 'good') {
|
||||
console.log('reached, not const');
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused_var;
|
||||
var test = 'test';
|
||||
var CONST_FOO_ANN = !1;
|
||||
var unused_var_2;
|
||||
var moo;
|
||||
var bar;
|
||||
var beef = 'good';
|
||||
var meat = 'beef';
|
||||
var pork = 'bad';
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
try_catch_finally: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
@@ -230,3 +377,247 @@ 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_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_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",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2383_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
if (0) {
|
||||
var {x, y} = foo();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var x, y;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2383_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
if (0) {
|
||||
var {
|
||||
x = 0,
|
||||
y: [ w, , { z, p: q = 7 } ] = [ 1, 2, { z: 3 } ]
|
||||
} = {};
|
||||
}
|
||||
console.log(x, q, w, z);
|
||||
}
|
||||
expect: {
|
||||
var x, w, z, q;
|
||||
console.log(x, q, w, z);
|
||||
}
|
||||
expect_stdout: "undefined undefined undefined undefined"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2383_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var b = 7, y = 8;
|
||||
if (0) {
|
||||
var a = 1, [ x, y, z ] = [ 2, 3, 4 ], b = 5;
|
||||
}
|
||||
console.log(a, x, y, z, b);
|
||||
}
|
||||
expect: {
|
||||
var b = 7, y = 8;
|
||||
var a, x, y, z, b;
|
||||
console.log(a, x, y, z, b);
|
||||
}
|
||||
expect_stdout: "undefined undefined 8 undefined 7"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
661
test/compress/destructuring.js
Normal file
661
test/compress/destructuring.js
Normal file
@@ -0,0 +1,661 @@
|
||||
destructuring_arrays: {
|
||||
input: {
|
||||
{const [aa, bb] = cc;}
|
||||
{const [aa, [bb, cc]] = dd;}
|
||||
{let [aa, bb] = cc;}
|
||||
{let [aa, [bb, cc]] = dd;}
|
||||
var [aa, bb] = cc;
|
||||
var [aa, [bb, cc]] = dd;
|
||||
var [,[,,,,,],,,zz,] = xx; // Trailing comma
|
||||
var [,,zzz,,] = xxx; // Trailing comma after hole
|
||||
}
|
||||
expect: {
|
||||
{const [aa, bb] = cc;}
|
||||
{const [aa, [bb, cc]] = dd;}
|
||||
{let [aa, bb] = cc;}
|
||||
{let [aa, [bb, cc]] = dd;}
|
||||
var [aa, bb] = cc;
|
||||
var [aa, [bb, cc]] = dd;
|
||||
var [,[,,,,,],,,zz] = xx;
|
||||
var [,,zzz,,] = xxx;
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_arrays_holes: {
|
||||
input: {
|
||||
var [,,,,] = a;
|
||||
var [,,b,] = c;
|
||||
var [d,,] = e;
|
||||
}
|
||||
expect_exact: "var[,,,,]=a;var[,,b]=c;var[d,,]=e;"
|
||||
}
|
||||
|
||||
destructuring_objects: {
|
||||
input: {
|
||||
{const {aa, bb} = {aa:1, bb:2};}
|
||||
{const {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
{let {aa, bb} = {aa:1, bb:2};}
|
||||
{let {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
var {aa, bb} = {aa:1, bb:2};
|
||||
var {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};
|
||||
}
|
||||
expect: {
|
||||
{const {aa, bb} = {aa:1, bb:2};}
|
||||
{const {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
{let {aa, bb} = {aa:1, bb:2};}
|
||||
{let {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
var {aa, bb} = {aa:1, bb:2};
|
||||
var {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_objects_trailing_elision: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
var {cc,} = foo;
|
||||
}
|
||||
expect_exact: "var{cc}=foo;"
|
||||
}
|
||||
|
||||
nested_destructuring_objects: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
const [{a},b] = c;
|
||||
let [{d},e] = f;
|
||||
var [{g},h] = i;
|
||||
}
|
||||
expect_exact: 'const[{a},b]=c;let[{d},e]=f;var[{g},h]=i;';
|
||||
}
|
||||
|
||||
destructuring_constdef_in_loops: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
for (const [x,y] in pairs);
|
||||
for (const [a] = 0;;);
|
||||
for (const {c} of cees);
|
||||
}
|
||||
expect_exact: "for(const[x,y]in pairs);for(const[a]=0;;);for(const{c}of cees);"
|
||||
}
|
||||
|
||||
destructuring_letdef_in_loops: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
for (let [x,y] in pairs);
|
||||
for (let [a] = 0;;);
|
||||
for (let {c} of cees);
|
||||
}
|
||||
expect_exact: "for(let[x,y]in pairs);for(let[a]=0;;);for(let{c}of cees);"
|
||||
}
|
||||
|
||||
destructuring_vardef_in_loops: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
for (var [x,y] in pairs);
|
||||
for (var [a] = 0;;);
|
||||
for (var {c} of cees);
|
||||
}
|
||||
expect_exact: "for(var[x,y]in pairs);for(var[a]=0;;);for(var{c}of cees);"
|
||||
}
|
||||
|
||||
destructuring_expressions: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
({a, b});
|
||||
[{a}];
|
||||
f({x});
|
||||
}
|
||||
expect_exact: "({a,b});[{a}];f({x});"
|
||||
}
|
||||
|
||||
destructuring_remove_unused_1: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function a() {
|
||||
var unused = "foo";
|
||||
var a = [1];
|
||||
var [b] = a;
|
||||
f(b);
|
||||
}
|
||||
function b() {
|
||||
var unused = "foo";
|
||||
var a = {b: 1};
|
||||
var {b} = a;
|
||||
f(b);
|
||||
}
|
||||
function c() {
|
||||
var unused = "foo";
|
||||
var a = [[1]];
|
||||
var [[b]] = a;
|
||||
f(b);
|
||||
}
|
||||
function d() {
|
||||
var unused = "foo";
|
||||
var a = {b: {b:1}};
|
||||
var {b:{b}} = a;
|
||||
f(b);
|
||||
}
|
||||
function e() {
|
||||
var unused = "foo";
|
||||
var a = [1, 2, 3, 4, 5];
|
||||
var x = [[1, 2, 3]];
|
||||
var y = {h: 1};
|
||||
var [b, ...c] = a;
|
||||
var [...[e, f]] = x;
|
||||
var [...{g: h}] = y;
|
||||
f(b, c, e, f, g);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
var a = [1];
|
||||
var [b] = a;
|
||||
f(b);
|
||||
}
|
||||
function b() {
|
||||
var a = {b: 1};
|
||||
var {b} = a;
|
||||
f(b);
|
||||
}
|
||||
function c() {
|
||||
var a = [[1]];
|
||||
var [[b]] = a;
|
||||
f(b);
|
||||
}
|
||||
function d() {
|
||||
var a = {b: {b:1}};
|
||||
var {b:{b}} = a;
|
||||
f(b);
|
||||
}
|
||||
function e() {
|
||||
var a = [1, 2, 3, 4, 5];
|
||||
var x = [[1, 2, 3]];
|
||||
var y = {h: 1};
|
||||
var [b, ...c] = a;
|
||||
var [...[e, f]] = x;
|
||||
var [...{g: h}] = y;
|
||||
f(b, c, e, f, g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_remove_unused_2: {
|
||||
options = {
|
||||
unused: true
|
||||
}
|
||||
input: {
|
||||
function a() {
|
||||
var unused = "foo";
|
||||
var a = [,,1];
|
||||
var [b] = a;
|
||||
f(b);
|
||||
}
|
||||
function b() {
|
||||
var unused = "foo";
|
||||
var a = [{a: [1]}];
|
||||
var [{b: a}] = a;
|
||||
f(b);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
var a = [,,1];
|
||||
var [b] = a;
|
||||
f(b);
|
||||
}
|
||||
function b() {
|
||||
var a = [{a: [1]}];
|
||||
var [{b: a}] = a;
|
||||
f(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object_destructuring_may_need_parentheses: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
({a, b} = {a: 1, b: 2});
|
||||
}
|
||||
expect_exact: "({a,b}={a:1,b:2});"
|
||||
}
|
||||
|
||||
destructuring_with_undefined_as_default_assignment: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
[foo = undefined] = bar;
|
||||
[foo = void 0] = bar;
|
||||
}
|
||||
expect: {
|
||||
[foo] = bar;
|
||||
[foo] = bar;
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_dont_evaluate_with_undefined_as_default_assignment: {
|
||||
options = {
|
||||
evaluate: false
|
||||
}
|
||||
input: {
|
||||
[foo = undefined] = bar;
|
||||
}
|
||||
expect: {
|
||||
[foo = void 0] = bar;
|
||||
}
|
||||
}
|
||||
|
||||
reduce_vars: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
{const [aa, [bb, cc]] = dd;}
|
||||
{let [aa, [bb, cc]] = dd;}
|
||||
var [aa, [bb, cc]] = dd;
|
||||
[aa, [bb, cc]] = dd;
|
||||
{const {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
{let {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
var {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};
|
||||
({aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}});
|
||||
const [{a},b] = c;
|
||||
let [{d},e] = f;
|
||||
var [{g},h] = i;
|
||||
[{a},b] = c;
|
||||
for (const [x,y] in pairs);
|
||||
for (let [x,y] in pairs);
|
||||
for (var [x,y] in pairs);
|
||||
for ([x,y] in pairs);
|
||||
}
|
||||
expect: {
|
||||
{const [aa, [bb, cc]] = dd;}
|
||||
{let [aa, [bb, cc]] = dd;}
|
||||
var [aa, [bb, cc]] = dd;
|
||||
[aa, [bb, cc]] = dd;
|
||||
{const {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
{let {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};}
|
||||
var {aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}};
|
||||
({aa, bb: {cc, dd}} = {aa:1, bb: {cc:2, dd: 3}});
|
||||
const [{a},b] = c;
|
||||
let [{d},e] = f;
|
||||
var [{g},h] = i;
|
||||
[{a},b] = c;
|
||||
for (const [x,y] in pairs);
|
||||
for (let [x,y] in pairs);
|
||||
for (var [x,y] in pairs);
|
||||
for ([x,y] in pairs);
|
||||
}
|
||||
}
|
||||
|
||||
unused: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
let { foo: [, , ...a] } = { foo: [1, 2, 3, 4], bar: 5 };
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
let { foo: [, , ...a] } = { foo: [1, 2, 3, 4], bar: 5 };
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
|
||||
issue_1886: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
let [a] = [1];
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
let [a] = [1];
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_decl_of_numeric_key: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
let { 3: x } = { [1 + 2]: 42 };
|
||||
console.log(x);
|
||||
}
|
||||
expect: {
|
||||
let { 3: x } = { [3]: 42 };
|
||||
console.log(x);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
destructuring_decl_of_computed_key: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
let four = 4;
|
||||
let { [7 - four]: x } = { [1 + 2]: 42 };
|
||||
console.log(x);
|
||||
}
|
||||
expect: {
|
||||
let four = 4;
|
||||
let { [7 - four]: x } = { [3]: 42 };
|
||||
console.log(x);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
destructuring_assign_of_numeric_key: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
let x;
|
||||
({ 3: x } = { [1 + 2]: 42 });
|
||||
console.log(x);
|
||||
}
|
||||
expect: {
|
||||
let x;
|
||||
({ 3: x } = { [3]: 42 });
|
||||
console.log(x);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
destructuring_assign_of_computed_key: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
let x;
|
||||
let four = 4;
|
||||
({ [(5 + 2) - four]: x } = { [1 + 2]: 42 });
|
||||
console.log(x);
|
||||
}
|
||||
expect: {
|
||||
let x;
|
||||
let four = 4;
|
||||
({ [7 - four]: x } = { [3]: 42 });
|
||||
console.log(x);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
mangle_destructuring_decl: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
}
|
||||
input: {
|
||||
function test(opts) {
|
||||
let a = opts.a || { e: 7, n: 8 };
|
||||
let { t, e, n, s = 5 + 4, o, r } = a;
|
||||
console.log(t, e, n, s, o, r);
|
||||
}
|
||||
test({a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 }});
|
||||
test({});
|
||||
}
|
||||
expect: {
|
||||
function test(t) {
|
||||
let e = t.a || { e: 7, n: 8 };
|
||||
let {t: n, e: o, n: s, s: l = 9, o: a, r: c} = e;
|
||||
console.log(n, o, s, l, a, c);
|
||||
}
|
||||
test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
|
||||
test({});
|
||||
}
|
||||
expect_stdout: [
|
||||
"1 2 3 4 5 6",
|
||||
"undefined 7 8 9 undefined undefined",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
mangle_destructuring_assign_toplevel_true: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
function test(opts) {
|
||||
let s, o, r;
|
||||
let a = opts.a || { e: 7, n: 8 };
|
||||
({ t, e, n, s = 5 + 4, o, r } = a);
|
||||
console.log(t, e, n, s, o, r);
|
||||
}
|
||||
let t, e, n;
|
||||
test({a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 }});
|
||||
test({});
|
||||
}
|
||||
expect: {
|
||||
function e(e) {
|
||||
let l, s, a;
|
||||
let c = e.a || { e: 7, n: 8 };
|
||||
({t: n, e: o, n: t, s: l = 9, o: s, r: a} = c);
|
||||
console.log(n, o, t, l, s, a);
|
||||
}
|
||||
let n, o, t;
|
||||
e({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
|
||||
e({});
|
||||
}
|
||||
expect_stdout: [
|
||||
"1 2 3 4 5 6",
|
||||
"undefined 7 8 9 undefined undefined",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
mangle_destructuring_assign_toplevel_false: {
|
||||
options = {
|
||||
toplevel: false,
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: false,
|
||||
}
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
function test(opts) {
|
||||
let s, o, r;
|
||||
let a = opts.a || { e: 7, n: 8 };
|
||||
({ t, e, n, s = 9, o, r } = a);
|
||||
console.log(t, e, n, s, o, r);
|
||||
}
|
||||
let t, e, n;
|
||||
test({a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 }});
|
||||
test({});
|
||||
}
|
||||
expect: {
|
||||
function test(o) {
|
||||
let s, l, a;
|
||||
let c = o.a || { e: 7, n: 8 };
|
||||
({t, e, n, s = 9, o: l, r: a} = c);
|
||||
console.log(t, e, n, s, l, a);
|
||||
}
|
||||
let t, e, n;
|
||||
test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
|
||||
test({});
|
||||
}
|
||||
expect_stdout: [
|
||||
"1 2 3 4 5 6",
|
||||
"undefined 7 8 9 undefined undefined",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
mangle_destructuring_decl_array: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
var [, t, e, n, s, o = 2, r = [ 1 + 2 ]] = [ 9, 8, 7, 6 ];
|
||||
console.log(t, e, n, s, o, r);
|
||||
}
|
||||
expect: {
|
||||
var [, o, l, a, c, e = 2, g = [ 3 ]] = [ 9, 8, 7, 6 ];
|
||||
console.log(o, l, a, c, e, g);
|
||||
}
|
||||
expect_stdout: "8 7 6 undefined 2 [ 3 ]"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
anon_func_with_destructuring_args: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
beautify = {
|
||||
ecma: 5,
|
||||
}
|
||||
input: {
|
||||
(function({foo = 1 + 0, bar = 2}, [car = 3, far = 4]) {
|
||||
console.log(foo, bar, car, far);
|
||||
})({bar: 5 - 0}, [, 6]);
|
||||
}
|
||||
expect: {
|
||||
(function({foo: o = 1, bar: n = 2}, [a = 3, b = 4]) {
|
||||
console.log(o, n, a, b);
|
||||
})({bar: 5}, [, 6]);
|
||||
}
|
||||
expect_stdout: "1 5 3 6"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
arrow_func_with_destructuring_args: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unused: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
beautify = {
|
||||
ecma: 5,
|
||||
}
|
||||
input: {
|
||||
(({foo = 1 + 0, bar = 2}, [car = 3, far = 4]) => {
|
||||
console.log(foo, bar, car, far);
|
||||
})({bar: 5 - 0}, [, 6]);
|
||||
}
|
||||
expect: {
|
||||
(({foo: o = 1, bar: a = 2}, [b = 3, l = 4]) => {
|
||||
console.log(o, a, b, l);
|
||||
})({bar: 5}, [, 6]);
|
||||
}
|
||||
expect_stdout: "1 5 3 6"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2044_ecma_5: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
ecma: 5,
|
||||
}
|
||||
input: {
|
||||
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
|
||||
}
|
||||
expect_exact: "({x:a=1,y:y=2+b,z:z=3-c}=obj);"
|
||||
}
|
||||
|
||||
issue_2044_ecma_6: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
ecma: 6,
|
||||
}
|
||||
input: {
|
||||
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
|
||||
}
|
||||
expect_exact: "({x:a=1,y=2+b,z=3-c}=obj);"
|
||||
}
|
||||
|
||||
issue_2044_ecma_5_beautify: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
ecma: 5,
|
||||
}
|
||||
input: {
|
||||
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
|
||||
}
|
||||
expect_exact: "({x: a = 1, y: y = 2 + b, z: z = 3 - c} = obj);"
|
||||
}
|
||||
|
||||
issue_2044_ecma_6_beautify: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
ecma: 6,
|
||||
}
|
||||
input: {
|
||||
({x : a = 1, y = 2 + b, z = 3 - c} = obj);
|
||||
}
|
||||
expect_exact: "({x: a = 1, y = 2 + b, z = 3 - c} = obj);"
|
||||
}
|
||||
|
||||
issue_2140: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function() {
|
||||
var t = {};
|
||||
console.log(([t.a] = [42])[0]);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
var t = {};
|
||||
console.log(([t.a] = [42])[0]);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "42"
|
||||
node_version: ">=6"
|
||||
}
|
||||
10
test/compress/directives.js
Normal file
10
test/compress/directives.js
Normal file
@@ -0,0 +1,10 @@
|
||||
class_directives_compression: {
|
||||
input: {
|
||||
class foo {
|
||||
foo() {
|
||||
"use strict";
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: "class foo{foo(){}}"
|
||||
}
|
||||
@@ -164,6 +164,87 @@ used_var_in_catch: {
|
||||
}
|
||||
}
|
||||
|
||||
unused_block_decls_in_catch: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {
|
||||
let x = 10;
|
||||
const y = 10;
|
||||
class Zee {};
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
used_block_decls_in_catch: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {
|
||||
let x = 10;
|
||||
const y = 10;
|
||||
class Zee {};
|
||||
}
|
||||
console.log(x, y, Zee);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
try {
|
||||
foo();
|
||||
} catch(ex) {}
|
||||
console.log(x, y, Zee);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_block_decls: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function foo() {
|
||||
{
|
||||
const x;
|
||||
}
|
||||
{
|
||||
let y;
|
||||
}
|
||||
console.log(x, y);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
console.log(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_keep_harmony_destructuring: {
|
||||
options = { unused: true };
|
||||
input: {
|
||||
function foo() {
|
||||
var {x, y} = foo;
|
||||
var a = foo;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
var {x, y} = foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keep_fnames: {
|
||||
options = { unused: true, keep_fnames: true, unsafe: true };
|
||||
input: {
|
||||
@@ -649,6 +730,37 @@ drop_value: {
|
||||
}
|
||||
}
|
||||
|
||||
const_assign: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
const b = 2;
|
||||
return 1 + b;
|
||||
}
|
||||
|
||||
function g() {
|
||||
const b = 2;
|
||||
b = 3;
|
||||
return 1 + b;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
function g() {
|
||||
const b = 2;
|
||||
b = 3;
|
||||
return 1 + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1539: {
|
||||
options = {
|
||||
cascade: true,
|
||||
@@ -751,12 +863,12 @@ issue_1583: {
|
||||
expect: {
|
||||
function m(t) {
|
||||
(function(e) {
|
||||
t = e();
|
||||
})(function() {
|
||||
return (function(a) {
|
||||
return a;
|
||||
})(function(a) {});
|
||||
});
|
||||
t = function() {
|
||||
return (function(a) {
|
||||
return function(a) {};
|
||||
})();
|
||||
}();
|
||||
})();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -785,6 +897,10 @@ issue_1709: {
|
||||
var x = 1;
|
||||
return x;
|
||||
}(),
|
||||
function y() {
|
||||
const y = 2;
|
||||
return y;
|
||||
}(),
|
||||
function z() {
|
||||
function z() {}
|
||||
return z;
|
||||
@@ -797,6 +913,10 @@ issue_1709: {
|
||||
var x = 1;
|
||||
return x;
|
||||
}(),
|
||||
function() {
|
||||
const y = 2;
|
||||
return y;
|
||||
}(),
|
||||
function() {
|
||||
function z() {}
|
||||
return z;
|
||||
@@ -1090,6 +1210,7 @@ var_catch_toplevel: {
|
||||
a--;
|
||||
try {
|
||||
a++;
|
||||
x();
|
||||
} catch(a) {
|
||||
if (a) var a;
|
||||
var a = 10;
|
||||
@@ -1099,9 +1220,8 @@ var_catch_toplevel: {
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
a--;
|
||||
try {
|
||||
a++;
|
||||
x();
|
||||
} catch(a) {
|
||||
var a;
|
||||
}
|
||||
@@ -1109,10 +1229,76 @@ var_catch_toplevel: {
|
||||
}
|
||||
}
|
||||
|
||||
reassign_const: {
|
||||
options = {
|
||||
cascade: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
const a = 1;
|
||||
a = 2;
|
||||
return a;
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
const a = 1;
|
||||
return a = 2, a;
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1968: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(c) {
|
||||
var a;
|
||||
if (c) {
|
||||
let b;
|
||||
return (a = 2) + (b = 3);
|
||||
}
|
||||
}
|
||||
console.log(f(1));
|
||||
}
|
||||
expect: {
|
||||
function f(c) {
|
||||
if (c) {
|
||||
let b;
|
||||
return 2 + (b = 3);
|
||||
}
|
||||
}
|
||||
console.log(f(1));
|
||||
}
|
||||
expect_stdout: "5"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2063: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
var a;
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2105: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -1138,7 +1324,7 @@ issue_2105: {
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
!void function() {
|
||||
(function() {
|
||||
var quux = function() {
|
||||
console.log("PASS");
|
||||
};
|
||||
@@ -1148,7 +1334,203 @@ issue_2105: {
|
||||
quux();
|
||||
}
|
||||
};
|
||||
}().prop();
|
||||
})().prop();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2136_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function(a, ...b) {
|
||||
console.log(b);
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function(a, ...b) {
|
||||
console.log(b);
|
||||
}();
|
||||
}
|
||||
expect_stdout: "[]"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2136_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
console.log(x);
|
||||
}
|
||||
!function(a, ...b) {
|
||||
f(b[0]);
|
||||
}(1, 2, 3);
|
||||
}
|
||||
expect: {
|
||||
function f(x) {
|
||||
console.log(x);
|
||||
}
|
||||
f([2,3][0]);
|
||||
}
|
||||
expect_stdout: "2"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2136_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(x) {
|
||||
console.log(x);
|
||||
}
|
||||
!function(a, ...b) {
|
||||
f(b[0]);
|
||||
}(1, 2, 3);
|
||||
}
|
||||
expect: {
|
||||
console.log(2);
|
||||
}
|
||||
expect_stdout: "2"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2163: {
|
||||
options = {
|
||||
pure_funcs: [ "pure" ],
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var c;
|
||||
/*@__PURE__*/f(...a);
|
||||
pure(b, ...c);
|
||||
}
|
||||
expect: {
|
||||
var c;
|
||||
a;
|
||||
b;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2226_1: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
var a = b;
|
||||
a += c;
|
||||
}
|
||||
function f2(a) {
|
||||
a <<= b;
|
||||
}
|
||||
function f3(a) {
|
||||
--a;
|
||||
}
|
||||
function f4() {
|
||||
var a = b;
|
||||
return a *= c;
|
||||
}
|
||||
function f5(a) {
|
||||
x(a /= b);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1() {
|
||||
b;
|
||||
c;
|
||||
}
|
||||
function f2(a) {
|
||||
b;
|
||||
}
|
||||
function f3(a) {
|
||||
0;
|
||||
}
|
||||
function f4() {
|
||||
var a = b;
|
||||
return a *= c;
|
||||
}
|
||||
function f5(a) {
|
||||
x(a /= b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2226_2: {
|
||||
options = {
|
||||
cascade: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a, b) {
|
||||
a += b;
|
||||
return a;
|
||||
}(1, 2));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a, b) {
|
||||
return a += b;
|
||||
}(1, 2));
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
|
||||
issue_2226_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a, b) {
|
||||
a += b;
|
||||
return a;
|
||||
}(1, 2));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a, b) {
|
||||
return a += 2;
|
||||
}(1));
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
|
||||
issue_2288: {
|
||||
options = {
|
||||
unused: true,
|
||||
}
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
function foo(o) {
|
||||
for (var j = o.a, i = 0; i < 0; i++);
|
||||
for (var i = 0; i < 0; i++);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(o) {
|
||||
o.a;
|
||||
for (i = 0; i < 0; i++);
|
||||
for (var i = 0; i < 0; i++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +224,100 @@ positive_zero: {
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
pow: {
|
||||
options = { evaluate: true }
|
||||
input: {
|
||||
var a = 5 ** 3;
|
||||
}
|
||||
expect: {
|
||||
var a = 125;
|
||||
}
|
||||
}
|
||||
|
||||
pow_sequence: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a = 2 ** 3 ** 2;
|
||||
}
|
||||
expect: {
|
||||
var a = 512;
|
||||
}
|
||||
}
|
||||
|
||||
pow_mixed: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a = 5 + 2 ** 3 + 5;
|
||||
var b = 5 * 3 ** 2;
|
||||
var c = 5 ** 3 * 2;
|
||||
var d = 5 ** +3;
|
||||
}
|
||||
expect: {
|
||||
var a = 18;
|
||||
var b = 45;
|
||||
var c = 250;
|
||||
var d = 125;
|
||||
}
|
||||
}
|
||||
|
||||
pow_with_right_side_evaluating_to_unary: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a = (4 - 7) ** foo;
|
||||
var b = ++bar ** 3;
|
||||
var c = --baz ** 2;
|
||||
}
|
||||
expect_exact: "var a=(-3)**foo;var b=++bar**3;var c=--baz**2;"
|
||||
}
|
||||
|
||||
pow_with_number_constants: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a = 5 ** NaN;
|
||||
/* NaN exponent results to NaN */
|
||||
var b = 42 ** +0;
|
||||
/* +0 exponent results to NaN */
|
||||
var c = 42 ** -0;
|
||||
/* -0 exponent results to NaN */
|
||||
var d = NaN ** 1;
|
||||
/* NaN with non-zero exponent is NaN */
|
||||
var e = 2 ** Infinity;
|
||||
/* abs(base) > 1 with Infinity as exponent is Infinity */
|
||||
var f = 2 ** -Infinity;
|
||||
/* abs(base) > 1 with -Infinity as exponent is +0 */
|
||||
var g = (-7) ** (0.5);
|
||||
var h = 2324334 ** 34343443;
|
||||
var i = (-2324334) ** 34343443;
|
||||
var j = 2 ** (-3);
|
||||
var k = 2.0 ** -3;
|
||||
var l = 2.0 ** (5 - 7);
|
||||
var m = 3 ** -10; // Result will be 0.000016935087808430286, which is too long
|
||||
}
|
||||
expect: {
|
||||
var a = NaN;
|
||||
var b = 1;
|
||||
var c = 1;
|
||||
var d = NaN;
|
||||
var e = 1/0;
|
||||
var f = 0;
|
||||
var g = NaN;
|
||||
var h = 1/0;
|
||||
var i = -1/0;
|
||||
var j = .125;
|
||||
var k = .125;
|
||||
var l = .25;
|
||||
var m = 3 ** -10;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_constant: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
@@ -250,22 +344,26 @@ unsafe_constant: {
|
||||
|
||||
unsafe_object: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
evaluate: 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
|
||||
);
|
||||
}
|
||||
@@ -274,22 +372,26 @@ unsafe_object: {
|
||||
|
||||
unsafe_object_nested: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
evaluate: 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
|
||||
);
|
||||
}
|
||||
@@ -298,21 +400,25 @@ unsafe_object_nested: {
|
||||
|
||||
unsafe_object_complex: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
evaluate: 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
|
||||
);
|
||||
@@ -322,22 +428,26 @@ unsafe_object_complex: {
|
||||
|
||||
unsafe_object_repeated: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
evaluate: 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
|
||||
);
|
||||
}
|
||||
@@ -370,10 +480,11 @@ unsafe_object_accessor: {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_function: {
|
||||
prop_function: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
@@ -386,9 +497,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
|
||||
@@ -614,10 +725,11 @@ unsafe_string_bad_index: {
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
unsafe_prototype_function: {
|
||||
prototype_function: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
unsafe : true
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = ({valueOf: 0}) < 1;
|
||||
@@ -636,8 +748,8 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -646,17 +758,16 @@ call_args: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
const a = 1;
|
||||
console.log(a);
|
||||
+function(a) {
|
||||
return a;
|
||||
}(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
const a = 1;
|
||||
console.log(1);
|
||||
+(1, 1);
|
||||
}
|
||||
@@ -669,17 +780,17 @@ call_args_drop_param: {
|
||||
inline: true,
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
const a = 1;
|
||||
console.log(a);
|
||||
+function(a) {
|
||||
return a;
|
||||
}(a, b);
|
||||
}
|
||||
expect: {
|
||||
const a = 1;
|
||||
console.log(1);
|
||||
+(b, 1);
|
||||
}
|
||||
@@ -1005,6 +1116,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());
|
||||
@@ -1012,11 +1124,15 @@ 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: {
|
||||
@@ -1029,17 +1145,22 @@ 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: {
|
||||
@@ -1069,3 +1190,140 @@ string_charCodeAt: {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
issue_2231_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(Object.getOwnPropertyNames(null));
|
||||
}
|
||||
expect: {
|
||||
console.log(Object.getOwnPropertyNames(null));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
self_comparison_1: {
|
||||
options = {
|
||||
evaluate: 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_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'"
|
||||
}
|
||||
|
||||
71
test/compress/expansions.js
Normal file
71
test/compress/expansions.js
Normal file
@@ -0,0 +1,71 @@
|
||||
|
||||
expand_arguments: {
|
||||
input: {
|
||||
func(a, ...rest);
|
||||
func(...all);
|
||||
}
|
||||
expect_exact: "func(a,...rest);func(...all);"
|
||||
}
|
||||
|
||||
expand_expression_arguments: {
|
||||
input: {
|
||||
f(...a.b);
|
||||
f(...a.b());
|
||||
f(...(a));
|
||||
f(...(a.b));
|
||||
f(...a[i]);
|
||||
}
|
||||
expect_exact: "f(...a.b);f(...a.b());f(...a);f(...a.b);f(...a[i]);"
|
||||
}
|
||||
|
||||
expand_parameters: {
|
||||
input: {
|
||||
(function (a, ...b){});
|
||||
(function (...args){});
|
||||
}
|
||||
expect_exact: "(function(a,...b){});(function(...args){});"
|
||||
}
|
||||
|
||||
avoid_spread_in_ternary: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
function print(...x) {
|
||||
console.log(...x);
|
||||
}
|
||||
var a = [1, 2], b = [3, 4];
|
||||
|
||||
if (Math)
|
||||
print(a);
|
||||
else
|
||||
print(b);
|
||||
|
||||
if (Math)
|
||||
print(...a);
|
||||
else
|
||||
print(b);
|
||||
|
||||
if (Math.no_such_property)
|
||||
print(a);
|
||||
else
|
||||
print(...b);
|
||||
}
|
||||
expect: {
|
||||
function print(...x) {
|
||||
console.log(...x);
|
||||
}
|
||||
var a = [ 1, 2 ], b = [ 3, 4 ];
|
||||
print(Math ? a : b);
|
||||
Math ? print(...a) : print(b);
|
||||
Math.no_such_property ? print(a) : print(...b);
|
||||
}
|
||||
expect_stdout: [
|
||||
"[ 1, 2 ]",
|
||||
"1 2",
|
||||
"3 4",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
252
test/compress/export.js
Normal file
252
test/compress/export.js
Normal file
@@ -0,0 +1,252 @@
|
||||
issue_2038_1: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
export var V = 1;
|
||||
export let L = 2;
|
||||
export const C = 3;
|
||||
}
|
||||
expect: {
|
||||
export var V = 1;
|
||||
export let L = 2;
|
||||
export const C = 3;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2038_2: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
let LET = 1;
|
||||
const CONST = 2;
|
||||
var VAR = 3;
|
||||
export { LET, CONST, VAR };
|
||||
}
|
||||
expect: {
|
||||
let t = 1;
|
||||
const e = 2;
|
||||
var o = 3;
|
||||
export { t as LET, e as CONST, o as VAR };
|
||||
}
|
||||
}
|
||||
|
||||
issue_2126: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
import { foo as bar, cat as dog } from "stuff";
|
||||
console.log(bar, dog);
|
||||
export { bar as qux };
|
||||
export { dog };
|
||||
}
|
||||
expect: {
|
||||
import { foo as o, cat as s } from "stuff";
|
||||
console.log(o, s);
|
||||
export { o as qux };
|
||||
export { s as dog };
|
||||
}
|
||||
}
|
||||
|
||||
beautify: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
export { A as B, C as D };
|
||||
}
|
||||
expect_exact: "export { A as B, C as D };"
|
||||
}
|
||||
|
||||
issue_2131: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function no() {
|
||||
console.log(42);
|
||||
}
|
||||
function go() {
|
||||
console.log(42);
|
||||
}
|
||||
var X = 1, Y = 2;
|
||||
export function main() {
|
||||
go(X);
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
function go() {
|
||||
console.log(42);
|
||||
}
|
||||
var X = 1;
|
||||
export function main() {
|
||||
go(X);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
issue_2129: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
export const { keys } = Object;
|
||||
}
|
||||
expect: {
|
||||
export const { keys } = Object;
|
||||
}
|
||||
}
|
||||
|
||||
async_func: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export async function Foo(x){};
|
||||
}
|
||||
expect: {
|
||||
export async function Foo(){};
|
||||
}
|
||||
}
|
||||
|
||||
issue_2134_1: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export function Foo(x){};
|
||||
Foo.prototype = {};
|
||||
}
|
||||
expect: {
|
||||
export function Foo(){};
|
||||
Foo.prototype = {};
|
||||
}
|
||||
}
|
||||
|
||||
issue_2134_2: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export async function Foo(x){};
|
||||
Foo.prototype = {};
|
||||
}
|
||||
expect: {
|
||||
export async function Foo(){};
|
||||
Foo.prototype = {};
|
||||
}
|
||||
}
|
||||
|
||||
redirection: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
let foo = 1, bar = 2;
|
||||
export { foo as delete };
|
||||
export { bar as default };
|
||||
export { foo as var } from "module.js";
|
||||
}
|
||||
expect: {
|
||||
let e = 1, o = 2;
|
||||
export { e as delete };
|
||||
export { o as default };
|
||||
export { foo as var } from "module.js";
|
||||
}
|
||||
}
|
||||
|
||||
keyword_invalid_1: {
|
||||
input: {
|
||||
export { default };
|
||||
}
|
||||
expect: {
|
||||
export { default };
|
||||
}
|
||||
}
|
||||
|
||||
keyword_invalid_2: {
|
||||
input: {
|
||||
export { default as Alias };
|
||||
}
|
||||
expect: {
|
||||
export { default as Alias };
|
||||
}
|
||||
}
|
||||
|
||||
keyword_invalid_3: {
|
||||
input: {
|
||||
export { default as default };
|
||||
}
|
||||
expect: {
|
||||
export { default as default };
|
||||
}
|
||||
}
|
||||
|
||||
keyword_valid_1: {
|
||||
input: {
|
||||
export { default } from "module.js";
|
||||
}
|
||||
expect: {
|
||||
export { default } from "module.js";
|
||||
}
|
||||
}
|
||||
|
||||
keyword_valid_2: {
|
||||
input: {
|
||||
export { default as Alias } from "module.js";
|
||||
}
|
||||
expect: {
|
||||
export { default as Alias } from "module.js";
|
||||
}
|
||||
}
|
||||
|
||||
keyword_valid_3: {
|
||||
input: {
|
||||
export { default as default } from "module.js";
|
||||
}
|
||||
expect: {
|
||||
export { default as default } from "module.js";
|
||||
}
|
||||
}
|
||||
|
||||
dynamic_import: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
import traditional from './traditional.js';
|
||||
function imp(x) {
|
||||
return import(x);
|
||||
}
|
||||
import("module_for_side_effects.js");
|
||||
let dynamic = import("some/module.js");
|
||||
dynamic.foo();
|
||||
}
|
||||
expect: {
|
||||
import o from "./traditional.js";
|
||||
function t(o) {
|
||||
return import(o);
|
||||
}
|
||||
import("module_for_side_effects.js");
|
||||
let r = import("some/module.js");
|
||||
r.foo();
|
||||
}
|
||||
}
|
||||
52
test/compress/expression.js
Normal file
52
test/compress/expression.js
Normal file
@@ -0,0 +1,52 @@
|
||||
pow: {
|
||||
input: {
|
||||
var a = 2 ** 7;
|
||||
var b = 3;
|
||||
b **= 2;
|
||||
}
|
||||
expect: {
|
||||
var a = 2 ** 7;
|
||||
var b = 3;
|
||||
b **= 2;
|
||||
}
|
||||
}
|
||||
|
||||
pow_with_number_constants: {
|
||||
input: {
|
||||
var a = 5 ** NaN;
|
||||
var b = 42 ** +0;
|
||||
var c = 42 ** -0;
|
||||
var d = NaN ** 1;
|
||||
var e = 2 ** Infinity;
|
||||
var f = 2 ** -Infinity;
|
||||
}
|
||||
expect: {
|
||||
var a = 5 ** NaN;
|
||||
var b = 42 ** +0;
|
||||
var c = 42 ** -0;
|
||||
var d = NaN ** 1;
|
||||
var e = 2 ** (1/0);
|
||||
var f = 2 ** (-1/0);
|
||||
}
|
||||
}
|
||||
|
||||
pow_with_parentheses: {
|
||||
input: {
|
||||
var g = (-7) ** (0.5);
|
||||
var h = 2324334 ** 34343443;
|
||||
var i = (-2324334) ** 34343443;
|
||||
var j = 2 ** (-3);
|
||||
var k = 2.0 ** -3;
|
||||
var l = 2.0 ** (5 - 7);
|
||||
}
|
||||
expect_exact: "var g=(-7)**.5;var h=2324334**34343443;var i=(-2324334)**34343443;var j=2**-3;var k=2**-3;var l=2**(5-7);"
|
||||
}
|
||||
|
||||
pow_with_unary_between_brackets: {
|
||||
input: {
|
||||
var a = (-(+5)) ** 3;
|
||||
}
|
||||
expect: {
|
||||
var a = (-+5)**3;
|
||||
}
|
||||
}
|
||||
@@ -151,13 +151,13 @@ issue_1841_2: {
|
||||
|
||||
function_returning_constant_literal: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
toplevel: true,
|
||||
evaluate: true,
|
||||
cascade: true,
|
||||
unused: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
properties: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function greeter() {
|
||||
@@ -189,25 +189,25 @@ hoist_funs: {
|
||||
console.log(6, typeof f, typeof g);
|
||||
}
|
||||
expect: {
|
||||
function f() {}
|
||||
function g() {}
|
||||
console.log(1, typeof f, typeof g);
|
||||
if (console.log(2, typeof f, typeof g))
|
||||
console.log(3, typeof f, typeof g);
|
||||
else {
|
||||
console.log(4, typeof f, typeof g);
|
||||
function f() {}
|
||||
console.log(5, typeof f, typeof g);
|
||||
}
|
||||
console.log(6, typeof f, typeof g);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1 'function' 'function'",
|
||||
"2 'function' 'function'",
|
||||
"1 'undefined' 'function'",
|
||||
"2 'undefined' 'function'",
|
||||
"4 'function' 'function'",
|
||||
"5 'function' 'function'",
|
||||
"6 'function' 'function'",
|
||||
]
|
||||
node_version: "<=4"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
hoist_funs_strict: {
|
||||
@@ -468,11 +468,9 @@ issue_2114_1: {
|
||||
}
|
||||
expect: {
|
||||
var c = 0;
|
||||
!function() {
|
||||
0;
|
||||
}((c += 1, c = 1 + c, function() {
|
||||
c = 1 + (c += 1), function() {
|
||||
var b = void (b && (b.b += (c += 1, 0)));
|
||||
}()));
|
||||
}();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "2"
|
||||
|
||||
@@ -37,6 +37,7 @@ object: {
|
||||
VALUE: 42,
|
||||
},
|
||||
},
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
@@ -120,7 +121,7 @@ mixed: {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var FOO = { BAR: 0 };
|
||||
const FOO = { BAR: 0 };
|
||||
console.log(FOO.BAR);
|
||||
console.log(++CONFIG.DEBUG);
|
||||
console.log(++CONFIG.VALUE);
|
||||
@@ -130,7 +131,7 @@ mixed: {
|
||||
console.log(CONFIG);
|
||||
}
|
||||
expect: {
|
||||
var FOO = { BAR: 0 };
|
||||
const FOO = { BAR: 0 };
|
||||
console.log("moo");
|
||||
console.log(++CONFIG.DEBUG);
|
||||
console.log(++CONFIG.VALUE);
|
||||
@@ -140,9 +141,9 @@ 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:128,22]',
|
||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:130,8]',
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
937
test/compress/harmony.js
Normal file
937
test/compress/harmony.js
Normal file
@@ -0,0 +1,937 @@
|
||||
arrow_function_parens: {
|
||||
input: {
|
||||
something && (() => {});
|
||||
}
|
||||
expect_exact: "something&&(()=>{});"
|
||||
}
|
||||
arrow_function_parens_2: {
|
||||
input: {
|
||||
(() => null)();
|
||||
}
|
||||
expect_exact: "(()=>null)();"
|
||||
}
|
||||
|
||||
typeof_arrow_functions: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = typeof (x => null);
|
||||
console.log(foo);
|
||||
}
|
||||
expect_exact: "var foo=\"function\";console.log(foo);"
|
||||
expect_stdout: "function"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
classes: {
|
||||
input: {
|
||||
class SomeClass {
|
||||
constructor() {
|
||||
};
|
||||
foo() {};
|
||||
};
|
||||
class NoSemi {
|
||||
constructor(...args) {
|
||||
}
|
||||
foo() {}
|
||||
};
|
||||
class ChildClass extends SomeClass {};
|
||||
var asExpression = class AsExpression {};
|
||||
var nameless = class {};
|
||||
}
|
||||
expect_exact: "class SomeClass{constructor(){}foo(){}}class NoSemi{constructor(...args){}foo(){}}class ChildClass extends SomeClass{}var asExpression=class AsExpression{};var nameless=class{};"
|
||||
}
|
||||
|
||||
class_statics: {
|
||||
input: {
|
||||
x = class {
|
||||
static staticMethod() {}
|
||||
static get foo() {}
|
||||
static set bar() {}
|
||||
static() { /* "static" can be a method name! */ }
|
||||
get() { /* "get" can be a method name! */ }
|
||||
set() { /* "set" can be a method name! */ }
|
||||
}
|
||||
}
|
||||
expect_exact: "x=class{static staticMethod(){}static get foo(){}static set bar(){}static(){}get(){}set(){}};"
|
||||
}
|
||||
|
||||
class_name_can_be_mangled: {
|
||||
mangle = { };
|
||||
input: {
|
||||
function x() {
|
||||
class Foo {
|
||||
}
|
||||
var class1 = Foo;
|
||||
var class2 = class Bar {};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
class a { }
|
||||
var s = a;
|
||||
var c = class a {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_name_can_be_preserved: {
|
||||
mangle = {
|
||||
keep_classnames: true
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
(class Baz { });
|
||||
class Foo {};
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
(class Baz { });
|
||||
class Foo {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
classes_can_have_generators: {
|
||||
input: {
|
||||
class Foo {
|
||||
*bar() {}
|
||||
static *baz() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
class Foo {
|
||||
*bar() {}
|
||||
static *baz() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
classes_can_have_computed_generators: {
|
||||
input: {
|
||||
class C4 {
|
||||
*['constructor']() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
class C4 {
|
||||
*['constructor']() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
classes_can_have_computed_static: {
|
||||
input: {
|
||||
class C4 {
|
||||
static ['constructor']() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
class C4 {
|
||||
static ['constructor']() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_methods_and_getters_with_keep_quoted_props_enabled: {
|
||||
beautify = {
|
||||
quote_style: 3,
|
||||
keep_quoted_props: true,
|
||||
}
|
||||
input: {
|
||||
class clss {
|
||||
a() {}
|
||||
"b"() {}
|
||||
get c() { return "c"}
|
||||
get "d"() { return "d"}
|
||||
set e(a) { doSomething(a); }
|
||||
set 'f'(a) { doSomething(b); }
|
||||
static g() {}
|
||||
static "h"() {}
|
||||
}
|
||||
}
|
||||
expect_exact: 'class clss{a(){}"b"(){}get c(){return"c"}get"d"(){return"d"}set e(a){doSomething(a)}set\'f\'(a){doSomething(b)}static g(){}static"h"(){}}'
|
||||
}
|
||||
|
||||
classes_with_expression_as_expand: {
|
||||
input: {
|
||||
class D extends (calls++, C) {}
|
||||
}
|
||||
expect_exact: "class D extends(calls++,C){}"
|
||||
}
|
||||
|
||||
new_target: {
|
||||
input: {
|
||||
new.target;
|
||||
new.target.name;
|
||||
}
|
||||
expect_exact: "new.target;new.target.name;"
|
||||
}
|
||||
|
||||
number_literals: {
|
||||
input: {
|
||||
0b1001;
|
||||
0B1001;
|
||||
0o11;
|
||||
0O11;
|
||||
}
|
||||
|
||||
expect: {
|
||||
9;
|
||||
9;
|
||||
9;
|
||||
9;
|
||||
}
|
||||
}
|
||||
|
||||
import_statement: {
|
||||
input: {
|
||||
import "mod-name";
|
||||
import Foo from "bar";
|
||||
import { Bar, Baz } from 'lel';
|
||||
import Bar, { Foo } from 'lel';
|
||||
import { Bar as kex, Baz as food } from 'lel';
|
||||
}
|
||||
expect_exact: 'import"mod-name";import Foo from"bar";import{Bar,Baz}from"lel";import Bar,{Foo}from"lel";import{Bar as kex,Baz as food}from"lel";'
|
||||
}
|
||||
|
||||
import_all_statement: {
|
||||
input: {
|
||||
import * from 'lel';
|
||||
import * as Lel from 'lel';
|
||||
}
|
||||
expect_exact: 'import*from"lel";import*as Lel from"lel";'
|
||||
}
|
||||
|
||||
export_statement: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
export default 1 + 2;
|
||||
export var a = 4;
|
||||
export let b = 6;
|
||||
export const c = 6;
|
||||
export function d() {};
|
||||
export class e {};
|
||||
}
|
||||
expect_exact: "export default 3;export var a=4;export let b=6;export const c=6;export function d(){};export class e{};"
|
||||
}
|
||||
|
||||
export_default_object_expression: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
export default {
|
||||
foo: 1 + 2,
|
||||
bar() { return 4; },
|
||||
get baz() { return this.foo; },
|
||||
};
|
||||
}
|
||||
expect_exact: "export default{foo:3,bar(){return 4},get baz(){return this.foo}};"
|
||||
}
|
||||
|
||||
export_default_array: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
export default [ 1 + 2, foo ];
|
||||
}
|
||||
expect_exact: "export default[3,foo];"
|
||||
}
|
||||
|
||||
export_default_anon_function: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
export default function(){
|
||||
console.log(1 + 2);
|
||||
}
|
||||
}
|
||||
expect_exact: "export default function(){console.log(3)};"
|
||||
}
|
||||
|
||||
export_default_anon_class: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
export default class {
|
||||
foo() { console.log(1 + 2); }
|
||||
}
|
||||
}
|
||||
expect_exact: "export default class{foo(){console.log(3)}};"
|
||||
}
|
||||
|
||||
export_module_statement: {
|
||||
input: {
|
||||
export * from "a.js";
|
||||
export {A} from "a.js";
|
||||
export {A, B} from "a.js";
|
||||
export {C};
|
||||
}
|
||||
expect_exact: 'export*from"a.js";export{A}from"a.js";export{A,B}from"a.js";export{C};'
|
||||
}
|
||||
|
||||
import_statement_mangling: {
|
||||
mangle = { toplevel: true };
|
||||
input: {
|
||||
import Foo from "foo";
|
||||
import Bar, {Food} from "lel";
|
||||
import {What as Whatever} from "lel";
|
||||
Foo();
|
||||
Bar();
|
||||
Food();
|
||||
Whatever();
|
||||
}
|
||||
expect: {
|
||||
import o from "foo";
|
||||
import m, {Food as r} from "lel";
|
||||
import {What as f} from "lel";
|
||||
o();
|
||||
m();
|
||||
r();
|
||||
f();
|
||||
}
|
||||
}
|
||||
|
||||
export_statement_mangling: {
|
||||
mangle = { };
|
||||
input: {
|
||||
export var foo = 6;
|
||||
export function bar() { }
|
||||
export class Baz { }
|
||||
bar(foo, Baz)
|
||||
}
|
||||
expect: {
|
||||
export var foo = 6;
|
||||
export function bar() { }
|
||||
export class Baz { }
|
||||
bar(foo, Baz)
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/mishoo/UglifyJS2/issues/1021
|
||||
regression_for_of_const: {
|
||||
input: {
|
||||
for (const x of y) {}
|
||||
for (const x in y) {}
|
||||
}
|
||||
expect: {
|
||||
for (const x of y);for (const x in y);
|
||||
}
|
||||
}
|
||||
|
||||
// Fabio: My patches accidentally caused a crash whenever
|
||||
// there's an extraneous set of parens around an object.
|
||||
regression_cannot_destructure: {
|
||||
input: {
|
||||
var x = ({ x : 3 });
|
||||
x(({ x: 3 }));
|
||||
}
|
||||
expect_exact: "var x={x:3};x({x:3});";
|
||||
}
|
||||
|
||||
regression_cannot_use_of: {
|
||||
input: {
|
||||
function of() {
|
||||
}
|
||||
var of = "is a valid variable name";
|
||||
of = { of: "is ok" };
|
||||
x.of;
|
||||
of: foo()
|
||||
}
|
||||
expect: {
|
||||
function of(){}
|
||||
var of="is a valid variable name";
|
||||
of={of:"is ok"};
|
||||
x.of;
|
||||
foo(); /* Label statement missing? No prob. */
|
||||
}
|
||||
}
|
||||
|
||||
fat_arrow_as_param: {
|
||||
input: {
|
||||
foo(x => x);
|
||||
foo(x => x, y => y);
|
||||
|
||||
foo(x => (x, x));
|
||||
foo(x => (x, x), y => (y, y));
|
||||
}
|
||||
expect_exact: "foo(x=>x);foo(x=>x,y=>y);foo(x=>(x,x));foo(x=>(x,x),y=>(y,y));"
|
||||
}
|
||||
|
||||
default_assign: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b = 3) {
|
||||
console.log(a);
|
||||
}
|
||||
|
||||
g = ([[] = 123]) => {};
|
||||
h = ([[x, y, z] = [4, 5, 6]] = []) => {};
|
||||
|
||||
function i([[x, y, z] = [4, 5, 6]] = []) {
|
||||
console.log(b);
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
console.log(a);
|
||||
}
|
||||
|
||||
g = ([[] = 123]) => {};
|
||||
h = ([[x, y, z] = [4, 5, 6]] = []) => {};
|
||||
|
||||
function i([[x, y, z] = [4, 5, 6]] = []) {
|
||||
console.log(b);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
expansion: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, ...b) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
console.log(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1613: {
|
||||
mangle = { toplevel: true };
|
||||
input: {
|
||||
const name = 1;
|
||||
const foo = {
|
||||
name
|
||||
};
|
||||
}
|
||||
expect_exact: "const n=1;const c={name:n};"
|
||||
}
|
||||
|
||||
format_methods: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
class A extends B {constructor(a){x()} static s(b,c){y()} run(d,e,f){z()}}
|
||||
}
|
||||
expect_exact: [
|
||||
"class A extends B {",
|
||||
" constructor(a) {",
|
||||
" x();",
|
||||
" }",
|
||||
" static s(b, c) {",
|
||||
" y();",
|
||||
" }",
|
||||
" run(d, e, f) {",
|
||||
" z();",
|
||||
" }",
|
||||
"}",
|
||||
]
|
||||
}
|
||||
|
||||
issue_1898: {
|
||||
options = {
|
||||
}
|
||||
mangle = {
|
||||
}
|
||||
input: {
|
||||
class Foo {
|
||||
bar() {
|
||||
for (const x of [ 6, 5 ]) {
|
||||
for (let y of [ 4, 3 ]) {
|
||||
for (var z of [ 2, 1 ]) {
|
||||
console.log(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
new Foo().bar();
|
||||
}
|
||||
expect: {
|
||||
class Foo {
|
||||
bar() {
|
||||
for (const f of [ 6, 5 ])
|
||||
for (let r of [ 4, 3 ])
|
||||
for (var o of [ 2, 1 ])
|
||||
console.log(f, r, o);
|
||||
}
|
||||
}
|
||||
new Foo().bar();
|
||||
}
|
||||
}
|
||||
|
||||
issue_1753: {
|
||||
mangle = { safari10: true };
|
||||
input: {
|
||||
class SomeClass {
|
||||
constructor(props) {
|
||||
let pickedSets = [];
|
||||
for (let i = 0; i < 6; i++) {
|
||||
pickedSets.push({
|
||||
mainDrawNumbers: [],
|
||||
extraDrawNumbers: []
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
class SomeClass {
|
||||
constructor(r) {
|
||||
let s = [];
|
||||
for (let a = 0; a < 6; a++)
|
||||
s.push({
|
||||
mainDrawNumbers: [],
|
||||
extraDrawNumbers: []
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1753_disable: {
|
||||
mangle = { safari10: false }
|
||||
input: {
|
||||
class SomeClass {
|
||||
constructor(props) {
|
||||
let pickedSets = [];
|
||||
for (let i = 0; i < 6; i++) {
|
||||
pickedSets.push({
|
||||
mainDrawNumbers: [],
|
||||
extraDrawNumbers: []
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
class SomeClass {
|
||||
constructor(r) {
|
||||
let s = [];
|
||||
for (let r = 0; r < 6; r++)
|
||||
s.push({
|
||||
mainDrawNumbers: [],
|
||||
extraDrawNumbers: []
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_extends: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
class foo extends bar {}
|
||||
class pro extends some.prop {}
|
||||
class arr extends stuff[1 - 1] {}
|
||||
class bin extends (a || b) {}
|
||||
class seq extends (a, b) {}
|
||||
class ter extends (a ? b : c) {}
|
||||
class uni extends (!0) {}
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(){class foo extends bar{}class pro extends some.prop{}class arr extends stuff[0]{}class bin extends(a||b){}class seq extends(a,b){}class ter extends(a?b:c){}class uni extends(!0){}}"
|
||||
}
|
||||
|
||||
class_extends_class: {
|
||||
options = {
|
||||
}
|
||||
input: {
|
||||
class anon extends class {} {}
|
||||
class named extends class base {} {}
|
||||
}
|
||||
expect_exact: "class anon extends class{}{}class named extends class base{}{}"
|
||||
}
|
||||
|
||||
class_extends_function: {
|
||||
options = {
|
||||
}
|
||||
input: {
|
||||
class anon extends function(){} {}
|
||||
class named extends function base(){} {}
|
||||
}
|
||||
expect_exact: "class anon extends function(){}{}class named extends function base(){}{}"
|
||||
}
|
||||
|
||||
class_extends_regex: {
|
||||
options = {
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
class rx1 extends (/rx/) {}
|
||||
// class rx2 extends /rx/ {} // FIXME - parse error
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(){class rx1 extends(/rx/){}}"
|
||||
}
|
||||
|
||||
issue_2028: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = {};
|
||||
(function(x) {
|
||||
x.X = function() {
|
||||
return X;
|
||||
};
|
||||
class X {
|
||||
static hello() {
|
||||
console.log("hello");
|
||||
}
|
||||
}
|
||||
}(a));
|
||||
a.X().hello();
|
||||
}
|
||||
expect: {
|
||||
var a = {};
|
||||
(function(x) {
|
||||
x.X = function() {
|
||||
return X;
|
||||
};
|
||||
class X {
|
||||
static hello() {
|
||||
console.log("hello");
|
||||
}
|
||||
}
|
||||
}(a));
|
||||
a.X().hello();
|
||||
}
|
||||
expect_stdout: "hello"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
class_expression_statement: {
|
||||
options = {
|
||||
toplevel: false,
|
||||
side_effects: false,
|
||||
unused: false,
|
||||
}
|
||||
input: {
|
||||
(class {});
|
||||
(class NamedClassExpr {});
|
||||
let expr = (class AnotherClassExpr {});
|
||||
class C {}
|
||||
}
|
||||
expect_exact: "(class{});(class NamedClassExpr{});let expr=class AnotherClassExpr{};class C{}"
|
||||
}
|
||||
|
||||
class_expression_statement_unused: {
|
||||
options = {
|
||||
toplevel: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(class {});
|
||||
(class NamedClassExpr {});
|
||||
let expr = (class AnotherClassExpr {});
|
||||
class C {}
|
||||
}
|
||||
expect_exact: "let expr=class{};class C{}"
|
||||
}
|
||||
|
||||
class_expression_statement_unused_toplevel: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(class {});
|
||||
(class NamedClassExpr {});
|
||||
let expr = (class AnotherClassExpr {});
|
||||
class C {}
|
||||
}
|
||||
expect_exact: ""
|
||||
}
|
||||
|
||||
export_default_function_decl: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
passes: 3,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
// do not drop "unused" exports
|
||||
export default function Foo() {};
|
||||
export function Far() {};
|
||||
}
|
||||
expect_exact: "export default function Foo(){};export function Far(){};"
|
||||
}
|
||||
|
||||
export_default_class_decl: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
passes: 3,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
// do not drop "unused" exports
|
||||
export default class Car {};
|
||||
export class Cab {};
|
||||
}
|
||||
expect_exact: "export default class Car{};export class Cab{};"
|
||||
}
|
||||
|
||||
object_rest_spread: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var { w: w1, ...V } = { w: 7, x: 1, y: 2 }; console.log(w1, V);
|
||||
let { w: w2, ...L } = { w: 8, x: 3, y: 4 }; console.log(w2, L);
|
||||
const { w: w3, ...C } = { w: 9, x: 5, y: 6 }; console.log(w3, C);
|
||||
|
||||
let b;
|
||||
({ b, ...V } = { a: 1, b: 2, c: 3 }); console.log(V);
|
||||
({ b, ...L } = { a: 4, b: 5, c: 6 }); console.log(L);
|
||||
|
||||
(function({ y, ...p }){ console.log(p); })({ x: 1, y: 2, z: 3 });
|
||||
(({ y, ...p }) => { console.log(p); })({ x: 4, y: 5, z: 6 });
|
||||
|
||||
const T = { a: 1, b: 2 }; console.log({ ...T, w: 0, ...{}, ...L, ...{K: 9} });
|
||||
}
|
||||
expect: {
|
||||
var { w: o, ...l } = { w: 7, x: 1, y: 2 }; console.log(o, l);
|
||||
let { w: c, ...n } = { w: 8, x: 3, y: 4 }; console.log(c, n);
|
||||
const { w: e, ...s } = { w: 9, x: 5, y: 6 }; console.log(e, s);
|
||||
|
||||
let g;
|
||||
({ b: g, ...l } = { a: 1, b: 2, c: 3 }); console.log(l);
|
||||
({ b: g, ...n } = { a: 4, b: 5, c: 6 }); console.log(n);
|
||||
|
||||
(function({ y: o, ...l }) { console.log(l); })({ x: 1, y: 2, z: 3 });
|
||||
(({ y: o, ...l }) => { console.log(l); })({ x: 4, y: 5, z: 6 });
|
||||
|
||||
const w = { a: 1, b: 2 }; console.log({ ...w, w: 0, ...{}, ...n, ...{ K: 9 } });
|
||||
}
|
||||
}
|
||||
|
||||
object_spread_unsafe: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var o1 = { x: 1, y: 2 };
|
||||
var o2 = { x: 3, z: 4 };
|
||||
var cloned = { ...o1 };
|
||||
var merged = { ...o1, ...o2 };
|
||||
console.log(cloned, merged);
|
||||
}
|
||||
expect: {
|
||||
var o = { x: 1, y: 2 }, l = { ...o }, x = { ...o, ...{ x: 3, z: 4 } };
|
||||
console.log(l, x);
|
||||
}
|
||||
}
|
||||
|
||||
array_spread_of_sequence: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = [1];
|
||||
console.log([...(a, a)]);
|
||||
console.log([...a, a]);
|
||||
console.log([...(a || a)]);
|
||||
console.log([...a || a]);
|
||||
}
|
||||
expect: {
|
||||
var o = [1];
|
||||
console.log([...(o, o)]);
|
||||
console.log([...o, o]);
|
||||
console.log([...o || o]);
|
||||
console.log([...o || o]);
|
||||
}
|
||||
expect_stdout: [
|
||||
"[ 1 ]",
|
||||
"[ 1, [ 1 ] ]",
|
||||
"[ 1 ]",
|
||||
"[ 1 ]",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
object_spread_of_sequence: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = {x: 1};
|
||||
console.log({ ...(a, a) });
|
||||
console.log({ ...a, a });
|
||||
console.log({ ...(a || a) });
|
||||
console.log({ ...a || a });
|
||||
}
|
||||
expect: {
|
||||
var o = { x: 1 };
|
||||
console.log({ ...(o, o) });
|
||||
console.log({ ...o, a: o });
|
||||
console.log({ ...o || o });
|
||||
console.log({ ...o || o });
|
||||
}
|
||||
}
|
||||
|
||||
// issue 2316
|
||||
class_name_can_be_preserved_with_reserved: {
|
||||
mangle = {
|
||||
reserved: [ "Foo" ],
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
class Foo {}
|
||||
Foo.bar;
|
||||
class Bar {}
|
||||
Bar.foo;
|
||||
}
|
||||
function y() {
|
||||
var Foo = class Foo {};
|
||||
Foo.bar;
|
||||
var Bar = class Bar {};
|
||||
Bar.bar;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
class Foo {}
|
||||
Foo.bar;
|
||||
class a {}
|
||||
a.foo;
|
||||
}
|
||||
function y() {
|
||||
var Foo = class Foo {};
|
||||
Foo.bar;
|
||||
var a = class a {};
|
||||
a.bar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2345: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log([...[3, 2, 1]].join("-"));
|
||||
var a = [3, 2, 1];
|
||||
console.log([...a].join("-"));
|
||||
}
|
||||
expect: {
|
||||
console.log([...[3, 2, 1]].join("-"));
|
||||
var a = [3, 2, 1];
|
||||
console.log([...a].join("-"));
|
||||
}
|
||||
expect_stdout: [
|
||||
"3-2-1",
|
||||
"3-2-1",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2349: {
|
||||
mangle = {}
|
||||
input: {
|
||||
function foo(boo, key) {
|
||||
const value = boo.get();
|
||||
return value.map(({[key]: bar}) => bar);
|
||||
}
|
||||
console.log(foo({
|
||||
get: () => [ {
|
||||
blah: 42
|
||||
} ]
|
||||
}, "blah"));
|
||||
}
|
||||
expect: {
|
||||
function foo(o, n) {
|
||||
const t = o.get();
|
||||
return t.map(({[n]: o}) => o);
|
||||
}
|
||||
console.log(foo({
|
||||
get: () => [ {
|
||||
blah: 42
|
||||
} ]
|
||||
}, "blah"));
|
||||
}
|
||||
expect_stdout: [
|
||||
"[ 42 ]",
|
||||
]
|
||||
node_version: ">=7"
|
||||
}
|
||||
|
||||
issue_2349b: {
|
||||
options = {
|
||||
arrows: true,
|
||||
collapse_vars: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
properties: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
side_effects: true,
|
||||
unsafe_arrows: true,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
function foo(boo, key) {
|
||||
const value = boo.get();
|
||||
return value.map(function({[key]: bar}){ return bar; });
|
||||
}
|
||||
console.log(foo({
|
||||
get: function() {
|
||||
return [ {
|
||||
blah: 42
|
||||
} ];
|
||||
}
|
||||
}, "blah"));
|
||||
}
|
||||
expect: {
|
||||
console.log([ {
|
||||
blah: 42
|
||||
} ].map(({["blah"]: l}) => l));
|
||||
}
|
||||
expect_stdout: [
|
||||
"[ 42 ]",
|
||||
]
|
||||
node_version: ">=7"
|
||||
}
|
||||
85
test/compress/hoist.js
Normal file
85
test/compress/hoist.js
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
hoist_vars: {
|
||||
options = {
|
||||
hoist_vars: true
|
||||
}
|
||||
input: {
|
||||
function a() {
|
||||
bar();
|
||||
var var1;
|
||||
var var2;
|
||||
}
|
||||
function b(anArg) {
|
||||
bar();
|
||||
var var1;
|
||||
var anArg;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
var var1, var2; // Vars go up and are joined
|
||||
bar();
|
||||
}
|
||||
function b(anArg) {
|
||||
var var1;
|
||||
bar();
|
||||
// But vars named like arguments go away!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hoist_funs: {
|
||||
options = {
|
||||
hoist_funs: true
|
||||
}
|
||||
input: {
|
||||
function a() {
|
||||
bar();
|
||||
function foo() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a() {
|
||||
function foo() {} // Funs go up
|
||||
bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hoist_no_destructurings: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
hoist_funs: true
|
||||
}
|
||||
input: {
|
||||
function a([anArg]) {
|
||||
bar();
|
||||
var var1;
|
||||
var anArg; // Because anArg is already declared, this goes away!
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function a([anArg]) {
|
||||
var var1;
|
||||
bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dont_hoist_var_destructurings: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
hoist_funs: true
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
// If foo is null or undefined, this should be an exception
|
||||
var {x,y} = foo;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
var {x,y} = foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
371
test/compress/hoist_props.js
Normal file
371
test/compress/hoist_props.js
Normal file
@@ -0,0 +1,371 @@
|
||||
issue_2377_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
hoist_props: 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,
|
||||
inline: true,
|
||||
hoist_props: true,
|
||||
passes: 2,
|
||||
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, function(x) {
|
||||
return x * x * x;
|
||||
}(3));
|
||||
}
|
||||
expect_stdout: "1 27"
|
||||
}
|
||||
|
||||
issue_2377_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
hoist_props: true,
|
||||
passes: 3,
|
||||
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, 27);
|
||||
}
|
||||
expect_stdout: "1 27"
|
||||
}
|
||||
|
||||
direct_access_1: {
|
||||
options = {
|
||||
hoist_props: 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_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_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_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_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_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
p: 1,
|
||||
0: function(x) {
|
||||
return x;
|
||||
},
|
||||
1: function(x) {
|
||||
return x + 1;
|
||||
}
|
||||
}, o__$0 = 2, o__$1 = 3;
|
||||
console.log(o.p === o.p, o[0](4), o[1](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_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
p: 1,
|
||||
0: function(x) {
|
||||
return x;
|
||||
},
|
||||
1: function(x) {
|
||||
return x + 1;
|
||||
}
|
||||
}, o__$0 = 2, o__$1 = 3;
|
||||
console.log(o.p === o.p, o[0](4), o[1](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_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_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_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"
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,3 +53,12 @@ html_comment_in_string_literal: {
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e"}';
|
||||
}
|
||||
|
||||
html_comment_after_multiline_comment: {
|
||||
input: {
|
||||
var foo; /*
|
||||
*/--> var bar;
|
||||
var foobar;
|
||||
}
|
||||
expect_exact: "var foo;var foobar;"
|
||||
}
|
||||
|
||||
@@ -326,3 +326,61 @@ issue_512: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1317: {
|
||||
options = {
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
!function(a) {
|
||||
if (a) return;
|
||||
let b = 1;
|
||||
function g() {
|
||||
return b;
|
||||
}
|
||||
console.log(g());
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
!function(a) {
|
||||
if (a) return;
|
||||
let b = 1;
|
||||
function g() {
|
||||
return b;
|
||||
}
|
||||
console.log(g());
|
||||
}();
|
||||
}
|
||||
expect_stdout: "1"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_1317_strict: {
|
||||
options = {
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
!function(a) {
|
||||
if (a) return;
|
||||
let b = 1;
|
||||
function g() {
|
||||
return b;
|
||||
}
|
||||
console.log(g());
|
||||
}();
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
!function(a) {
|
||||
if (a) return;
|
||||
let b = 1;
|
||||
function g() {
|
||||
return b;
|
||||
}
|
||||
console.log(g());
|
||||
}();
|
||||
}
|
||||
expect_stdout: "1"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
8
test/compress/issue-1001.js
Normal file
8
test/compress/issue-1001.js
Normal file
@@ -0,0 +1,8 @@
|
||||
parenthesis_strings_in_parenthesis: {
|
||||
input: {
|
||||
var foo = ('(');
|
||||
a(')');
|
||||
|
||||
}
|
||||
expect_exact: 'var foo="(";a(")");'
|
||||
}
|
||||
@@ -71,11 +71,13 @@ non_hoisted_function_after_return_2a: {
|
||||
"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: pass 0: last_count: Infinity, count: 37",
|
||||
"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: pass 1: last_count: 37, count: 18",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -109,11 +111,11 @@ 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:97,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:99,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:99,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:103,12]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -151,10 +153,10 @@ non_hoisted_function_after_return_strict: {
|
||||
}
|
||||
expect_stdout: "8 7"
|
||||
expect_warnings: [
|
||||
'WARN: Dropping unreachable code [test/compress/issue-1034.js:131,16]',
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:134,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:137,12]",
|
||||
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:138,21]"
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:133,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:136,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:139,12]",
|
||||
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:140,21]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -194,17 +196,19 @@ non_hoisted_function_after_return_2a_strict: {
|
||||
}
|
||||
expect_stdout: "5 6"
|
||||
expect_warnings: [
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:173,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:173,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:176,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:176,16]",
|
||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:173,20]",
|
||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:180,21]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:181,12]",
|
||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:176,20]",
|
||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:178,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:175,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:175,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,16]",
|
||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:175,20]",
|
||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:182,21]",
|
||||
"WARN: pass 0: last_count: Infinity, count: 48",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:180,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:180,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:183,12]",
|
||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:178,20]",
|
||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:180,16]",
|
||||
"WARN: pass 1: last_count: 48, count: 29",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -243,10 +247,10 @@ non_hoisted_function_after_return_2b_strict: {
|
||||
expect_stdout: "5 6"
|
||||
expect_warnings: [
|
||||
// duplicate warnings no longer emitted
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:225,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:225,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:227,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:227,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:229,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:229,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:231,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:231,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:235,12]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
const_declaration: {
|
||||
options = {
|
||||
evaluate: true
|
||||
};
|
||||
|
||||
input: {
|
||||
const goog = goog || {};
|
||||
}
|
||||
expect: {
|
||||
const goog = goog || {};
|
||||
}
|
||||
}
|
||||
|
||||
const_pragma: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
|
||||
30
test/compress/issue-1043.js
Normal file
30
test/compress/issue-1043.js
Normal file
@@ -0,0 +1,30 @@
|
||||
issue_1043: {
|
||||
options = {
|
||||
side_effects: true
|
||||
};
|
||||
|
||||
input: {
|
||||
function* range(start = 0, end = null, step = 1) {
|
||||
if (end == null) {
|
||||
end = start;
|
||||
start = 0;
|
||||
}
|
||||
|
||||
for (let i = start; i < end; i += step) {
|
||||
yield i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expect: {
|
||||
function* range(start = 0, end = null, step = 1) {
|
||||
if (null == end) {
|
||||
end = start;
|
||||
start = 0;
|
||||
}
|
||||
|
||||
for (let i = start; i < end; i += step)
|
||||
yield i;
|
||||
}
|
||||
}
|
||||
}
|
||||
9
test/compress/issue-1044.js
Normal file
9
test/compress/issue-1044.js
Normal file
@@ -0,0 +1,9 @@
|
||||
issue_1044: {
|
||||
options = { evaluate: true, conditionals: true };
|
||||
input: {
|
||||
const mixed = Base ? class extends Base {} : class {}
|
||||
}
|
||||
expect: {
|
||||
const mixed = Base ? class extends Base {} : class {}
|
||||
}
|
||||
}
|
||||
@@ -134,9 +134,8 @@ defun_hoist_funs: {
|
||||
expect: {
|
||||
function e() {
|
||||
function f() {}
|
||||
function g() {}
|
||||
function h() {}
|
||||
if (window);
|
||||
if (window) function g() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
76
test/compress/issue-1212.js
Normal file
76
test/compress/issue-1212.js
Normal file
@@ -0,0 +1,76 @@
|
||||
issue_1212_debug_false: {
|
||||
options = {
|
||||
global_defs : { DEBUG: false },
|
||||
sequences : true,
|
||||
properties : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
loops : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
keep_fargs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
side_effects : true,
|
||||
}
|
||||
input: {
|
||||
class foo {
|
||||
bar() {
|
||||
if (DEBUG)
|
||||
console.log("DEV");
|
||||
else
|
||||
console.log("PROD");
|
||||
}
|
||||
}
|
||||
new foo().bar();
|
||||
}
|
||||
expect: {
|
||||
class foo{
|
||||
bar() { console.log("PROD") }
|
||||
}
|
||||
(new foo).bar();
|
||||
}
|
||||
}
|
||||
|
||||
issue_1212_debug_true: {
|
||||
options = {
|
||||
global_defs : { DEBUG: true },
|
||||
sequences : true,
|
||||
properties : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
loops : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
keep_fargs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
side_effects : true,
|
||||
}
|
||||
input: {
|
||||
class foo {
|
||||
bar() {
|
||||
if (DEBUG)
|
||||
console.log("DEV");
|
||||
else
|
||||
console.log("PROD");
|
||||
}
|
||||
}
|
||||
new foo().bar();
|
||||
}
|
||||
expect: {
|
||||
class foo{
|
||||
bar() { console.log("DEV") }
|
||||
}
|
||||
(new foo).bar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,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();
|
||||
@@ -110,10 +117,12 @@ pure_function_calls_toplevel: {
|
||||
"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:107,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:108,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:100,45]",
|
||||
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:100,12]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -148,29 +157,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:137,61]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,23]",
|
||||
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:137,23]",
|
||||
"WARN: Boolean || always true [test/compress/issue-1261.js:138,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:138,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:138,23]",
|
||||
"WARN: Condition left of || always true [test/compress/issue-1261.js:139,8]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:139,8]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:140,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:140,23]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:140,23]",
|
||||
"WARN: Condition left of && always false [test/compress/issue-1261.js:141,8]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:141,8]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:142,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:142,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:142,23]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:143,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,31]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:143,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:145,24]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:145,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:146,31]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:146,8]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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.o = 1;
|
||||
x["a"] = 2 * x.o;
|
||||
console.log(x.o, x["a"]);
|
||||
x.x = 1;
|
||||
x["a"] = 2 * x.x;
|
||||
console.log(x.x, x["a"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1321_debug: {
|
||||
mangle_props = {
|
||||
keep_quoted: true,
|
||||
debug: ""
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: "",
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
@@ -30,16 +34,18 @@ issue_1321_debug: {
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.o = 1;
|
||||
x["_$foo$_"] = 2 * x.o;
|
||||
console.log(x.o, 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.o = 1;
|
||||
x["x"] = 2 * x.o;
|
||||
console.log(x.o, x["x"]);
|
||||
x.x = 1;
|
||||
x["o"] = 2 * x.x;
|
||||
console.log(x.x, x["o"]);
|
||||
}
|
||||
expect_stdout: 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: {
|
||||
|
||||
291
test/compress/issue-1466.js
Normal file
291
test/compress/issue-1466.js
Normal file
@@ -0,0 +1,291 @@
|
||||
same_variable_in_multiple_for_loop: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
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: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
let a = 100;
|
||||
console.log(i, a);
|
||||
for (let i = 0; i < 2; i++) {
|
||||
console.log(i, a);
|
||||
let c = 2;
|
||||
console.log(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (let o = 0; o < 3; o++) {
|
||||
let l = 100;
|
||||
console.log(o, l);
|
||||
for (let o = 0; o < 2; o++) {
|
||||
console.log(o, l);
|
||||
let e = 2;
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
same_variable_in_multiple_forOf: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
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: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let tmp of test) {
|
||||
console.log(tmp);
|
||||
let dd;
|
||||
dd = [ "e", "f", "g" ];
|
||||
for (let tmp of dd) {
|
||||
console.log(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let o of test) {
|
||||
console.log(o);
|
||||
let e;
|
||||
e = [ "e", "f", "g" ];
|
||||
for (let o of e)
|
||||
console.log(o);
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
same_variable_in_multiple_forIn: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
evaluate: true,
|
||||
booleans: true,
|
||||
loops: true,
|
||||
unused: false,
|
||||
keep_fargs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade: true,
|
||||
side_effects: true,
|
||||
collapse_vars: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let tmp in test) {
|
||||
console.log(tmp);
|
||||
let dd;
|
||||
dd = [ "e", "f", "g" ];
|
||||
for (let tmp in test) {
|
||||
console.log(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let e in test) {
|
||||
console.log(e);
|
||||
let t;
|
||||
t = [ "e", "f", "g" ];
|
||||
for (let e in test)
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
different_variable_in_multiple_for_loop: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
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: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
let a = 100;
|
||||
console.log(i, a);
|
||||
for (let j = 0; j < 2; j++) {
|
||||
console.log(j, a);
|
||||
let c = 2;
|
||||
console.log(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (let o = 0; o < 3; o++) {
|
||||
let l = 100;
|
||||
console.log(o, l);
|
||||
for (let o = 0; o < 2; o++) {
|
||||
console.log(o, l);
|
||||
let e = 2;
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
different_variable_in_multiple_forOf: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
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: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let tmp of test) {
|
||||
console.log(tmp);
|
||||
let dd;
|
||||
dd = [ "e", "f", "g" ];
|
||||
for (let t of dd) {
|
||||
console.log(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let o of test) {
|
||||
console.log(o);
|
||||
let e;
|
||||
e = [ "e", "f", "g" ];
|
||||
for (let o of e)
|
||||
console.log(o);
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
different_variable_in_multiple_forIn: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
evaluate: true,
|
||||
booleans: true,
|
||||
loops: true,
|
||||
unused: false,
|
||||
keep_fargs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade: true,
|
||||
side_effects: true,
|
||||
collapse_vars: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let tmp in test) {
|
||||
console.log(tmp);
|
||||
let dd;
|
||||
dd = [ "e", "f", "g" ];
|
||||
for (let t in test) {
|
||||
console.log(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let e in test) {
|
||||
console.log(e);
|
||||
let t;
|
||||
t = [ "e", "f", "g" ];
|
||||
for (let e in test)
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
more_variable_in_multiple_for: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
evaluate: true,
|
||||
booleans: true,
|
||||
loops: true,
|
||||
unused: false,
|
||||
keep_fargs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
cascade: true,
|
||||
side_effects: true,
|
||||
collapse_vars: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
for (let a = 9, i = 0; i < 20; i += a) {
|
||||
let b = a++ + i;
|
||||
console.log(a, b, i);
|
||||
for (let k = b, m = b*b, i = 0; i < 10; i++) {
|
||||
console.log(a, b, m, k, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (let o = 9, l = 0; l < 20; l += o) {
|
||||
let e = o++ + l;
|
||||
console.log(o, e, l);
|
||||
for (let l = e, t = e * e, c = 0; c < 10; c++)
|
||||
console.log(o, e, t, l, c);
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
@@ -85,3 +85,15 @@ unsafe_undefined: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
runtime_error: {
|
||||
input: {
|
||||
const a = 1;
|
||||
console.log(a++);
|
||||
}
|
||||
expect: {
|
||||
const a = 1;
|
||||
console.log(a++);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -103,137 +107,3 @@ numeric_literal: {
|
||||
"8 7 8",
|
||||
]
|
||||
}
|
||||
|
||||
identifier: {
|
||||
mangle_props = {}
|
||||
input: {
|
||||
var obj = {
|
||||
abstract: 1,
|
||||
boolean: 2,
|
||||
byte: 3,
|
||||
char: 4,
|
||||
class: 5,
|
||||
double: 6,
|
||||
enum: 7,
|
||||
export: 8,
|
||||
extends: 9,
|
||||
final: 10,
|
||||
float: 11,
|
||||
goto: 12,
|
||||
implements: 13,
|
||||
import: 14,
|
||||
int: 15,
|
||||
interface: 16,
|
||||
let: 17,
|
||||
long: 18,
|
||||
native: 19,
|
||||
package: 20,
|
||||
private: 21,
|
||||
protected: 22,
|
||||
public: 23,
|
||||
short: 24,
|
||||
static: 25,
|
||||
super: 26,
|
||||
synchronized: 27,
|
||||
this: 28,
|
||||
throws: 29,
|
||||
transient: 30,
|
||||
volatile: 31,
|
||||
yield: 32,
|
||||
false: 33,
|
||||
null: 34,
|
||||
true: 35,
|
||||
break: 36,
|
||||
case: 37,
|
||||
catch: 38,
|
||||
const: 39,
|
||||
continue: 40,
|
||||
debugger: 41,
|
||||
default: 42,
|
||||
delete: 43,
|
||||
do: 44,
|
||||
else: 45,
|
||||
finally: 46,
|
||||
for: 47,
|
||||
function: 48,
|
||||
if: 49,
|
||||
in: 50,
|
||||
instanceof: 51,
|
||||
new: 52,
|
||||
return: 53,
|
||||
switch: 54,
|
||||
throw: 55,
|
||||
try: 56,
|
||||
typeof: 57,
|
||||
var: 58,
|
||||
void: 59,
|
||||
while: 60,
|
||||
with: 61,
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var obj = {
|
||||
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,
|
||||
D: 30,
|
||||
F: 31,
|
||||
G: 32,
|
||||
false: 33,
|
||||
null: 34,
|
||||
true: 35,
|
||||
H: 36,
|
||||
I: 37,
|
||||
J: 38,
|
||||
K: 39,
|
||||
L: 40,
|
||||
M: 41,
|
||||
N: 42,
|
||||
O: 43,
|
||||
P: 44,
|
||||
Q: 45,
|
||||
R: 46,
|
||||
S: 47,
|
||||
T: 48,
|
||||
U: 49,
|
||||
V: 50,
|
||||
W: 51,
|
||||
X: 52,
|
||||
Y: 53,
|
||||
Z: 54,
|
||||
$: 55,
|
||||
_: 56,
|
||||
ee: 57,
|
||||
te: 58,
|
||||
ne: 59,
|
||||
ae: 60,
|
||||
ie: 61,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
281
test/compress/issue-2001.js
Normal file
281
test/compress/issue-2001.js
Normal file
@@ -0,0 +1,281 @@
|
||||
export_func_1: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export function f(){};
|
||||
}
|
||||
expect_exact: "export function f(){};"
|
||||
}
|
||||
|
||||
export_func_2: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
side_effects: false,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export function f(){}(1);
|
||||
}
|
||||
expect_exact: "export function f(){};1;"
|
||||
}
|
||||
|
||||
export_func_3: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export function f(){}(1);
|
||||
}
|
||||
expect_exact: "export function f(){};"
|
||||
}
|
||||
|
||||
export_default_func_1: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export default function f(){};
|
||||
}
|
||||
expect_exact: "export default function f(){};"
|
||||
}
|
||||
|
||||
export_default_func_2: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
side_effects: false,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export default function f(){}(1);
|
||||
}
|
||||
expect_exact: "export default function f(){};1;"
|
||||
}
|
||||
|
||||
export_default_func_3: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export default function f(){}(1);
|
||||
}
|
||||
expect_exact: "export default function f(){};"
|
||||
}
|
||||
|
||||
export_class_1: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export class C {};
|
||||
}
|
||||
expect_exact: "export class C{};"
|
||||
}
|
||||
|
||||
export_class_2: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
side_effects: false,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export class C {}(1);
|
||||
}
|
||||
expect_exact: "export class C{};1;"
|
||||
}
|
||||
|
||||
export_class_3: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export class C {}(1);
|
||||
}
|
||||
expect_exact: "export class C{};"
|
||||
}
|
||||
|
||||
export_default_class_1: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export default class C {};
|
||||
}
|
||||
expect_exact: "export default class C{};"
|
||||
}
|
||||
|
||||
export_default_class_2: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
side_effects: false,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export default class C {}(1);
|
||||
}
|
||||
expect_exact: "export default class C{};1;"
|
||||
}
|
||||
|
||||
export_default_class_3: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export default class C {}(1);
|
||||
}
|
||||
expect_exact: "export default class C{};"
|
||||
}
|
||||
|
||||
export_mangle_1: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
export function foo(one, two) {
|
||||
return one - two;
|
||||
};
|
||||
}
|
||||
expect_exact: "export function foo(o,n){return o-n};"
|
||||
}
|
||||
|
||||
export_mangle_2: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
export default function foo(one, two) {
|
||||
return one - two;
|
||||
};
|
||||
}
|
||||
expect_exact: "export default function foo(o,t){return o-t};"
|
||||
}
|
||||
|
||||
export_mangle_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
export class C {
|
||||
go(one, two) {
|
||||
var z = one;
|
||||
return one - two + z;
|
||||
}
|
||||
};
|
||||
}
|
||||
expect_exact: "export class C{go(r,e){return r-e+r}};"
|
||||
}
|
||||
|
||||
export_mangle_4: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
export default class C {
|
||||
go(one, two) {
|
||||
var z = one;
|
||||
return one - two + z;
|
||||
}
|
||||
};
|
||||
}
|
||||
expect_exact: "export default class C{go(e,r){return e-r+e}};"
|
||||
}
|
||||
|
||||
export_mangle_5: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
export default {
|
||||
prop: function(one, two) {
|
||||
return one - two;
|
||||
}
|
||||
};
|
||||
}
|
||||
expect_exact: "export default{prop:function(r,t){return r-t}};"
|
||||
}
|
||||
|
||||
export_mangle_6: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var baz = 2;
|
||||
export let foo = 1, bar = baz;
|
||||
}
|
||||
expect_exact: "var o=2;export let foo=1,bar=o;"
|
||||
}
|
||||
|
||||
export_toplevel_1: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(){}
|
||||
export function g(){};
|
||||
export default function h(){};
|
||||
}
|
||||
expect: {
|
||||
export function g(){};
|
||||
export default function h(){};
|
||||
}
|
||||
}
|
||||
|
||||
export_toplevel_2: {
|
||||
options = {
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
class A {}
|
||||
export class B {};
|
||||
export default class C {};
|
||||
}
|
||||
expect: {
|
||||
export class B {};
|
||||
export default class C {};
|
||||
}
|
||||
}
|
||||
|
||||
export_default_func_ref: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
export default function f(){};
|
||||
f();
|
||||
}
|
||||
expect_exact: "export default function f(){};f();"
|
||||
}
|
||||
57
test/compress/issue-203.js
Normal file
57
test/compress/issue-203.js
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
compress_new_function: {
|
||||
options = {
|
||||
unsafe: true,
|
||||
unsafe_Func: true,
|
||||
}
|
||||
input: {
|
||||
new Function("aa, bb", 'return aa;');
|
||||
}
|
||||
expect: {
|
||||
Function("n,r", "return n");
|
||||
}
|
||||
}
|
||||
|
||||
compress_new_function_with_destruct: {
|
||||
options = {
|
||||
unsafe: true,
|
||||
unsafe_Func: true,
|
||||
ecma: 6
|
||||
}
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
new Function("aa, [bb]", 'return aa;');
|
||||
new Function("aa, {bb}", 'return aa;');
|
||||
new Function("[[aa]], [{bb}]", 'return aa;');
|
||||
}
|
||||
expect: {
|
||||
Function("n,[r]", "return n");
|
||||
Function("n,{bb:b}", "return n");
|
||||
Function("[[n]],[{bb:b}]", "return n");
|
||||
}
|
||||
}
|
||||
|
||||
compress_new_function_with_destruct_arrows: {
|
||||
options = {
|
||||
arrows: true,
|
||||
unsafe_arrows: true,
|
||||
unsafe: true,
|
||||
unsafe_Func: true,
|
||||
ecma: 6,
|
||||
}
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
new Function("aa, [bb]", 'return aa;');
|
||||
new Function("aa, {bb}", 'return aa;');
|
||||
new Function("[[aa]], [{bb}]", 'return aa;');
|
||||
}
|
||||
expect: {
|
||||
Function("n,[a]", "return n");
|
||||
Function("b,{bb:n}", "return b");
|
||||
Function("[[b]],[{bb:n}]", "return b");
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ mixed: {
|
||||
}
|
||||
}
|
||||
input: {
|
||||
var ENV = 3;
|
||||
const ENV = 3;
|
||||
var FOO = 4;
|
||||
f(ENV * 10);
|
||||
--FOO;
|
||||
@@ -49,7 +49,7 @@ mixed: {
|
||||
x = DEBUG;
|
||||
}
|
||||
expect: {
|
||||
var ENV = 3;
|
||||
const ENV = 3;
|
||||
var FOO = 4;
|
||||
f(10);
|
||||
--FOO;
|
||||
@@ -60,7 +60,7 @@ mixed: {
|
||||
x = 0;
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,12]',
|
||||
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,14]',
|
||||
'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]',
|
||||
'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]',
|
||||
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]',
|
||||
|
||||
@@ -419,7 +419,7 @@ wrap_iife_in_return_call: {
|
||||
expect_exact: '(void console.log("test"))();'
|
||||
}
|
||||
|
||||
pure_annotation: {
|
||||
pure_annotation_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
side_effects: true,
|
||||
@@ -432,6 +432,20 @@ pure_annotation: {
|
||||
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 = {
|
||||
cascade: true,
|
||||
@@ -449,9 +463,7 @@ drop_fargs: {
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
!function() {
|
||||
a++;
|
||||
}(++a && a.var);
|
||||
++a && a.var, a++;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "3"
|
||||
@@ -474,9 +486,7 @@ keep_fargs: {
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
!function(a_1) {
|
||||
a++;
|
||||
}(++a && a.var);
|
||||
++a && a.var, a++;
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "3"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
dont_reuse_prop: {
|
||||
mangle_props = {
|
||||
regex: /asd/
|
||||
mangle = {
|
||||
properties: {
|
||||
regex: /asd/,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
"aaaaaaaaaabbbbb";
|
||||
@@ -20,8 +22,10 @@ dont_reuse_prop: {
|
||||
}
|
||||
|
||||
unmangleable_props_should_always_be_reserved: {
|
||||
mangle_props = {
|
||||
regex: /asd/
|
||||
mangle = {
|
||||
properties: {
|
||||
regex: /asd/,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
"aaaaaaaaaabbbbb";
|
||||
|
||||
9
test/compress/issue-926.js
Normal file
9
test/compress/issue-926.js
Normal file
@@ -0,0 +1,9 @@
|
||||
template_strings: {
|
||||
input: {
|
||||
foo(
|
||||
`<span>${contents}</span>`,
|
||||
`<a href="${url}">${text}</a>`
|
||||
);
|
||||
}
|
||||
expect_exact: "foo(`<span>${contents}</span>`,`<a href=\"${url}\">${text}</a>`);"
|
||||
}
|
||||
40
test/compress/join-vars.js
Normal file
40
test/compress/join-vars.js
Normal file
@@ -0,0 +1,40 @@
|
||||
only_vars: {
|
||||
options = { join_vars: true };
|
||||
input: {
|
||||
let netmaskBinary = '';
|
||||
for (let i = 0; i < netmaskBits; ++i) {
|
||||
netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
let netmaskBinary = '';
|
||||
for (let i = 0; i < netmaskBits; ++i) netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
|
||||
issue_1079_with_vars: {
|
||||
options = { join_vars: true };
|
||||
input: {
|
||||
var netmaskBinary = '';
|
||||
for (var i = 0; i < netmaskBits; ++i) {
|
||||
netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
for (var netmaskBinary = '', i = 0; i < netmaskBits; ++i) netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
|
||||
issue_1079_with_mixed: {
|
||||
options = { join_vars: true };
|
||||
input: {
|
||||
var netmaskBinary = '';
|
||||
for (let i = 0; i < netmaskBits; ++i) {
|
||||
netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var netmaskBinary = ''
|
||||
for (let i = 0; i < netmaskBits; ++i) netmaskBinary += '1';
|
||||
}
|
||||
}
|
||||
@@ -146,6 +146,50 @@ parse_do_while_without_semicolon: {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
keep_collapse_const_in_own_block_scope: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
loops: true
|
||||
}
|
||||
input: {
|
||||
var i=2;
|
||||
const c=5;
|
||||
while(i--)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var i=2;
|
||||
const c=5;
|
||||
for(;i--;)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
keep_collapse_const_in_own_block_scope_2: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
loops: true
|
||||
}
|
||||
input: {
|
||||
const c=5;
|
||||
var i=2; // Moves to loop, while it did not in previous test
|
||||
while(i--)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
const c=5;
|
||||
for(var i=2;i--;)
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
evaluate: {
|
||||
options = {
|
||||
loops: true,
|
||||
@@ -436,3 +480,17 @@ 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;);'
|
||||
}
|
||||
|
||||
@@ -82,3 +82,35 @@ new_with_unary_prefix: {
|
||||
}
|
||||
expect_exact: 'var bar=(+new Date).toString(32);';
|
||||
}
|
||||
|
||||
new_with_assignement_expression: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
new x(a = 5 * 2, b = [1, 2, 3], c = {a: "a", b: "b", cd: "c" + "d"});
|
||||
new y([a, b] = [3, 4]);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
new x(a = 10, b = [1, 2, 3], c = {a: "a", b: "b", cd: "cd"});
|
||||
new y([a, b] = [3, 4]);
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
814
test/compress/object.js
Normal file
814
test/compress/object.js
Normal file
@@ -0,0 +1,814 @@
|
||||
getter_setter: {
|
||||
input: {
|
||||
var get = "bar";
|
||||
var a = {
|
||||
get,
|
||||
set: "foo",
|
||||
get bar() {
|
||||
return this.get;
|
||||
},
|
||||
get 5() {
|
||||
return "five";
|
||||
},
|
||||
get 0xf55() {
|
||||
return "f five five";
|
||||
},
|
||||
get "five"() {
|
||||
return 5;
|
||||
},
|
||||
set one(value) {
|
||||
this._one = value;
|
||||
},
|
||||
set 9(value) {
|
||||
this._nine = value;
|
||||
},
|
||||
set 0b1010(value) {
|
||||
this._ten = value;
|
||||
},
|
||||
set "eleven"(value) {
|
||||
this._eleven = value;
|
||||
}
|
||||
};
|
||||
var b = {
|
||||
get() { return "gift"; },
|
||||
set: function(code) { return "Storing code " + code; }
|
||||
};
|
||||
var c = {
|
||||
["get"]: "foo",
|
||||
["set"]: "bar"
|
||||
};
|
||||
var d = {
|
||||
get: "foo",
|
||||
set: "bar"
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var get = "bar";
|
||||
var a = {
|
||||
get,
|
||||
set: "foo",
|
||||
get bar() {
|
||||
return this.get;
|
||||
},
|
||||
get 5() {
|
||||
return "five";
|
||||
},
|
||||
get 0xf55() {
|
||||
return "f five five";
|
||||
},
|
||||
get "five"() {
|
||||
return 5;
|
||||
},
|
||||
set one(value) {
|
||||
this._one = value;
|
||||
},
|
||||
set 9(value) {
|
||||
this._nine = value;
|
||||
},
|
||||
set 0b1010(value) {
|
||||
this._ten = value;
|
||||
},
|
||||
set "eleven"(value) {
|
||||
this._eleven = value;
|
||||
}
|
||||
};
|
||||
var b = {
|
||||
get() { return "gift"; },
|
||||
set: function(code) { return "Storing code " + code; }
|
||||
};
|
||||
var c = {
|
||||
["get"]: "foo",
|
||||
["set"]: "bar"
|
||||
};
|
||||
var d = {
|
||||
get: "foo",
|
||||
set: "bar"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getter_setter_mangler: {
|
||||
mangle = {}
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
function f(get,set) {
|
||||
return {
|
||||
get,
|
||||
set,
|
||||
get g(){},
|
||||
set s(n){},
|
||||
c,
|
||||
a:1,
|
||||
m(){}
|
||||
};
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(t,e){return{get:t,set:e,get g(){},set s(t){},c,a:1,m(){}}}"
|
||||
}
|
||||
|
||||
use_shorthand_opportunity: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
var foo = 123;
|
||||
var obj = {foo: foo};
|
||||
}
|
||||
expect_exact: "var foo=123;var obj={foo};"
|
||||
}
|
||||
|
||||
computed_property_names: {
|
||||
input: {
|
||||
obj({ ["x" + "x"]: 6 });
|
||||
}
|
||||
expect_exact: 'obj({["x"+"x"]:6});'
|
||||
}
|
||||
|
||||
convert_computed_props_to_regular_ones: {
|
||||
options = {
|
||||
booleans: true,
|
||||
computed_props: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
["hi"]: 0,
|
||||
["A" + 1]: 1,
|
||||
[/B/]: 2,
|
||||
[100 + 23]: 3,
|
||||
[1 + .5]: 4,
|
||||
[Math.PI]: 5,
|
||||
[undefined]: 6,
|
||||
[true]: 7,
|
||||
[false]: 8,
|
||||
[null]: 9,
|
||||
[Infinity]: 10,
|
||||
[NaN]: 11,
|
||||
};
|
||||
for (var k in o) {
|
||||
console.log(k, o[k]);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
hi: 0,
|
||||
A1: 1,
|
||||
[/B/]: 2,
|
||||
123: 3,
|
||||
1.5: 4,
|
||||
[Math.PI]: 5,
|
||||
|
||||
// leave these problematic cases as is
|
||||
[void 0]: 6,
|
||||
[!0]: 7,
|
||||
[!1]: 8,
|
||||
[null]: 9,
|
||||
[1 / 0]: 10,
|
||||
[NaN]: 11
|
||||
};
|
||||
for (var k in o) console.log(k, o[k]);
|
||||
}
|
||||
expect_stdout: [
|
||||
"123 3",
|
||||
"hi 0",
|
||||
"A1 1",
|
||||
"/B/ 2",
|
||||
"1.5 4",
|
||||
"3.141592653589793 5",
|
||||
"undefined 6",
|
||||
"true 7",
|
||||
"false 8",
|
||||
"null 9",
|
||||
"Infinity 10",
|
||||
"NaN 11",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
computed_property_names_evaluated_1: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
obj({
|
||||
[1 + 1]: 2,
|
||||
["x" + "x"]: 6
|
||||
});
|
||||
}
|
||||
expect_exact: 'obj({[2]:2,["xx"]:6});'
|
||||
}
|
||||
|
||||
computed_property_names_evaluated_2: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = something();
|
||||
|
||||
var obj = {
|
||||
[foo]() {
|
||||
return "blah";
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'var foo=something();var obj={[foo](){return"blah"}};'
|
||||
}
|
||||
|
||||
shorthand_properties: {
|
||||
mangle = true;
|
||||
input: {
|
||||
(function() {
|
||||
var prop = 1;
|
||||
const value = {prop};
|
||||
return value;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var n = 1;
|
||||
const r = {prop:n};
|
||||
return r;
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
concise_methods: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
x = {
|
||||
foo(a, b) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
y = {
|
||||
foo([{a}]) {
|
||||
return a;
|
||||
},
|
||||
bar(){}
|
||||
}
|
||||
}
|
||||
expect_exact: "x={foo(a,b){return x}};y={foo([{a}]){return a},bar(){}};"
|
||||
}
|
||||
|
||||
concise_methods_with_computed_property: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = {
|
||||
[Symbol.iterator]() {
|
||||
return { /* stuff */ }
|
||||
},
|
||||
[1 + 2]() {
|
||||
return 3;
|
||||
},
|
||||
["1" + "4"]() {
|
||||
return 14;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var foo = {
|
||||
[Symbol.iterator]() {
|
||||
return { /* stuff */ }
|
||||
},
|
||||
[3]() {
|
||||
return 3;
|
||||
},
|
||||
["14"]() {
|
||||
return 14;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
concise_methods_with_computed_property2: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = {
|
||||
[[1]](){
|
||||
return "success";
|
||||
}
|
||||
};
|
||||
doSomething(foo[[1]]());
|
||||
}
|
||||
expect_exact: 'var foo={[[1]](){return"success"}};doSomething(foo[[1]]());'
|
||||
}
|
||||
|
||||
concise_methods_with_various_property_names: {
|
||||
input: {
|
||||
var get = "bar";
|
||||
var a = {
|
||||
bar() {
|
||||
return this.get;
|
||||
},
|
||||
5() {
|
||||
return "five";
|
||||
},
|
||||
0xf55() {
|
||||
return "f five five";
|
||||
},
|
||||
"five"() {
|
||||
return 5;
|
||||
},
|
||||
0b1010(value) {
|
||||
this._ten = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var get = "bar";
|
||||
var a = {
|
||||
bar() {
|
||||
return this.get;
|
||||
},
|
||||
5() {
|
||||
return "five";
|
||||
},
|
||||
0xf55() {
|
||||
return "f five five";
|
||||
},
|
||||
"five"() {
|
||||
return 5;
|
||||
},
|
||||
0b1010(value) {
|
||||
this._ten = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
concise_methods_and_mangle_props: {
|
||||
mangle = {
|
||||
properties: {
|
||||
regex: /_/,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
obj = {
|
||||
_foo() { return 1; }
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
obj = {
|
||||
o() { return 1; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
concise_generators: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
x = {
|
||||
*foo(a, b) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
y = {
|
||||
*foo([{a}]) {
|
||||
yield a;
|
||||
},
|
||||
bar(){}
|
||||
}
|
||||
}
|
||||
expect_exact: "x={*foo(a,b){return x}};y={*foo([{a}]){yield a},bar(){}};"
|
||||
}
|
||||
|
||||
concise_methods_and_keyword_names: {
|
||||
input: {
|
||||
x = {
|
||||
catch() {},
|
||||
throw() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
x={catch(){},throw(){}};
|
||||
}
|
||||
}
|
||||
|
||||
getter_setter_with_computed_value: {
|
||||
input: {
|
||||
class C {
|
||||
get ['a']() {
|
||||
return 'A';
|
||||
}
|
||||
set ['a'](value) {
|
||||
do_something(a);
|
||||
}
|
||||
}
|
||||
var x = {
|
||||
get [a.b]() {
|
||||
return 42;
|
||||
}
|
||||
};
|
||||
class MyArray extends Array {
|
||||
get [Symbol.species]() {
|
||||
return Array;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'class C{get["a"](){return"A"}set["a"](value){do_something(a)}}var x={get[a.b](){return 42}};class MyArray extends Array{get[Symbol.species](){return Array}}'
|
||||
}
|
||||
|
||||
property_with_operator_value: {
|
||||
input: {
|
||||
var foo = {
|
||||
"*": 1,
|
||||
get "*"() {
|
||||
return 2;
|
||||
},
|
||||
*"*"() {
|
||||
return 3;
|
||||
},
|
||||
"%": 1,
|
||||
get "%"() {
|
||||
return 2;
|
||||
},
|
||||
*"%"() {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
class bar {
|
||||
get "*"() {
|
||||
return 1
|
||||
}
|
||||
*"*"() {
|
||||
return 2;
|
||||
}
|
||||
get "%"() {
|
||||
return 1
|
||||
}
|
||||
*"%"() {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'var foo={"*":1,get"*"(){return 2},*"*"(){return 3},"%":1,get"%"(){return 2},*"%"(){return 3}};class bar{get"*"(){return 1}*"*"(){return 2}get"%"(){return 1}*"%"(){return 2}}'
|
||||
}
|
||||
|
||||
property_with_unprintable: {
|
||||
input: {
|
||||
var foo = {
|
||||
"\x00\x01": "foo",
|
||||
get "\x00\x01"() {
|
||||
return "bar";
|
||||
},
|
||||
set "\x00\x01"(foo) {
|
||||
save(foo);
|
||||
},
|
||||
*"\x00\x01"() {
|
||||
return "foobar";
|
||||
}
|
||||
}
|
||||
class bar {
|
||||
get "\x00\x01"() {
|
||||
return "bar"
|
||||
}
|
||||
set "\x00\x01"(foo) {
|
||||
save(foo);
|
||||
}
|
||||
*"\x00\x01"() {
|
||||
return "foobar";
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'var foo={"\\0\x01":"foo",get"\\0\x01"(){return"bar"},set"\\0\x01"(foo){save(foo)},*"\\0\x01"(){return"foobar"}};class bar{get"\\0\x01"(){return"bar"}set"\\0\x01"(foo){save(foo)}*"\\0\x01"(){return"foobar"}}'
|
||||
}
|
||||
|
||||
property_with_unprintable_ascii_only: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
var foo = {
|
||||
"\x00\x01": "foo",
|
||||
get "\x00\x01"() {
|
||||
return "bar";
|
||||
},
|
||||
set "\x00\x01"(foo) {
|
||||
save(foo);
|
||||
},
|
||||
*"\x00\x01"() {
|
||||
return "foobar";
|
||||
}
|
||||
}
|
||||
class bar {
|
||||
get "\x00\x01"() {
|
||||
return "bar"
|
||||
}
|
||||
set "\x00\x01"(foo) {
|
||||
save(foo);
|
||||
}
|
||||
*"\x00\x01"() {
|
||||
return "foobar";
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'var foo={"\\0\\x01":"foo",get"\\0\\x01"(){return"bar"},set"\\0\\x01"(foo){save(foo)},*"\\0\\x01"(){return"foobar"}};class bar{get"\\0\\x01"(){return"bar"}set"\\0\\x01"(foo){save(foo)}*"\\0\\x01"(){return"foobar"}}'
|
||||
}
|
||||
|
||||
property_with_unprintable_ascii_only_static: {
|
||||
beautify = {
|
||||
ascii_only: true
|
||||
}
|
||||
input: {
|
||||
class foo {
|
||||
static get "\x02\x03"() {
|
||||
return "bar";
|
||||
}
|
||||
static set "\x04\x05"(foo) {
|
||||
save(foo);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: 'class foo{static get"\\x02\\x03"(){return"bar"}static set"\\x04\\x05"(foo){save(foo)}}'
|
||||
}
|
||||
|
||||
methods_and_getters_with_keep_quoted_props_enabled: {
|
||||
beautify = {
|
||||
quote_style: 3,
|
||||
keep_quoted_props: true,
|
||||
}
|
||||
input: {
|
||||
var obj = {
|
||||
a() {},
|
||||
"b"() {},
|
||||
get c() { return "c"},
|
||||
get "d"() { return "d"},
|
||||
set e(a) { doSomething(a); },
|
||||
set f(a) { doSomething(b); }
|
||||
}
|
||||
}
|
||||
expect_exact: 'var obj={a(){},"b"(){},get c(){return"c"},get"d"(){return"d"},set e(a){doSomething(a)},set f(a){doSomething(b)}};'
|
||||
}
|
||||
|
||||
allow_assignments_to_property_values: {
|
||||
input: {
|
||||
var foo = {123: foo = 123} = {foo: "456"};
|
||||
}
|
||||
expect: {
|
||||
var foo = {123: foo = 123} = {foo: "456"};
|
||||
}
|
||||
}
|
||||
|
||||
variable_as_computed_property: {
|
||||
input: {
|
||||
function getLine(header) {
|
||||
return {
|
||||
[header]: {}
|
||||
};
|
||||
}
|
||||
}
|
||||
expect_exact: "function getLine(header){return{[header]:{}}}"
|
||||
}
|
||||
|
||||
prop_func_to_concise_method: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
emit: function NamedFunctionExpression() {
|
||||
console.log("PASS");
|
||||
},
|
||||
run: function() {
|
||||
this.emit();
|
||||
}
|
||||
}).run();
|
||||
}
|
||||
expect: {
|
||||
({
|
||||
emit: function NamedFunctionExpression() {
|
||||
console.log("PASS");
|
||||
},
|
||||
run() {
|
||||
this.emit();
|
||||
}
|
||||
}).run();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
prop_arrow_to_concise_method: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
run: () => {
|
||||
console.log("PASS");
|
||||
}
|
||||
}).run();
|
||||
}
|
||||
expect: {
|
||||
({
|
||||
run() {
|
||||
console.log("PASS");
|
||||
}
|
||||
}).run();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
concise_method_to_prop_arrow: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
}
|
||||
input: {
|
||||
console.log(({ a: () => 1 }).a());
|
||||
console.log(({ a: () => { return 2; } }).a());
|
||||
console.log(({ a() { return 3; } }).a());
|
||||
console.log(({ a() { return this.b; }, b: 4 }).a());
|
||||
}
|
||||
expect: {
|
||||
console.log({ a: () => 1 }.a());
|
||||
console.log({ a: () => 2 }.a());
|
||||
console.log({ a: () => 3 }.a());
|
||||
console.log({ a() { return this.b; }, b: 4 }.a());
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
prop_func_to_async_concise_method: {
|
||||
options = {
|
||||
ecma: 8,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
run: async function() {
|
||||
console.log("PASS");
|
||||
}
|
||||
}).run();
|
||||
}
|
||||
expect: {
|
||||
({
|
||||
async run() {
|
||||
console.log("PASS");
|
||||
}
|
||||
}).run();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=8"
|
||||
}
|
||||
|
||||
prop_func_to_concise_method_various: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
null: function(x, y){ x(y); },
|
||||
123: function(x, y){ x(y); },
|
||||
"A B": function(x, y){ x(y); },
|
||||
p1: function(x, y){ x(y); },
|
||||
p2: function*(x, y){ yield x(y); },
|
||||
p3: async function(x, y){ await x(y); },
|
||||
[c1]: function(x, y){ x(y); },
|
||||
[c2]: function*(x, y){ yield x(y); },
|
||||
[c3]: async function(x, y){ await x(y); },
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
({
|
||||
null(x, y) { x(y); },
|
||||
123(x, y) { x(y); },
|
||||
"A B"(x, y) { x(y); },
|
||||
p1(x, y) { x(y); },
|
||||
*p2(x, y) { yield x(y); },
|
||||
async p3(x, y) { await x(y); },
|
||||
[c1](x, y) { x(y); },
|
||||
*[c2](x, y) { yield x(y); },
|
||||
async [c3](x, y) { await x(y); },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
prop_arrows_to_concise_method_various: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
null: (x, y) => { x(y); },
|
||||
123: (x, y) => { x(y); },
|
||||
"A B": (x, y) => { x(y); },
|
||||
p1: (x, y) => { x(y); },
|
||||
p3: async (x, y) => { await x(y); },
|
||||
[c1]: (x, y) => { x(y); },
|
||||
[c3]: async (x, y) => { await x(y); },
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
({
|
||||
null(x, y) { x(y); },
|
||||
123(x, y) { x(y); },
|
||||
"A B"(x, y) { x(y); },
|
||||
p1(x, y) { x(y); },
|
||||
async p3(x, y) { await x(y); },
|
||||
[c1](x, y) { x(y); },
|
||||
async [c3](x, y) { await x(y); },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
prop_arrow_with_this: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
function run(arg) {
|
||||
console.log(arg === this ? "global" : arg === foo ? "foo" : arg);
|
||||
}
|
||||
var foo = {
|
||||
func_no_this: function() { run(); },
|
||||
func_with_this: function() { run(this); },
|
||||
arrow_no_this: () => { run(); },
|
||||
arrow_with_this: () => { run(this); },
|
||||
};
|
||||
for (var key in foo) foo[key]();
|
||||
}
|
||||
expect: {
|
||||
function run(arg) {
|
||||
console.log(arg === this ? "global" : arg === foo ? "foo" : arg);
|
||||
}
|
||||
var foo = {
|
||||
func_no_this() { run(); },
|
||||
func_with_this() { run(this); },
|
||||
arrow_no_this() { run(); },
|
||||
arrow_with_this: () => { run(this); },
|
||||
};
|
||||
for (var key in foo) foo[key]();
|
||||
}
|
||||
expect_stdout: [
|
||||
"undefined",
|
||||
"foo",
|
||||
"undefined",
|
||||
"global",
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
prop_arrow_with_nested_this: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
function run(arg) {
|
||||
console.log(arg === this ? "global" : arg === foo ? "foo" : arg);
|
||||
}
|
||||
var foo = {
|
||||
func_func_this: function() { (function() { run(this); })(); },
|
||||
func_arrow_this: function() { (() => { run(this); })(); },
|
||||
arrow_func_this: () => { (function() { run(this); })(); },
|
||||
arrow_arrow_this: () => { (() => { run(this); })(); },
|
||||
};
|
||||
for (var key in foo) foo[key]();
|
||||
}
|
||||
expect: {
|
||||
function run(arg) {
|
||||
console.log(arg === this ? "global" : arg === foo ? "foo" : arg);
|
||||
}
|
||||
var foo = {
|
||||
func_func_this() { (function() { run(this); })(); },
|
||||
func_arrow_this() { (() => { run(this); })(); },
|
||||
arrow_func_this() { (function() { run(this); })(); },
|
||||
arrow_arrow_this: () => { (() => { run(this); })(); },
|
||||
};
|
||||
for (var key in foo) foo[key]();
|
||||
}
|
||||
expect_stdout: [
|
||||
"global",
|
||||
"foo",
|
||||
"global",
|
||||
"global",
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
186
test/compress/parameters.js
Normal file
186
test/compress/parameters.js
Normal file
@@ -0,0 +1,186 @@
|
||||
arrow_functions: {
|
||||
options = {
|
||||
arrows: true,
|
||||
}
|
||||
input: {
|
||||
(a) => b; // 1 args
|
||||
(a, b) => c; // n args
|
||||
() => b; // 0 args
|
||||
(a) => (b) => c; // func returns func returns func
|
||||
(a) => ((b) => c); // So these parens are dropped
|
||||
() => (b,c) => d; // func returns func returns func
|
||||
a=>{return b;}
|
||||
a => 'lel'; // Dropping the parens
|
||||
}
|
||||
expect_exact: "a=>b;(a,b)=>c;()=>b;a=>b=>c;a=>b=>c;()=>(b,c)=>d;a=>b;a=>\"lel\";"
|
||||
}
|
||||
|
||||
arrow_return: {
|
||||
options = {
|
||||
arrows: true,
|
||||
}
|
||||
input: {
|
||||
() => {};
|
||||
() => { return; };
|
||||
a => { return 1; }
|
||||
a => { return -b }
|
||||
a => { return b; var b; }
|
||||
(x, y) => { return x - y; }
|
||||
}
|
||||
expect_exact: "()=>{};()=>{};a=>1;a=>-b;a=>{return b;var b};(x,y)=>x-y;"
|
||||
}
|
||||
|
||||
regression_arrow_functions_and_hoist: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
hoist_funs: true
|
||||
}
|
||||
input: {
|
||||
(a) => b;
|
||||
}
|
||||
expect_exact: "a=>b;"
|
||||
}
|
||||
|
||||
regression_assign_arrow_functions: {
|
||||
input: {
|
||||
oninstall = e => false;
|
||||
oninstall = () => false;
|
||||
}
|
||||
expect: {
|
||||
oninstall=e=>false;
|
||||
oninstall=()=>false;
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_arguments_1: {
|
||||
input: {
|
||||
(function ( a ) { });
|
||||
(function ( [ a ] ) { });
|
||||
(function ( [ a, b ] ) { });
|
||||
(function ( [ [ a ] ] ) { });
|
||||
(function ( [ [ a, b ] ] ) { });
|
||||
(function ( [ a, [ b ] ] ) { });
|
||||
(function ( [ [ b ], a ] ) { });
|
||||
|
||||
(function ( { a } ) { });
|
||||
(function ( { a, b } ) { });
|
||||
|
||||
(function ( [ { a } ] ) { });
|
||||
(function ( [ { a, b } ] ) { });
|
||||
(function ( [ a, { b } ] ) { });
|
||||
(function ( [ { b }, a ] ) { });
|
||||
|
||||
( [ a ] ) => { };
|
||||
( [ a, b ] ) => { };
|
||||
|
||||
( { a } ) => { };
|
||||
( { a, b, c, d, e } ) => { };
|
||||
|
||||
( [ a ] ) => b;
|
||||
( [ a, b ] ) => c;
|
||||
|
||||
( { a } ) => b;
|
||||
( { a, b } ) => c;
|
||||
}
|
||||
expect: {
|
||||
(function(a){});
|
||||
(function([a]){});
|
||||
(function([a,b]){});
|
||||
(function([[a]]){});
|
||||
(function([[a,b]]){});
|
||||
(function([a,[b]]){});
|
||||
(function([[b],a]){});
|
||||
|
||||
(function({a}){});
|
||||
(function({a,b}){});
|
||||
|
||||
(function([{a}]){});
|
||||
(function([{a,b}]){});
|
||||
(function([a,{b}]){});
|
||||
(function([{b},a]){});
|
||||
|
||||
([a])=>{};
|
||||
([a,b])=>{};
|
||||
|
||||
({a})=>{};
|
||||
({a,b,c,d,e})=>{};
|
||||
|
||||
([a])=>b;
|
||||
([a,b])=>c;
|
||||
|
||||
({a})=>b;
|
||||
({a,b})=>c;
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_arguments_2: {
|
||||
input: {
|
||||
(function([]) {});
|
||||
(function({}) {});
|
||||
(function([,,,,,]) {});
|
||||
(function ([a, {b: c}]) {});
|
||||
(function ([...args]) {});
|
||||
(function ({x,}) {});
|
||||
class a { *method({ [thrower()]: x } = {}) {}};
|
||||
(function(a, b, c, d, [{e: [...f]}]){})(1, 2, 3, 4, [{e: [1, 2, 3]}]);
|
||||
}
|
||||
expect: {
|
||||
(function([]) {});
|
||||
(function({}) {});
|
||||
(function([,,,,,]) {});
|
||||
(function ([a, {b: c}]) {});
|
||||
(function ([...args]) {});
|
||||
(function ({x,}) {});
|
||||
class a { *method({ [thrower()]: x } = {}) {}};
|
||||
(function(a, b, c, d, [{e: [...f]}]){})(1, 2, 3, 4, [{e: [1, 2, 3]}]);
|
||||
}
|
||||
}
|
||||
|
||||
destructuring_arguments_3: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
function fn3({x: {y: {z: {} = 42}}}) {}
|
||||
const { a = (function () {}), b = (0, function() {}) } = {};
|
||||
let { c = (function () {}), d = (0, function() {}) } = {};
|
||||
var { e = (function () {}), f = (0, function() {}) } = {};
|
||||
}
|
||||
expect_exact: "function fn3({x:{y:{z:{}=42}}}){}const{a=function(){},b=(0,function(){})}={};let{c=function(){},d=(0,function(){})}={};var{e=function(){},f=(0,function(){})}={};"
|
||||
}
|
||||
|
||||
default_arguments: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
function x(a = 6) { }
|
||||
function x(a = (6 + 5)) { }
|
||||
function x({ foo } = {}, [ bar ] = [ 1 ]) { }
|
||||
}
|
||||
expect_exact: "function x(a=6){}function x(a=6+5){}function x({foo}={},[bar]=[1]){}"
|
||||
}
|
||||
|
||||
default_values_in_destructurings: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
function x({a=(4), b}) {}
|
||||
function x([b, c=(12)]) {}
|
||||
var { x = (6), y } = x;
|
||||
var [ x, y = (6) ] = x;
|
||||
}
|
||||
expect_exact: "function x({a=4,b}){}function x([b,c=12]){}var{x=6,y}=x;var[x,y=6]=x;"
|
||||
}
|
||||
|
||||
accept_duplicated_parameters_in_non_strict_without_spread_or_default_assignment: {
|
||||
input: {
|
||||
function a(b, b){}
|
||||
function b({c: test, c: test}){}
|
||||
}
|
||||
expect: {
|
||||
function a(b, b){}
|
||||
function b({c: test, c: test}){}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
keep_properties: {
|
||||
options = {
|
||||
properties: false
|
||||
};
|
||||
evaluate: true,
|
||||
properties: false,
|
||||
}
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
}
|
||||
@@ -12,9 +13,12 @@ keep_properties: {
|
||||
|
||||
dot_properties: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
}
|
||||
beautify = {
|
||||
ie8: true,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
a["if"] = "if";
|
||||
@@ -35,9 +39,12 @@ dot_properties: {
|
||||
|
||||
dot_properties_es5: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
}
|
||||
beautify = {
|
||||
ie8: false,
|
||||
};
|
||||
}
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
a["if"] = "if";
|
||||
@@ -57,8 +64,8 @@ dot_properties_es5: {
|
||||
sub_properties: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true
|
||||
};
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
a[0] = 0;
|
||||
a["0"] = 1;
|
||||
@@ -77,18 +84,18 @@ sub_properties: {
|
||||
a[3.14] = 3;
|
||||
a.if = 4;
|
||||
a["foo bar"] = 5;
|
||||
a[NaN] = 6;
|
||||
a[null] = 7;
|
||||
a.NaN = 6;
|
||||
a.null = 7;
|
||||
a[void 0] = 8;
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_array_length: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
unsafe: true,
|
||||
evaluate: true
|
||||
};
|
||||
}
|
||||
input: {
|
||||
a = [1, 2, 3].length;
|
||||
a = [1, 2, 3].join()["len" + "gth"];
|
||||
@@ -105,10 +112,10 @@ evaluate_array_length: {
|
||||
|
||||
evaluate_string_length: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
unsafe: true,
|
||||
evaluate: true
|
||||
};
|
||||
}
|
||||
input: {
|
||||
a = "foo".length;
|
||||
a = ("foo" + "bar")["len" + "gth"];
|
||||
@@ -124,9 +131,11 @@ evaluate_string_length: {
|
||||
}
|
||||
|
||||
mangle_properties: {
|
||||
mangle_props = {
|
||||
keep_quoted: false
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: false,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
@@ -135,20 +144,24 @@ mangle_properties: {
|
||||
a['run']({color: "blue", foo: "baz"});
|
||||
}
|
||||
expect: {
|
||||
a["o"] = "bar";
|
||||
a.a = "red";
|
||||
x = {r: 10};
|
||||
a.b(x.r, a.o);
|
||||
a['b']({a: "blue", o: "baz"});
|
||||
a["a"] = "bar";
|
||||
a.b = "red";
|
||||
x = {o: 10};
|
||||
a.r(x.o, a.a);
|
||||
a['r']({b: "blue", a: "baz"});
|
||||
}
|
||||
}
|
||||
|
||||
mangle_unquoted_properties: {
|
||||
options = {
|
||||
properties: false
|
||||
evaluate: true,
|
||||
properties: false,
|
||||
}
|
||||
mangle_props = {
|
||||
keep_quoted: true
|
||||
mangle = {
|
||||
properties: {
|
||||
builtins: true,
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
@@ -177,24 +190,26 @@ mangle_unquoted_properties: {
|
||||
function f1() {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
a.o = 2;
|
||||
x = {"bar": 10, f: 7};
|
||||
a.f = 9;
|
||||
a.r = 2;
|
||||
x = {"bar": 10, b: 7};
|
||||
a.b = 9;
|
||||
}
|
||||
function f2() {
|
||||
a.foo = "bar";
|
||||
a['color'] = "red";
|
||||
x = {bar: 10, f: 7};
|
||||
a.f = 9;
|
||||
a.o = 3;
|
||||
x = {bar: 10, b: 7};
|
||||
a.b = 9;
|
||||
a.r = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mangle_debug: {
|
||||
mangle_props = {
|
||||
debug: ""
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: "",
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
@@ -206,9 +221,11 @@ mangle_debug: {
|
||||
}
|
||||
|
||||
mangle_debug_true: {
|
||||
mangle_props = {
|
||||
debug: true
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
@@ -220,9 +237,11 @@ mangle_debug_true: {
|
||||
}
|
||||
|
||||
mangle_debug_suffix: {
|
||||
mangle_props = {
|
||||
debug: "XYZ"
|
||||
};
|
||||
mangle = {
|
||||
properties: {
|
||||
debug: "XYZ",
|
||||
},
|
||||
}
|
||||
input: {
|
||||
a.foo = "bar";
|
||||
x = { baz: "ban" };
|
||||
@@ -235,12 +254,16 @@ mangle_debug_suffix: {
|
||||
|
||||
mangle_debug_suffix_keep_quoted: {
|
||||
options = {
|
||||
properties: false
|
||||
evaluate: true,
|
||||
properties: false,
|
||||
}
|
||||
mangle_props = {
|
||||
keep_quoted: true,
|
||||
debug: "XYZ",
|
||||
reserved: []
|
||||
mangle = {
|
||||
properties: {
|
||||
builtins: true,
|
||||
debug: "XYZ",
|
||||
keep_quoted: true,
|
||||
reserved: [],
|
||||
},
|
||||
}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
@@ -657,3 +680,605 @@ accessor_this: {
|
||||
expect_exact: 'var a=1;var b={get this(){return a},set this(c){a=c}};console.log(b.this,b.this=2,b.this);'
|
||||
expect_stdout: "1 2 2"
|
||||
}
|
||||
|
||||
issue_2208_1: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
p: function() {
|
||||
return 42;
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
console.log(42);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_2208_2: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
a: 42,
|
||||
p: function() {
|
||||
return this.a;
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
console.log({
|
||||
a: 42,
|
||||
p: function() {
|
||||
return this.a;
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_2208_3: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
a = 42;
|
||||
console.log({
|
||||
p: function() {
|
||||
return function() {
|
||||
return this.a;
|
||||
}();
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
a = 42;
|
||||
console.log(function() {
|
||||
return this.a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_2208_4: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function foo() {}
|
||||
console.log({
|
||||
a: foo(),
|
||||
p: function() {
|
||||
return 42;
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
function foo() {}
|
||||
console.log((foo(), function() {
|
||||
return 42;
|
||||
})());
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_2208_5: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
p: "FAIL",
|
||||
p: function() {
|
||||
return 42;
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
console.log(42);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
}
|
||||
|
||||
issue_2208_6: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
p: () => 42
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
console.log(42);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_2208_7: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
unsafe_arrows: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
p() {
|
||||
return 42;
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
console.log(42);
|
||||
}
|
||||
expect_stdout: "42"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
issue_2208_8: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
unsafe_arrows: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
*p() {
|
||||
return x();
|
||||
}
|
||||
}.p());
|
||||
console.log({
|
||||
async p() {
|
||||
return await x();
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
console.log({
|
||||
*p() {
|
||||
return x();
|
||||
}
|
||||
}.p());
|
||||
console.log((async () => {
|
||||
return await x();
|
||||
})());
|
||||
}
|
||||
}
|
||||
|
||||
issue_2208_9: {
|
||||
options = {
|
||||
inline: true,
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
a = 42;
|
||||
console.log({
|
||||
p: () => {
|
||||
return function() {
|
||||
return this.a;
|
||||
}();
|
||||
}
|
||||
}.p());
|
||||
}
|
||||
expect: {
|
||||
a = 42;
|
||||
console.log(function() {
|
||||
return this.a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "42"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
methods_keep_quoted_true: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
class C { "Quoted"(){} Unquoted(){} }
|
||||
f1({ "Quoted"(){}, Unquoted(){}, "Prop": 3 });
|
||||
f2({ "Quoted": function(){} });
|
||||
f3({ "Quoted": ()=>{} });
|
||||
}
|
||||
expect_exact: "class C{Quoted(){}o(){}}f1({Quoted(){},o(){},Prop:3});f2({Quoted(){}});f3({Quoted(){}});"
|
||||
}
|
||||
|
||||
methods_keep_quoted_false: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: false,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
class C { "Quoted"(){} Unquoted(){} }
|
||||
f1({ "Quoted"(){}, Unquoted(){}, "Prop": 3 });
|
||||
f2({ "Quoted": function(){} });
|
||||
f3({ "Quoted": ()=>{} });
|
||||
}
|
||||
expect_exact: "class C{o(){}d(){}}f1({o(){},d(){},e:3});f2({o(){}});f3({o(){}});"
|
||||
}
|
||||
|
||||
methods_keep_quoted_from_dead_code: {
|
||||
options = {
|
||||
arrows: true,
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
ecma: 6,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
class C { Quoted(){} Unquoted(){} }
|
||||
f1({ Quoted(){}, Unquoted(){}, "Prop": 3 });
|
||||
f2({ Quoted: function(){} });
|
||||
f3({ Quoted: ()=>{} });
|
||||
0 && obj["Quoted"];
|
||||
}
|
||||
expect_exact: "class C{Quoted(){}o(){}}f1({Quoted(){},o(){},Prop:3});f2({Quoted(){}});f3({Quoted(){}});"
|
||||
}
|
||||
|
||||
issue_2256: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
keep_quoted: true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
({ "keep": 1 });
|
||||
g.keep = g.change;
|
||||
}
|
||||
expect: {
|
||||
g.keep = g.g;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2321: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: false,
|
||||
}
|
||||
input: {
|
||||
var f = {
|
||||
foo: function(){ console.log("foo") },
|
||||
bar() { console.log("bar") }
|
||||
};
|
||||
var foo = new f.foo();
|
||||
var bar = f.bar();
|
||||
}
|
||||
expect: {
|
||||
var f = {
|
||||
foo: function() {
|
||||
console.log("foo");
|
||||
},
|
||||
bar() {
|
||||
console.log("bar");
|
||||
}
|
||||
};
|
||||
var foo = new f.foo();
|
||||
var bar = f.bar();
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
unsafe_methods_regex: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: /^[A-Z1]/,
|
||||
}
|
||||
input: {
|
||||
var f = {
|
||||
123: function(){ console.log("123") },
|
||||
foo: function(){ console.log("foo") },
|
||||
bar() { console.log("bar") },
|
||||
Baz: function(){ console.log("baz") },
|
||||
BOO: function(){ console.log("boo") },
|
||||
null: function(){ console.log("null") },
|
||||
undefined: function(){ console.log("undefined") },
|
||||
};
|
||||
f[123]();
|
||||
new f.foo();
|
||||
f.bar();
|
||||
f.Baz();
|
||||
f.BOO();
|
||||
new f.null();
|
||||
new f.undefined();
|
||||
}
|
||||
expect: {
|
||||
var f = {
|
||||
123() { console.log("123") },
|
||||
foo: function(){ console.log("foo") },
|
||||
bar() { console.log("bar"); },
|
||||
Baz() { console.log("baz") },
|
||||
BOO() { console.log("boo") },
|
||||
null: function(){ console.log("null") },
|
||||
undefined: function(){ console.log("undefined") },
|
||||
};
|
||||
f[123]();
|
||||
new f.foo();
|
||||
f.bar();
|
||||
f.Baz();
|
||||
f.BOO();
|
||||
new f.null();
|
||||
new f.undefined();
|
||||
}
|
||||
expect_stdout: [
|
||||
"123",
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
"boo",
|
||||
"null",
|
||||
"undefined",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
lhs_prop_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
console.log(++{
|
||||
a: 1
|
||||
}.a);
|
||||
}
|
||||
expect: {
|
||||
console.log(++{
|
||||
a: 1
|
||||
}.a);
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
lhs_prop_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
properties: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
[1][0] = 42;
|
||||
(function(a) {
|
||||
a.b = "g";
|
||||
})("abc");
|
||||
(function(a) {
|
||||
a[2] = "g";
|
||||
})("def");
|
||||
(function(a) {
|
||||
a[""] = "g";
|
||||
})("ghi");
|
||||
}
|
||||
expect: {
|
||||
[1][0] = 42;
|
||||
"abc".b = "g";
|
||||
"def"[2] = "g";
|
||||
"ghi"[""] = "g";
|
||||
}
|
||||
}
|
||||
|
||||
literal_duplicate_key_side_effects: {
|
||||
options = {
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
a: "FAIL",
|
||||
a: console.log ? "PASS" : "FAIL"
|
||||
}.a);
|
||||
}
|
||||
expect: {
|
||||
console.log(console.log ? "PASS" : "FAIL");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
prop_side_effects_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
properties: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var C = 1;
|
||||
console.log(C);
|
||||
var obj = {
|
||||
bar: function() {
|
||||
return C + C;
|
||||
}
|
||||
};
|
||||
console.log(obj.bar());
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
var obj = {
|
||||
bar: function() {
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
console.log(obj.bar());
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
prop_side_effects_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
properties: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var C = 1;
|
||||
console.log(C);
|
||||
var obj = {
|
||||
"": function() {
|
||||
return C + C;
|
||||
}
|
||||
};
|
||||
console.log(obj[""]());
|
||||
}
|
||||
expect: {
|
||||
console.log(1);
|
||||
console.log(2);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
accessor_1: {
|
||||
options = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
a: "FAIL",
|
||||
get a() {
|
||||
return "PASS";
|
||||
}
|
||||
}.a);
|
||||
}
|
||||
expect: {
|
||||
console.log({
|
||||
a: "FAIL",
|
||||
get a() {
|
||||
return "PASS";
|
||||
}
|
||||
}.a);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
accessor_2: {
|
||||
options = {
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
get a() {
|
||||
return "PASS";
|
||||
},
|
||||
set a(v) {},
|
||||
a: "FAIL"
|
||||
}.a);
|
||||
}
|
||||
expect: {
|
||||
console.log({
|
||||
get a() {
|
||||
return "PASS";
|
||||
},
|
||||
set a(v) {},
|
||||
a: "FAIL"
|
||||
}.a);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
array_hole: {
|
||||
options = {
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(
|
||||
[ 1, 2, , 3][1],
|
||||
[ 1, 2, , 3][2],
|
||||
[ 1, 2, , 3][3]
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(2, void 0, 3);
|
||||
}
|
||||
expect_stdout: "2 undefined 3"
|
||||
}
|
||||
|
||||
computed_property: {
|
||||
options = {
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
a: "bar",
|
||||
[console.log("foo")]: 42,
|
||||
}.a);
|
||||
}
|
||||
expect: {
|
||||
console.log([
|
||||
"bar",
|
||||
console.log("foo")
|
||||
][0]);
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
@@ -385,3 +385,338 @@ set_mutable_2: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2265_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
({ ...{} }).p;
|
||||
({ ...g }).p;
|
||||
}
|
||||
expect: {
|
||||
({ ...g }).p;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2265_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = {
|
||||
get b() {
|
||||
throw 0;
|
||||
}
|
||||
};
|
||||
({...a}).b;
|
||||
}
|
||||
expect: {
|
||||
var a = {
|
||||
get b() {
|
||||
throw 0;
|
||||
}
|
||||
};
|
||||
({...a}).b;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2265_3: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = {
|
||||
set b() {
|
||||
throw 0;
|
||||
}
|
||||
};
|
||||
({...a}).b;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2265_4: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = { b: 1 };
|
||||
({...a}).b;
|
||||
}
|
||||
expect: {}
|
||||
}
|
||||
|
||||
issue_2313_1: {
|
||||
options = {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
return console.log(1), {
|
||||
y: function() {
|
||||
return console.log(2), {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++,
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_2: {
|
||||
options = {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
return console.log(1), {
|
||||
y: function() {
|
||||
return console.log(2), {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++,
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_4: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
pure_getters: true,
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
if (x().y().z) {
|
||||
console.log(3);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
console.log(1);
|
||||
return {
|
||||
y: function() {
|
||||
console.log(2);
|
||||
return {
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
x().y().z++;
|
||||
x().y().z && console.log(3);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2313_5: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
x().y++;
|
||||
x().y;
|
||||
}
|
||||
expect: {
|
||||
x().y++;
|
||||
x().y;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2313_6: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
x().y++;
|
||||
x().y;
|
||||
}
|
||||
expect: {
|
||||
x().y++;
|
||||
x();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2313_7: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
pure_getters: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 0;
|
||||
class foo {
|
||||
get c() {
|
||||
a++;
|
||||
return 42;
|
||||
}
|
||||
set c(c) {
|
||||
b++;
|
||||
}
|
||||
}
|
||||
class bar extends foo {
|
||||
d() {
|
||||
super.c++;
|
||||
if (super.c) console.log(a, b);
|
||||
}
|
||||
}
|
||||
new bar().d();
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b = 0;
|
||||
class foo {
|
||||
get c() {
|
||||
a++;
|
||||
return 42;
|
||||
}
|
||||
set c(c) {
|
||||
b++;
|
||||
}
|
||||
}
|
||||
class bar extends foo {
|
||||
d() {
|
||||
super.c++;
|
||||
super.c && console.log(a, b);
|
||||
}
|
||||
}
|
||||
new bar().d();
|
||||
}
|
||||
expect_stdout: "2 1"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -325,3 +325,69 @@ issue_2120_2: {
|
||||
}
|
||||
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(e) {
|
||||
try {
|
||||
throw "FAIL";
|
||||
} catch (t) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -176,6 +176,11 @@ for_sequences: {
|
||||
// 4
|
||||
x = (foo in bar);
|
||||
for (y = 5; false;);
|
||||
// 5
|
||||
x = function() {
|
||||
foo in bar;
|
||||
};
|
||||
for (y = 5; false;);
|
||||
}
|
||||
expect: {
|
||||
// 1
|
||||
@@ -188,6 +193,10 @@ for_sequences: {
|
||||
// 4
|
||||
x = (foo in bar);
|
||||
for (y = 5; false;);
|
||||
// 5
|
||||
for (x = function() {
|
||||
foo in bar;
|
||||
}, y = 5; false;);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,6 +720,30 @@ issue_27: {
|
||||
}
|
||||
}
|
||||
|
||||
reassign_const: {
|
||||
options = {
|
||||
cascade: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
const a = 1;
|
||||
a++;
|
||||
return a;
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
const a = 1;
|
||||
return a++, a;
|
||||
}
|
||||
console.log(f());
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_2062: {
|
||||
options = {
|
||||
booleans: true,
|
||||
@@ -730,3 +763,44 @@ issue_2062: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_2313: {
|
||||
options = {
|
||||
cascade: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 0;
|
||||
var foo = {
|
||||
get c() {
|
||||
a++;
|
||||
return 42;
|
||||
},
|
||||
set c(c) {
|
||||
b++;
|
||||
},
|
||||
d: function() {
|
||||
this.c++;
|
||||
if (this.c) console.log(a, b);
|
||||
}
|
||||
}
|
||||
foo.d();
|
||||
}
|
||||
expect: {
|
||||
var a = 0, b = 0;
|
||||
var foo = {
|
||||
get c() {
|
||||
return a++, 42;
|
||||
},
|
||||
set c(c) {
|
||||
b++;
|
||||
},
|
||||
d: function() {
|
||||
if (this.c++, this.c) console.log(a, b);
|
||||
}
|
||||
}
|
||||
foo.d();
|
||||
}
|
||||
expect_stdout: "2 1"
|
||||
}
|
||||
|
||||
9
test/compress/super.js
Normal file
9
test/compress/super.js
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
super_can_be_parsed: {
|
||||
input: {
|
||||
super(1,2);
|
||||
super.meth();
|
||||
}
|
||||
expect_exact: "super(1,2);super.meth();"
|
||||
}
|
||||
|
||||
460
test/compress/template-string.js
Normal file
460
test/compress/template-string.js
Normal file
@@ -0,0 +1,460 @@
|
||||
template_strings: {
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
``;
|
||||
`xx\`x`;
|
||||
`${ foo + 2 }`;
|
||||
` foo ${ bar + `baz ${ qux }` }`;
|
||||
}
|
||||
expect_exact: "``;`xx\\`x`;`${foo+2}`;` foo ${bar+`baz ${qux}`}`;";
|
||||
}
|
||||
|
||||
template_string_prefixes: {
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
String.raw`foo`;
|
||||
foo `bar`;
|
||||
}
|
||||
expect_exact: "String.raw`foo`;foo`bar`;";
|
||||
}
|
||||
|
||||
template_strings_ascii_only: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `foo
|
||||
bar
|
||||
ↂωↂ`;
|
||||
var bar = `\``;
|
||||
}
|
||||
expect_exact: "var foo=`foo\\n bar\\n \\u2182\\u03c9\\u2182`;var bar=`\\``;"
|
||||
}
|
||||
|
||||
template_strings_without_ascii_only: {
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `foo
|
||||
bar
|
||||
ↂωↂ`
|
||||
}
|
||||
expect_exact: "var foo=`foo\\n bar\\n ↂωↂ`;"
|
||||
}
|
||||
|
||||
template_string_with_constant_expression: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `${4 + 4} equals 4 + 4`;
|
||||
}
|
||||
expect: {
|
||||
var foo = "8 equals 4 + 4";
|
||||
}
|
||||
}
|
||||
|
||||
template_string_with_predefined_constants: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `This is ${undefined}`;
|
||||
var bar = `This is ${NaN}`;
|
||||
var baz = `This is ${null}`;
|
||||
var foofoo = `This is ${Infinity}`;
|
||||
var foobar = "This is ${1/0}";
|
||||
var foobaz = 'This is ${1/0}';
|
||||
var barfoo = "This is ${NaN}";
|
||||
var bazfoo = "This is ${null}";
|
||||
var bazbaz = `This is ${1/0}`;
|
||||
var barbar = `This is ${0/0}`;
|
||||
var barbar = "This is ${0/0}";
|
||||
var barber = 'This is ${0/0}';
|
||||
|
||||
var a = `${4**11}`; // 8 in template vs 7 chars - 4194304
|
||||
var b = `${4**12}`; // 8 in template vs 8 chars - 16777216
|
||||
var c = `${4**14}`; // 8 in template vs 9 chars - 268435456
|
||||
}
|
||||
expect: {
|
||||
var foo = "This is undefined";
|
||||
var bar = "This is NaN";
|
||||
var baz = "This is null";
|
||||
var foofoo = `This is ${1/0}`;
|
||||
var foobar = "This is ${1/0}";
|
||||
var foobaz = 'This is ${1/0}';
|
||||
var barfoo = "This is ${NaN}";
|
||||
var bazfoo = "This is ${null}";
|
||||
var bazbaz = `This is ${1/0}`;
|
||||
var barbar = "This is NaN";
|
||||
var barbar = "This is ${0/0}";
|
||||
var barber = 'This is ${0/0}';
|
||||
|
||||
var a = "4194304";
|
||||
var b = "16777216"; // Potential for further concatentation
|
||||
var c = `${4**14}`; // Not worth converting
|
||||
}
|
||||
}
|
||||
|
||||
template_string_evaluate_with_many_segments: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello ${guest()}, welcome to ${location()}${"."}`;
|
||||
var bar = `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
|
||||
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
|
||||
var buzz = `${1}${foobar()}${2}${foobar()}${3}${foobar()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `Hello ${guest()}, welcome to ${location()}.`;
|
||||
var bar = "1234567890";
|
||||
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
|
||||
var buzz = `1${foobar()}2${foobar()}3${foobar()}`;
|
||||
}
|
||||
}
|
||||
|
||||
template_string_with_many_segments: {
|
||||
beautify = {
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello ${guest()}, welcome to ${location()}${"."}`;
|
||||
var bar = `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
|
||||
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
|
||||
var buzz = `${1}${foobar()}${2}${foobar()}${3}${foobar()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `Hello ${guest()}, welcome to ${location()}${"."}`;
|
||||
var bar = `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
|
||||
var baz = `${foobar()}${foobar()}${foobar()}${foobar()}`;
|
||||
var buzz = `${1}${foobar()}${2}${foobar()}${3}${foobar()}`;
|
||||
}
|
||||
}
|
||||
|
||||
template_string_to_normal_string: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 0
|
||||
}
|
||||
input: {
|
||||
var foo = `This is ${undefined}`;
|
||||
var bar = "Decimals " + `${1}${2}${3}${4}${5}${6}${7}${8}${9}${0}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = "This is undefined";
|
||||
var bar = "Decimals 1234567890";
|
||||
}
|
||||
}
|
||||
|
||||
template_concattenating_string: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 3 // Yes, keep quotes
|
||||
}
|
||||
input: {
|
||||
var foo = "Have a nice " + `day. ${`day. ` + `day.`}`;
|
||||
var bar = "Have a nice " + `${day()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = "Have a nice day. day. day.";
|
||||
var bar = "Have a nice " + `${day()}`;
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_nested_templates: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
beautify = {
|
||||
quote_style: 0
|
||||
}
|
||||
input: {
|
||||
var baz = `${`${`${`foo`}`}`}`;
|
||||
}
|
||||
expect: {
|
||||
var baz = "foo";
|
||||
}
|
||||
}
|
||||
|
||||
enforce_double_quotes: {
|
||||
beautify = {
|
||||
quote_style: 1
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${'world'}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${"world"}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
}
|
||||
|
||||
enforce_single_quotes: {
|
||||
beautify = {
|
||||
quote_style: 2
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${"world"}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${'world'}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
}
|
||||
|
||||
enforce_double_quotes_and_evaluate: {
|
||||
beautify = {
|
||||
quote_style: 1
|
||||
}
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${'world'}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = "Hello world";
|
||||
var bar = "Hello world";
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
}
|
||||
|
||||
enforce_single_quotes_and_evaluate: {
|
||||
beautify = {
|
||||
quote_style: 2
|
||||
}
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = `Hello world`;
|
||||
var bar = `Hello ${"world"}`;
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
expect: {
|
||||
var foo = "Hello world";
|
||||
var bar = "Hello world";
|
||||
var baz = `Hello ${world()}`;
|
||||
}
|
||||
}
|
||||
|
||||
respect_inline_script: {
|
||||
beautify = {
|
||||
inline_script: true,
|
||||
quote_style: 3
|
||||
}
|
||||
input: {
|
||||
var foo = `</script>${content}`;
|
||||
var bar = `<!--`;
|
||||
var baz = `-->`;
|
||||
}
|
||||
expect_exact: "var foo=`<\\/script>${content}`;var bar=`\\x3c!--`;var baz=`--\\x3e`;";
|
||||
}
|
||||
|
||||
do_not_optimize_tagged_template_1: {
|
||||
beautify = {
|
||||
quote_style: 0
|
||||
}
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = tag`Shall not be optimized. ${"But " + "this " + "is " + "fine."}`;
|
||||
var bar = tag`Don't even mind changing my quotes!`;
|
||||
}
|
||||
expect_exact:
|
||||
'var foo=tag`Shall not be optimized. ${"But this is fine."}`;var bar=tag`Don\'t even mind changing my quotes!`;';
|
||||
}
|
||||
|
||||
do_not_optimize_tagged_template_2: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = tag`test` + " something out";
|
||||
}
|
||||
expect_exact: 'var foo=tag`test`+" something out";';
|
||||
}
|
||||
|
||||
keep_raw_content_in_tagged_template: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
var foo = tag`\u0020\u{20}\u{00020}\x20\40\040 `;
|
||||
}
|
||||
expect_exact: "var foo=tag`\\u0020\\u{20}\\u{00020}\\x20\\40\\040 `;";
|
||||
}
|
||||
|
||||
allow_chained_templates: {
|
||||
input: {
|
||||
var foo = tag`a``b``c``d`;
|
||||
}
|
||||
expect: {
|
||||
var foo = tag`a``b``c``d`;
|
||||
}
|
||||
}
|
||||
|
||||
check_escaped_chars: {
|
||||
input: {
|
||||
var foo = `\u0020\u{20}\u{00020}\x20\40\040 `;
|
||||
}
|
||||
expect_exact: "var foo=` `;";
|
||||
}
|
||||
|
||||
escape_dollar_curly: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
console.log(`\$\{ beep \}`)
|
||||
console.log(`${1-0}\${2-0}$\{3-0}${4-0}`)
|
||||
console.log(`$${""}{not an expression}`)
|
||||
}
|
||||
expect_exact: 'console.log("${ beep }");console.log("1${2-0}${3-0}4");console.log("${not an expression}");'
|
||||
}
|
||||
|
||||
template_starting_with_newline: {
|
||||
options = {
|
||||
dead_code: true
|
||||
}
|
||||
input: {
|
||||
function foo(e) {
|
||||
return `
|
||||
this is a template string!`;
|
||||
};
|
||||
}
|
||||
expect_exact: "function foo(e){return`\\nthis is a template string!`}"
|
||||
}
|
||||
|
||||
template_with_newline: {
|
||||
options = {
|
||||
dead_code: true
|
||||
}
|
||||
input: {
|
||||
function foo(e) {
|
||||
return `yep,
|
||||
this is a template string!`;
|
||||
};
|
||||
}
|
||||
expect_exact: "function foo(e){return`yep,\\nthis is a template string!`}"
|
||||
}
|
||||
|
||||
template_ending_with_newline: {
|
||||
options = {
|
||||
dead_code: true
|
||||
}
|
||||
input: {
|
||||
function foo(e) {
|
||||
return `this is a template string!
|
||||
`;
|
||||
};
|
||||
}
|
||||
expect_exact: "function foo(e){return`this is a template string!\\n`}"
|
||||
}
|
||||
|
||||
issue_1856: {
|
||||
beautify = {
|
||||
ascii_only: false,
|
||||
}
|
||||
input: {
|
||||
console.log(`\\n\\r\\u2028\\u2029\n\r\u2028\u2029`);
|
||||
}
|
||||
expect_exact: "console.log(`\\\\n\\\\r\\\\u2028\\\\u2029\\n\\r\\u2028\\u2029`);"
|
||||
}
|
||||
|
||||
issue_1856_ascii_only: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
console.log(`\\n\\r\\u2028\\u2029\n\r\u2028\u2029`);
|
||||
}
|
||||
expect_exact: "console.log(`\\\\n\\\\r\\\\u2028\\\\u2029\\n\\r\\u2028\\u2029`);"
|
||||
}
|
||||
|
||||
side_effects: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
`t1`;
|
||||
tag`t2`;
|
||||
`t${3}`;
|
||||
tag`t${4}`;
|
||||
console.log(`
|
||||
t${5}`);
|
||||
function f(a) {
|
||||
`t6${a}`;
|
||||
a = `t7${a}` & a;
|
||||
a = `t8${b}` | a;
|
||||
a = f`t9${a}` ^ a;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
tag`t2`;
|
||||
tag`t${4}`;
|
||||
console.log("\nt5");
|
||||
function f(a) {
|
||||
a &= `t7${a}`;
|
||||
a = `t8${b}` | a;
|
||||
a = f`t9${a}` ^ a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
simple_string: {
|
||||
options = {
|
||||
computed_props: true,
|
||||
evaluate: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
console.log({[`foo`]: 1}[`foo`], `hi` == "hi", `world`);
|
||||
}
|
||||
expect: {
|
||||
console.log([ 1 ][0], true, "world");
|
||||
}
|
||||
expect_stdout: "1 true 'world'"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
semicolons: {
|
||||
beautify = {
|
||||
semicolons: false,
|
||||
}
|
||||
input: {
|
||||
foo;
|
||||
`bar`;
|
||||
}
|
||||
expect_exact: "foo;`bar`\n"
|
||||
}
|
||||
12
test/compress/try-catch.js
Normal file
12
test/compress/try-catch.js
Normal file
@@ -0,0 +1,12 @@
|
||||
catch_destructuring_with_sequence: {
|
||||
beautify = {
|
||||
ecma: 6
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
throw {};
|
||||
} catch ({xCover = (0, function() {})} ) {
|
||||
}
|
||||
}
|
||||
expect_exact: "try{throw{}}catch({xCover=(0,function(){})}){}"
|
||||
}
|
||||
@@ -15,3 +15,107 @@ unicode_parse_variables: {
|
||||
var l০ = 3;
|
||||
}
|
||||
}
|
||||
|
||||
unicode_escaped_identifier: {
|
||||
beautify = {ecma: 6}
|
||||
input: {
|
||||
var \u{61} = "foo";
|
||||
var \u{10000} = "bar";
|
||||
}
|
||||
expect_exact: 'var a="foo";var \u{10000}="bar";';
|
||||
}
|
||||
|
||||
unicode_identifier_ascii_only: {
|
||||
beautify = {ascii_only: true, ecma: 6}
|
||||
input: {
|
||||
var \u{0061} = "hi";
|
||||
var bar = "h\u{0065}llo";
|
||||
var \u{10000} = "testing \u{101111}";
|
||||
}
|
||||
expect_exact: 'var a="hi";var bar="hello";var \\u{10000}="testing \\u{101111}";'
|
||||
}
|
||||
|
||||
unicode_string_literals: {
|
||||
beautify = {ascii_only: true, ecma: 6}
|
||||
input: {
|
||||
var a = "6 length unicode character: \u{101111}";
|
||||
}
|
||||
expect_exact: 'var a="6 length unicode character: \\u{101111}";'
|
||||
}
|
||||
|
||||
check_escape_style: {
|
||||
beautify = {ascii_only: true, ecma: 6}
|
||||
input: {
|
||||
var a = "\x01";
|
||||
var \ua0081 = "\x10"; // \u0081 only in ID_Continue
|
||||
var \u0100 = "\u0100";
|
||||
var \u1000 = "\u1000";
|
||||
var \u{10000} = "\u{10000}";
|
||||
var \u{2f800} = "\u{100000}";
|
||||
}
|
||||
expect_exact: 'var a="\\x01";var \\ua0081="\\x10";var \\u0100="\\u0100";var \\u1000="\\u1000";var \\u{10000}="\\u{10000}";var \\u{2f800}="\\u{100000}";'
|
||||
}
|
||||
|
||||
ID_continue_with_surrogate_pair: {
|
||||
beautify = {ascii_only: true, ecma: 6}
|
||||
input: {
|
||||
var \u{2f800}\u{2f800}\u{2f800}\u{2f800} = "\u{100000}\u{100000}\u{100000}\u{100000}\u{100000}";
|
||||
}
|
||||
expect_exact: 'var \\u{2f800}\\u{2f800}\\u{2f800}\\u{2f800}="\\u{100000}\\u{100000}\\u{100000}\\u{100000}\\u{100000}";'
|
||||
}
|
||||
|
||||
escape_non_escaped_identifier: {
|
||||
beautify = {ascii_only: true, ecma: 6}
|
||||
input: {
|
||||
var µþ = "µþ";
|
||||
}
|
||||
expect_exact: 'var \\u00b5\\u00fe="\\xb5\\xfe";'
|
||||
}
|
||||
|
||||
non_escape_2_non_escape: {
|
||||
beautify = {ascii_only: false, ecma: 6}
|
||||
input: {
|
||||
var µþ = "µþ";
|
||||
}
|
||||
expect_exact: 'var µþ="µþ";'
|
||||
}
|
||||
|
||||
issue_2242_1: {
|
||||
beautify = {
|
||||
ascii_only: false,
|
||||
}
|
||||
input: {
|
||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\\ud83d","\\ude00","\ud83d\ude00","\\ud83d@\\ude00");'
|
||||
}
|
||||
|
||||
issue_2242_2: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\\ud83d","\\ude00","\\ud83d\\ude00","\\ud83d@\\ude00");'
|
||||
}
|
||||
|
||||
issue_2242_3: {
|
||||
options = {
|
||||
evaluate: false,
|
||||
}
|
||||
input: {
|
||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\\ud83d"+"\\ude00","\\ud83d"+"@"+"\\ude00");'
|
||||
}
|
||||
|
||||
issue_2242_4: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||
}
|
||||
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
|
||||
}
|
||||
|
||||
201
test/compress/yield.js
Normal file
201
test/compress/yield.js
Normal file
@@ -0,0 +1,201 @@
|
||||
generators: {
|
||||
input: {
|
||||
function* fn() {};
|
||||
}
|
||||
expect_exact: "function*fn(){}"
|
||||
}
|
||||
|
||||
generators_yield: {
|
||||
input: {
|
||||
function* fn() {
|
||||
yield remote();
|
||||
}
|
||||
}
|
||||
expect_exact: "function*fn(){yield remote()}"
|
||||
}
|
||||
|
||||
generators_yield_assign: {
|
||||
input: {
|
||||
function* fn() {
|
||||
var x = {};
|
||||
x.prop = yield 5;
|
||||
}
|
||||
}
|
||||
expect_exact: "function*fn(){var x={};x.prop=yield 5}"
|
||||
}
|
||||
|
||||
generator_yield_undefined: {
|
||||
input: {
|
||||
function* fn() {
|
||||
yield;
|
||||
}
|
||||
}
|
||||
expect_exact: "function*fn(){yield}"
|
||||
}
|
||||
|
||||
yield_optimize_expression: {
|
||||
options = {
|
||||
}
|
||||
input: {
|
||||
function* f1() { yield; }
|
||||
function* f2() { yield undefined; }
|
||||
function* f3() { yield null; }
|
||||
function* f4() { yield* undefined; }
|
||||
}
|
||||
expect: {
|
||||
function* f1() { yield }
|
||||
function* f2() { yield; }
|
||||
function* f3() { yield null; }
|
||||
function* f4() { yield* void 0; }
|
||||
}
|
||||
}
|
||||
|
||||
yield_statements: {
|
||||
input: {
|
||||
function* fn() {
|
||||
var a = (yield 1) + (yield 2);
|
||||
var b = (yield 3) === (yield 4);
|
||||
var c = (yield 5) << (yield 6);
|
||||
var d = yield 7;
|
||||
var e = (yield 8) ? yield 9 : yield 10;
|
||||
var f = -(yield 11);
|
||||
}
|
||||
}
|
||||
expect_exact: "function*fn(){var a=(yield 1)+(yield 2);var b=(yield 3)===(yield 4);var c=(yield 5)<<(yield 6);var d=yield 7;var e=(yield 8)?yield 9:yield 10;var f=-(yield 11)}"
|
||||
}
|
||||
|
||||
yield_as_identifier_in_function_in_generator: {
|
||||
input: {
|
||||
var g = function*() {
|
||||
function h() {
|
||||
yield = 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var g = function*() {
|
||||
function h() {
|
||||
yield = 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
yield_before_punctuators: {
|
||||
input: {
|
||||
iter = (function*() {
|
||||
assignmentResult = [ x = yield ] = value;
|
||||
})();
|
||||
function* g1() { (yield) }
|
||||
function* g2() { [yield] }
|
||||
function* g3() { return {yield} } // Added return to avoid {} drop
|
||||
function* g4() { yield, yield; }
|
||||
function* g5() { (yield) ? yield : yield; }
|
||||
}
|
||||
expect: {
|
||||
iter = (function*() {
|
||||
assignmentResult = [ x = yield ] = value;
|
||||
})();
|
||||
function* g1() { (yield) }
|
||||
function* g2() { [yield] }
|
||||
function* g3() { return {yield} }
|
||||
function* g4() { yield, yield; }
|
||||
function* g5() { (yield) ? yield : yield; }
|
||||
}
|
||||
}
|
||||
|
||||
yield_as_identifier_outside_strict_mode: {
|
||||
input: {
|
||||
import yield from "bar";
|
||||
yield = 123;
|
||||
while (true) {
|
||||
yield:
|
||||
for(;;) break yield;
|
||||
|
||||
foo();
|
||||
}
|
||||
while (true)
|
||||
yield: for(;;) continue yield;
|
||||
function yield(){}
|
||||
function foo(...yield){}
|
||||
try { new Error("") } catch (yield) {}
|
||||
var yield = "foo";
|
||||
}
|
||||
expect: {
|
||||
import yield from "bar";
|
||||
yield = 123;
|
||||
while (true) {
|
||||
yield:
|
||||
for(;;) break yield;
|
||||
|
||||
foo();
|
||||
}
|
||||
while (true)
|
||||
yield: for(;;) continue yield;
|
||||
function yield(){}
|
||||
function foo(...yield){}
|
||||
try { new Error("") } catch (yield) {}
|
||||
var yield = "foo";
|
||||
}
|
||||
}
|
||||
|
||||
empty_generator_as_parameter_with_side_effects: {
|
||||
options = {
|
||||
side_effects: true
|
||||
}
|
||||
input: {
|
||||
var GeneratorPrototype = Object.getPrototypeOf(
|
||||
Object.getPrototypeOf(function*() {}())
|
||||
);
|
||||
evaluate(GeneratorPrototype);
|
||||
}
|
||||
expect_exact: "var GeneratorPrototype=Object.getPrototypeOf(Object.getPrototypeOf(function*(){}()));evaluate(GeneratorPrototype);"
|
||||
}
|
||||
|
||||
empty_generator_as_parameter_without_side_effects: {
|
||||
options = {
|
||||
side_effects: false
|
||||
}
|
||||
input: {
|
||||
var GeneratorPrototype = Object.getPrototypeOf(
|
||||
Object.getPrototypeOf(function*() {}())
|
||||
);
|
||||
evaluate(GeneratorPrototype);
|
||||
}
|
||||
expect_exact: "var GeneratorPrototype=Object.getPrototypeOf(Object.getPrototypeOf(function*(){}()));evaluate(GeneratorPrototype);"
|
||||
}
|
||||
|
||||
yield_dot: {
|
||||
options = {
|
||||
}
|
||||
input: {
|
||||
function* foo(){
|
||||
yield x.foo;
|
||||
(yield x).foo;
|
||||
yield (yield obj.foo()).bar();
|
||||
}
|
||||
}
|
||||
expect_exact: "function*foo(){yield x.foo;(yield x).foo;yield(yield obj.foo()).bar()}"
|
||||
}
|
||||
|
||||
yield_sub: {
|
||||
options = {
|
||||
}
|
||||
input: {
|
||||
function* foo(){
|
||||
yield x['foo'];
|
||||
(yield x)['foo'];
|
||||
yield (yield obj.foo())['bar']();
|
||||
}
|
||||
}
|
||||
expect_exact: 'function*foo(){yield x["foo"];(yield x)["foo"];yield(yield obj.foo())["bar"]()}'
|
||||
}
|
||||
|
||||
yield_as_ES5_property: {
|
||||
input: {
|
||||
"use strict";
|
||||
console.log({yield: 42}.yield);
|
||||
}
|
||||
expect_exact: '"use strict";console.log({yield:42}.yield);'
|
||||
expect_stdout: "42"
|
||||
}
|
||||
@@ -8,6 +8,7 @@ exports["defaults"] = defaults;
|
||||
exports["mangle_properties"] = mangle_properties;
|
||||
exports["minify"] = minify;
|
||||
exports["parse"] = parse;
|
||||
exports["reserve_quoted_keys"] = reserve_quoted_keys;
|
||||
exports["string_template"] = string_template;
|
||||
exports["tokenizer"] = tokenizer;
|
||||
exports["is_identifier"] = is_identifier;
|
||||
|
||||
8
test/input/invalid/const.js
Normal file
8
test/input/invalid/const.js
Normal file
@@ -0,0 +1,8 @@
|
||||
function f() {
|
||||
const a;
|
||||
}
|
||||
|
||||
function g() {
|
||||
"use strict";
|
||||
const a;
|
||||
}
|
||||
3
test/input/invalid/export_1.js
Normal file
3
test/input/invalid/export_1.js
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
export var V = 1;
|
||||
}
|
||||
1
test/input/invalid/export_2.js
Normal file
1
test/input/invalid/export_2.js
Normal file
@@ -0,0 +1 @@
|
||||
export class{};
|
||||
1
test/input/invalid/export_3.js
Normal file
1
test/input/invalid/export_3.js
Normal file
@@ -0,0 +1 @@
|
||||
export function(){};
|
||||
3
test/input/invalid/import.js
Normal file
3
test/input/invalid/import.js
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
import A from "B";
|
||||
}
|
||||
1
test/input/invalid/sequence.js
Normal file
1
test/input/invalid/sequence.js
Normal file
@@ -0,0 +1 @@
|
||||
(a, ...b);
|
||||
10
test/input/issue-2310/input.js
Normal file
10
test/input/issue-2310/input.js
Normal file
@@ -0,0 +1,10 @@
|
||||
function foo() {
|
||||
return function() {
|
||||
console.log("PASS");
|
||||
};
|
||||
}
|
||||
|
||||
(function() {
|
||||
var f = foo();
|
||||
f();
|
||||
})();
|
||||
@@ -16,8 +16,8 @@ describe("Accessor tokens", function() {
|
||||
assert.equal(node.start.pos, 12);
|
||||
assert.equal(node.end.endpos, 46);
|
||||
|
||||
assert(node.key instanceof UglifyJS.AST_SymbolAccessor);
|
||||
assert.equal(node.key.start.pos, 16);
|
||||
assert(node.key instanceof UglifyJS.AST_SymbolMethod);
|
||||
assert.equal(node.key.start.pos, 12);
|
||||
assert.equal(node.key.end.endpos, 22);
|
||||
|
||||
assert(node.value instanceof UglifyJS.AST_Accessor);
|
||||
|
||||
@@ -27,4 +27,253 @@ describe("arguments", function() {
|
||||
assert.strictEqual(ast.body[0].body[0].uses_arguments, true);
|
||||
assert.strictEqual(ast.body[0].body[0].body[0].uses_arguments, false);
|
||||
});
|
||||
});
|
||||
|
||||
it("Should parse a function containing default assignment correctly", function() {
|
||||
var ast = UglifyJS.parse("function foo(a = 123) {}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// First argument
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_DefaultAssign);
|
||||
assert(ast.body[0].argnames[0].left instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].argnames[0].operator, "=");
|
||||
assert(ast.body[0].argnames[0].right instanceof UglifyJS.AST_Number);
|
||||
|
||||
ast = UglifyJS.parse("function foo(a = a) {}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// First argument
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_DefaultAssign);
|
||||
assert(ast.body[0].argnames[0].left instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].argnames[0].operator, "=");
|
||||
assert(ast.body[0].argnames[0].right instanceof UglifyJS.AST_SymbolRef);
|
||||
});
|
||||
|
||||
it("Should parse a function containing default assignments in destructuring correctly", function() {
|
||||
var ast = UglifyJS.parse("function foo([a = 123]) {}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// First argument
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].is_array, true);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names.length, 1);
|
||||
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_DefaultAssign);
|
||||
assert(ast.body[0].argnames[0].names[0].left instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[0].operator, "=");
|
||||
assert(ast.body[0].argnames[0].names[0].right instanceof UglifyJS.AST_Number);
|
||||
|
||||
|
||||
ast = UglifyJS.parse("function foo({a = 123}) {}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// First argument
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].is_array, false);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names.length, 1);
|
||||
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[0].key, "a");
|
||||
|
||||
// Property a of first argument
|
||||
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_DefaultAssign);
|
||||
assert(ast.body[0].argnames[0].names[0].value.left instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[0].value.operator, "=");
|
||||
assert(ast.body[0].argnames[0].names[0].value.right instanceof UglifyJS.AST_Number);
|
||||
|
||||
|
||||
ast = UglifyJS.parse("function foo({a: a = 123}) {}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// First argument
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].is_array, false);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names.length, 1);
|
||||
|
||||
// Content destructuring of first argument
|
||||
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[0].key, "a");
|
||||
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_DefaultAssign);
|
||||
|
||||
// Property a of first argument
|
||||
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_DefaultAssign);
|
||||
assert(ast.body[0].argnames[0].names[0].value.left instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[0].value.operator, "=");
|
||||
assert(ast.body[0].argnames[0].names[0].value.right instanceof UglifyJS.AST_Number);
|
||||
});
|
||||
|
||||
it("Should parse a function containing default assignments in complex destructuring correctly", function() {
|
||||
var ast = UglifyJS.parse("function foo([a, [b = 123]]){}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// Check first argument
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].is_array, true);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names.length, 2);
|
||||
|
||||
// Check whole destructuring structure of first argument
|
||||
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert(ast.body[0].argnames[0].names[1] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[1].is_array, true);
|
||||
|
||||
// Check content of second destructuring element (which is the nested destructuring pattern)
|
||||
assert(ast.body[0].argnames[0].names[1].names[0] instanceof UglifyJS.AST_DefaultAssign);
|
||||
assert(ast.body[0].argnames[0].names[1].names[0].left instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[1].names[0].operator, "=");
|
||||
assert(ast.body[0].argnames[0].names[1].names[0].right instanceof UglifyJS.AST_Number);
|
||||
|
||||
|
||||
ast = UglifyJS.parse("function foo([a, {b: c = 123}]){}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// Check first argument
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].is_array, true);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names.length, 2);
|
||||
|
||||
// Check whole destructuring structure of first argument
|
||||
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert(ast.body[0].argnames[0].names[1] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[1].is_array, false);
|
||||
|
||||
// Check content of second destructuring element (which is the nested destructuring pattern)
|
||||
assert(ast.body[0].argnames[0].names[1].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[1].names[0].key, "b");
|
||||
assert(ast.body[0].argnames[0].names[1].names[0].value instanceof UglifyJS.AST_DefaultAssign);
|
||||
|
||||
// Property b of second argument
|
||||
assert(ast.body[0].argnames[0].names[1].names[0].value instanceof UglifyJS.AST_DefaultAssign);
|
||||
assert(ast.body[0].argnames[0].names[1].names[0].value.left instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[1].names[0].value.operator, "=");
|
||||
assert(ast.body[0].argnames[0].names[1].names[0].value.right instanceof UglifyJS.AST_Number);
|
||||
|
||||
|
||||
ast = UglifyJS.parse("function foo({a, b: {b = 123}}){}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// Check first argument
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].is_array, false);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names.length, 2);
|
||||
|
||||
// Check whole destructuring structure of first argument
|
||||
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[0].key, "a");
|
||||
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert(ast.body[0].argnames[0].names[1] instanceof UglifyJS.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[1].key, "b");
|
||||
assert(ast.body[0].argnames[0].names[1].value instanceof UglifyJS.AST_Destructuring);
|
||||
|
||||
// Check content of nested destructuring in first parameter
|
||||
var content = ast.body[0].argnames[0].names[1].value
|
||||
assert.strictEqual(content.is_array, false);
|
||||
assert.strictEqual(content.names.length, 1);
|
||||
assert(content.names[0] instanceof UglifyJS.AST_ObjectKeyVal);
|
||||
assert.strictEqual(content.names[0].key, "b");
|
||||
assert(content.names[0].value instanceof UglifyJS.AST_DefaultAssign);
|
||||
assert(content.names[0].value.left instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert.strictEqual(content.names[0].value.operator, "=");
|
||||
assert(content.names[0].value.right instanceof UglifyJS.AST_Number);
|
||||
|
||||
|
||||
ast = UglifyJS.parse("function foo({a: {b = 123}}){}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// Check first argument
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].is_array, false);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names.length, 1);
|
||||
|
||||
// Check whole destructuring structure of first argument
|
||||
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[0].key, "a");
|
||||
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_Destructuring);
|
||||
|
||||
// Check content of nested destructuring
|
||||
content = ast.body[0].argnames[0].names[0].value
|
||||
assert.strictEqual(content.is_array, false);
|
||||
assert.strictEqual(content.names.length, 1);
|
||||
assert(content.names[0] instanceof UglifyJS.AST_ObjectKeyVal);
|
||||
assert.strictEqual(content.names[0].key, "b");
|
||||
assert(content.names[0].value instanceof UglifyJS.AST_DefaultAssign);
|
||||
assert(content.names[0].value.left instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert.strictEqual(content.names[0].value.operator, "=");
|
||||
assert(content.names[0].value.right instanceof UglifyJS.AST_Number);
|
||||
});
|
||||
|
||||
it("Should parse spread correctly", function() {
|
||||
var ast = UglifyJS.parse("function foo(a, b, ...c){}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 3);
|
||||
|
||||
// Check parameters
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert(ast.body[0].argnames[1] instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert(ast.body[0].argnames[2] instanceof UglifyJS.AST_Expansion);
|
||||
assert(ast.body[0].argnames[2].expression instanceof UglifyJS.AST_SymbolFunarg);
|
||||
|
||||
|
||||
ast = UglifyJS.parse("function foo([a, b, ...c]){}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// Check first parameter
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].is_array, true);
|
||||
|
||||
// Check content first parameter
|
||||
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert(ast.body[0].argnames[0].names[1] instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert(ast.body[0].argnames[0].names[2] instanceof UglifyJS.AST_Expansion);
|
||||
assert(ast.body[0].argnames[0].names[2].expression instanceof UglifyJS.AST_SymbolFunarg);
|
||||
|
||||
|
||||
ast = UglifyJS.parse("function foo([a, b, [c, ...d]]){}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// Check first parameter
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].is_array, true);
|
||||
|
||||
// Check content outer destructuring array
|
||||
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert(ast.body[0].argnames[0].names[1] instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert(ast.body[0].argnames[0].names[2] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[2].is_array, true);
|
||||
|
||||
// Check content nested destructuring array
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[2].names.length, 2);
|
||||
assert(ast.body[0].argnames[0].names[2].names[0] instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert(ast.body[0].argnames[0].names[2].names[1] instanceof UglifyJS.AST_Expansion);
|
||||
assert(ast.body[0].argnames[0].names[2].names[1].expression instanceof UglifyJS.AST_SymbolFunarg);
|
||||
|
||||
|
||||
ast = UglifyJS.parse("function foo({a: [b, ...c]}){}");
|
||||
assert(ast.body[0] instanceof UglifyJS.AST_Defun);
|
||||
assert.strictEqual(ast.body[0].argnames.length, 1);
|
||||
|
||||
// Check first parameter
|
||||
assert(ast.body[0].argnames[0] instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].is_array, false);
|
||||
|
||||
// Check outer destructuring object
|
||||
assert.strictEqual(ast.body[0].argnames[0].names.length, 1);
|
||||
assert(ast.body[0].argnames[0].names[0] instanceof UglifyJS.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[0].key, "a");
|
||||
assert(ast.body[0].argnames[0].names[0].value instanceof UglifyJS.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[0].value.is_array, true);
|
||||
|
||||
// Check content nested destructuring array
|
||||
assert.strictEqual(ast.body[0].argnames[0].names[0].value.names.length, 2);
|
||||
assert(ast.body[0].argnames[0].names[0].value.names[0] instanceof UglifyJS.AST_SymbolFunarg);
|
||||
assert(ast.body[0].argnames[0].names[0].value.names[1] instanceof UglifyJS.AST_Expansion);
|
||||
assert(ast.body[0].argnames[0].names[0].value.names[1].expression instanceof UglifyJS.AST_SymbolFunarg);
|
||||
});
|
||||
});
|
||||
|
||||
399
test/mocha/arrow.js
Normal file
399
test/mocha/arrow.js
Normal file
@@ -0,0 +1,399 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Arrow functions", function() {
|
||||
it("Should not accept spread tokens on non-last parameters or without arguments parentheses", function() {
|
||||
var tests = [
|
||||
"var a = ...a => {return a.join()}",
|
||||
"var b = (a, ...b, c) => { return a + b.join() + c}",
|
||||
"var c = (...a, b) => a.join()"
|
||||
];
|
||||
var test = function(code) {
|
||||
return function() {
|
||||
uglify.parse(code);
|
||||
}
|
||||
}
|
||||
var error = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
e.message === "Unexpected token: expand (...)";
|
||||
}
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(test(tests[i]), error);
|
||||
}
|
||||
});
|
||||
it("Should not accept holes in object binding patterns, while still allowing a trailing elision", function() {
|
||||
var tests = [
|
||||
"f = ({, , ...x} = [1, 2]) => {};"
|
||||
];
|
||||
var test = function(code) {
|
||||
return function() {
|
||||
uglify.parse(code);
|
||||
}
|
||||
}
|
||||
var error = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
e.message === "Unexpected token: punc (,)";
|
||||
}
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(test(tests[i]), error);
|
||||
}
|
||||
});
|
||||
it("Should not accept newlines before arrow token", function() {
|
||||
var tests = [
|
||||
"f = foo\n=> 'foo';",
|
||||
"f = (foo, bar)\n=> 'foo';",
|
||||
"f = ()\n=> 'foo';",
|
||||
"foo((bar)\n=>'baz';);"
|
||||
];
|
||||
var test = function(code) {
|
||||
return function() {
|
||||
uglify.parse(code);
|
||||
}
|
||||
}
|
||||
var error = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
e.message === "Unexpected newline before arrow (=>)";
|
||||
}
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(test(tests[i]), error);
|
||||
}
|
||||
});
|
||||
it("Should not accept arrow functions in the middle or end of an expression", function() {
|
||||
[
|
||||
"0 + x => 0",
|
||||
"0 + async x => 0",
|
||||
"typeof x => 0",
|
||||
"typeof async x => 0",
|
||||
"typeof (x) => null",
|
||||
"typeof async (x) => null",
|
||||
].forEach(function(code) {
|
||||
assert.throws(function() {
|
||||
uglify.parse(code);
|
||||
}, function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error && /^Unexpected /.test(e.message);
|
||||
}, code);
|
||||
});
|
||||
});
|
||||
|
||||
it("Should parse a function containing default assignment correctly", function() {
|
||||
var ast = uglify.parse("var a = (a = 123) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// First argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_DefaultAssign);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].left instanceof uglify.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].operator, "=");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].right instanceof uglify.AST_Number);
|
||||
|
||||
ast = uglify.parse("var a = (a = a) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// First argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_DefaultAssign);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].left instanceof uglify.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].operator, "=");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].right instanceof uglify.AST_SymbolRef);
|
||||
});
|
||||
|
||||
it("Should parse a function containing default assignments in destructuring correctly", function() {
|
||||
var ast = uglify.parse("var a = ([a = 123]) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// First argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, true);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 1);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_DefaultAssign);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].left instanceof uglify.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].operator, "=");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].right instanceof uglify.AST_Number);
|
||||
|
||||
|
||||
ast = uglify.parse("var a = ({a = 123}) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// First argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, false);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 1);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_ObjectKeyVal);
|
||||
|
||||
// First object element in first argument
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].key, "a");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value instanceof uglify.AST_DefaultAssign);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.left instanceof uglify.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].value.operator, "=");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.right instanceof uglify.AST_Number);
|
||||
|
||||
|
||||
ast = uglify.parse("var a = ({a: a = 123}) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// First argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, false);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 1);
|
||||
|
||||
// Content destructuring of first argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_ObjectProperty);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].key, "a");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value instanceof uglify.AST_DefaultAssign);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.left instanceof uglify.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].value.operator, "=");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.right instanceof uglify.AST_Number);
|
||||
});
|
||||
|
||||
it("Should parse a function containing default assignments in complex destructuring correctly", function() {
|
||||
var ast = uglify.parse("var a = ([a, [b = 123]]) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// Check first argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, true);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 2);
|
||||
|
||||
// Check whole destructuring structure of first argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_SymbolFunarg);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].is_array, true);
|
||||
|
||||
// Check content of second destructuring element (which is the nested destructuring pattern)
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0] instanceof uglify.AST_DefaultAssign);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].left instanceof uglify.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].operator, "=");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].right instanceof uglify.AST_Number);
|
||||
|
||||
|
||||
ast = uglify.parse("var a = ([a, {b: c = 123}]) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// Check first argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, true);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 2);
|
||||
|
||||
// Check whole destructuring structure of first argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_SymbolFunarg);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].is_array, false);
|
||||
|
||||
// Check content of second destructuring element (which is the nested destructuring pattern)
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0] instanceof uglify.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].key, "b");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].value instanceof uglify.AST_DefaultAssign);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].value.left instanceof uglify.AST_SymbolFunarg);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].value.operator, "=");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1].names[0].value.right instanceof uglify.AST_Number);
|
||||
|
||||
|
||||
ast = uglify.parse("var a = ({a, b: {b = 123}}) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// Check first argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, false);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 2);
|
||||
|
||||
// First argument, property 1
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].key, "a");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value instanceof uglify.AST_SymbolFunarg);
|
||||
|
||||
// First argument, property 2
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1] instanceof uglify.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[1].key, "b");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1].value instanceof uglify.AST_Destructuring);
|
||||
|
||||
// Check content of nested destructuring
|
||||
var content = ast.body[0].definitions[0].value.argnames[0].names[1].value
|
||||
assert.strictEqual(content.is_array, false);
|
||||
assert.strictEqual(content.names.length, 1);
|
||||
assert(content.names[0] instanceof uglify.AST_ObjectKeyVal);
|
||||
|
||||
// Content of first property in nested destructuring
|
||||
assert.strictEqual(content.names[0].key, "b");
|
||||
assert(content.names[0].value instanceof uglify.AST_DefaultAssign);
|
||||
assert(content.names[0].value.left instanceof uglify.AST_SymbolFunarg);
|
||||
assert.strictEqual(content.names[0].value.operator, "=");
|
||||
assert(content.names[0].value.right instanceof uglify.AST_Number);
|
||||
|
||||
|
||||
ast = uglify.parse("var a = ({a: {b = 123}}) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// Check first argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, false);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 1);
|
||||
|
||||
// Check whole destructuring structure of first argument
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].key, "a");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value instanceof uglify.AST_Destructuring);
|
||||
|
||||
// Check content of nested destructuring
|
||||
content = ast.body[0].definitions[0].value.argnames[0].names[0].value
|
||||
assert.strictEqual(content.is_array, false);
|
||||
assert.strictEqual(content.names.length, 1);
|
||||
assert(content.names[0] instanceof uglify.AST_ObjectKeyVal);
|
||||
|
||||
// Check first property of nested destructuring
|
||||
assert.strictEqual(content.names[0].key, "b");
|
||||
assert(content.names[0].value instanceof uglify.AST_DefaultAssign);
|
||||
assert(content.names[0].value.left instanceof uglify.AST_SymbolFunarg);
|
||||
assert.strictEqual(content.names[0].value.operator, "=");
|
||||
assert(content.names[0].value.right instanceof uglify.AST_Number);
|
||||
});
|
||||
|
||||
it("Should parse spread correctly", function() {
|
||||
var ast = uglify.parse("var a = (a, b, ...c) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 3);
|
||||
|
||||
// Check parameters
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_SymbolFunarg);
|
||||
assert(ast.body[0].definitions[0].value.argnames[1] instanceof uglify.AST_SymbolFunarg);
|
||||
assert(ast.body[0].definitions[0].value.argnames[2] instanceof uglify.AST_Expansion);
|
||||
assert(ast.body[0].definitions[0].value.argnames[2].expression instanceof uglify.AST_SymbolFunarg);
|
||||
|
||||
|
||||
ast = uglify.parse("var a = ([a, b, ...c]) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// Check first parameter
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, true);
|
||||
|
||||
// Check content first parameter
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_SymbolFunarg);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1] instanceof uglify.AST_SymbolFunarg);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[2] instanceof uglify.AST_Expansion);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[2].expression instanceof uglify.AST_SymbolFunarg);
|
||||
|
||||
|
||||
ast = uglify.parse("var a = ([a, b, [c, ...d]]) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// Check first parameter
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, true);
|
||||
|
||||
// Check content outer destructuring array
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_SymbolFunarg);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[1] instanceof uglify.AST_SymbolFunarg);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[2] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[2].is_array, true);
|
||||
|
||||
// Check content nested destructuring array
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[2].names.length, 2);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[2].names[0] instanceof uglify.AST_SymbolFunarg);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[2].names[1] instanceof uglify.AST_Expansion);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[2].names[1].expression instanceof uglify.AST_SymbolFunarg);
|
||||
|
||||
|
||||
ast = uglify.parse("var a = ({a: [b, ...c]}) => {}");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert.strictEqual(ast.body[0].definitions.length, 1);
|
||||
assert(ast.body[0].definitions[0] instanceof uglify.AST_VarDef);
|
||||
assert(ast.body[0].definitions[0].name instanceof uglify.AST_SymbolVar);
|
||||
assert(ast.body[0].definitions[0].value instanceof uglify.AST_Arrow);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames.length, 1);
|
||||
|
||||
// Check first parameter
|
||||
assert(ast.body[0].definitions[0].value.argnames[0] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].is_array, false);
|
||||
|
||||
// Check outer destructuring object
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names.length, 1);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0] instanceof uglify.AST_ObjectKeyVal);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].key, "a");
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].value.is_array, true);
|
||||
|
||||
// Check content nested destructuring array
|
||||
assert.strictEqual(ast.body[0].definitions[0].value.argnames[0].names[0].value.names.length, 2);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.names[0] instanceof uglify.AST_SymbolFunarg);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.names[1] instanceof uglify.AST_Expansion);
|
||||
assert(ast.body[0].definitions[0].value.argnames[0].names[0].value.names[1].expression instanceof uglify.AST_SymbolFunarg);
|
||||
});
|
||||
|
||||
it("Should handle arrow function with bind", function() {
|
||||
function minify(code) {
|
||||
return uglify.minify(code, {
|
||||
mangle: false
|
||||
}).code;
|
||||
}
|
||||
|
||||
assert.strictEqual(
|
||||
minify(minify("test(((index) => { console.log(this, index); }).bind(this, 1));")),
|
||||
"test((index=>{console.log(this,index)}).bind(this,1));"
|
||||
);
|
||||
assert.strictEqual(
|
||||
minify(minify('test(((index) => { console.log(this, index); })["bind"](this, 1));')),
|
||||
"test((index=>{console.log(this,index)}).bind(this,1));"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
34
test/mocha/builtins.js
Normal file
34
test/mocha/builtins.js
Normal file
@@ -0,0 +1,34 @@
|
||||
var UglifyJS = require("../../");
|
||||
var assert = require("assert");
|
||||
|
||||
describe("builtins", function() {
|
||||
it ("Should not mangle builtins", function() {
|
||||
var test = "function foo(something){\n" +
|
||||
" return [Object,Array,Function,Number,String,Boolean,Error,Math,Date,RegExp,Symbol,Map,Promise,Proxy,Reflect,Set,WeakMap,WeakSet,Float32Array,something];\n" +
|
||||
"};";
|
||||
|
||||
var result = UglifyJS.minify(test, {parse: {bare_returns: true}}).code;
|
||||
|
||||
assert.strictEqual(result.indexOf("something"), -1);
|
||||
|
||||
assert.notEqual(result.indexOf("Object"), -1);
|
||||
assert.notEqual(result.indexOf("Array"), -1);
|
||||
assert.notEqual(result.indexOf("Function"), -1);
|
||||
assert.notEqual(result.indexOf("Number"), -1);
|
||||
assert.notEqual(result.indexOf("String"), -1);
|
||||
assert.notEqual(result.indexOf("Boolean"), -1);
|
||||
assert.notEqual(result.indexOf("Error"), -1);
|
||||
assert.notEqual(result.indexOf("Math"), -1);
|
||||
assert.notEqual(result.indexOf("Date"), -1);
|
||||
assert.notEqual(result.indexOf("RegExp"), -1);
|
||||
assert.notEqual(result.indexOf("Symbol"), -1);
|
||||
assert.notEqual(result.indexOf("Promise"), -1);
|
||||
assert.notEqual(result.indexOf("Proxy"), -1);
|
||||
assert.notEqual(result.indexOf("Reflect"), -1);
|
||||
assert.notEqual(result.indexOf("Set"), -1);
|
||||
assert.notEqual(result.indexOf("WeakMap"), -1);
|
||||
assert.notEqual(result.indexOf("WeakSet"), -1);
|
||||
assert.notEqual(result.indexOf("Map"), -1);
|
||||
assert.notEqual(result.indexOf("Float32Array"), -1);
|
||||
});
|
||||
});
|
||||
57
test/mocha/class.js
Normal file
57
test/mocha/class.js
Normal file
@@ -0,0 +1,57 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Class", function() {
|
||||
it("Should not accept spread on non-last parameters in methods", function() {
|
||||
var tests = [
|
||||
"class foo { bar(...a, b) { return a.join(b) } }",
|
||||
"class foo { bar(a, b, ...c, d) { return c.join(a + b) + d } }",
|
||||
"class foo { *bar(...a, b) { return a.join(b) } }",
|
||||
"class foo { *bar(a, b, ...c, d) { return c.join(a + b) + d } }"
|
||||
];
|
||||
var test = function(code) {
|
||||
return function() {
|
||||
uglify.parse(code);
|
||||
}
|
||||
}
|
||||
var error = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
/^Unexpected token: /.test(e.message);
|
||||
}
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(test(tests[i]), error);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should return the correct token for class methods", function() {
|
||||
var tests = [
|
||||
{
|
||||
code: "class foo{static test(){}}",
|
||||
token_value_start: "static",
|
||||
token_value_end: "}"
|
||||
},
|
||||
{
|
||||
code: "class bar{*procedural(){}}",
|
||||
token_value_start: "*",
|
||||
token_value_end: "}"
|
||||
},
|
||||
{
|
||||
code: "class foobar{aMethod(){}}",
|
||||
token_value_start: "aMethod",
|
||||
token_value_end: "}"
|
||||
},
|
||||
{
|
||||
code: "class foobaz{get something(){}}",
|
||||
token_value_start: "get",
|
||||
token_value_end: "}"
|
||||
}
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
var ast = uglify.parse(tests[i].code);
|
||||
assert.strictEqual(ast.body[0].properties[0].start.value, tests[i].token_value_start);
|
||||
assert.strictEqual(ast.body[0].properties[0].end.value, tests[i].token_value_end);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
var assert = require("assert");
|
||||
var exec = require("child_process").exec;
|
||||
var readFileSync = require("fs").readFileSync;
|
||||
var semver = require("semver");
|
||||
|
||||
function read(path) {
|
||||
return readFileSync(path, "utf8");
|
||||
@@ -9,9 +10,11 @@ function read(path) {
|
||||
describe("bin/uglifyjs", function () {
|
||||
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||
it("should produce a functional build when using --self", function (done) {
|
||||
this.timeout(30000);
|
||||
this.timeout(60000);
|
||||
|
||||
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
|
||||
var command = uglifyjscmd + ' --self -mc ecma=';
|
||||
command += semver.satisfies(process.version, ">=4") ? "6" : "5";
|
||||
command += ',passes=3,keep_fargs=false,unsafe --wrap WrappedUglifyJS';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
@@ -63,7 +66,7 @@ describe("bin/uglifyjs", function () {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" +
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DIn0=\n");
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -192,7 +195,7 @@ describe("bin/uglifyjs", function () {
|
||||
|
||||
assert.strictEqual(stdout, [
|
||||
"var bar=function(){function foo(bar){return bar}return foo}();",
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DIn0=",
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
|
||||
"",
|
||||
].join("\n"));
|
||||
assert.strictEqual(stderr, "WARN: inline source map not found\n");
|
||||
@@ -398,6 +401,21 @@ describe("bin/uglifyjs", function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (const a)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/const.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/const.js:7,11",
|
||||
" const a;",
|
||||
" ^",
|
||||
"ERROR: Missing initializer in const declaration"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (delete x)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/delete.js';
|
||||
|
||||
@@ -468,7 +486,7 @@ describe("bin/uglifyjs", function () {
|
||||
"Parse error at test/input/invalid/try.js:7,18",
|
||||
" try {} catch (eval) {}",
|
||||
" ^",
|
||||
"ERROR: Unexpected eval in strict mode"
|
||||
"ERROR: Unexpected eval identifier as parameter inside strict mode"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
@@ -518,6 +536,81 @@ describe("bin/uglifyjs", function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (block-level export)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/export_1.js -m';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/export_1.js:2,4",
|
||||
" export var V = 1;",
|
||||
" ^",
|
||||
"ERROR: Export statement may only appear at top level"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (block-level import)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/import.js -m';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/import.js:2,4",
|
||||
' import A from "B";',
|
||||
" ^",
|
||||
"ERROR: Import statement may only appear at top level"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (anonymous class)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/export_2.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/export_2.js:1,12",
|
||||
"export class{};",
|
||||
" ^",
|
||||
"ERROR: Unexpected token: punc ({)"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (anonymous function)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/export_3.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/export_3.js:1,15",
|
||||
"export function(){};",
|
||||
" ^",
|
||||
"ERROR: Unexpected token: punc (()"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (spread in sequence)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/sequence.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/sequence.js:1,4",
|
||||
"(a, ...b);",
|
||||
" ^",
|
||||
"ERROR: Unexpected token: expand (...)"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (for-in init)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/for-in_1.js';
|
||||
|
||||
@@ -573,6 +666,25 @@ describe("bin/uglifyjs", function () {
|
||||
return JSON.stringify(map).replace(/"/g, '\\"');
|
||||
}
|
||||
});
|
||||
it("Should include function calls in source map", function(done) {
|
||||
var command = [
|
||||
uglifyjscmd,
|
||||
"test/input/issue-2310/input.js",
|
||||
"-c",
|
||||
"--source-map", "url=inline",
|
||||
].join(" ");
|
||||
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, [
|
||||
'function foo(){return function(){console.log("PASS")}}foo()();',
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIiwiZiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFDTCxPQUFPLFdBQ0hDLFFBQVFDLElBQUksU0FLUkYsS0FDUkcifQ==",
|
||||
""
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should dump AST as JSON", function(done) {
|
||||
var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast";
|
||||
exec(command, function (err, stdout) {
|
||||
@@ -593,8 +705,8 @@ describe("bin/uglifyjs", function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --mangle reserved=[]", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-505/input.js -m reserved=[callback]';
|
||||
it("Should work with --mangle reserved=[]", function(done) {
|
||||
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=[callback]";
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
@@ -603,8 +715,8 @@ describe("bin/uglifyjs", function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --mangle reserved=false", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-505/input.js -m reserved=false';
|
||||
it("Should work with --mangle reserved=false", function(done) {
|
||||
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=false";
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
@@ -613,4 +725,22 @@ describe("bin/uglifyjs", function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should fail with --mangle-props reserved=[in]", function(done) {
|
||||
var command = uglifyjscmd + " test/input/issue-505/input.js --mangle-props reserved=[in]";
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `reserved=\[in]` is not a supported option/.test(stderr), stderr);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should fail with --define a-b", function(done) {
|
||||
var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b";
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr, "Error parsing arguments for 'define': a-b\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,7 +31,8 @@ describe("Comment", function() {
|
||||
"/*Some comment 2\r\n\r\n\r\n*/\r\n>\n\n\n\n\n\n",
|
||||
"/*Some comment 3\r\r\r*/\r>\n\n\n\n\n\n",
|
||||
"/*Some comment 4\u2028\u2028\u2028*/\u2028>\n\n\n\n\n\n",
|
||||
"/*Some comment 5\u2029\u2029\u2029*/\u2029>\n\n\n\n\n\n"
|
||||
"/*Some comment 5\u2029\u2029\u2029*/\u2029>\n\n\n\n\n\n",
|
||||
"/*Some comment 6\udbff\udfff\udbff\udfff\n\n\n*/\n>\n\n\n\n\n"
|
||||
];
|
||||
|
||||
var fail = function(e) {
|
||||
|
||||
138
test/mocha/destructuring.js
Normal file
138
test/mocha/destructuring.js
Normal file
@@ -0,0 +1,138 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Destructuring", function() {
|
||||
it("Should generate similar trees for destructuring in left hand side expressions, definitions, functions and arrow functions", function() {
|
||||
var patterns = [
|
||||
"[]",
|
||||
"{}",
|
||||
|
||||
"[a, b, c]",
|
||||
"{a: b, c: d}",
|
||||
"{a}",
|
||||
"{a, b}",
|
||||
|
||||
"{a: {}}",
|
||||
"{a: []}",
|
||||
"[{}]",
|
||||
"[[]]",
|
||||
"{a: {b}}",
|
||||
|
||||
// Can't do `a = 123` with lhs expression, so only test in destructuring
|
||||
"[foo = bar]",
|
||||
"{a = 123}",
|
||||
"[{foo: abc = 123}]",
|
||||
"{foo: [abc = 123]}",
|
||||
|
||||
"[...foo]",
|
||||
"[...{}]",
|
||||
"[...[]]"
|
||||
|
||||
// Can't do `...` because that is an invalid lhs expression, spread in array destructuring should be fine though
|
||||
];
|
||||
|
||||
var types = [
|
||||
{
|
||||
name: "lhs",
|
||||
symbolType: uglify.AST_SymbolRef,
|
||||
tree: function (ast) {
|
||||
return ast.body[0].body.left;
|
||||
},
|
||||
generate: function (code) {
|
||||
return "(" + code + " = a)";
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "var",
|
||||
symbolType: uglify.AST_SymbolVar,
|
||||
tree: function (ast) {
|
||||
return ast.body[0].definitions[0].name;
|
||||
},
|
||||
generate: function (code) {
|
||||
return "var " + code + " = a";
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "function",
|
||||
symbolType: uglify.AST_SymbolFunarg,
|
||||
tree: function (ast) {
|
||||
return ast.body[0].argnames[0];
|
||||
},
|
||||
generate: function (code) {
|
||||
return "function a(" + code + ") {}";
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "arrow",
|
||||
symbolType: uglify.AST_SymbolFunarg,
|
||||
tree: function (ast) {
|
||||
return ast.body[0].definitions[0].value.argnames[0];
|
||||
},
|
||||
generate: function (code) {
|
||||
return "var a = (" + code + ") => {}";
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var walker = function(type, ref, code, result) {
|
||||
var w = new uglify.TreeWalker(function(node) {
|
||||
if (w.parent() instanceof uglify.AST_DefaultAssign &&
|
||||
w.parent().right === node
|
||||
) {
|
||||
return true; // Don't check the content of the default assignment
|
||||
|
||||
} else if (node instanceof uglify.AST_Symbol) {
|
||||
assert(node instanceof type.symbolType,
|
||||
node.TYPE + " while " + type.symbolType.TYPE + " expected at pos " +
|
||||
node.start.pos + " in `" + code + "` (" + ref + ")"
|
||||
);
|
||||
|
||||
result.push([
|
||||
new uglify.AST_Symbol({
|
||||
start: node.start,
|
||||
name: node.name,
|
||||
end: node.end
|
||||
}),
|
||||
w.parent()
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
result.push([node, w.parent()]);
|
||||
});
|
||||
|
||||
return w;
|
||||
};
|
||||
|
||||
var getNodeType = function(node) {
|
||||
return node[0].TYPE + (node[1] ? " " + node[1].TYPE : "");
|
||||
}
|
||||
|
||||
for (var i = 0; i < patterns.length; i++) {
|
||||
var results = [];
|
||||
|
||||
for (var j = 0; j < types.length; j++) {
|
||||
var code = types[j].generate(patterns[i])
|
||||
var ast = types[j].tree(
|
||||
uglify.parse(code)
|
||||
);
|
||||
results.push([]);
|
||||
ast.walk(walker(
|
||||
types[j],
|
||||
"`" + patterns[i] + "` on " + types[j].name,
|
||||
code,
|
||||
results[j]
|
||||
));
|
||||
|
||||
if (j > 0) {
|
||||
assert.deepEqual(
|
||||
results[0].map(getNodeType),
|
||||
results[j].map(getNodeType),
|
||||
"AST disagree on " + patterns[i] + " with " + types[j].name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -62,10 +62,10 @@ describe("Directives", function() {
|
||||
it("Should know which strings are directive and which ones are not", function() {
|
||||
var test_directive = function(tokenizer, test) {
|
||||
test.directives.map(function(directive) {
|
||||
assert.strictEqual(tokenizer.has_directive(directive), true, directive + " in " + test.input);
|
||||
assert.strictEqual(tokenizer.has_directive(directive), true, "Didn't found directive `" + directive + "` at the end of `" + test.input + '`');
|
||||
});
|
||||
test.non_directives.map(function(fake_directive) {
|
||||
assert.strictEqual(tokenizer.has_directive(fake_directive), false, fake_directive + " in " + test.input);
|
||||
assert.strictEqual(tokenizer.has_directive(fake_directive), false, "Unexpectedly found directive `" + fake_directive + "` at the end of `" + test.input + '`');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -156,6 +156,16 @@ describe("Directives", function() {
|
||||
input: '"use strict";try{"use asm";',
|
||||
directives: ["use strict"],
|
||||
non_directives: ["use\nstrict", "use \nstrict", "use asm"]
|
||||
},
|
||||
{
|
||||
input: 'class foo {',
|
||||
directives: ["use strict"],
|
||||
non_directives: ["use\nstrict", "use asm"]
|
||||
},
|
||||
{
|
||||
input: 'class foo {}',
|
||||
directives: [],
|
||||
non_directives: ["use strict", "use asm", "use\nstrict"]
|
||||
}
|
||||
];
|
||||
|
||||
@@ -378,4 +388,44 @@ describe("Directives", function() {
|
||||
);
|
||||
}
|
||||
});
|
||||
it("Should be detect implicit usages of strict mode from tree walker", function() {
|
||||
var tests = [
|
||||
{
|
||||
input: 'class foo {bar(){_check_}}',
|
||||
directives: ["use strict"],
|
||||
non_directives: ["use bar"]
|
||||
},
|
||||
{
|
||||
input: 'class foo {bar(){}}_check_',
|
||||
directives: [],
|
||||
non_directives: ["use strict", "use bar"]
|
||||
}
|
||||
];
|
||||
|
||||
var i = 0;
|
||||
var checked;
|
||||
var checkWalker = new uglify.TreeWalker(function(node, descend) {
|
||||
if (node instanceof uglify.AST_Symbol && node.name === "_check_") {
|
||||
checked = true;
|
||||
for (var j = 0; j < tests[i].directives.length; j++) {
|
||||
assert.ok(checkWalker.has_directive(tests[i].directives[j]),
|
||||
"Did not found directive '" + tests[i].directives[j] + "' in test " + tests[i].input)
|
||||
}
|
||||
for (var k = 0; k < tests[i].non_directives.length; k++) {
|
||||
assert.equal(checkWalker.has_directive(tests[i].non_directives[k]), undefined,
|
||||
"Found directive '" + tests[i].non_directives[k] + "' in test " + tests[i].input)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for (; i < tests.length; i++) {
|
||||
// Do tests - iterate the ast in each test - check only when _check_ occurs - fail when no _check_ has been found
|
||||
checked = false;
|
||||
var ast = uglify.parse(tests[i].input);
|
||||
ast.walk(checkWalker);
|
||||
if (!checked) {
|
||||
throw "No _check_ symbol found in " + tests[i].input;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
35
test/mocha/eof.js
Normal file
35
test/mocha/eof.js
Normal file
@@ -0,0 +1,35 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("EOF", function() {
|
||||
it("Should test code for at least throwing syntax error when incomplete", function() {
|
||||
var error = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error;
|
||||
}
|
||||
var parse = function(test) {
|
||||
return function() {
|
||||
uglify.parse(test);
|
||||
}
|
||||
}
|
||||
// Chops off 1 char at a time until limit or start of string is reached
|
||||
// The passed code must still be valid when unchopped
|
||||
var test_eol = function(input, chopLimit) {
|
||||
if (chopLimit === undefined) {
|
||||
chopLimit = input.length - 1;
|
||||
}
|
||||
|
||||
assert.doesNotThrow(parse(input), "Expected valid code for \n" + input);
|
||||
|
||||
for (var i = input.length - 1; chopLimit > 0; chopLimit--, i--) {
|
||||
var code = input.substr(0, i);
|
||||
assert.throws(parse(code), error, code);
|
||||
}
|
||||
}
|
||||
|
||||
test_eol("var \\u1234", 7); // Incomplete identifier
|
||||
test_eol("'Incomplete string'");
|
||||
test_eol("/Unterminated regex/");
|
||||
test_eol("` Unterminated template string`");
|
||||
test_eol("/* Unfinishing multiline comment */");
|
||||
});
|
||||
});
|
||||
57
test/mocha/export.js
Normal file
57
test/mocha/export.js
Normal file
@@ -0,0 +1,57 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Export/Import", function() {
|
||||
it("Should parse export directives", function() {
|
||||
var inputs = [
|
||||
['export * from "a.js"', ['*'], "a.js"],
|
||||
['export {A} from "a.js"', ['A'], "a.js"],
|
||||
['export {A as X} from "a.js"', ['X'], "a.js"],
|
||||
['export {A as Foo, B} from "a.js"', ['Foo', 'B'], "a.js"],
|
||||
['export {A, B} from "a.js"', ['A', 'B'], "a.js"],
|
||||
];
|
||||
|
||||
function test(code) {
|
||||
return uglify.parse(code);
|
||||
}
|
||||
|
||||
function extractNames(symbols) {
|
||||
var ret = [];
|
||||
for (var i = 0; i < symbols.length; i++) {
|
||||
ret.push(symbols[i].foreign_name.name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (var i = 0; i < inputs.length; i++) {
|
||||
var ast = test(inputs[i][0]);
|
||||
var names = inputs[i][1];
|
||||
var filename = inputs[i][2];
|
||||
assert(ast instanceof uglify.AST_Toplevel);
|
||||
assert.equal(ast.body.length, 1);
|
||||
var st = ast.body[0];
|
||||
assert(st instanceof uglify.AST_Export);
|
||||
var actualNames = extractNames(st.exported_names);
|
||||
assert.deepEqual(actualNames, names);
|
||||
assert.equal(st.module_name.value, filename);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should not parse invalid uses of export", function() {
|
||||
assert.equal(uglify.minify("export").error.message, "Unexpected token: eof (undefined)");
|
||||
assert.equal(uglify.minify("export;").error.message, "Unexpected token: punc (;)");
|
||||
assert.equal(uglify.minify("export();").error.message, "Unexpected token: keyword (export)");
|
||||
assert.equal(uglify.minify("export(1);").error.message, "Unexpected token: keyword (export)");
|
||||
assert.equal(uglify.minify("var export;").error.message, "Name expected");
|
||||
assert.equal(uglify.minify("var export = 1;").error.message, "Name expected");
|
||||
assert.equal(uglify.minify("function f(export){}").error.message, "Invalid function parameter");
|
||||
});
|
||||
|
||||
it("Should not parse invalid uses of import", function() {
|
||||
assert.equal(uglify.minify("import").error.message, "Unexpected token: eof (undefined)");
|
||||
assert.equal(uglify.minify("import;").error.message, "Unexpected token: punc (;)");
|
||||
assert.equal(uglify.minify("var import;").error.message, "Unexpected token: import");
|
||||
assert.equal(uglify.minify("var import = 1;").error.message, "Unexpected token: import");
|
||||
assert.equal(uglify.minify("function f(import){}").error.message, "Unexpected token: name (import)");
|
||||
});
|
||||
});
|
||||
32
test/mocha/expression.js
Normal file
32
test/mocha/expression.js
Normal file
@@ -0,0 +1,32 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Expression", function() {
|
||||
it("Should not allow the first exponentiation operator to be prefixed with an unary operator", function() {
|
||||
var tests = [
|
||||
"+5 ** 3",
|
||||
"-5 ** 3",
|
||||
"~5 ** 3",
|
||||
"!5 ** 3",
|
||||
"void 5 ** 3",
|
||||
"typeof 5 ** 3",
|
||||
"delete 5 ** 3",
|
||||
"var a = -(5) ** 3;"
|
||||
];
|
||||
|
||||
var fail = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
/^Unexpected token: operator \((?:[!+~-]|void|typeof|delete)\)/.test(e.message);
|
||||
}
|
||||
|
||||
var exec = function(test) {
|
||||
return function() {
|
||||
uglify.parse(test);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(exec(tests[i]), fail, tests[i]);
|
||||
}
|
||||
});
|
||||
});
|
||||
288
test/mocha/function.js
Normal file
288
test/mocha/function.js
Normal file
@@ -0,0 +1,288 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Function", function() {
|
||||
it ("Should parse binding patterns correctly", function() {
|
||||
// Function argument nodes are correct
|
||||
function get_args(args) {
|
||||
return args.map(function (arg) {
|
||||
return [arg.TYPE, arg.name];
|
||||
});
|
||||
}
|
||||
|
||||
// Destructurings as arguments
|
||||
var destr_fun1 = uglify.parse('(function ({a, b}) {})').body[0].body;
|
||||
var destr_fun2 = uglify.parse('(function ([a, [b]]) {})').body[0].body;
|
||||
var destr_fun3 = uglify.parse('({a, b}) => null').body[0].body;
|
||||
var destr_fun4 = uglify.parse('([a, [b]]) => null').body[0].body;
|
||||
|
||||
assert.equal(destr_fun1.argnames.length, 1);
|
||||
assert.equal(destr_fun2.argnames.length, 1);
|
||||
assert.equal(destr_fun3.argnames.length, 1);
|
||||
assert.equal(destr_fun4.argnames.length, 1);
|
||||
|
||||
var destruct1 = destr_fun1.argnames[0];
|
||||
var destruct2 = destr_fun2.argnames[0];
|
||||
var destruct3 = destr_fun3.argnames[0];
|
||||
var destruct4 = destr_fun4.argnames[0];
|
||||
|
||||
assert(destruct1 instanceof uglify.AST_Destructuring);
|
||||
assert(destruct2 instanceof uglify.AST_Destructuring);
|
||||
assert(destruct3 instanceof uglify.AST_Destructuring);
|
||||
assert(destruct4 instanceof uglify.AST_Destructuring);
|
||||
assert(destruct2.names[1] instanceof uglify.AST_Destructuring);
|
||||
assert(destruct4.names[1] instanceof uglify.AST_Destructuring);
|
||||
|
||||
assert.equal(destruct1.start.value, '{');
|
||||
assert.equal(destruct1.end.value, '}');
|
||||
assert.equal(destruct2.start.value, '[');
|
||||
assert.equal(destruct2.end.value, ']');
|
||||
assert.equal(destruct3.start.value, '{');
|
||||
assert.equal(destruct3.end.value, '}');
|
||||
assert.equal(destruct4.start.value, '[');
|
||||
assert.equal(destruct4.end.value, ']');
|
||||
|
||||
assert.equal(destruct1.is_array, false);
|
||||
assert.equal(destruct2.is_array, true);
|
||||
assert.equal(destruct3.is_array, false);
|
||||
assert.equal(destruct4.is_array, true);
|
||||
|
||||
// destruct 1
|
||||
assert.deepEqual(
|
||||
[
|
||||
destruct1.names[0].TYPE,
|
||||
destruct1.names[0].key,
|
||||
destruct1.names[0].value.name
|
||||
],
|
||||
['ObjectKeyVal', 'a', 'a']
|
||||
);
|
||||
assert.deepEqual(
|
||||
[
|
||||
destruct1.names[1].TYPE,
|
||||
destruct1.names[1].key,
|
||||
destruct1.names[1].value.name
|
||||
],
|
||||
['ObjectKeyVal', 'b', 'b']
|
||||
);
|
||||
|
||||
// destruct 2
|
||||
assert.deepEqual(
|
||||
[
|
||||
destruct2.names[0].TYPE,
|
||||
destruct2.names[0].name
|
||||
],
|
||||
['SymbolFunarg', 'a']
|
||||
);
|
||||
assert.deepEqual(
|
||||
[
|
||||
destruct2.names[1].names[0].TYPE,
|
||||
destruct2.names[1].names[0].name
|
||||
],
|
||||
['SymbolFunarg', 'b']
|
||||
);
|
||||
|
||||
// destruct 3
|
||||
assert.strictEqual(typeof destruct3.names[0].key, "string");
|
||||
assert.strictEqual(destruct3.names[0].key, "a");
|
||||
assert.strictEqual(destruct3.names[0].value.TYPE, "SymbolFunarg");
|
||||
assert.strictEqual(destruct3.names[0].value.name, "a");
|
||||
assert.strictEqual(typeof destruct3.names[1].key, "string");
|
||||
assert.strictEqual(destruct3.names[1].key, "b");
|
||||
assert.strictEqual(destruct3.names[1].value.TYPE, "SymbolFunarg");
|
||||
assert.strictEqual(destruct3.names[1].value.name, "b");
|
||||
|
||||
// destruct 4
|
||||
assert.deepEqual(
|
||||
[
|
||||
destruct4.names[0].TYPE,
|
||||
destruct4.names[0].name
|
||||
],
|
||||
['SymbolFunarg', 'a']
|
||||
);
|
||||
assert.strictEqual(destruct4.names[1].TYPE, "Destructuring");
|
||||
assert.deepEqual(
|
||||
[
|
||||
destruct4.names[1].names[0].TYPE,
|
||||
destruct4.names[1].names[0].name
|
||||
],
|
||||
['SymbolFunarg', 'b']
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
get_args(destr_fun1.args_as_names()),
|
||||
[['SymbolFunarg', 'a'], ['SymbolFunarg', 'b']]
|
||||
);
|
||||
assert.deepEqual(
|
||||
get_args(destr_fun2.args_as_names()),
|
||||
[['SymbolFunarg', 'a'], ['SymbolFunarg', 'b']]
|
||||
);
|
||||
assert.deepEqual(
|
||||
get_args(destr_fun3.args_as_names()),
|
||||
[['SymbolFunarg', 'a'], ['SymbolFunarg', 'b']]
|
||||
);
|
||||
assert.deepEqual(
|
||||
get_args(destr_fun4.args_as_names()),
|
||||
[['SymbolFunarg', 'a'], ['SymbolFunarg', 'b']]
|
||||
);
|
||||
|
||||
// Making sure we don't accidentally accept things which
|
||||
// Aren't argument destructurings
|
||||
|
||||
assert.throws(function () {
|
||||
uglify.parse('(function ( { a, [ b ] } ) { })')
|
||||
});
|
||||
|
||||
assert.throws(function () {
|
||||
uglify.parse('(function (1) { })');
|
||||
}, /Invalid function parameter/);
|
||||
|
||||
assert.throws(function () {
|
||||
uglify.parse('(function (this) { })');
|
||||
});
|
||||
|
||||
assert.throws(function () {
|
||||
uglify.parse('(function ([1]) { })');
|
||||
}, /Invalid function parameter/);
|
||||
|
||||
assert.throws(function () {
|
||||
uglify.parse('(function [a] { })');
|
||||
});
|
||||
|
||||
// generators
|
||||
var generators_def = uglify.parse('function* fn() {}').body[0];
|
||||
assert.equal(generators_def.is_generator, true);
|
||||
|
||||
assert.throws(function () {
|
||||
uglify.parse('function* (){ }');
|
||||
});
|
||||
|
||||
var generators_yield_def = uglify.parse('function* fn() {\nyield remote();\}').body[0].body[0];
|
||||
assert.strictEqual(generators_yield_def.body.is_star, false);
|
||||
});
|
||||
it("Should not accept spread on non-last parameters", function() {
|
||||
var tests = [
|
||||
"var a = function(...a, b) { return a.join(b) }",
|
||||
"var b = function(a, b, ...c, d) { return c.join(a + b) + d }",
|
||||
"function foo(...a, b) { return a.join(b) }",
|
||||
"function bar(a, b, ...c, d) { return c.join(a + b) + d }",
|
||||
"var a = function*(...a, b) { return a.join(b) }",
|
||||
"var b = function*(a, b, ...c, d) { return c.join(a + b) + d }",
|
||||
"function* foo(...a, b) { return a.join(b) }",
|
||||
"function* bar(a, b, ...c, d) { return c.join(a + b) + d }"
|
||||
];
|
||||
var test = function(code) {
|
||||
return function() {
|
||||
uglify.parse(code);
|
||||
}
|
||||
}
|
||||
var error = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
/^Unexpected token: /.test(e.message);
|
||||
}
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(test(tests[i]), error);
|
||||
}
|
||||
});
|
||||
it("Should not accept empty parameters after elision", function() {
|
||||
var tests = [
|
||||
"(function(,){})()",
|
||||
"(function(a,){})()",
|
||||
];
|
||||
var test = function(code) {
|
||||
return function() {
|
||||
uglify.parse(code, { ecma: 5 });
|
||||
}
|
||||
}
|
||||
var error = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error;
|
||||
}
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(test(tests[i]), error, tests[i]);
|
||||
}
|
||||
});
|
||||
it("Should accept trailing commas only for ES8", function() {
|
||||
[
|
||||
"new Foo(a, );",
|
||||
"async(...[1, 2], );",
|
||||
"console.log(...[1, 2], );",
|
||||
"!function(a, b, ){ console.log(a + b); }(3, 4, );",
|
||||
].forEach(function(code) {
|
||||
uglify.parse(code, { ecma: 8 });
|
||||
assert.throws(function() {
|
||||
uglify.parse(code, { ecma: 6 });
|
||||
}, function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error;
|
||||
}, code);
|
||||
});
|
||||
});
|
||||
it("Should not accept invalid trailing commas", function() {
|
||||
var tests = [
|
||||
"f(, );",
|
||||
"(, ) => {};",
|
||||
"(...p, ) => {};",
|
||||
"function f(, ) {}",
|
||||
"function f(...p, ) {}",
|
||||
"function foo(a, b, , ) {}",
|
||||
'console.log("hello", , );',
|
||||
];
|
||||
var test = function(code) {
|
||||
return function() {
|
||||
uglify.parse(code, { ecma: 8 });
|
||||
}
|
||||
}
|
||||
var error = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error;
|
||||
}
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(test(tests[i]), error, tests[i]);
|
||||
}
|
||||
});
|
||||
it("Should not accept an initializer when parameter is a rest parameter", function() {
|
||||
var tests = [
|
||||
"(function(...a = b){})()",
|
||||
"(function(a, ...b = [c, d]))"
|
||||
];
|
||||
var test = function(code) {
|
||||
return function () {
|
||||
uglify.parse(code);
|
||||
}
|
||||
}
|
||||
var error = function (e) {
|
||||
return e instanceof uglify.JS_Parse_Error;
|
||||
}
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(test(tests[i]), error, tests[i]);
|
||||
}
|
||||
});
|
||||
it("Shoult not accept duplicated identifiers inside parameters in strict mode or when using default assigment or spread", function() {
|
||||
// From: ES2016 9.2.12 FunctionDeclarationInstantiation (func, argumentsList)
|
||||
// NOTE Early errors ensure that duplicate parameter names can only occur
|
||||
// in non-strict functions that do not have parameter default values or
|
||||
// rest parameters.
|
||||
var tests = [
|
||||
"(function(a = 1, a){})()",
|
||||
"(function(a, [a = 3]){})()",
|
||||
"(function(a, b, c, d, [{e: [...a]}]){})()",
|
||||
"'use strict'; (function(a, a){})",
|
||||
"(function({a, a = b}))",
|
||||
"(function(a, [...a]){})",
|
||||
"(function(a, ...a){})",
|
||||
"(function(a, [a, ...b]){})",
|
||||
"(function(a, {b: a, c: [...d]}){})",
|
||||
"(function(a, a, {b: [...c]}){})"
|
||||
];
|
||||
var test = function(code) {
|
||||
return function () {
|
||||
uglify.parse(code);
|
||||
}
|
||||
}
|
||||
var error = function (e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
/^Parameter [a-zA-Z]+ was used already$/.test(e.message);
|
||||
}
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
assert.throws(test(tests[i]), error, tests[i]);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -71,7 +71,7 @@ describe("Getters and setters", function() {
|
||||
var fail = function(data) {
|
||||
return function (e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error &&
|
||||
e.message === "Unexpected token: operator (" + data.operator + ")";
|
||||
/^Unexpected token: /.test(e.message);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@ describe("bin/uglifyjs with input file globs", function() {
|
||||
});
|
||||
});
|
||||
it("bin/uglifyjs with multiple input file globs.", function(done) {
|
||||
var command = uglifyjscmd + ' "test/input/issue-1242/???.es5" "test/input/issue-1242/*.js" -mc toplevel';
|
||||
var command = uglifyjscmd + ' "test/input/issue-1242/???.es5" "test/input/issue-1242/*.js" -mc toplevel,passes=2';
|
||||
|
||||
exec(command, function(err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, 'var print=console.log.bind(console);print("qux",9,6),print("Foo:",2*11);\n');
|
||||
assert.strictEqual(stdout, 'var print=console.log.bind(console);print("qux",9,6),print("Foo:",22);\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,16 +2,17 @@ var Uglify = require('../../');
|
||||
var assert = require("assert");
|
||||
|
||||
describe("let", function() {
|
||||
it("Should not produce reserved keywords as variable name in mangle", function(done) {
|
||||
this.timeout(10000);
|
||||
|
||||
this.timeout(30000);
|
||||
it("Should not produce reserved keywords as variable name in mangle", function() {
|
||||
// Produce a lot of variables in a function and run it through mangle.
|
||||
var s = '"dddddeeeeelllllooooottttt"; function foo() {';
|
||||
for (var i = 0; i < 18000; i++) {
|
||||
s += "var v" + i + "=0;";
|
||||
}
|
||||
s += '}';
|
||||
var result = Uglify.minify(s, {compress: false});
|
||||
var result = Uglify.minify(s, {
|
||||
compress: false
|
||||
}).code;
|
||||
|
||||
// Verify that select keywords and reserved keywords not produced
|
||||
[
|
||||
@@ -19,7 +20,7 @@ describe("let", function() {
|
||||
"let",
|
||||
"var",
|
||||
].forEach(function(name) {
|
||||
assert.strictEqual(result.code.indexOf("var " + name + "="), -1);
|
||||
assert.strictEqual(result.indexOf("var " + name + "="), -1);
|
||||
});
|
||||
|
||||
// Verify that the variable names that appeared immediately before
|
||||
@@ -30,9 +31,27 @@ describe("let", function() {
|
||||
"eet", "fet",
|
||||
"rar", "oar",
|
||||
].forEach(function(name) {
|
||||
assert.ok(result.code.indexOf("var " + name + "=") >= 0);
|
||||
assert.notStrictEqual(result.indexOf("var " + name + "="), -1);
|
||||
});
|
||||
});
|
||||
it("Should quote mangled properties that are reserved keywords", function() {
|
||||
var s = '"rrrrrnnnnniiiiiaaaaa";';
|
||||
for (var i = 0; i < 18000; i++) {
|
||||
s += "v.b" + i + ";";
|
||||
}
|
||||
var result = Uglify.minify(s, {
|
||||
compress: false,
|
||||
ie8: true,
|
||||
mangle: {
|
||||
properties: true,
|
||||
}
|
||||
}).code;
|
||||
[
|
||||
"in",
|
||||
"var",
|
||||
].forEach(function(name) {
|
||||
assert.notStrictEqual(result.indexOf(name), -1);
|
||||
assert.notStrictEqual(result.indexOf('v["' + name + '"]'), -1);
|
||||
});
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
271
test/mocha/lhs-expressions.js
Normal file
271
test/mocha/lhs-expressions.js
Normal file
@@ -0,0 +1,271 @@
|
||||
var assert = require("assert");
|
||||
var uglify = require("../node");
|
||||
|
||||
describe("Left-hand side expressions", function () {
|
||||
it("Should parse destructuring with const/let/var correctly", function () {
|
||||
var decls = uglify.parse('var {a,b} = foo, { c, d } = bar');
|
||||
|
||||
assert.equal(decls.body[0].TYPE, 'Var');
|
||||
assert.equal(decls.body[0].definitions.length, 2);
|
||||
|
||||
// Item 1
|
||||
assert.equal(decls.body[0].definitions[0].name.TYPE, 'Destructuring');
|
||||
assert.equal(decls.body[0].definitions[0].value.TYPE, 'SymbolRef');
|
||||
|
||||
// Item 2
|
||||
assert.equal(decls.body[0].definitions[1].name.TYPE, 'Destructuring');
|
||||
assert.equal(decls.body[0].definitions[1].value.TYPE, 'SymbolRef');
|
||||
|
||||
var nested_def = uglify.parse('var [{x}] = foo').body[0].definitions[0];
|
||||
|
||||
assert.equal(nested_def.name.names[0].names[0].TYPE, 'ObjectKeyVal');
|
||||
assert.equal(nested_def.name.names[0].names[0].value.TYPE, 'SymbolVar');
|
||||
assert.equal(nested_def.name.names[0].names[0].key, 'x');
|
||||
assert.equal(nested_def.name.names[0].names[0].value.name, 'x');
|
||||
|
||||
var holey_def = uglify.parse('const [,,third] = [1,2,3]').body[0].definitions[0];
|
||||
|
||||
assert.equal(holey_def.name.names[0].TYPE, 'Hole');
|
||||
assert.equal(holey_def.name.names[1].TYPE, 'Hole');
|
||||
assert.equal(holey_def.name.names[2].TYPE, 'SymbolConst');
|
||||
|
||||
var expanding_def = uglify.parse('var [first, ...rest] = [1,2,3]').body[0].definitions[0];
|
||||
|
||||
assert.equal(expanding_def.name.names[0].TYPE, 'SymbolVar');
|
||||
assert.equal(expanding_def.name.names[1].TYPE, 'Expansion');
|
||||
assert.equal(expanding_def.name.names[1].expression.TYPE, 'SymbolVar');
|
||||
});
|
||||
|
||||
it("Parser should use AST_Array for array literals", function() {
|
||||
var ast = uglify.parse('["foo", "bar"]');
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
assert(ast.body[0].body instanceof uglify.AST_Array);
|
||||
|
||||
ast = uglify.parse('a = ["foo"]');
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
|
||||
assert(ast.body[0].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[0].body.left instanceof uglify.AST_SymbolRef);
|
||||
assert.equal(ast.body[0].body.operator, "=");
|
||||
assert(ast.body[0].body.right instanceof uglify.AST_Array);
|
||||
});
|
||||
|
||||
it("Parser should use AST_Object for object literals", function() {
|
||||
var ast = uglify.parse('({foo: "bar"})');
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
assert(ast.body[0].body instanceof uglify.AST_Object);
|
||||
|
||||
// This example should be fine though
|
||||
ast = uglify.parse('a = {foo: "bar"}');
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
|
||||
assert(ast.body[0].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[0].body.left instanceof uglify.AST_SymbolRef);
|
||||
assert.equal(ast.body[0].body.operator, "=");
|
||||
assert(ast.body[0].body.right instanceof uglify.AST_Object);
|
||||
});
|
||||
|
||||
it("Parser should use AST_Destructuring for array assignment patterns", function() {
|
||||
var ast = uglify.parse('[foo, bar] = [1, 2]');
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
|
||||
assert(ast.body[0].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.is_array, true);
|
||||
assert.equal(ast.body[0].body.operator, "=");
|
||||
assert(ast.body[0].body.right instanceof uglify.AST_Array);
|
||||
});
|
||||
|
||||
it("Parser should use AST_Destructuring for object assignment patterns", function() {
|
||||
var ast = uglify.parse('({a: b, b: c} = {b: "c", c: "d"})');
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
|
||||
assert(ast.body[0].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.is_array, false);
|
||||
assert.equal(ast.body[0].body.operator, "=");
|
||||
assert(ast.body[0].body.right instanceof uglify.AST_Object);
|
||||
});
|
||||
|
||||
it("Parser should be able to handle nested destructuring", function() {
|
||||
var ast = uglify.parse('[{a,b},[d, e, f, {g, h}]] = [{a: 1, b: 2}, [3, 4, 5, {g: 6, h: 7}]]');
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
|
||||
assert(ast.body[0].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.is_array, true);
|
||||
assert.equal(ast.body[0].body.operator, "=");
|
||||
assert(ast.body[0].body.right instanceof uglify.AST_Array);
|
||||
|
||||
assert(ast.body[0].body.left.names[0] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.names[0].is_array, false);
|
||||
|
||||
assert(ast.body[0].body.left.names[1] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.names[1].is_array, true);
|
||||
|
||||
assert(ast.body[0].body.left.names[1].names[3] instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.names[1].names[3].is_array, false);
|
||||
});
|
||||
|
||||
it("Should handle spread operator in destructuring", function() {
|
||||
var ast = uglify.parse("[a, b, ...c] = [1, 2, 3, 4, 5]");
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
|
||||
assert(ast.body[0].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.is_array, true);
|
||||
assert.equal(ast.body[0].body.operator, "=");
|
||||
assert(ast.body[0].body.right instanceof uglify.AST_Array);
|
||||
|
||||
assert(ast.body[0].body.left.names[0] instanceof uglify.AST_SymbolRef);
|
||||
assert(ast.body[0].body.left.names[1] instanceof uglify.AST_SymbolRef);
|
||||
|
||||
assert(ast.body[0].body.left.names[2] instanceof uglify.AST_Expansion);
|
||||
});
|
||||
|
||||
it("Should handle default assignments in destructuring", function() {
|
||||
var ast = uglify.parse("({x: v, z = z + 5} = obj);");
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
|
||||
assert(ast.body[0].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.is_array, false);
|
||||
assert.equal(ast.body[0].body.operator, "=");
|
||||
assert(ast.body[0].body.right instanceof uglify.AST_SymbolRef);
|
||||
|
||||
assert(ast.body[0].body.left.names[0].value instanceof uglify.AST_SymbolRef);
|
||||
assert.strictEqual(ast.body[0].body.left.names[0].start.value, "x");
|
||||
|
||||
assert(ast.body[0].body.left.names[1].value instanceof uglify.AST_DefaultAssign);
|
||||
assert.strictEqual(ast.body[0].body.left.names[1].start.value, "z");
|
||||
assert(ast.body[0].body.left.names[1].value.left instanceof uglify.AST_SymbolRef);
|
||||
assert.strictEqual(ast.body[0].body.left.names[1].value.operator, "=");
|
||||
assert(ast.body[0].body.left.names[1].value.right instanceof uglify.AST_Binary);
|
||||
|
||||
|
||||
ast = uglify.parse("({x = 123} = obj);");
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
assert(ast.body[0].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.is_array, false);
|
||||
assert.equal(ast.body[0].body.operator, "=");
|
||||
assert(ast.body[0].body.right instanceof uglify.AST_SymbolRef);
|
||||
|
||||
assert(ast.body[0].body.left.names[0].value instanceof uglify.AST_DefaultAssign);
|
||||
assert.strictEqual(ast.body[0].body.left.names[0].value.operator, "=");
|
||||
assert(ast.body[0].body.left.names[0].value.left instanceof uglify.AST_SymbolRef);
|
||||
|
||||
|
||||
ast = uglify.parse("[x, y = 5] = foo");
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
|
||||
assert(ast.body[0].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.is_array, true);
|
||||
assert.equal(ast.body[0].body.operator, "=");
|
||||
assert(ast.body[0].body.right instanceof uglify.AST_SymbolRef);
|
||||
|
||||
assert(ast.body[0].body.left.names[0] instanceof uglify.AST_SymbolRef);
|
||||
assert.strictEqual(ast.body[0].body.left.names[0].start.value, "x");
|
||||
|
||||
assert(ast.body[0].body.left.names[1] instanceof uglify.AST_DefaultAssign);
|
||||
assert(ast.body[0].body.left.names[1].left instanceof uglify.AST_SymbolRef);
|
||||
assert.strictEqual(ast.body[0].body.left.names[1].start.value, "y");
|
||||
});
|
||||
|
||||
it("Should handle default assignments containing assignments in a destructuring", function() {
|
||||
var ast = uglify.parse("[x, y = z = 2] = a;");
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
|
||||
assert(ast.body[0].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.is_array, true);
|
||||
assert.equal(ast.body[0].body.operator, "=");
|
||||
assert(ast.body[0].body.right instanceof uglify.AST_SymbolRef);
|
||||
|
||||
assert(ast.body[0].body.left.names[0] instanceof uglify.AST_SymbolRef);
|
||||
|
||||
assert(ast.body[0].body.left.names[1] instanceof uglify.AST_DefaultAssign);
|
||||
assert(ast.body[0].body.left.names[1].left instanceof uglify.AST_SymbolRef);
|
||||
assert.equal(ast.body[0].body.left.names[1].operator, "=");
|
||||
assert(ast.body[0].body.left.names[1].right instanceof uglify.AST_Assign);
|
||||
|
||||
assert(ast.body[0].body.left.names[1].right.left instanceof uglify.AST_SymbolRef);
|
||||
assert.equal(ast.body[0].body.left.names[1].right.operator, "=");
|
||||
assert(ast.body[0].body.left.names[1].right.right instanceof uglify.AST_Number);
|
||||
|
||||
ast = uglify.parse("({a: a = 123} = obj)");
|
||||
assert(ast.body[0] instanceof uglify.AST_SimpleStatement);
|
||||
|
||||
assert(ast.body[0].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[0].body.left instanceof uglify.AST_Destructuring);
|
||||
assert.strictEqual(ast.body[0].body.left.is_array, false);
|
||||
assert.equal(ast.body[0].body.operator, "=");
|
||||
assert(ast.body[0].body.right instanceof uglify.AST_SymbolRef);
|
||||
|
||||
assert(ast.body[0].body.left.names[0] instanceof uglify.AST_ObjectProperty);
|
||||
assert.strictEqual(ast.body[0].body.left.names[0].key, "a");
|
||||
assert(ast.body[0].body.left.names[0].value instanceof uglify.AST_DefaultAssign);
|
||||
assert(ast.body[0].body.left.names[0].value.left instanceof uglify.AST_SymbolRef);
|
||||
assert.strictEqual(ast.body[0].body.left.names[0].value.operator, "=");
|
||||
assert(ast.body[0].body.left.names[0].value.right instanceof uglify.AST_Number);
|
||||
});
|
||||
|
||||
it("Should allow multiple spread in array literals", function() {
|
||||
var ast = uglify.parse("var a = [1, 2, 3], b = [4, 5, 6], joined; joined = [...a, ...b]");
|
||||
assert(ast.body[0] instanceof uglify.AST_Var);
|
||||
assert(ast.body[1] instanceof uglify.AST_SimpleStatement);
|
||||
|
||||
// Check statement containing array with spreads
|
||||
assert(ast.body[1].body instanceof uglify.AST_Assign);
|
||||
assert(ast.body[1].body.left instanceof uglify.AST_SymbolRef);
|
||||
assert.equal(ast.body[1].body.operator, "=");
|
||||
assert(ast.body[1].body.right instanceof uglify.AST_Array);
|
||||
|
||||
// Check array content
|
||||
assert.strictEqual(ast.body[1].body.right.elements.length, 2);
|
||||
assert(ast.body[1].body.right.elements[0] instanceof uglify.AST_Expansion);
|
||||
assert(ast.body[1].body.right.elements[0].expression instanceof uglify.AST_SymbolRef);
|
||||
assert(ast.body[1].body.right.elements[0].expression.name, "a");
|
||||
assert(ast.body[1].body.right.elements[1] instanceof uglify.AST_Expansion);
|
||||
assert(ast.body[1].body.right.elements[1].expression instanceof uglify.AST_SymbolRef);
|
||||
assert(ast.body[1].body.right.elements[1].expression.name, "b");
|
||||
});
|
||||
|
||||
it("Should not allow spread on invalid locations", function() {
|
||||
var expect = function(input, expected) {
|
||||
var execute = function(input) {
|
||||
return function() {
|
||||
uglify.parse(input);
|
||||
}
|
||||
}
|
||||
var check = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
e.message === expected;
|
||||
}
|
||||
|
||||
assert.throws(execute(input), check);
|
||||
}
|
||||
|
||||
// Spreads are not allowed in destructuring array if it's not the last element
|
||||
expect("[...a, ...b] = [1, 2, 3, 4]", "Spread must the be last element in destructuring array");
|
||||
|
||||
// Multiple spreads are not allowed in destructuring array
|
||||
expect("[...a, ...b] = [1, 2, 3, 4]", "Spread must the be last element in destructuring array");
|
||||
|
||||
// Array spread must be last in destructuring declaration
|
||||
expect("let [ ...x, a ] = o;", "Rest element must be last element");
|
||||
|
||||
// Only one spread per destructuring array declaration
|
||||
expect("let [ a, ...x, ...y ] = o;", "Rest element must be last element");
|
||||
|
||||
// Spread in block should not be allowed
|
||||
expect("{...a} = foo", "Unexpected token: expand (...)");
|
||||
|
||||
// Object spread must be last in destructuring declaration
|
||||
expect("let { ...x, a } = o;", "Rest element must be last element");
|
||||
|
||||
// Only one spread per destructuring declaration
|
||||
expect("let { a, ...x, ...y } = o;", "Rest element must be last element");
|
||||
});
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user