Compare commits
305 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff526be61d | ||
|
|
e005099fb1 | ||
|
|
504a436e9d | ||
|
|
3ca902258c | ||
|
|
fd0951231c | ||
|
|
9e29b6dad2 | ||
|
|
c391576d52 | ||
|
|
ac73c5d421 | ||
|
|
547f41beba | ||
|
|
daaefc17b9 | ||
|
|
1d407e761e | ||
|
|
2b44f4ae30 | ||
|
|
e51c3541da | ||
|
|
3bf194684b | ||
|
|
aae7d49d0c | ||
|
|
0459af2ecc | ||
|
|
04f2344efc | ||
|
|
bad9d5cf88 | ||
|
|
a0f5f862df | ||
|
|
41996be86f | ||
|
|
5fd8244a2e | ||
|
|
c14e280585 | ||
|
|
bc3fa78e8c | ||
|
|
8c7c107765 | ||
|
|
3dd328dce3 | ||
|
|
014f428153 | ||
|
|
a3b2eb75bd | ||
|
|
da295de82b | ||
|
|
4f8ca4626e | ||
|
|
e54748365c | ||
|
|
2d99d06601 | ||
|
|
98cf95e5b5 | ||
|
|
7313465cba | ||
|
|
2c7ee956fd | ||
|
|
ecf3563c45 | ||
|
|
dee5a27516 | ||
|
|
5a25d24b56 | ||
|
|
bffdc8dca8 | ||
|
|
69b5663653 | ||
|
|
ea9289771b | ||
|
|
2cb55b2ad0 | ||
|
|
bbb5f2a89c | ||
|
|
76d19b60ad | ||
|
|
9e62628171 | ||
|
|
9bf72cf758 | ||
|
|
64d74432f6 | ||
|
|
45ce369480 | ||
|
|
ca32a09032 | ||
|
|
6f954aa3d0 | ||
|
|
f05d4f7af3 | ||
|
|
88e7a542cd | ||
|
|
4dcff038cb | ||
|
|
b4b9305db0 | ||
|
|
28cfb65c47 | ||
|
|
0f4f01b66c | ||
|
|
5d9f1da3ab | ||
|
|
d1aa09c5c7 | ||
|
|
6d5f341999 | ||
|
|
4ffb6fce76 | ||
|
|
71a8d0d236 | ||
|
|
1a498db2d3 | ||
|
|
44dfa5a318 | ||
|
|
251ff1d1af | ||
|
|
ec443e422c | ||
|
|
32deb365d5 | ||
|
|
2244743545 | ||
|
|
04b8964505 | ||
|
|
d6fbc365e2 | ||
|
|
9a978843f5 | ||
|
|
0479ff0c54 | ||
|
|
cf72fe552f | ||
|
|
a1532eb076 | ||
|
|
c2a1bceb77 | ||
|
|
e3c9c22c75 | ||
|
|
0f4cd73dcc | ||
|
|
281e882d27 | ||
|
|
cc6aa3e5ac | ||
|
|
e869779a98 | ||
|
|
06cdb74279 | ||
|
|
ff289b90a9 | ||
|
|
9b6bc67c33 | ||
|
|
4b90dc1fdb | ||
|
|
951770fc68 | ||
|
|
48b3fe9952 | ||
|
|
a400741868 | ||
|
|
59a4e56bc8 | ||
|
|
1f1fccc45d | ||
|
|
b7f6b73f4e | ||
|
|
9469c03ac9 | ||
|
|
d57527697f | ||
|
|
f7ca4f2297 | ||
|
|
c076e7b60d | ||
|
|
4a55bb0be5 | ||
|
|
28ecea50a6 | ||
|
|
9a311705f5 | ||
|
|
ee3fe0f4cd | ||
|
|
87f6e1b091 | ||
|
|
c934fc8142 | ||
|
|
257ddc3bdb | ||
|
|
1ddc05725d | ||
|
|
e6b76a4879 | ||
|
|
a0c3836ba0 | ||
|
|
f8a71b56fd | ||
|
|
11e9bdc427 | ||
|
|
a84564d1a8 | ||
|
|
c595b84032 | ||
|
|
7cb1adf455 | ||
|
|
7bea38a05d | ||
|
|
0f910ee25c | ||
|
|
beb9659778 | ||
|
|
f1a833a7aa | ||
|
|
2e41cd6394 | ||
|
|
09f77c7d4d | ||
|
|
fef0bf9ee0 | ||
|
|
ae740b933f | ||
|
|
ec7f37f314 | ||
|
|
eb48a035e7 | ||
|
|
6ab3224c0d | ||
|
|
c909ffb715 | ||
|
|
f71f4905b0 | ||
|
|
fb177a6312 | ||
|
|
65da9acce6 | ||
|
|
67d0237f73 | ||
|
|
984a21704e | ||
|
|
aa3f647656 | ||
|
|
c526da59a1 | ||
|
|
581630e0a7 | ||
|
|
f5952933a0 | ||
|
|
f001e4cb9d | ||
|
|
57ce5bd9e0 | ||
|
|
861a79ac9f | ||
|
|
00996afd2c | ||
|
|
e76fb354eb | ||
|
|
3276740779 | ||
|
|
5509e51098 | ||
|
|
94f84727ce | ||
|
|
8a4f86528f | ||
|
|
adb0e882e9 | ||
|
|
f83d370f57 | ||
|
|
b19aa58cff | ||
|
|
0a65de89b9 | ||
|
|
6e86ee950d | ||
|
|
8ca2401ebe | ||
|
|
491f16c766 | ||
|
|
a30092e20f | ||
|
|
b1abe92e1a | ||
|
|
b454ce667e | ||
|
|
32283a0def | ||
|
|
ac51d4c5a0 | ||
|
|
0432a7abb9 | ||
|
|
f3a1694a41 | ||
|
|
2e0dc97003 | ||
|
|
701035621d | ||
|
|
79334dda10 | ||
|
|
e918748d88 | ||
|
|
6b2f34769a | ||
|
|
48ffbef51d | ||
|
|
c0f3feae9f | ||
|
|
a00040dd93 | ||
|
|
ee95c1b38b | ||
|
|
4bceb85cbf | ||
|
|
30a75049f5 | ||
|
|
a3cc3a9b87 | ||
|
|
96f8befdd7 | ||
|
|
cd58635dcc | ||
|
|
274331d0ea | ||
|
|
0489d6de64 | ||
|
|
fb092839c2 | ||
|
|
b7c112eefe | ||
|
|
b2b8a0d386 | ||
|
|
ac40301813 | ||
|
|
3563d8c09e | ||
|
|
5ae04b3545 | ||
|
|
a80b228d8b | ||
|
|
cf4bf4ceb1 | ||
|
|
8223b2e0db | ||
|
|
381bd3836e | ||
|
|
919d5e3482 | ||
|
|
e3a3db73ae | ||
|
|
d9344f30b8 | ||
|
|
be80f7e706 | ||
|
|
cf45e2f79b | ||
|
|
8354758f30 | ||
|
|
9e6b128374 | ||
|
|
93cdb194f4 | ||
|
|
b633706ce4 | ||
|
|
e9920f7ca1 | ||
|
|
7e465d4a01 | ||
|
|
aa80ee349d | ||
|
|
80e81765cf | ||
|
|
711f88dcb4 | ||
|
|
344d11d591 | ||
|
|
c7cdcf06a6 | ||
|
|
3ee55748d4 | ||
|
|
dedbeeff15 | ||
|
|
bd6dee52ab | ||
|
|
144052ca49 | ||
|
|
65c848cc6f | ||
|
|
8a8a94a596 | ||
|
|
8153b7bd8a | ||
|
|
d787d70127 | ||
|
|
3ac2421932 | ||
|
|
a9fc9ddc33 | ||
|
|
a5d62a3fc6 | ||
|
|
067e5a5762 | ||
|
|
33b5f31984 | ||
|
|
35a849dc48 | ||
|
|
b70591be1a | ||
|
|
b33e7f88e6 | ||
|
|
1f0333e9f1 | ||
|
|
eb98a7f2f3 | ||
|
|
78d1bb92d4 | ||
|
|
ea9ab9fb0e | ||
|
|
ce54c9ccee | ||
|
|
07accd2fbb | ||
|
|
18059cc94f | ||
|
|
b5e0e8c203 | ||
|
|
e5cb9275df | ||
|
|
17b81350d4 | ||
|
|
4d63d4f5b3 | ||
|
|
70d72ad806 | ||
|
|
fe9227a41b | ||
|
|
b49e142a26 | ||
|
|
ee3b39b909 | ||
|
|
9699ffb1af | ||
|
|
fdc9b9413b | ||
|
|
40ceddb48a | ||
|
|
7aa69117e1 | ||
|
|
bff7ad67bb | ||
|
|
c2334baa48 | ||
|
|
fb2b6c7c6f | ||
|
|
f5cbe19b75 | ||
|
|
b34fa11a13 | ||
|
|
320984c5f5 | ||
|
|
4365a51237 | ||
|
|
858e6c78a4 | ||
|
|
0b0296eb2a | ||
|
|
872270b149 | ||
|
|
b1c593a041 | ||
|
|
13be50a4a9 | ||
|
|
16cd5d57a5 | ||
|
|
834f9f3924 | ||
|
|
cf0951f726 | ||
|
|
852f78491a | ||
|
|
229e42cdee | ||
|
|
4e49302916 | ||
|
|
1e51586996 | ||
|
|
d48a3080ac | ||
|
|
26fbeece1c | ||
|
|
8898b8a0fe | ||
|
|
ec64acd2c8 | ||
|
|
ac0b61ed6e | ||
|
|
c06a50f338 | ||
|
|
09f9ae2de9 | ||
|
|
7e6331bb39 | ||
|
|
e275148998 | ||
|
|
974247c8c0 | ||
|
|
a0f4fd390a | ||
|
|
b8b133d91a | ||
|
|
c525a2b190 | ||
|
|
6ffbecb72b | ||
|
|
f0ff6189be | ||
|
|
6b3c49e458 | ||
|
|
f584ca8d07 | ||
|
|
ae4db00991 | ||
|
|
100307ab31 | ||
|
|
148047fbbf | ||
|
|
d11dca3cf9 | ||
|
|
e5badb9541 | ||
|
|
fa668a28b4 | ||
|
|
686a496b1c | ||
|
|
11676f9d72 | ||
|
|
dd31d12a91 | ||
|
|
eb55d8a9bb | ||
|
|
81f1df14d7 | ||
|
|
7f8d72d9d3 | ||
|
|
1eaa211e09 | ||
|
|
0610c020b1 | ||
|
|
0d7d4918eb | ||
|
|
48284844a4 | ||
|
|
ec2e5fa3a2 | ||
|
|
da17766ddd | ||
|
|
0913db8c84 | ||
|
|
5c7705fcad | ||
|
|
f6372483a0 | ||
|
|
98f330658f | ||
|
|
a7b3b0d3a5 | ||
|
|
0a35acbbe7 | ||
|
|
2a9989dd18 | ||
|
|
79b98a9fe8 | ||
|
|
057de570e6 | ||
|
|
557b3e412f | ||
|
|
8d74f34373 | ||
|
|
266ddd9639 | ||
|
|
e51c6ba380 | ||
|
|
6389e52305 | ||
|
|
e05510f3bc | ||
|
|
fc9804b909 | ||
|
|
4761d07e0b | ||
|
|
0111497fc9 | ||
|
|
7d8dea3b26 | ||
|
|
25fc02743a | ||
|
|
0bd8053524 | ||
|
|
1a78bbcd23 | ||
|
|
8430123e9d |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.js text eol=lf
|
||||||
20
.github/ISSUE_TEMPLATE.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
**Bug report or feature request?**
|
||||||
|
|
||||||
|
<!-- Note: sub-optimal but correct code is not a bug -->
|
||||||
|
|
||||||
|
**ES5 or ES6+ input?**
|
||||||
|
|
||||||
|
<!-- Note: for ES6 see: https://github.com/mishoo/UglifyJS2/tree/harmony#harmony -->
|
||||||
|
|
||||||
|
**Uglify version (`uglifyjs -V`)**
|
||||||
|
|
||||||
|
**JavaScript input** <!-- ideally as small as possible -->
|
||||||
|
|
||||||
|
**The `uglifyjs` CLI command executed or `minify()` options used.**
|
||||||
|
|
||||||
|
**JavaScript output or error produced.**
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Note: `uglify-js` only supports ES5.
|
||||||
|
Those wishing to minify ES6 should use `uglify-es`.
|
||||||
|
-->
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
before_install: "npm install -g npm"
|
before_install: "npm install -g npm"
|
||||||
node_js:
|
node_js:
|
||||||
- "0.12"
|
|
||||||
- "0.10"
|
- "0.10"
|
||||||
|
- "0.12"
|
||||||
- "4"
|
- "4"
|
||||||
- "6"
|
- "6"
|
||||||
|
env:
|
||||||
|
- UGLIFYJS_TEST_ALL=1
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|||||||
722
README.md
722
README.md
@@ -1,14 +1,15 @@
|
|||||||
UglifyJS 2
|
UglifyJS 3
|
||||||
==========
|
==========
|
||||||
[](https://travis-ci.org/mishoo/UglifyJS2)
|
[](https://travis-ci.org/mishoo/UglifyJS2)
|
||||||
|
|
||||||
UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit.
|
UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
|
||||||
|
|
||||||
This page documents the command line utility. For
|
#### Note:
|
||||||
[API and internals documentation see my website](http://lisperator.net/uglifyjs/).
|
- **`uglify-js@3.x` has a simplified API and CLI that is not backwards compatible with [`uglify-js@2.x`](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
|
||||||
There's also an
|
- **Documentation for UglifyJS `2.x` releases can be found [here](https://github.com/mishoo/UglifyJS2/tree/v2.x)**.
|
||||||
[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,
|
- `uglify-js` only supports ECMAScript 5 (ES5).
|
||||||
Chrome and probably Safari).
|
- Those wishing to minify
|
||||||
|
ES2015+ (ES6+) should use the `npm` package [**uglify-es**](https://github.com/mishoo/UglifyJS2/tree/harmony).
|
||||||
|
|
||||||
Install
|
Install
|
||||||
-------
|
-------
|
||||||
@@ -24,25 +25,18 @@ From NPM for programmatic use:
|
|||||||
|
|
||||||
npm install uglify-js
|
npm install uglify-js
|
||||||
|
|
||||||
From Git:
|
|
||||||
|
|
||||||
git clone git://github.com/mishoo/UglifyJS2.git
|
|
||||||
cd UglifyJS2
|
|
||||||
npm link .
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
uglifyjs [input files] [options]
|
uglifyjs [input files] [options]
|
||||||
|
|
||||||
UglifyJS2 can take multiple input files. It's recommended that you pass the
|
UglifyJS can take multiple input files. It's recommended that you pass the
|
||||||
input files first, then pass the options. UglifyJS will parse input files
|
input files first, then pass the options. UglifyJS will parse input files
|
||||||
in sequence and apply any compression options. The files are parsed in the
|
in sequence and apply any compression options. The files are parsed in the
|
||||||
same global scope, that is, a reference from a file to some
|
same global scope, that is, a reference from a file to some
|
||||||
variable/function declared in another file will be matched properly.
|
variable/function declared in another file will be matched properly.
|
||||||
|
|
||||||
If you want to read from STDIN instead, pass a single dash instead of input
|
If no input file is specified, UglifyJS will read from STDIN.
|
||||||
files.
|
|
||||||
|
|
||||||
If you wish to pass your options before the input files, separate the two with
|
If you wish to pass your options before the input files, separate the two with
|
||||||
a double dash to prevent input files being used as option arguments:
|
a double dash to prevent input files being used as option arguments:
|
||||||
@@ -52,103 +46,97 @@ a double dash to prevent input files being used as option arguments:
|
|||||||
The available options are:
|
The available options are:
|
||||||
|
|
||||||
```
|
```
|
||||||
--source-map Specify an output file where to generate source
|
-h, --help Print usage information.
|
||||||
map.
|
-V, --version Print version number.
|
||||||
--source-map-root The path to the original source to be included
|
-p, --parse <options> Specify parser options:
|
||||||
in the source map.
|
`acorn` Use Acorn for parsing.
|
||||||
--source-map-url The path to the source map to be added in //#
|
`bare_returns` Allow return outside of functions.
|
||||||
sourceMappingURL. Defaults to the value passed
|
Useful when minifying CommonJS
|
||||||
with --source-map.
|
modules and Userscripts that may
|
||||||
--source-map-include-sources Pass this flag if you want to include the
|
be anonymous function wrapped (IIFE)
|
||||||
content of source files in the source map as
|
by the .user.js engine `caller`.
|
||||||
sourcesContent property.
|
`expression` Parse a single expression, rather than
|
||||||
--in-source-map Input source map, useful if you're compressing
|
a program (for parsing JSON).
|
||||||
JS that was generated from some other original
|
`spidermonkey` Assume input files are SpiderMonkey
|
||||||
code.
|
AST format (as JSON).
|
||||||
--screw-ie8 Use this flag if you don't wish to support
|
-c, --compress [options] Enable compressor/specify compressor options:
|
||||||
Internet Explorer 6-8 quirks.
|
`pure_funcs` List of functions that can be safely
|
||||||
By default UglifyJS will not try to be IE-proof.
|
removed when their return values are
|
||||||
--support-ie8 Use this flag to support Internet Explorer 6-8 quirks.
|
not used.
|
||||||
Note: may break standards compliant `catch` identifiers.
|
-m, --mangle [options] Mangle names/specify mangler options:
|
||||||
--expr Parse a single expression, rather than a
|
`reserved` List of names that should not be mangled.
|
||||||
program (for parsing JSON)
|
--mangle-props [options] Mangle properties/specify mangler options:
|
||||||
-p, --prefix Skip prefix for original filenames that appear
|
`builtins` Mangle property names that overlaps
|
||||||
in source maps. For example -p 3 will drop 3
|
with standard JavaScript globals.
|
||||||
directories from file names and ensure they are
|
`debug` Add debug prefix and suffix.
|
||||||
relative paths. You can also specify -p
|
`domprops` Mangle property names that overlaps
|
||||||
relative, which will make UglifyJS figure out
|
with DOM properties.
|
||||||
itself the relative paths between original
|
`keep_quoted` Only mangle unquoted properies.
|
||||||
sources, the source map and the output file.
|
`regex` Only mangle matched property names.
|
||||||
-o, --output Output file (default STDOUT).
|
`reserved` List of names that should not be mangled.
|
||||||
-b, --beautify Beautify output/specify output options.
|
-b, --beautify [options] Beautify output/specify output options:
|
||||||
-m, --mangle Mangle names/pass mangler options.
|
`beautify` Enabled with `--beautify` by default.
|
||||||
-r, --reserved Reserved names to exclude from mangling.
|
`preamble` Preamble to prepend to the output. You
|
||||||
-c, --compress Enable compressor/pass compressor options. Pass
|
can use this to insert a comment, for
|
||||||
options like -c
|
example for licensing information.
|
||||||
hoist_vars=false,if_return=false. Use -c with
|
This will not be parsed, but the source
|
||||||
no argument to use the default compression
|
map will adjust for its presence.
|
||||||
options.
|
`quote_style` Quote style:
|
||||||
-d, --define Global definitions
|
0 - auto
|
||||||
-e, --enclose Embed everything in a big function, with a
|
1 - single
|
||||||
configurable parameter/argument list.
|
2 - double
|
||||||
--comments Preserve copyright comments in the output. By
|
3 - original
|
||||||
|
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
|
||||||
|
want to disable `negate_iife` under
|
||||||
|
compressor options.
|
||||||
|
-o, --output <file> Output file path (default STDOUT). Specify `ast` or
|
||||||
|
`spidermonkey` to write UglifyJS or SpiderMonkey AST
|
||||||
|
as JSON to STDOUT respectively.
|
||||||
|
--comments [filter] Preserve copyright comments in the output. By
|
||||||
default this works like Google Closure, keeping
|
default this works like Google Closure, keeping
|
||||||
JSDoc-style comments that contain "@license" or
|
JSDoc-style comments that contain "@license" or
|
||||||
"@preserve". You can optionally pass one of the
|
"@preserve". You can optionally pass one of the
|
||||||
following arguments to this flag:
|
following arguments to this flag:
|
||||||
- "all" to keep all comments
|
- "all" to keep all comments
|
||||||
- a valid JS regexp (needs to start with a
|
- a valid JS RegExp like `/foo/` or `/^!/` to
|
||||||
slash) to keep only comments that match.
|
keep only matching comments.
|
||||||
Note that currently not *all* comments can be
|
Note that currently not *all* comments can be
|
||||||
kept when compression is on, because of dead
|
kept when compression is on, because of dead
|
||||||
code removal or cascading statements into
|
code removal or cascading statements into
|
||||||
sequences.
|
sequences.
|
||||||
--preamble Preamble to prepend to the output. You can use
|
--config-file <file> Read `minify()` options from JSON file.
|
||||||
this to insert a comment, for example for
|
-d, --define <expr>[=value] Global definitions.
|
||||||
licensing information. This will not be
|
--ie8 Support non-standard Internet Explorer 8.
|
||||||
parsed, but the source map will adjust for its
|
Equivalent to setting `ie8: true` in `minify()`
|
||||||
presence.
|
for `compress`, `mangle` and `output` options.
|
||||||
--stats Display operations run time on STDERR.
|
By default UglifyJS will not try to be IE-proof.
|
||||||
--acorn Use Acorn for parsing.
|
--keep-fnames Do not mangle/drop function names. Useful for
|
||||||
--spidermonkey Assume input files are SpiderMonkey AST format
|
code relying on Function.prototype.name.
|
||||||
(as JSON).
|
--name-cache File to hold mangled name mappings.
|
||||||
--self Build itself (UglifyJS2) as a library (implies
|
--self Build UglifyJS as a library (implies --wrap UglifyJS)
|
||||||
--wrap=UglifyJS --export-all)
|
--source-map [options] Enable source map/specify source map options:
|
||||||
--wrap Embed everything in a big function, making the
|
`base` Path to compute relative paths from input files.
|
||||||
|
`content` Input source map, useful if you're compressing
|
||||||
|
JS that was generated from some other original
|
||||||
|
code. Specify "inline" if the source map is
|
||||||
|
included within the sources.
|
||||||
|
`filename` Name and/or location of the output source.
|
||||||
|
`includeSources` Pass this flag if you want to include
|
||||||
|
the content of source files in the
|
||||||
|
source map as sourcesContent property.
|
||||||
|
`root` Path to the original source to be included in
|
||||||
|
the source map.
|
||||||
|
`url` If specified, path to the source map to append in
|
||||||
|
`//# sourceMappingURL`.
|
||||||
|
--stats Display operations run time on STDERR.
|
||||||
|
--toplevel Compress and/or mangle variables in toplevel scope.
|
||||||
|
--verbose Print diagnostic messages.
|
||||||
|
--warn Print warning messages.
|
||||||
|
--wrap <name> Embed everything in a big function, making the
|
||||||
“exports” and “global” variables available. You
|
“exports” and “global” variables available. You
|
||||||
need to pass an argument to this option to
|
need to pass an argument to this option to
|
||||||
specify the name that your module will take
|
specify the name that your module will take
|
||||||
when included in, say, a browser.
|
when included in, say, a browser.
|
||||||
--export-all Only used when --wrap, this tells UglifyJS to
|
|
||||||
add code to automatically export all globals.
|
|
||||||
--lint Display some scope warnings
|
|
||||||
-v, --verbose Verbose
|
|
||||||
-V, --version Print version number and exit.
|
|
||||||
--noerr Don't throw an error for unknown options in -c,
|
|
||||||
-b or -m.
|
|
||||||
--bare-returns Allow return outside of functions. Useful when
|
|
||||||
minifying CommonJS modules and Userscripts that
|
|
||||||
may be anonymous function wrapped (IIFE) by the
|
|
||||||
.user.js engine `caller`.
|
|
||||||
--keep-fnames Do not mangle/drop function names. Useful for
|
|
||||||
code relying on Function.prototype.name.
|
|
||||||
--reserved-file File containing reserved names
|
|
||||||
--reserve-domprops Make (most?) DOM properties reserved for
|
|
||||||
--mangle-props
|
|
||||||
--mangle-props Mangle property names (default `0`). Set to
|
|
||||||
`true` or `1` to mangle all property names. Set
|
|
||||||
to `unquoted` or `2` to only mangle unquoted
|
|
||||||
property names. Mode `2` also enables the
|
|
||||||
`keep_quoted_props` beautifier option to
|
|
||||||
preserve the quotes around property names and
|
|
||||||
disables the `properties` compressor option to
|
|
||||||
prevent rewriting quoted properties with dot
|
|
||||||
notation. You can override these by setting
|
|
||||||
them explicitly on the command line.
|
|
||||||
--mangle-regex Only mangle property names matching the regex
|
|
||||||
--name-cache File to hold mangled names mappings
|
|
||||||
--pure-funcs List of functions that can be safely removed if
|
|
||||||
their return value is not used [array]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Specify `--output` (`-o`) to declare the output file. Otherwise the output
|
Specify `--output` (`-o`) to declare the output file. Otherwise the output
|
||||||
@@ -156,25 +144,26 @@ goes to STDOUT.
|
|||||||
|
|
||||||
## Source map options
|
## Source map options
|
||||||
|
|
||||||
UglifyJS2 can generate a source map file, which is highly useful for
|
UglifyJS can generate a source map file, which is highly useful for
|
||||||
debugging your compressed JavaScript. To get a source map, pass
|
debugging your compressed JavaScript. To get a source map, pass
|
||||||
`--source-map output.js.map` (full path to the file where you want the
|
`--source-map --output output.js` (source map will be written out to
|
||||||
source map dumped).
|
`output.js.map`).
|
||||||
|
|
||||||
Additionally you might need `--source-map-root` to pass the URL where the
|
Additional options:
|
||||||
original files can be found. In case you are passing full paths to input
|
|
||||||
files to UglifyJS, you can use `--prefix` (`-p`) to specify the number of
|
- `--source-map filename=<NAME>` to specify the name of the source map.
|
||||||
directories to drop from the path prefix when declaring files in the source
|
|
||||||
map.
|
- `--source-map root=<URL>` to pass the URL where the original files 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:
|
For example:
|
||||||
|
|
||||||
uglifyjs /home/doe/work/foo/src/js/file1.js \
|
uglifyjs js/file1.js js/file2.js \
|
||||||
/home/doe/work/foo/src/js/file2.js \
|
-o foo.min.js -c -m \
|
||||||
-o foo.min.js \
|
--source-map root="http://foo.com/src",url=foo.min.js.map
|
||||||
--source-map foo.min.js.map \
|
|
||||||
--source-map-root http://foo.com/src \
|
|
||||||
-p 5 -c -m
|
|
||||||
|
|
||||||
The above will compress and mangle `file1.js` and `file2.js`, will drop the
|
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
|
output in `foo.min.js` and the source map in `foo.min.js.map`. The source
|
||||||
@@ -193,10 +182,9 @@ CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →
|
|||||||
compressed JS by mapping every token in the compiled JS to its original
|
compressed JS by mapping every token in the compiled JS to its original
|
||||||
location.
|
location.
|
||||||
|
|
||||||
To use this feature you need to pass `--in-source-map
|
To use this feature pass `--source-map content="/path/to/input/source.map"`
|
||||||
/path/to/input/source.map`. Normally the input source map should also point
|
or `--source-map content=inline` if the source map is included inline with
|
||||||
to the file containing the generated JS, so if that's correct you can omit
|
the sources.
|
||||||
input files from the command line.
|
|
||||||
|
|
||||||
## Mangler options
|
## Mangler options
|
||||||
|
|
||||||
@@ -210,10 +198,10 @@ To enable the mangler you need to pass `--mangle` (`-m`). The following
|
|||||||
(disabled by default).
|
(disabled by default).
|
||||||
|
|
||||||
When mangling is enabled but you want to prevent certain names from being
|
When mangling is enabled but you want to prevent certain names from being
|
||||||
mangled, you can declare those names with `--reserved` (`-r`) — pass a
|
mangled, you can declare those names with `--mangle reserved` — pass a
|
||||||
comma-separated list of names. For example:
|
comma-separated list of names. For example:
|
||||||
|
|
||||||
uglifyjs ... -m -r '$,require,exports'
|
uglifyjs ... -m reserved=[$,require,exports]
|
||||||
|
|
||||||
to prevent the `require`, `exports` and `$` names from being changed.
|
to prevent the `require`, `exports` and `$` names from being changed.
|
||||||
|
|
||||||
@@ -238,39 +226,22 @@ console.log(x.something());
|
|||||||
In the above code, `foo`, `bar`, `baz`, `moo` and `boo` will be replaced
|
In the above code, `foo`, `bar`, `baz`, `moo` and `boo` will be replaced
|
||||||
with single characters, while `something()` will be left as is.
|
with single characters, while `something()` will be left as is.
|
||||||
|
|
||||||
In order for this to be of any use, we should avoid mangling standard JS
|
In order for this to be of any use, we avoid mangling standard JS names by
|
||||||
names. For instance, if your code would contain `x.length = 10`, then
|
default (`--mangle-props builtins` to override).
|
||||||
`length` becomes a candidate for mangling and it will be mangled throughout
|
|
||||||
the code, regardless if it's being used as part of your own objects or
|
|
||||||
accessing an array's length. To avoid that, you can use `--reserved-file`
|
|
||||||
to pass a filename that should contain the names to be excluded from
|
|
||||||
mangling. This file can be used both for excluding variable names and
|
|
||||||
property names. It could look like this, for example:
|
|
||||||
|
|
||||||
```js
|
|
||||||
{
|
|
||||||
"vars": [ "define", "require", ... ],
|
|
||||||
"props": [ "length", "prototype", ... ]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`--reserved-file` can be an array of file names (either a single
|
|
||||||
comma-separated argument, or you can pass multiple `--reserved-file`
|
|
||||||
arguments) — in this case it will exclude names from all those files.
|
|
||||||
|
|
||||||
A default exclusion file is provided in `tools/domprops.json` which should
|
A default exclusion file is provided in `tools/domprops.json` which should
|
||||||
cover most standard JS and DOM properties defined in various browsers. Pass
|
cover most standard JS and DOM properties defined in various browsers. Pass
|
||||||
`--reserve-domprops` to read that in.
|
`--mangle-props domprops` to disable this feature.
|
||||||
|
|
||||||
You can also use a regular expression to define which property names should be
|
You can also use a regular expression to define which property names should be
|
||||||
mangled. For example, `--mangle-regex="/^_/"` will only mangle property names
|
mangled. For example, `--mangle-props regex=/^_/` will only mangle property
|
||||||
that start with an underscore.
|
names that start with an underscore.
|
||||||
|
|
||||||
When you compress multiple files using this option, in order for them to
|
When you compress multiple files using this option, in order for them to
|
||||||
work together in the end we need to ensure somehow that one property gets
|
work together in the end we need to ensure somehow that one property gets
|
||||||
mangled to the same name in all of them. For this, pass `--name-cache
|
mangled to the same name in all of them. For this, pass `--name-cache filename.json`
|
||||||
filename.json` and UglifyJS will maintain these mappings in a file which can
|
and UglifyJS will maintain these mappings in a file which can then be reused.
|
||||||
then be reused. It should be initially empty. Example:
|
It should be initially empty. Example:
|
||||||
|
|
||||||
```
|
```
|
||||||
rm -f /tmp/cache.json # start fresh
|
rm -f /tmp/cache.json # start fresh
|
||||||
@@ -284,6 +255,32 @@ of mangled property names.
|
|||||||
Using the name cache is not necessary if you compress all your files in a
|
Using the name cache is not necessary if you compress all your files in a
|
||||||
single call to UglifyJS.
|
single call to UglifyJS.
|
||||||
|
|
||||||
|
#### Mangling unquoted names (`--mangle-props keep_quoted`)
|
||||||
|
|
||||||
|
Using quoted property name (`o["foo"]`) reserves the property name (`foo`)
|
||||||
|
so that it is not mangled throughout the entire script even when used in an
|
||||||
|
unquoted style (`o.foo`). Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ echo 'var o={"foo":1, bar:3}; o.foo += o.bar; console.log(o.foo);' | uglifyjs --mangle-props keep_quoted -mc
|
||||||
|
var o={foo:1,a:3};o.foo+=o.a,console.log(o.foo);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Debugging property name mangling
|
||||||
|
|
||||||
|
You can also pass `--mangle-props debug` in order to mangle property names
|
||||||
|
without completely obscuring them. For example the property `o.foo`
|
||||||
|
would mangle to `o._$foo$_` with this option. This allows property mangling
|
||||||
|
of a large codebase while still being able to debug the code and identify
|
||||||
|
where mangling is breaking things.
|
||||||
|
|
||||||
|
You can also pass a custom suffix using `--mangle-props debug=XYZ`. This would then
|
||||||
|
mangle `o.foo` to `o._$foo$XYZ_`. You can change this each time you compile a
|
||||||
|
script to identify how a property got mangled. One technique is to pass a
|
||||||
|
random number on every compile to simulate mangling changing with different
|
||||||
|
inputs (e.g. as you update the input script with new properties), and to help
|
||||||
|
identify mistakes like writing mangled keys to storage.
|
||||||
|
|
||||||
## Compressor options
|
## Compressor options
|
||||||
|
|
||||||
You need to pass `--compress` (`-c`) to enable the compressor. Optionally
|
You need to pass `--compress` (`-c`) to enable the compressor. Optionally
|
||||||
@@ -316,6 +313,12 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
|||||||
comparison are switching. Compression only works if both `comparisons` and
|
comparison are switching. Compression only works if both `comparisons` and
|
||||||
`unsafe_comps` are both set to true.
|
`unsafe_comps` are both set to true.
|
||||||
|
|
||||||
|
- `unsafe_math` (default: false) -- optimize numerical expressions like
|
||||||
|
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
||||||
|
|
||||||
|
- `unsafe_proto` (default: false) -- optimize expressions like
|
||||||
|
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
||||||
|
|
||||||
- `conditionals` -- apply optimizations for `if`-s and conditional
|
- `conditionals` -- apply optimizations for `if`-s and conditional
|
||||||
expressions
|
expressions
|
||||||
|
|
||||||
@@ -331,7 +334,15 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
|||||||
- `loops` -- optimizations for `do`, `while` and `for` loops when we can
|
- `loops` -- optimizations for `do`, `while` and `for` loops when we can
|
||||||
statically determine the condition
|
statically determine the condition
|
||||||
|
|
||||||
- `unused` -- drop unreferenced functions and variables
|
- `unused` -- drop unreferenced functions and variables (simple direct variable
|
||||||
|
assignments do not count as references unless set to `"keep_assign"`)
|
||||||
|
|
||||||
|
- `toplevel` -- drop unreferenced functions (`"funcs"`) and/or variables (`"vars"`)
|
||||||
|
in the toplevel scope (`false` by default, `true` to drop both unreferenced
|
||||||
|
functions and variables)
|
||||||
|
|
||||||
|
- `top_retain` -- prevent specific toplevel functions and variables from `unused`
|
||||||
|
removal (can be array, comma-separated, RegExp or function. Implies `toplevel`)
|
||||||
|
|
||||||
- `hoist_funs` -- hoist function declarations
|
- `hoist_funs` -- hoist function declarations
|
||||||
|
|
||||||
@@ -345,8 +356,11 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
|||||||
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
||||||
and `x = something(), x` into `x = something()`
|
and `x = something(), x` into `x = something()`
|
||||||
|
|
||||||
- `collapse_vars` -- default `false`. Collapse single-use `var` and `const`
|
- `collapse_vars` -- Collapse single-use `var` and `const` definitions
|
||||||
definitions when possible.
|
when possible.
|
||||||
|
|
||||||
|
- `reduce_vars` -- Improve optimization on variables assigned with and
|
||||||
|
used as constant values.
|
||||||
|
|
||||||
- `warnings` -- display warnings when dropping unreachable code or unused
|
- `warnings` -- display warnings when dropping unreachable code or unused
|
||||||
declarations etc.
|
declarations etc.
|
||||||
@@ -358,6 +372,8 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
|||||||
- `pure_getters` -- the default is `false`. If you pass `true` for
|
- `pure_getters` -- the default is `false`. If you pass `true` for
|
||||||
this, UglifyJS will assume that object property access
|
this, UglifyJS will assume that object property access
|
||||||
(e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
|
(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`.
|
||||||
|
|
||||||
- `pure_funcs` -- default `null`. You can pass an array of names and
|
- `pure_funcs` -- default `null`. You can pass an array of names and
|
||||||
UglifyJS will assume that those functions do not produce side
|
UglifyJS will assume that those functions do not produce side
|
||||||
@@ -371,7 +387,12 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
|||||||
overhead (compression will be slower).
|
overhead (compression will be slower).
|
||||||
|
|
||||||
- `drop_console` -- default `false`. Pass `true` to discard calls to
|
- `drop_console` -- default `false`. Pass `true` to discard calls to
|
||||||
`console.*` functions.
|
`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.
|
||||||
|
|
||||||
|
- `expression` -- default `false`. Pass `true` to preserve completion values
|
||||||
|
from terminal statements without `return`, e.g. in bookmarklets.
|
||||||
|
|
||||||
- `keep_fargs` -- default `true`. Prevents the
|
- `keep_fargs` -- default `true`. Prevents the
|
||||||
compressor from discarding unused function arguments. You need this
|
compressor from discarding unused function arguments. You need this
|
||||||
@@ -381,9 +402,18 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
|||||||
compressor from discarding function names. Useful for code relying on
|
compressor from discarding function names. Useful for code relying on
|
||||||
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
|
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
|
||||||
|
|
||||||
- `passes` -- default `1`. Number of times to run compress. Use an
|
- `passes` -- default `1`. Number of times to run compress with a maximum of 3.
|
||||||
integer argument larger than 1 to further reduce code size in some cases.
|
In some cases more than one pass leads to further compressed code. Keep in
|
||||||
Note: raising the number of passes will increase uglify compress time.
|
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 `false`. Pass `true` to potentially drop 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()`;
|
||||||
|
|
||||||
|
|
||||||
### The `unsafe` option
|
### The `unsafe` option
|
||||||
|
|
||||||
@@ -413,6 +443,8 @@ if (DEBUG) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can specify nested constants in the form of `--define env.DEBUG=false`.
|
||||||
|
|
||||||
UglifyJS will warn about the condition being always false and about dropping
|
UglifyJS will warn about the condition being always false and about dropping
|
||||||
unreachable code; for now there is no option to turn off only this specific
|
unreachable code; for now there is no option to turn off only this specific
|
||||||
warning, you can pass `warnings=false` to turn off *all* warnings.
|
warning, you can pass `warnings=false` to turn off *all* warnings.
|
||||||
@@ -423,8 +455,6 @@ separate file and include it into the build. For example you can have a
|
|||||||
```javascript
|
```javascript
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
const PRODUCTION = true;
|
const PRODUCTION = true;
|
||||||
// Alternative for environments that don't support `const`
|
|
||||||
/** @const */ var STAGING = false;
|
|
||||||
// etc.
|
// etc.
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -435,16 +465,15 @@ and build your code like this:
|
|||||||
UglifyJS will notice the constants and, since they cannot be altered, it
|
UglifyJS will notice the constants and, since they cannot be altered, it
|
||||||
will evaluate references to them to the value itself and drop unreachable
|
will evaluate references to them to the value itself and drop unreachable
|
||||||
code as usual. The build will contain the `const` declarations if you use
|
code as usual. The build will contain the `const` declarations if you use
|
||||||
them. If you are targeting < ES6 environments, use `/** @const */ var`.
|
them. If you are targeting < ES6 environments which does not support `const`,
|
||||||
|
using `var` with `reduce_vars` (enabled by default) should suffice.
|
||||||
<a name="codegen-options"></a>
|
|
||||||
|
|
||||||
#### Conditional compilation, API
|
#### Conditional compilation, API
|
||||||
You can also use conditional compilation via the programmatic API. With the difference that the
|
You can also use conditional compilation via the programmatic API. With the difference that the
|
||||||
property name is `global_defs` and is a compressor property:
|
property name is `global_defs` and is a compressor property:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
uglifyJS.minify([ "input.js"], {
|
uglifyJS.minify(fs.readFileSync("input.js", "utf8"), {
|
||||||
compress: {
|
compress: {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
global_defs: {
|
global_defs: {
|
||||||
@@ -464,21 +493,21 @@ can pass additional arguments that control the code output:
|
|||||||
Passing `-b` will set this to true, but you might need to pass `-b` even
|
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
|
when you want to generate minified code, in order to specify additional
|
||||||
arguments, so you can use `-b beautify=false` to override it.
|
arguments, so you can use `-b beautify=false` to override it.
|
||||||
- `indent-level` (default 4)
|
- `indent_level` (default 4)
|
||||||
- `indent-start` (default 0) -- prefix all lines by that many spaces
|
- `indent_start` (default 0) -- prefix all lines by that many spaces
|
||||||
- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal
|
- `quote_keys` (default `false`) -- pass `true` to quote all keys in literal
|
||||||
objects
|
objects
|
||||||
- `space-colon` (default `true`) -- insert a space after the colon signs
|
- `space_colon` (default `true`) -- insert a space after the colon signs
|
||||||
- `ascii-only` (default `false`) -- escape Unicode characters in strings and
|
- `ascii_only` (default `false`) -- escape Unicode characters in strings and
|
||||||
regexps (affects directives with non-ascii characters becoming invalid)
|
regexps (affects directives with non-ascii characters becoming invalid)
|
||||||
- `inline-script` (default `false`) -- escape the slash in occurrences of
|
- `inline_script` (default `false`) -- escape the slash in occurrences of
|
||||||
`</script` in strings
|
`</script` in strings
|
||||||
- `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
|
specifies an (orientative) line width that the beautifier will try to
|
||||||
obey. It refers to the width of the line text (excluding indentation).
|
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
|
It doesn't work very well currently, but it does make the code generated
|
||||||
by UglifyJS more readable.
|
by UglifyJS more readable.
|
||||||
- `max-line-len` (default 32000) -- maximum line length (for uglified code)
|
- `max_line_len` (default 32000) -- maximum line length (for uglified code)
|
||||||
- `bracketize` (default `false`) -- always insert brackets in `if`, `for`,
|
- `bracketize` (default `false`) -- always insert brackets in `if`, `for`,
|
||||||
`do`, `while` or `with` statements, even if their body is a single
|
`do`, `while` or `with` statements, even if their body is a single
|
||||||
statement.
|
statement.
|
||||||
@@ -506,8 +535,8 @@ You can pass `--comments` to retain certain comments in the output. By
|
|||||||
default it will keep JSDoc-style comments that contain "@preserve",
|
default it will keep JSDoc-style comments that contain "@preserve",
|
||||||
"@license" or "@cc_on" (conditional compilation for IE). You can pass
|
"@license" or "@cc_on" (conditional compilation for IE). You can pass
|
||||||
`--comments all` to keep all the comments, or a valid JavaScript regexp to
|
`--comments all` to keep all the comments, or a valid JavaScript regexp to
|
||||||
keep only comments that match this regexp. For example `--comments
|
keep only comments that match this regexp. For example `--comments /^!/`
|
||||||
'/foo|bar/'` will keep only comments that contain "foo" or "bar".
|
will keep comments like `/*! Copyright Notice */`.
|
||||||
|
|
||||||
Note, however, that there might be situations where comments are lost. For
|
Note, however, that there might be situations where comments are lost. For
|
||||||
example:
|
example:
|
||||||
@@ -530,7 +559,7 @@ needs to be kept in the output) are comments attached to toplevel nodes.
|
|||||||
|
|
||||||
## Support for the SpiderMonkey AST
|
## Support for the SpiderMonkey AST
|
||||||
|
|
||||||
UglifyJS2 has its own abstract syntax tree format; for
|
UglifyJS has its own abstract syntax tree format; for
|
||||||
[practical reasons](http://lisperator.net/blog/uglifyjs-why-not-switching-to-spidermonkey-ast/)
|
[practical reasons](http://lisperator.net/blog/uglifyjs-why-not-switching-to-spidermonkey-ast/)
|
||||||
we can't easily change to using the SpiderMonkey AST internally. However,
|
we can't easily change to using the SpiderMonkey AST internally. However,
|
||||||
UglifyJS now has a converter which can import a SpiderMonkey AST.
|
UglifyJS now has a converter which can import a SpiderMonkey AST.
|
||||||
@@ -540,54 +569,22 @@ SpiderMonkey AST. It has a small CLI utility that parses one file and dumps
|
|||||||
the AST in JSON on the standard output. To use UglifyJS to mangle and
|
the AST in JSON on the standard output. To use UglifyJS to mangle and
|
||||||
compress that:
|
compress that:
|
||||||
|
|
||||||
acorn file.js | uglifyjs --spidermonkey -m -c
|
acorn file.js | uglifyjs -p spidermonkey -m -c
|
||||||
|
|
||||||
The `--spidermonkey` option tells UglifyJS that all input files are not
|
The `-p spidermonkey` option tells UglifyJS that all input files are not
|
||||||
JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we
|
JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we
|
||||||
don't use our own parser in this case, but just transform that AST into our
|
don't use our own parser in this case, but just transform that AST into our
|
||||||
internal AST.
|
internal AST.
|
||||||
|
|
||||||
### Use Acorn for parsing
|
### Use Acorn for parsing
|
||||||
|
|
||||||
More for fun, I added the `--acorn` option which will use Acorn to do all
|
More for fun, I added the `-p acorn` option which will use Acorn to do all
|
||||||
the parsing. If you pass this option, UglifyJS will `require("acorn")`.
|
the parsing. If you pass this option, UglifyJS will `require("acorn")`.
|
||||||
|
|
||||||
Acorn is really fast (e.g. 250ms instead of 380ms on some 650K code), but
|
Acorn is really fast (e.g. 250ms instead of 380ms on some 650K code), but
|
||||||
converting the SpiderMonkey tree that Acorn produces takes another 150ms so
|
converting the SpiderMonkey tree that Acorn produces takes another 150ms so
|
||||||
in total it's a bit more than just using UglifyJS's own parser.
|
in total it's a bit more than just using UglifyJS's own parser.
|
||||||
|
|
||||||
### Using UglifyJS to transform SpiderMonkey AST
|
|
||||||
|
|
||||||
Now you can use UglifyJS as any other intermediate tool for transforming
|
|
||||||
JavaScript ASTs in SpiderMonkey format.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
function uglify(ast, options, mangle) {
|
|
||||||
// Conversion from SpiderMonkey AST to internal format
|
|
||||||
var uAST = UglifyJS.AST_Node.from_mozilla_ast(ast);
|
|
||||||
|
|
||||||
// Compression
|
|
||||||
uAST.figure_out_scope();
|
|
||||||
uAST = uAST.transform(UglifyJS.Compressor(options));
|
|
||||||
|
|
||||||
// Mangling (optional)
|
|
||||||
if (mangle) {
|
|
||||||
uAST.figure_out_scope();
|
|
||||||
uAST.compute_char_frequency();
|
|
||||||
uAST.mangle_names();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Back-conversion to SpiderMonkey AST
|
|
||||||
return uAST.to_mozilla_ast();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Check out
|
|
||||||
[original blog post](http://rreverser.com/using-mozilla-ast-with-uglifyjs/)
|
|
||||||
for details.
|
|
||||||
|
|
||||||
API Reference
|
API Reference
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@@ -597,98 +594,73 @@ like this:
|
|||||||
var UglifyJS = require("uglify-js");
|
var UglifyJS = require("uglify-js");
|
||||||
```
|
```
|
||||||
|
|
||||||
It exports a lot of names, but I'll discuss here the basics that are needed
|
There is a single toplevel function, `minify(files, options)`, which will
|
||||||
for parsing, mangling and compressing a piece of code. The sequence is (1)
|
performs all the steps in a configurable manner.
|
||||||
parse, (2) compress, (3) mangle, (4) generate output code.
|
|
||||||
|
|
||||||
### The simple way
|
|
||||||
|
|
||||||
There's a single toplevel function which combines all the steps. If you
|
|
||||||
don't need additional customization, you might want to go with `minify`.
|
|
||||||
Example:
|
Example:
|
||||||
```javascript
|
```javascript
|
||||||
var result = UglifyJS.minify("/path/to/file.js");
|
var result = UglifyJS.minify("var b = function() {};");
|
||||||
console.log(result.code); // minified output
|
console.log(result.code); // minified output
|
||||||
// if you need to pass code instead of file name
|
console.log(result.error); // runtime error
|
||||||
var result = UglifyJS.minify("var b = function () {};", {fromString: true});
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also compress multiple files:
|
You can also compress multiple files:
|
||||||
```javascript
|
```javascript
|
||||||
var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ]);
|
var result = UglifyJS.minify({
|
||||||
|
"file1.js": "var a = function() {};",
|
||||||
|
"file2.js": "var b = function() {};"
|
||||||
|
});
|
||||||
console.log(result.code);
|
console.log(result.code);
|
||||||
```
|
```
|
||||||
|
|
||||||
To generate a source map:
|
To generate a source map:
|
||||||
```javascript
|
```javascript
|
||||||
var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ], {
|
var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, {
|
||||||
outSourceMap: "out.js.map"
|
sourceMap: {
|
||||||
|
filename: "out.js",
|
||||||
|
url: "out.js.map"
|
||||||
|
}
|
||||||
});
|
});
|
||||||
console.log(result.code); // minified output
|
console.log(result.code); // minified output
|
||||||
console.log(result.map);
|
console.log(result.map); // source map
|
||||||
```
|
|
||||||
|
|
||||||
To generate a source map with the fromString option, you can also use an object:
|
|
||||||
```javascript
|
|
||||||
var result = UglifyJS.minify({"file1.js": "var a = function () {};"}, {
|
|
||||||
outSourceMap: "out.js.map",
|
|
||||||
fromString: true
|
|
||||||
});
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the source map is not saved in a file, it's just returned in
|
Note that the source map is not saved in a file, it's just returned in
|
||||||
`result.map`. The value passed for `outSourceMap` is only used to set the
|
`result.map`. The value passed for `sourceMap.url` is only used to set
|
||||||
`file` attribute in the source map (see [the spec][sm-spec]).
|
`//# sourceMappingURL=out.js.map` in `result.code`. The value of
|
||||||
|
`filename` is only used to set `file` attribute (see [the spec][sm-spec])
|
||||||
|
in source map file.
|
||||||
|
|
||||||
|
You can set option `sourceMap.url` to be `"inline"` and source map will
|
||||||
|
be appended to code.
|
||||||
|
|
||||||
You can also specify sourceRoot property to be included in source map:
|
You can also specify sourceRoot property to be included in source map:
|
||||||
```javascript
|
```javascript
|
||||||
var result = UglifyJS.minify([ "file1.js", "file2.js", "file3.js" ], {
|
var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, {
|
||||||
outSourceMap: "out.js.map",
|
sourceMap: {
|
||||||
sourceRoot: "http://example.com/src"
|
root: "http://example.com/src",
|
||||||
|
url: "out.js.map"
|
||||||
|
}
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
If you're compressing compiled JavaScript and have a source map for it, you
|
If you're compressing compiled JavaScript and have a source map for it, you
|
||||||
can use the `inSourceMap` argument:
|
can use `sourceMap.content`:
|
||||||
```javascript
|
```javascript
|
||||||
var result = UglifyJS.minify("compiled.js", {
|
var result = UglifyJS.minify({"compiled.js": "compiled code"}, {
|
||||||
inSourceMap: "compiled.js.map",
|
sourceMap: {
|
||||||
outSourceMap: "minified.js.map"
|
content: "content from compiled.js.map",
|
||||||
|
url: "minified.js.map"
|
||||||
|
}
|
||||||
});
|
});
|
||||||
// same as before, it returns `code` and `map`
|
// same as before, it returns `code` and `map`
|
||||||
```
|
```
|
||||||
|
|
||||||
If your input source map is not in a file, you can pass it in as an object
|
If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.url`.
|
||||||
using the `inSourceMap` argument:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var result = UglifyJS.minify("compiled.js", {
|
|
||||||
inSourceMap: JSON.parse(my_source_map_string),
|
|
||||||
outSourceMap: "minified.js.map"
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
The `inSourceMap` is only used if you also request `outSourceMap` (it makes
|
|
||||||
no sense otherwise).
|
|
||||||
|
|
||||||
To set the source map url, use the `sourceMapUrl` option.
|
|
||||||
If you're using the X-SourceMap header instead, you can just set the `sourceMapUrl` option to false.
|
|
||||||
Defaults to outSourceMap:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var result = UglifyJS.minify([ "file1.js" ], {
|
|
||||||
outSourceMap: "out.js.map",
|
|
||||||
sourceMapUrl: "localhost/out.js.map"
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
Other options:
|
Other options:
|
||||||
|
|
||||||
- `warnings` (default `false`) — pass `true` to display compressor warnings.
|
- `warnings` (default `false`) — pass `true` to display compressor warnings.
|
||||||
|
|
||||||
- `fromString` (default `false`) — if you pass `true` then you can pass
|
|
||||||
JavaScript source code, rather than file names.
|
|
||||||
|
|
||||||
- `mangle` (default `true`) — pass `false` to skip mangling names, or pass
|
- `mangle` (default `true`) — pass `false` to skip mangling names, or pass
|
||||||
an object to specify mangling options (see below).
|
an object to specify mangling options (see below).
|
||||||
|
|
||||||
@@ -696,212 +668,58 @@ Other options:
|
|||||||
mangle property options.
|
mangle property options.
|
||||||
|
|
||||||
- `output` (default `null`) — pass an object if you wish to specify
|
- `output` (default `null`) — pass an object if you wish to specify
|
||||||
additional [output options][codegen]. The defaults are optimized
|
additional [output options](#beautifier-options). The defaults are optimized
|
||||||
for best compression.
|
for best compression.
|
||||||
|
|
||||||
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
|
- `compress` (default `{}`) — pass `false` to skip compressing entirely.
|
||||||
Pass an object to specify custom [compressor options][compressor].
|
Pass an object to specify custom [compressor options](#compressor-options).
|
||||||
|
|
||||||
- `parse` (default {}) — pass an object if you wish to specify some
|
- `parse` (default {}) — pass an object if you wish to specify some
|
||||||
additional [parser options][parser]. (not all options available... see below)
|
additional [parser options](#the-parser).
|
||||||
|
|
||||||
##### mangle
|
##### mangle
|
||||||
|
|
||||||
- `except` - pass an array of identifiers that should be excluded from mangling
|
- `reserved` - pass an array of identifiers that should be excluded from mangling
|
||||||
|
|
||||||
- `toplevel` — mangle names declared in the toplevel scope (disabled by
|
- `toplevel` — mangle names declared in the toplevel scope (disabled by
|
||||||
default).
|
default).
|
||||||
|
|
||||||
- `eval` — mangle names visible in scopes where eval or with are used
|
- `eval` — mangle names visible in scopes where eval or with are used
|
||||||
(disabled by default).
|
(disabled by default).
|
||||||
|
|
||||||
- `keep_fnames` -- default `false`. Pass `true` to not mangle
|
- `keep_fnames` -- default `false`. Pass `true` to not mangle
|
||||||
function names. Useful for code relying on `Function.prototype.name`.
|
function names. Useful for code relying on `Function.prototype.name`.
|
||||||
See also: the `keep_fnames` [compress option](#compressor-options).
|
See also: the `keep_fnames` [compress option](#compressor-options).
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
//tst.js
|
// test.js
|
||||||
var globalVar;
|
var globalVar;
|
||||||
function funcName(firstLongName, anotherLongName)
|
function funcName(firstLongName, anotherLongName)
|
||||||
{
|
{
|
||||||
var myVariable = firstLongName + anotherLongName;
|
var myVariable = firstLongName + anotherLongName;
|
||||||
}
|
}
|
||||||
|
```
|
||||||
UglifyJS.minify("tst.js").code;
|
|
||||||
// 'function funcName(a,n){}var globalVar;'
|
|
||||||
|
|
||||||
UglifyJS.minify("tst.js", { mangle: { except: ['firstLongName'] } }).code;
|
|
||||||
// 'function funcName(firstLongName,a){}var globalVar;'
|
|
||||||
|
|
||||||
UglifyJS.minify("tst.js", { mangle: { toplevel: true } }).code;
|
|
||||||
// 'function n(n,a){}var a;'
|
|
||||||
```
|
|
||||||
|
|
||||||
##### mangleProperties options
|
|
||||||
|
|
||||||
- `regex` — Pass a RegExp to only mangle certain names (maps to the `--mangle-regex` CLI arguments option)
|
|
||||||
- `ignore_quoted` – Only mangle unquoted property names (maps to the `--mangle-props 2` CLI arguments option)
|
|
||||||
|
|
||||||
We could add more options to `UglifyJS.minify` — if you need additional
|
|
||||||
functionality please suggest!
|
|
||||||
|
|
||||||
### The hard way
|
|
||||||
|
|
||||||
Following there's more detailed API info, in case the `minify` function is
|
|
||||||
too simple for your needs.
|
|
||||||
|
|
||||||
#### The parser
|
|
||||||
```javascript
|
```javascript
|
||||||
var toplevel_ast = UglifyJS.parse(code, options);
|
var code = fs.readFileSync("test.js", "utf8");
|
||||||
|
|
||||||
|
UglifyJS.minify(code).code;
|
||||||
|
// 'function funcName(a,n){}var globalVar;'
|
||||||
|
|
||||||
|
UglifyJS.minify(code, { mangle: { reserved: ['firstLongName'] } }).code;
|
||||||
|
// 'function funcName(firstLongName,a){}var globalVar;'
|
||||||
|
|
||||||
|
UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
|
||||||
|
// 'function n(n,a){}var a;'
|
||||||
```
|
```
|
||||||
|
|
||||||
`options` is optional and if present it must be an object. The following
|
##### mangle.properties options
|
||||||
properties are available:
|
|
||||||
|
|
||||||
- `strict` — disable automatic semicolon insertion and support for trailing
|
- `regex` — Pass a RegExp to only mangle certain names
|
||||||
comma in arrays and objects
|
- `keep_quoted` — Only mangle unquoted property names
|
||||||
- `bare_returns` — Allow return outside of functions. (maps to the
|
- `debug` — Mangle names with the original name still present. Defaults to `false`.
|
||||||
`--bare-returns` CLI arguments option and available to `minify` `parse`
|
Pass an empty string to enable, or a non-empty string to set the suffix.
|
||||||
other options object)
|
|
||||||
- `filename` — the name of the file where this code is coming from
|
|
||||||
- `toplevel` — a `toplevel` node (as returned by a previous invocation of
|
|
||||||
`parse`)
|
|
||||||
|
|
||||||
The last two options are useful when you'd like to minify multiple files and
|
[acorn]: https://github.com/ternjs/acorn
|
||||||
get a single file as the output and a proper source map. Our CLI tool does
|
[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k
|
||||||
something like this:
|
|
||||||
```javascript
|
|
||||||
var toplevel = null;
|
|
||||||
files.forEach(function(file){
|
|
||||||
var code = fs.readFileSync(file, "utf8");
|
|
||||||
toplevel = UglifyJS.parse(code, {
|
|
||||||
filename: file,
|
|
||||||
toplevel: toplevel
|
|
||||||
});
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
After this, we have in `toplevel` a big AST containing all our files, with
|
|
||||||
each token having proper information about where it came from.
|
|
||||||
|
|
||||||
#### Scope information
|
|
||||||
|
|
||||||
UglifyJS contains a scope analyzer that you need to call manually before
|
|
||||||
compressing or mangling. Basically it augments various nodes in the AST
|
|
||||||
with information about where is a name defined, how many times is a name
|
|
||||||
referenced, if it is a global or not, if a function is using `eval` or the
|
|
||||||
`with` statement etc. I will discuss this some place else, for now what's
|
|
||||||
important to know is that you need to call the following before doing
|
|
||||||
anything with the tree:
|
|
||||||
```javascript
|
|
||||||
toplevel.figure_out_scope()
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Compression
|
|
||||||
|
|
||||||
Like this:
|
|
||||||
```javascript
|
|
||||||
var compressor = UglifyJS.Compressor(options);
|
|
||||||
var compressed_ast = toplevel.transform(compressor);
|
|
||||||
```
|
|
||||||
|
|
||||||
The `options` can be missing. Available options are discussed above in
|
|
||||||
“Compressor options”. Defaults should lead to best compression in most
|
|
||||||
scripts.
|
|
||||||
|
|
||||||
The compressor is destructive, so don't rely that `toplevel` remains the
|
|
||||||
original tree.
|
|
||||||
|
|
||||||
#### Mangling
|
|
||||||
|
|
||||||
After compression it is a good idea to call again `figure_out_scope` (since
|
|
||||||
the compressor might drop unused variables / unreachable code and this might
|
|
||||||
change the number of identifiers or their position). Optionally, you can
|
|
||||||
call a trick that helps after Gzip (counting character frequency in
|
|
||||||
non-mangleable words). Example:
|
|
||||||
```javascript
|
|
||||||
compressed_ast.figure_out_scope();
|
|
||||||
compressed_ast.compute_char_frequency();
|
|
||||||
compressed_ast.mangle_names();
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Generating output
|
|
||||||
|
|
||||||
AST nodes have a `print` method that takes an output stream. Essentially,
|
|
||||||
to generate code you do this:
|
|
||||||
```javascript
|
|
||||||
var stream = UglifyJS.OutputStream(options);
|
|
||||||
compressed_ast.print(stream);
|
|
||||||
var code = stream.toString(); // this is your minified code
|
|
||||||
```
|
|
||||||
|
|
||||||
or, for a shortcut you can do:
|
|
||||||
```javascript
|
|
||||||
var code = compressed_ast.print_to_string(options);
|
|
||||||
```
|
|
||||||
|
|
||||||
As usual, `options` is optional. The output stream accepts a lot of options,
|
|
||||||
most of them documented above in section “Beautifier options”. The two
|
|
||||||
which we care about here are `source_map` and `comments`.
|
|
||||||
|
|
||||||
#### Keeping comments in the output
|
|
||||||
|
|
||||||
In order to keep certain comments in the output you need to pass the
|
|
||||||
`comments` option. Pass a RegExp or a function. If you pass a RegExp, only
|
|
||||||
those comments whose body matches the regexp will be kept. Note that body
|
|
||||||
means without the initial `//` or `/*`. If you pass a function, it will be
|
|
||||||
called for every comment in the tree and will receive two arguments: the
|
|
||||||
node that the comment is attached to, and the comment token itself.
|
|
||||||
|
|
||||||
The comment token has these properties:
|
|
||||||
|
|
||||||
- `type`: "comment1" for single-line comments or "comment2" for multi-line
|
|
||||||
comments
|
|
||||||
- `value`: the comment body
|
|
||||||
- `pos` and `endpos`: the start/end positions (zero-based indexes) in the
|
|
||||||
original code where this comment appears
|
|
||||||
- `line` and `col`: the line and column where this comment appears in the
|
|
||||||
original code
|
|
||||||
- `file` — the file name of the original file
|
|
||||||
- `nlb` — true if there was a newline before this comment in the original
|
|
||||||
code, or if this comment contains a newline.
|
|
||||||
|
|
||||||
Your function should return `true` to keep the comment, or a falsy value
|
|
||||||
otherwise.
|
|
||||||
|
|
||||||
#### Generating a source mapping
|
|
||||||
|
|
||||||
You need to pass the `source_map` argument when calling `print`. It needs
|
|
||||||
to be a `SourceMap` object (which is a thin wrapper on top of the
|
|
||||||
[source-map][source-map] library).
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```javascript
|
|
||||||
var source_map = UglifyJS.SourceMap(source_map_options);
|
|
||||||
var stream = UglifyJS.OutputStream({
|
|
||||||
...
|
|
||||||
source_map: source_map
|
|
||||||
});
|
|
||||||
compressed_ast.print(stream);
|
|
||||||
|
|
||||||
var code = stream.toString();
|
|
||||||
var map = source_map.toString(); // json output for your source map
|
|
||||||
```
|
|
||||||
|
|
||||||
The `source_map_options` (optional) can contain the following properties:
|
|
||||||
|
|
||||||
- `file`: the name of the JavaScript output file that this mapping refers to
|
|
||||||
- `root`: the `sourceRoot` property (see the [spec][sm-spec])
|
|
||||||
- `orig`: the "original source map", handy when you compress generated JS
|
|
||||||
and want to map the minified output back to the original code where it
|
|
||||||
came from. It can be simply a string in JSON, or a JSON object containing
|
|
||||||
the original source map.
|
|
||||||
|
|
||||||
[acorn]: https://github.com/ternjs/acorn
|
|
||||||
[source-map]: https://github.com/mozilla/source-map
|
|
||||||
[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
|
|
||||||
[codegen]: http://lisperator.net/uglifyjs/codegen
|
|
||||||
[compressor]: http://lisperator.net/uglifyjs/compress
|
|
||||||
[parser]: http://lisperator.net/uglifyjs/parser
|
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
#! /usr/bin/env node
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var U2 = require("../tools/node");
|
|
||||||
var fs = require("fs");
|
|
||||||
var yargs = require("yargs");
|
|
||||||
var ARGS = yargs
|
|
||||||
.describe("o", "Output file")
|
|
||||||
.argv;
|
|
||||||
var files = ARGS._.slice();
|
|
||||||
var output = {
|
|
||||||
vars: {},
|
|
||||||
props: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ARGS.o) try {
|
|
||||||
output = JSON.parse(fs.readFileSync(ARGS.o, "utf8"));
|
|
||||||
} catch(ex) {}
|
|
||||||
|
|
||||||
files.forEach(getProps);
|
|
||||||
|
|
||||||
if (ARGS.o) {
|
|
||||||
fs.writeFileSync(ARGS.o, JSON.stringify(output, null, 2), "utf8");
|
|
||||||
} else {
|
|
||||||
console.log("%s", JSON.stringify(output, null, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getProps(filename) {
|
|
||||||
var code = fs.readFileSync(filename, "utf8");
|
|
||||||
var ast = U2.parse(code);
|
|
||||||
|
|
||||||
ast.walk(new U2.TreeWalker(function(node){
|
|
||||||
if (node instanceof U2.AST_ObjectKeyVal) {
|
|
||||||
add(node.key);
|
|
||||||
}
|
|
||||||
else if (node instanceof U2.AST_ObjectProperty) {
|
|
||||||
add(node.key.name);
|
|
||||||
}
|
|
||||||
else if (node instanceof U2.AST_Dot) {
|
|
||||||
add(node.property);
|
|
||||||
}
|
|
||||||
else if (node instanceof U2.AST_Sub) {
|
|
||||||
addStrings(node.property);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
function addStrings(node) {
|
|
||||||
var out = {};
|
|
||||||
try {
|
|
||||||
(function walk(node){
|
|
||||||
node.walk(new U2.TreeWalker(function(node){
|
|
||||||
if (node instanceof U2.AST_Seq) {
|
|
||||||
walk(node.cdr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof U2.AST_String) {
|
|
||||||
add(node.value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node instanceof U2.AST_Conditional) {
|
|
||||||
walk(node.consequent);
|
|
||||||
walk(node.alternative);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
throw out;
|
|
||||||
}));
|
|
||||||
})(node);
|
|
||||||
} catch(ex) {
|
|
||||||
if (ex !== out) throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function add(name) {
|
|
||||||
output.props[name] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
899
bin/uglifyjs
899
bin/uglifyjs
@@ -3,592 +3,383 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var UglifyJS = require("../tools/node");
|
// workaround for tty output truncation upon process.exit()
|
||||||
var sys = require("util");
|
[process.stdout, process.stderr].forEach(function(stream){
|
||||||
var yargs = require("yargs");
|
if (stream._handle && stream._handle.setBlocking)
|
||||||
|
stream._handle.setBlocking(true);
|
||||||
|
});
|
||||||
|
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
|
var info = require("../package.json");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var async = require("async");
|
var program = require("commander");
|
||||||
var acorn;
|
var UglifyJS = require("../tools/node");
|
||||||
var screw_ie8 = true;
|
|
||||||
var ARGS = yargs
|
|
||||||
.usage("$0 input1.js [input2.js ...] [options]\n\
|
|
||||||
Use a single dash to read input from the standard input.\
|
|
||||||
\n\n\
|
|
||||||
NOTE: by default there is no mangling/compression.\n\
|
|
||||||
Without [options] it will simply parse input files and dump the AST\n\
|
|
||||||
with whitespace and comments discarded. To achieve compression and\n\
|
|
||||||
mangling you need to use `-c` and `-m`.\
|
|
||||||
")
|
|
||||||
.describe("source-map", "Specify an output file where to generate source map.")
|
|
||||||
.describe("source-map-root", "The path to the original source to be included in the source map.")
|
|
||||||
.describe("source-map-url", "The path to the source map to be added in //# sourceMappingURL. Defaults to the value passed with --source-map.")
|
|
||||||
.describe("source-map-include-sources", "Pass this flag if you want to include the content of source files in the source map as sourcesContent property.")
|
|
||||||
.describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
|
|
||||||
.describe("screw-ie8", "Do not support Internet Explorer 6-8 quirks. This flag is enabled by default.")
|
|
||||||
.describe("support-ie8", "Support non-standard Internet Explorer 6-8 javascript. Note: may break standards compliant `catch` identifiers.")
|
|
||||||
.describe("expr", "Parse a single expression, rather than a program (for parsing JSON)")
|
|
||||||
.describe("p", "Skip prefix for original filenames that appear in source maps. \
|
|
||||||
For example -p 3 will drop 3 directories from file names and ensure they are relative paths. \
|
|
||||||
You can also specify -p relative, which will make UglifyJS figure out itself the relative paths between original sources, \
|
|
||||||
the source map and the output file.")
|
|
||||||
.describe("o", "Output file (default STDOUT).")
|
|
||||||
.describe("b", "Beautify output/specify output options.")
|
|
||||||
.describe("m", "Mangle names/pass mangler options.")
|
|
||||||
.describe("r", "Reserved names to exclude from mangling.")
|
|
||||||
.describe("c", "Enable compressor/pass compressor options. \
|
|
||||||
Pass options like -c hoist_vars=false,if_return=false. \
|
|
||||||
Use -c with no argument to use the default compression options.")
|
|
||||||
.describe("d", "Global definitions")
|
|
||||||
.describe("e", "Embed everything in a big function, with a configurable parameter/argument list.")
|
|
||||||
|
|
||||||
.describe("comments", "Preserve copyright comments in the output. \
|
var skip_keys = [ "cname", "enclosed", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
|
||||||
By default this works like Google Closure, keeping JSDoc-style comments that contain \"@license\" or \"@preserve\". \
|
var files = {};
|
||||||
You can optionally pass one of the following arguments to this flag:\n\
|
var options = {
|
||||||
- \"all\" to keep all comments\n\
|
compress: false,
|
||||||
- a valid JS regexp (needs to start with a slash) to keep only comments that match.\n\
|
mangle: false
|
||||||
\
|
};
|
||||||
Note that currently not *all* comments can be kept when compression is on, \
|
program._name = info.name;
|
||||||
because of dead code removal or cascading statements into sequences.")
|
program.version(info.version);
|
||||||
|
program.parseArgv = program.parse;
|
||||||
.describe("preamble", "Preamble to prepend to the output. You can use this to insert a \
|
program.parse = undefined;
|
||||||
comment, for example for licensing information. This will not be \
|
program.option("-p, --parse <options>", "Specify parser options.", parse_js("parse", true));
|
||||||
parsed, but the source map will adjust for its presence.")
|
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));
|
||||||
.describe("stats", "Display operations run time on STDERR.")
|
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js("mangle-props", true));
|
||||||
.describe("acorn", "Use Acorn for parsing.")
|
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js("beautify", true));
|
||||||
.describe("spidermonkey", "Assume input files are SpiderMonkey AST format (as JSON).")
|
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
||||||
.describe("self", "Build itself (UglifyJS2) as a library (implies --wrap=UglifyJS --export-all)")
|
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
||||||
.describe("wrap", "Embed everything in a big function, making the “exports” and “global” variables available. \
|
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
||||||
You need to pass an argument to this option to specify the name that your module will take when included in, say, a browser.")
|
program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define"));
|
||||||
.describe("export-all", "Only used when --wrap, this tells UglifyJS to add code to automatically export all globals.")
|
program.option("--ie8", "Support non-standard Internet Explorer 8.");
|
||||||
.describe("lint", "Display some scope warnings")
|
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
|
||||||
.describe("v", "Verbose")
|
program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
||||||
.describe("V", "Print version number and exit.")
|
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
||||||
.describe("noerr", "Don't throw an error for unknown options in -c, -b or -m.")
|
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_source_map());
|
||||||
.describe("bare-returns", "Allow return outside of functions. Useful when minifying CommonJS modules.")
|
program.option("--stats", "Display operations run time on STDERR.")
|
||||||
.describe("keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.")
|
program.option("--toplevel", "Compress and/or mangle variables in toplevel scope.");
|
||||||
.describe("quotes", "Quote style (0 - auto, 1 - single, 2 - double, 3 - original)")
|
program.option("--verbose", "Print diagnostic messages.");
|
||||||
.describe("reserved-file", "File containing reserved names")
|
program.option("--warn", "Print warning messages.");
|
||||||
.describe("reserve-domprops", "Make (most?) DOM properties reserved for --mangle-props")
|
program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
|
||||||
.describe("mangle-props", "Mangle property names (0 - disabled, 1 - mangle all properties, 2 - mangle unquoted properies)")
|
program.arguments("[files...]").parseArgv(process.argv);
|
||||||
.describe("mangle-regex", "Only mangle property names matching the regex")
|
if (program.configFile) {
|
||||||
.describe("name-cache", "File to hold mangled names mappings")
|
options = JSON.parse(read_file(program.configFile));
|
||||||
.describe("pure-funcs", "List of functions that can be safely removed if their return value is not used")
|
}
|
||||||
.describe("dump-spidermonkey-ast", "Dump SpiderMonkey AST to stdout.")
|
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
||||||
|
fatal("ERROR: cannot write source map to STDOUT");
|
||||||
.alias("p", "prefix")
|
}
|
||||||
.alias("o", "output")
|
[
|
||||||
.alias("v", "verbose")
|
"compress",
|
||||||
.alias("b", "beautify")
|
"ie8",
|
||||||
.alias("m", "mangle")
|
"mangle",
|
||||||
.alias("c", "compress")
|
"sourceMap",
|
||||||
.alias("d", "define")
|
"toplevel",
|
||||||
.alias("r", "reserved")
|
"wrap"
|
||||||
.alias("V", "version")
|
].forEach(function(name) {
|
||||||
.alias("e", "enclose")
|
if (name in program) {
|
||||||
.alias("q", "quotes")
|
options[name] = program[name];
|
||||||
|
}
|
||||||
.string("source-map")
|
});
|
||||||
.string("source-map-root")
|
if (program.beautify) {
|
||||||
.string("source-map-url")
|
options.output = typeof program.beautify == "object" ? program.beautify : {};
|
||||||
.string("b")
|
if (!("beautify" in options.output)) {
|
||||||
.string("beautify")
|
options.output.beautify = true;
|
||||||
.string("m")
|
}
|
||||||
.string("mangle")
|
}
|
||||||
.string("c")
|
if (program.comments) {
|
||||||
.string("compress")
|
if (typeof options.output != "object") options.output = {};
|
||||||
.string("d")
|
options.output.comments = typeof program.comments == "string" ? program.comments : "some";
|
||||||
.string("define")
|
}
|
||||||
.string("e")
|
if (program.define) {
|
||||||
.string("enclose")
|
if (typeof options.compress != "object") options.compress = {};
|
||||||
.string("comments")
|
if (typeof options.compress.global_defs != "object") options.compress.global_defs = {};
|
||||||
.string("wrap")
|
for (var expr in program.define) {
|
||||||
.string("p")
|
options.compress.global_defs[expr] = program.define[expr];
|
||||||
.string("prefix")
|
}
|
||||||
.string("name-cache")
|
}
|
||||||
|
if (program.keepFnames) {
|
||||||
.array("reserved-file")
|
options.keep_fnames = true;
|
||||||
.array("pure-funcs")
|
}
|
||||||
|
if (program.mangleProps) {
|
||||||
.boolean("expr")
|
if (program.mangleProps.domprops) {
|
||||||
.boolean("source-map-include-sources")
|
delete program.mangleProps.domprops;
|
||||||
.boolean("screw-ie8")
|
} else {
|
||||||
.boolean("support-ie8")
|
if (typeof program.mangleProps != "object") program.mangleProps = {};
|
||||||
.boolean("export-all")
|
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
|
||||||
.boolean("self")
|
require("../tools/domprops").forEach(function(name) {
|
||||||
.boolean("v")
|
UglifyJS._push_uniq(program.mangleProps.reserved, name);
|
||||||
.boolean("verbose")
|
});
|
||||||
.boolean("stats")
|
}
|
||||||
.boolean("acorn")
|
if (typeof options.mangle != "object") options.mangle = {};
|
||||||
.boolean("spidermonkey")
|
options.mangle.properties = program.mangleProps;
|
||||||
.boolean("dump-spidermonkey-ast")
|
}
|
||||||
.boolean("lint")
|
var cache;
|
||||||
.boolean("V")
|
if (program.nameCache) {
|
||||||
.boolean("version")
|
cache = JSON.parse(read_file(program.nameCache, "{}"));
|
||||||
.boolean("noerr")
|
if (options.mangle) {
|
||||||
.boolean("bare-returns")
|
if (typeof options.mangle != "object") options.mangle = {};
|
||||||
.boolean("keep-fnames")
|
options.mangle.cache = to_cache("vars");
|
||||||
.boolean("reserve-domprops")
|
if (options.mangle.properties) {
|
||||||
|
if (typeof options.mangle.properties != "object") options.mangle.properties = {};
|
||||||
.wrap(80)
|
options.mangle.properties.cache = to_cache("props");
|
||||||
|
}
|
||||||
.argv
|
}
|
||||||
;
|
}
|
||||||
|
if (program.output == "ast") {
|
||||||
normalize(ARGS);
|
options.output = {
|
||||||
|
ast: true,
|
||||||
if (ARGS.noerr) {
|
code: false
|
||||||
UglifyJS.DefaultsError.croak = function(msg, defs) {
|
|
||||||
print_error("WARN: " + msg);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (program.parse) {
|
||||||
if (ARGS.version || ARGS.V) {
|
if (program.parse.acorn || program.parse.spidermonkey) {
|
||||||
var json = require("../package.json");
|
if (program.sourceMap) fatal("ERROR: inline source map only works with built-in parser");
|
||||||
print(json.name + ' ' + json.version);
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.ast_help) {
|
|
||||||
var desc = UglifyJS.describe_ast();
|
|
||||||
print(typeof desc == "string" ? desc : JSON.stringify(desc, null, 2));
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.h || ARGS.help) {
|
|
||||||
print(yargs.help());
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.acorn) {
|
|
||||||
acorn = require("acorn");
|
|
||||||
}
|
|
||||||
|
|
||||||
var COMPRESS = getOptions("c", true);
|
|
||||||
var MANGLE = getOptions("m", true);
|
|
||||||
var BEAUTIFY = getOptions("b", true);
|
|
||||||
var RESERVED = null;
|
|
||||||
|
|
||||||
if (ARGS.reserved_file) ARGS.reserved_file.forEach(function(filename){
|
|
||||||
RESERVED = UglifyJS.readReservedFile(filename, RESERVED);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ARGS.reserve_domprops) {
|
|
||||||
RESERVED = UglifyJS.readDefaultReservedFile(RESERVED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.d) {
|
|
||||||
if (COMPRESS) COMPRESS.global_defs = getOptions("d");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.pure_funcs) {
|
|
||||||
if (COMPRESS) COMPRESS.pure_funcs = ARGS.pure_funcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.r) {
|
|
||||||
if (MANGLE) MANGLE.except = ARGS.r.replace(/^\s+|\s+$/g).split(/\s*,+\s*/);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RESERVED && MANGLE) {
|
|
||||||
if (!MANGLE.except) MANGLE.except = RESERVED.vars;
|
|
||||||
else MANGLE.except = MANGLE.except.concat(RESERVED.vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
function readNameCache(key) {
|
|
||||||
return UglifyJS.readNameCache(ARGS.name_cache, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeNameCache(key, cache) {
|
|
||||||
return UglifyJS.writeNameCache(ARGS.name_cache, key, cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractRegex(str) {
|
|
||||||
if (/^\/.*\/[a-zA-Z]*$/.test(str)) {
|
|
||||||
var regex_pos = str.lastIndexOf("/");
|
|
||||||
return new RegExp(str.substr(1, regex_pos - 1), str.substr(regex_pos + 1));
|
|
||||||
} else {
|
|
||||||
throw new Error("Invalid regular expression: " + str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.quotes === true) {
|
|
||||||
ARGS.quotes = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.mangle_props === true) {
|
|
||||||
ARGS.mangle_props = 1;
|
|
||||||
} else if (ARGS.mangle_props === "unquoted") {
|
|
||||||
ARGS.mangle_props = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
var OUTPUT_OPTIONS = {
|
|
||||||
beautify : BEAUTIFY ? true : false,
|
|
||||||
preamble : ARGS.preamble || null,
|
|
||||||
quote_style : ARGS.quotes != null ? ARGS.quotes : 0
|
|
||||||
};
|
|
||||||
|
|
||||||
if (ARGS.mangle_props == 2) {
|
|
||||||
OUTPUT_OPTIONS.keep_quoted_props = true;
|
|
||||||
if (COMPRESS && !("properties" in COMPRESS))
|
|
||||||
COMPRESS.properties = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.support_ie8 === true && ARGS.screw_ie8 !== true) {
|
|
||||||
screw_ie8 = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (COMPRESS) COMPRESS.screw_ie8 = screw_ie8;
|
|
||||||
if (MANGLE) MANGLE.screw_ie8 = screw_ie8;
|
|
||||||
OUTPUT_OPTIONS.screw_ie8 = screw_ie8;
|
|
||||||
|
|
||||||
if (ARGS.keep_fnames) {
|
|
||||||
if (COMPRESS) COMPRESS.keep_fnames = true;
|
|
||||||
if (MANGLE) MANGLE.keep_fnames = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BEAUTIFY)
|
|
||||||
UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY);
|
|
||||||
|
|
||||||
if (ARGS.comments != null) {
|
|
||||||
if (/^\/.*\/[a-zA-Z]*$/.test(ARGS.comments)) {
|
|
||||||
try {
|
|
||||||
OUTPUT_OPTIONS.comments = extractRegex(ARGS.comments);
|
|
||||||
} catch (e) {
|
|
||||||
print_error("ERROR: Invalid --comments: " + e.message);
|
|
||||||
}
|
|
||||||
} else if (ARGS.comments == "all") {
|
|
||||||
OUTPUT_OPTIONS.comments = true;
|
|
||||||
} else {
|
} else {
|
||||||
OUTPUT_OPTIONS.comments = function(node, comment) {
|
options.parse = program.parse;
|
||||||
var text = comment.value;
|
|
||||||
var type = comment.type;
|
|
||||||
if (type == "comment2") {
|
|
||||||
// multiline comment
|
|
||||||
return /@preserve|@license|@cc_on/i.test(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var convert_path = function(name) {
|
||||||
var files = ARGS._.slice();
|
return name;
|
||||||
|
};
|
||||||
if (process.platform === "win32")
|
if (typeof program.sourceMap == "object" && "base" in program.sourceMap) {
|
||||||
files = UglifyJS.simple_glob(files);
|
convert_path = function() {
|
||||||
|
var base = program.sourceMap.base;
|
||||||
if (ARGS.self) {
|
delete options.sourceMap.base;
|
||||||
if (files.length > 0) {
|
return function(name) {
|
||||||
print_error("WARN: Ignoring input files since --self was passed");
|
return path.relative(base, name);
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
if (program.verbose) {
|
||||||
|
options.warnings = "verbose";
|
||||||
|
} else if (program.warn) {
|
||||||
|
options.warnings = true;
|
||||||
|
}
|
||||||
|
if (program.self) {
|
||||||
|
if (program.args.length) {
|
||||||
|
console.error("WARN: Ignoring input files since --self was passed");
|
||||||
}
|
}
|
||||||
files = UglifyJS.FILES;
|
if (!options.wrap) options.wrap = "UglifyJS";
|
||||||
if (!ARGS.wrap) ARGS.wrap = "UglifyJS";
|
simple_glob(UglifyJS.FILES).forEach(function(name) {
|
||||||
|
files[convert_path(name)] = read_file(name);
|
||||||
|
});
|
||||||
|
run();
|
||||||
|
} else if (program.args.length) {
|
||||||
|
simple_glob(program.args).forEach(function(name) {
|
||||||
|
files[convert_path(name)] = read_file(name);
|
||||||
|
});
|
||||||
|
run();
|
||||||
|
} else {
|
||||||
|
var chunks = [];
|
||||||
|
process.stdin.setEncoding("utf8");
|
||||||
|
process.stdin.on("data", function(chunk) {
|
||||||
|
chunks.push(chunk);
|
||||||
|
}).on("end", function() {
|
||||||
|
files = [ chunks.join("") ];
|
||||||
|
run();
|
||||||
|
});
|
||||||
|
process.stdin.resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
var ORIG_MAP = ARGS.in_source_map;
|
function convert_ast(fn) {
|
||||||
|
return UglifyJS.AST_Node.from_mozilla_ast(Object.keys(files).reduce(fn, null));
|
||||||
if (ORIG_MAP) {
|
|
||||||
ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
|
|
||||||
if (files.length == 0) {
|
|
||||||
print_error("INFO: Using file from the input source map: " + ORIG_MAP.file);
|
|
||||||
files = [ ORIG_MAP.file ];
|
|
||||||
}
|
|
||||||
if (ARGS.source_map_root == null) {
|
|
||||||
ARGS.source_map_root = ORIG_MAP.sourceRoot;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files.length == 0) {
|
function run() {
|
||||||
files = [ "-" ];
|
UglifyJS.AST_Node.warn_function = function(msg) {
|
||||||
}
|
console.error("WARN:", msg);
|
||||||
|
};
|
||||||
if (files.indexOf("-") >= 0 && ARGS.source_map) {
|
if (program.stats) program.stats = Date.now();
|
||||||
print_error("ERROR: Source map doesn't work with input from STDIN");
|
try {
|
||||||
process.exit(1);
|
if (program.parse) {
|
||||||
}
|
if (program.parse.acorn) {
|
||||||
|
files = convert_ast(function(toplevel, name) {
|
||||||
if (files.filter(function(el){ return el == "-" }).length > 1) {
|
return require("acorn").parse(files[name], {
|
||||||
print_error("ERROR: Can read a single file from STDIN (two or more dashes specified)");
|
locations: true,
|
||||||
process.exit(1);
|
program: toplevel,
|
||||||
}
|
sourceFile: name
|
||||||
|
});
|
||||||
var STATS = {};
|
});
|
||||||
var OUTPUT_FILE = ARGS.o;
|
} else if (program.parse.spidermonkey) {
|
||||||
var TOPLEVEL = null;
|
files = convert_ast(function(toplevel, name) {
|
||||||
var P_RELATIVE = ARGS.p && ARGS.p == "relative";
|
var obj = JSON.parse(files[name]);
|
||||||
var SOURCES_CONTENT = {};
|
if (!toplevel) return obj;
|
||||||
|
toplevel.body = toplevel.body.concat(obj.body);
|
||||||
var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({
|
return toplevel;
|
||||||
file: P_RELATIVE ? path.relative(path.dirname(ARGS.source_map), OUTPUT_FILE) : OUTPUT_FILE,
|
|
||||||
root: ARGS.source_map_root,
|
|
||||||
orig: ORIG_MAP,
|
|
||||||
}) : null;
|
|
||||||
|
|
||||||
OUTPUT_OPTIONS.source_map = SOURCE_MAP;
|
|
||||||
|
|
||||||
try {
|
|
||||||
var output = UglifyJS.OutputStream(OUTPUT_OPTIONS);
|
|
||||||
var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
|
|
||||||
} catch(ex) {
|
|
||||||
if (ex instanceof UglifyJS.DefaultsError) {
|
|
||||||
print_error(ex.msg);
|
|
||||||
print_error("Supported options:");
|
|
||||||
print_error(sys.inspect(ex.defs));
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async.eachLimit(files, 1, function (file, cb) {
|
|
||||||
read_whole_file(file, function (err, code) {
|
|
||||||
if (err) {
|
|
||||||
print_error("ERROR: can't read file: " + file);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
if (ARGS.p != null) {
|
|
||||||
if (P_RELATIVE) {
|
|
||||||
file = path.relative(path.dirname(ARGS.source_map), file).replace(/\\/g, '/');
|
|
||||||
} else {
|
|
||||||
var p = parseInt(ARGS.p, 10);
|
|
||||||
if (!isNaN(p)) {
|
|
||||||
file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SOURCES_CONTENT[file] = code;
|
|
||||||
time_it("parse", function(){
|
|
||||||
if (ARGS.spidermonkey) {
|
|
||||||
var program = JSON.parse(code);
|
|
||||||
if (!TOPLEVEL) TOPLEVEL = program;
|
|
||||||
else TOPLEVEL.body = TOPLEVEL.body.concat(program.body);
|
|
||||||
}
|
|
||||||
else if (ARGS.acorn) {
|
|
||||||
TOPLEVEL = acorn.parse(code, {
|
|
||||||
locations : true,
|
|
||||||
sourceFile : file,
|
|
||||||
program : TOPLEVEL
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
try {
|
} catch (ex) {
|
||||||
TOPLEVEL = UglifyJS.parse(code, {
|
fatal(ex);
|
||||||
filename : file,
|
}
|
||||||
toplevel : TOPLEVEL,
|
var result = UglifyJS.minify(files, options);
|
||||||
expression : ARGS.expr,
|
if (result.error) {
|
||||||
bare_returns : ARGS.bare_returns,
|
var ex = result.error;
|
||||||
});
|
if (ex.name == "SyntaxError") {
|
||||||
} catch(ex) {
|
console.error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
|
||||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
var col = ex.col;
|
||||||
print_error("Parse error at " + file + ":" + ex.line + "," + ex.col);
|
var lines = files[ex.filename].split(/\r?\n/);
|
||||||
print_error(ex.message);
|
var line = lines[ex.line - 1];
|
||||||
print_error(ex.stack);
|
if (!line && !col) {
|
||||||
process.exit(1);
|
line = lines[ex.line - 2];
|
||||||
}
|
col = line.length;
|
||||||
throw ex;
|
}
|
||||||
|
if (line) {
|
||||||
|
if (col > 40) {
|
||||||
|
line = line.slice(col - 40);
|
||||||
|
col = 40;
|
||||||
}
|
}
|
||||||
};
|
console.error(line.slice(0, 80));
|
||||||
});
|
console.error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
||||||
cb();
|
|
||||||
});
|
|
||||||
}, function () {
|
|
||||||
if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
|
|
||||||
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ARGS.wrap != null) {
|
|
||||||
TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.enclose != null) {
|
|
||||||
var arg_parameter_list = ARGS.enclose;
|
|
||||||
if (arg_parameter_list === true) {
|
|
||||||
arg_parameter_list = [];
|
|
||||||
}
|
|
||||||
else if (!(arg_parameter_list instanceof Array)) {
|
|
||||||
arg_parameter_list = [arg_parameter_list];
|
|
||||||
}
|
|
||||||
TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGS.mangle_props || ARGS.name_cache) (function(){
|
|
||||||
var reserved = RESERVED ? RESERVED.props : null;
|
|
||||||
var cache = readNameCache("props");
|
|
||||||
var regex;
|
|
||||||
|
|
||||||
try {
|
|
||||||
regex = ARGS.mangle_regex ? extractRegex(ARGS.mangle_regex) : null;
|
|
||||||
} catch (e) {
|
|
||||||
print_error("ERROR: Invalid --mangle-regex: " + e.message);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TOPLEVEL = UglifyJS.mangle_properties(TOPLEVEL, {
|
|
||||||
reserved : reserved,
|
|
||||||
cache : cache,
|
|
||||||
only_cache : !ARGS.mangle_props,
|
|
||||||
regex : regex,
|
|
||||||
ignore_quoted : ARGS.mangle_props == 2
|
|
||||||
});
|
|
||||||
writeNameCache("props", cache);
|
|
||||||
})();
|
|
||||||
|
|
||||||
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint
|
|
||||||
var TL_CACHE = readNameCache("vars");
|
|
||||||
|
|
||||||
if (SCOPE_IS_NEEDED) {
|
|
||||||
time_it("scope", function(){
|
|
||||||
TOPLEVEL.figure_out_scope({ screw_ie8: screw_ie8, cache: TL_CACHE });
|
|
||||||
if (ARGS.lint) {
|
|
||||||
TOPLEVEL.scope_warnings();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (COMPRESS) {
|
|
||||||
time_it("squeeze", function(){
|
|
||||||
TOPLEVEL = compressor.compress(TOPLEVEL);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SCOPE_IS_NEEDED) {
|
|
||||||
time_it("scope", function(){
|
|
||||||
TOPLEVEL.figure_out_scope({ screw_ie8: screw_ie8, cache: TL_CACHE });
|
|
||||||
if (MANGLE && !TL_CACHE) {
|
|
||||||
TOPLEVEL.compute_char_frequency(MANGLE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MANGLE) time_it("mangle", function(){
|
|
||||||
MANGLE.cache = TL_CACHE;
|
|
||||||
TOPLEVEL.mangle_names(MANGLE);
|
|
||||||
});
|
|
||||||
|
|
||||||
writeNameCache("vars", TL_CACHE);
|
|
||||||
|
|
||||||
if (ARGS.source_map_include_sources) {
|
|
||||||
for (var file in SOURCES_CONTENT) {
|
|
||||||
if (SOURCES_CONTENT.hasOwnProperty(file)) {
|
|
||||||
SOURCE_MAP.get().setSourceContent(file, SOURCES_CONTENT[file]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (ex.defs) {
|
||||||
|
console.error("Supported options:");
|
||||||
if (ARGS.dump_spidermonkey_ast) {
|
console.error(ex.defs);
|
||||||
print(JSON.stringify(TOPLEVEL.to_mozilla_ast(), null, 2));
|
}
|
||||||
|
fatal(ex);
|
||||||
|
} else if (program.output == "ast") {
|
||||||
|
console.log(JSON.stringify(result.ast, function(key, value) {
|
||||||
|
if (skip_key(key)) return;
|
||||||
|
if (value instanceof UglifyJS.AST_Token) return;
|
||||||
|
if (value instanceof UglifyJS.Dictionary) return;
|
||||||
|
if (value instanceof UglifyJS.AST_Node) {
|
||||||
|
var result = {
|
||||||
|
_class: "AST_" + value.TYPE
|
||||||
|
};
|
||||||
|
value.CTOR.PROPS.forEach(function(prop) {
|
||||||
|
result[prop] = value[prop];
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}, 2));
|
||||||
|
} else if (program.output == "spidermonkey") {
|
||||||
|
console.log(JSON.stringify(UglifyJS.minify(result.code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
ast: true,
|
||||||
|
code: false
|
||||||
|
}
|
||||||
|
}).ast.to_mozilla_ast(), null, 2));
|
||||||
|
} else if (program.output) {
|
||||||
|
fs.writeFileSync(program.output, result.code);
|
||||||
|
if (result.map) {
|
||||||
|
fs.writeFileSync(program.output + ".map", result.map);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
time_it("generate", function(){
|
console.log(result.code);
|
||||||
TOPLEVEL.print(output);
|
}
|
||||||
});
|
if (program.nameCache) {
|
||||||
|
fs.writeFileSync(program.nameCache, JSON.stringify(cache, function(key, value) {
|
||||||
|
return value instanceof UglifyJS.Dictionary ? value.toObject() : value;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if (program.stats) console.error("Elapsed:", Date.now() - program.stats);
|
||||||
|
}
|
||||||
|
|
||||||
output = output.get();
|
function fatal(message) {
|
||||||
|
if (message instanceof Error) message = message.stack.replace(/^\S*?Error:/, "ERROR:")
|
||||||
|
console.error(message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (SOURCE_MAP) {
|
// A file glob function that only supports "*" and "?" wildcards in the basename.
|
||||||
fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
|
// Example: "foo/bar/*baz??.*.js"
|
||||||
var source_map_url = ARGS.source_map_url || (
|
// Argument `glob` may be a string or an array of strings.
|
||||||
P_RELATIVE
|
// Returns an array of strings. Garbage in, garbage out.
|
||||||
? path.relative(path.dirname(OUTPUT_FILE), ARGS.source_map)
|
function simple_glob(glob) {
|
||||||
: ARGS.source_map
|
if (Array.isArray(glob)) {
|
||||||
);
|
return [].concat.apply([], glob.map(simple_glob));
|
||||||
output += "\n//# sourceMappingURL=" + source_map_url;
|
}
|
||||||
}
|
if (glob.match(/\*|\?/)) {
|
||||||
|
var dir = path.dirname(glob);
|
||||||
if (OUTPUT_FILE) {
|
try {
|
||||||
fs.writeFileSync(OUTPUT_FILE, output, "utf8");
|
var entries = fs.readdirSync(dir);
|
||||||
} else {
|
} catch (ex) {}
|
||||||
print(output);
|
if (entries) {
|
||||||
|
var pattern = "^" + path.basename(glob)
|
||||||
|
.replace(/[.+^$[\]\\(){}]/g, "\\$&")
|
||||||
|
.replace(/\*/g, "[^/\\\\]*")
|
||||||
|
.replace(/\?/g, "[^/\\\\]") + "$";
|
||||||
|
var mod = process.platform === "win32" ? "i" : "";
|
||||||
|
var rx = new RegExp(pattern, mod);
|
||||||
|
var results = entries.filter(function(name) {
|
||||||
|
return rx.test(name);
|
||||||
|
}).map(function(name) {
|
||||||
|
return path.join(dir, name);
|
||||||
|
});
|
||||||
|
if (results.length) return results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return [ glob ];
|
||||||
|
}
|
||||||
|
|
||||||
if (ARGS.stats) {
|
function read_file(path, default_value) {
|
||||||
print_error(UglifyJS.string_template("Timing information (compressed {count} files):", {
|
try {
|
||||||
count: files.length
|
return fs.readFileSync(path, "utf8");
|
||||||
}));
|
} catch (ex) {
|
||||||
for (var i in STATS) if (STATS.hasOwnProperty(i)) {
|
if (ex.code == "ENOENT" && default_value != null) return default_value;
|
||||||
print_error(UglifyJS.string_template("- {name}: {time}s", {
|
fatal(ex);
|
||||||
name: i,
|
}
|
||||||
time: (STATS[i] / 1000).toFixed(3)
|
}
|
||||||
|
|
||||||
|
function parse_js(flag, constants) {
|
||||||
|
return function(value, options) {
|
||||||
|
options = options || {};
|
||||||
|
try {
|
||||||
|
UglifyJS.minify(value, {
|
||||||
|
parse: {
|
||||||
|
expression: true
|
||||||
|
},
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
ast: true,
|
||||||
|
code: false
|
||||||
|
}
|
||||||
|
}).ast.walk(new UglifyJS.TreeWalker(function(node) {
|
||||||
|
if (node instanceof UglifyJS.AST_Assign) {
|
||||||
|
var name = node.left.print_to_string();
|
||||||
|
var value = node.right;
|
||||||
|
if (!constants) {
|
||||||
|
options[name] = value;
|
||||||
|
} else if (value instanceof UglifyJS.AST_Array) {
|
||||||
|
options[name] = value.elements.map(to_string);
|
||||||
|
} else {
|
||||||
|
options[name] = to_string(value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_PropAccess) {
|
||||||
|
var name = node.print_to_string();
|
||||||
|
options[name] = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
|
||||||
|
|
||||||
|
function to_string(value) {
|
||||||
|
return value instanceof UglifyJS.AST_Constant ? value.getValue() : value.print_to_string({
|
||||||
|
quote_keys: true
|
||||||
|
});
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -----[ functions ]----- */
|
|
||||||
|
|
||||||
function normalize(o) {
|
|
||||||
for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) {
|
|
||||||
o[i.replace(/-/g, "_")] = o[i];
|
|
||||||
delete o[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOptions(flag, constants) {
|
|
||||||
var x = ARGS[flag];
|
|
||||||
if (x == null || x === false) return null;
|
|
||||||
var ret = {};
|
|
||||||
if (x !== "") {
|
|
||||||
if (Array.isArray(x)) x = x.map(function (v) { return "(" + v + ")"; }).join(", ");
|
|
||||||
|
|
||||||
var ast;
|
|
||||||
try {
|
|
||||||
ast = UglifyJS.parse(x, { expression: true });
|
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
fatal("Error parsing arguments for '" + flag + "': " + value);
|
||||||
print_error("Error parsing arguments for flag `" + flag + "': " + x);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ast.walk(new UglifyJS.TreeWalker(function(node){
|
return options;
|
||||||
if (node instanceof UglifyJS.AST_Seq) return; // descend
|
|
||||||
if (node instanceof UglifyJS.AST_Assign) {
|
|
||||||
var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_");
|
|
||||||
var value = node.right;
|
|
||||||
if (constants)
|
|
||||||
value = new Function("return (" + value.print_to_string() + ")")();
|
|
||||||
ret[name] = value;
|
|
||||||
return true; // no descend
|
|
||||||
}
|
|
||||||
if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_Binary) {
|
|
||||||
var name = node.print_to_string({ beautify: false }).replace(/-/g, "_");
|
|
||||||
ret[name] = true;
|
|
||||||
return true; // no descend
|
|
||||||
}
|
|
||||||
print_error(node.TYPE)
|
|
||||||
print_error("Error parsing arguments for flag `" + flag + "': " + x);
|
|
||||||
process.exit(1);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function read_whole_file(filename, cb) {
|
function parse_source_map() {
|
||||||
if (filename == "-") {
|
var parse = parse_js("sourceMap", true);
|
||||||
var chunks = [];
|
return function(value, options) {
|
||||||
process.stdin.setEncoding('utf-8');
|
var hasContent = options && options.sourceMap && "content" in options.sourceMap;
|
||||||
process.stdin.on('data', function (chunk) {
|
var settings = parse(value, options);
|
||||||
chunks.push(chunk);
|
if (!hasContent && settings.content && settings.content != "inline") {
|
||||||
}).on('end', function () {
|
console.error("INFO: Using input source map:", settings.content);
|
||||||
cb(null, chunks.join(""));
|
settings.content = read_file(settings.content, settings.content);
|
||||||
});
|
}
|
||||||
process.openStdin();
|
return settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function to_cache(key) {
|
||||||
|
if (cache[key]) {
|
||||||
|
cache[key].props = UglifyJS.Dictionary.fromObject(cache[key].props);
|
||||||
} else {
|
} else {
|
||||||
fs.readFile(filename, "utf-8", cb);
|
cache[key] = {
|
||||||
|
cname: -1,
|
||||||
|
props: new UglifyJS.Dictionary()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
return cache[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
function time_it(name, cont) {
|
function skip_key(key) {
|
||||||
var t1 = new Date().getTime();
|
return skip_keys.indexOf(key) >= 0;
|
||||||
var ret = cont();
|
|
||||||
if (ARGS.stats) {
|
|
||||||
var spent = new Date().getTime() - t1;
|
|
||||||
if (STATS[name]) STATS[name] += spent;
|
|
||||||
else STATS[name] = spent;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_error(msg) {
|
|
||||||
console.error("%s", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
function print(txt) {
|
|
||||||
console.log("%s", txt);
|
|
||||||
}
|
}
|
||||||
|
|||||||
252
lib/ast.js
252
lib/ast.js
@@ -81,7 +81,9 @@ function DEFNODE(type, props, methods, base) {
|
|||||||
ctor.DEFMETHOD = function(name, method) {
|
ctor.DEFMETHOD = function(name, method) {
|
||||||
this.prototype[name] = method;
|
this.prototype[name] = method;
|
||||||
};
|
};
|
||||||
exports["AST_" + type] = ctor;
|
if (typeof exports !== "undefined") {
|
||||||
|
exports["AST_" + type] = ctor;
|
||||||
|
}
|
||||||
return ctor;
|
return ctor;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,9 +91,20 @@ var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos
|
|||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
var AST_Node = DEFNODE("Node", "start end", {
|
var AST_Node = DEFNODE("Node", "start end", {
|
||||||
clone: function() {
|
_clone: function(deep) {
|
||||||
|
if (deep) {
|
||||||
|
var self = this.clone();
|
||||||
|
return self.transform(new TreeTransformer(function(node) {
|
||||||
|
if (node !== self) {
|
||||||
|
return node.clone(true);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
return new this.CTOR(this);
|
return new this.CTOR(this);
|
||||||
},
|
},
|
||||||
|
clone: function(deep) {
|
||||||
|
return this._clone(deep);
|
||||||
|
},
|
||||||
$documentation: "Base class of all AST nodes",
|
$documentation: "Base class of all AST nodes",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
start: "[AST_Token] The first token of this node",
|
start: "[AST_Token] The first token of this node",
|
||||||
@@ -143,12 +156,13 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
|
|||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
|
|
||||||
function walk_body(node, visitor) {
|
function walk_body(node, visitor) {
|
||||||
if (node.body instanceof AST_Statement) {
|
var body = node.body;
|
||||||
node.body._walk(visitor);
|
if (body instanceof AST_Statement) {
|
||||||
|
body._walk(visitor);
|
||||||
|
}
|
||||||
|
else for (var i = 0, len = body.length; i < len; i++) {
|
||||||
|
body[i]._walk(visitor);
|
||||||
}
|
}
|
||||||
else node.body.forEach(function(stat){
|
|
||||||
stat._walk(visitor);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var AST_Block = DEFNODE("Block", "body", {
|
var AST_Block = DEFNODE("Block", "body", {
|
||||||
@@ -168,21 +182,13 @@ var AST_BlockStatement = DEFNODE("BlockStatement", null, {
|
|||||||
}, AST_Block);
|
}, AST_Block);
|
||||||
|
|
||||||
var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
|
var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
|
||||||
$documentation: "The empty statement (empty block or simply a semicolon)",
|
$documentation: "The empty statement (empty block or simply a semicolon)"
|
||||||
_walk: function(visitor) {
|
|
||||||
return visitor._visit(this);
|
|
||||||
}
|
|
||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
|
|
||||||
var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {
|
var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {
|
||||||
$documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
|
$documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
|
body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
|
||||||
},
|
|
||||||
_walk: function(visitor) {
|
|
||||||
return visitor._visit(this, function(){
|
|
||||||
this.body._walk(visitor);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
|
|
||||||
@@ -196,6 +202,21 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
|
|||||||
this.label._walk(visitor);
|
this.label._walk(visitor);
|
||||||
this.body._walk(visitor);
|
this.body._walk(visitor);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
clone: function(deep) {
|
||||||
|
var node = this._clone(deep);
|
||||||
|
if (deep) {
|
||||||
|
var label = node.label;
|
||||||
|
var def = this.label;
|
||||||
|
node.walk(new TreeWalker(function(node) {
|
||||||
|
if (node instanceof AST_LoopControl
|
||||||
|
&& node.label && node.label.thedef === def) {
|
||||||
|
node.label.thedef = label;
|
||||||
|
label.references.push(node);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
}, AST_StatementWithBody);
|
}, AST_StatementWithBody);
|
||||||
|
|
||||||
@@ -297,62 +318,13 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
|||||||
$propdoc: {
|
$propdoc: {
|
||||||
globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
|
globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
|
||||||
},
|
},
|
||||||
wrap_enclose: function(arg_parameter_pairs) {
|
wrap_commonjs: function(name) {
|
||||||
var self = this;
|
var body = this.body;
|
||||||
var args = [];
|
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
|
||||||
var parameters = [];
|
|
||||||
|
|
||||||
arg_parameter_pairs.forEach(function(pair) {
|
|
||||||
var splitAt = pair.lastIndexOf(":");
|
|
||||||
|
|
||||||
args.push(pair.substr(0, splitAt));
|
|
||||||
parameters.push(pair.substr(splitAt + 1));
|
|
||||||
});
|
|
||||||
|
|
||||||
var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
|
|
||||||
wrapped_tl = parse(wrapped_tl);
|
wrapped_tl = parse(wrapped_tl);
|
||||||
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
|
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
|
||||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
||||||
return MAP.splice(self.body);
|
return MAP.splice(body);
|
||||||
}
|
|
||||||
}));
|
|
||||||
return wrapped_tl;
|
|
||||||
},
|
|
||||||
wrap_commonjs: function(name, export_all) {
|
|
||||||
var self = this;
|
|
||||||
var to_export = [];
|
|
||||||
if (export_all) {
|
|
||||||
self.figure_out_scope();
|
|
||||||
self.walk(new TreeWalker(function(node){
|
|
||||||
if (node instanceof AST_SymbolDeclaration && node.definition().global) {
|
|
||||||
if (!find_if(function(n){ return n.name == node.name }, to_export))
|
|
||||||
to_export.push(node);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
var wrapped_tl = "(function(exports, global){ '$ORIG'; '$EXPORTS'; global['" + name + "'] = exports; }({}, (function(){return this}())))";
|
|
||||||
wrapped_tl = parse(wrapped_tl);
|
|
||||||
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){
|
|
||||||
if (node instanceof AST_Directive) {
|
|
||||||
switch (node.value) {
|
|
||||||
case "$ORIG":
|
|
||||||
return MAP.splice(self.body);
|
|
||||||
case "$EXPORTS":
|
|
||||||
var body = [];
|
|
||||||
to_export.forEach(function(sym){
|
|
||||||
body.push(new AST_SimpleStatement({
|
|
||||||
body: new AST_Assign({
|
|
||||||
left: new AST_Sub({
|
|
||||||
expression: new AST_SymbolRef({ name: "exports" }),
|
|
||||||
property: new AST_String({ value: sym.name }),
|
|
||||||
}),
|
|
||||||
operator: "=",
|
|
||||||
right: new AST_SymbolRef(sym),
|
|
||||||
}),
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
return MAP.splice(body);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
return wrapped_tl;
|
return wrapped_tl;
|
||||||
@@ -369,9 +341,10 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
|
|||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
if (this.name) this.name._walk(visitor);
|
if (this.name) this.name._walk(visitor);
|
||||||
this.argnames.forEach(function(arg){
|
var argnames = this.argnames;
|
||||||
arg._walk(visitor);
|
for (var i = 0, len = argnames.length; i < len; i++) {
|
||||||
});
|
argnames[i]._walk(visitor);
|
||||||
|
}
|
||||||
walk_body(this, visitor);
|
walk_body(this, visitor);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -522,18 +495,19 @@ var AST_Finally = DEFNODE("Finally", null, {
|
|||||||
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
|
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
|
||||||
}, AST_Block);
|
}, AST_Block);
|
||||||
|
|
||||||
/* -----[ VAR/CONST ]----- */
|
/* -----[ VAR ]----- */
|
||||||
|
|
||||||
var AST_Definitions = DEFNODE("Definitions", "definitions", {
|
var AST_Definitions = DEFNODE("Definitions", "definitions", {
|
||||||
$documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
|
$documentation: "Base class for `var` nodes (variable declarations/initializations)",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
definitions: "[AST_VarDef*] array of variable definitions"
|
definitions: "[AST_VarDef*] array of variable definitions"
|
||||||
},
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
this.definitions.forEach(function(def){
|
var definitions = this.definitions;
|
||||||
def._walk(visitor);
|
for (var i = 0, len = definitions.length; i < len; i++) {
|
||||||
});
|
definitions[i]._walk(visitor);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
@@ -542,14 +516,10 @@ var AST_Var = DEFNODE("Var", null, {
|
|||||||
$documentation: "A `var` statement"
|
$documentation: "A `var` statement"
|
||||||
}, AST_Definitions);
|
}, AST_Definitions);
|
||||||
|
|
||||||
var AST_Const = DEFNODE("Const", null, {
|
|
||||||
$documentation: "A `const` statement"
|
|
||||||
}, AST_Definitions);
|
|
||||||
|
|
||||||
var AST_VarDef = DEFNODE("VarDef", "name value", {
|
var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||||
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
$documentation: "A variable declaration; only appears in a AST_Definitions node",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
|
name: "[AST_SymbolVar] name of the variable",
|
||||||
value: "[AST_Node?] initializer, or null of there's no initializer"
|
value: "[AST_Node?] initializer, or null of there's no initializer"
|
||||||
},
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
@@ -570,10 +540,11 @@ var AST_Call = DEFNODE("Call", "expression args", {
|
|||||||
},
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
|
var args = this.args;
|
||||||
|
for (var i = 0, len = args.length; i < len; i++) {
|
||||||
|
args[i]._walk(visitor);
|
||||||
|
}
|
||||||
this.expression._walk(visitor);
|
this.expression._walk(visitor);
|
||||||
this.args.forEach(function(arg){
|
|
||||||
arg._walk(visitor);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -582,68 +553,16 @@ var AST_New = DEFNODE("New", null, {
|
|||||||
$documentation: "An object instantiation. Derives from a function call since it has exactly the same properties"
|
$documentation: "An object instantiation. Derives from a function call since it has exactly the same properties"
|
||||||
}, AST_Call);
|
}, AST_Call);
|
||||||
|
|
||||||
var AST_Seq = DEFNODE("Seq", "car cdr", {
|
var AST_Sequence = DEFNODE("Sequence", "expressions", {
|
||||||
$documentation: "A sequence expression (two comma-separated expressions)",
|
$documentation: "A sequence expression (comma-separated expressions)",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
car: "[AST_Node] first element in sequence",
|
expressions: "[AST_Node*] array of expressions (at least two)"
|
||||||
cdr: "[AST_Node] second element in sequence"
|
|
||||||
},
|
|
||||||
$cons: function(x, y) {
|
|
||||||
var seq = new AST_Seq(x);
|
|
||||||
seq.car = x;
|
|
||||||
seq.cdr = y;
|
|
||||||
return seq;
|
|
||||||
},
|
|
||||||
$from_array: function(array) {
|
|
||||||
if (array.length == 0) return null;
|
|
||||||
if (array.length == 1) return array[0].clone();
|
|
||||||
var list = null;
|
|
||||||
for (var i = array.length; --i >= 0;) {
|
|
||||||
list = AST_Seq.cons(array[i], list);
|
|
||||||
}
|
|
||||||
var p = list;
|
|
||||||
while (p) {
|
|
||||||
if (p.cdr && !p.cdr.cdr) {
|
|
||||||
p.cdr = p.cdr.car;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p = p.cdr;
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
},
|
|
||||||
to_array: function() {
|
|
||||||
var p = this, a = [];
|
|
||||||
while (p) {
|
|
||||||
a.push(p.car);
|
|
||||||
if (p.cdr && !(p.cdr instanceof AST_Seq)) {
|
|
||||||
a.push(p.cdr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p = p.cdr;
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
},
|
|
||||||
add: function(node) {
|
|
||||||
var p = this;
|
|
||||||
while (p) {
|
|
||||||
if (!(p.cdr instanceof AST_Seq)) {
|
|
||||||
var cell = AST_Seq.cons(p.cdr, node);
|
|
||||||
return p.cdr = cell;
|
|
||||||
}
|
|
||||||
p = p.cdr;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
len: function() {
|
|
||||||
if (this.cdr instanceof AST_Seq) {
|
|
||||||
return this.cdr.len() + 1;
|
|
||||||
} else {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
this.car._walk(visitor);
|
this.expressions.forEach(function(node) {
|
||||||
if (this.cdr) this.cdr._walk(visitor);
|
node._walk(visitor);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -696,7 +615,7 @@ var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
|
|||||||
$documentation: "Unary postfix expression, i.e. `i++`"
|
$documentation: "Unary postfix expression, i.e. `i++`"
|
||||||
}, AST_Unary);
|
}, AST_Unary);
|
||||||
|
|
||||||
var AST_Binary = DEFNODE("Binary", "left operator right", {
|
var AST_Binary = DEFNODE("Binary", "operator left right", {
|
||||||
$documentation: "Binary expression, i.e. `a + b`",
|
$documentation: "Binary expression, i.e. `a + b`",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
left: "[AST_Node] left-hand side expression",
|
left: "[AST_Node] left-hand side expression",
|
||||||
@@ -740,9 +659,10 @@ var AST_Array = DEFNODE("Array", "elements", {
|
|||||||
},
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
this.elements.forEach(function(el){
|
var elements = this.elements;
|
||||||
el._walk(visitor);
|
for (var i = 0, len = elements.length; i < len; i++) {
|
||||||
});
|
elements[i]._walk(visitor);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -754,9 +674,10 @@ var AST_Object = DEFNODE("Object", "properties", {
|
|||||||
},
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
this.properties.forEach(function(prop){
|
var properties = this.properties;
|
||||||
prop._walk(visitor);
|
for (var i = 0, len = properties.length; i < len; i++) {
|
||||||
});
|
properties[i]._walk(visitor);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -764,8 +685,8 @@ var AST_Object = DEFNODE("Object", "properties", {
|
|||||||
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
||||||
$documentation: "Base class for literal object properties",
|
$documentation: "Base class for literal object properties",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an arbitrary AST_Node.",
|
key: "[string] the property name converted to a string for ObjectKeyVal. For setters and getters this is an AST_SymbolAccessor.",
|
||||||
value: "[AST_Node] property value. For setters and getters this is an AST_Function."
|
value: "[AST_Node] property value. For setters and getters this is an AST_Accessor."
|
||||||
},
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
@@ -803,20 +724,13 @@ var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
|
|||||||
}, AST_Symbol);
|
}, AST_Symbol);
|
||||||
|
|
||||||
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
|
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
|
||||||
$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
|
$documentation: "A declaration symbol (symbol in var, function name or argument, symbol in catch)",
|
||||||
$propdoc: {
|
|
||||||
init: "[AST_Node*/S] array of initializers for this declaration."
|
|
||||||
}
|
|
||||||
}, AST_Symbol);
|
}, AST_Symbol);
|
||||||
|
|
||||||
var AST_SymbolVar = DEFNODE("SymbolVar", null, {
|
var AST_SymbolVar = DEFNODE("SymbolVar", null, {
|
||||||
$documentation: "Symbol defining a variable",
|
$documentation: "Symbol defining a variable",
|
||||||
}, AST_SymbolDeclaration);
|
}, AST_SymbolDeclaration);
|
||||||
|
|
||||||
var AST_SymbolConst = DEFNODE("SymbolConst", null, {
|
|
||||||
$documentation: "A constant declaration"
|
|
||||||
}, AST_SymbolDeclaration);
|
|
||||||
|
|
||||||
var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
|
var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
|
||||||
$documentation: "Symbol naming a function argument",
|
$documentation: "Symbol naming a function argument",
|
||||||
}, AST_SymbolVar);
|
}, AST_SymbolVar);
|
||||||
@@ -951,11 +865,11 @@ TreeWalker.prototype = {
|
|||||||
parent: function(n) {
|
parent: function(n) {
|
||||||
return this.stack[this.stack.length - 2 - (n || 0)];
|
return this.stack[this.stack.length - 2 - (n || 0)];
|
||||||
},
|
},
|
||||||
push: function (node) {
|
push: function(node) {
|
||||||
if (node instanceof AST_Lambda) {
|
if (node instanceof AST_Lambda) {
|
||||||
this.directives = Object.create(this.directives);
|
this.directives = Object.create(this.directives);
|
||||||
} else if (node instanceof AST_Directive) {
|
} else if (node instanceof AST_Directive && !this.directives[node.value]) {
|
||||||
this.directives[node.value] = this.directives[node.value] ? "up" : true;
|
this.directives[node.value] = node;
|
||||||
}
|
}
|
||||||
this.stack.push(node);
|
this.stack.push(node);
|
||||||
},
|
},
|
||||||
@@ -983,7 +897,7 @@ TreeWalker.prototype = {
|
|||||||
for (var i = 0; i < node.body.length; ++i) {
|
for (var i = 0; i < node.body.length; ++i) {
|
||||||
var st = node.body[i];
|
var st = node.body[i];
|
||||||
if (!(st instanceof AST_Directive)) break;
|
if (!(st instanceof AST_Directive)) break;
|
||||||
if (st.value == type) return true;
|
if (st.value == type) return st;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1005,16 +919,16 @@ TreeWalker.prototype = {
|
|||||||
self = p;
|
self = p;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
loopcontrol_target: function(label) {
|
loopcontrol_target: function(node) {
|
||||||
var stack = this.stack;
|
var stack = this.stack;
|
||||||
if (label) for (var i = stack.length; --i >= 0;) {
|
if (node.label) for (var i = stack.length; --i >= 0;) {
|
||||||
var x = stack[i];
|
var x = stack[i];
|
||||||
if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
|
if (x instanceof AST_LabeledStatement && x.label.name == node.label.name)
|
||||||
return x.body;
|
return x.body;
|
||||||
}
|
|
||||||
} else for (var i = stack.length; --i >= 0;) {
|
} else for (var i = stack.length; --i >= 0;) {
|
||||||
var x = stack[i];
|
var x = stack[i];
|
||||||
if (x instanceof AST_Switch || x instanceof AST_IterationStatement)
|
if (x instanceof AST_IterationStatement
|
||||||
|
|| node instanceof AST_Break && x instanceof AST_Switch)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3600
lib/compress.js
3600
lib/compress.js
File diff suppressed because it is too large
Load Diff
154
lib/minify.js
Normal file
154
lib/minify.js
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
var to_ascii = typeof atob == "undefined" ? function(b64) {
|
||||||
|
return new Buffer(b64, "base64").toString();
|
||||||
|
} : atob;
|
||||||
|
var to_base64 = typeof btoa == "undefined" ? function(str) {
|
||||||
|
return new Buffer(str).toString("base64");
|
||||||
|
} : btoa;
|
||||||
|
|
||||||
|
function read_source_map(code) {
|
||||||
|
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
|
||||||
|
if (!match) {
|
||||||
|
AST_Node.warn("inline source map not found");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return to_ascii(match[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_shorthand(name, options, keys) {
|
||||||
|
if (options[name]) {
|
||||||
|
keys.forEach(function(key) {
|
||||||
|
if (options[key]) {
|
||||||
|
if (typeof options[key] != "object") options[key] = {};
|
||||||
|
if (!(name in options[key])) options[key][name] = options[name];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function minify(files, options) {
|
||||||
|
var warn_function = AST_Node.warn_function;
|
||||||
|
try {
|
||||||
|
if (typeof files == "string") {
|
||||||
|
files = [ files ];
|
||||||
|
}
|
||||||
|
options = defaults(options, {
|
||||||
|
compress: {},
|
||||||
|
ie8: false,
|
||||||
|
keep_fnames: false,
|
||||||
|
mangle: {},
|
||||||
|
output: {},
|
||||||
|
parse: {},
|
||||||
|
sourceMap: false,
|
||||||
|
toplevel: false,
|
||||||
|
warnings: false,
|
||||||
|
wrap: false,
|
||||||
|
}, true);
|
||||||
|
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" ]);
|
||||||
|
if (options.mangle) {
|
||||||
|
options.mangle = defaults(options.mangle, {
|
||||||
|
cache: null,
|
||||||
|
eval: false,
|
||||||
|
ie8: false,
|
||||||
|
keep_fnames: false,
|
||||||
|
properties: false,
|
||||||
|
reserved: [],
|
||||||
|
toplevel: false,
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
if (options.sourceMap) {
|
||||||
|
options.sourceMap = defaults(options.sourceMap, {
|
||||||
|
content: null,
|
||||||
|
filename: null,
|
||||||
|
includeSources: false,
|
||||||
|
root: null,
|
||||||
|
url: null,
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
var warnings = [];
|
||||||
|
if (options.warnings && !AST_Node.warn_function) {
|
||||||
|
AST_Node.warn_function = function(warning) {
|
||||||
|
warnings.push(warning);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var toplevel;
|
||||||
|
if (files instanceof AST_Toplevel) {
|
||||||
|
toplevel = files;
|
||||||
|
} else {
|
||||||
|
options.parse = options.parse || {};
|
||||||
|
options.parse.toplevel = null;
|
||||||
|
for (var name in files) {
|
||||||
|
options.parse.filename = name;
|
||||||
|
options.parse.toplevel = parse(files[name], options.parse);
|
||||||
|
if (options.sourceMap && options.sourceMap.content == "inline") {
|
||||||
|
if (Object.keys(files).length > 1)
|
||||||
|
throw new Error("inline source map only works with singular input");
|
||||||
|
options.sourceMap.content = read_source_map(files[name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toplevel = options.parse.toplevel;
|
||||||
|
}
|
||||||
|
if (options.wrap) {
|
||||||
|
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||||
|
}
|
||||||
|
if (options.compress) {
|
||||||
|
toplevel.figure_out_scope(options.mangle);
|
||||||
|
toplevel = new Compressor(options.compress).compress(toplevel);
|
||||||
|
}
|
||||||
|
if (options.mangle) {
|
||||||
|
toplevel.figure_out_scope(options.mangle);
|
||||||
|
base54.reset();
|
||||||
|
toplevel.compute_char_frequency(options.mangle);
|
||||||
|
toplevel.mangle_names(options.mangle);
|
||||||
|
if (options.mangle.properties) {
|
||||||
|
toplevel = mangle_properties(toplevel, options.mangle.properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var result = {};
|
||||||
|
if (options.output.ast) {
|
||||||
|
result.ast = toplevel;
|
||||||
|
}
|
||||||
|
if (!HOP(options.output, "code") || options.output.code) {
|
||||||
|
if (options.sourceMap) {
|
||||||
|
if (typeof options.sourceMap.content == "string") {
|
||||||
|
options.sourceMap.content = JSON.parse(options.sourceMap.content);
|
||||||
|
}
|
||||||
|
options.output.source_map = SourceMap({
|
||||||
|
file: options.sourceMap.filename,
|
||||||
|
orig: options.sourceMap.content,
|
||||||
|
root: options.sourceMap.root
|
||||||
|
});
|
||||||
|
if (options.sourceMap.includeSources) {
|
||||||
|
for (var name in files) {
|
||||||
|
options.output.source_map.get().setSourceContent(name, files[name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete options.output.ast;
|
||||||
|
delete options.output.code;
|
||||||
|
var stream = OutputStream(options.output);
|
||||||
|
toplevel.print(stream);
|
||||||
|
result.code = stream.get();
|
||||||
|
if (options.sourceMap) {
|
||||||
|
result.map = options.output.source_map.toString();
|
||||||
|
if (options.sourceMap.url == "inline") {
|
||||||
|
result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(result.map);
|
||||||
|
} else if (options.sourceMap.url) {
|
||||||
|
result.code += "\n//# sourceMappingURL=" + options.sourceMap.url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (warnings.length) {
|
||||||
|
result.warnings = warnings;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (ex) {
|
||||||
|
return { error: ex };
|
||||||
|
} finally {
|
||||||
|
AST_Node.warn_function = warn_function;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -111,23 +111,19 @@
|
|||||||
},
|
},
|
||||||
Property: function(M) {
|
Property: function(M) {
|
||||||
var key = M.key;
|
var key = M.key;
|
||||||
var name = key.type == "Identifier" ? key.name : key.value;
|
|
||||||
var args = {
|
var args = {
|
||||||
start : my_start_token(key),
|
start : my_start_token(key),
|
||||||
end : my_end_token(M.value),
|
end : my_end_token(M.value),
|
||||||
key : name,
|
key : key.type == "Identifier" ? key.name : key.value,
|
||||||
value : from_moz(M.value)
|
value : from_moz(M.value)
|
||||||
};
|
};
|
||||||
switch (M.kind) {
|
if (M.kind == "init") return new AST_ObjectKeyVal(args);
|
||||||
case "init":
|
args.key = new AST_SymbolAccessor({
|
||||||
return new AST_ObjectKeyVal(args);
|
name: args.key
|
||||||
case "set":
|
});
|
||||||
args.value.name = from_moz(key);
|
args.value = new AST_Accessor(args.value);
|
||||||
return new AST_ObjectSetter(args);
|
if (M.kind == "get") return new AST_ObjectGetter(args);
|
||||||
case "get":
|
if (M.kind == "set") return new AST_ObjectSetter(args);
|
||||||
args.value.name = from_moz(key);
|
|
||||||
return new AST_ObjectGetter(args);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
ArrayExpression: function(M) {
|
ArrayExpression: function(M) {
|
||||||
return new AST_Array({
|
return new AST_Array({
|
||||||
@@ -149,7 +145,11 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
SequenceExpression: function(M) {
|
SequenceExpression: function(M) {
|
||||||
return AST_Seq.from_array(M.expressions.map(from_moz));
|
return new AST_Sequence({
|
||||||
|
start : my_start_token(M),
|
||||||
|
end : my_end_token(M),
|
||||||
|
expressions: M.expressions.map(from_moz)
|
||||||
|
});
|
||||||
},
|
},
|
||||||
MemberExpression: function(M) {
|
MemberExpression: function(M) {
|
||||||
return new (M.computed ? AST_Sub : AST_Dot)({
|
return new (M.computed ? AST_Sub : AST_Dot)({
|
||||||
@@ -168,7 +168,7 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
VariableDeclaration: function(M) {
|
VariableDeclaration: function(M) {
|
||||||
return new (M.kind === "const" ? AST_Const : AST_Var)({
|
return new AST_Var({
|
||||||
start : my_start_token(M),
|
start : my_start_token(M),
|
||||||
end : my_end_token(M),
|
end : my_end_token(M),
|
||||||
definitions : M.declarations.map(from_moz)
|
definitions : M.declarations.map(from_moz)
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
Identifier: function(M) {
|
Identifier: function(M) {
|
||||||
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
|
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
|
||||||
return new ( p.type == "LabeledStatement" ? AST_Label
|
return new ( p.type == "LabeledStatement" ? AST_Label
|
||||||
: p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
|
: p.type == "VariableDeclarator" && p.id === M ? AST_SymbolVar
|
||||||
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
|
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
|
||||||
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
|
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
|
||||||
: p.type == "CatchClause" ? AST_SymbolCatch
|
: p.type == "CatchClause" ? AST_SymbolCatch
|
||||||
@@ -256,10 +256,7 @@
|
|||||||
map("CallExpression", AST_Call, "callee>expression, arguments@args");
|
map("CallExpression", AST_Call, "callee>expression, arguments@args");
|
||||||
|
|
||||||
def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
|
def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
|
||||||
return {
|
return to_moz_scope("Program", M);
|
||||||
type: "Program",
|
|
||||||
body: M.body.map(to_moz)
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
|
def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
|
||||||
@@ -267,7 +264,7 @@
|
|||||||
type: "FunctionDeclaration",
|
type: "FunctionDeclaration",
|
||||||
id: to_moz(M.name),
|
id: to_moz(M.name),
|
||||||
params: M.argnames.map(to_moz),
|
params: M.argnames.map(to_moz),
|
||||||
body: to_moz_block(M)
|
body: to_moz_scope("BlockStatement", M)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -276,7 +273,7 @@
|
|||||||
type: "FunctionExpression",
|
type: "FunctionExpression",
|
||||||
id: to_moz(M.name),
|
id: to_moz(M.name),
|
||||||
params: M.argnames.map(to_moz),
|
params: M.argnames.map(to_moz),
|
||||||
body: to_moz_block(M)
|
body: to_moz_scope("BlockStatement", M)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -327,15 +324,15 @@
|
|||||||
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
|
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
|
||||||
return {
|
return {
|
||||||
type: "VariableDeclaration",
|
type: "VariableDeclaration",
|
||||||
kind: M instanceof AST_Const ? "const" : "var",
|
kind: "var",
|
||||||
declarations: M.definitions.map(to_moz)
|
declarations: M.definitions.map(to_moz)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
|
def_to_moz(AST_Sequence, function To_Moz_SequenceExpression(M) {
|
||||||
return {
|
return {
|
||||||
type: "SequenceExpression",
|
type: "SequenceExpression",
|
||||||
expressions: M.to_array().map(to_moz)
|
expressions: M.expressions.map(to_moz)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -382,11 +379,10 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
|
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
|
||||||
var key = (
|
var key = {
|
||||||
is_identifier(M.key)
|
type: "Literal",
|
||||||
? {type: "Identifier", name: M.key}
|
value: M.key instanceof AST_SymbolAccessor ? M.key.name : M.key
|
||||||
: {type: "Literal", value: M.key}
|
};
|
||||||
);
|
|
||||||
var kind;
|
var kind;
|
||||||
if (M instanceof AST_ObjectKeyVal) {
|
if (M instanceof AST_ObjectKeyVal) {
|
||||||
kind = "init";
|
kind = "init";
|
||||||
@@ -547,8 +543,8 @@
|
|||||||
moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
|
moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
|
||||||
exports, my_start_token, my_end_token, from_moz
|
exports, my_start_token, my_end_token, from_moz
|
||||||
);
|
);
|
||||||
me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
|
me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")(
|
||||||
to_moz, to_moz_block
|
to_moz, to_moz_block, to_moz_scope
|
||||||
);
|
);
|
||||||
MOZ_TO_ME[moztype] = moz_to_me;
|
MOZ_TO_ME[moztype] = moz_to_me;
|
||||||
def_to_moz(mytype, me_to_moz);
|
def_to_moz(mytype, me_to_moz);
|
||||||
@@ -606,4 +602,14 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function to_moz_scope(type, node) {
|
||||||
|
var body = node.body.map(to_moz);
|
||||||
|
if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) {
|
||||||
|
body.unshift(to_moz(new AST_EmptyStatement(node.body[0])));
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: type,
|
||||||
|
body: body
|
||||||
|
};
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
305
lib/output.js
305
lib/output.js
@@ -45,31 +45,65 @@
|
|||||||
|
|
||||||
var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/;
|
var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/;
|
||||||
|
|
||||||
|
function is_some_comments(comment) {
|
||||||
|
// multiline comment
|
||||||
|
return comment.type == "comment2" && /@preserve|@license|@cc_on/i.test(comment.value);
|
||||||
|
}
|
||||||
|
|
||||||
function OutputStream(options) {
|
function OutputStream(options) {
|
||||||
|
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
indent_start : 0,
|
|
||||||
indent_level : 4,
|
|
||||||
quote_keys : false,
|
|
||||||
space_colon : true,
|
|
||||||
ascii_only : false,
|
ascii_only : false,
|
||||||
unescape_regexps : false,
|
|
||||||
inline_script : false,
|
|
||||||
width : 80,
|
|
||||||
max_line_len : 32000,
|
|
||||||
beautify : false,
|
beautify : false,
|
||||||
source_map : null,
|
|
||||||
bracketize : false,
|
bracketize : false,
|
||||||
semicolons : true,
|
|
||||||
comments : false,
|
comments : false,
|
||||||
shebang : true,
|
ie8 : false,
|
||||||
preserve_line : false,
|
indent_level : 4,
|
||||||
screw_ie8 : true,
|
indent_start : 0,
|
||||||
|
inline_script : true,
|
||||||
|
keep_quoted_props: false,
|
||||||
|
max_line_len : false,
|
||||||
preamble : null,
|
preamble : null,
|
||||||
|
preserve_line : false,
|
||||||
|
quote_keys : false,
|
||||||
quote_style : 0,
|
quote_style : 0,
|
||||||
keep_quoted_props: false
|
semicolons : true,
|
||||||
|
shebang : true,
|
||||||
|
source_map : null,
|
||||||
|
space_colon : true,
|
||||||
|
unescape_regexps : false,
|
||||||
|
width : 80,
|
||||||
|
wrap_iife : false,
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
var comments = options.comments;
|
||||||
|
if (typeof options.comments === "string" && /^\/.*\/[a-zA-Z]*$/.test(options.comments)) {
|
||||||
|
var regex_pos = options.comments.lastIndexOf("/");
|
||||||
|
comments = new RegExp(
|
||||||
|
options.comments.substr(1, regex_pos - 1),
|
||||||
|
options.comments.substr(regex_pos + 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (comments instanceof RegExp) {
|
||||||
|
comment_filter = function(comment) {
|
||||||
|
return comment.type != "comment5" && comments.test(comment.value);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (typeof comments === "function") {
|
||||||
|
comment_filter = function(comment) {
|
||||||
|
return comment.type != "comment5" && comments(this, comment);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (comments === "some") {
|
||||||
|
comment_filter = is_some_comments;
|
||||||
|
} else { // NOTE includes "all" option
|
||||||
|
comment_filter = return_true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var indentation = 0;
|
var indentation = 0;
|
||||||
var current_col = 0;
|
var current_col = 0;
|
||||||
var current_line = 1;
|
var current_line = 1;
|
||||||
@@ -102,7 +136,7 @@ function OutputStream(options) {
|
|||||||
case "\t": return "\\t";
|
case "\t": return "\\t";
|
||||||
case "\b": return "\\b";
|
case "\b": return "\\b";
|
||||||
case "\f": return "\\f";
|
case "\f": return "\\f";
|
||||||
case "\x0B": return options.screw_ie8 ? "\\v" : "\\x0B";
|
case "\x0B": return options.ie8 ? "\\x0B" : "\\v";
|
||||||
case "\u2028": return "\\u2028";
|
case "\u2028": return "\\u2028";
|
||||||
case "\u2029": return "\\u2029";
|
case "\u2029": return "\\u2029";
|
||||||
case "\ufeff": return "\\ufeff";
|
case "\ufeff": return "\\ufeff";
|
||||||
@@ -155,31 +189,42 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
var might_need_space = false;
|
var might_need_space = false;
|
||||||
var might_need_semicolon = false;
|
var might_need_semicolon = false;
|
||||||
var last = null;
|
var might_add_newline = 0;
|
||||||
|
var last = "";
|
||||||
|
|
||||||
function last_char() {
|
var ensure_line_len = options.max_line_len ? function() {
|
||||||
return last.charAt(last.length - 1);
|
if (current_col > options.max_line_len) {
|
||||||
};
|
if (might_add_newline) {
|
||||||
|
var left = OUTPUT.slice(0, might_add_newline);
|
||||||
function maybe_newline() {
|
var right = OUTPUT.slice(might_add_newline);
|
||||||
if (options.max_line_len && current_col > options.max_line_len)
|
OUTPUT = left + "\n" + right;
|
||||||
print("\n");
|
current_line++;
|
||||||
};
|
current_pos++;
|
||||||
|
current_col = right.length;
|
||||||
|
}
|
||||||
|
if (current_col > options.max_line_len) {
|
||||||
|
AST_Node.warn("Output exceeds {max_line_len} characters", options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
might_add_newline = 0;
|
||||||
|
} : noop;
|
||||||
|
|
||||||
var requireSemicolonChars = makePredicate("( [ + * / - , .");
|
var requireSemicolonChars = makePredicate("( [ + * / - , .");
|
||||||
|
|
||||||
function print(str) {
|
function print(str) {
|
||||||
str = String(str);
|
str = String(str);
|
||||||
var ch = str.charAt(0);
|
var ch = str.charAt(0);
|
||||||
|
var prev = last.charAt(last.length - 1);
|
||||||
if (might_need_semicolon) {
|
if (might_need_semicolon) {
|
||||||
might_need_semicolon = false;
|
might_need_semicolon = false;
|
||||||
|
|
||||||
if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
|
if (prev == ":" && ch == "}" || (!ch || ";}".indexOf(ch) < 0) && prev != ";") {
|
||||||
if (options.semicolons || requireSemicolonChars(ch)) {
|
if (options.semicolons || requireSemicolonChars(ch)) {
|
||||||
OUTPUT += ";";
|
OUTPUT += ";";
|
||||||
current_col++;
|
current_col++;
|
||||||
current_pos++;
|
current_pos++;
|
||||||
} else {
|
} else {
|
||||||
|
ensure_line_len();
|
||||||
OUTPUT += "\n";
|
OUTPUT += "\n";
|
||||||
current_pos++;
|
current_pos++;
|
||||||
current_line++;
|
current_line++;
|
||||||
@@ -200,6 +245,7 @@ function OutputStream(options) {
|
|||||||
if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
|
if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
|
||||||
var target_line = stack[stack.length - 1].start.line;
|
var target_line = stack[stack.length - 1].start.line;
|
||||||
while (current_line < target_line) {
|
while (current_line < target_line) {
|
||||||
|
ensure_line_len();
|
||||||
OUTPUT += "\n";
|
OUTPUT += "\n";
|
||||||
current_pos++;
|
current_pos++;
|
||||||
current_line++;
|
current_line++;
|
||||||
@@ -209,10 +255,10 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (might_need_space) {
|
if (might_need_space) {
|
||||||
var prev = last_char();
|
|
||||||
if ((is_identifier_char(prev)
|
if ((is_identifier_char(prev)
|
||||||
&& (is_identifier_char(ch) || ch == "\\"))
|
&& (is_identifier_char(ch) || ch == "\\"))
|
||||||
|| (/^[\+\-\/]$/.test(ch) && ch == prev))
|
|| (ch == "/" && ch == prev)
|
||||||
|
|| ((ch == "+" || ch == "-") && ch == last))
|
||||||
{
|
{
|
||||||
OUTPUT += " ";
|
OUTPUT += " ";
|
||||||
current_col++;
|
current_col++;
|
||||||
@@ -220,16 +266,16 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
might_need_space = false;
|
might_need_space = false;
|
||||||
}
|
}
|
||||||
|
OUTPUT += str;
|
||||||
|
current_pos += str.length;
|
||||||
var a = str.split(/\r?\n/), n = a.length - 1;
|
var a = str.split(/\r?\n/), n = a.length - 1;
|
||||||
current_line += n;
|
current_line += n;
|
||||||
if (n == 0) {
|
current_col += a[0].length;
|
||||||
current_col += a[n].length;
|
if (n > 0) {
|
||||||
} else {
|
ensure_line_len();
|
||||||
current_col = a[n].length;
|
current_col = a[n].length;
|
||||||
}
|
}
|
||||||
current_pos += str.length;
|
|
||||||
last = str;
|
last = str;
|
||||||
OUTPUT += str;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var space = options.beautify ? function() {
|
var space = options.beautify ? function() {
|
||||||
@@ -255,7 +301,10 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
var newline = options.beautify ? function() {
|
var newline = options.beautify ? function() {
|
||||||
print("\n");
|
print("\n");
|
||||||
} : maybe_newline;
|
} : options.max_line_len ? function() {
|
||||||
|
ensure_line_len();
|
||||||
|
might_add_newline = OUTPUT.length;
|
||||||
|
} : noop;
|
||||||
|
|
||||||
var semicolon = options.beautify ? function() {
|
var semicolon = options.beautify ? function() {
|
||||||
print(";");
|
print(";");
|
||||||
@@ -332,13 +381,12 @@ function OutputStream(options) {
|
|||||||
} : noop;
|
} : noop;
|
||||||
|
|
||||||
function get() {
|
function get() {
|
||||||
|
if (might_add_newline) {
|
||||||
|
ensure_line_len();
|
||||||
|
}
|
||||||
return OUTPUT;
|
return OUTPUT;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.preamble) {
|
|
||||||
print(options.preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
var stack = [];
|
var stack = [];
|
||||||
return {
|
return {
|
||||||
get : get,
|
get : get,
|
||||||
@@ -376,12 +424,12 @@ function OutputStream(options) {
|
|||||||
with_square : with_square,
|
with_square : with_square,
|
||||||
add_mapping : add_mapping,
|
add_mapping : add_mapping,
|
||||||
option : function(opt) { return options[opt] },
|
option : function(opt) { return options[opt] },
|
||||||
|
comment_filter : comment_filter,
|
||||||
line : function() { return current_line },
|
line : function() { return current_line },
|
||||||
col : function() { return current_col },
|
col : function() { return current_col },
|
||||||
pos : function() { return current_pos },
|
pos : function() { return current_pos },
|
||||||
push_node : function(node) { stack.push(node) },
|
push_node : function(node) { stack.push(node) },
|
||||||
pop_node : function() { return stack.pop() },
|
pop_node : function() { return stack.pop() },
|
||||||
stack : function() { return stack },
|
|
||||||
parent : function(n) {
|
parent : function(n) {
|
||||||
return stack[stack.length - 2 - (n || 0)];
|
return stack[stack.length - 2 - (n || 0)];
|
||||||
}
|
}
|
||||||
@@ -435,7 +483,7 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
AST_Node.DEFMETHOD("add_comments", function(output){
|
AST_Node.DEFMETHOD("add_comments", function(output){
|
||||||
if (output._readonly) return;
|
if (output._readonly) return;
|
||||||
var c = output.option("comments"), self = this;
|
var self = this;
|
||||||
var start = self.start;
|
var start = self.start;
|
||||||
if (start && !start._comments_dumped) {
|
if (start && !start._comments_dumped) {
|
||||||
start._comments_dumped = true;
|
start._comments_dumped = true;
|
||||||
@@ -458,20 +506,19 @@ function OutputStream(options) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!c) {
|
if (output.pos() == 0) {
|
||||||
comments = comments.filter(function(comment) {
|
if (comments.length > 0 && output.option("shebang") && comments[0].type == "comment5") {
|
||||||
return comment.type == "comment5";
|
output.print("#!" + comments.shift().value + "\n");
|
||||||
});
|
output.indent();
|
||||||
} else if (c.test) {
|
}
|
||||||
comments = comments.filter(function(comment){
|
var preamble = output.option("preamble");
|
||||||
return comment.type == "comment5" || c.test(comment.value);
|
if (preamble) {
|
||||||
});
|
output.print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
|
||||||
} else if (typeof c == "function") {
|
}
|
||||||
comments = comments.filter(function(comment){
|
|
||||||
return comment.type == "comment5" || c(self, comment);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comments = comments.filter(output.comment_filter, self);
|
||||||
|
|
||||||
// Keep single line comments after nlb, after nlb
|
// Keep single line comments after nlb, after nlb
|
||||||
if (!output.option("beautify") && comments.length > 0 &&
|
if (!output.option("beautify") && comments.length > 0 &&
|
||||||
/comment[134]/.test(comments[0].type) &&
|
/comment[134]/.test(comments[0].type) &&
|
||||||
@@ -494,10 +541,6 @@ function OutputStream(options) {
|
|||||||
output.space();
|
output.space();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (output.pos() === 0 && c.type == "comment5" && output.option("shebang")) {
|
|
||||||
output.print("#!" + c.value + "\n");
|
|
||||||
output.indent();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -521,7 +564,16 @@ function OutputStream(options) {
|
|||||||
// a function expression needs parens around it when it's provably
|
// a function expression needs parens around it when it's provably
|
||||||
// the first token to appear in a statement.
|
// the first token to appear in a statement.
|
||||||
PARENS(AST_Function, function(output){
|
PARENS(AST_Function, function(output){
|
||||||
return first_in_statement(output);
|
if (first_in_statement(output)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output.option('wrap_iife')) {
|
||||||
|
var p = output.parent();
|
||||||
|
return p instanceof AST_Call && p.expression === this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
// same goes for an object literal, because otherwise it would be
|
// same goes for an object literal, because otherwise it would be
|
||||||
@@ -530,15 +582,13 @@ function OutputStream(options) {
|
|||||||
return first_in_statement(output);
|
return first_in_statement(output);
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS([ AST_Unary, AST_Undefined ], function(output){
|
PARENS(AST_Unary, function(output){
|
||||||
if (this.expression instanceof AST_Call)
|
|
||||||
return false;
|
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
return p instanceof AST_PropAccess && p.expression === this
|
return p instanceof AST_PropAccess && p.expression === this
|
||||||
|| p instanceof AST_Call && p.expression === this;
|
|| p instanceof AST_Call && p.expression === this;
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS(AST_Seq, function(output){
|
PARENS(AST_Sequence, function(output){
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|
||||||
|| p instanceof AST_Unary // !(foo, bar, baz)
|
|| p instanceof AST_Unary // !(foo, bar, baz)
|
||||||
@@ -627,7 +677,7 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
PARENS([ AST_Assign, AST_Conditional ], function (output){
|
PARENS([ AST_Assign, AST_Conditional ], function(output){
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
// !(a = false) → true
|
// !(a = false) → true
|
||||||
if (p instanceof AST_Unary)
|
if (p instanceof AST_Unary)
|
||||||
@@ -723,7 +773,7 @@ function OutputStream(options) {
|
|||||||
DEFPRINT(AST_Do, function(self, output){
|
DEFPRINT(AST_Do, function(self, output){
|
||||||
output.print("do");
|
output.print("do");
|
||||||
output.space();
|
output.space();
|
||||||
self._do_print_body(output);
|
make_block(self.body, output);
|
||||||
output.space();
|
output.space();
|
||||||
output.print("while");
|
output.print("while");
|
||||||
output.space();
|
output.space();
|
||||||
@@ -745,7 +795,7 @@ function OutputStream(options) {
|
|||||||
output.print("for");
|
output.print("for");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function(){
|
output.with_parens(function(){
|
||||||
if (self.init && !(self.init instanceof AST_EmptyStatement)) {
|
if (self.init) {
|
||||||
if (self.init instanceof AST_Definitions) {
|
if (self.init instanceof AST_Definitions) {
|
||||||
self.init.print(output);
|
self.init.print(output);
|
||||||
} else {
|
} else {
|
||||||
@@ -850,10 +900,10 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
/* -----[ if ]----- */
|
/* -----[ if ]----- */
|
||||||
function make_then(self, output) {
|
function make_then(self, output) {
|
||||||
if (output.option("bracketize")) {
|
var b = self.body;
|
||||||
make_block(self.body, output);
|
if (output.option("bracketize")
|
||||||
return;
|
|| output.option("ie8") && b instanceof AST_Do)
|
||||||
}
|
return make_block(b, output);
|
||||||
// The squeezer replaces "block"-s that contain only a single
|
// The squeezer replaces "block"-s that contain only a single
|
||||||
// statement with the statement itself; technically, the AST
|
// statement with the statement itself; technically, the AST
|
||||||
// is correct, but this can create problems when we output an
|
// is correct, but this can create problems when we output an
|
||||||
@@ -861,18 +911,7 @@ function OutputStream(options) {
|
|||||||
// IF *without* an ELSE block (then the outer ELSE would refer
|
// IF *without* an ELSE block (then the outer ELSE would refer
|
||||||
// to the inner IF). This function checks for this case and
|
// to the inner IF). This function checks for this case and
|
||||||
// adds the block brackets if needed.
|
// adds the block brackets if needed.
|
||||||
if (!self.body)
|
if (!b) return output.force_semicolon();
|
||||||
return output.force_semicolon();
|
|
||||||
if (self.body instanceof AST_Do) {
|
|
||||||
// Unconditionally use the if/do-while workaround for all browsers.
|
|
||||||
// https://github.com/mishoo/UglifyJS/issues/#issue/57 IE
|
|
||||||
// croaks with "syntax error" on code like this: if (foo)
|
|
||||||
// do ... while(cond); else ... we need block brackets
|
|
||||||
// around do/while
|
|
||||||
make_block(self.body, output);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var b = self.body;
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (b instanceof AST_If) {
|
if (b instanceof AST_If) {
|
||||||
if (!b.alternative) {
|
if (!b.alternative) {
|
||||||
@@ -900,7 +939,10 @@ function OutputStream(options) {
|
|||||||
output.space();
|
output.space();
|
||||||
output.print("else");
|
output.print("else");
|
||||||
output.space();
|
output.space();
|
||||||
force_statement(self.alternative, output);
|
if (self.alternative instanceof AST_If)
|
||||||
|
self.alternative.print(output);
|
||||||
|
else
|
||||||
|
force_statement(self.alternative, output);
|
||||||
} else {
|
} else {
|
||||||
self._do_print_body(output);
|
self._do_print_body(output);
|
||||||
}
|
}
|
||||||
@@ -914,24 +956,24 @@ function OutputStream(options) {
|
|||||||
self.expression.print(output);
|
self.expression.print(output);
|
||||||
});
|
});
|
||||||
output.space();
|
output.space();
|
||||||
if (self.body.length > 0) output.with_block(function(){
|
var last = self.body.length - 1;
|
||||||
self.body.forEach(function(stmt, i){
|
if (last < 0) output.print("{}");
|
||||||
if (i) output.newline();
|
else output.with_block(function(){
|
||||||
|
self.body.forEach(function(branch, i){
|
||||||
output.indent(true);
|
output.indent(true);
|
||||||
stmt.print(output);
|
branch.print(output);
|
||||||
|
if (i < last && branch.body.length > 0)
|
||||||
|
output.newline();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
else output.print("{}");
|
|
||||||
});
|
});
|
||||||
AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){
|
AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){
|
||||||
if (this.body.length > 0) {
|
output.newline();
|
||||||
|
this.body.forEach(function(stmt){
|
||||||
|
output.indent();
|
||||||
|
stmt.print(output);
|
||||||
output.newline();
|
output.newline();
|
||||||
this.body.forEach(function(stmt){
|
});
|
||||||
output.indent();
|
|
||||||
stmt.print(output);
|
|
||||||
output.newline();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Default, function(self, output){
|
DEFPRINT(AST_Default, function(self, output){
|
||||||
output.print("default:");
|
output.print("default:");
|
||||||
@@ -991,9 +1033,6 @@ function OutputStream(options) {
|
|||||||
DEFPRINT(AST_Var, function(self, output){
|
DEFPRINT(AST_Var, function(self, output){
|
||||||
self._do_print(output, "var");
|
self._do_print(output, "var");
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Const, function(self, output){
|
|
||||||
self._do_print(output, "const");
|
|
||||||
});
|
|
||||||
|
|
||||||
function parenthesize_for_noin(node, output, noin) {
|
function parenthesize_for_noin(node, output, noin) {
|
||||||
if (!noin) node.print(output);
|
if (!noin) node.print(output);
|
||||||
@@ -1041,18 +1080,19 @@ function OutputStream(options) {
|
|||||||
AST_Call.prototype._codegen(self, output);
|
AST_Call.prototype._codegen(self, output);
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Seq.DEFMETHOD("_do_print", function(output){
|
AST_Sequence.DEFMETHOD("_do_print", function(output){
|
||||||
this.car.print(output);
|
this.expressions.forEach(function(node, index) {
|
||||||
if (this.cdr) {
|
if (index > 0) {
|
||||||
output.comma();
|
output.comma();
|
||||||
if (output.should_break()) {
|
if (output.should_break()) {
|
||||||
output.newline();
|
output.newline();
|
||||||
output.indent();
|
output.indent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.cdr.print(output);
|
node.print(output);
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Seq, function(self, output){
|
DEFPRINT(AST_Sequence, function(self, output){
|
||||||
self._do_print(output);
|
self._do_print(output);
|
||||||
// var p = output.parent();
|
// var p = output.parent();
|
||||||
// if (p instanceof AST_Statement) {
|
// if (p instanceof AST_Statement) {
|
||||||
@@ -1175,7 +1215,7 @@ function OutputStream(options) {
|
|||||||
&& +key + "" == key)
|
&& +key + "" == key)
|
||||||
&& parseFloat(key) >= 0) {
|
&& parseFloat(key) >= 0) {
|
||||||
output.print(make_num(key));
|
output.print(make_num(key));
|
||||||
} else if (RESERVED_WORDS(key) ? output.option("screw_ie8") : is_identifier_string(key)) {
|
} else if (RESERVED_WORDS(key) ? !output.option("ie8") : is_identifier_string(key)) {
|
||||||
if (quote && output.option("keep_quoted_props")) {
|
if (quote && output.option("keep_quoted_props")) {
|
||||||
output.print_string(key, quote);
|
output.print_string(key, quote);
|
||||||
} else {
|
} else {
|
||||||
@@ -1203,16 +1243,7 @@ function OutputStream(options) {
|
|||||||
var def = self.definition();
|
var def = self.definition();
|
||||||
output.print_name(def ? def.mangled_name || def.name : self.name);
|
output.print_name(def ? def.mangled_name || def.name : self.name);
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Undefined, function(self, output){
|
|
||||||
output.print("void 0");
|
|
||||||
});
|
|
||||||
DEFPRINT(AST_Hole, noop);
|
DEFPRINT(AST_Hole, noop);
|
||||||
DEFPRINT(AST_Infinity, function(self, output){
|
|
||||||
output.print("Infinity");
|
|
||||||
});
|
|
||||||
DEFPRINT(AST_NaN, function(self, output){
|
|
||||||
output.print("NaN");
|
|
||||||
});
|
|
||||||
DEFPRINT(AST_This, function(self, output){
|
DEFPRINT(AST_This, function(self, output){
|
||||||
output.print("this");
|
output.print("this");
|
||||||
});
|
});
|
||||||
@@ -1278,15 +1309,7 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
function force_statement(stat, output) {
|
function force_statement(stat, output) {
|
||||||
if (output.option("bracketize")) {
|
if (output.option("bracketize")) {
|
||||||
if (!stat || stat instanceof AST_EmptyStatement)
|
make_block(stat, output);
|
||||||
output.print("{}");
|
|
||||||
else if (stat instanceof AST_BlockStatement)
|
|
||||||
stat.print(output);
|
|
||||||
else output.with_block(function(){
|
|
||||||
output.indent();
|
|
||||||
stat.print(output);
|
|
||||||
output.newline();
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
if (!stat || stat instanceof AST_EmptyStatement)
|
if (!stat || stat instanceof AST_EmptyStatement)
|
||||||
output.force_semicolon();
|
output.force_semicolon();
|
||||||
@@ -1295,30 +1318,6 @@ function OutputStream(options) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// return true if the node at the top of the stack (that means the
|
|
||||||
// innermost node in the current output) is lexically the first in
|
|
||||||
// a statement.
|
|
||||||
function first_in_statement(output) {
|
|
||||||
var a = output.stack(), i = a.length, node = a[--i], p = a[--i];
|
|
||||||
while (i > 0) {
|
|
||||||
if (p instanceof AST_Statement && p.body === node)
|
|
||||||
return true;
|
|
||||||
if ((p instanceof AST_Seq && p.car === node ) ||
|
|
||||||
(p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||
|
|
||||||
(p instanceof AST_Dot && p.expression === node ) ||
|
|
||||||
(p instanceof AST_Sub && p.expression === node ) ||
|
|
||||||
(p instanceof AST_Conditional && p.condition === node ) ||
|
|
||||||
(p instanceof AST_Binary && p.left === node ) ||
|
|
||||||
(p instanceof AST_UnaryPostfix && p.expression === node ))
|
|
||||||
{
|
|
||||||
node = p;
|
|
||||||
p = a[--i];
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// self should be AST_New. decide if we want to show parens or not.
|
// self should be AST_New. decide if we want to show parens or not.
|
||||||
function need_constructor_parens(self, output) {
|
function need_constructor_parens(self, output) {
|
||||||
// Always print parentheses with arguments
|
// Always print parentheses with arguments
|
||||||
@@ -1359,11 +1358,11 @@ function OutputStream(options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function make_block(stmt, output) {
|
function make_block(stmt, output) {
|
||||||
if (stmt instanceof AST_BlockStatement) {
|
if (!stmt || stmt instanceof AST_EmptyStatement)
|
||||||
|
output.print("{}");
|
||||||
|
else if (stmt instanceof AST_BlockStatement)
|
||||||
stmt.print(output);
|
stmt.print(output);
|
||||||
return;
|
else output.with_block(function(){
|
||||||
}
|
|
||||||
output.with_block(function(){
|
|
||||||
output.indent();
|
output.indent();
|
||||||
stmt.print(output);
|
stmt.print(output);
|
||||||
output.newline();
|
output.newline();
|
||||||
|
|||||||
260
lib/parse.js
260
lib/parse.js
@@ -111,7 +111,7 @@ var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u20
|
|||||||
|
|
||||||
var NEWLINE_CHARS = makePredicate(characters("\n\r\u2028\u2029"));
|
var NEWLINE_CHARS = makePredicate(characters("\n\r\u2028\u2029"));
|
||||||
|
|
||||||
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
|
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,;:"));
|
||||||
|
|
||||||
var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
|
var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
|
||||||
|
|
||||||
@@ -195,12 +195,11 @@ function JS_Parse_Error(message, filename, line, col, pos) {
|
|||||||
this.line = line;
|
this.line = line;
|
||||||
this.col = col;
|
this.col = col;
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
this.stack = new Error().stack;
|
|
||||||
};
|
|
||||||
|
|
||||||
JS_Parse_Error.prototype.toString = function() {
|
|
||||||
return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
|
|
||||||
};
|
};
|
||||||
|
JS_Parse_Error.prototype = Object.create(Error.prototype);
|
||||||
|
JS_Parse_Error.prototype.constructor = JS_Parse_Error;
|
||||||
|
JS_Parse_Error.prototype.name = "SyntaxError";
|
||||||
|
configure_error_stack(JS_Parse_Error);
|
||||||
|
|
||||||
function js_error(message, filename, line, col, pos) {
|
function js_error(message, filename, line, col, pos) {
|
||||||
throw new JS_Parse_Error(message, filename, line, col, pos);
|
throw new JS_Parse_Error(message, filename, line, col, pos);
|
||||||
@@ -350,13 +349,13 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
});
|
});
|
||||||
if (prefix) num = prefix + num;
|
if (prefix) num = prefix + num;
|
||||||
if (RE_OCT_NUMBER.test(num) && next_token.has_directive("use strict")) {
|
if (RE_OCT_NUMBER.test(num) && next_token.has_directive("use strict")) {
|
||||||
parse_error("SyntaxError: Legacy octal literals are not allowed in strict mode");
|
parse_error("Legacy octal literals are not allowed in strict mode");
|
||||||
}
|
}
|
||||||
var valid = parse_js_number(num);
|
var valid = parse_js_number(num);
|
||||||
if (!isNaN(valid)) {
|
if (!isNaN(valid)) {
|
||||||
return token("num", valid);
|
return token("num", valid);
|
||||||
} else {
|
} else {
|
||||||
parse_error("SyntaxError: Invalid syntax: " + num);
|
parse_error("Invalid syntax: " + num);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -395,7 +394,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
// Parse
|
// Parse
|
||||||
if (ch === "0") return "\0";
|
if (ch === "0") return "\0";
|
||||||
if (ch.length > 0 && next_token.has_directive("use strict"))
|
if (ch.length > 0 && next_token.has_directive("use strict"))
|
||||||
parse_error("SyntaxError: Legacy octal escape sequences are not allowed in strict mode");
|
parse_error("Legacy octal escape sequences are not allowed in strict mode");
|
||||||
return String.fromCharCode(parseInt(ch, 8));
|
return String.fromCharCode(parseInt(ch, 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,18 +403,18 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
for (; n > 0; --n) {
|
for (; n > 0; --n) {
|
||||||
var digit = parseInt(next(true), 16);
|
var digit = parseInt(next(true), 16);
|
||||||
if (isNaN(digit))
|
if (isNaN(digit))
|
||||||
parse_error("SyntaxError: Invalid hex-character pattern in string");
|
parse_error("Invalid hex-character pattern in string");
|
||||||
num = (num << 4) | digit;
|
num = (num << 4) | digit;
|
||||||
}
|
}
|
||||||
return num;
|
return num;
|
||||||
};
|
};
|
||||||
|
|
||||||
var read_string = with_eof_error("SyntaxError: Unterminated string constant", function(quote_char){
|
var read_string = with_eof_error("Unterminated string constant", function(quote_char){
|
||||||
var quote = next(), ret = "";
|
var quote = next(), ret = "";
|
||||||
for (;;) {
|
for (;;) {
|
||||||
var ch = next(true, true);
|
var ch = next(true, true);
|
||||||
if (ch == "\\") ch = read_escaped_char(true);
|
if (ch == "\\") ch = read_escaped_char(true);
|
||||||
else if (NEWLINE_CHARS(ch)) parse_error("SyntaxError: Unterminated string constant");
|
else if (NEWLINE_CHARS(ch)) parse_error("Unterminated string constant");
|
||||||
else if (ch == quote) break;
|
else if (ch == quote) break;
|
||||||
ret += ch;
|
ret += ch;
|
||||||
}
|
}
|
||||||
@@ -440,7 +439,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
return next_token;
|
return next_token;
|
||||||
};
|
};
|
||||||
|
|
||||||
var skip_multiline_comment = with_eof_error("SyntaxError: Unterminated multiline comment", function(){
|
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){
|
||||||
var regex_allowed = S.regex_allowed;
|
var regex_allowed = S.regex_allowed;
|
||||||
var i = find("*/", true);
|
var i = find("*/", true);
|
||||||
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n');
|
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n');
|
||||||
@@ -460,9 +459,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (ch != "u") parse_error("SyntaxError: Expecting UnicodeEscapeSequence -- uXXXX");
|
if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
|
||||||
ch = read_escaped_char();
|
ch = read_escaped_char();
|
||||||
if (!is_identifier_char(ch)) parse_error("SyntaxError: Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
|
if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
|
||||||
name += ch;
|
name += ch;
|
||||||
backslash = false;
|
backslash = false;
|
||||||
}
|
}
|
||||||
@@ -474,10 +473,10 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
return name;
|
return name;
|
||||||
};
|
};
|
||||||
|
|
||||||
var read_regexp = with_eof_error("SyntaxError: Unterminated regular expression", function(regexp){
|
var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){
|
||||||
var prev_backslash = false, ch, in_class = false;
|
var prev_backslash = false, ch, in_class = false;
|
||||||
while ((ch = next(true))) if (NEWLINE_CHARS(ch)) {
|
while ((ch = next(true))) if (NEWLINE_CHARS(ch)) {
|
||||||
parse_error("SyntaxError: Unexpected line terminator");
|
parse_error("Unexpected line terminator");
|
||||||
} else if (prev_backslash) {
|
} else if (prev_backslash) {
|
||||||
regexp += "\\" + ch;
|
regexp += "\\" + ch;
|
||||||
prev_backslash = false;
|
prev_backslash = false;
|
||||||
@@ -498,7 +497,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
try {
|
try {
|
||||||
return token("regexp", new RegExp(regexp, mods));
|
return token("regexp", new RegExp(regexp, mods));
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
parse_error("SyntaxError: " + e.message);
|
parse_error(e.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -559,6 +558,11 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
function next_token(force_regexp) {
|
function next_token(force_regexp) {
|
||||||
if (force_regexp != null)
|
if (force_regexp != null)
|
||||||
return read_regexp(force_regexp);
|
return read_regexp(force_regexp);
|
||||||
|
if (shebang && S.pos == 0 && looking_at("#!")) {
|
||||||
|
start_token();
|
||||||
|
forward(2);
|
||||||
|
skip_line_comment("comment5");
|
||||||
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
skip_whitespace();
|
skip_whitespace();
|
||||||
start_token();
|
start_token();
|
||||||
@@ -590,16 +594,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
if (PUNC_CHARS(ch)) return token("punc", next());
|
if (PUNC_CHARS(ch)) return token("punc", next());
|
||||||
if (OPERATOR_CHARS(ch)) return read_operator();
|
if (OPERATOR_CHARS(ch)) return read_operator();
|
||||||
if (code == 92 || is_identifier_start(code)) return read_word();
|
if (code == 92 || is_identifier_start(code)) return read_word();
|
||||||
if (shebang) {
|
|
||||||
if (S.pos == 0 && looking_at("#!")) {
|
|
||||||
forward(2);
|
|
||||||
skip_line_comment("comment5");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
parse_error("SyntaxError: Unexpected character '" + ch + "'");
|
parse_error("Unexpected character '" + ch + "'");
|
||||||
};
|
};
|
||||||
|
|
||||||
next_token.context = function(nc) {
|
next_token.context = function(nc) {
|
||||||
@@ -632,8 +629,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
next_token.has_directive = function(directive) {
|
next_token.has_directive = function(directive) {
|
||||||
return S.directives[directive] !== undefined &&
|
return S.directives[directive] > 0;
|
||||||
S.directives[directive] > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return next_token;
|
return next_token;
|
||||||
@@ -691,13 +687,13 @@ var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "nam
|
|||||||
function parse($TEXT, options) {
|
function parse($TEXT, options) {
|
||||||
|
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
strict : false,
|
|
||||||
filename : null,
|
|
||||||
toplevel : null,
|
|
||||||
expression : false,
|
|
||||||
html5_comments : true,
|
|
||||||
bare_returns : false,
|
bare_returns : false,
|
||||||
|
expression : false,
|
||||||
|
filename : null,
|
||||||
|
html5_comments : true,
|
||||||
shebang : true,
|
shebang : true,
|
||||||
|
strict : false,
|
||||||
|
toplevel : null,
|
||||||
});
|
});
|
||||||
|
|
||||||
var S = {
|
var S = {
|
||||||
@@ -756,14 +752,14 @@ function parse($TEXT, options) {
|
|||||||
function unexpected(token) {
|
function unexpected(token) {
|
||||||
if (token == null)
|
if (token == null)
|
||||||
token = S.token;
|
token = S.token;
|
||||||
token_error(token, "SyntaxError: Unexpected token: " + token.type + " (" + token.value + ")");
|
token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
|
||||||
};
|
};
|
||||||
|
|
||||||
function expect_token(type, val) {
|
function expect_token(type, val) {
|
||||||
if (is(type, val)) {
|
if (is(type, val)) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
token_error(S.token, "SyntaxError: Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
|
token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
|
||||||
};
|
};
|
||||||
|
|
||||||
function expect(punc) { return expect_token("punc", punc); };
|
function expect(punc) { return expect_token("punc", punc); };
|
||||||
@@ -809,24 +805,20 @@ function parse($TEXT, options) {
|
|||||||
handle_regexp();
|
handle_regexp();
|
||||||
switch (S.token.type) {
|
switch (S.token.type) {
|
||||||
case "string":
|
case "string":
|
||||||
var dir = false;
|
if (S.in_directives) {
|
||||||
if (S.in_directives === true) {
|
tmp = peek();
|
||||||
if ((is_token(peek(), "punc", ";") || peek().nlb) && S.token.raw.indexOf("\\") === -1) {
|
if (S.token.raw.indexOf("\\") == -1
|
||||||
|
&& (tmp.nlb
|
||||||
|
|| is_token(tmp, "eof")
|
||||||
|
|| is_token(tmp, "punc", ";")
|
||||||
|
|| is_token(tmp, "punc", "}"))) {
|
||||||
S.input.add_directive(S.token.value);
|
S.input.add_directive(S.token.value);
|
||||||
} else {
|
} else {
|
||||||
S.in_directives = false;
|
S.in_directives = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var dir = S.in_directives, stat = simple_statement();
|
var dir = S.in_directives, stat = simple_statement();
|
||||||
if (dir) {
|
return dir ? new AST_Directive(stat.body) : stat;
|
||||||
return new AST_Directive({
|
|
||||||
start : stat.body.start,
|
|
||||||
end : stat.body.end,
|
|
||||||
quote : stat.body.quote,
|
|
||||||
value : stat.body.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return stat;
|
|
||||||
case "num":
|
case "num":
|
||||||
case "regexp":
|
case "regexp":
|
||||||
case "operator":
|
case "operator":
|
||||||
@@ -892,7 +884,7 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
case "return":
|
case "return":
|
||||||
if (S.in_function == 0 && !options.bare_returns)
|
if (S.in_function == 0 && !options.bare_returns)
|
||||||
croak("SyntaxError: 'return' outside of function");
|
croak("'return' outside of function");
|
||||||
return new AST_Return({
|
return new AST_Return({
|
||||||
value: ( is("punc", ";")
|
value: ( is("punc", ";")
|
||||||
? (next(), null)
|
? (next(), null)
|
||||||
@@ -909,7 +901,7 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
case "throw":
|
case "throw":
|
||||||
if (S.token.nlb)
|
if (S.token.nlb)
|
||||||
croak("SyntaxError: Illegal newline after 'throw'");
|
croak("Illegal newline after 'throw'");
|
||||||
return new AST_Throw({
|
return new AST_Throw({
|
||||||
value: (tmp = expression(true), semicolon(), tmp)
|
value: (tmp = expression(true), semicolon(), tmp)
|
||||||
});
|
});
|
||||||
@@ -920,22 +912,17 @@ function parse($TEXT, options) {
|
|||||||
case "var":
|
case "var":
|
||||||
return tmp = var_(), semicolon(), tmp;
|
return tmp = var_(), semicolon(), tmp;
|
||||||
|
|
||||||
case "const":
|
|
||||||
return tmp = const_(), semicolon(), tmp;
|
|
||||||
|
|
||||||
case "with":
|
case "with":
|
||||||
if (S.input.has_directive("use strict")) {
|
if (S.input.has_directive("use strict")) {
|
||||||
croak("SyntaxError: Strict mode may not include a with statement");
|
croak("Strict mode may not include a with statement");
|
||||||
}
|
}
|
||||||
return new AST_With({
|
return new AST_With({
|
||||||
expression : parenthesised(),
|
expression : parenthesised(),
|
||||||
body : statement()
|
body : statement()
|
||||||
});
|
});
|
||||||
|
|
||||||
default:
|
|
||||||
unexpected();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
unexpected();
|
||||||
});
|
});
|
||||||
|
|
||||||
function labeled_statement() {
|
function labeled_statement() {
|
||||||
@@ -945,7 +932,7 @@ function parse($TEXT, options) {
|
|||||||
// syntactically incorrect if it contains a
|
// syntactically incorrect if it contains a
|
||||||
// LabelledStatement that is enclosed by a
|
// LabelledStatement that is enclosed by a
|
||||||
// LabelledStatement with the same Identifier as label.
|
// LabelledStatement with the same Identifier as label.
|
||||||
croak("SyntaxError: Label " + label.name + " defined twice");
|
croak("Label " + label.name + " defined twice");
|
||||||
}
|
}
|
||||||
expect(":");
|
expect(":");
|
||||||
S.labels.push(label);
|
S.labels.push(label);
|
||||||
@@ -958,7 +945,7 @@ function parse($TEXT, options) {
|
|||||||
label.references.forEach(function(ref){
|
label.references.forEach(function(ref){
|
||||||
if (ref instanceof AST_Continue) {
|
if (ref instanceof AST_Continue) {
|
||||||
ref = ref.label.start;
|
ref = ref.label.start;
|
||||||
croak("SyntaxError: Continue label `" + label.name + "` refers to non-IterationStatement.",
|
croak("Continue label `" + label.name + "` refers to non-IterationStatement.",
|
||||||
ref.line, ref.col, ref.pos);
|
ref.line, ref.col, ref.pos);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -978,11 +965,11 @@ function parse($TEXT, options) {
|
|||||||
if (label != null) {
|
if (label != null) {
|
||||||
ldef = find_if(function(l){ return l.name == label.name }, S.labels);
|
ldef = find_if(function(l){ return l.name == label.name }, S.labels);
|
||||||
if (!ldef)
|
if (!ldef)
|
||||||
croak("SyntaxError: Undefined label " + label.name);
|
croak("Undefined label " + label.name);
|
||||||
label.thedef = ldef;
|
label.thedef = ldef;
|
||||||
}
|
}
|
||||||
else if (S.in_loop == 0)
|
else if (S.in_loop == 0)
|
||||||
croak("SyntaxError: " + type.TYPE + " not inside a loop or switch");
|
croak(type.TYPE + " not inside a loop or switch");
|
||||||
semicolon();
|
semicolon();
|
||||||
var stat = new type({ label: label });
|
var stat = new type({ label: label });
|
||||||
if (ldef) ldef.references.push(stat);
|
if (ldef) ldef.references.push(stat);
|
||||||
@@ -998,7 +985,7 @@ function parse($TEXT, options) {
|
|||||||
: expression(true, true);
|
: expression(true, true);
|
||||||
if (is("operator", "in")) {
|
if (is("operator", "in")) {
|
||||||
if (init instanceof AST_Var && init.definitions.length > 1)
|
if (init instanceof AST_Var && init.definitions.length > 1)
|
||||||
croak("SyntaxError: Only one variable declaration allowed in for..in loop");
|
croak("Only one variable declaration allowed in for..in loop");
|
||||||
next();
|
next();
|
||||||
return for_in(init);
|
return for_in(init);
|
||||||
}
|
}
|
||||||
@@ -1038,29 +1025,32 @@ function parse($TEXT, options) {
|
|||||||
if (in_statement && !name)
|
if (in_statement && !name)
|
||||||
unexpected();
|
unexpected();
|
||||||
expect("(");
|
expect("(");
|
||||||
|
var argnames = [];
|
||||||
|
for (var first = true; !is("punc", ")");) {
|
||||||
|
if (first) first = false; else expect(",");
|
||||||
|
argnames.push(as_symbol(AST_SymbolFunarg));
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
var loop = S.in_loop;
|
||||||
|
var labels = S.labels;
|
||||||
|
++S.in_function;
|
||||||
|
S.in_directives = true;
|
||||||
|
S.input.push_directives_stack();
|
||||||
|
S.in_loop = 0;
|
||||||
|
S.labels = [];
|
||||||
|
var body = block_();
|
||||||
|
if (S.input.has_directive("use strict")) {
|
||||||
|
if (name) strict_verify_symbol(name);
|
||||||
|
argnames.forEach(strict_verify_symbol);
|
||||||
|
}
|
||||||
|
S.input.pop_directives_stack();
|
||||||
|
--S.in_function;
|
||||||
|
S.in_loop = loop;
|
||||||
|
S.labels = labels;
|
||||||
return new ctor({
|
return new ctor({
|
||||||
name: name,
|
name: name,
|
||||||
argnames: (function(first, a){
|
argnames: argnames,
|
||||||
while (!is("punc", ")")) {
|
body: body
|
||||||
if (first) first = false; else expect(",");
|
|
||||||
a.push(as_symbol(AST_SymbolFunarg));
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
return a;
|
|
||||||
})(true, []),
|
|
||||||
body: (function(loop, labels){
|
|
||||||
++S.in_function;
|
|
||||||
S.in_directives = true;
|
|
||||||
S.input.push_directives_stack();
|
|
||||||
S.in_loop = 0;
|
|
||||||
S.labels = [];
|
|
||||||
var a = block_();
|
|
||||||
S.input.pop_directives_stack();
|
|
||||||
--S.in_function;
|
|
||||||
S.in_loop = loop;
|
|
||||||
S.labels = labels;
|
|
||||||
return a;
|
|
||||||
})(S.in_loop, S.labels)
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1148,7 +1138,7 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!bcatch && !bfinally)
|
if (!bcatch && !bfinally)
|
||||||
croak("SyntaxError: Missing catch/finally blocks");
|
croak("Missing catch/finally blocks");
|
||||||
return new AST_Try({
|
return new AST_Try({
|
||||||
body : body,
|
body : body,
|
||||||
bcatch : bcatch,
|
bcatch : bcatch,
|
||||||
@@ -1156,12 +1146,12 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function vardefs(no_in, in_const) {
|
function vardefs(no_in) {
|
||||||
var a = [];
|
var a = [];
|
||||||
for (;;) {
|
for (;;) {
|
||||||
a.push(new AST_VarDef({
|
a.push(new AST_VarDef({
|
||||||
start : S.token,
|
start : S.token,
|
||||||
name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
|
name : as_symbol(AST_SymbolVar),
|
||||||
value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
|
value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
|
||||||
end : prev()
|
end : prev()
|
||||||
}));
|
}));
|
||||||
@@ -1175,15 +1165,7 @@ function parse($TEXT, options) {
|
|||||||
var var_ = function(no_in) {
|
var var_ = function(no_in) {
|
||||||
return new AST_Var({
|
return new AST_Var({
|
||||||
start : prev(),
|
start : prev(),
|
||||||
definitions : vardefs(no_in, false),
|
definitions : vardefs(no_in),
|
||||||
end : prev()
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var const_ = function() {
|
|
||||||
return new AST_Const({
|
|
||||||
start : prev(),
|
|
||||||
definitions : vardefs(false, true),
|
|
||||||
end : prev()
|
end : prev()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -1242,7 +1224,7 @@ function parse($TEXT, options) {
|
|||||||
break;
|
break;
|
||||||
case "operator":
|
case "operator":
|
||||||
if (!is_identifier_string(tok.value)) {
|
if (!is_identifier_string(tok.value)) {
|
||||||
croak("SyntaxError: Invalid getter/setter name: " + tok.value,
|
croak("Invalid getter/setter name: " + tok.value,
|
||||||
tok.line, tok.col, tok.pos);
|
tok.line, tok.col, tok.pos);
|
||||||
}
|
}
|
||||||
ret = _make_symbol(AST_SymbolRef);
|
ret = _make_symbol(AST_SymbolRef);
|
||||||
@@ -1308,6 +1290,10 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var create_accessor = embed_tokens(function() {
|
||||||
|
return function_(AST_Accessor);
|
||||||
|
});
|
||||||
|
|
||||||
var object_ = embed_tokens(function() {
|
var object_ = embed_tokens(function() {
|
||||||
expect("{");
|
expect("{");
|
||||||
var first = true, a = [];
|
var first = true, a = [];
|
||||||
@@ -1320,11 +1306,16 @@ function parse($TEXT, options) {
|
|||||||
var type = start.type;
|
var type = start.type;
|
||||||
var name = as_property_name();
|
var name = as_property_name();
|
||||||
if (type == "name" && !is("punc", ":")) {
|
if (type == "name" && !is("punc", ":")) {
|
||||||
|
var key = new AST_SymbolAccessor({
|
||||||
|
start: S.token,
|
||||||
|
name: as_property_name(),
|
||||||
|
end: prev()
|
||||||
|
});
|
||||||
if (name == "get") {
|
if (name == "get") {
|
||||||
a.push(new AST_ObjectGetter({
|
a.push(new AST_ObjectGetter({
|
||||||
start : start,
|
start : start,
|
||||||
key : as_atom_node(),
|
key : key,
|
||||||
value : function_(AST_Accessor),
|
value : create_accessor(),
|
||||||
end : prev()
|
end : prev()
|
||||||
}));
|
}));
|
||||||
continue;
|
continue;
|
||||||
@@ -1332,8 +1323,8 @@ function parse($TEXT, options) {
|
|||||||
if (name == "set") {
|
if (name == "set") {
|
||||||
a.push(new AST_ObjectSetter({
|
a.push(new AST_ObjectSetter({
|
||||||
start : start,
|
start : start,
|
||||||
key : as_atom_node(),
|
key : key,
|
||||||
value : function_(AST_Accessor),
|
value : create_accessor(),
|
||||||
end : prev()
|
end : prev()
|
||||||
}));
|
}));
|
||||||
continue;
|
continue;
|
||||||
@@ -1354,14 +1345,15 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
function as_property_name() {
|
function as_property_name() {
|
||||||
var tmp = S.token;
|
var tmp = S.token;
|
||||||
next();
|
|
||||||
switch (tmp.type) {
|
switch (tmp.type) {
|
||||||
|
case "operator":
|
||||||
|
if (!KEYWORDS(tmp.value)) unexpected();
|
||||||
case "num":
|
case "num":
|
||||||
case "string":
|
case "string":
|
||||||
case "name":
|
case "name":
|
||||||
case "operator":
|
|
||||||
case "keyword":
|
case "keyword":
|
||||||
case "atom":
|
case "atom":
|
||||||
|
next();
|
||||||
return tmp.value;
|
return tmp.value;
|
||||||
default:
|
default:
|
||||||
unexpected();
|
unexpected();
|
||||||
@@ -1370,16 +1362,9 @@ function parse($TEXT, options) {
|
|||||||
|
|
||||||
function as_name() {
|
function as_name() {
|
||||||
var tmp = S.token;
|
var tmp = S.token;
|
||||||
|
if (tmp.type != "name") unexpected();
|
||||||
next();
|
next();
|
||||||
switch (tmp.type) {
|
return tmp.value;
|
||||||
case "name":
|
|
||||||
case "operator":
|
|
||||||
case "keyword":
|
|
||||||
case "atom":
|
|
||||||
return tmp.value;
|
|
||||||
default:
|
|
||||||
unexpected();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function _make_symbol(type) {
|
function _make_symbol(type) {
|
||||||
@@ -1391,12 +1376,20 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function strict_verify_symbol(sym) {
|
||||||
|
if (sym.name == "arguments" || sym.name == "eval")
|
||||||
|
croak("Unexpected " + sym.name + " in strict mode", sym.start.line, sym.start.col, sym.start.pos);
|
||||||
|
}
|
||||||
|
|
||||||
function as_symbol(type, noerror) {
|
function as_symbol(type, noerror) {
|
||||||
if (!is("name")) {
|
if (!is("name")) {
|
||||||
if (!noerror) croak("SyntaxError: Name expected");
|
if (!noerror) croak("Name expected");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var sym = _make_symbol(type);
|
var sym = _make_symbol(type);
|
||||||
|
if (S.input.has_directive("use strict") && sym instanceof AST_SymbolDeclaration) {
|
||||||
|
strict_verify_symbol(sym);
|
||||||
|
}
|
||||||
next();
|
next();
|
||||||
return sym;
|
return sym;
|
||||||
};
|
};
|
||||||
@@ -1440,14 +1433,14 @@ function parse($TEXT, options) {
|
|||||||
if (is("operator") && UNARY_PREFIX(start.value)) {
|
if (is("operator") && UNARY_PREFIX(start.value)) {
|
||||||
next();
|
next();
|
||||||
handle_regexp();
|
handle_regexp();
|
||||||
var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls));
|
var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls));
|
||||||
ex.start = start;
|
ex.start = start;
|
||||||
ex.end = prev();
|
ex.end = prev();
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
var val = expr_atom(allow_calls);
|
var val = expr_atom(allow_calls);
|
||||||
while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
|
while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
|
||||||
val = make_unary(AST_UnaryPostfix, S.token.value, val);
|
val = make_unary(AST_UnaryPostfix, S.token, val);
|
||||||
val.start = start;
|
val.start = start;
|
||||||
val.end = S.token;
|
val.end = S.token;
|
||||||
next();
|
next();
|
||||||
@@ -1455,9 +1448,19 @@ function parse($TEXT, options) {
|
|||||||
return val;
|
return val;
|
||||||
};
|
};
|
||||||
|
|
||||||
function make_unary(ctor, op, expr) {
|
function make_unary(ctor, token, expr) {
|
||||||
if ((op == "++" || op == "--") && !is_assignable(expr))
|
var op = token.value;
|
||||||
croak("SyntaxError: Invalid use of " + op + " operator");
|
switch (op) {
|
||||||
|
case "++":
|
||||||
|
case "--":
|
||||||
|
if (!is_assignable(expr))
|
||||||
|
croak("Invalid use of " + op + " operator", token.line, token.col, token.pos);
|
||||||
|
break;
|
||||||
|
case "delete":
|
||||||
|
if (expr instanceof AST_SymbolRef && S.input.has_directive("use strict"))
|
||||||
|
croak("Calling delete on expression not allowed in strict mode", expr.start.line, expr.start.col, expr.start.pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
return new ctor({ operator: op, expression: expr });
|
return new ctor({ operator: op, expression: expr });
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1502,9 +1505,7 @@ function parse($TEXT, options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function is_assignable(expr) {
|
function is_assignable(expr) {
|
||||||
if (!options.strict) return true;
|
return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef;
|
||||||
if (expr instanceof AST_This) return false;
|
|
||||||
return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var maybe_assign = function(no_in) {
|
var maybe_assign = function(no_in) {
|
||||||
@@ -1521,24 +1522,25 @@ function parse($TEXT, options) {
|
|||||||
end : prev()
|
end : prev()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
croak("SyntaxError: Invalid assignment");
|
croak("Invalid assignment");
|
||||||
}
|
}
|
||||||
return left;
|
return left;
|
||||||
};
|
};
|
||||||
|
|
||||||
var expression = function(commas, no_in) {
|
var expression = function(commas, no_in) {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
var expr = maybe_assign(no_in);
|
var exprs = [];
|
||||||
if (commas && is("punc", ",")) {
|
while (true) {
|
||||||
|
exprs.push(maybe_assign(no_in));
|
||||||
|
if (!commas || !is("punc", ",")) break;
|
||||||
next();
|
next();
|
||||||
return new AST_Seq({
|
commas = true;
|
||||||
start : start,
|
|
||||||
car : expr,
|
|
||||||
cdr : expression(true, no_in),
|
|
||||||
end : peek()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return expr;
|
return exprs.length == 1 ? exprs[0] : new AST_Sequence({
|
||||||
|
start : start,
|
||||||
|
expressions : exprs,
|
||||||
|
end : peek()
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function in_loop(cont) {
|
function in_loop(cont) {
|
||||||
|
|||||||
@@ -43,8 +43,16 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function find_builtins() {
|
function find_builtins(reserved) {
|
||||||
var a = [];
|
// NaN will be included due to Number.NaN
|
||||||
|
[
|
||||||
|
"null",
|
||||||
|
"true",
|
||||||
|
"false",
|
||||||
|
"Infinity",
|
||||||
|
"-Infinity",
|
||||||
|
"undefined",
|
||||||
|
].forEach(add);
|
||||||
[ Object, Array, Function, Number,
|
[ Object, Array, Function, Number,
|
||||||
String, Boolean, Error, Math,
|
String, Boolean, Error, Math,
|
||||||
Date, RegExp
|
Date, RegExp
|
||||||
@@ -55,23 +63,23 @@ function find_builtins() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
function add(name) {
|
function add(name) {
|
||||||
push_uniq(a, name);
|
push_uniq(reserved, name);
|
||||||
}
|
}
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mangle_properties(ast, options) {
|
function mangle_properties(ast, options) {
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
reserved : null,
|
builtins: false,
|
||||||
cache : null,
|
cache: null,
|
||||||
only_cache : false,
|
debug: false,
|
||||||
regex : null,
|
keep_quoted: false,
|
||||||
ignore_quoted : false
|
only_cache: false,
|
||||||
|
regex: null,
|
||||||
|
reserved: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
var reserved = options.reserved;
|
var reserved = options.reserved || [];
|
||||||
if (reserved == null)
|
if (!options.builtins) find_builtins(reserved);
|
||||||
reserved = find_builtins();
|
|
||||||
|
|
||||||
var cache = options.cache;
|
var cache = options.cache;
|
||||||
if (cache == null) {
|
if (cache == null) {
|
||||||
@@ -82,16 +90,25 @@ function mangle_properties(ast, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var regex = options.regex;
|
var regex = options.regex;
|
||||||
var ignore_quoted = options.ignore_quoted;
|
var keep_quoted = options.keep_quoted;
|
||||||
|
|
||||||
|
// note debug is either false (disabled), or a string of the debug suffix to use (enabled).
|
||||||
|
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
|
||||||
|
// the same as passing an empty string.
|
||||||
|
var debug = options.debug !== false;
|
||||||
|
var debug_name_suffix;
|
||||||
|
if (debug) {
|
||||||
|
debug_name_suffix = (options.debug === true ? "" : options.debug);
|
||||||
|
}
|
||||||
|
|
||||||
var names_to_mangle = [];
|
var names_to_mangle = [];
|
||||||
var unmangleable = [];
|
var unmangleable = [];
|
||||||
var ignored = {};
|
var to_keep = {};
|
||||||
|
|
||||||
// step 1: find candidates to mangle
|
// step 1: find candidates to mangle
|
||||||
ast.walk(new TreeWalker(function(node){
|
ast.walk(new TreeWalker(function(node){
|
||||||
if (node instanceof AST_ObjectKeyVal) {
|
if (node instanceof AST_ObjectKeyVal) {
|
||||||
add(node.key, ignore_quoted && node.quote);
|
add(node.key, keep_quoted && node.quote);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_ObjectProperty) {
|
else if (node instanceof AST_ObjectProperty) {
|
||||||
// setter or getter, since KeyVal is handled above
|
// setter or getter, since KeyVal is handled above
|
||||||
@@ -101,14 +118,14 @@ function mangle_properties(ast, options) {
|
|||||||
add(node.property);
|
add(node.property);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_Sub) {
|
else if (node instanceof AST_Sub) {
|
||||||
addStrings(node.property, ignore_quoted);
|
addStrings(node.property, keep_quoted);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// step 2: transform the tree, renaming properties
|
// step 2: transform the tree, renaming properties
|
||||||
return ast.transform(new TreeTransformer(function(node){
|
return ast.transform(new TreeTransformer(function(node){
|
||||||
if (node instanceof AST_ObjectKeyVal) {
|
if (node instanceof AST_ObjectKeyVal) {
|
||||||
if (!(ignore_quoted && node.quote))
|
if (!(keep_quoted && node.quote))
|
||||||
node.key = mangle(node.key);
|
node.key = mangle(node.key);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_ObjectProperty) {
|
else if (node instanceof AST_ObjectProperty) {
|
||||||
@@ -119,7 +136,7 @@ function mangle_properties(ast, options) {
|
|||||||
node.property = mangle(node.property);
|
node.property = mangle(node.property);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_Sub) {
|
else if (node instanceof AST_Sub) {
|
||||||
if (!ignore_quoted)
|
if (!keep_quoted)
|
||||||
node.property = mangleStrings(node.property);
|
node.property = mangleStrings(node.property);
|
||||||
}
|
}
|
||||||
// else if (node instanceof AST_String) {
|
// else if (node instanceof AST_String) {
|
||||||
@@ -144,21 +161,21 @@ function mangle_properties(ast, options) {
|
|||||||
if (options.only_cache) {
|
if (options.only_cache) {
|
||||||
return cache.props.has(name);
|
return cache.props.has(name);
|
||||||
}
|
}
|
||||||
if (/^[0-9.]+$/.test(name)) return false;
|
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function should_mangle(name) {
|
function should_mangle(name) {
|
||||||
if (ignore_quoted && name in ignored) return false;
|
if (keep_quoted && name in to_keep) return false;
|
||||||
if (regex && !regex.test(name)) return false;
|
if (regex && !regex.test(name)) return false;
|
||||||
if (reserved.indexOf(name) >= 0) return false;
|
if (reserved.indexOf(name) >= 0) return false;
|
||||||
return cache.props.has(name)
|
return cache.props.has(name)
|
||||||
|| names_to_mangle.indexOf(name) >= 0;
|
|| names_to_mangle.indexOf(name) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function add(name, ignore) {
|
function add(name, keep) {
|
||||||
if (ignore) {
|
if (keep) {
|
||||||
ignored[name] = true;
|
to_keep[name] = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,25 +194,41 @@ function mangle_properties(ast, options) {
|
|||||||
|
|
||||||
var mangled = cache.props.get(name);
|
var mangled = cache.props.get(name);
|
||||||
if (!mangled) {
|
if (!mangled) {
|
||||||
do {
|
if (debug) {
|
||||||
mangled = base54(++cache.cname);
|
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
|
||||||
} while (!can_mangle(mangled));
|
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
|
||||||
|
|
||||||
|
if (can_mangle(debug_mangled) && !(keep_quoted && debug_mangled in to_keep)) {
|
||||||
|
mangled = debug_mangled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// either debug mode is off, or it is on and we could not use the mangled name
|
||||||
|
if (!mangled) {
|
||||||
|
// Note: `can_mangle()` does not check if the name collides with the `to_keep` set
|
||||||
|
// (filled with quoted properties when `keep_quoted` is set). Make sure we add this
|
||||||
|
// check so we don't collide with a quoted name.
|
||||||
|
do {
|
||||||
|
mangled = base54(++cache.cname);
|
||||||
|
} while (!can_mangle(mangled) || keep_quoted && mangled in to_keep);
|
||||||
|
}
|
||||||
|
|
||||||
cache.props.set(name, mangled);
|
cache.props.set(name, mangled);
|
||||||
}
|
}
|
||||||
return mangled;
|
return mangled;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStrings(node, ignore) {
|
function addStrings(node, keep) {
|
||||||
var out = {};
|
var out = {};
|
||||||
try {
|
try {
|
||||||
(function walk(node){
|
(function walk(node){
|
||||||
node.walk(new TreeWalker(function(node){
|
node.walk(new TreeWalker(function(node){
|
||||||
if (node instanceof AST_Seq) {
|
if (node instanceof AST_Sequence) {
|
||||||
walk(node.cdr);
|
walk(node.expressions[node.expressions.length - 1]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_String) {
|
if (node instanceof AST_String) {
|
||||||
add(node.value, ignore);
|
add(node.value, keep);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Conditional) {
|
if (node instanceof AST_Conditional) {
|
||||||
@@ -213,8 +246,9 @@ function mangle_properties(ast, options) {
|
|||||||
|
|
||||||
function mangleStrings(node) {
|
function mangleStrings(node) {
|
||||||
return node.transform(new TreeTransformer(function(node){
|
return node.transform(new TreeTransformer(function(node){
|
||||||
if (node instanceof AST_Seq) {
|
if (node instanceof AST_Sequence) {
|
||||||
node.cdr = mangleStrings(node.cdr);
|
var last = node.expressions.length - 1;
|
||||||
|
node.expressions[last] = mangleStrings(node.expressions[last]);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_String) {
|
else if (node instanceof AST_String) {
|
||||||
node.value = mangle(node.value);
|
node.value = mangle(node.value);
|
||||||
@@ -226,5 +260,4 @@ function mangle_properties(ast, options) {
|
|||||||
return node;
|
return node;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
266
lib/scope.js
266
lib/scope.js
@@ -51,7 +51,6 @@ function SymbolDef(scope, index, orig) {
|
|||||||
this.global = false;
|
this.global = false;
|
||||||
this.mangled_name = null;
|
this.mangled_name = null;
|
||||||
this.undeclared = false;
|
this.undeclared = false;
|
||||||
this.constant = false;
|
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.id = SymbolDef.next_id++;
|
this.id = SymbolDef.next_id++;
|
||||||
};
|
};
|
||||||
@@ -76,9 +75,14 @@ SymbolDef.prototype = {
|
|||||||
}
|
}
|
||||||
else if (!this.mangled_name && !this.unmangleable(options)) {
|
else if (!this.mangled_name && !this.unmangleable(options)) {
|
||||||
var s = this.scope;
|
var s = this.scope;
|
||||||
if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda)
|
var sym = this.orig[0];
|
||||||
|
if (options.ie8 && sym instanceof AST_SymbolLambda)
|
||||||
s = s.parent_scope;
|
s = s.parent_scope;
|
||||||
this.mangled_name = s.next_mangled(options, this);
|
var def;
|
||||||
|
if (this.defun && (def = this.defun.variables.get(this.name))) {
|
||||||
|
this.mangled_name = def.mangled_name || def.name;
|
||||||
|
} else
|
||||||
|
this.mangled_name = s.next_mangled(options, this);
|
||||||
if (this.global && cache) {
|
if (this.global && cache) {
|
||||||
cache.set(this.name, this.mangled_name);
|
cache.set(this.name, this.mangled_name);
|
||||||
}
|
}
|
||||||
@@ -88,8 +92,8 @@ SymbolDef.prototype = {
|
|||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
screw_ie8: true,
|
cache: null,
|
||||||
cache: null
|
ie8: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// pass 1: setup scope chaining and handle definitions
|
// pass 1: setup scope chaining and handle definitions
|
||||||
@@ -97,26 +101,23 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
var scope = self.parent_scope = null;
|
var scope = self.parent_scope = null;
|
||||||
var labels = new Dictionary();
|
var labels = new Dictionary();
|
||||||
var defun = null;
|
var defun = null;
|
||||||
var last_var_had_const_pragma = false;
|
|
||||||
var nesting = 0;
|
|
||||||
var tw = new TreeWalker(function(node, descend){
|
var tw = new TreeWalker(function(node, descend){
|
||||||
if (options.screw_ie8 && node instanceof AST_Catch) {
|
if (node instanceof AST_Catch) {
|
||||||
var save_scope = scope;
|
var save_scope = scope;
|
||||||
scope = new AST_Scope(node);
|
scope = new AST_Scope(node);
|
||||||
scope.init_scope_vars(nesting);
|
scope.init_scope_vars(save_scope);
|
||||||
scope.parent_scope = save_scope;
|
|
||||||
descend();
|
descend();
|
||||||
scope = save_scope;
|
scope = save_scope;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Scope) {
|
if (node instanceof AST_Scope) {
|
||||||
node.init_scope_vars(nesting);
|
node.init_scope_vars(scope);
|
||||||
var save_scope = node.parent_scope = scope;
|
var save_scope = scope;
|
||||||
var save_defun = defun;
|
var save_defun = defun;
|
||||||
var save_labels = labels;
|
var save_labels = labels;
|
||||||
defun = scope = node;
|
defun = scope = node;
|
||||||
labels = new Dictionary();
|
labels = new Dictionary();
|
||||||
++nesting; descend(); --nesting;
|
descend();
|
||||||
scope = save_scope;
|
scope = save_scope;
|
||||||
defun = save_defun;
|
defun = save_defun;
|
||||||
labels = save_labels;
|
labels = save_labels;
|
||||||
@@ -155,18 +156,19 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
// later.
|
// later.
|
||||||
(node.scope = defun.parent_scope).def_function(node);
|
(node.scope = defun.parent_scope).def_function(node);
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_Var) {
|
else if (node instanceof AST_SymbolVar) {
|
||||||
last_var_had_const_pragma = node.has_const_pragma();
|
defun.def_variable(node);
|
||||||
}
|
if (defun !== scope) {
|
||||||
else if (node instanceof AST_SymbolVar
|
node.mark_enclosed(options);
|
||||||
|| node instanceof AST_SymbolConst) {
|
var def = scope.find_variable(node);
|
||||||
var def = defun.def_variable(node);
|
if (node.thedef !== def) {
|
||||||
def.constant = node instanceof AST_SymbolConst || last_var_had_const_pragma;
|
node.thedef = def;
|
||||||
def.init = tw.parent().value;
|
node.reference(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_SymbolCatch) {
|
else if (node instanceof AST_SymbolCatch) {
|
||||||
(options.screw_ie8 ? scope : defun)
|
scope.def_variable(node).defun = defun;
|
||||||
.def_variable(node);
|
|
||||||
}
|
}
|
||||||
else if (node instanceof AST_LabelRef) {
|
else if (node instanceof AST_LabelRef) {
|
||||||
var sym = labels.get(node.name);
|
var sym = labels.get(node.name);
|
||||||
@@ -203,64 +205,93 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var sym = node.scope.find_variable(name);
|
var sym = node.scope.find_variable(name);
|
||||||
if (!sym) {
|
if (node.scope instanceof AST_Lambda && name == "arguments") {
|
||||||
var g;
|
node.scope.uses_arguments = true;
|
||||||
if (globals.has(name)) {
|
|
||||||
g = globals.get(name);
|
|
||||||
} else {
|
|
||||||
g = new SymbolDef(self, globals.size(), node);
|
|
||||||
g.undeclared = true;
|
|
||||||
g.global = true;
|
|
||||||
globals.set(name, g);
|
|
||||||
}
|
|
||||||
node.thedef = g;
|
|
||||||
if (func && name == "arguments") {
|
|
||||||
func.uses_arguments = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
node.thedef = sym;
|
|
||||||
}
|
}
|
||||||
node.reference();
|
if (!sym) {
|
||||||
|
sym = self.def_global(node);
|
||||||
|
}
|
||||||
|
node.thedef = sym;
|
||||||
|
node.reference(options);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.walk(tw);
|
self.walk(tw);
|
||||||
|
|
||||||
|
// pass 3: fix up any scoping issue with IE8
|
||||||
|
if (options.ie8) {
|
||||||
|
self.walk(new TreeWalker(function(node, descend) {
|
||||||
|
if (node instanceof AST_SymbolCatch) {
|
||||||
|
var name = node.name;
|
||||||
|
var refs = node.thedef.references;
|
||||||
|
var scope = node.thedef.defun;
|
||||||
|
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
|
||||||
|
refs.forEach(function(ref) {
|
||||||
|
ref.thedef = def;
|
||||||
|
ref.reference(options);
|
||||||
|
});
|
||||||
|
node.thedef = def;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
if (options.cache) {
|
if (options.cache) {
|
||||||
this.cname = options.cache.cname;
|
this.cname = options.cache.cname;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
|
AST_Toplevel.DEFMETHOD("def_global", function(node){
|
||||||
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
var globals = this.globals, name = node.name;
|
||||||
this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
|
if (globals.has(name)) {
|
||||||
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
return globals.get(name);
|
||||||
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
} else {
|
||||||
this.parent_scope = null; // the parent scope
|
var g = new SymbolDef(this, globals.size(), node);
|
||||||
this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
|
g.undeclared = true;
|
||||||
this.cname = -1; // the current index for mangling functions/variables
|
g.global = true;
|
||||||
this.nesting = nesting; // the nesting level of this scope (0 means toplevel)
|
globals.set(name, g);
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){
|
||||||
|
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
||||||
|
this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
|
||||||
|
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
||||||
|
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
||||||
|
this.parent_scope = parent_scope; // the parent scope
|
||||||
|
this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
|
||||||
|
this.cname = -1; // the current index for mangling functions/variables
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
|
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
|
||||||
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
|
AST_Scope.prototype.init_scope_vars.apply(this, arguments);
|
||||||
this.uses_arguments = false;
|
this.uses_arguments = false;
|
||||||
|
this.def_variable(new AST_SymbolFunarg({
|
||||||
var symbol = new AST_VarDef({ name: "arguments", start: this.start, end: this.end });
|
name: "arguments",
|
||||||
var def = new SymbolDef(this, this.variables.size(), symbol);
|
start: this.start,
|
||||||
this.variables.set(symbol.name, def);
|
end: this.end
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_SymbolRef.DEFMETHOD("reference", function() {
|
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
|
||||||
var def = this.definition();
|
var def = this.definition();
|
||||||
def.references.push(this);
|
|
||||||
var s = this.scope;
|
var s = this.scope;
|
||||||
while (s) {
|
while (s) {
|
||||||
push_uniq(s.enclosed, def);
|
push_uniq(s.enclosed, def);
|
||||||
|
if (options.keep_fnames) {
|
||||||
|
s.functions.each(function(d) {
|
||||||
|
push_uniq(def.scope.enclosed, d);
|
||||||
|
});
|
||||||
|
}
|
||||||
if (s === def.scope) break;
|
if (s === def.scope) break;
|
||||||
s = s.parent_scope;
|
s = s.parent_scope;
|
||||||
}
|
}
|
||||||
this.frame = this.scope.nesting - def.scope.nesting;
|
});
|
||||||
|
|
||||||
|
AST_Symbol.DEFMETHOD("reference", function(options) {
|
||||||
|
this.definition().references.push(this);
|
||||||
|
this.mark_enclosed(options);
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("find_variable", function(name){
|
AST_Scope.DEFMETHOD("find_variable", function(name){
|
||||||
@@ -293,8 +324,8 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){
|
|||||||
if (!is_identifier(m)) continue; // skip over "do"
|
if (!is_identifier(m)) continue; // skip over "do"
|
||||||
|
|
||||||
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
|
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
|
||||||
// shadow a name excepted from mangling.
|
// shadow a name reserved from mangling.
|
||||||
if (options.except.indexOf(m) >= 0) continue;
|
if (options.reserved.indexOf(m) >= 0) continue;
|
||||||
|
|
||||||
// we must ensure that the mangled name does not shadow a name
|
// we must ensure that the mangled name does not shadow a name
|
||||||
// from some parent scope that is referenced in this or in
|
// from some parent scope that is referenced in this or in
|
||||||
@@ -325,20 +356,10 @@ AST_Function.DEFMETHOD("next_mangled", function(options, def){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Scope.DEFMETHOD("references", function(sym){
|
|
||||||
if (sym instanceof AST_Symbol) sym = sym.definition();
|
|
||||||
return this.enclosed.indexOf(sym) < 0 ? null : sym;
|
|
||||||
});
|
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("unmangleable", function(options){
|
AST_Symbol.DEFMETHOD("unmangleable", function(options){
|
||||||
return this.definition().unmangleable(options);
|
return this.definition().unmangleable(options);
|
||||||
});
|
});
|
||||||
|
|
||||||
// property accessors are not mangleable
|
|
||||||
AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// labels are always mangleable
|
// labels are always mangleable
|
||||||
AST_Label.DEFMETHOD("unmangleable", function(){
|
AST_Label.DEFMETHOD("unmangleable", function(){
|
||||||
return false;
|
return false;
|
||||||
@@ -369,20 +390,13 @@ AST_Symbol.DEFMETHOD("global", function(){
|
|||||||
return this.definition().global;
|
return this.definition().global;
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Var.DEFMETHOD("has_const_pragma", function() {
|
|
||||||
var comments_before = this.start && this.start.comments_before;
|
|
||||||
var lastComment = comments_before && comments_before[comments_before.length - 1];
|
|
||||||
return lastComment && /@const\b/.test(lastComment.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
|
||||||
return defaults(options, {
|
return defaults(options, {
|
||||||
except : [],
|
|
||||||
eval : false,
|
eval : false,
|
||||||
sort : false, // Ignored. Flag retained for backwards compatibility.
|
ie8 : false,
|
||||||
|
keep_fnames : false,
|
||||||
|
reserved : [],
|
||||||
toplevel : false,
|
toplevel : false,
|
||||||
screw_ie8 : true,
|
|
||||||
keep_fnames : false
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -390,7 +404,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
|||||||
options = this._default_mangler_options(options);
|
options = this._default_mangler_options(options);
|
||||||
|
|
||||||
// Never mangle arguments
|
// Never mangle arguments
|
||||||
options.except.push('arguments');
|
options.reserved.push('arguments');
|
||||||
|
|
||||||
// We only need to mangle declaration nodes. Special logic wired
|
// We only need to mangle declaration nodes. Special logic wired
|
||||||
// into the code generator will display the mangled name if it's
|
// into the code generator will display the mangled name if it's
|
||||||
@@ -401,7 +415,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
|||||||
|
|
||||||
if (options.cache) {
|
if (options.cache) {
|
||||||
this.globals.each(function(symbol){
|
this.globals.each(function(symbol){
|
||||||
if (options.except.indexOf(symbol.name) < 0) {
|
if (options.reserved.indexOf(symbol.name) < 0) {
|
||||||
to_mangle.push(symbol);
|
to_mangle.push(symbol);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -418,7 +432,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
|||||||
if (node instanceof AST_Scope) {
|
if (node instanceof AST_Scope) {
|
||||||
var p = tw.parent(), a = [];
|
var p = tw.parent(), a = [];
|
||||||
node.variables.each(function(symbol){
|
node.variables.each(function(symbol){
|
||||||
if (options.except.indexOf(symbol.name) < 0) {
|
if (options.reserved.indexOf(symbol.name) < 0) {
|
||||||
a.push(symbol);
|
a.push(symbol);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -431,7 +445,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
|||||||
node.mangled_name = name;
|
node.mangled_name = name;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
|
if (!options.ie8 && node instanceof AST_SymbolCatch) {
|
||||||
to_mangle.push(node.definition());
|
to_mangle.push(node.definition());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -471,8 +485,6 @@ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
|
|||||||
}
|
}
|
||||||
else if (node instanceof AST_Var)
|
else if (node instanceof AST_Var)
|
||||||
base54.consider("var");
|
base54.consider("var");
|
||||||
else if (node instanceof AST_Const)
|
|
||||||
base54.consider("const");
|
|
||||||
else if (node instanceof AST_Lambda)
|
else if (node instanceof AST_Lambda)
|
||||||
base54.consider("function");
|
base54.consider("function");
|
||||||
else if (node instanceof AST_For)
|
else if (node instanceof AST_For)
|
||||||
@@ -552,89 +564,3 @@ var base54 = (function() {
|
|||||||
};
|
};
|
||||||
return base54;
|
return base54;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
|
|
||||||
options = defaults(options, {
|
|
||||||
undeclared : false, // this makes a lot of noise
|
|
||||||
unreferenced : true,
|
|
||||||
assign_to_global : true,
|
|
||||||
func_arguments : true,
|
|
||||||
nested_defuns : true,
|
|
||||||
eval : true
|
|
||||||
});
|
|
||||||
var tw = new TreeWalker(function(node){
|
|
||||||
if (options.undeclared
|
|
||||||
&& node instanceof AST_SymbolRef
|
|
||||||
&& node.undeclared())
|
|
||||||
{
|
|
||||||
// XXX: this also warns about JS standard names,
|
|
||||||
// i.e. Object, Array, parseInt etc. Should add a list of
|
|
||||||
// exceptions.
|
|
||||||
AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
|
|
||||||
name: node.name,
|
|
||||||
file: node.start.file,
|
|
||||||
line: node.start.line,
|
|
||||||
col: node.start.col
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (options.assign_to_global)
|
|
||||||
{
|
|
||||||
var sym = null;
|
|
||||||
if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef)
|
|
||||||
sym = node.left;
|
|
||||||
else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef)
|
|
||||||
sym = node.init;
|
|
||||||
if (sym
|
|
||||||
&& (sym.undeclared()
|
|
||||||
|| (sym.global() && sym.scope !== sym.definition().scope))) {
|
|
||||||
AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
|
|
||||||
msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
|
|
||||||
name: sym.name,
|
|
||||||
file: sym.start.file,
|
|
||||||
line: sym.start.line,
|
|
||||||
col: sym.start.col
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (options.eval
|
|
||||||
&& node instanceof AST_SymbolRef
|
|
||||||
&& node.undeclared()
|
|
||||||
&& node.name == "eval") {
|
|
||||||
AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
|
|
||||||
}
|
|
||||||
if (options.unreferenced
|
|
||||||
&& (node instanceof AST_SymbolDeclaration || node instanceof AST_Label)
|
|
||||||
&& !(node instanceof AST_SymbolCatch)
|
|
||||||
&& node.unreferenced()) {
|
|
||||||
AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
|
|
||||||
type: node instanceof AST_Label ? "Label" : "Symbol",
|
|
||||||
name: node.name,
|
|
||||||
file: node.start.file,
|
|
||||||
line: node.start.line,
|
|
||||||
col: node.start.col
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (options.func_arguments
|
|
||||||
&& node instanceof AST_Lambda
|
|
||||||
&& node.uses_arguments) {
|
|
||||||
AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
|
|
||||||
name: node.name ? node.name.name : "anonymous",
|
|
||||||
file: node.start.file,
|
|
||||||
line: node.start.line,
|
|
||||||
col: node.start.col
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (options.nested_defuns
|
|
||||||
&& node instanceof AST_Defun
|
|
||||||
&& !(tw.parent() instanceof AST_Scope)) {
|
|
||||||
AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", {
|
|
||||||
name: node.name.name,
|
|
||||||
type: tw.parent().TYPE,
|
|
||||||
file: node.start.file,
|
|
||||||
line: node.start.line,
|
|
||||||
col: node.start.col
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.walk(tw);
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ function SourceMap(options) {
|
|||||||
var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
|
var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
|
||||||
|
|
||||||
if (orig_map && Array.isArray(options.orig.sources)) {
|
if (orig_map && Array.isArray(options.orig.sources)) {
|
||||||
options.orig.sources.forEach(function(source) {
|
orig_map._sources.toArray().forEach(function(source) {
|
||||||
var sourceContent = orig_map.sourceContentFor(source, true);
|
var sourceContent = orig_map.sourceContentFor(source, true);
|
||||||
if (sourceContent) {
|
if (sourceContent) {
|
||||||
generator.setSourceContent(source, sourceContent);
|
generator.setSourceContent(source, sourceContent);
|
||||||
|
|||||||
@@ -174,9 +174,8 @@ TreeTransformer.prototype = new TreeWalker;
|
|||||||
self.args = do_list(self.args, tw);
|
self.args = do_list(self.args, tw);
|
||||||
});
|
});
|
||||||
|
|
||||||
_(AST_Seq, function(self, tw){
|
_(AST_Sequence, function(self, tw){
|
||||||
self.car = self.car.transform(tw);
|
self.expressions = do_list(self.expressions, tw);
|
||||||
self.cdr = self.cdr.transform(tw);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
_(AST_Dot, function(self, tw){
|
_(AST_Dot, function(self, tw){
|
||||||
|
|||||||
50
lib/utils.js
50
lib/utils.js
@@ -78,13 +78,28 @@ function repeat_string(str, i) {
|
|||||||
return d;
|
return d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function configure_error_stack(fn) {
|
||||||
|
Object.defineProperty(fn.prototype, "stack", {
|
||||||
|
get: function() {
|
||||||
|
var err = new Error(this.message);
|
||||||
|
err.name = this.name;
|
||||||
|
try {
|
||||||
|
throw err;
|
||||||
|
} catch(e) {
|
||||||
|
return e.stack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function DefaultsError(msg, defs) {
|
function DefaultsError(msg, defs) {
|
||||||
Error.call(this, msg);
|
this.message = msg;
|
||||||
this.msg = msg;
|
|
||||||
this.defs = defs;
|
this.defs = defs;
|
||||||
};
|
};
|
||||||
DefaultsError.prototype = Object.create(Error.prototype);
|
DefaultsError.prototype = Object.create(Error.prototype);
|
||||||
DefaultsError.prototype.constructor = DefaultsError;
|
DefaultsError.prototype.constructor = DefaultsError;
|
||||||
|
DefaultsError.prototype.name = "DefaultsError";
|
||||||
|
configure_error_stack(DefaultsError);
|
||||||
|
|
||||||
DefaultsError.croak = function(msg, defs) {
|
DefaultsError.croak = function(msg, defs) {
|
||||||
throw new DefaultsError(msg, defs);
|
throw new DefaultsError(msg, defs);
|
||||||
@@ -111,7 +126,11 @@ function merge(obj, ext) {
|
|||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
|
|
||||||
function noop() {};
|
function noop() {}
|
||||||
|
function return_false() { return false; }
|
||||||
|
function return_true() { return true; }
|
||||||
|
function return_this() { return this; }
|
||||||
|
function return_null() { return null; }
|
||||||
|
|
||||||
var MAP = (function(){
|
var MAP = (function(){
|
||||||
function MAP(a, f, backwards) {
|
function MAP(a, f, backwards) {
|
||||||
@@ -168,7 +187,7 @@ function push_uniq(array, el) {
|
|||||||
|
|
||||||
function string_template(text, props) {
|
function string_template(text, props) {
|
||||||
return text.replace(/\{(.+?)\}/g, function(str, p){
|
return text.replace(/\{(.+?)\}/g, function(str, p){
|
||||||
return props[p];
|
return props && props[p];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -318,3 +337,26 @@ Dictionary.fromObject = function(obj) {
|
|||||||
function HOP(obj, prop) {
|
function HOP(obj, prop) {
|
||||||
return Object.prototype.hasOwnProperty.call(obj, prop);
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return true if the node at the top of the stack (that means the
|
||||||
|
// innermost node in the current output) is lexically the first in
|
||||||
|
// a statement.
|
||||||
|
function first_in_statement(stack) {
|
||||||
|
var node = stack.parent(-1);
|
||||||
|
for (var i = 0, p; p = stack.parent(i); i++) {
|
||||||
|
if (p instanceof AST_Statement && p.body === node)
|
||||||
|
return true;
|
||||||
|
if ((p instanceof AST_Sequence && p.expressions[0] === node) ||
|
||||||
|
(p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||
|
||||||
|
(p instanceof AST_Dot && p.expression === node ) ||
|
||||||
|
(p instanceof AST_Sub && p.expression === node ) ||
|
||||||
|
(p instanceof AST_Conditional && p.condition === node ) ||
|
||||||
|
(p instanceof AST_Binary && p.left === node ) ||
|
||||||
|
(p instanceof AST_UnaryPostfix && p.expression === node ))
|
||||||
|
{
|
||||||
|
node = p;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
128
npm-shrinkwrap.json
generated
128
npm-shrinkwrap.json
generated
@@ -1,128 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "uglify-js",
|
|
||||||
"version": "2.4.24",
|
|
||||||
"dependencies": {
|
|
||||||
"abbrev": {
|
|
||||||
"version": "1.0.7",
|
|
||||||
"from": "abbrev@>=1.0.0 <2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.7.tgz"
|
|
||||||
},
|
|
||||||
"amdefine": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"from": "amdefine@>=0.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.0.tgz"
|
|
||||||
},
|
|
||||||
"async": {
|
|
||||||
"version": "0.2.10",
|
|
||||||
"from": "async@>=0.2.6 <0.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz"
|
|
||||||
},
|
|
||||||
"camelcase": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"from": "camelcase@>=1.0.2 <2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz"
|
|
||||||
},
|
|
||||||
"decamelize": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"from": "decamelize@>=1.0.0 <2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.0.0.tgz"
|
|
||||||
},
|
|
||||||
"deep-is": {
|
|
||||||
"version": "0.1.3",
|
|
||||||
"from": "deep-is@>=0.1.2 <0.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz"
|
|
||||||
},
|
|
||||||
"esprima": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"from": "esprima@>=1.1.1 <1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz"
|
|
||||||
},
|
|
||||||
"estraverse": {
|
|
||||||
"version": "1.5.1",
|
|
||||||
"from": "estraverse@>=1.5.1 <1.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz"
|
|
||||||
},
|
|
||||||
"esutils": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"from": "esutils@>=1.0.0 <1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz"
|
|
||||||
},
|
|
||||||
"fast-levenshtein": {
|
|
||||||
"version": "1.0.7",
|
|
||||||
"from": "fast-levenshtein@>=1.0.0 <1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz"
|
|
||||||
},
|
|
||||||
"levn": {
|
|
||||||
"version": "0.2.5",
|
|
||||||
"from": "levn@>=0.2.5 <0.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.2.5.tgz"
|
|
||||||
},
|
|
||||||
"nopt": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"from": "nopt@>=2.1.2 <2.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-2.1.2.tgz"
|
|
||||||
},
|
|
||||||
"optionator": {
|
|
||||||
"version": "0.5.0",
|
|
||||||
"from": "optionator@>=0.5.0 <0.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.5.0.tgz"
|
|
||||||
},
|
|
||||||
"prelude-ls": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"from": "prelude-ls@>=1.1.1 <1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz"
|
|
||||||
},
|
|
||||||
"reflect": {
|
|
||||||
"version": "0.1.3",
|
|
||||||
"from": "git://github.com/zaach/reflect.js.git",
|
|
||||||
"resolved": "git://github.com/zaach/reflect.js.git#286bcd79661c96ecc404357d3c0e35fdb54a6967"
|
|
||||||
},
|
|
||||||
"source-map": {
|
|
||||||
"version": "0.5.1",
|
|
||||||
"from": "source-map@>=0.5.1 <0.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.1.tgz"
|
|
||||||
},
|
|
||||||
"type-check": {
|
|
||||||
"version": "0.3.1",
|
|
||||||
"from": "type-check@>=0.3.1 <0.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.1.tgz"
|
|
||||||
},
|
|
||||||
"uglify-js": {
|
|
||||||
"version": "2.4.24",
|
|
||||||
"from": "git://github.com/mishoo/UglifyJS2.git",
|
|
||||||
"resolved": "git://github.com/mishoo/UglifyJS2.git#2a06c7758e24a64740473c8031eafbb7fefa213f",
|
|
||||||
"dependencies": {
|
|
||||||
"source-map": {
|
|
||||||
"version": "0.1.34",
|
|
||||||
"from": "source-map@0.1.34",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uglify-to-browserify": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"from": "uglify-to-browserify@>=1.0.0 <1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz"
|
|
||||||
},
|
|
||||||
"window-size": {
|
|
||||||
"version": "0.1.0",
|
|
||||||
"from": "window-size@0.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz"
|
|
||||||
},
|
|
||||||
"wordwrap": {
|
|
||||||
"version": "0.0.2",
|
|
||||||
"from": "wordwrap@0.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz"
|
|
||||||
},
|
|
||||||
"yargs": {
|
|
||||||
"version": "3.10.0",
|
|
||||||
"from": "yargs@>=3.10.0 <3.11.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz"
|
|
||||||
},
|
|
||||||
"zeparser": {
|
|
||||||
"version": "0.0.7",
|
|
||||||
"from": "git://github.com/qfox/ZeParser.git",
|
|
||||||
"resolved": "git://github.com/qfox/ZeParser.git#c99240c5ba7054c467733800ff38265958a2dda9"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
19
package.json
19
package.json
@@ -4,7 +4,7 @@
|
|||||||
"homepage": "http://lisperator.net/uglifyjs",
|
"homepage": "http://lisperator.net/uglifyjs",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "2.7.2",
|
"version": "3.0.5",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
@@ -29,25 +29,14 @@
|
|||||||
"LICENSE"
|
"LICENSE"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "~0.2.6",
|
"commander": "~2.9.0",
|
||||||
"source-map": "~0.5.1",
|
"source-map": "~0.5.1"
|
||||||
"uglify-to-browserify": "~1.0.0",
|
|
||||||
"yargs": "~3.10.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"acorn": "~0.6.0",
|
"acorn": "~5.0.3",
|
||||||
"escodegen": "~1.3.3",
|
|
||||||
"esfuzz": "~0.3.1",
|
|
||||||
"estraverse": "~1.5.1",
|
|
||||||
"mocha": "~2.3.4"
|
"mocha": "~2.3.4"
|
||||||
},
|
},
|
||||||
"browserify": {
|
|
||||||
"transform": [
|
|
||||||
"uglify-to-browserify"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"shrinkwrap": "rm ./npm-shrinkwrap.json; rm -rf ./node_modules; npm i && npm shrinkwrap && npm outdated",
|
|
||||||
"test": "node test/run-tests.js"
|
"test": "node test/run-tests.js"
|
||||||
},
|
},
|
||||||
"keywords": ["uglify", "uglify-js", "minify", "minifier"]
|
"keywords": ["uglify", "uglify-js", "minify", "minifier"]
|
||||||
|
|||||||
80
test/benchmark.js
Normal file
80
test/benchmark.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#! /usr/bin/env node
|
||||||
|
// -*- js -*-
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var createHash = require("crypto").createHash;
|
||||||
|
var fork = require("child_process").fork;
|
||||||
|
var args = process.argv.slice(2);
|
||||||
|
if (!args.length) {
|
||||||
|
args.push("-mc");
|
||||||
|
}
|
||||||
|
args.push("--stats");
|
||||||
|
var urls = [
|
||||||
|
"https://code.jquery.com/jquery-3.2.1.js",
|
||||||
|
"https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js",
|
||||||
|
"https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.9.0/math.js",
|
||||||
|
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
|
||||||
|
"https://unpkg.com/react@15.3.2/dist/react.js",
|
||||||
|
"http://builds.emberjs.com/tags/v2.11.0/ember.prod.js",
|
||||||
|
"https://cdn.jsdelivr.net/lodash/4.17.4/lodash.js",
|
||||||
|
"https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.js",
|
||||||
|
];
|
||||||
|
var results = {};
|
||||||
|
var remaining = 2 * urls.length;
|
||||||
|
function done() {
|
||||||
|
if (!--remaining) {
|
||||||
|
var failures = [];
|
||||||
|
urls.forEach(function(url) {
|
||||||
|
var info = results[url];
|
||||||
|
console.log();
|
||||||
|
console.log(url);
|
||||||
|
var elapsed = 0;
|
||||||
|
console.log(info.log.replace(/Elapsed: ([0-9]+)\s*/g, function(match, time) {
|
||||||
|
elapsed += 1e-3 * parseInt(time);
|
||||||
|
return "";
|
||||||
|
}));
|
||||||
|
console.log("Run-time:", elapsed.toFixed(3), "s");
|
||||||
|
console.log("Original:", info.input, "bytes");
|
||||||
|
console.log("Uglified:", info.output, "bytes");
|
||||||
|
console.log("SHA1 sum:", info.sha1);
|
||||||
|
if (info.code) {
|
||||||
|
failures.push(url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (failures.length) {
|
||||||
|
console.error("Benchmark failed:");
|
||||||
|
failures.forEach(function(url) {
|
||||||
|
console.error(url);
|
||||||
|
});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
urls.forEach(function(url) {
|
||||||
|
results[url] = {
|
||||||
|
input: 0,
|
||||||
|
output: 0,
|
||||||
|
log: ""
|
||||||
|
};
|
||||||
|
require(url.slice(0, url.indexOf(":"))).get(url, function(res) {
|
||||||
|
var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
|
||||||
|
res.on("data", function(data) {
|
||||||
|
results[url].input += data.length;
|
||||||
|
}).pipe(uglifyjs.stdin);
|
||||||
|
uglifyjs.stdout.on("data", function(data) {
|
||||||
|
results[url].output += data.length;
|
||||||
|
}).pipe(createHash("sha1")).on("data", function(data) {
|
||||||
|
results[url].sha1 = data.toString("hex");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
uglifyjs.stderr.setEncoding("utf8");
|
||||||
|
uglifyjs.stderr.on("data", function(data) {
|
||||||
|
results[url].log += data;
|
||||||
|
});
|
||||||
|
uglifyjs.on("exit", function(code) {
|
||||||
|
results[url].code = code;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
67
test/compress/angular-inject.js
vendored
67
test/compress/angular-inject.js
vendored
@@ -1,67 +0,0 @@
|
|||||||
ng_inject_defun: {
|
|
||||||
options = {
|
|
||||||
angular: true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
/*@ngInject*/
|
|
||||||
function Controller(dependency) {
|
|
||||||
return dependency;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
function Controller(dependency) {
|
|
||||||
return dependency;
|
|
||||||
}
|
|
||||||
Controller.$inject=['dependency']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ng_inject_assignment: {
|
|
||||||
options = {
|
|
||||||
angular: true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
/*@ngInject*/
|
|
||||||
var Controller = function(dependency) {
|
|
||||||
return dependency;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var Controller = function(dependency) {
|
|
||||||
return dependency;
|
|
||||||
}
|
|
||||||
Controller.$inject=['dependency']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ng_inject_inline: {
|
|
||||||
options = {
|
|
||||||
angular: true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
angular.module('a').
|
|
||||||
factory('b',
|
|
||||||
/*@ngInject*/
|
|
||||||
function(dependency) {
|
|
||||||
return dependency;
|
|
||||||
}).
|
|
||||||
directive('c',
|
|
||||||
/*@ngInject*/
|
|
||||||
function(anotherDependency) {
|
|
||||||
return anotherDependency;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
angular.module('a').
|
|
||||||
factory('b',[
|
|
||||||
'dependency',
|
|
||||||
function(dependency) {
|
|
||||||
return dependency;
|
|
||||||
}]).
|
|
||||||
directive('c',[
|
|
||||||
'anotherDependency',
|
|
||||||
function(anotherDependency) {
|
|
||||||
return anotherDependency;
|
|
||||||
}])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,10 +21,19 @@ constant_join: {
|
|||||||
input: {
|
input: {
|
||||||
var a = [ "foo", "bar", "baz" ].join("");
|
var a = [ "foo", "bar", "baz" ].join("");
|
||||||
var a1 = [ "foo", "bar", "baz" ].join();
|
var a1 = [ "foo", "bar", "baz" ].join();
|
||||||
|
var a2 = [ "foo", "bar", "baz" ].join(null);
|
||||||
|
var a3 = [ "foo", "bar", "baz" ].join(void 0);
|
||||||
|
var a4 = [ "foo", , "baz" ].join();
|
||||||
|
var a5 = [ "foo", null, "baz" ].join();
|
||||||
|
var a6 = [ "foo", void 0, "baz" ].join();
|
||||||
var b = [ "foo", 1, 2, 3, "bar" ].join("");
|
var b = [ "foo", 1, 2, 3, "bar" ].join("");
|
||||||
var c = [ boo(), "foo", 1, 2, 3, "bar", bar() ].join("");
|
var c = [ boo(), "foo", 1, 2, 3, "bar", bar() ].join("");
|
||||||
var c1 = [ boo(), bar(), "foo", 1, 2, 3, "bar", bar() ].join("");
|
var c1 = [ boo(), bar(), "foo", 1, 2, 3, "bar", bar() ].join("");
|
||||||
var c2 = [ 1, 2, "foo", "bar", baz() ].join("");
|
var c2 = [ 1, 2, "foo", "bar", baz() ].join("");
|
||||||
|
var c3 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join("");
|
||||||
|
var c4 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join("");
|
||||||
|
var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join();
|
||||||
|
var c6 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join();
|
||||||
var d = [ "foo", 1 + 2 + "bar", "baz" ].join("-");
|
var d = [ "foo", 1 + 2 + "bar", "baz" ].join("-");
|
||||||
var e = [].join(foo + bar);
|
var e = [].join(foo + bar);
|
||||||
var f = [].join("");
|
var f = [].join("");
|
||||||
@@ -33,10 +42,19 @@ constant_join: {
|
|||||||
expect: {
|
expect: {
|
||||||
var a = "foobarbaz";
|
var a = "foobarbaz";
|
||||||
var a1 = "foo,bar,baz";
|
var a1 = "foo,bar,baz";
|
||||||
|
var a2 = "foonullbarnullbaz";
|
||||||
|
var a3 = "foo,bar,baz";
|
||||||
|
var a4 = "foo,,baz";
|
||||||
|
var a5 = "foo,,baz";
|
||||||
|
var a6 = "foo,,baz";
|
||||||
var b = "foo123bar";
|
var b = "foo123bar";
|
||||||
var c = boo() + "foo123bar" + bar();
|
var c = boo() + "foo123bar" + bar();
|
||||||
var c1 = "" + boo() + bar() + "foo123bar" + bar();
|
var c1 = "" + boo() + bar() + "foo123bar" + bar();
|
||||||
var c2 = "12foobar" + baz();
|
var c2 = "12foobar" + baz();
|
||||||
|
var c3 = boo() + bar() + "foo123bar" + bar() + "foo";
|
||||||
|
var c4 = "12foobar" + baz();
|
||||||
|
var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join();
|
||||||
|
var c6 = [ "1,2,,,foo,bar", baz() ].join();
|
||||||
var d = "foo-3bar-baz";
|
var d = "foo-3bar-baz";
|
||||||
var e = [].join(foo + bar);
|
var e = [].join(foo + bar);
|
||||||
var f = "";
|
var f = "";
|
||||||
@@ -72,3 +90,88 @@ constant_join_2: {
|
|||||||
var f = "strstr" + variable + "foobarmoo" + foo;
|
var f = "strstr" + variable + "foobarmoo" + foo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constant_join_3: {
|
||||||
|
options = {
|
||||||
|
unsafe: true,
|
||||||
|
evaluate: true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
var a = [ null ].join();
|
||||||
|
var b = [ , ].join();
|
||||||
|
var c = [ , 1, , 3 ].join();
|
||||||
|
var d = [ foo ].join();
|
||||||
|
var e = [ foo, null, undefined, bar ].join("-");
|
||||||
|
var f = [ foo, bar ].join("");
|
||||||
|
var g = [ null, "foo", null, bar + "baz" ].join("");
|
||||||
|
var h = [ null, "foo", null, bar + "baz" ].join("-");
|
||||||
|
var i = [ "foo" + bar, null, baz + "moo" ].join("");
|
||||||
|
var j = [ foo + "bar", baz ].join("");
|
||||||
|
var k = [ foo, "bar" + baz ].join("");
|
||||||
|
var l = [ foo, bar + "baz" ].join("");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "";
|
||||||
|
var b = "";
|
||||||
|
var c = ",1,,3";
|
||||||
|
var d = "" + foo;
|
||||||
|
var e = [ foo, "-", bar ].join("-");
|
||||||
|
var f = "" + foo + bar;
|
||||||
|
var g = "foo" + bar + "baz";
|
||||||
|
var h = [ "-foo-", bar + "baz" ].join("-");
|
||||||
|
var i = "foo" + bar + baz + "moo";
|
||||||
|
var j = foo + "bar" + baz;
|
||||||
|
var k = foo + "bar" + baz;
|
||||||
|
var l = foo + (bar + "baz");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for_loop: {
|
||||||
|
options = {
|
||||||
|
unsafe : true,
|
||||||
|
unused : true,
|
||||||
|
evaluate : true,
|
||||||
|
reduce_vars : true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function f0() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0, len = a.length; i < len; i++) {
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
a[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < a.length; i++)
|
||||||
|
a[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ ascii_only_true: {
|
|||||||
options = {}
|
options = {}
|
||||||
beautify = {
|
beautify = {
|
||||||
ascii_only : true,
|
ascii_only : true,
|
||||||
screw_ie8 : true,
|
ie8 : false,
|
||||||
beautify : false,
|
beautify : false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -20,7 +20,7 @@ ascii_only_false: {
|
|||||||
options = {}
|
options = {}
|
||||||
beautify = {
|
beautify = {
|
||||||
ascii_only : false,
|
ascii_only : false,
|
||||||
screw_ie8 : true,
|
ie8 : false,
|
||||||
beautify : false,
|
beautify : false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -33,4 +33,3 @@ ascii_only_false: {
|
|||||||
}
|
}
|
||||||
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\\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\'}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,13 +90,13 @@ asm_mixed: {
|
|||||||
}
|
}
|
||||||
function no_asm_GeometricMean(stdlib, foreign, buffer) {
|
function no_asm_GeometricMean(stdlib, foreign, buffer) {
|
||||||
function logSum(start, end) {
|
function logSum(start, end) {
|
||||||
start = 0 | start, end = 0 | end;
|
start |= 0, end |= 0;
|
||||||
var sum = 0, p = 0, q = 0;
|
var sum = 0, p = 0, q = 0;
|
||||||
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
|
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
|
||||||
return +sum;
|
return +sum;
|
||||||
}
|
}
|
||||||
function geometricMean(start, end) {
|
function geometricMean(start, end) {
|
||||||
return start = 0 | start, end = 0 | end, +exp(+logSum(start, end) / +(end - start | 0));
|
return start |= 0, end |= 0, +exp(+logSum(start, end) / +(end - start | 0));
|
||||||
}
|
}
|
||||||
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
|
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
|
||||||
return { geometricMean: geometricMean };
|
return { geometricMean: geometricMean };
|
||||||
|
|||||||
238
test/compress/assignment.js
Normal file
238
test/compress/assignment.js
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
op_equals_left_local_var: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x;
|
||||||
|
|
||||||
|
x = x + 3;
|
||||||
|
x = x - 3;
|
||||||
|
x = x / 3;
|
||||||
|
x = x * 3;
|
||||||
|
x = x >> 3;
|
||||||
|
x = x << 3;
|
||||||
|
x = x >>> 3;
|
||||||
|
x = x | 3;
|
||||||
|
x = x ^ 3;
|
||||||
|
x = x % 3;
|
||||||
|
x = x & 3;
|
||||||
|
|
||||||
|
x = x + g();
|
||||||
|
x = x - g();
|
||||||
|
x = x / g();
|
||||||
|
x = x * g();
|
||||||
|
x = x >> g();
|
||||||
|
x = x << g();
|
||||||
|
x = x >>> g();
|
||||||
|
x = x | g();
|
||||||
|
x = x ^ g();
|
||||||
|
x = x % g();
|
||||||
|
x = x & g();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x;
|
||||||
|
|
||||||
|
x += 3;
|
||||||
|
x -= 3;
|
||||||
|
x /= 3;
|
||||||
|
x *= 3;
|
||||||
|
x >>= 3;
|
||||||
|
x <<= 3;
|
||||||
|
x >>>= 3;
|
||||||
|
x |= 3;
|
||||||
|
x ^= 3;
|
||||||
|
x %= 3;
|
||||||
|
x &= 3;
|
||||||
|
|
||||||
|
x += g();
|
||||||
|
x -= g();
|
||||||
|
x /= g();
|
||||||
|
x *= g();
|
||||||
|
x >>= g();
|
||||||
|
x <<= g();
|
||||||
|
x >>>= g();
|
||||||
|
x |= g();
|
||||||
|
x ^= g();
|
||||||
|
x %= g();
|
||||||
|
x &= g();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
op_equals_right_local_var: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x;
|
||||||
|
|
||||||
|
x = (x -= 2) ^ x;
|
||||||
|
|
||||||
|
x = 3 + x;
|
||||||
|
x = 3 - x;
|
||||||
|
x = 3 / x;
|
||||||
|
x = 3 * x;
|
||||||
|
x = 3 >> x;
|
||||||
|
x = 3 << x;
|
||||||
|
x = 3 >>> x;
|
||||||
|
x = 3 | x;
|
||||||
|
x = 3 ^ x;
|
||||||
|
x = 3 % x;
|
||||||
|
x = 3 & x;
|
||||||
|
|
||||||
|
x = g() + x;
|
||||||
|
x = g() - x;
|
||||||
|
x = g() / x;
|
||||||
|
x = g() * x;
|
||||||
|
x = g() >> x;
|
||||||
|
x = g() << x;
|
||||||
|
x = g() >>> x;
|
||||||
|
x = g() | x;
|
||||||
|
x = g() ^ x;
|
||||||
|
x = g() % x;
|
||||||
|
x = g() & x;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x;
|
||||||
|
|
||||||
|
x = (x -= 2) ^ x;
|
||||||
|
|
||||||
|
x = 3 + x;
|
||||||
|
x = 3 - x;
|
||||||
|
x = 3 / x;
|
||||||
|
x *= 3;
|
||||||
|
x = 3 >> x;
|
||||||
|
x = 3 << x;
|
||||||
|
x = 3 >>> x;
|
||||||
|
x |= 3;
|
||||||
|
x ^= 3;
|
||||||
|
x = 3 % x;
|
||||||
|
x &= 3;
|
||||||
|
|
||||||
|
x = g() + x;
|
||||||
|
x = g() - x;
|
||||||
|
x = g() / x;
|
||||||
|
x = g() * x;
|
||||||
|
x = g() >> x;
|
||||||
|
x = g() << x;
|
||||||
|
x = g() >>> x;
|
||||||
|
x = g() | x;
|
||||||
|
x = g() ^ x;
|
||||||
|
x = g() % x;
|
||||||
|
x = g() & x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
op_equals_left_global_var: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
x = x + 3;
|
||||||
|
x = x - 3;
|
||||||
|
x = x / 3;
|
||||||
|
x = x * 3;
|
||||||
|
x = x >> 3;
|
||||||
|
x = x << 3;
|
||||||
|
x = x >>> 3;
|
||||||
|
x = x | 3;
|
||||||
|
x = x ^ 3;
|
||||||
|
x = x % 3;
|
||||||
|
x = x & 3;
|
||||||
|
|
||||||
|
x = x + g();
|
||||||
|
x = x - g();
|
||||||
|
x = x / g();
|
||||||
|
x = x * g();
|
||||||
|
x = x >> g();
|
||||||
|
x = x << g();
|
||||||
|
x = x >>> g();
|
||||||
|
x = x | g();
|
||||||
|
x = x ^ g();
|
||||||
|
x = x % g();
|
||||||
|
x = x & g();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
x += 3;
|
||||||
|
x -= 3;
|
||||||
|
x /= 3;
|
||||||
|
x *= 3;
|
||||||
|
x >>= 3;
|
||||||
|
x <<= 3;
|
||||||
|
x >>>= 3;
|
||||||
|
x |= 3;
|
||||||
|
x ^= 3;
|
||||||
|
x %= 3;
|
||||||
|
x &= 3;
|
||||||
|
|
||||||
|
x += g();
|
||||||
|
x -= g();
|
||||||
|
x /= g();
|
||||||
|
x *= g();
|
||||||
|
x >>= g();
|
||||||
|
x <<= g();
|
||||||
|
x >>>= g();
|
||||||
|
x |= g();
|
||||||
|
x ^= g();
|
||||||
|
x %= g();
|
||||||
|
x &= g();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
op_equals_right_global_var: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
x = (x -= 2) ^ x;
|
||||||
|
|
||||||
|
x = 3 + x;
|
||||||
|
x = 3 - x;
|
||||||
|
x = 3 / x;
|
||||||
|
x = 3 * x;
|
||||||
|
x = 3 >> x;
|
||||||
|
x = 3 << x;
|
||||||
|
x = 3 >>> x;
|
||||||
|
x = 3 | x;
|
||||||
|
x = 3 ^ x;
|
||||||
|
x = 3 % x;
|
||||||
|
x = 3 & x;
|
||||||
|
|
||||||
|
x = g() + x;
|
||||||
|
x = g() - x;
|
||||||
|
x = g() / x;
|
||||||
|
x = g() * x;
|
||||||
|
x = g() >> x;
|
||||||
|
x = g() << x;
|
||||||
|
x = g() >>> x;
|
||||||
|
x = g() | x;
|
||||||
|
x = g() ^ x;
|
||||||
|
x = g() % x;
|
||||||
|
x = g() & x;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
x = (x -= 2) ^ x;
|
||||||
|
|
||||||
|
x = 3 + x;
|
||||||
|
x = 3 - x;
|
||||||
|
x = 3 / x;
|
||||||
|
x *= 3;
|
||||||
|
x = 3 >> x;
|
||||||
|
x = 3 << x;
|
||||||
|
x = 3 >>> x;
|
||||||
|
x |= 3;
|
||||||
|
x ^= 3;
|
||||||
|
x = 3 % x;
|
||||||
|
x &= 3;
|
||||||
|
|
||||||
|
x = g() + x;
|
||||||
|
x = g() - x;
|
||||||
|
x = g() / x;
|
||||||
|
x = g() * x;
|
||||||
|
x = g() >> x;
|
||||||
|
x = g() << x;
|
||||||
|
x = g() >>> x;
|
||||||
|
x = g() | x;
|
||||||
|
x = g() ^ x;
|
||||||
|
x = g() % x;
|
||||||
|
x = g() & x;
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -24,3 +24,200 @@ concat_1: {
|
|||||||
var f = "\x00360\08\0";
|
var f = "\x00360\08\0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
concat_2: {
|
||||||
|
options = {};
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
1 + (2 + 3),
|
||||||
|
1 + (2 + "3"),
|
||||||
|
1 + ("2" + 3),
|
||||||
|
1 + ("2" + "3"),
|
||||||
|
"1" + (2 + 3),
|
||||||
|
"1" + (2 + "3"),
|
||||||
|
"1" + ("2" + 3),
|
||||||
|
"1" + ("2" + "3")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
1 + (2 + 3),
|
||||||
|
1 + (2 + "3"),
|
||||||
|
1 + "2" + 3,
|
||||||
|
1 + "2" + "3",
|
||||||
|
"1" + (2 + 3),
|
||||||
|
"1" + 2 + "3",
|
||||||
|
"1" + "2" + 3,
|
||||||
|
"1" + "2" + "3"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
concat_3: {
|
||||||
|
options = {};
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
1 + 2 + (3 + 4 + 5),
|
||||||
|
1 + 2 + (3 + 4 + "5"),
|
||||||
|
1 + 2 + (3 + "4" + 5),
|
||||||
|
1 + 2 + (3 + "4" + "5"),
|
||||||
|
1 + 2 + ("3" + 4 + 5),
|
||||||
|
1 + 2 + ("3" + 4 + "5"),
|
||||||
|
1 + 2 + ("3" + "4" + 5),
|
||||||
|
1 + 2 + ("3" + "4" + "5")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
1 + 2 + (3 + 4 + 5),
|
||||||
|
1 + 2 + (3 + 4 + "5"),
|
||||||
|
1 + 2 + (3 + "4") + 5,
|
||||||
|
1 + 2 + (3 + "4") + "5",
|
||||||
|
1 + 2 + "3" + 4 + 5,
|
||||||
|
1 + 2 + "3" + 4 + "5",
|
||||||
|
1 + 2 + "3" + "4" + 5,
|
||||||
|
1 + 2 + "3" + "4" + "5"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
concat_4: {
|
||||||
|
options = {};
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
1 + "2" + (3 + 4 + 5),
|
||||||
|
1 + "2" + (3 + 4 + "5"),
|
||||||
|
1 + "2" + (3 + "4" + 5),
|
||||||
|
1 + "2" + (3 + "4" + "5"),
|
||||||
|
1 + "2" + ("3" + 4 + 5),
|
||||||
|
1 + "2" + ("3" + 4 + "5"),
|
||||||
|
1 + "2" + ("3" + "4" + 5),
|
||||||
|
1 + "2" + ("3" + "4" + "5")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
1 + "2" + (3 + 4 + 5),
|
||||||
|
1 + "2" + (3 + 4) + "5",
|
||||||
|
1 + "2" + 3 + "4" + 5,
|
||||||
|
1 + "2" + 3 + "4" + "5",
|
||||||
|
1 + "2" + "3" + 4 + 5,
|
||||||
|
1 + "2" + "3" + 4 + "5",
|
||||||
|
1 + "2" + "3" + "4" + 5,
|
||||||
|
1 + "2" + "3" + "4" + "5"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
concat_5: {
|
||||||
|
options = {};
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1" + 2 + (3 + 4 + 5),
|
||||||
|
"1" + 2 + (3 + 4 + "5"),
|
||||||
|
"1" + 2 + (3 + "4" + 5),
|
||||||
|
"1" + 2 + (3 + "4" + "5"),
|
||||||
|
"1" + 2 + ("3" + 4 + 5),
|
||||||
|
"1" + 2 + ("3" + 4 + "5"),
|
||||||
|
"1" + 2 + ("3" + "4" + 5),
|
||||||
|
"1" + 2 + ("3" + "4" + "5")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"1" + 2 + (3 + 4 + 5),
|
||||||
|
"1" + 2 + (3 + 4) + "5",
|
||||||
|
"1" + 2 + 3 + "4" + 5,
|
||||||
|
"1" + 2 + 3 + "4" + "5",
|
||||||
|
"1" + 2 + "3" + 4 + 5,
|
||||||
|
"1" + 2 + "3" + 4 + "5",
|
||||||
|
"1" + 2 + "3" + "4" + 5,
|
||||||
|
"1" + 2 + "3" + "4" + "5"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
concat_6: {
|
||||||
|
options = {};
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1" + "2" + (3 + 4 + 5),
|
||||||
|
"1" + "2" + (3 + 4 + "5"),
|
||||||
|
"1" + "2" + (3 + "4" + 5),
|
||||||
|
"1" + "2" + (3 + "4" + "5"),
|
||||||
|
"1" + "2" + ("3" + 4 + 5),
|
||||||
|
"1" + "2" + ("3" + 4 + "5"),
|
||||||
|
"1" + "2" + ("3" + "4" + 5),
|
||||||
|
"1" + "2" + ("3" + "4" + "5")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"1" + "2" + (3 + 4 + 5),
|
||||||
|
"1" + "2" + (3 + 4) + "5",
|
||||||
|
"1" + "2" + 3 + "4" + 5,
|
||||||
|
"1" + "2" + 3 + "4" + "5",
|
||||||
|
"1" + "2" + "3" + 4 + 5,
|
||||||
|
"1" + "2" + "3" + 4 + "5",
|
||||||
|
"1" + "2" + "3" + "4" + 5,
|
||||||
|
"1" + "2" + "3" + "4" + "5"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
concat_7: {
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"" + 1,
|
||||||
|
"" + "1",
|
||||||
|
"" + 1 + 2,
|
||||||
|
"" + 1 + "2",
|
||||||
|
"" + "1" + 2,
|
||||||
|
"" + "1" + "2",
|
||||||
|
"" + (x += "foo")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"" + 1,
|
||||||
|
"1",
|
||||||
|
"" + 1 + 2,
|
||||||
|
1 + "2",
|
||||||
|
"1" + 2,
|
||||||
|
"1" + "2",
|
||||||
|
x += "foo"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
concat_8: {
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
1 + "",
|
||||||
|
"1" + "",
|
||||||
|
1 + 2 + "",
|
||||||
|
1 + "2" + "",
|
||||||
|
"1" + 2 + "",
|
||||||
|
"1" + "2" + "",
|
||||||
|
(x += "foo") + ""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
1 + "",
|
||||||
|
"1",
|
||||||
|
1 + 2 + "",
|
||||||
|
1 + "2",
|
||||||
|
"1" + 2,
|
||||||
|
"1" + "2",
|
||||||
|
x += "foo"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ ifs_3_should_warn: {
|
|||||||
conditionals : true,
|
conditionals : true,
|
||||||
dead_code : true,
|
dead_code : true,
|
||||||
evaluate : true,
|
evaluate : true,
|
||||||
booleans : true
|
booleans : true,
|
||||||
|
side_effects : true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var x, y;
|
var x, y;
|
||||||
@@ -135,16 +136,28 @@ ifs_6: {
|
|||||||
comparisons: true
|
comparisons: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var x;
|
var x, y;
|
||||||
if (!foo && !bar && !baz && !boo) {
|
if (!foo && !bar && !baz && !boo) {
|
||||||
x = 10;
|
x = 10;
|
||||||
} else {
|
} else {
|
||||||
x = 20;
|
x = 20;
|
||||||
}
|
}
|
||||||
|
if (y) {
|
||||||
|
x[foo] = 10;
|
||||||
|
} else {
|
||||||
|
x[foo] = 20;
|
||||||
|
}
|
||||||
|
if (foo) {
|
||||||
|
x[bar] = 10;
|
||||||
|
} else {
|
||||||
|
x[bar] = 20;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var x;
|
var x, y;
|
||||||
x = foo || bar || baz || boo ? 20 : 10;
|
x = foo || bar || baz || boo ? 20 : 10;
|
||||||
|
x[foo] = y ? 10 : 20;
|
||||||
|
foo ? x[bar] = 10 : x[bar] = 20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,10 +172,16 @@ cond_1: {
|
|||||||
} else {
|
} else {
|
||||||
do_something(y);
|
do_something(y);
|
||||||
}
|
}
|
||||||
|
if (some_condition()) {
|
||||||
|
side_effects(x);
|
||||||
|
} else {
|
||||||
|
side_effects(y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var do_something;
|
var do_something;
|
||||||
do_something(some_condition() ? x : y);
|
do_something(some_condition() ? x : y);
|
||||||
|
some_condition() ? side_effects(x) : side_effects(y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,10 +232,16 @@ cond_4: {
|
|||||||
} else {
|
} else {
|
||||||
do_something();
|
do_something();
|
||||||
}
|
}
|
||||||
|
if (some_condition()) {
|
||||||
|
side_effects();
|
||||||
|
} else {
|
||||||
|
side_effects();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var do_something;
|
var do_something;
|
||||||
some_condition(), do_something();
|
some_condition(), do_something();
|
||||||
|
some_condition(), side_effects();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +275,8 @@ cond_5: {
|
|||||||
cond_7: {
|
cond_7: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
evaluate : true
|
evaluate : true,
|
||||||
|
side_effects: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var x, y, z, a, b;
|
var x, y, z, a, b;
|
||||||
@@ -635,166 +661,6 @@ ternary_boolean_alternative: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conditional_and: {
|
|
||||||
options = {
|
|
||||||
conditionals: true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var a;
|
|
||||||
// compress these
|
|
||||||
|
|
||||||
a = true && condition;
|
|
||||||
a = 1 && console.log("a");
|
|
||||||
a = 2 * 3 && 2 * condition;
|
|
||||||
a = 5 == 5 && condition + 3;
|
|
||||||
a = "string" && 4 - condition;
|
|
||||||
a = 5 + "" && condition / 5;
|
|
||||||
a = -4.5 && 6 << condition;
|
|
||||||
a = 6 && 7;
|
|
||||||
|
|
||||||
a = false && condition;
|
|
||||||
a = NaN && console.log("b");
|
|
||||||
a = 0 && console.log("c");
|
|
||||||
a = undefined && 2 * condition;
|
|
||||||
a = null && condition + 3;
|
|
||||||
a = 2 * 3 - 6 && 4 - condition;
|
|
||||||
a = 10 == 7 && condition / 5;
|
|
||||||
a = !"string" && 6 % condition;
|
|
||||||
a = 0 && 7;
|
|
||||||
|
|
||||||
// don't compress these
|
|
||||||
|
|
||||||
a = condition && true;
|
|
||||||
a = console.log("a") && 2;
|
|
||||||
a = 4 - condition && "string";
|
|
||||||
a = 6 << condition && -4.5;
|
|
||||||
|
|
||||||
a = condition && false;
|
|
||||||
a = console.log("b") && NaN;
|
|
||||||
a = console.log("c") && 0;
|
|
||||||
a = 2 * condition && undefined;
|
|
||||||
a = condition + 3 && null;
|
|
||||||
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var a;
|
|
||||||
|
|
||||||
a = condition;
|
|
||||||
a = console.log("a");
|
|
||||||
a = 2 * condition;
|
|
||||||
a = condition + 3;
|
|
||||||
a = 4 - condition;
|
|
||||||
a = condition / 5;
|
|
||||||
a = 6 << condition;
|
|
||||||
a = 7;
|
|
||||||
|
|
||||||
a = false;
|
|
||||||
a = NaN;
|
|
||||||
a = 0;
|
|
||||||
a = void 0;
|
|
||||||
a = null;
|
|
||||||
a = 0;
|
|
||||||
a = false;
|
|
||||||
a = false;
|
|
||||||
a = 0;
|
|
||||||
|
|
||||||
a = condition && true;
|
|
||||||
a = console.log("a") && 2;
|
|
||||||
a = 4 - condition && "string";
|
|
||||||
a = 6 << condition && -4.5;
|
|
||||||
|
|
||||||
a = condition && false;
|
|
||||||
a = console.log("b") && NaN;
|
|
||||||
a = console.log("c") && 0;
|
|
||||||
a = 2 * condition && void 0;
|
|
||||||
a = condition + 3 && null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conditional_or: {
|
|
||||||
options = {
|
|
||||||
conditionals: true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var a;
|
|
||||||
// compress these
|
|
||||||
|
|
||||||
a = true || condition;
|
|
||||||
a = 1 || console.log("a");
|
|
||||||
a = 2 * 3 || 2 * condition;
|
|
||||||
a = 5 == 5 || condition + 3;
|
|
||||||
a = "string" || 4 - condition;
|
|
||||||
a = 5 + "" || condition / 5;
|
|
||||||
a = -4.5 || 6 << condition;
|
|
||||||
a = 6 || 7;
|
|
||||||
|
|
||||||
a = false || condition;
|
|
||||||
a = 0 || console.log("b");
|
|
||||||
a = NaN || console.log("c");
|
|
||||||
a = undefined || 2 * condition;
|
|
||||||
a = null || condition + 3;
|
|
||||||
a = 2 * 3 - 6 || 4 - condition;
|
|
||||||
a = 10 == 7 || condition / 5;
|
|
||||||
a = !"string" || 6 % condition;
|
|
||||||
a = null || 7;
|
|
||||||
|
|
||||||
a = console.log(undefined && condition || null);
|
|
||||||
a = console.log(undefined || condition && null);
|
|
||||||
|
|
||||||
// don't compress these
|
|
||||||
|
|
||||||
a = condition || true;
|
|
||||||
a = console.log("a") || 2;
|
|
||||||
a = 4 - condition || "string";
|
|
||||||
a = 6 << condition || -4.5;
|
|
||||||
|
|
||||||
a = condition || false;
|
|
||||||
a = console.log("b") || NaN;
|
|
||||||
a = console.log("c") || 0;
|
|
||||||
a = 2 * condition || undefined;
|
|
||||||
a = condition + 3 || null;
|
|
||||||
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var a;
|
|
||||||
|
|
||||||
a = true;
|
|
||||||
a = 1;
|
|
||||||
a = 6;
|
|
||||||
a = true;
|
|
||||||
a = "string";
|
|
||||||
a = "5";
|
|
||||||
a = -4.5;
|
|
||||||
a = 6;
|
|
||||||
|
|
||||||
a = condition;
|
|
||||||
a = console.log("b");
|
|
||||||
a = console.log("c");
|
|
||||||
a = 2 * condition;
|
|
||||||
a = condition + 3;
|
|
||||||
a = 4 - condition;
|
|
||||||
a = condition / 5;
|
|
||||||
a = 6 % condition;
|
|
||||||
a = 7;
|
|
||||||
|
|
||||||
a = console.log(null);
|
|
||||||
a = console.log(condition && null);
|
|
||||||
|
|
||||||
a = condition || true;
|
|
||||||
a = console.log("a") || 2;
|
|
||||||
a = 4 - condition || "string";
|
|
||||||
a = 6 << condition || -4.5;
|
|
||||||
|
|
||||||
a = condition || false;
|
|
||||||
a = console.log("b") || NaN;
|
|
||||||
a = console.log("c") || 0;
|
|
||||||
a = 2 * condition || void 0;
|
|
||||||
a = condition + 3 || null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trivial_boolean_ternary_expressions : {
|
trivial_boolean_ternary_expressions : {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
@@ -874,6 +740,7 @@ issue_1154: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
evaluate : true,
|
evaluate : true,
|
||||||
booleans : true,
|
booleans : true,
|
||||||
|
side_effects: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
function f1(x) { return x ? -1 : -1; }
|
function f1(x) { return x ? -1 : -1; }
|
||||||
@@ -902,7 +769,249 @@ issue_1154: {
|
|||||||
function g2() { return g(), 2; }
|
function g2() { return g(), 2; }
|
||||||
function g3() { return g(), -4; }
|
function g3() { return g(), -4; }
|
||||||
function g4() { return g(), !1; }
|
function g4() { return g(), !1; }
|
||||||
function g5() { return g(), void 0; }
|
function g5() { return void g(); }
|
||||||
function g6() { return g(), "number"; }
|
function g6() { return g(), "number"; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
no_evaluate: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate : false,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(b) {
|
||||||
|
a = b ? !0 : !0;
|
||||||
|
a = b ? ~1 : ~1;
|
||||||
|
a = b ? -2 : -2;
|
||||||
|
a = b ? +3 : +3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(b) {
|
||||||
|
a = !0;
|
||||||
|
a = ~1;
|
||||||
|
a = -2;
|
||||||
|
a = +3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
equality_conditionals_false: {
|
||||||
|
options = {
|
||||||
|
conditionals: false,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a == (b ? a : a),
|
||||||
|
a == (b ? a : c),
|
||||||
|
a != (b ? a : a),
|
||||||
|
a != (b ? a : c),
|
||||||
|
a === (b ? a : a),
|
||||||
|
a === (b ? a : c),
|
||||||
|
a !== (b ? a : a),
|
||||||
|
a !== (b ? a : c)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
f(0, 0, 0);
|
||||||
|
f(0, true, 0);
|
||||||
|
f(1, 2, 3);
|
||||||
|
f(1, null, 3);
|
||||||
|
f(NaN);
|
||||||
|
f(NaN, "foo");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a == (b ? a : a),
|
||||||
|
a == (b ? a : c),
|
||||||
|
a != (b ? a : a),
|
||||||
|
a != (b ? a : c),
|
||||||
|
a === (b ? a : a),
|
||||||
|
a === (b ? a : c),
|
||||||
|
a !== (b ? a : a),
|
||||||
|
a !== (b ? a : c)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
f(0, 0, 0),
|
||||||
|
f(0, true, 0),
|
||||||
|
f(1, 2, 3),
|
||||||
|
f(1, null, 3),
|
||||||
|
f(NaN),
|
||||||
|
f(NaN, "foo");
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
equality_conditionals_true: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a == (b ? a : a),
|
||||||
|
a == (b ? a : c),
|
||||||
|
a != (b ? a : a),
|
||||||
|
a != (b ? a : c),
|
||||||
|
a === (b ? a : a),
|
||||||
|
a === (b ? a : c),
|
||||||
|
a !== (b ? a : a),
|
||||||
|
a !== (b ? a : c)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
f(0, 0, 0);
|
||||||
|
f(0, true, 0);
|
||||||
|
f(1, 2, 3);
|
||||||
|
f(1, null, 3);
|
||||||
|
f(NaN);
|
||||||
|
f(NaN, "foo");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
(b, a == a),
|
||||||
|
a == (b ? a : c),
|
||||||
|
(b, a != a),
|
||||||
|
a != (b ? a : c),
|
||||||
|
(b, a === a),
|
||||||
|
a === (b ? a : c),
|
||||||
|
(b, a !== a),
|
||||||
|
a !== (b ? a : c)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
f(0, 0, 0),
|
||||||
|
f(0, true, 0),
|
||||||
|
f(1, 2, 3),
|
||||||
|
f(1, null, 3),
|
||||||
|
f(NaN),
|
||||||
|
f(NaN, "foo");
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1645_1: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
(b = a) ? a++ + (b += a) ? b += a : b += a : b ^= a;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
(b = a) ? (a++ + (b += a), b += a) : b ^= a;
|
||||||
|
console.log(a,b);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1645_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
function f() {
|
||||||
|
return a++;
|
||||||
|
}
|
||||||
|
f() ? a += 2 : a += 4;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
function f(){
|
||||||
|
return a++;
|
||||||
|
}
|
||||||
|
f() ? a += 2 : a += 4;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
condition_symbol_matches_consequent: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo(x, y) {
|
||||||
|
return x ? x : y;
|
||||||
|
}
|
||||||
|
function bar() {
|
||||||
|
return g ? g : h;
|
||||||
|
}
|
||||||
|
var g = 4;
|
||||||
|
var h = 5;
|
||||||
|
console.log(foo(3, null), foo(0, 7), foo(true, false), bar());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo(x, y) {
|
||||||
|
return x || y;
|
||||||
|
}
|
||||||
|
function bar() {
|
||||||
|
return g || h;
|
||||||
|
}
|
||||||
|
var g = 4;
|
||||||
|
var h = 5;
|
||||||
|
console.log(foo(3, null), foo(0, 7), foo(true, false), bar());
|
||||||
|
}
|
||||||
|
expect_stdout: "3 7 true 4"
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_conditional_1: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(delete (1 ? undefined : x));
|
||||||
|
console.log(delete (1 ? void 0 : x));
|
||||||
|
console.log(delete (1 ? Infinity : x));
|
||||||
|
console.log(delete (1 ? 1 / 0 : x));
|
||||||
|
console.log(delete (1 ? NaN : x));
|
||||||
|
console.log(delete (1 ? 0 / 0 : x));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_conditional_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
keep_infinity: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(delete (0 ? x : undefined));
|
||||||
|
console.log(delete (0 ? x : void 0));
|
||||||
|
console.log(delete (0 ? x : Infinity));
|
||||||
|
console.log(delete (0 ? x : 1 / 0));
|
||||||
|
console.log(delete (0 ? x : NaN));
|
||||||
|
console.log(delete (0 ? x : 0 / 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,206 +1,149 @@
|
|||||||
dead_code_1: {
|
dead_code_1: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true
|
dead_code: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
function f() {
|
function f() {
|
||||||
a();
|
a();
|
||||||
b();
|
b();
|
||||||
x = 10;
|
x = 10;
|
||||||
return;
|
return;
|
||||||
if (x) {
|
if (x) {
|
||||||
y();
|
y();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f() {
|
function f() {
|
||||||
a();
|
a();
|
||||||
b();
|
b();
|
||||||
x = 10;
|
x = 10;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_2_should_warn: {
|
dead_code_2_should_warn: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true
|
dead_code: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
function f() {
|
function f() {
|
||||||
g();
|
g();
|
||||||
x = 10;
|
x = 10;
|
||||||
throw "foo";
|
throw "foo";
|
||||||
// completely discarding the `if` would introduce some
|
// completely discarding the `if` would introduce some
|
||||||
// bugs. UglifyJS v1 doesn't deal with this issue; in v2
|
// bugs. UglifyJS v1 doesn't deal with this issue; in v2
|
||||||
// we copy any declarations to the upper scope.
|
// we copy any declarations to the upper scope.
|
||||||
if (x) {
|
if (x) {
|
||||||
y();
|
y();
|
||||||
var x;
|
var x;
|
||||||
function g(){};
|
function g(){};
|
||||||
// but nested declarations should not be kept.
|
// but nested declarations should not be kept.
|
||||||
(function(){
|
(function(){
|
||||||
var q;
|
var q;
|
||||||
function y(){};
|
function y(){};
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f() {
|
function f() {
|
||||||
g();
|
g();
|
||||||
x = 10;
|
x = 10;
|
||||||
throw "foo";
|
throw "foo";
|
||||||
var x;
|
var x;
|
||||||
function g(){};
|
function g(){};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_constant_boolean_should_warn_more: {
|
dead_code_constant_boolean_should_warn_more: {
|
||||||
options = {
|
options = {
|
||||||
dead_code : true,
|
dead_code : true,
|
||||||
loops : true,
|
loops : true,
|
||||||
booleans : true,
|
booleans : true,
|
||||||
conditionals : true,
|
conditionals : true,
|
||||||
evaluate : true
|
evaluate : true,
|
||||||
};
|
side_effects : true,
|
||||||
input: {
|
};
|
||||||
while (!((foo && bar) || (x + "0"))) {
|
input: {
|
||||||
console.log("unreachable");
|
while (!((foo && bar) || (x + "0"))) {
|
||||||
var foo;
|
console.log("unreachable");
|
||||||
function bar() {}
|
var foo;
|
||||||
}
|
function bar() {}
|
||||||
for (var x = 10, y; x && (y || x) && (!typeof x); ++x) {
|
}
|
||||||
asdf();
|
for (var x = 10, y; x && (y || x) && (!typeof x); ++x) {
|
||||||
foo();
|
asdf();
|
||||||
var moo;
|
foo();
|
||||||
}
|
var moo;
|
||||||
}
|
}
|
||||||
expect: {
|
}
|
||||||
var foo;
|
expect: {
|
||||||
function bar() {}
|
var foo;
|
||||||
// nothing for the while
|
function bar() {}
|
||||||
// as for the for, it should keep:
|
// nothing for the while
|
||||||
var x = 10, y;
|
// as for the for, it should keep:
|
||||||
var moo;
|
var x = 10, y;
|
||||||
}
|
var moo;
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
dead_code_const_declaration: {
|
}
|
||||||
options = {
|
|
||||||
dead_code : true,
|
try_catch_finally: {
|
||||||
loops : true,
|
options = {
|
||||||
booleans : true,
|
conditionals: true,
|
||||||
conditionals : true,
|
dead_code: true,
|
||||||
evaluate : true
|
evaluate: true,
|
||||||
};
|
}
|
||||||
input: {
|
input: {
|
||||||
var unused;
|
var a = 1;
|
||||||
const CONST_FOO = false;
|
!function() {
|
||||||
if (CONST_FOO) {
|
try {
|
||||||
console.log("unreachable");
|
if (false) throw x;
|
||||||
var moo;
|
} catch (a) {
|
||||||
function bar() {}
|
var a = 2;
|
||||||
}
|
console.log("FAIL");
|
||||||
}
|
} finally {
|
||||||
expect: {
|
a = 3;
|
||||||
var unused;
|
console.log("PASS");
|
||||||
const CONST_FOO = !1;
|
}
|
||||||
var moo;
|
}();
|
||||||
function bar() {}
|
try {
|
||||||
}
|
console.log(a);
|
||||||
}
|
} finally {
|
||||||
|
}
|
||||||
dead_code_const_annotation: {
|
}
|
||||||
options = {
|
expect: {
|
||||||
dead_code : true,
|
var a = 1;
|
||||||
loops : true,
|
!function() {
|
||||||
booleans : true,
|
var a;
|
||||||
conditionals : true,
|
a = 3;
|
||||||
evaluate : true
|
console.log("PASS");
|
||||||
};
|
}();
|
||||||
input: {
|
try {
|
||||||
var unused;
|
console.log(a);
|
||||||
/** @const */ var CONST_FOO_ANN = false;
|
} finally {
|
||||||
if (CONST_FOO_ANN) {
|
}
|
||||||
console.log("unreachable");
|
}
|
||||||
var moo;
|
expect_stdout: [
|
||||||
function bar() {}
|
"PASS",
|
||||||
}
|
"1",
|
||||||
}
|
]
|
||||||
expect: {
|
}
|
||||||
var unused;
|
|
||||||
var CONST_FOO_ANN = !1;
|
accessor: {
|
||||||
var moo;
|
options = {
|
||||||
function bar() {}
|
side_effects: true,
|
||||||
}
|
}
|
||||||
}
|
input: {
|
||||||
|
({
|
||||||
dead_code_const_annotation_regex: {
|
get a() {},
|
||||||
options = {
|
set a(v){
|
||||||
dead_code : true,
|
this.b = 2;
|
||||||
loops : true,
|
},
|
||||||
booleans : true,
|
b: 1
|
||||||
conditionals : true,
|
});
|
||||||
evaluate : true
|
}
|
||||||
};
|
expect: {}
|
||||||
input: {
|
}
|
||||||
var unused;
|
|
||||||
// @constraint this shouldn't be a constant
|
|
||||||
var CONST_FOO_ANN = false;
|
|
||||||
if (CONST_FOO_ANN) {
|
|
||||||
console.log("reachable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var unused;
|
|
||||||
var CONST_FOO_ANN = !1;
|
|
||||||
CONST_FOO_ANN && console.log('reachable');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dead_code_const_annotation_complex_scope: {
|
|
||||||
options = {
|
|
||||||
dead_code : true,
|
|
||||||
loops : true,
|
|
||||||
booleans : true,
|
|
||||||
conditionals : true,
|
|
||||||
evaluate : true
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
var unused_var;
|
|
||||||
/** @const */ var test = 'test';
|
|
||||||
// @const
|
|
||||||
var CONST_FOO_ANN = false;
|
|
||||||
var unused_var_2;
|
|
||||||
if (CONST_FOO_ANN) {
|
|
||||||
console.log("unreachable");
|
|
||||||
var moo;
|
|
||||||
function bar() {}
|
|
||||||
}
|
|
||||||
if (test === 'test') {
|
|
||||||
var beef = 'good';
|
|
||||||
/** @const */ var meat = 'beef';
|
|
||||||
var pork = 'bad';
|
|
||||||
if (meat === 'pork') {
|
|
||||||
console.log('also unreachable');
|
|
||||||
} else if (pork === 'good') {
|
|
||||||
console.log('reached, not const');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
var unused_var;
|
|
||||||
var test = 'test';
|
|
||||||
var CONST_FOO_ANN = !1;
|
|
||||||
var unused_var_2;
|
|
||||||
var moo;
|
|
||||||
function bar() {}
|
|
||||||
var beef = 'good';
|
|
||||||
var meat = 'beef';
|
|
||||||
var pork = 'bad';
|
|
||||||
'good' === pork && console.log('reached, not const');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
drop_console_1: {
|
drop_console_1: {
|
||||||
options = {};
|
options = {};
|
||||||
input: {
|
input: {
|
||||||
console.log('foo');
|
console.log('foo');
|
||||||
console.log.apply(console, arguments);
|
console.log.apply(console, arguments);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log('foo');
|
console.log('foo');
|
||||||
console.log.apply(console, arguments);
|
console.log.apply(console, arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drop_console_1: {
|
drop_console_2: {
|
||||||
options = { drop_console: true };
|
options = { drop_console: true };
|
||||||
input: {
|
input: {
|
||||||
console.log('foo');
|
console.log('foo');
|
||||||
console.log.apply(console, arguments);
|
console.log.apply(console, arguments);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
// with regular compression these will be stripped out as well
|
// with regular compression these will be stripped out as well
|
||||||
void 0;
|
void 0;
|
||||||
void 0;
|
void 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,3 +177,934 @@ keep_fnames: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop_assign: {
|
||||||
|
options = { unused: true };
|
||||||
|
input: {
|
||||||
|
function f1() {
|
||||||
|
var a;
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
function f2() {
|
||||||
|
var a = 1;
|
||||||
|
a = 2;
|
||||||
|
}
|
||||||
|
function f3(a) {
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
function f4() {
|
||||||
|
var a;
|
||||||
|
return a = 1;
|
||||||
|
}
|
||||||
|
function f5() {
|
||||||
|
var a;
|
||||||
|
return function() {
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1() {
|
||||||
|
1;
|
||||||
|
}
|
||||||
|
function f2() {
|
||||||
|
2;
|
||||||
|
}
|
||||||
|
function f3(a) {
|
||||||
|
1;
|
||||||
|
}
|
||||||
|
function f4() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
function f5() {
|
||||||
|
var a;
|
||||||
|
return function() {
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_assign: {
|
||||||
|
options = { unused: "keep_assign" };
|
||||||
|
input: {
|
||||||
|
function f1() {
|
||||||
|
var a;
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
function f2() {
|
||||||
|
var a = 1;
|
||||||
|
a = 2;
|
||||||
|
}
|
||||||
|
function f3(a) {
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
function f4() {
|
||||||
|
var a;
|
||||||
|
return a = 1;
|
||||||
|
}
|
||||||
|
function f5() {
|
||||||
|
var a;
|
||||||
|
return function() {
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1() {
|
||||||
|
var a;
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
function f2() {
|
||||||
|
var a = 1;
|
||||||
|
a = 2;
|
||||||
|
}
|
||||||
|
function f3(a) {
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
function f4() {
|
||||||
|
var a;
|
||||||
|
return a = 1;
|
||||||
|
}
|
||||||
|
function f5() {
|
||||||
|
var a;
|
||||||
|
return function() {
|
||||||
|
a = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_toplevel_funcs: {
|
||||||
|
options = { toplevel: "funcs", unused: true };
|
||||||
|
input: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_toplevel_vars: {
|
||||||
|
options = { toplevel: "vars", unused: true };
|
||||||
|
input: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_toplevel_vars_fargs: {
|
||||||
|
options = { keep_fargs: false, toplevel: "vars", unused: true };
|
||||||
|
input: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = g;
|
||||||
|
function f() {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_toplevel_all: {
|
||||||
|
options = { toplevel: true, unused: true };
|
||||||
|
input: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
2;
|
||||||
|
console.log(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_toplevel_retain: {
|
||||||
|
options = { top_retain: "f,a,o", unused: true };
|
||||||
|
input: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
console.log(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_toplevel_retain_array: {
|
||||||
|
options = { top_retain: [ "f", "a", "o" ], unused: true };
|
||||||
|
input: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
console.log(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_toplevel_retain_regex: {
|
||||||
|
options = { top_retain: /^[fao]$/, unused: true };
|
||||||
|
input: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
console.log(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_toplevel_all_retain: {
|
||||||
|
options = { toplevel: true, top_retain: "f,a,o", unused: true };
|
||||||
|
input: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
console.log(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_toplevel_funcs_retain: {
|
||||||
|
options = { toplevel: "funcs", top_retain: "f,a,o", unused: true };
|
||||||
|
input: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_toplevel_vars_retain: {
|
||||||
|
options = { toplevel: "vars", top_retain: "f,a,o", unused: true };
|
||||||
|
input: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_toplevel_keep_assign: {
|
||||||
|
options = { toplevel: true, unused: "keep_assign" };
|
||||||
|
input: {
|
||||||
|
var a, b = 1, c = g;
|
||||||
|
function f(d) {
|
||||||
|
return function() {
|
||||||
|
c = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 2;
|
||||||
|
function g() {}
|
||||||
|
function h() {}
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = 1;
|
||||||
|
a = 2;
|
||||||
|
console.log(b = 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_fargs: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_fnames: {
|
||||||
|
options = {
|
||||||
|
keep_fnames: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
return function g() {
|
||||||
|
var a = g;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
return function() {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global_var: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
function foo(b) {
|
||||||
|
a;
|
||||||
|
b;
|
||||||
|
c;
|
||||||
|
typeof c === "undefined";
|
||||||
|
c + b + a;
|
||||||
|
b && b.ar();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
function foo(b) {
|
||||||
|
c;
|
||||||
|
c;
|
||||||
|
b && b.ar();
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iife: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a;
|
||||||
|
~function() {}(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_value: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(1, [2, foo()], 3, {a:1, b:bar()});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo(), bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1539: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a, b;
|
||||||
|
a = b = 42;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vardef_value: {
|
||||||
|
options = {
|
||||||
|
keep_fnames: false,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g(){
|
||||||
|
return x();
|
||||||
|
}
|
||||||
|
var a = g();
|
||||||
|
return a(42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
var a = function(){
|
||||||
|
return x();
|
||||||
|
}();
|
||||||
|
return a(42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assign_binding: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a;
|
||||||
|
a = f.g, a();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
(0, f.g)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assign_chain: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a, b;
|
||||||
|
x = a = y = b = 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
x = y = 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1583: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function m(t) {
|
||||||
|
(function(e) {
|
||||||
|
t = e();
|
||||||
|
})(function() {
|
||||||
|
return (function(a) {
|
||||||
|
return a;
|
||||||
|
})(function(a) {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function m(t) {
|
||||||
|
(function(e) {
|
||||||
|
t = (function() {
|
||||||
|
return (function(a) {
|
||||||
|
return a;
|
||||||
|
})(function(a) {});
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1656: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for(var a=0;;);
|
||||||
|
}
|
||||||
|
expect_exact: "for (;;) ;"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1709: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
function x() {
|
||||||
|
var x = 1;
|
||||||
|
return x;
|
||||||
|
}(),
|
||||||
|
function z() {
|
||||||
|
function z() {}
|
||||||
|
return z;
|
||||||
|
}()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
function() {
|
||||||
|
var x = 1;
|
||||||
|
return x;
|
||||||
|
}(),
|
||||||
|
function() {
|
||||||
|
function z() {}
|
||||||
|
return z;
|
||||||
|
}()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1715_1: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
a++;
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
a++;
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1715_2: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
a++;
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (a) {
|
||||||
|
var a = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
a++;
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1715_3: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
a++;
|
||||||
|
try {
|
||||||
|
console;
|
||||||
|
} catch (a) {
|
||||||
|
var a = 2 + x();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
function f() {
|
||||||
|
a++;
|
||||||
|
try {
|
||||||
|
console;
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
x();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1715_4: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
!function a() {
|
||||||
|
a++;
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
!function() {
|
||||||
|
a++;
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_assign_1: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
console.log(delete (a = undefined));
|
||||||
|
console.log(delete (a = void 0));
|
||||||
|
console.log(delete (a = Infinity));
|
||||||
|
console.log(delete (a = 1 / 0));
|
||||||
|
console.log(delete (a = NaN));
|
||||||
|
console.log(delete (a = 0 / 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log((void 0, !0));
|
||||||
|
console.log((void 0, !0));
|
||||||
|
console.log((1 / 0, !0));
|
||||||
|
console.log((1 / 0, !0));
|
||||||
|
console.log((NaN, !0));
|
||||||
|
console.log((0 / 0, !0));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_assign_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
keep_infinity: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
console.log(delete (a = undefined));
|
||||||
|
console.log(delete (a = void 0));
|
||||||
|
console.log(delete (a = Infinity));
|
||||||
|
console.log(delete (a = 1 / 0));
|
||||||
|
console.log(delete (a = NaN));
|
||||||
|
console.log(delete (a = 0 / 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log((void 0, !0));
|
||||||
|
console.log((void 0, !0));
|
||||||
|
console.log((Infinity, !0));
|
||||||
|
console.log((1 / 0, !0));
|
||||||
|
console.log((NaN, !0));
|
||||||
|
console.log((0 / 0, !0));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_var: {
|
||||||
|
options = {
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
console.log(a, b);
|
||||||
|
var a = 1, b = 2;
|
||||||
|
console.log(a, b);
|
||||||
|
var a = 3;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(a, b);
|
||||||
|
var a = 1, b = 2;
|
||||||
|
console.log(a, b);
|
||||||
|
a = 3;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined undefined",
|
||||||
|
"1 2",
|
||||||
|
"3 2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1830_1: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function() {
|
||||||
|
L: for (var b = console.log(1); !1;) continue L;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
L: for (console.log(1); !1;) continue L;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1830_2: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function() {
|
||||||
|
L: for (var a = 1, b = console.log(a); --a;) continue L;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
var a = 1;
|
||||||
|
L: for (console.log(a); --a;) continue L;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1838: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
loops: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var b = a;
|
||||||
|
while (c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
"function f() {",
|
||||||
|
" for (a; c; ) ;",
|
||||||
|
"}",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
var_catch_toplevel: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
a--;
|
||||||
|
try {
|
||||||
|
a++;
|
||||||
|
} catch(a) {
|
||||||
|
if (a) var a;
|
||||||
|
var a = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
a--;
|
||||||
|
try {
|
||||||
|
a++;
|
||||||
|
} catch(a) {
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,187 @@
|
|||||||
|
and: {
|
||||||
|
options = {
|
||||||
|
evaluate: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
// compress these
|
||||||
|
|
||||||
|
a = true && condition;
|
||||||
|
a = 1 && console.log("a");
|
||||||
|
a = 2 * 3 && 2 * condition;
|
||||||
|
a = 5 == 5 && condition + 3;
|
||||||
|
a = "string" && 4 - condition;
|
||||||
|
a = 5 + "" && condition / 5;
|
||||||
|
a = -4.5 && 6 << condition;
|
||||||
|
a = 6 && 7;
|
||||||
|
|
||||||
|
a = false && condition;
|
||||||
|
a = NaN && console.log("b");
|
||||||
|
a = 0 && console.log("c");
|
||||||
|
a = undefined && 2 * condition;
|
||||||
|
a = null && condition + 3;
|
||||||
|
a = 2 * 3 - 6 && 4 - condition;
|
||||||
|
a = 10 == 7 && condition / 5;
|
||||||
|
a = !"string" && 6 % condition;
|
||||||
|
a = 0 && 7;
|
||||||
|
|
||||||
|
// don't compress these
|
||||||
|
|
||||||
|
a = condition && true;
|
||||||
|
a = console.log("a") && 2;
|
||||||
|
a = 4 - condition && "string";
|
||||||
|
a = 6 << condition && -4.5;
|
||||||
|
|
||||||
|
a = condition && false;
|
||||||
|
a = console.log("b") && NaN;
|
||||||
|
a = console.log("c") && 0;
|
||||||
|
a = 2 * condition && undefined;
|
||||||
|
a = condition + 3 && null;
|
||||||
|
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
|
||||||
|
a = condition;
|
||||||
|
a = console.log("a");
|
||||||
|
a = 2 * condition;
|
||||||
|
a = condition + 3;
|
||||||
|
a = 4 - condition;
|
||||||
|
a = condition / 5;
|
||||||
|
a = 6 << condition;
|
||||||
|
a = 7;
|
||||||
|
|
||||||
|
a = false;
|
||||||
|
a = NaN;
|
||||||
|
a = 0;
|
||||||
|
a = void 0;
|
||||||
|
a = null;
|
||||||
|
a = 0;
|
||||||
|
a = false;
|
||||||
|
a = false;
|
||||||
|
a = 0;
|
||||||
|
|
||||||
|
a = condition && true;
|
||||||
|
a = console.log("a") && 2;
|
||||||
|
a = 4 - condition && "string";
|
||||||
|
a = 6 << condition && -4.5;
|
||||||
|
|
||||||
|
a = condition && false;
|
||||||
|
a = console.log("b") && NaN;
|
||||||
|
a = console.log("c") && 0;
|
||||||
|
a = 2 * condition && void 0;
|
||||||
|
a = condition + 3 && null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
or: {
|
||||||
|
options = {
|
||||||
|
evaluate: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
// compress these
|
||||||
|
|
||||||
|
a = true || condition;
|
||||||
|
a = 1 || console.log("a");
|
||||||
|
a = 2 * 3 || 2 * condition;
|
||||||
|
a = 5 == 5 || condition + 3;
|
||||||
|
a = "string" || 4 - condition;
|
||||||
|
a = 5 + "" || condition / 5;
|
||||||
|
a = -4.5 || 6 << condition;
|
||||||
|
a = 6 || 7;
|
||||||
|
|
||||||
|
a = false || condition;
|
||||||
|
a = 0 || console.log("b");
|
||||||
|
a = NaN || console.log("c");
|
||||||
|
a = undefined || 2 * condition;
|
||||||
|
a = null || condition + 3;
|
||||||
|
a = 2 * 3 - 6 || 4 - condition;
|
||||||
|
a = 10 == 7 || condition / 5;
|
||||||
|
a = !"string" || 6 % condition;
|
||||||
|
a = null || 7;
|
||||||
|
|
||||||
|
a = console.log(undefined && condition || null);
|
||||||
|
a = console.log(undefined || condition && null);
|
||||||
|
|
||||||
|
// don't compress these
|
||||||
|
|
||||||
|
a = condition || true;
|
||||||
|
a = console.log("a") || 2;
|
||||||
|
a = 4 - condition || "string";
|
||||||
|
a = 6 << condition || -4.5;
|
||||||
|
|
||||||
|
a = condition || false;
|
||||||
|
a = console.log("b") || NaN;
|
||||||
|
a = console.log("c") || 0;
|
||||||
|
a = 2 * condition || undefined;
|
||||||
|
a = condition + 3 || null;
|
||||||
|
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
|
||||||
|
a = true;
|
||||||
|
a = 1;
|
||||||
|
a = 6;
|
||||||
|
a = true;
|
||||||
|
a = "string";
|
||||||
|
a = "5";
|
||||||
|
a = -4.5;
|
||||||
|
a = 6;
|
||||||
|
|
||||||
|
a = condition;
|
||||||
|
a = console.log("b");
|
||||||
|
a = console.log("c");
|
||||||
|
a = 2 * condition;
|
||||||
|
a = condition + 3;
|
||||||
|
a = 4 - condition;
|
||||||
|
a = condition / 5;
|
||||||
|
a = 6 % condition;
|
||||||
|
a = 7;
|
||||||
|
|
||||||
|
a = console.log(null);
|
||||||
|
a = console.log(condition && null);
|
||||||
|
|
||||||
|
a = condition || true;
|
||||||
|
a = console.log("a") || 2;
|
||||||
|
a = 4 - condition || "string";
|
||||||
|
a = 6 << condition || -4.5;
|
||||||
|
|
||||||
|
a = condition || false;
|
||||||
|
a = console.log("b") || NaN;
|
||||||
|
a = console.log("c") || 0;
|
||||||
|
a = 2 * condition || void 0;
|
||||||
|
a = condition + 3 || null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unary_prefix: {
|
||||||
|
options = {
|
||||||
|
evaluate: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a = !0 && b;
|
||||||
|
a = !0 || b;
|
||||||
|
a = ~1 && b;
|
||||||
|
a = ~1 || b;
|
||||||
|
a = -2 && b;
|
||||||
|
a = -2 || b;
|
||||||
|
a = +3 && b;
|
||||||
|
a = +3 || b;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = b;
|
||||||
|
a = !0;
|
||||||
|
a = b;
|
||||||
|
a = -2;
|
||||||
|
a = b;
|
||||||
|
a = -2;
|
||||||
|
a = b;
|
||||||
|
a = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
negative_zero: {
|
negative_zero: {
|
||||||
options = { evaluate: true }
|
options = { evaluate: true }
|
||||||
input: {
|
input: {
|
||||||
@@ -12,10 +196,11 @@ negative_zero: {
|
|||||||
console.log(
|
console.log(
|
||||||
-0,
|
-0,
|
||||||
0,
|
0,
|
||||||
1 / (-0),
|
-1/0,
|
||||||
1 / (-0)
|
-1/0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
positive_zero: {
|
positive_zero: {
|
||||||
@@ -32,8 +217,776 @@ positive_zero: {
|
|||||||
console.log(
|
console.log(
|
||||||
0,
|
0,
|
||||||
-0,
|
-0,
|
||||||
1 / (0),
|
1/0,
|
||||||
1 / (0)
|
1/0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_constant: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
true.a,
|
||||||
|
false.a,
|
||||||
|
null.a,
|
||||||
|
undefined.a
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
true.a,
|
||||||
|
false.a,
|
||||||
|
null.a,
|
||||||
|
(void 0).a
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:1}) + 1,
|
||||||
|
({a:1}).a + 1,
|
||||||
|
({a:1}).b + 1,
|
||||||
|
({a:1}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:1}) + 1,
|
||||||
|
2,
|
||||||
|
({a:1}).b + 1,
|
||||||
|
1..b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_nested: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1}}) + 1,
|
||||||
|
({a:{b:1}}).a + 1,
|
||||||
|
({a:{b:1}}).b + 1,
|
||||||
|
({a:{b:1}}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1}}) + 1,
|
||||||
|
({a:{b:1}}).a + 1,
|
||||||
|
({a:{b:1}}).b + 1,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_complex: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:1}) + 1,
|
||||||
|
({a:{b:1},b:1}).a + 1,
|
||||||
|
({a:{b:1},b:1}).b + 1,
|
||||||
|
({a:{b:1},b:1}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:1}) + 1,
|
||||||
|
({a:{b:1},b:1}).a + 1,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_repeated: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},a:1}) + 1,
|
||||||
|
({a:{b:1},a:1}).a + 1,
|
||||||
|
({a:{b:1},a:1}).b + 1,
|
||||||
|
({a:{b:1},a:1}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},a:1}) + 1,
|
||||||
|
2,
|
||||||
|
({a:{b:1},a:1}).b + 1,
|
||||||
|
1..b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_accessor: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a = {
|
||||||
|
get b() {},
|
||||||
|
set b() {}
|
||||||
|
};
|
||||||
|
return {a:a};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
var a = {
|
||||||
|
get b() {},
|
||||||
|
set b() {}
|
||||||
|
};
|
||||||
|
return {a:a};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_function: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:function(){}}) + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a + 1,
|
||||||
|
({a:{b:1},b:function(){}}).b + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:function(){}}) + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a + 1,
|
||||||
|
({a:{b:1},b:function(){}}).b + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_integer_key: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({0:1}) + 1,
|
||||||
|
({0:1})[0] + 1,
|
||||||
|
({0:1})["0"] + 1,
|
||||||
|
({0:1})[1] + 1,
|
||||||
|
({0:1})[0][1] + 1,
|
||||||
|
({0:1})[0]["1"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({0:1}) + 1,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
({0:1})[1] + 1,
|
||||||
|
1[1] + 1,
|
||||||
|
1["1"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_integer_key_complex: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({0:{1:1},1:1}) + 1,
|
||||||
|
({0:{1:1},1:1})[0] + 1,
|
||||||
|
({0:{1:1},1:1})["0"] + 1,
|
||||||
|
({0:{1:1},1:1})[1] + 1,
|
||||||
|
({0:{1:1},1:1})[0][1] + 1,
|
||||||
|
({0:{1:1},1:1})[0]["1"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({0:{1:1},1:1}) + 1,
|
||||||
|
"[object Object]1",
|
||||||
|
"[object Object]1",
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_float_key: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({2.72:1}) + 1,
|
||||||
|
({2.72:1})[2.72] + 1,
|
||||||
|
({2.72:1})["2.72"] + 1,
|
||||||
|
({2.72:1})[3.14] + 1,
|
||||||
|
({2.72:1})[2.72][3.14] + 1,
|
||||||
|
({2.72:1})[2.72]["3.14"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({2.72:1}) + 1,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
({2.72:1})[3.14] + 1,
|
||||||
|
1[3.14] + 1,
|
||||||
|
1["3.14"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_float_key_complex: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({2.72:{3.14:1},3.14:1}) + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[2.72] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})["2.72"] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[3.14] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[2.72][3.14] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[2.72]["3.14"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"[object Object]1",
|
||||||
|
"[object Object]1",
|
||||||
|
"[object Object]1",
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_array: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
[1, , 3][1],
|
||||||
|
[1, 2, 3, a] + 1,
|
||||||
|
[1, 2, 3, 4] + 1,
|
||||||
|
[1, 2, 3, a][0] + 1,
|
||||||
|
[1, 2, 3, 4][0] + 1,
|
||||||
|
[1, 2, 3, 4][6 - 5] + 1,
|
||||||
|
[1, , 3, 4][6 - 5] + 1,
|
||||||
|
[[1, 2], [3, 4]][0] + 1,
|
||||||
|
[[1, 2], [3, 4]][6 - 5][1] + 1,
|
||||||
|
[[1, 2], , [3, 4]][6 - 5][1] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
void 0,
|
||||||
|
[1, 2, 3, a] + 1,
|
||||||
|
"1,2,3,41",
|
||||||
|
[1, 2, 3, a][0] + 1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
NaN,
|
||||||
|
"1,21",
|
||||||
|
5,
|
||||||
|
(void 0)[1] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_string: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1234" + 1,
|
||||||
|
"1234"[0] + 1,
|
||||||
|
"1234"[6 - 5] + 1,
|
||||||
|
("12" + "34")[0] + 1,
|
||||||
|
("12" + "34")[6 - 5] + 1,
|
||||||
|
[1, 2, 3, 4].join("")[0] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"12341",
|
||||||
|
"11",
|
||||||
|
"21",
|
||||||
|
"11",
|
||||||
|
"21",
|
||||||
|
"11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_array_bad_index: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
[1, 2, 3, 4].a + 1,
|
||||||
|
[1, 2, 3, 4]["a"] + 1,
|
||||||
|
[1, 2, 3, 4][3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
[1, 2, 3, 4].a + 1,
|
||||||
|
[1, 2, 3, 4]["a"] + 1,
|
||||||
|
[1, 2, 3, 4][3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_string_bad_index: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1234".a + 1,
|
||||||
|
"1234"["a"] + 1,
|
||||||
|
"1234"[3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"1234".a + 1,
|
||||||
|
"1234"["a"] + 1,
|
||||||
|
"1234"[3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_prototype_function: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = ({valueOf: 0}) < 1;
|
||||||
|
var b = ({toString: 0}) < 1;
|
||||||
|
var c = ({valueOf: 0}) + "";
|
||||||
|
var d = ({toString: 0}) + "";
|
||||||
|
var e = (({valueOf: 0}) + "")[2];
|
||||||
|
var f = (({toString: 0}) + "")[2];
|
||||||
|
var g = ({valueOf: 0}).valueOf();
|
||||||
|
var h = ({toString: 0}).toString();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = ({valueOf: 0}) < 1;
|
||||||
|
var b = ({toString: 0}) < 1;
|
||||||
|
var c = ({valueOf: 0}) + "";
|
||||||
|
var d = ({toString: 0}) + "";
|
||||||
|
var e = (({valueOf: 0}) + "")[2];
|
||||||
|
var f = (({toString: 0}) + "")[2];
|
||||||
|
var g = ({valueOf: 0}).valueOf();
|
||||||
|
var h = "" + ({toString: 0});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call_args: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
console.log(a);
|
||||||
|
+function(a) {
|
||||||
|
return a;
|
||||||
|
}(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
console.log(1);
|
||||||
|
+(1, 1);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
call_args_drop_param: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
console.log(a);
|
||||||
|
+function(a) {
|
||||||
|
return a;
|
||||||
|
}(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1);
|
||||||
|
+(b, 1);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
in_boolean_context: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
!42,
|
||||||
|
!"foo",
|
||||||
|
![1, 2],
|
||||||
|
!/foo/,
|
||||||
|
!b(42),
|
||||||
|
!b("foo"),
|
||||||
|
!b([1, 2]),
|
||||||
|
!b(/foo/),
|
||||||
|
![1, foo()],
|
||||||
|
![1, foo(), 2]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
!1,
|
||||||
|
!1,
|
||||||
|
!1,
|
||||||
|
!1,
|
||||||
|
!b(42),
|
||||||
|
!b("foo"),
|
||||||
|
!b([1, 2]),
|
||||||
|
!b(/foo/),
|
||||||
|
![1, foo()],
|
||||||
|
(foo(), !1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_charAt: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1234" + 1,
|
||||||
|
"1234".charAt(0) + 1,
|
||||||
|
"1234".charAt(6 - 5) + 1,
|
||||||
|
("12" + "34").charAt(0) + 1,
|
||||||
|
("12" + "34").charAt(6 - 5) + 1,
|
||||||
|
[1, 2, 3, 4].join("").charAt(0) + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"12341",
|
||||||
|
"11",
|
||||||
|
"21",
|
||||||
|
"11",
|
||||||
|
"21",
|
||||||
|
"11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_charAt_bad_index: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1234".charAt() + 1,
|
||||||
|
"1234".charAt("a") + 1,
|
||||||
|
"1234".charAt(3.14) + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"11",
|
||||||
|
"11",
|
||||||
|
"41"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_charAt_noop: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
s.charAt(0),
|
||||||
|
"string".charAt(x)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
s.charAt(0),
|
||||||
|
"string".charAt(x)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1649: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(-1 + -1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(-2);
|
||||||
|
}
|
||||||
|
expect_stdout: "-2";
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1760_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function(a) {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (NaN) {
|
||||||
|
a = +"foo";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(a) {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (NaN) {
|
||||||
|
a = 0 / 0;
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "NaN"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1760_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
keep_infinity: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function(a) {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (Infinity) {
|
||||||
|
a = 123456789 / 0;
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(a) {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (Infinity) {
|
||||||
|
a = 1 / 0;
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
expect_stdout: "Infinity"
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_expr_1: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(delete undefined);
|
||||||
|
console.log(delete void 0);
|
||||||
|
console.log(delete Infinity);
|
||||||
|
console.log(delete (1 / 0));
|
||||||
|
console.log(delete NaN);
|
||||||
|
console.log(delete (0 / 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(delete undefined);
|
||||||
|
console.log((void 0, !0));
|
||||||
|
console.log(delete Infinity);
|
||||||
|
console.log((1 / 0, !0));
|
||||||
|
console.log(delete NaN);
|
||||||
|
console.log((0 / 0, !0));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_expr_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
keep_infinity: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(delete undefined);
|
||||||
|
console.log(delete void 0);
|
||||||
|
console.log(delete Infinity);
|
||||||
|
console.log(delete (1 / 0));
|
||||||
|
console.log(delete NaN);
|
||||||
|
console.log(delete (0 / 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(delete undefined);
|
||||||
|
console.log((void 0, !0));
|
||||||
|
console.log(delete Infinity);
|
||||||
|
console.log((1 / 0, !0));
|
||||||
|
console.log(delete NaN);
|
||||||
|
console.log((0 / 0, !0));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_binary_1: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(delete (true && undefined));
|
||||||
|
console.log(delete (true && void 0));
|
||||||
|
console.log(delete (true && Infinity));
|
||||||
|
console.log(delete (true && (1 / 0)));
|
||||||
|
console.log(delete (true && NaN));
|
||||||
|
console.log(delete (true && (0 / 0)));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_binary_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
keep_infinity: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(delete (false || undefined));
|
||||||
|
console.log(delete (false || void 0));
|
||||||
|
console.log(delete (false || Infinity));
|
||||||
|
console.log(delete (false || (1 / 0)));
|
||||||
|
console.log(delete (false || NaN));
|
||||||
|
console.log(delete (false || (0 / 0)));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Infinity_NaN_undefined_LHS: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
Infinity = Infinity;
|
||||||
|
++Infinity;
|
||||||
|
Infinity--;
|
||||||
|
NaN *= NaN;
|
||||||
|
++NaN;
|
||||||
|
NaN--;
|
||||||
|
undefined |= undefined;
|
||||||
|
++undefined;
|
||||||
|
undefined--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
"function f() {",
|
||||||
|
" Infinity = 1 / 0;",
|
||||||
|
" ++Infinity;",
|
||||||
|
" Infinity--;",
|
||||||
|
" NaN *= NaN;",
|
||||||
|
" ++NaN;",
|
||||||
|
" NaN--;",
|
||||||
|
" undefined |= void 0;",
|
||||||
|
" ++undefined;",
|
||||||
|
" undefined--;",
|
||||||
|
"}",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
169
test/compress/functions.js
Normal file
169
test/compress/functions.js
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
non_ascii_function_identifier_name: {
|
||||||
|
input: {
|
||||||
|
function fooλ(δλ) {}
|
||||||
|
function λ(δλ) {}
|
||||||
|
(function λ(δλ) {})()
|
||||||
|
}
|
||||||
|
expect_exact: "function fooλ(δλ){}function λ(δλ){}(function λ(δλ){})();"
|
||||||
|
}
|
||||||
|
|
||||||
|
iifes_returning_constants_keep_fargs_true: {
|
||||||
|
options = {
|
||||||
|
keep_fargs : true,
|
||||||
|
side_effects : true,
|
||||||
|
evaluate : true,
|
||||||
|
unused : true,
|
||||||
|
dead_code : true,
|
||||||
|
conditionals : true,
|
||||||
|
comparisons : true,
|
||||||
|
booleans : true,
|
||||||
|
if_return : true,
|
||||||
|
join_vars : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
cascade : true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return -1.23; }());
|
||||||
|
console.log( function foo(){ return "okay"; }() );
|
||||||
|
console.log( function foo(x, y, z){ return 123; }() );
|
||||||
|
console.log( function(x, y, z){ return z; }() );
|
||||||
|
console.log( function(x, y, z){ if (x) return y; return z; }(1, 2, 3) );
|
||||||
|
console.log( function(x, y){ return x * y; }(2, 3) );
|
||||||
|
console.log( function(x, y){ return x * y; }(2, 3, a(), b()) );
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("okay");
|
||||||
|
console.log(123);
|
||||||
|
console.log(void 0);
|
||||||
|
console.log(2);
|
||||||
|
console.log(6);
|
||||||
|
console.log((a(), b(), 6));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
iifes_returning_constants_keep_fargs_false: {
|
||||||
|
options = {
|
||||||
|
keep_fargs : false,
|
||||||
|
side_effects : true,
|
||||||
|
evaluate : true,
|
||||||
|
unused : true,
|
||||||
|
dead_code : true,
|
||||||
|
conditionals : true,
|
||||||
|
comparisons : true,
|
||||||
|
booleans : true,
|
||||||
|
if_return : true,
|
||||||
|
join_vars : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
cascade : true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return -1.23; }());
|
||||||
|
console.log( function foo(){ return "okay"; }() );
|
||||||
|
console.log( function foo(x, y, z){ return 123; }() );
|
||||||
|
console.log( function(x, y, z){ return z; }() );
|
||||||
|
console.log( function(x, y, z){ if (x) return y; return z; }(1, 2, 3) );
|
||||||
|
console.log( function(x, y){ return x * y; }(2, 3) );
|
||||||
|
console.log( function(x, y){ return x * y; }(2, 3, a(), b()) );
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("okay");
|
||||||
|
console.log(123);
|
||||||
|
console.log(void 0);
|
||||||
|
console.log(2);
|
||||||
|
console.log(6);
|
||||||
|
console.log((a(), b(), 6));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_485_crashing_1530: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
if (true) return;
|
||||||
|
var b = 42;
|
||||||
|
})(this);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
this, void 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1841_1: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 10;
|
||||||
|
!function(arg) {
|
||||||
|
for (var key in "hi")
|
||||||
|
var n = arg.baz, n = [ b = 42 ];
|
||||||
|
}(--b);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 10;
|
||||||
|
!function() {
|
||||||
|
for (var key in "hi")
|
||||||
|
b = 42;
|
||||||
|
}(--b);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_exact: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1841_2: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
pure_getters: false,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var b = 10;
|
||||||
|
!function(arg) {
|
||||||
|
for (var key in "hi")
|
||||||
|
var n = arg.baz, n = [ b = 42 ];
|
||||||
|
}(--b);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var b = 10;
|
||||||
|
!function(arg) {
|
||||||
|
for (var key in "hi")
|
||||||
|
arg.baz, b = 42;
|
||||||
|
}(--b);
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
expect_exact: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
function_returning_constant_literal: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
toplevel: true,
|
||||||
|
evaluate: true,
|
||||||
|
cascade: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function greeter() {
|
||||||
|
return { message: 'Hello there' };
|
||||||
|
}
|
||||||
|
var greeting = greeter();
|
||||||
|
console.log(greeting.message);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("Hello there");
|
||||||
|
}
|
||||||
|
expect_stdout: "Hello there"
|
||||||
|
}
|
||||||
162
test/compress/global_defs.js
Normal file
162
test/compress/global_defs.js
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
must_replace: {
|
||||||
|
options = {
|
||||||
|
global_defs: {
|
||||||
|
D: "foo bar",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(D);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("foo bar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyword: {
|
||||||
|
options = {
|
||||||
|
global_defs: {
|
||||||
|
undefined: 0,
|
||||||
|
NaN: 1,
|
||||||
|
Infinity: 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(undefined, NaN, Infinity);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(0, 1, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
global_defs: {
|
||||||
|
CONFIG: {
|
||||||
|
DEBUG: [ 0 ],
|
||||||
|
VALUE: 42,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(CONFIG) {
|
||||||
|
// CONFIG not global - do not replace
|
||||||
|
return CONFIG.VALUE;
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
var CONFIG = { VALUE: 1 };
|
||||||
|
// CONFIG not global - do not replace
|
||||||
|
return CONFIG.VALUE;
|
||||||
|
}
|
||||||
|
function h() {
|
||||||
|
return CONFIG.VALUE;
|
||||||
|
}
|
||||||
|
if (CONFIG.DEBUG[0])
|
||||||
|
console.debug("foo");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(CONFIG) {
|
||||||
|
return CONFIG.VALUE;
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
var CONFIG = { VALUE: 1 };
|
||||||
|
return CONFIG.VALUE;
|
||||||
|
}
|
||||||
|
function h() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
if (0)
|
||||||
|
console.debug("foo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expanded: {
|
||||||
|
options = {
|
||||||
|
global_defs: {
|
||||||
|
"CONFIG.DEBUG": [ 0 ],
|
||||||
|
"CONFIG.VALUE": 42,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(CONFIG) {
|
||||||
|
// CONFIG not global - do not replace
|
||||||
|
return CONFIG.VALUE;
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
var CONFIG = { VALUE: 1 };
|
||||||
|
// CONFIG not global - do not replace
|
||||||
|
return CONFIG.VALUE;
|
||||||
|
}
|
||||||
|
function h() {
|
||||||
|
return CONFIG.VALUE;
|
||||||
|
}
|
||||||
|
if (CONFIG.DEBUG[0])
|
||||||
|
console.debug("foo");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(CONFIG) {
|
||||||
|
return CONFIG.VALUE;
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
var CONFIG = { VALUE: 1 };
|
||||||
|
return CONFIG.VALUE;
|
||||||
|
}
|
||||||
|
function h() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
if ([0][0])
|
||||||
|
console.debug("foo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mixed: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
global_defs: {
|
||||||
|
"CONFIG.VALUE": 42,
|
||||||
|
"FOO.BAR": "moo",
|
||||||
|
},
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var FOO = { BAR: 0 };
|
||||||
|
console.log(FOO.BAR);
|
||||||
|
console.log(++CONFIG.DEBUG);
|
||||||
|
console.log(++CONFIG.VALUE);
|
||||||
|
console.log(++CONFIG["VAL" + "UE"]);
|
||||||
|
console.log(++DEBUG[CONFIG.VALUE]);
|
||||||
|
CONFIG.VALUE.FOO = "bar";
|
||||||
|
console.log(CONFIG);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var FOO = { BAR: 0 };
|
||||||
|
console.log("moo");
|
||||||
|
console.log(++CONFIG.DEBUG);
|
||||||
|
console.log(++CONFIG.VALUE);
|
||||||
|
console.log(++CONFIG.VALUE);
|
||||||
|
console.log(++DEBUG[42]);
|
||||||
|
CONFIG.VALUE.FOO = "bar";
|
||||||
|
console.log(CONFIG);
|
||||||
|
}
|
||||||
|
expect_warnings: [
|
||||||
|
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:126,22]',
|
||||||
|
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]',
|
||||||
|
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:129,8]',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1801: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
global_defs: {
|
||||||
|
"CONFIG.FOO.BAR": true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(CONFIG.FOO.BAR);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!0);
|
||||||
|
}
|
||||||
|
}
|
||||||
90
test/compress/hoist_vars.js
Normal file
90
test/compress/hoist_vars.js
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
statements: {
|
||||||
|
options = {
|
||||||
|
hoist_funs: false,
|
||||||
|
hoist_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a = 1;
|
||||||
|
var b = 2;
|
||||||
|
var c = 3;
|
||||||
|
function g() {}
|
||||||
|
return g(a, b, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
var a = 1, b = 2, c = 3;
|
||||||
|
function g() {}
|
||||||
|
return g(a, b, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
statements_funs: {
|
||||||
|
options = {
|
||||||
|
hoist_funs: true,
|
||||||
|
hoist_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a = 1;
|
||||||
|
var b = 2;
|
||||||
|
var c = 3;
|
||||||
|
function g() {}
|
||||||
|
return g(a, b, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
function g() {}
|
||||||
|
var a = 1, b = 2, c = 3;
|
||||||
|
return g(a, b, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sequences: {
|
||||||
|
options = {
|
||||||
|
hoist_funs: false,
|
||||||
|
hoist_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a = 1, b = 2;
|
||||||
|
function g() {}
|
||||||
|
var c = 3;
|
||||||
|
return g(a, b, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
var c, a = 1, b = 2;
|
||||||
|
function g() {}
|
||||||
|
c = 3;
|
||||||
|
return g(a, b, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sequences_funs: {
|
||||||
|
options = {
|
||||||
|
hoist_funs: true,
|
||||||
|
hoist_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a = 1, b = 2;
|
||||||
|
function g() {}
|
||||||
|
var c = 3;
|
||||||
|
return g(a, b, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
function g() {}
|
||||||
|
var a = 1, b = 2, c = 3;
|
||||||
|
return g(a, b, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,22 +47,6 @@ html_comment_in_greater_than_or_equal: {
|
|||||||
expect_exact: "function f(a,b){return a-- >=b}";
|
expect_exact: "function f(a,b){return a-- >=b}";
|
||||||
}
|
}
|
||||||
|
|
||||||
html_comment_in_right_shift_assign: {
|
|
||||||
input: {
|
|
||||||
// Note: illegal javascript
|
|
||||||
function f(a, b) { return a-- >>= b; }
|
|
||||||
}
|
|
||||||
expect_exact: "function f(a,b){return a-- >>=b}";
|
|
||||||
}
|
|
||||||
|
|
||||||
html_comment_in_zero_fill_right_shift_assign: {
|
|
||||||
input: {
|
|
||||||
// Note: illegal javascript
|
|
||||||
function f(a, b) { return a-- >>>= b; }
|
|
||||||
}
|
|
||||||
expect_exact: "function f(a,b){return a-- >>>=b}";
|
|
||||||
}
|
|
||||||
|
|
||||||
html_comment_in_string_literal: {
|
html_comment_in_string_literal: {
|
||||||
input: {
|
input: {
|
||||||
function f() { return "<!--HTML-->comment in<!--string literal-->"; }
|
function f() { return "<!--HTML-->comment in<!--string literal-->"; }
|
||||||
|
|||||||
@@ -170,8 +170,51 @@ if_return_7: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
// suboptimal
|
function f(x){if(x)return!0;foo(),bar()}
|
||||||
function f(x){return!!x||(foo(),void bar())}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if_return_8: {
|
||||||
|
options = {
|
||||||
|
if_return: true,
|
||||||
|
sequences: true,
|
||||||
|
conditionals: true,
|
||||||
|
side_effects : true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(e) {
|
||||||
|
if (2 == e) return foo();
|
||||||
|
if (3 == e) return bar();
|
||||||
|
if (4 == e) return baz();
|
||||||
|
fail(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function g(e) {
|
||||||
|
if (a(e)) return foo();
|
||||||
|
if (b(e)) return bar();
|
||||||
|
if (c(e)) return baz();
|
||||||
|
fail(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function h(e) {
|
||||||
|
if (a(e)) return foo();
|
||||||
|
else if (b(e)) return bar();
|
||||||
|
else if (c(e)) return baz();
|
||||||
|
else fail(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function i(e) {
|
||||||
|
if (a(e)) return foo();
|
||||||
|
else if (b(e)) return bar();
|
||||||
|
else if (c(e)) return baz();
|
||||||
|
fail(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(e){return 2==e?foo():3==e?bar():4==e?baz():void fail(e)}
|
||||||
|
function g(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
|
||||||
|
function h(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
|
||||||
|
function i(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,3 +248,57 @@ issue_1089: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1437: {
|
||||||
|
options = {
|
||||||
|
if_return : true,
|
||||||
|
sequences : true,
|
||||||
|
conditionals : false
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function x() {
|
||||||
|
if (a())
|
||||||
|
return b();
|
||||||
|
if (c())
|
||||||
|
return d();
|
||||||
|
else
|
||||||
|
e();
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function x() {
|
||||||
|
if (a())
|
||||||
|
return b();
|
||||||
|
if (c())
|
||||||
|
return d();
|
||||||
|
else
|
||||||
|
e()
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1437_conditionals: {
|
||||||
|
options = {
|
||||||
|
conditionals : true,
|
||||||
|
if_return : true,
|
||||||
|
sequences : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function x() {
|
||||||
|
if (a())
|
||||||
|
return b();
|
||||||
|
if (c())
|
||||||
|
return d();
|
||||||
|
else
|
||||||
|
e();
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function x() {
|
||||||
|
return a() ? b() : c() ? d() : (e(), f(), void 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ non_hoisted_function_after_return_2a: {
|
|||||||
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
|
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
|
||||||
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
||||||
if_return: true, join_vars: true, cascade: true, side_effects: true,
|
if_return: true, join_vars: true, cascade: true, side_effects: true,
|
||||||
collapse_vars: false, passes: 2
|
collapse_vars: false, passes: 2, warnings: "verbose"
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function foo(x) {
|
function foo(x) {
|
||||||
@@ -75,7 +75,7 @@ non_hoisted_function_after_return_2a: {
|
|||||||
"WARN: Declarations in 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 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 b [test/compress/issue-1034.js:51,20]",
|
||||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]"
|
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,8 +114,5 @@ non_hoisted_function_after_return_2b: {
|
|||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]",
|
||||||
"WARN: Declarations in 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:101,12]",
|
||||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:95,20]",
|
|
||||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:97,16]"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,7 @@
|
|||||||
const_declaration: {
|
|
||||||
options = {
|
|
||||||
evaluate: true
|
|
||||||
};
|
|
||||||
|
|
||||||
input: {
|
|
||||||
const goog = goog || {};
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
const goog = goog || {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const_pragma: {
|
const_pragma: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
input: {
|
input: {
|
||||||
@@ -27,7 +15,8 @@ const_pragma: {
|
|||||||
// for completeness' sake
|
// for completeness' sake
|
||||||
not_const: {
|
not_const: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
typeof_eq_undefined: {
|
|
||||||
options = {
|
|
||||||
comparisons: true
|
|
||||||
};
|
|
||||||
input: { a = typeof b.c != "undefined" }
|
|
||||||
expect: { a = "undefined" != typeof b.c }
|
|
||||||
}
|
|
||||||
|
|
||||||
typeof_eq_undefined_unsafe: {
|
|
||||||
options = {
|
|
||||||
comparisons: true,
|
|
||||||
unsafe: true
|
|
||||||
};
|
|
||||||
input: { a = typeof b.c != "undefined" }
|
|
||||||
expect: { a = void 0 !== b.c }
|
|
||||||
}
|
|
||||||
|
|
||||||
typeof_eq_undefined_unsafe2: {
|
|
||||||
options = {
|
|
||||||
comparisons: true,
|
|
||||||
unsafe: true
|
|
||||||
};
|
|
||||||
input: { a = "undefined" != typeof b.c }
|
|
||||||
expect: { a = void 0 !== b.c }
|
|
||||||
}
|
|
||||||
@@ -193,13 +193,15 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
|
|||||||
cascade: true,
|
cascade: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
sequences: false,
|
sequences: false,
|
||||||
|
keep_infinity: false,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
var f = console.log;
|
||||||
var o = {
|
var o = {
|
||||||
undefined : 3,
|
undefined : 3,
|
||||||
NaN : 4,
|
NaN : 4,
|
||||||
Infinity : 5,
|
Infinity : 5,
|
||||||
}
|
};
|
||||||
if (o) {
|
if (o) {
|
||||||
f(undefined, void 0);
|
f(undefined, void 0);
|
||||||
f(NaN, 0/0);
|
f(NaN, 0/0);
|
||||||
@@ -216,25 +218,88 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var o = {
|
var f = console.log, o = {
|
||||||
undefined : 3,
|
undefined : 3,
|
||||||
NaN : 4,
|
NaN : 4,
|
||||||
Infinity : 5
|
Infinity : 5
|
||||||
}
|
};
|
||||||
if (o) {
|
if (o) {
|
||||||
f(void 0, void 0);
|
f(void 0, void 0);
|
||||||
f(NaN, NaN);
|
f(NaN, NaN);
|
||||||
f(1/0, 1/0);
|
f(1/0, 1/0);
|
||||||
f(-(1/0), -(1/0));
|
f(-1/0, -1/0);
|
||||||
f(NaN, NaN);
|
f(NaN, NaN);
|
||||||
}
|
}
|
||||||
with (o) {
|
with (o) {
|
||||||
f(undefined, void 0);
|
f(undefined, void 0);
|
||||||
f(NaN, 0/0);
|
f(NaN, 0/0);
|
||||||
f(Infinity, 1/0);
|
f(Infinity, 1/0);
|
||||||
f(-Infinity, -(1/0));
|
f(-Infinity, -1/0);
|
||||||
f(9 + undefined, 9 + void 0);
|
f(9 + undefined, 9 + void 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
evaluate: true,
|
||||||
|
dead_code: true,
|
||||||
|
conditionals: true,
|
||||||
|
comparisons: true,
|
||||||
|
booleans: true,
|
||||||
|
hoist_funs: true,
|
||||||
|
keep_fargs: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
cascade: true,
|
||||||
|
side_effects: true,
|
||||||
|
sequences: false,
|
||||||
|
keep_infinity: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var f = console.log;
|
||||||
|
var o = {
|
||||||
|
undefined : 3,
|
||||||
|
NaN : 4,
|
||||||
|
Infinity : 5,
|
||||||
|
};
|
||||||
|
if (o) {
|
||||||
|
f(undefined, void 0);
|
||||||
|
f(NaN, 0/0);
|
||||||
|
f(Infinity, 1/0);
|
||||||
|
f(-Infinity, -(1/0));
|
||||||
|
f(2 + 7 + undefined, 2 + 7 + void 0);
|
||||||
|
}
|
||||||
|
with (o) {
|
||||||
|
f(undefined, void 0);
|
||||||
|
f(NaN, 0/0);
|
||||||
|
f(Infinity, 1/0);
|
||||||
|
f(-Infinity, -(1/0));
|
||||||
|
f(2 + 7 + undefined, 2 + 7 + void 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var f = console.log, o = {
|
||||||
|
undefined : 3,
|
||||||
|
NaN : 4,
|
||||||
|
Infinity : 5
|
||||||
|
};
|
||||||
|
if (o) {
|
||||||
|
f(void 0, void 0);
|
||||||
|
f(NaN, NaN);
|
||||||
|
f(Infinity, 1/0);
|
||||||
|
f(-Infinity, -1/0);
|
||||||
|
f(NaN, NaN);
|
||||||
|
}
|
||||||
|
with (o) {
|
||||||
|
f(undefined, void 0);
|
||||||
|
f(NaN, 0/0);
|
||||||
|
f(Infinity, 1/0);
|
||||||
|
f(-Infinity, -1/0);
|
||||||
|
f(9 + undefined, 9 + void 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,4 +49,3 @@ mangle_keep_fnames_true: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
176
test/compress/issue-1261.js
Normal file
176
test/compress/issue-1261.js
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
pure_function_calls: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
conditionals : true,
|
||||||
|
comparisons : true,
|
||||||
|
side_effects : true,
|
||||||
|
booleans : true,
|
||||||
|
unused : true,
|
||||||
|
if_return : true,
|
||||||
|
join_vars : true,
|
||||||
|
cascade : true,
|
||||||
|
negate_iife : true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
// pure top-level IIFE will be dropped
|
||||||
|
// @__PURE__ - comment
|
||||||
|
(function() {
|
||||||
|
console.log("iife0");
|
||||||
|
})();
|
||||||
|
|
||||||
|
// pure top-level IIFE assigned to unreferenced var will not be dropped
|
||||||
|
var iife1 = /*@__PURE__*/(function() {
|
||||||
|
console.log("iife1");
|
||||||
|
function iife1() {}
|
||||||
|
return iife1;
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
// pure IIFE in function scope assigned to unreferenced var will be dropped
|
||||||
|
var iife2 = /*#__PURE__*/(function() {
|
||||||
|
console.log("iife2");
|
||||||
|
function iife2() {}
|
||||||
|
return iife2;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
|
||||||
|
// comment #__PURE__ comment
|
||||||
|
bar(), baz(), quux();
|
||||||
|
a.b(), /* @__PURE__ */ c.d.e(), f.g();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var iife1 = function() {
|
||||||
|
console.log("iife1");
|
||||||
|
function iife1() {}
|
||||||
|
return iife1;
|
||||||
|
}();
|
||||||
|
|
||||||
|
baz(), quux();
|
||||||
|
a.b(), f.g();
|
||||||
|
}
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:17,8]",
|
||||||
|
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:17,8]",
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:30,37]",
|
||||||
|
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:30,16]",
|
||||||
|
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:28,8]",
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:38,8]",
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:39,31]",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
pure_function_calls_toplevel: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
conditionals : true,
|
||||||
|
comparisons : true,
|
||||||
|
side_effects : true,
|
||||||
|
booleans : true,
|
||||||
|
unused : true,
|
||||||
|
if_return : true,
|
||||||
|
join_vars : true,
|
||||||
|
cascade : true,
|
||||||
|
negate_iife : true,
|
||||||
|
toplevel : true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
// pure top-level IIFE will be dropped
|
||||||
|
// @__PURE__ - comment
|
||||||
|
(function() {
|
||||||
|
console.log("iife0");
|
||||||
|
})();
|
||||||
|
|
||||||
|
// pure top-level IIFE assigned to unreferenced var will be dropped
|
||||||
|
var iife1 = /*@__PURE__*/(function() {
|
||||||
|
console.log("iife1");
|
||||||
|
function iife1() {}
|
||||||
|
return iife1;
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
// pure IIFE in function scope assigned to unreferenced var will be dropped
|
||||||
|
var iife2 = /*#__PURE__*/(function() {
|
||||||
|
console.log("iife2");
|
||||||
|
function iife2() {}
|
||||||
|
return iife2;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
|
||||||
|
// comment #__PURE__ comment
|
||||||
|
bar(), baz(), quux();
|
||||||
|
a.b(), /* @__PURE__ */ c.d.e(), f.g();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
baz(), quux();
|
||||||
|
a.b(), f.g();
|
||||||
|
}
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:79,8]",
|
||||||
|
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:79,8]",
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:92,37]",
|
||||||
|
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:92,16]",
|
||||||
|
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:90,8]",
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,8]",
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:101,31]",
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:84,33]",
|
||||||
|
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:84,12]",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
should_warn: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
/* @__PURE__ */(function(){x})(), void/* @__PURE__ */(function(){y})();
|
||||||
|
/* @__PURE__ */(function(){x})() || true ? foo() : bar();
|
||||||
|
true || /* @__PURE__ */(function(){y})() ? foo() : bar();
|
||||||
|
/* @__PURE__ */(function(){x})() && false ? foo() : bar();
|
||||||
|
false && /* @__PURE__ */(function(){y})() ? foo() : bar();
|
||||||
|
/* @__PURE__ */(function(){x})() + "foo" ? bar() : baz();
|
||||||
|
"foo" + /* @__PURE__ */(function(){y})() ? bar() : baz();
|
||||||
|
/* @__PURE__ */(function(){x})() ? foo() : foo();
|
||||||
|
[/* @__PURE__ */(function(){x})()] ? foo() : bar();
|
||||||
|
!{ foo: /* @__PURE__ */(function(){x})() } ? bar() : baz();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo();
|
||||||
|
foo();
|
||||||
|
bar();
|
||||||
|
bar();
|
||||||
|
bar();
|
||||||
|
bar();
|
||||||
|
foo();
|
||||||
|
foo();
|
||||||
|
baz();
|
||||||
|
}
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,61]",
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,23]",
|
||||||
|
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:128,23]",
|
||||||
|
"WARN: Boolean || always true [test/compress/issue-1261.js:129,23]",
|
||||||
|
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:129,23]",
|
||||||
|
"WARN: Condition always true [test/compress/issue-1261.js:129,23]",
|
||||||
|
"WARN: 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]",
|
||||||
|
]
|
||||||
|
}
|
||||||
50
test/compress/issue-1275.js
Normal file
50
test/compress/issue-1275.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
string_plus_optimization: {
|
||||||
|
options = {
|
||||||
|
side_effects : true,
|
||||||
|
evaluate : true,
|
||||||
|
conditionals : true,
|
||||||
|
comparisons : true,
|
||||||
|
dead_code : true,
|
||||||
|
booleans : true,
|
||||||
|
unused : true,
|
||||||
|
if_return : true,
|
||||||
|
join_vars : true,
|
||||||
|
cascade : true,
|
||||||
|
hoist_funs : true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function foo(anything) {
|
||||||
|
function throwing_function() {
|
||||||
|
throw "nope";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
console.log('0' + throwing_function() ? "yes" : "no");
|
||||||
|
} catch (ex) {
|
||||||
|
console.log(ex);
|
||||||
|
}
|
||||||
|
console.log('0' + anything ? "yes" : "no");
|
||||||
|
console.log(anything + '0' ? "Yes" : "No");
|
||||||
|
console.log('' + anything);
|
||||||
|
console.log(anything + '');
|
||||||
|
}
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo(anything) {
|
||||||
|
function throwing_function() {
|
||||||
|
throw "nope";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
console.log((throwing_function(), "yes"));
|
||||||
|
} catch (ex) {
|
||||||
|
console.log(ex);
|
||||||
|
}
|
||||||
|
console.log("yes");
|
||||||
|
console.log("Yes");
|
||||||
|
console.log('' + anything);
|
||||||
|
console.log(anything + '');
|
||||||
|
}
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
57
test/compress/issue-1321.js
Normal file
57
test/compress/issue-1321.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
issue_1321_no_debug: {
|
||||||
|
mangle_props = {
|
||||||
|
keep_quoted: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = {};
|
||||||
|
x.foo = 1;
|
||||||
|
x["a"] = 2 * x.foo;
|
||||||
|
console.log(x.foo, x["a"]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = {};
|
||||||
|
x.b = 1;
|
||||||
|
x["a"] = 2 * x.b;
|
||||||
|
console.log(x.b, x["a"]);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1321_debug: {
|
||||||
|
mangle_props = {
|
||||||
|
keep_quoted: true,
|
||||||
|
debug: ""
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = {};
|
||||||
|
x.foo = 1;
|
||||||
|
x["_$foo$_"] = 2 * x.foo;
|
||||||
|
console.log(x.foo, x["_$foo$_"]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = {};
|
||||||
|
x.a = 1;
|
||||||
|
x["_$foo$_"] = 2 * x.a;
|
||||||
|
console.log(x.a, x["_$foo$_"]);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1321_with_quoted: {
|
||||||
|
mangle_props = {
|
||||||
|
keep_quoted: false
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = {};
|
||||||
|
x.foo = 1;
|
||||||
|
x["a"] = 2 * x.foo;
|
||||||
|
console.log(x.foo, x["a"]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = {};
|
||||||
|
x.a = 1;
|
||||||
|
x["b"] = 2 * x.a;
|
||||||
|
console.log(x.a, x["b"]);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
151
test/compress/issue-1431.js
Normal file
151
test/compress/issue-1431.js
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
level_zero: {
|
||||||
|
options = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x) {
|
||||||
|
function n(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(r) {
|
||||||
|
function n(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
level_one: {
|
||||||
|
options = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x) {
|
||||||
|
return function() {
|
||||||
|
function n(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return x(n);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(r) {
|
||||||
|
return function() {
|
||||||
|
function n(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return r(n);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
level_two: {
|
||||||
|
options = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x) {
|
||||||
|
return function() {
|
||||||
|
function r(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
function n(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return x(n);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(t) {
|
||||||
|
return function() {
|
||||||
|
function r(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return function() {
|
||||||
|
function n(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return t(n);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
level_three: {
|
||||||
|
options = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x) {
|
||||||
|
return function() {
|
||||||
|
function r(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
function() {
|
||||||
|
function t(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
function n(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
return x(n);
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(t) {
|
||||||
|
return function() {
|
||||||
|
function r(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
function() {
|
||||||
|
function t(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
function n(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return t(n);
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
test/compress/issue-1443.js
Normal file
61
test/compress/issue-1443.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// tests assume that variable `undefined` not redefined and has `void 0` as value
|
||||||
|
|
||||||
|
unsafe_undefined: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
unsafe: true
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
function f(undefined) {
|
||||||
|
return function() {
|
||||||
|
if (a)
|
||||||
|
return b;
|
||||||
|
if (c)
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(n) {
|
||||||
|
return function() {
|
||||||
|
return a ? b : c ? d : n;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_fnames: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
unsafe: true
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
keep_fnames: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(undefined) {
|
||||||
|
return function() {
|
||||||
|
function n(a) {
|
||||||
|
return a * a;
|
||||||
|
}
|
||||||
|
if (a)
|
||||||
|
return b;
|
||||||
|
if (c)
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(r) {
|
||||||
|
return function() {
|
||||||
|
function n(n) {
|
||||||
|
return n * n;
|
||||||
|
}
|
||||||
|
return a ? b : c ? d : r;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
71
test/compress/issue-1446.js
Normal file
71
test/compress/issue-1446.js
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
typeof_eq_undefined: {
|
||||||
|
options = {
|
||||||
|
comparisons: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = typeof b != "undefined";
|
||||||
|
b = typeof a != "undefined";
|
||||||
|
var c = typeof d.e !== "undefined";
|
||||||
|
var f = "undefined" === typeof g;
|
||||||
|
g = "undefined" === typeof f;
|
||||||
|
var h = "undefined" == typeof i.j;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "undefined" != typeof b;
|
||||||
|
b = void 0 !== a;
|
||||||
|
var c = void 0 !== d.e;
|
||||||
|
var f = "undefined" == typeof g;
|
||||||
|
g = void 0 === f;
|
||||||
|
var h = void 0 === i.j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeof_eq_undefined_ie8: {
|
||||||
|
options = {
|
||||||
|
comparisons: true,
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = typeof b != "undefined";
|
||||||
|
b = typeof a != "undefined";
|
||||||
|
var c = typeof d.e !== "undefined";
|
||||||
|
var f = "undefined" === typeof g;
|
||||||
|
g = "undefined" === typeof f;
|
||||||
|
var h = "undefined" == typeof i.j;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "undefined" != typeof b;
|
||||||
|
b = void 0 !== a;
|
||||||
|
var c = "undefined" != typeof d.e;
|
||||||
|
var f = "undefined" == typeof g;
|
||||||
|
g = void 0 === f;
|
||||||
|
var h = "undefined" == typeof i.j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
undefined_redefined: {
|
||||||
|
options = {
|
||||||
|
comparisons: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(undefined) {
|
||||||
|
var n = 1;
|
||||||
|
return typeof n == "undefined";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "function f(undefined){var n=1;return void 0===n}"
|
||||||
|
}
|
||||||
|
|
||||||
|
undefined_redefined_mangle: {
|
||||||
|
options = {
|
||||||
|
comparisons: true
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
function f(undefined) {
|
||||||
|
var n = 1;
|
||||||
|
return typeof n == "undefined";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "function f(n){var r=1;return void 0===r}"
|
||||||
|
}
|
||||||
46
test/compress/issue-1447.js
Normal file
46
test/compress/issue-1447.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
else_with_empty_block: {
|
||||||
|
options = {}
|
||||||
|
input: {
|
||||||
|
if (x)
|
||||||
|
yes();
|
||||||
|
else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "if(x)yes();"
|
||||||
|
}
|
||||||
|
|
||||||
|
else_with_empty_statement: {
|
||||||
|
options = {}
|
||||||
|
input: {
|
||||||
|
if (x)
|
||||||
|
yes();
|
||||||
|
else
|
||||||
|
;
|
||||||
|
}
|
||||||
|
expect_exact: "if(x)yes();"
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_false_stray_else_in_loop: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
comparisons : true,
|
||||||
|
booleans : true,
|
||||||
|
unused : true,
|
||||||
|
loops : true,
|
||||||
|
side_effects : true,
|
||||||
|
dead_code : true,
|
||||||
|
hoist_vars : true,
|
||||||
|
join_vars : true,
|
||||||
|
if_return : true,
|
||||||
|
cascade : true,
|
||||||
|
conditionals : false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var i = 1; i <= 4; ++i) {
|
||||||
|
if (i <= 2) continue;
|
||||||
|
console.log(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "for(var i=1;i<=4;++i)if(!(i<=2))console.log(i);"
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
19
test/compress/issue-1569.js
Normal file
19
test/compress/issue-1569.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
inner_reference: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
!function f(a) {
|
||||||
|
return a && f(a - 1) + a;
|
||||||
|
}(42);
|
||||||
|
!function g(a) {
|
||||||
|
return a;
|
||||||
|
}(42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function f(a) {
|
||||||
|
return a && f(a - 1) + a;
|
||||||
|
}(42);
|
||||||
|
!void 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
87
test/compress/issue-1588.js
Normal file
87
test/compress/issue-1588.js
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
screw_ie8: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try { throw "foo"; } catch (x) { console.log(x); }
|
||||||
|
}
|
||||||
|
expect_exact: 'try{throw"foo"}catch(o){console.log(o)}'
|
||||||
|
expect_stdout: [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
support_ie8: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try { throw "foo"; } catch (x) { console.log(x); }
|
||||||
|
}
|
||||||
|
expect_exact: 'try{throw"foo"}catch(x){console.log(x)}'
|
||||||
|
expect_stdout: "foo"
|
||||||
|
}
|
||||||
|
|
||||||
|
safe_undefined: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
unsafe: false,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var a, c;
|
||||||
|
console.log(function(undefined) {
|
||||||
|
return function() {
|
||||||
|
if (a)
|
||||||
|
return b;
|
||||||
|
if (c)
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
}(1)());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, c;
|
||||||
|
console.log(function(n) {
|
||||||
|
return function() {
|
||||||
|
return a ? b : c ? d : void 0;
|
||||||
|
};
|
||||||
|
}(1)());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_undefined: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var a, c;
|
||||||
|
console.log(function(undefined) {
|
||||||
|
return function() {
|
||||||
|
if (a)
|
||||||
|
return b;
|
||||||
|
if (c)
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
}()());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, c;
|
||||||
|
console.log(function(n) {
|
||||||
|
return function() {
|
||||||
|
return a ? b : c ? d : n;
|
||||||
|
};
|
||||||
|
}()());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
52
test/compress/issue-1609.js
Normal file
52
test/compress/issue-1609.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
chained_evaluation_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a = 1;
|
||||||
|
(function() {
|
||||||
|
var b = a, c;
|
||||||
|
c = f(b);
|
||||||
|
c.bar = b;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
f(1).bar = 1;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chained_evaluation_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a = "long piece of string";
|
||||||
|
(function() {
|
||||||
|
var b = a, c;
|
||||||
|
c = f(b);
|
||||||
|
c.bar = b;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
var b = "long piece of string";
|
||||||
|
f(b).bar = b;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
88
test/compress/issue-1639.js
Normal file
88
test/compress/issue-1639.js
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
|
||||||
|
issue_1639_1: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
cascade: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
loops: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
|
||||||
|
var L1 = 5;
|
||||||
|
while (--L1 > 0) {
|
||||||
|
if ((--b), false) {
|
||||||
|
if (b) {
|
||||||
|
var ignore = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
|
||||||
|
if (--b, !1) var ignore = 0;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1639_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
cascade: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
|
||||||
|
function f19() {
|
||||||
|
if (++a, false)
|
||||||
|
if (a)
|
||||||
|
if (++a);
|
||||||
|
}
|
||||||
|
f19();
|
||||||
|
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
function f19() {
|
||||||
|
++a, 1;
|
||||||
|
}
|
||||||
|
f19(),
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1639_3: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
cascade: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
a++ && false && a ? 0 : 0;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
a++,
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
45
test/compress/issue-1656.js
Normal file
45
test/compress/issue-1656.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
f7: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
cascade: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
comparisons: true,
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
drop_debugger: true,
|
||||||
|
evaluate: true,
|
||||||
|
hoist_funs: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
loops: true,
|
||||||
|
negate_iife: true,
|
||||||
|
passes: 3,
|
||||||
|
properties: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
function f22464() {
|
||||||
|
var brake146670 = 5;
|
||||||
|
while (((b = a) ? !a : ~a ? null : b += a) && --brake146670 > 0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f22464();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
"var b = 10;",
|
||||||
|
"",
|
||||||
|
"!function() {",
|
||||||
|
" for (;b = 100, !1; ) ;",
|
||||||
|
"}(), console.log(100, b);",
|
||||||
|
]
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
161
test/compress/issue-1673.js
Normal file
161
test/compress/issue-1673.js
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
side_effects_catch: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
side_effects_else: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x) {
|
||||||
|
function g() {
|
||||||
|
if (x);
|
||||||
|
else console.log("PASS");
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(x) {
|
||||||
|
(function() {
|
||||||
|
if (x);
|
||||||
|
else console.log("PASS");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
side_effects_finally: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (e) {
|
||||||
|
} finally {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (e) {
|
||||||
|
} finally {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
side_effects_label: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x) {
|
||||||
|
function g() {
|
||||||
|
L: {
|
||||||
|
console.log("PASS");
|
||||||
|
break L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(x) {
|
||||||
|
(function() {
|
||||||
|
L: {
|
||||||
|
console.log("PASS");
|
||||||
|
break L;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
f(0);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
side_effects_switch: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
case console.log("PASS"):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
(function() {
|
||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
case console.log("PASS"):
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
347
test/compress/issue-1704.js
Normal file
347
test/compress/issue-1704.js
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
mangle_catch: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (args) {
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="FAIL";try{throw 1}catch(o){a="PASS"}console.log(a);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_ie8: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (args) {
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="FAIL";try{throw 1}catch(args){a="PASS"}console.log(a);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_var: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (args) {
|
||||||
|
var a = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="FAIL";try{throw 1}catch(o){var a="PASS"}console.log(a);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_var_ie8: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (args) {
|
||||||
|
var a = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="FAIL";try{throw 1}catch(args){var a="PASS"}console.log(a);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_toplevel: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (args) {
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var o="FAIL";try{throw 1}catch(c){o="PASS"}console.log(o);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_ie8_toplevel: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (args) {
|
||||||
|
a = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var o="FAIL";try{throw 1}catch(c){o="PASS"}console.log(o);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_var_toplevel: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (args) {
|
||||||
|
var a = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var o="FAIL";try{throw 1}catch(r){var o="PASS"}console.log(o);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_var_ie8_toplevel: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (args) {
|
||||||
|
var a = "PASS";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var o="FAIL";try{throw 1}catch(r){var o="PASS"}console.log(o);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_redef_1: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
try {
|
||||||
|
throw "FAIL1";
|
||||||
|
} catch (a) {
|
||||||
|
var a = "FAIL2";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="PASS";try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_redef_1_ie8: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
try {
|
||||||
|
throw "FAIL1";
|
||||||
|
} catch (a) {
|
||||||
|
var a = "FAIL2";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var a="PASS";try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_redef_1_toplevel: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
try {
|
||||||
|
throw "FAIL1";
|
||||||
|
} catch (a) {
|
||||||
|
var a = "FAIL2";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var o="PASS";try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_redef_1_ie8_toplevel: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
try {
|
||||||
|
throw "FAIL1";
|
||||||
|
} catch (a) {
|
||||||
|
var a = "FAIL2";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'var o="PASS";try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_redef_2: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
throw "FAIL1";
|
||||||
|
} catch (a) {
|
||||||
|
var a = "FAIL2";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_redef_2_ie8: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
throw "FAIL1";
|
||||||
|
} catch (a) {
|
||||||
|
var a = "FAIL2";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_redef_2_toplevel: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
throw "FAIL1";
|
||||||
|
} catch (a) {
|
||||||
|
var a = "FAIL2";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_catch_redef_2_ie8_toplevel: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try {
|
||||||
|
throw "FAIL1";
|
||||||
|
} catch (a) {
|
||||||
|
var a = "FAIL2";
|
||||||
|
}
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
97
test/compress/issue-1733.js
Normal file
97
test/compress/issue-1733.js
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
function_iife_catch: {
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(n) {
|
||||||
|
!function() {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (n) {
|
||||||
|
var a = 1;
|
||||||
|
console.log(n, a);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_exact: "function f(o){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();"
|
||||||
|
expect_stdout: "0 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
function_iife_catch_ie8: {
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(n) {
|
||||||
|
!function() {
|
||||||
|
try {
|
||||||
|
throw 0;
|
||||||
|
} catch (n) {
|
||||||
|
var a = 1;
|
||||||
|
console.log(n, a);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_exact: "function f(o){!function(){try{throw 0}catch(o){var c=1;console.log(o,c)}}()}f();"
|
||||||
|
expect_stdout: "0 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
function_catch_catch: {
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = 0;
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (c) {
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (o) {
|
||||||
|
var o = 3;
|
||||||
|
console.log(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(o);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_exact: "var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();"
|
||||||
|
expect_stdout: [
|
||||||
|
"3",
|
||||||
|
"undefined",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
function_catch_catch_ie8: {
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = 0;
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
throw 1;
|
||||||
|
} catch (c) {
|
||||||
|
try {
|
||||||
|
throw 2;
|
||||||
|
} catch (o) {
|
||||||
|
var o = 3;
|
||||||
|
console.log(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(o);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_exact: "var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();"
|
||||||
|
expect_stdout: [
|
||||||
|
"3",
|
||||||
|
"undefined",
|
||||||
|
]
|
||||||
|
}
|
||||||
54
test/compress/issue-1750.js
Normal file
54
test/compress/issue-1750.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
case_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b = 1;
|
||||||
|
switch (true) {
|
||||||
|
case a, true:
|
||||||
|
default:
|
||||||
|
b = 2;
|
||||||
|
case true:
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0, b = 1;
|
||||||
|
switch (true) {
|
||||||
|
case a, true:
|
||||||
|
b = 2;
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "0 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
case_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0, b = 1;
|
||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
b = 2;
|
||||||
|
case a:
|
||||||
|
a = 3;
|
||||||
|
case 0:
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0, b = 1;
|
||||||
|
switch (0) {
|
||||||
|
case a:
|
||||||
|
a = 3;
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "3 1"
|
||||||
|
}
|
||||||
239
test/compress/issue-1770.js
Normal file
239
test/compress/issue-1770.js
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
mangle_props: {
|
||||||
|
mangle_props = {}
|
||||||
|
input: {
|
||||||
|
var obj = {
|
||||||
|
undefined: 1,
|
||||||
|
NaN: 2,
|
||||||
|
Infinity: 3,
|
||||||
|
"-Infinity": 4,
|
||||||
|
null: 5,
|
||||||
|
};
|
||||||
|
console.log(
|
||||||
|
obj[void 0],
|
||||||
|
obj[undefined],
|
||||||
|
obj["undefined"],
|
||||||
|
obj[0/0],
|
||||||
|
obj[NaN],
|
||||||
|
obj["NaN"],
|
||||||
|
obj[1/0],
|
||||||
|
obj[Infinity],
|
||||||
|
obj["Infinity"],
|
||||||
|
obj[-1/0],
|
||||||
|
obj[-Infinity],
|
||||||
|
obj["-Infinity"],
|
||||||
|
obj[null],
|
||||||
|
obj["null"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var obj = {
|
||||||
|
undefined: 1,
|
||||||
|
NaN: 2,
|
||||||
|
Infinity: 3,
|
||||||
|
"-Infinity": 4,
|
||||||
|
null: 5,
|
||||||
|
};
|
||||||
|
console.log(
|
||||||
|
obj[void 0],
|
||||||
|
obj[void 0],
|
||||||
|
obj["undefined"],
|
||||||
|
obj[0/0],
|
||||||
|
obj[NaN],
|
||||||
|
obj["NaN"],
|
||||||
|
obj[1/0],
|
||||||
|
obj[1/0],
|
||||||
|
obj["Infinity"],
|
||||||
|
obj[-1/0],
|
||||||
|
obj[-1/0],
|
||||||
|
obj["-Infinity"],
|
||||||
|
obj[null],
|
||||||
|
obj["null"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 1 1 2 2 2 3 3 3 4 4 4 5 5"
|
||||||
|
}
|
||||||
|
|
||||||
|
numeric_literal: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
|
mangle_props = {}
|
||||||
|
input: {
|
||||||
|
var obj = {
|
||||||
|
0: 0,
|
||||||
|
"-0": 1,
|
||||||
|
42: 2,
|
||||||
|
"42": 3,
|
||||||
|
0x25: 4,
|
||||||
|
"0x25": 5,
|
||||||
|
1E42: 6,
|
||||||
|
"1E42": 7,
|
||||||
|
"1e+42": 8,
|
||||||
|
};
|
||||||
|
console.log(obj[-0], obj[-""], obj["-0"]);
|
||||||
|
console.log(obj[42], obj["42"]);
|
||||||
|
console.log(obj[0x25], obj["0x25"], obj[37], obj["37"]);
|
||||||
|
console.log(obj[1E42], obj["1E42"], obj["1e+42"]);
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
'var obj = {',
|
||||||
|
' 0: 0,',
|
||||||
|
' "-0": 1,',
|
||||||
|
' 42: 2,',
|
||||||
|
' "42": 3,',
|
||||||
|
' 37: 4,',
|
||||||
|
' a: 5,',
|
||||||
|
' 1e42: 6,',
|
||||||
|
' b: 7,',
|
||||||
|
' "1e+42": 8',
|
||||||
|
'};',
|
||||||
|
'',
|
||||||
|
'console.log(obj[-0], obj[-""], obj["-0"]);',
|
||||||
|
'',
|
||||||
|
'console.log(obj[42], obj["42"]);',
|
||||||
|
'',
|
||||||
|
'console.log(obj[37], obj["a"], obj[37], obj["37"]);',
|
||||||
|
'',
|
||||||
|
'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
|
||||||
|
]
|
||||||
|
expect_stdout: [
|
||||||
|
"0 0 1",
|
||||||
|
"3 3",
|
||||||
|
"4 5 4 4",
|
||||||
|
"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 = {
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
c: 3,
|
||||||
|
d: 4,
|
||||||
|
e: 5,
|
||||||
|
f: 6,
|
||||||
|
g: 7,
|
||||||
|
h: 8,
|
||||||
|
i: 9,
|
||||||
|
j: 10,
|
||||||
|
k: 11,
|
||||||
|
l: 12,
|
||||||
|
m: 13,
|
||||||
|
n: 14,
|
||||||
|
o: 15,
|
||||||
|
p: 16,
|
||||||
|
q: 17,
|
||||||
|
r: 18,
|
||||||
|
s: 19,
|
||||||
|
t: 20,
|
||||||
|
u: 21,
|
||||||
|
v: 22,
|
||||||
|
w: 23,
|
||||||
|
x: 24,
|
||||||
|
y: 25,
|
||||||
|
z: 26,
|
||||||
|
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,
|
||||||
|
aa: 57,
|
||||||
|
ba: 58,
|
||||||
|
ca: 59,
|
||||||
|
da: 60,
|
||||||
|
ea: 61,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
15
test/compress/issue-1787.js
Normal file
15
test/compress/issue-1787.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
unary_prefix: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var x = -(2 / 3);
|
||||||
|
return x;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_exact: "console.log(-2/3);"
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
134
test/compress/issue-1833.js
Normal file
134
test/compress/issue-1833.js
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
iife_for: {
|
||||||
|
options = {
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
L: for (;;) break L;
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
!function() {
|
||||||
|
L: for (;;) break L;
|
||||||
|
}();
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iife_for_in: {
|
||||||
|
options = {
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
L: for (var a in x) break L;
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
!function() {
|
||||||
|
L: for (var a in x) break L;
|
||||||
|
}();
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iife_do: {
|
||||||
|
options = {
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
L: do {
|
||||||
|
break L;
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
!function() {
|
||||||
|
L: do {
|
||||||
|
break L;
|
||||||
|
} while (1);
|
||||||
|
}();
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iife_while: {
|
||||||
|
options = {
|
||||||
|
negate_iife: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
L: while (1) break L;
|
||||||
|
}
|
||||||
|
g();
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function() {
|
||||||
|
!function() {
|
||||||
|
L: while (1) break L;
|
||||||
|
}();
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label_do: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L: do {
|
||||||
|
continue L;
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
L: do {
|
||||||
|
continue L;
|
||||||
|
} while (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label_while: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
L: while (0) continue L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "function f(){L:;}"
|
||||||
|
}
|
||||||
@@ -1,11 +1,70 @@
|
|||||||
do_not_update_lhs: {
|
do_not_update_lhs: {
|
||||||
options = { global_defs: { DEBUG: false } };
|
options = {
|
||||||
input: { DEBUG = false; }
|
global_defs: { DEBUG: 0 }
|
||||||
expect: { DEBUG = false; }
|
}
|
||||||
|
input: {
|
||||||
|
DEBUG++;
|
||||||
|
DEBUG += 1;
|
||||||
|
DEBUG = 1;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
DEBUG++;
|
||||||
|
DEBUG += 1;
|
||||||
|
DEBUG = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_update_rhs: {
|
do_update_rhs: {
|
||||||
options = { global_defs: { DEBUG: false } };
|
options = {
|
||||||
input: { MY_DEBUG = DEBUG; }
|
global_defs: { DEBUG: 0 }
|
||||||
expect: { MY_DEBUG = false; }
|
}
|
||||||
|
input: {
|
||||||
|
MY_DEBUG = DEBUG;
|
||||||
|
MY_DEBUG += DEBUG;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
MY_DEBUG = 0;
|
||||||
|
MY_DEBUG += 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mixed: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
global_defs: {
|
||||||
|
DEBUG: 0,
|
||||||
|
ENV: 1,
|
||||||
|
FOO: 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var ENV = 3;
|
||||||
|
var FOO = 4;
|
||||||
|
f(ENV * 10);
|
||||||
|
--FOO;
|
||||||
|
DEBUG = 1;
|
||||||
|
DEBUG++;
|
||||||
|
DEBUG += 1;
|
||||||
|
f(DEBUG);
|
||||||
|
x = DEBUG;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var ENV = 3;
|
||||||
|
var FOO = 4;
|
||||||
|
f(10);
|
||||||
|
--FOO;
|
||||||
|
DEBUG = 1;
|
||||||
|
DEBUG++;
|
||||||
|
DEBUG += 1;
|
||||||
|
f(0);
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
expect_warnings: [
|
||||||
|
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,12]',
|
||||||
|
'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]',
|
||||||
|
'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]',
|
||||||
|
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]',
|
||||||
|
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:46,8]',
|
||||||
|
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:47,8]',
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
55
test/compress/issue-368.js
Normal file
55
test/compress/issue-368.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
collapse: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f1() {
|
||||||
|
var a;
|
||||||
|
a = typeof b === 'function' ? b() : b;
|
||||||
|
return a !== undefined && c();
|
||||||
|
}
|
||||||
|
function f2(b) {
|
||||||
|
var a;
|
||||||
|
b = c();
|
||||||
|
a = typeof b === 'function' ? b() : b;
|
||||||
|
return 'stirng' == typeof a && d();
|
||||||
|
}
|
||||||
|
function f3(c) {
|
||||||
|
var a;
|
||||||
|
a = b(a / 2);
|
||||||
|
if (a < 0) {
|
||||||
|
a++;
|
||||||
|
++c;
|
||||||
|
return c / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function f4(c) {
|
||||||
|
var a;
|
||||||
|
a = b(a / 2);
|
||||||
|
if (a < 0) {
|
||||||
|
a++;
|
||||||
|
c++;
|
||||||
|
return c / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1() {
|
||||||
|
return void 0 !== ('function' === typeof b ? b() : b) && c();
|
||||||
|
}
|
||||||
|
function f2(b) {
|
||||||
|
return b = c(), 'stirng' == typeof ('function' === typeof b ? b() : b) && d();
|
||||||
|
}
|
||||||
|
function f3(c) {
|
||||||
|
var a;
|
||||||
|
if ((a = b(a / 2)) < 0) return a++, ++c / 2;
|
||||||
|
}
|
||||||
|
function f4(c) {
|
||||||
|
var a;
|
||||||
|
if ((a = b(a / 2)) < 0) return a++, ++c / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ NaN_and_Infinity_must_have_parens: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
(1/0).toString();
|
(1/0).toString();
|
||||||
NaN.toString(); // transformation to 0/0 dropped
|
NaN.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,3 +23,135 @@ NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: {
|
|||||||
NaN.toString();
|
NaN.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NaN_and_Infinity_must_have_parens_evaluate: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(123456789 / 0).toString();
|
||||||
|
(+"foo").toString();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(1/0).toString();
|
||||||
|
NaN.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined_evaluate: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var Infinity, NaN;
|
||||||
|
(123456789 / 0).toString();
|
||||||
|
(+"foo").toString();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var Infinity, NaN;
|
||||||
|
(1/0).toString();
|
||||||
|
(0/0).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beautify_off_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
beautify: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var NaN;
|
||||||
|
console.log(
|
||||||
|
null,
|
||||||
|
undefined,
|
||||||
|
Infinity,
|
||||||
|
NaN,
|
||||||
|
Infinity * undefined,
|
||||||
|
Infinity.toString(),
|
||||||
|
NaN.toString(),
|
||||||
|
(Infinity * undefined).toString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_exact: "var NaN;console.log(null,void 0,1/0,NaN,0/0,(1/0).toString(),NaN.toString(),(0/0).toString());"
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
beautify_off_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
beautify: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
null.toString(),
|
||||||
|
undefined.toString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_exact: "console.log(null.toString(),(void 0).toString());"
|
||||||
|
}
|
||||||
|
|
||||||
|
beautify_on_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var NaN;
|
||||||
|
console.log(
|
||||||
|
null,
|
||||||
|
undefined,
|
||||||
|
Infinity,
|
||||||
|
NaN,
|
||||||
|
Infinity * undefined,
|
||||||
|
Infinity.toString(),
|
||||||
|
NaN.toString(),
|
||||||
|
(Infinity * undefined).toString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
"var NaN;",
|
||||||
|
"",
|
||||||
|
"console.log(null, void 0, 1 / 0, NaN, 0 / 0, (1 / 0).toString(), NaN.toString(), (0 / 0).toString());",
|
||||||
|
]
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
beautify_on_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
null.toString(),
|
||||||
|
undefined.toString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_exact: "console.log(null.toString(), (void 0).toString());"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1724: {
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
++a % Infinity | Infinity ? a++ : 0;
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_exact: "var a=0;++a%(1/0)|1/0?a++:0;console.log(a);"
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1725: {
|
||||||
|
input: {
|
||||||
|
([].length === 0) % Infinity ? console.log("PASS") : console.log("FAIL");
|
||||||
|
}
|
||||||
|
expect_exact: '(0===[].length)%(1/0)?console.log("PASS"):console.log("FAIL");'
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
320
test/compress/issue-640.js
Normal file
320
test/compress/issue-640.js
Normal file
@@ -0,0 +1,320 @@
|
|||||||
|
cond_5: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
expression: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if (some_condition()) {
|
||||||
|
if (some_other_condition()) {
|
||||||
|
do_something();
|
||||||
|
} else {
|
||||||
|
alternate();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alternate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (some_condition()) {
|
||||||
|
if (some_other_condition()) {
|
||||||
|
do_something();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
some_condition() && some_other_condition() ? do_something() : alternate();
|
||||||
|
if (some_condition() && some_other_condition()) do_something();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dead_code_const_annotation_regex: {
|
||||||
|
options = {
|
||||||
|
booleans : true,
|
||||||
|
conditionals : true,
|
||||||
|
dead_code : true,
|
||||||
|
evaluate : true,
|
||||||
|
expression : true,
|
||||||
|
loops : 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;
|
||||||
|
if (CONST_FOO_ANN) console.log('reachable');
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_console_2: {
|
||||||
|
options = {
|
||||||
|
drop_console: true,
|
||||||
|
expression: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log('foo');
|
||||||
|
console.log.apply(console, arguments);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
// with regular compression these will be stripped out as well
|
||||||
|
void 0;
|
||||||
|
void 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_value: {
|
||||||
|
options = {
|
||||||
|
expression: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(1, [2, foo()], 3, {a:1, b:bar()});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo(), {a:1, b:bar()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wrongly_optimized: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
expression: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function func() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
if (func() || true) {
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function func() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
// TODO: optimize to `func(), bar()`
|
||||||
|
if (func(), !0) bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_1: {
|
||||||
|
options = {
|
||||||
|
expression: true,
|
||||||
|
negate_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ stuff() })();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(){ stuff() })();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_3: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
expression: true,
|
||||||
|
negate_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_3_off: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
expression: true,
|
||||||
|
negate_iife: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_4: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
expression: true,
|
||||||
|
negate_iife: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
(function(){
|
||||||
|
console.log("something");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(){ return t }() ? console.log(false) : console.log(true), function(){
|
||||||
|
console.log("something");
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_5: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
expression: true,
|
||||||
|
negate_iife: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if ((function(){ return t })()) {
|
||||||
|
foo(true);
|
||||||
|
} else {
|
||||||
|
bar(false);
|
||||||
|
}
|
||||||
|
(function(){
|
||||||
|
console.log("something");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(){ return t }() ? bar(false) : foo(true), function(){
|
||||||
|
console.log("something");
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_5_off: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
expression: true,
|
||||||
|
negate_iife: false,
|
||||||
|
sequences: true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
if ((function(){ return t })()) {
|
||||||
|
foo(true);
|
||||||
|
} else {
|
||||||
|
bar(false);
|
||||||
|
}
|
||||||
|
(function(){
|
||||||
|
console.log("something");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(){ return t }() ? bar(false) : foo(true), function(){
|
||||||
|
console.log("something");
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1254_negate_iife_true: {
|
||||||
|
options = {
|
||||||
|
expression: true,
|
||||||
|
negate_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return function() {
|
||||||
|
console.log('test')
|
||||||
|
};
|
||||||
|
})()();
|
||||||
|
}
|
||||||
|
expect_exact: '(function(){return function(){console.log("test")}})()();'
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1254_negate_iife_nested: {
|
||||||
|
options = {
|
||||||
|
expression: true,
|
||||||
|
negate_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return function() {
|
||||||
|
console.log('test')
|
||||||
|
};
|
||||||
|
})()()()()();
|
||||||
|
}
|
||||||
|
expect_exact: '(function(){return function(){console.log("test")}})()()()()();'
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional: {
|
||||||
|
options = {
|
||||||
|
expression: true,
|
||||||
|
pure_funcs: [ "pure" ],
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
pure(1 | a() ? 2 & b() : 7 ^ c());
|
||||||
|
pure(1 | a() ? 2 & b() : 5);
|
||||||
|
pure(1 | a() ? 4 : 7 ^ c());
|
||||||
|
pure(1 | a() ? 4 : 5);
|
||||||
|
pure(3 ? 2 & b() : 7 ^ c());
|
||||||
|
pure(3 ? 2 & b() : 5);
|
||||||
|
pure(3 ? 4 : 7 ^ c());
|
||||||
|
pure(3 ? 4 : 5);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
1 | a() ? b() : c();
|
||||||
|
1 | a() && b();
|
||||||
|
1 | a() || c();
|
||||||
|
a();
|
||||||
|
3 ? b() : c();
|
||||||
|
3 && b();
|
||||||
|
3 || c();
|
||||||
|
pure(3 ? 4 : 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
limit_1: {
|
||||||
|
options = {
|
||||||
|
expression: true,
|
||||||
|
sequences: 3,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a;
|
||||||
|
b;
|
||||||
|
c;
|
||||||
|
d;
|
||||||
|
e;
|
||||||
|
f;
|
||||||
|
g;
|
||||||
|
h;
|
||||||
|
i;
|
||||||
|
j;
|
||||||
|
k;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
// Turned into a single return statement
|
||||||
|
// so it can no longer be split into lines
|
||||||
|
a,b,c,d,e,f,g,h,i,j,k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iife: {
|
||||||
|
options = {
|
||||||
|
expression: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
x = 42;
|
||||||
|
(function a() {})();
|
||||||
|
!function b() {}();
|
||||||
|
~function c() {}();
|
||||||
|
+function d() {}();
|
||||||
|
-function e() {}();
|
||||||
|
void function f() {}();
|
||||||
|
typeof function g() {}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
x = 42, function a() {}(), function b() {}(), function c() {}(),
|
||||||
|
function d() {}(), function e() {}(), function f() {}(), typeof function g() {}();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,4 +29,5 @@ dont_mangle_arguments: {
|
|||||||
})(5,6,7);
|
})(5,6,7);
|
||||||
}
|
}
|
||||||
expect_exact: "(function(){var arguments=arguments,o=9;console.log(o,arguments)})(5,6,7);"
|
expect_exact: "(function(){var arguments=arguments,o=9;console.log(o,arguments)})(5,6,7);"
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ this_binding_conditionals: {
|
|||||||
this_binding_collapse_vars: {
|
this_binding_collapse_vars: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var c = a; c();
|
var c = a; c();
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ eval_collapse_vars: {
|
|||||||
eval("console.log(a);");
|
eval("console.log(a);");
|
||||||
})(eval);
|
})(eval);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
eval_unused: {
|
eval_unused: {
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ issue979_test_negated_is_best: {
|
|||||||
1!=a||2!=b||foo();
|
1!=a||2!=b||foo();
|
||||||
}
|
}
|
||||||
function f7() {
|
function f7() {
|
||||||
return 1!=a&&2!=b?bar():void foo();
|
if(1!=a&&2!=b)return bar();foo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ labels_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
foo || console.log("bar");
|
foo || console.log("bar");
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
labels_2: {
|
labels_2: {
|
||||||
@@ -40,6 +41,7 @@ labels_3: {
|
|||||||
for (var i = 0; i < 5; ++i)
|
for (var i = 0; i < 5; ++i)
|
||||||
i < 3 || console.log(i);
|
i < 3 || console.log(i);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
labels_4: {
|
labels_4: {
|
||||||
@@ -54,6 +56,7 @@ labels_4: {
|
|||||||
for (var i = 0; i < 5; ++i)
|
for (var i = 0; i < 5; ++i)
|
||||||
i < 3 || console.log(i);
|
i < 3 || console.log(i);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
labels_5: {
|
labels_5: {
|
||||||
|
|||||||
@@ -146,44 +146,293 @@ parse_do_while_without_semicolon: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
evaluate: {
|
||||||
keep_collapse_const_in_own_block_scope: {
|
|
||||||
options = {
|
options = {
|
||||||
join_vars: true,
|
loops: true,
|
||||||
loops: true
|
dead_code: true,
|
||||||
}
|
evaluate: true,
|
||||||
|
};
|
||||||
input: {
|
input: {
|
||||||
var i=2;
|
while (true) {
|
||||||
const c=5;
|
a();
|
||||||
while(i--)
|
}
|
||||||
console.log(i);
|
while (false) {
|
||||||
console.log(c);
|
b();
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
c();
|
||||||
|
} while (true);
|
||||||
|
do {
|
||||||
|
d();
|
||||||
|
} while (false);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var i=2;
|
for(;;)
|
||||||
const c=5;
|
a();
|
||||||
for(;i--;)
|
for(;;)
|
||||||
console.log(i);
|
c();
|
||||||
console.log(c);
|
d();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keep_collapse_const_in_own_block_scope_2: {
|
issue_1532: {
|
||||||
options = {
|
options = {
|
||||||
join_vars: true,
|
evaluate: true,
|
||||||
loops: true
|
loops: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
const c=5;
|
function f(x, y) {
|
||||||
var i=2; // Moves to loop, while it did not in previous test
|
do {
|
||||||
while(i--)
|
if (x) break;
|
||||||
console.log(i);
|
foo();
|
||||||
console.log(c);
|
} while (false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
const c=5;
|
function f(x, y) {
|
||||||
for(var i=2;i--;)
|
do {
|
||||||
console.log(i);
|
if (x) break;
|
||||||
console.log(c);
|
foo();
|
||||||
|
} while (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_186: {
|
||||||
|
beautify = {
|
||||||
|
beautify: false,
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = 3;
|
||||||
|
if (foo())
|
||||||
|
do
|
||||||
|
do
|
||||||
|
alert(x);
|
||||||
|
while (--x);
|
||||||
|
while (x);
|
||||||
|
else
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
expect_exact: 'var x=3;if(foo())do{do{alert(x)}while(--x)}while(x);else bar();'
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_186_ie8: {
|
||||||
|
beautify = {
|
||||||
|
beautify: false,
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = 3;
|
||||||
|
if (foo())
|
||||||
|
do
|
||||||
|
do
|
||||||
|
alert(x);
|
||||||
|
while (--x);
|
||||||
|
while (x);
|
||||||
|
else
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else bar();'
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_186_beautify: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = 3;
|
||||||
|
if (foo())
|
||||||
|
do
|
||||||
|
do
|
||||||
|
alert(x);
|
||||||
|
while (--x);
|
||||||
|
while (x);
|
||||||
|
else
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
'var x = 3;',
|
||||||
|
'',
|
||||||
|
'if (foo()) do {',
|
||||||
|
' do {',
|
||||||
|
' alert(x);',
|
||||||
|
' } while (--x);',
|
||||||
|
'} while (x); else bar();',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_186_beautify_ie8: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = 3;
|
||||||
|
if (foo())
|
||||||
|
do
|
||||||
|
do
|
||||||
|
alert(x);
|
||||||
|
while (--x);
|
||||||
|
while (x);
|
||||||
|
else
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
'var x = 3;',
|
||||||
|
'',
|
||||||
|
'if (foo()) {',
|
||||||
|
' do {',
|
||||||
|
' do {',
|
||||||
|
' alert(x);',
|
||||||
|
' } while (--x);',
|
||||||
|
' } while (x);',
|
||||||
|
'} else bar();',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_186_bracketize: {
|
||||||
|
beautify = {
|
||||||
|
beautify: false,
|
||||||
|
bracketize: true,
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = 3;
|
||||||
|
if (foo())
|
||||||
|
do
|
||||||
|
do
|
||||||
|
alert(x);
|
||||||
|
while (--x);
|
||||||
|
while (x);
|
||||||
|
else
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else{bar()}'
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_186_bracketize_ie8: {
|
||||||
|
beautify = {
|
||||||
|
beautify: false,
|
||||||
|
bracketize: true,
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = 3;
|
||||||
|
if (foo())
|
||||||
|
do
|
||||||
|
do
|
||||||
|
alert(x);
|
||||||
|
while (--x);
|
||||||
|
while (x);
|
||||||
|
else
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else{bar()}'
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_186_beautify_bracketize: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
bracketize: true,
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = 3;
|
||||||
|
if (foo())
|
||||||
|
do
|
||||||
|
do
|
||||||
|
alert(x);
|
||||||
|
while (--x);
|
||||||
|
while (x);
|
||||||
|
else
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
'var x = 3;',
|
||||||
|
'',
|
||||||
|
'if (foo()) {',
|
||||||
|
' do {',
|
||||||
|
' do {',
|
||||||
|
' alert(x);',
|
||||||
|
' } while (--x);',
|
||||||
|
' } while (x);',
|
||||||
|
'} else {',
|
||||||
|
' bar();',
|
||||||
|
'}',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_186_beautify_bracketize_ie8: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
bracketize: true,
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = 3;
|
||||||
|
if (foo())
|
||||||
|
do
|
||||||
|
do
|
||||||
|
alert(x);
|
||||||
|
while (--x);
|
||||||
|
while (x);
|
||||||
|
else
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
'var x = 3;',
|
||||||
|
'',
|
||||||
|
'if (foo()) {',
|
||||||
|
' do {',
|
||||||
|
' do {',
|
||||||
|
' alert(x);',
|
||||||
|
' } while (--x);',
|
||||||
|
' } while (x);',
|
||||||
|
'} else {',
|
||||||
|
' bar();',
|
||||||
|
'}',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1648: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
loops: true,
|
||||||
|
passes: 2,
|
||||||
|
sequences: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
x();
|
||||||
|
var b = 1;
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "function f(){for(x();1;);}"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_switch: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
do {
|
||||||
|
switch (a) {
|
||||||
|
case b:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} while (false);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
do {
|
||||||
|
switch (a) {
|
||||||
|
case b:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} while (false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
39
test/compress/max_line_len.js
Normal file
39
test/compress/max_line_len.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
too_short: {
|
||||||
|
beautify = {
|
||||||
|
max_line_len: 10,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
return { c: 42, d: a(), e: "foo"};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
'function f(a){',
|
||||||
|
'return{',
|
||||||
|
'c:42,',
|
||||||
|
'd:a(),',
|
||||||
|
'e:"foo"}}',
|
||||||
|
]
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Output exceeds 10 characters"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
just_enough: {
|
||||||
|
beautify = {
|
||||||
|
max_line_len: 14,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
return { c: 42, d: a(), e: "foo"};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
'function f(a){',
|
||||||
|
'return{c:42,',
|
||||||
|
'd:a(),e:"foo"}',
|
||||||
|
'}',
|
||||||
|
]
|
||||||
|
expect_warnings: [
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -10,56 +10,169 @@ negate_iife_1: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
negate_iife_1_off: {
|
||||||
|
options = {
|
||||||
|
negate_iife: false,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
(function(){ stuff() })();
|
||||||
|
}
|
||||||
|
expect_exact: '(function(){stuff()})();'
|
||||||
|
}
|
||||||
|
|
||||||
negate_iife_2: {
|
negate_iife_2: {
|
||||||
options = {
|
options = {
|
||||||
negate_iife: true
|
negate_iife: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
(function(){ return {} })().x = 10; // should not transform this one
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
(function(){ return {} })().x = 10;
|
(function(){ return {} })().x = 10;
|
||||||
}
|
}
|
||||||
|
expect_exact: "({}).x=10;"
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_2_side_effects: {
|
||||||
|
options = {
|
||||||
|
negate_iife: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return {} })().x = 10;
|
||||||
|
}
|
||||||
|
expect_exact: "({}).x=10;"
|
||||||
}
|
}
|
||||||
|
|
||||||
negate_iife_3: {
|
negate_iife_3: {
|
||||||
options = {
|
options = {
|
||||||
negate_iife: true,
|
negate_iife: true,
|
||||||
|
conditionals: true
|
||||||
};
|
};
|
||||||
|
input: {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(){ return t }() ? console.log(false) : console.log(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_3_evaluate: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
negate_iife: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(){ return true }() ? console.log(false) : console.log(true);
|
console.log(true);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_3_side_effects: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
negate_iife: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(){ return t }() ? console.log(false) : console.log(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
negate_iife_3: {
|
negate_iife_3_off: {
|
||||||
|
options = {
|
||||||
|
negate_iife: false,
|
||||||
|
conditionals: true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(){ return t }() ? console.log(false) : console.log(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_3_off_evaluate: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
negate_iife: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(true);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_4: {
|
||||||
options = {
|
options = {
|
||||||
negate_iife: true,
|
negate_iife: true,
|
||||||
|
conditionals: true,
|
||||||
sequences: true
|
sequences: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
(function(){
|
(function(){
|
||||||
console.log("something");
|
console.log("something");
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(){ return true }() ? console.log(false) : console.log(true), function(){
|
!function(){ return t }() ? console.log(false) : console.log(true), function(){
|
||||||
console.log("something");
|
console.log("something");
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
negate_iife_4: {
|
sequence_off: {
|
||||||
|
options = {
|
||||||
|
negate_iife: false,
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
passes: 2,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
(function(){
|
||||||
|
console.log("something");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
(function(){
|
||||||
|
console.log("something");
|
||||||
|
})();
|
||||||
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
!function(){ return t }() ? console.log(false) : console.log(true), function(){
|
||||||
|
console.log("something");
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
(function(){
|
||||||
|
console.log("something");
|
||||||
|
})(), function(){ return t }() ? console.log(true) : console.log(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_5: {
|
||||||
options = {
|
options = {
|
||||||
negate_iife: true,
|
negate_iife: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
if ((function(){ return true })()) {
|
if ((function(){ return t })()) {
|
||||||
foo(true);
|
foo(true);
|
||||||
} else {
|
} else {
|
||||||
bar(false);
|
bar(false);
|
||||||
@@ -69,7 +182,30 @@ negate_iife_4: {
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(){ return true }() ? bar(false) : foo(true), function(){
|
!function(){ return t }() ? bar(false) : foo(true), function(){
|
||||||
|
console.log("something");
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_5_off: {
|
||||||
|
options = {
|
||||||
|
negate_iife: false,
|
||||||
|
sequences: true,
|
||||||
|
conditionals: true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
if ((function(){ return t })()) {
|
||||||
|
foo(true);
|
||||||
|
} else {
|
||||||
|
bar(false);
|
||||||
|
}
|
||||||
|
(function(){
|
||||||
|
console.log("something");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!function(){ return t }() ? bar(false) : foo(true), function(){
|
||||||
console.log("something");
|
console.log("something");
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
@@ -105,6 +241,40 @@ negate_iife_nested: {
|
|||||||
}(7);
|
}(7);
|
||||||
}).f();
|
}).f();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_nested_off: {
|
||||||
|
options = {
|
||||||
|
negate_iife: false,
|
||||||
|
sequences: true,
|
||||||
|
conditionals: true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function Foo(f) {
|
||||||
|
this.f = f;
|
||||||
|
}
|
||||||
|
new Foo(function() {
|
||||||
|
(function(x) {
|
||||||
|
(function(y) {
|
||||||
|
console.log(y);
|
||||||
|
})(x);
|
||||||
|
})(7);
|
||||||
|
}).f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function Foo(f) {
|
||||||
|
this.f = f;
|
||||||
|
}
|
||||||
|
new Foo(function() {
|
||||||
|
(function(x) {
|
||||||
|
(function(y) {
|
||||||
|
console.log(y);
|
||||||
|
})(x);
|
||||||
|
})(7);
|
||||||
|
}).f();
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
negate_iife_issue_1073: {
|
negate_iife_issue_1073: {
|
||||||
@@ -129,6 +299,7 @@ negate_iife_issue_1073: {
|
|||||||
};
|
};
|
||||||
}(7))();
|
}(7))();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1254_negate_iife_false: {
|
issue_1254_negate_iife_false: {
|
||||||
@@ -143,6 +314,7 @@ issue_1254_negate_iife_false: {
|
|||||||
})()();
|
})()();
|
||||||
}
|
}
|
||||||
expect_exact: '(function(){return function(){console.log("test")}})()();'
|
expect_exact: '(function(){return function(){console.log("test")}})()();'
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1254_negate_iife_true: {
|
issue_1254_negate_iife_true: {
|
||||||
@@ -157,4 +329,86 @@ issue_1254_negate_iife_true: {
|
|||||||
})()();
|
})()();
|
||||||
}
|
}
|
||||||
expect_exact: '!function(){return function(){console.log("test")}}()();'
|
expect_exact: '!function(){return function(){console.log("test")}}()();'
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1254_negate_iife_nested: {
|
||||||
|
options = {
|
||||||
|
negate_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return function() {
|
||||||
|
console.log('test')
|
||||||
|
};
|
||||||
|
})()()()()();
|
||||||
|
}
|
||||||
|
expect_exact: '!function(){return function(){console.log("test")}}()()()()();'
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1288: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
negate_iife: true,
|
||||||
|
side_effects: false,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
if (w) ;
|
||||||
|
else {
|
||||||
|
(function f() {})();
|
||||||
|
}
|
||||||
|
if (!x) {
|
||||||
|
(function() {
|
||||||
|
x = {};
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
if (y)
|
||||||
|
(function() {})();
|
||||||
|
else
|
||||||
|
(function(z) {
|
||||||
|
return z;
|
||||||
|
})(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
w || !function f() {}();
|
||||||
|
x || !function() {
|
||||||
|
x = {};
|
||||||
|
}();
|
||||||
|
y ? !function() {}() : !function(z) {
|
||||||
|
return z;
|
||||||
|
}(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1288_side_effects: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
negate_iife: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if (w) ;
|
||||||
|
else {
|
||||||
|
(function f() {})();
|
||||||
|
}
|
||||||
|
if (!x) {
|
||||||
|
(function() {
|
||||||
|
x = {};
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
if (y)
|
||||||
|
(function() {})();
|
||||||
|
else
|
||||||
|
(function(z) {
|
||||||
|
return z;
|
||||||
|
})(0);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
w;
|
||||||
|
x || function() {
|
||||||
|
x = {};
|
||||||
|
}();
|
||||||
|
y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,3 +75,10 @@ call_with_unary_arguments: {
|
|||||||
}
|
}
|
||||||
expect_exact: "x();x(-1);x(-1,-2);x(void 1,+2,-3,~4,!5,--a,++b,c--,d++,typeof e,delete f);(-1)();(-1)(-2);"
|
expect_exact: "x();x(-1);x(-1,-2);x(void 1,+2,-3,~4,!5,--a,++b,c--,d++,typeof e,delete f);(-1)();(-1)(-2);"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_with_unary_prefix: {
|
||||||
|
input: {
|
||||||
|
var bar = (+new Date()).toString(32);
|
||||||
|
}
|
||||||
|
expect_exact: 'var bar=(+new Date).toString(32);';
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,3 +17,188 @@ hex_numbers_in_parentheses_for_prototype_functions: {
|
|||||||
}
|
}
|
||||||
expect_exact: "-2;(-2).toFixed(0);2;2..toFixed(0);.2;.2.toFixed(0);2e-8;2e-8.toFixed(0);0xde0b6b3a7640080;(0xde0b6b3a7640080).toFixed(0);"
|
expect_exact: "-2;(-2).toFixed(0);2;2..toFixed(0);.2;.2.toFixed(0);2e-8;2e-8.toFixed(0);0xde0b6b3a7640080;(0xde0b6b3a7640080).toFixed(0);"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
comparisons: {
|
||||||
|
options = {
|
||||||
|
comparisons: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
~x === 42,
|
||||||
|
x % n === 42
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
42 == ~x,
|
||||||
|
x % n == 42
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
x + 1 + 2,
|
||||||
|
x * 1 * 2,
|
||||||
|
+x + 1 + 2,
|
||||||
|
1 + x + 2 + 3,
|
||||||
|
1 | x | 2 | 3,
|
||||||
|
1 + x-- + 2 + 3,
|
||||||
|
1 + (x*y + 2) + 3,
|
||||||
|
1 + (2 + x + 3),
|
||||||
|
1 + (2 + ~x + 3),
|
||||||
|
-y + (2 + ~x + 3),
|
||||||
|
1 & (2 & x & 3),
|
||||||
|
1 + (2 + (x |= 0) + 3)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
x + 1 + 2,
|
||||||
|
1 * x * 2,
|
||||||
|
+x + 1 + 2,
|
||||||
|
1 + x + 2 + 3,
|
||||||
|
3 | x,
|
||||||
|
1 + x-- + 2 + 3,
|
||||||
|
x*y + 2 + 1 + 3,
|
||||||
|
1 + (2 + x + 3),
|
||||||
|
2 + ~x + 3 + 1,
|
||||||
|
-y + (2 + ~x + 3),
|
||||||
|
0 & x,
|
||||||
|
2 + (x |= 0) + 3 + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
x + 1 + 2,
|
||||||
|
x * 1 * 2,
|
||||||
|
+x + 1 + 2,
|
||||||
|
1 + x + 2 + 3,
|
||||||
|
1 | x | 2 | 3,
|
||||||
|
1 + x-- + 2 + 3,
|
||||||
|
1 + (x*y + 2) + 3,
|
||||||
|
1 + (2 + x + 3),
|
||||||
|
1 & (2 & x & 3),
|
||||||
|
1 + (2 + (x |= 0) + 3)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
x + 1 + 2,
|
||||||
|
2 * x,
|
||||||
|
3 + +x,
|
||||||
|
1 + x + 2 + 3,
|
||||||
|
3 | x,
|
||||||
|
6 + x--,
|
||||||
|
6 + x*y,
|
||||||
|
1 + (2 + x + 3),
|
||||||
|
0 & x,
|
||||||
|
6 + (x |= 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(1 + Number(x) + 2);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(3 + +x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_4: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
1+ +a,
|
||||||
|
+a+1,
|
||||||
|
1+-a,
|
||||||
|
-a+1,
|
||||||
|
+a+ +b,
|
||||||
|
+a+-b,
|
||||||
|
-a+ +b,
|
||||||
|
-a+-b
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
+a+1,
|
||||||
|
+a+1,
|
||||||
|
1-a,
|
||||||
|
1-a,
|
||||||
|
+a+ +b,
|
||||||
|
+a-b,
|
||||||
|
-a+ +b,
|
||||||
|
-a-b
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1710: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var x = {};
|
||||||
|
console.log((x += 1) + -x);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = {};
|
||||||
|
console.log((x += 1) + -x);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unary_binary_parenthesis: {
|
||||||
|
input: {
|
||||||
|
var v = [ 0, 1, NaN, Infinity, null, undefined, true, false, "", "foo", /foo/ ];
|
||||||
|
v.forEach(function(x) {
|
||||||
|
v.forEach(function(y) {
|
||||||
|
console.log(
|
||||||
|
+(x*y),
|
||||||
|
+(x/y),
|
||||||
|
+(x%y),
|
||||||
|
-(x*y),
|
||||||
|
-(x/y),
|
||||||
|
-(x%y)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var v = [ 0, 1, NaN, 1/0, null, void 0, true, false, "", "foo", /foo/ ];
|
||||||
|
v.forEach(function(x) {
|
||||||
|
v.forEach(function(y) {
|
||||||
|
console.log(
|
||||||
|
+x*y,
|
||||||
|
+x/y,
|
||||||
|
+x%y,
|
||||||
|
-x*y,
|
||||||
|
-x/y,
|
||||||
|
-x%y
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ keep_properties: {
|
|||||||
dot_properties: {
|
dot_properties: {
|
||||||
options = {
|
options = {
|
||||||
properties: true,
|
properties: true,
|
||||||
screw_ie8: false
|
ie8: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
a["foo"] = "bar";
|
a["foo"] = "bar";
|
||||||
@@ -36,7 +36,7 @@ dot_properties: {
|
|||||||
dot_properties_es5: {
|
dot_properties_es5: {
|
||||||
options = {
|
options = {
|
||||||
properties: true,
|
properties: true,
|
||||||
screw_ie8: true
|
ie8: false,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
a["foo"] = "bar";
|
a["foo"] = "bar";
|
||||||
@@ -54,7 +54,56 @@ dot_properties_es5: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluate_length: {
|
sub_properties: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
properties: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a[0] = 0;
|
||||||
|
a["0"] = 1;
|
||||||
|
a[3.14] = 2;
|
||||||
|
a["3" + ".14"] = 3;
|
||||||
|
a["i" + "f"] = 4;
|
||||||
|
a["foo" + " bar"] = 5;
|
||||||
|
a[0 / 0] = 6;
|
||||||
|
a[null] = 7;
|
||||||
|
a[undefined] = 8;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a[0] = 0;
|
||||||
|
a[0] = 1;
|
||||||
|
a[3.14] = 2;
|
||||||
|
a[3.14] = 3;
|
||||||
|
a.if = 4;
|
||||||
|
a["foo bar"] = 5;
|
||||||
|
a[NaN] = 6;
|
||||||
|
a[null] = 7;
|
||||||
|
a[void 0] = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_array_length: {
|
||||||
|
options = {
|
||||||
|
properties: true,
|
||||||
|
unsafe: true,
|
||||||
|
evaluate: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a = [1, 2, 3].length;
|
||||||
|
a = [1, 2, 3].join()["len" + "gth"];
|
||||||
|
a = [1, 2, b].length;
|
||||||
|
a = [1, 2, 3].join(b).length;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = 3;
|
||||||
|
a = 5;
|
||||||
|
a = [1, 2, b].length;
|
||||||
|
a = [1, 2, 3].join(b).length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_string_length: {
|
||||||
options = {
|
options = {
|
||||||
properties: true,
|
properties: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
@@ -76,7 +125,7 @@ evaluate_length: {
|
|||||||
|
|
||||||
mangle_properties: {
|
mangle_properties: {
|
||||||
mangle_props = {
|
mangle_props = {
|
||||||
ignore_quoted: false
|
keep_quoted: false
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
a["foo"] = "bar";
|
a["foo"] = "bar";
|
||||||
@@ -99,7 +148,7 @@ mangle_unquoted_properties: {
|
|||||||
properties: false
|
properties: false
|
||||||
}
|
}
|
||||||
mangle_props = {
|
mangle_props = {
|
||||||
ignore_quoted: true
|
keep_quoted: true
|
||||||
}
|
}
|
||||||
beautify = {
|
beautify = {
|
||||||
beautify: false,
|
beautify: false,
|
||||||
@@ -142,6 +191,98 @@ mangle_unquoted_properties: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mangle_debug: {
|
||||||
|
mangle_props = {
|
||||||
|
debug: ""
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a.foo = "bar";
|
||||||
|
x = { baz: "ban" };
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a._$foo$_ = "bar";
|
||||||
|
x = { _$baz$_: "ban" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_debug_true: {
|
||||||
|
mangle_props = {
|
||||||
|
debug: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a.foo = "bar";
|
||||||
|
x = { baz: "ban" };
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a._$foo$_ = "bar";
|
||||||
|
x = { _$baz$_: "ban" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_debug_suffix: {
|
||||||
|
mangle_props = {
|
||||||
|
debug: "XYZ"
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a.foo = "bar";
|
||||||
|
x = { baz: "ban" };
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a._$foo$XYZ_ = "bar";
|
||||||
|
x = { _$baz$XYZ_: "ban" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mangle_debug_suffix_keep_quoted: {
|
||||||
|
options = {
|
||||||
|
properties: false
|
||||||
|
}
|
||||||
|
mangle_props = {
|
||||||
|
keep_quoted: true,
|
||||||
|
debug: "XYZ",
|
||||||
|
reserved: []
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
beautify: false,
|
||||||
|
quote_style: 3,
|
||||||
|
keep_quoted_props: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a.top = 1;
|
||||||
|
function f1() {
|
||||||
|
a["foo"] = "bar";
|
||||||
|
a.color = "red";
|
||||||
|
a.stuff = 2;
|
||||||
|
x = {"bar": 10, size: 7};
|
||||||
|
a.size = 9;
|
||||||
|
}
|
||||||
|
function f2() {
|
||||||
|
a.foo = "bar";
|
||||||
|
a['color'] = "red";
|
||||||
|
x = {bar: 10, size: 7};
|
||||||
|
a.size = 9;
|
||||||
|
a.stuff = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a._$top$XYZ_ = 1;
|
||||||
|
function f1() {
|
||||||
|
a["foo"] = "bar";
|
||||||
|
a.color = "red";
|
||||||
|
a._$stuff$XYZ_ = 2;
|
||||||
|
x = {"bar": 10, _$size$XYZ_: 7};
|
||||||
|
a._$size$XYZ_ = 9;
|
||||||
|
}
|
||||||
|
function f2() {
|
||||||
|
a.foo = "bar";
|
||||||
|
a['color'] = "red";
|
||||||
|
x = {bar: 10, _$size$XYZ_: 7};
|
||||||
|
a._$size$XYZ_ = 9;
|
||||||
|
a._$stuff$XYZ_ = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
first_256_chars_as_properties: {
|
first_256_chars_as_properties: {
|
||||||
beautify = {
|
beautify = {
|
||||||
ascii_only: true,
|
ascii_only: true,
|
||||||
@@ -398,3 +539,19 @@ first_256_hex_chars_as_properties: {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
native_prototype: {
|
||||||
|
options = {
|
||||||
|
unsafe_proto: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
Array.prototype.splice.apply(a, [1, 2, b, c]);
|
||||||
|
Object.prototype.hasOwnProperty.call(d, "foo");
|
||||||
|
String.prototype.indexOf.call(e, "bar");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
[].splice.apply(a, [1, 2, b, c]);
|
||||||
|
({}).hasOwnProperty.call(d, "foo");
|
||||||
|
"".indexOf.call(e, "bar");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
295
test/compress/pure_funcs.js
Normal file
295
test/compress/pure_funcs.js
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
array: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "Math.floor" ],
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
function f(b) {
|
||||||
|
Math.floor(a / b);
|
||||||
|
Math.floor(c / b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
function f(b) {
|
||||||
|
c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: function(node) {
|
||||||
|
return !~node.args[0].print_to_string().indexOf("a");
|
||||||
|
},
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
Math.floor(a / b);
|
||||||
|
Math.floor(c / b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
Math.floor(c / b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
side_effects: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "console.log" ],
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
console.log(a());
|
||||||
|
console.log(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unused: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "pure" ],
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo() {
|
||||||
|
var u = pure(1);
|
||||||
|
var x = pure(2);
|
||||||
|
var y = pure(x);
|
||||||
|
var z = pure(pure(side_effects()));
|
||||||
|
return pure(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo() {
|
||||||
|
side_effects();
|
||||||
|
return pure(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
babel: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "_classCallCheck" ],
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function _classCallCheck(instance, Constructor) {
|
||||||
|
if (!(instance instanceof Constructor))
|
||||||
|
throw new TypeError("Cannot call a class as a function");
|
||||||
|
}
|
||||||
|
var Foo = function Foo() {
|
||||||
|
_classCallCheck(this, Foo);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function _classCallCheck(instance, Constructor) {
|
||||||
|
if (!(instance instanceof Constructor))
|
||||||
|
throw new TypeError("Cannot call a class as a function");
|
||||||
|
}
|
||||||
|
var Foo = function() {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "pure" ],
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
pure(1 | a() ? 2 & b() : 7 ^ c());
|
||||||
|
pure(1 | a() ? 2 & b() : 5);
|
||||||
|
pure(1 | a() ? 4 : 7 ^ c());
|
||||||
|
pure(1 | a() ? 4 : 5);
|
||||||
|
pure(3 ? 2 & b() : 7 ^ c());
|
||||||
|
pure(3 ? 2 & b() : 5);
|
||||||
|
pure(3 ? 4 : 7 ^ c());
|
||||||
|
pure(3 ? 4 : 5);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
1 | a() ? b() : c();
|
||||||
|
1 | a() && b();
|
||||||
|
1 | a() || c();
|
||||||
|
a();
|
||||||
|
3 ? b() : c();
|
||||||
|
3 && b();
|
||||||
|
3 || c();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
relational: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "foo" ],
|
||||||
|
side_effects :true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
foo() in foo();
|
||||||
|
foo() instanceof bar();
|
||||||
|
foo() < "bar";
|
||||||
|
bar() > foo();
|
||||||
|
bar() != bar();
|
||||||
|
bar() !== "bar";
|
||||||
|
"bar" == foo();
|
||||||
|
"bar" === bar();
|
||||||
|
"bar" >= "bar";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
bar();
|
||||||
|
bar();
|
||||||
|
bar(), bar();
|
||||||
|
bar();
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arithmetic: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "foo" ],
|
||||||
|
side_effects :true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
foo() + foo();
|
||||||
|
foo() - bar();
|
||||||
|
foo() * "bar";
|
||||||
|
bar() / foo();
|
||||||
|
bar() & bar();
|
||||||
|
bar() | "bar";
|
||||||
|
"bar" >> foo();
|
||||||
|
"bar" << bar();
|
||||||
|
"bar" >>> "bar";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
bar();
|
||||||
|
bar();
|
||||||
|
bar(), bar();
|
||||||
|
bar();
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean_and: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "foo" ],
|
||||||
|
side_effects :true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
foo() && foo();
|
||||||
|
foo() && bar();
|
||||||
|
foo() && "bar";
|
||||||
|
bar() && foo();
|
||||||
|
bar() && bar();
|
||||||
|
bar() && "bar";
|
||||||
|
"bar" && foo();
|
||||||
|
"bar" && bar();
|
||||||
|
"bar" && "bar";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo() && bar();
|
||||||
|
bar();
|
||||||
|
bar() && bar();
|
||||||
|
bar();
|
||||||
|
"bar" && bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean_or: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "foo" ],
|
||||||
|
side_effects :true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
foo() || foo();
|
||||||
|
foo() || bar();
|
||||||
|
foo() || "bar";
|
||||||
|
bar() || foo();
|
||||||
|
bar() || bar();
|
||||||
|
bar() || "bar";
|
||||||
|
"bar" || foo();
|
||||||
|
"bar" || bar();
|
||||||
|
"bar" || "bar";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo() || bar();
|
||||||
|
bar();
|
||||||
|
bar() || bar();
|
||||||
|
bar();
|
||||||
|
"bar" || bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assign: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "foo" ],
|
||||||
|
side_effects :true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
function f(b) {
|
||||||
|
a = foo();
|
||||||
|
b *= 4 + foo();
|
||||||
|
c >>= 0 | foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
function f(b) {
|
||||||
|
a = foo();
|
||||||
|
b *= 4 + foo();
|
||||||
|
c >>= 0 | foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unary: {
|
||||||
|
options = {
|
||||||
|
pure_funcs: [ "foo" ],
|
||||||
|
side_effects :true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
typeof foo();
|
||||||
|
typeof bar();
|
||||||
|
typeof "bar";
|
||||||
|
void foo();
|
||||||
|
void bar();
|
||||||
|
void "bar";
|
||||||
|
delete a[foo()];
|
||||||
|
delete a[bar()];
|
||||||
|
delete a["bar"];
|
||||||
|
a[foo()]++;
|
||||||
|
a[bar()]++;
|
||||||
|
a["bar"]++;
|
||||||
|
--a[foo()];
|
||||||
|
--a[bar()];
|
||||||
|
--a["bar"];
|
||||||
|
~foo();
|
||||||
|
~bar();
|
||||||
|
~"bar";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
bar();
|
||||||
|
bar();
|
||||||
|
delete a[foo()];
|
||||||
|
delete a[bar()];
|
||||||
|
delete a["bar"];
|
||||||
|
a[foo()]++;
|
||||||
|
a[bar()]++;
|
||||||
|
a["bar"]++;
|
||||||
|
--a[foo()];
|
||||||
|
--a[bar()];
|
||||||
|
--a["bar"];
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
180
test/compress/pure_getters.js
Normal file
180
test/compress/pure_getters.js
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
strict: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: false,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b = null, c = {};
|
||||||
|
a.prop;
|
||||||
|
b.prop;
|
||||||
|
c.prop;
|
||||||
|
d.prop;
|
||||||
|
null.prop;
|
||||||
|
(void 0).prop;
|
||||||
|
undefined.prop;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = null, c = {};
|
||||||
|
a.prop;
|
||||||
|
b.prop;
|
||||||
|
c.prop;
|
||||||
|
d.prop;
|
||||||
|
null.prop;
|
||||||
|
(void 0).prop;
|
||||||
|
(void 0).prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strict_reduce_vars: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b = null, c = {};
|
||||||
|
a.prop;
|
||||||
|
b.prop;
|
||||||
|
c.prop;
|
||||||
|
d.prop;
|
||||||
|
null.prop;
|
||||||
|
(void 0).prop;
|
||||||
|
undefined.prop;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = null, c = {};
|
||||||
|
a.prop;
|
||||||
|
b.prop;
|
||||||
|
d.prop;
|
||||||
|
null.prop;
|
||||||
|
(void 0).prop;
|
||||||
|
(void 0).prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe: {
|
||||||
|
options = {
|
||||||
|
pure_getters: true,
|
||||||
|
reduce_vars: false,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b = null, c = {};
|
||||||
|
a.prop;
|
||||||
|
b.prop;
|
||||||
|
c.prop;
|
||||||
|
d.prop;
|
||||||
|
null.prop;
|
||||||
|
(void 0).prop;
|
||||||
|
undefined.prop;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = null, c = {};
|
||||||
|
d;
|
||||||
|
null.prop;
|
||||||
|
(void 0).prop;
|
||||||
|
(void 0).prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_reduce_vars: {
|
||||||
|
options = {
|
||||||
|
pure_getters: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, b = null, c = {};
|
||||||
|
a.prop;
|
||||||
|
b.prop;
|
||||||
|
c.prop;
|
||||||
|
d.prop;
|
||||||
|
null.prop;
|
||||||
|
(void 0).prop;
|
||||||
|
undefined.prop;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, b = null, c = {};
|
||||||
|
d;
|
||||||
|
null.prop;
|
||||||
|
(void 0).prop;
|
||||||
|
(void 0).prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chained: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a.b.c;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a.b.c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impure_getter_1: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).a;
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).b;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).a;
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).b;
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
impure_getter_2: {
|
||||||
|
options = {
|
||||||
|
pure_getters: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
// will produce incorrect output because getter is not pure
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).a;
|
||||||
|
({
|
||||||
|
get a() {
|
||||||
|
console.log(1);
|
||||||
|
},
|
||||||
|
b: 1
|
||||||
|
}).b;
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
}
|
||||||
2539
test/compress/reduce_vars.js
Normal file
2539
test/compress/reduce_vars.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,257 @@
|
|||||||
do_screw: {
|
do_screw: {
|
||||||
options = { screw_ie8: true };
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
beautify = {
|
beautify = {
|
||||||
screw_ie8: true,
|
ie8: false,
|
||||||
ascii_only: true
|
ascii_only: true,
|
||||||
};
|
}
|
||||||
|
input: {
|
||||||
input: f("\v");
|
f("\v");
|
||||||
expect_exact: 'f("\\v");';
|
}
|
||||||
|
expect_exact: 'f("\\v");'
|
||||||
}
|
}
|
||||||
|
|
||||||
dont_screw: {
|
dont_screw: {
|
||||||
options = { screw_ie8: false };
|
options = {
|
||||||
beautify = { screw_ie8: false, ascii_only: true };
|
ie8: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
ie8: true,
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
f("\v");
|
||||||
|
}
|
||||||
|
expect_exact: 'f("\\x0B");'
|
||||||
|
}
|
||||||
|
|
||||||
input: f("\v");
|
do_screw_constants: {
|
||||||
expect_exact: 'f("\\x0B");';
|
options = {
|
||||||
}
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
f(undefined, Infinity);
|
||||||
|
}
|
||||||
|
expect_exact: "f(void 0,1/0);"
|
||||||
|
}
|
||||||
|
|
||||||
|
dont_screw_constants: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
f(undefined, Infinity);
|
||||||
|
}
|
||||||
|
expect_exact: "f(undefined,Infinity);"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_screw_try_catch: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
good = function(e){
|
||||||
|
return function(error){
|
||||||
|
try{
|
||||||
|
e()
|
||||||
|
} catch(e) {
|
||||||
|
error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
good = function(n){
|
||||||
|
return function(t){
|
||||||
|
try{
|
||||||
|
n()
|
||||||
|
} catch(n) {
|
||||||
|
t(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dont_screw_try_catch: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
bad = function(e){
|
||||||
|
return function(error){
|
||||||
|
try{
|
||||||
|
e()
|
||||||
|
} catch(e) {
|
||||||
|
error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
bad = function(n){
|
||||||
|
return function(t){
|
||||||
|
try{
|
||||||
|
n()
|
||||||
|
} catch(n) {
|
||||||
|
t(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do_screw_try_catch_undefined: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function a(b){
|
||||||
|
try {
|
||||||
|
throw 'Stuff';
|
||||||
|
} catch (undefined) {
|
||||||
|
console.log('caught: ' + undefined);
|
||||||
|
}
|
||||||
|
console.log('undefined is ' + undefined);
|
||||||
|
return b === undefined;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function a(o){
|
||||||
|
try{
|
||||||
|
throw "Stuff"
|
||||||
|
} catch (o) {
|
||||||
|
console.log("caught: "+o)
|
||||||
|
}
|
||||||
|
console.log("undefined is " + void 0);
|
||||||
|
return void 0===o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
dont_screw_try_catch_undefined: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function a(b){
|
||||||
|
try {
|
||||||
|
throw 'Stuff';
|
||||||
|
} catch (undefined) {
|
||||||
|
console.log('caught: ' + undefined);
|
||||||
|
}
|
||||||
|
console.log('undefined is ' + undefined);
|
||||||
|
return b === undefined;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function a(n){
|
||||||
|
try{
|
||||||
|
throw "Stuff"
|
||||||
|
} catch (undefined) {
|
||||||
|
console.log("caught: " + undefined)
|
||||||
|
}
|
||||||
|
console.log("undefined is " + undefined);
|
||||||
|
return n === undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce_vars: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
ie8: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a;
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (a) {
|
||||||
|
y();
|
||||||
|
}
|
||||||
|
alert(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
var t;
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (t) {
|
||||||
|
y();
|
||||||
|
}
|
||||||
|
alert(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1586_1: {
|
||||||
|
options = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "function f(){try{x()}catch(c){console.log(c.message)}}"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1586_2: {
|
||||||
|
options = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
x();
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "function f(){try{x()}catch(c){console.log(c.message)}}"
|
||||||
|
}
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ make_sequences_4: {
|
|||||||
switch (x = 5, y) {}
|
switch (x = 5, y) {}
|
||||||
with (x = 5, obj);
|
with (x = 5, obj);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
lift_sequences_1: {
|
lift_sequences_1: {
|
||||||
@@ -103,15 +104,18 @@ lift_sequences_1: {
|
|||||||
lift_sequences_2: {
|
lift_sequences_2: {
|
||||||
options = { sequences: true, evaluate: true };
|
options = { sequences: true, evaluate: true };
|
||||||
input: {
|
input: {
|
||||||
var foo, bar;
|
var foo = 1, bar;
|
||||||
foo.x = (foo = {}, 10);
|
foo.x = (foo = {}, 10);
|
||||||
bar = (bar = {}, 10);
|
bar = (bar = {}, 10);
|
||||||
|
console.log(foo, bar);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var foo, bar;
|
var foo = 1, bar;
|
||||||
foo.x = (foo = {}, 10),
|
foo.x = (foo = {}, 10),
|
||||||
bar = {}, bar = 10;
|
bar = {}, bar = 10,
|
||||||
|
console.log(foo, bar);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
lift_sequences_3: {
|
lift_sequences_3: {
|
||||||
@@ -138,6 +142,23 @@ lift_sequences_4: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lift_sequences_5: {
|
||||||
|
options = {
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 2, b;
|
||||||
|
a *= (b, a = 4, 3);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 2, b;
|
||||||
|
b, a *= (a = 4, 3),
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "6"
|
||||||
|
}
|
||||||
|
|
||||||
for_sequences: {
|
for_sequences: {
|
||||||
options = { sequences: true };
|
options = { sequences: true };
|
||||||
input: {
|
input: {
|
||||||
@@ -169,3 +190,523 @@ for_sequences: {
|
|||||||
for (y = 5; false;);
|
for (y = 5; false;);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
limit_1: {
|
||||||
|
options = {
|
||||||
|
sequences: 3,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a;
|
||||||
|
b;
|
||||||
|
c;
|
||||||
|
d;
|
||||||
|
e;
|
||||||
|
f;
|
||||||
|
g;
|
||||||
|
h;
|
||||||
|
i;
|
||||||
|
j;
|
||||||
|
k;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a, b, c;
|
||||||
|
d, e, f;
|
||||||
|
g, h, i;
|
||||||
|
j, k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
limit_2: {
|
||||||
|
options = {
|
||||||
|
sequences: 3,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a, b;
|
||||||
|
c, d;
|
||||||
|
e, f;
|
||||||
|
g, h;
|
||||||
|
i, j;
|
||||||
|
k;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a, b, c, d;
|
||||||
|
e, f, g, h;
|
||||||
|
i, j, k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
negate_iife_for: {
|
||||||
|
options = {
|
||||||
|
sequences: true,
|
||||||
|
negate_iife: true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
(function() {})();
|
||||||
|
for (i = 0; i < 5; i++) console.log(i);
|
||||||
|
|
||||||
|
(function() {})();
|
||||||
|
for (; i < 5; i++) console.log(i);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (!function() {}(), i = 0; i < 5; i++) console.log(i);
|
||||||
|
for (function() {}(); i < 5; i++) console.log(i);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
iife: {
|
||||||
|
options = {
|
||||||
|
sequences: true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
x = 42;
|
||||||
|
(function a() {})();
|
||||||
|
!function b() {}();
|
||||||
|
~function c() {}();
|
||||||
|
+function d() {}();
|
||||||
|
-function e() {}();
|
||||||
|
void function f() {}();
|
||||||
|
typeof function g() {}();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
x = 42, function a() {}(), function b() {}(), function c() {}(),
|
||||||
|
function d() {}(), function e() {}(), function f() {}(), function g() {}();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_undefined: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(undefined) {
|
||||||
|
if (a)
|
||||||
|
return b;
|
||||||
|
if (c)
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
function g(undefined) {
|
||||||
|
if (a)
|
||||||
|
return b;
|
||||||
|
if (c)
|
||||||
|
return d;
|
||||||
|
e();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(undefined) {
|
||||||
|
return a ? b : c ? d : undefined;
|
||||||
|
}
|
||||||
|
function g(undefined) {
|
||||||
|
return a ? b : c ? d : void e();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1685: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
function f() {
|
||||||
|
var a = (a--, delete a && --b);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
function f() {
|
||||||
|
var a = (a--, delete a && --b);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
func_def_1: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
return f = 0, !!f;
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
return !!(f = 0);
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
}
|
||||||
|
|
||||||
|
func_def_2: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f() {
|
||||||
|
return f = 0, !!f;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function f() {
|
||||||
|
return f = 0, !!f;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
func_def_3: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {}
|
||||||
|
return g = 0, !!g;
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
function g() {}
|
||||||
|
return !!(g = 0);
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
}
|
||||||
|
|
||||||
|
func_def_4: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
return g = 0, !!g;
|
||||||
|
}
|
||||||
|
return g();
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
function g() {
|
||||||
|
return !!(g = 0);
|
||||||
|
}
|
||||||
|
return g();
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect_stdout: "false"
|
||||||
|
}
|
||||||
|
|
||||||
|
func_def_5: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
return function g(){
|
||||||
|
return g = 0, !!g;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
return function g(){
|
||||||
|
return g = 0, !!g;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1758: {
|
||||||
|
options = {
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(c) {
|
||||||
|
var undefined = 42;
|
||||||
|
return function() {
|
||||||
|
c--;
|
||||||
|
c--, c.toString();
|
||||||
|
return;
|
||||||
|
}();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(c) {
|
||||||
|
var undefined = 42;
|
||||||
|
return function() {
|
||||||
|
return c--, c--, void c.toString();
|
||||||
|
}();
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_seq_1: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(delete (1, undefined));
|
||||||
|
console.log(delete (1, void 0));
|
||||||
|
console.log(delete (1, Infinity));
|
||||||
|
console.log(delete (1, 1 / 0));
|
||||||
|
console.log(delete (1, NaN));
|
||||||
|
console.log(delete (1, 0 / 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_seq_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(delete (1, 2, undefined));
|
||||||
|
console.log(delete (1, 2, void 0));
|
||||||
|
console.log(delete (1, 2, Infinity));
|
||||||
|
console.log(delete (1, 2, 1 / 0));
|
||||||
|
console.log(delete (1, 2, NaN));
|
||||||
|
console.log(delete (1, 2, 0 / 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_seq_3: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
keep_infinity: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(delete (1, 2, undefined));
|
||||||
|
console.log(delete (1, 2, void 0));
|
||||||
|
console.log(delete (1, 2, Infinity));
|
||||||
|
console.log(delete (1, 2, 1 / 0));
|
||||||
|
console.log(delete (1, 2, NaN));
|
||||||
|
console.log(delete (1, 2, 0 / 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
console.log(!0);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_seq_4: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {}
|
||||||
|
console.log(delete (f(), undefined));
|
||||||
|
console.log(delete (f(), void 0));
|
||||||
|
console.log(delete (f(), Infinity));
|
||||||
|
console.log(delete (f(), 1 / 0));
|
||||||
|
console.log(delete (f(), NaN));
|
||||||
|
console.log(delete (f(), 0 / 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {}
|
||||||
|
console.log((f(), !0)),
|
||||||
|
console.log((f(), !0)),
|
||||||
|
console.log((f(), !0)),
|
||||||
|
console.log((f(), !0)),
|
||||||
|
console.log((f(), !0)),
|
||||||
|
console.log((f(), !0));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_seq_5: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
keep_infinity: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {}
|
||||||
|
console.log(delete (f(), undefined));
|
||||||
|
console.log(delete (f(), void 0));
|
||||||
|
console.log(delete (f(), Infinity));
|
||||||
|
console.log(delete (f(), 1 / 0));
|
||||||
|
console.log(delete (f(), NaN));
|
||||||
|
console.log(delete (f(), 0 / 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {}
|
||||||
|
console.log((f(), !0)),
|
||||||
|
console.log((f(), !0)),
|
||||||
|
console.log((f(), !0)),
|
||||||
|
console.log((f(), !0)),
|
||||||
|
console.log((f(), !0)),
|
||||||
|
console.log((f(), !0));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_seq_6: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
console.log(delete (1, a));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
console.log(!0);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
side_effects: {
|
||||||
|
options = {
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
0, a(), 1, b(), 2, c(), 3;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a(), b(), c();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
side_effects_cascade_1: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
a -= 42;
|
||||||
|
if (a < 0) a = 0;
|
||||||
|
b.a = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
(a -= 42) < 0 && (a = 0), b.a = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
side_effects_cascade_2: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
b = a,
|
||||||
|
!a + (b += a) || (b += a),
|
||||||
|
b = a,
|
||||||
|
b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
b = a,
|
||||||
|
!a + (b += a) || (b += a),
|
||||||
|
b = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
side_effects_cascade_3: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
conditionals: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
"foo" ^ (b += a),
|
||||||
|
b ? false : (b = a) ? -1 : (b -= a) - (b ^= a),
|
||||||
|
a-- || !a,
|
||||||
|
a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
!(b += a) && ((b = a) || (b -= a, b ^= a)),
|
||||||
|
--a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_27: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
passes: 2,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(jQuery) {
|
||||||
|
var $;
|
||||||
|
$ = jQuery;
|
||||||
|
$("body").addClass("foo");
|
||||||
|
})(jQuery);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(jQuery) {
|
||||||
|
jQuery("body").addClass("foo");
|
||||||
|
})(jQuery);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
constant_switch_1: {
|
constant_switch_1: {
|
||||||
options = { dead_code: true, evaluate: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (1+1) {
|
switch (1+1) {
|
||||||
case 1: foo(); break;
|
case 1: foo(); break;
|
||||||
@@ -13,7 +18,12 @@ constant_switch_1: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constant_switch_2: {
|
constant_switch_2: {
|
||||||
options = { dead_code: true, evaluate: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (1) {
|
switch (1) {
|
||||||
case 1: foo();
|
case 1: foo();
|
||||||
@@ -28,7 +38,12 @@ constant_switch_2: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constant_switch_3: {
|
constant_switch_3: {
|
||||||
options = { dead_code: true, evaluate: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (10) {
|
switch (10) {
|
||||||
case 1: foo();
|
case 1: foo();
|
||||||
@@ -44,7 +59,12 @@ constant_switch_3: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constant_switch_4: {
|
constant_switch_4: {
|
||||||
options = { dead_code: true, evaluate: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (2) {
|
switch (2) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -65,7 +85,12 @@ constant_switch_4: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constant_switch_5: {
|
constant_switch_5: {
|
||||||
options = { dead_code: true, evaluate: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (1) {
|
switch (1) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -94,7 +119,12 @@ constant_switch_5: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constant_switch_6: {
|
constant_switch_6: {
|
||||||
options = { dead_code: true, evaluate: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
OUT: {
|
OUT: {
|
||||||
foo();
|
foo();
|
||||||
@@ -123,7 +153,12 @@ constant_switch_6: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constant_switch_7: {
|
constant_switch_7: {
|
||||||
options = { dead_code: true, evaluate: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
OUT: {
|
OUT: {
|
||||||
foo();
|
foo();
|
||||||
@@ -161,7 +196,12 @@ constant_switch_7: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constant_switch_8: {
|
constant_switch_8: {
|
||||||
options = { dead_code: true, evaluate: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
OUT: switch (1) {
|
OUT: switch (1) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -185,7 +225,12 @@ constant_switch_8: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constant_switch_9: {
|
constant_switch_9: {
|
||||||
options = { dead_code: true, evaluate: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
OUT: switch (1) {
|
OUT: switch (1) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -210,7 +255,10 @@ constant_switch_9: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drop_default_1: {
|
drop_default_1: {
|
||||||
options = { dead_code: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz();
|
case 'bar': baz();
|
||||||
@@ -225,7 +273,10 @@ drop_default_1: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drop_default_2: {
|
drop_default_2: {
|
||||||
options = { dead_code: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz(); break;
|
case 'bar': baz(); break;
|
||||||
@@ -241,7 +292,10 @@ drop_default_2: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
keep_default: {
|
keep_default: {
|
||||||
options = { dead_code: true };
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
input: {
|
input: {
|
||||||
switch (foo) {
|
switch (foo) {
|
||||||
case 'bar': baz();
|
case 'bar': baz();
|
||||||
@@ -258,3 +312,507 @@ keep_default: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1663: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
function f() {
|
||||||
|
switch (1) {
|
||||||
|
case 1:
|
||||||
|
b = a++;
|
||||||
|
return ++b;
|
||||||
|
default:
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
function f() {
|
||||||
|
var b;
|
||||||
|
b = a++;
|
||||||
|
return ++b;
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_case: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (foo) {
|
||||||
|
case 'bar': baz(); break;
|
||||||
|
case 'moo':
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (foo) {
|
||||||
|
case 'bar': baz();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_case: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (foo) {
|
||||||
|
case 'bar': baz(); break;
|
||||||
|
case moo:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (foo) {
|
||||||
|
case 'bar': baz(); break;
|
||||||
|
case moo:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_376: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (true) {
|
||||||
|
case boolCondition:
|
||||||
|
console.log(1);
|
||||||
|
break;
|
||||||
|
case false:
|
||||||
|
console.log(2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (true) {
|
||||||
|
case boolCondition:
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_441_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (foo) {
|
||||||
|
case bar:
|
||||||
|
qux();
|
||||||
|
break;
|
||||||
|
case baz:
|
||||||
|
qux();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qux();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (foo) {
|
||||||
|
case bar:
|
||||||
|
case baz:
|
||||||
|
default:
|
||||||
|
qux();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_441_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (foo) {
|
||||||
|
case bar:
|
||||||
|
// TODO: Fold into the case below
|
||||||
|
qux();
|
||||||
|
break;
|
||||||
|
case fall:
|
||||||
|
case baz:
|
||||||
|
qux();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qux();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (foo) {
|
||||||
|
case bar:
|
||||||
|
qux();
|
||||||
|
break;
|
||||||
|
case fall:
|
||||||
|
case baz:
|
||||||
|
default:
|
||||||
|
qux();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1674: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
console.log("FAIL");
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
console.log("PASS");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1679: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
function f() {
|
||||||
|
switch (--b) {
|
||||||
|
default:
|
||||||
|
case !function x() {}:
|
||||||
|
break;
|
||||||
|
case b--:
|
||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
case a--:
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case (a++):
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
function f() {
|
||||||
|
switch (--b) {
|
||||||
|
default:
|
||||||
|
case !function x() {}:
|
||||||
|
break;
|
||||||
|
case b--:
|
||||||
|
switch (0) {
|
||||||
|
default:
|
||||||
|
case a--:
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case (a++):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1680_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x) {
|
||||||
|
console.log(x);
|
||||||
|
return x + 1;
|
||||||
|
}
|
||||||
|
switch (2) {
|
||||||
|
case f(0):
|
||||||
|
case f(1):
|
||||||
|
f(2);
|
||||||
|
case 2:
|
||||||
|
case f(3):
|
||||||
|
case f(4):
|
||||||
|
f(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(x) {
|
||||||
|
console.log(x);
|
||||||
|
return x + 1;
|
||||||
|
}
|
||||||
|
switch (2) {
|
||||||
|
case f(0):
|
||||||
|
case f(1):
|
||||||
|
f(2);
|
||||||
|
case 2:
|
||||||
|
f(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"5",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1680_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
switch (b) {
|
||||||
|
case a--:
|
||||||
|
break;
|
||||||
|
case b:
|
||||||
|
var c;
|
||||||
|
break;
|
||||||
|
case a:
|
||||||
|
break;
|
||||||
|
case a--:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 100, b = 10;
|
||||||
|
switch (b) {
|
||||||
|
case a--:
|
||||||
|
break;
|
||||||
|
case b:
|
||||||
|
var c;
|
||||||
|
break;
|
||||||
|
case a:
|
||||||
|
case a--:
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1690_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (console.log("PASS")) {}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1690_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: false,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (console.log("PASS")) {}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (console.log("PASS")) {}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
if_switch_typeof: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if (a) switch(typeof b) {}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1698: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
!function() {
|
||||||
|
switch (a++) {}
|
||||||
|
}();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
!function() {
|
||||||
|
switch (a++) {}
|
||||||
|
}();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1705_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
switch (a) {
|
||||||
|
default:
|
||||||
|
console.log("FAIL");
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
switch (a) {
|
||||||
|
default:
|
||||||
|
console.log("FAIL");
|
||||||
|
case 0:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1705_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
switches: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
switch (a) {
|
||||||
|
default:
|
||||||
|
console.log("FAIL");
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1705_3: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (a) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a;
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
beautify: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (a) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
switch (b) {
|
||||||
|
case 3:
|
||||||
|
foo();
|
||||||
|
bar();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
"switch (a) {",
|
||||||
|
" case 0:",
|
||||||
|
" case 1:",
|
||||||
|
" break;",
|
||||||
|
"",
|
||||||
|
" case 2:",
|
||||||
|
" default:",
|
||||||
|
"}",
|
||||||
|
"",
|
||||||
|
"switch (b) {",
|
||||||
|
" case 3:",
|
||||||
|
" foo();",
|
||||||
|
" bar();",
|
||||||
|
"",
|
||||||
|
" default:",
|
||||||
|
" break;",
|
||||||
|
"}",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1758: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1, b = 2;
|
||||||
|
switch (a--) {
|
||||||
|
default:
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1, b = 2;
|
||||||
|
a--;
|
||||||
|
b++;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "0 3"
|
||||||
|
}
|
||||||
|
|||||||
130
test/compress/transform.js
Normal file
130
test/compress/transform.js
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
booleans_evaluate: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof void 0 != "undefined");
|
||||||
|
console.log(1 == 1, 1 === 1)
|
||||||
|
console.log(1 != 1, 1 !== 1)
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!1);
|
||||||
|
console.log(!0, !0);
|
||||||
|
console.log(!1, !1);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
booleans_global_defs: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
global_defs: {
|
||||||
|
A: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(A == 1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
condition_evaluate: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
dead_code: false,
|
||||||
|
evaluate: true,
|
||||||
|
loops: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
while (1 === 2);
|
||||||
|
for (; 1 == true;);
|
||||||
|
if (void 0 == null);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
while (!1);
|
||||||
|
for (; !0;);
|
||||||
|
if (!0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if_else_empty: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if ({} ? a : b); else {}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!{} ? b : a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label_if_break: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L: if (true) {
|
||||||
|
a;
|
||||||
|
break L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while_if_break: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
loops: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
while (a) {
|
||||||
|
if (b) if(c) d;
|
||||||
|
if (e) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for(; a && (b && c && d, !e););
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if_return: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(w, x, y, z) {
|
||||||
|
if (x) return;
|
||||||
|
if (w) {
|
||||||
|
if (y) return;
|
||||||
|
} else if (z) return;
|
||||||
|
if (x == y) return true;
|
||||||
|
|
||||||
|
if (x) w();
|
||||||
|
if (y) z();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(w, x, y, z) {
|
||||||
|
if (!x) {
|
||||||
|
if (w) {
|
||||||
|
if (y) return;
|
||||||
|
} else if (z) return;
|
||||||
|
return x == y || (x && w(), y && z(), !0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,3 +23,40 @@ typeof_evaluation: {
|
|||||||
h='undefined';
|
h='undefined';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typeof_in_boolean_context: {
|
||||||
|
options = {
|
||||||
|
booleans : true,
|
||||||
|
evaluate : true,
|
||||||
|
conditionals : true,
|
||||||
|
side_effects : true,
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function f1(x) { return typeof x ? "yes" : "no"; }
|
||||||
|
function f2() { return typeof g()? "Yes" : "No"; }
|
||||||
|
typeof 0 ? foo() : bar();
|
||||||
|
!typeof console.log(1);
|
||||||
|
var a = !typeof console.log(2);
|
||||||
|
if (typeof (1 + foo()));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1(x) { return "yes"; }
|
||||||
|
function f2() { return g(), "Yes"; }
|
||||||
|
foo();
|
||||||
|
console.log(1);
|
||||||
|
var a = !(console.log(2), !0);
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1668: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if (typeof bar);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
if (!0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
48
test/compress/wrap_iife.js
Normal file
48
test/compress/wrap_iife.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
wrap_iife: {
|
||||||
|
options = {
|
||||||
|
negate_iife: false,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
wrap_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return function() {
|
||||||
|
console.log('test')
|
||||||
|
};
|
||||||
|
})()();
|
||||||
|
}
|
||||||
|
expect_exact: '(function(){return function(){console.log("test")}})()();'
|
||||||
|
}
|
||||||
|
|
||||||
|
wrap_iife_in_expression: {
|
||||||
|
options = {
|
||||||
|
negate_iife: false,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
wrap_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
foo = (function () {
|
||||||
|
return bar();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_exact: 'foo=(function(){return bar()})();'
|
||||||
|
}
|
||||||
|
|
||||||
|
wrap_iife_in_return_call: {
|
||||||
|
options = {
|
||||||
|
negate_iife: false,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
|
wrap_iife: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return (function() {
|
||||||
|
console.log('test')
|
||||||
|
})();
|
||||||
|
})()();
|
||||||
|
}
|
||||||
|
expect_exact: '(function(){return(function(){console.log("test")})()})()();'
|
||||||
|
}
|
||||||
13
test/exports.js
Normal file
13
test/exports.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
exports["Compressor"] = Compressor;
|
||||||
|
exports["JS_Parse_Error"] = JS_Parse_Error;
|
||||||
|
exports["OutputStream"] = OutputStream;
|
||||||
|
exports["SourceMap"] = SourceMap;
|
||||||
|
exports["TreeWalker"] = TreeWalker;
|
||||||
|
exports["base54"] = base54;
|
||||||
|
exports["defaults"] = defaults;
|
||||||
|
exports["mangle_properties"] = mangle_properties;
|
||||||
|
exports["minify"] = minify;
|
||||||
|
exports["parse"] = parse;
|
||||||
|
exports["string_template"] = string_template;
|
||||||
|
exports["tokenizer"] = tokenizer;
|
||||||
|
exports["is_identifier"] = is_identifier;
|
||||||
3
test/input/comments/filter.js
Normal file
3
test/input/comments/filter.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// foo
|
||||||
|
/*@preserve*/
|
||||||
|
// bar
|
||||||
1
test/input/global_defs/nested.js
Normal file
1
test/input/global_defs/nested.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
console.log(C.V, C.D);
|
||||||
1
test/input/global_defs/simple.js
Normal file
1
test/input/global_defs/simple.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
console.log(D);
|
||||||
1
test/input/invalid/assign_1.js
Normal file
1
test/input/invalid/assign_1.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
console.log(1 || 5--);
|
||||||
1
test/input/invalid/assign_2.js
Normal file
1
test/input/invalid/assign_2.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
console.log(2 || (Math.random() /= 2));
|
||||||
1
test/input/invalid/assign_3.js
Normal file
1
test/input/invalid/assign_3.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
console.log(3 || ++this);
|
||||||
1
test/input/invalid/assign_4.js
Normal file
1
test/input/invalid/assign_4.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
++null
|
||||||
14
test/input/invalid/delete.js
Normal file
14
test/input/invalid/delete.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
function f(x) {
|
||||||
|
delete 42;
|
||||||
|
delete (0, x);
|
||||||
|
delete null;
|
||||||
|
delete x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function g(x) {
|
||||||
|
"use strict";
|
||||||
|
delete 42;
|
||||||
|
delete (0, x);
|
||||||
|
delete null;
|
||||||
|
delete x;
|
||||||
|
}
|
||||||
1
test/input/invalid/dot_1.js
Normal file
1
test/input/invalid/dot_1.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
a.=
|
||||||
1
test/input/invalid/dot_2.js
Normal file
1
test/input/invalid/dot_2.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
%.a;
|
||||||
1
test/input/invalid/dot_3.js
Normal file
1
test/input/invalid/dot_3.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
a./();
|
||||||
1
test/input/invalid/eof.js
Normal file
1
test/input/invalid/eof.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
foo, bar(
|
||||||
6
test/input/invalid/function_1.js
Normal file
6
test/input/invalid/function_1.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
function f(arguments) {
|
||||||
|
}
|
||||||
|
|
||||||
|
function g(arguments) {
|
||||||
|
"use strict";
|
||||||
|
}
|
||||||
6
test/input/invalid/function_2.js
Normal file
6
test/input/invalid/function_2.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
function arguments() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function eval() {
|
||||||
|
"use strict";
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user