Compare commits
205 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
614db97cca | ||
|
|
d854523783 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.js text eol=lf
|
||||
9
.github/ISSUE_TEMPLATE.md
vendored
Normal file
9
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
- Bug report or feature request? <!-- Note: sub-optimal but correct code is not a bug -->
|
||||
- `uglify-js` version (`uglifyjs -V`)
|
||||
- JavaScript input - ideally as small as possible.
|
||||
- The `uglifyjs` CLI command executed or `minify()` options used.
|
||||
- An example of JavaScript output produced and/or the error or warning.
|
||||
<!--
|
||||
Note: the release version of uglify-js only supports ES5. Those wishing
|
||||
to minify ES6 should use the experimental harmony branch.
|
||||
-->
|
||||
@@ -1,10 +1,12 @@
|
||||
language: node_js
|
||||
before_install: "npm install -g npm"
|
||||
node_js:
|
||||
- "0.12"
|
||||
- "0.10"
|
||||
- "0.12"
|
||||
- "4"
|
||||
- "6"
|
||||
env:
|
||||
- UGLIFYJS_TEST_ALL=1
|
||||
matrix:
|
||||
fast_finish: true
|
||||
sudo: false
|
||||
|
||||
145
README.md
145
README.md
@@ -10,6 +10,11 @@ There's also an
|
||||
[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,
|
||||
Chrome and probably Safari).
|
||||
|
||||
#### Note:
|
||||
- release versions of `uglify-js` only support ECMAScript 5 (ES5). If you wish to minify
|
||||
ES2015+ (ES6+) code then please use the [harmony](#harmony) development branch.
|
||||
- Node 7 has a known performance regression and runs `uglify-js` twice as slow.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
@@ -62,14 +67,17 @@ The available options are:
|
||||
--source-map-include-sources Pass this flag if you want to include the
|
||||
content of source files in the source map as
|
||||
sourcesContent property.
|
||||
--source-map-inline Write base64-encoded source map to the end of js output.
|
||||
--in-source-map Input source map, useful if you're compressing
|
||||
JS that was generated from some other original
|
||||
code.
|
||||
code. Specify "inline" if the source map is included
|
||||
inline with the sources.
|
||||
--screw-ie8 Use this flag if you don't wish to support
|
||||
Internet Explorer 6-8 quirks.
|
||||
Internet Explorer 6/7/8.
|
||||
By default UglifyJS will not try to be IE-proof.
|
||||
--support-ie8 Use this flag to support Internet Explorer 6-8 quirks.
|
||||
Note: may break standards compliant `catch` identifiers.
|
||||
--support-ie8 Use this flag to support Internet Explorer 6/7/8.
|
||||
Equivalent to setting `screw_ie8: false` in `minify()`
|
||||
for `compress`, `mangle` and `output` options.
|
||||
--expr Parse a single expression, rather than a
|
||||
program (for parsing JSON)
|
||||
-p, --prefix Skip prefix for original filenames that appear
|
||||
@@ -83,10 +91,9 @@ The available options are:
|
||||
-b, --beautify Beautify output/specify output options.
|
||||
-m, --mangle Mangle names/pass mangler options.
|
||||
-r, --reserved Reserved names to exclude from mangling.
|
||||
-c, --compress Enable compressor/pass compressor options. Pass
|
||||
options like -c
|
||||
hoist_vars=false,if_return=false. Use -c with
|
||||
no argument to use the default compression
|
||||
-c, --compress Enable compressor/pass compressor options, e.g.
|
||||
`-c 'if_return=false,pure_funcs=["Math.pow","console.log"]'`
|
||||
Use `-c` with no argument to enable default compression
|
||||
options.
|
||||
-d, --define Global definitions
|
||||
-e, --enclose Embed everything in a big function, with a
|
||||
@@ -97,8 +104,8 @@ The available options are:
|
||||
"@preserve". You can optionally pass one of the
|
||||
following arguments to this flag:
|
||||
- "all" to keep all comments
|
||||
- a valid JS regexp (needs to start with a
|
||||
slash) to keep only comments that match.
|
||||
- a valid JS RegExp like `/foo/` or `/^!/` to
|
||||
keep only matching comments.
|
||||
Note that currently not *all* comments can be
|
||||
kept when compression is on, because of dead
|
||||
code removal or cascading statements into
|
||||
@@ -147,8 +154,10 @@ The available options are:
|
||||
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]
|
||||
--pure-funcs Functions that can be safely removed if their
|
||||
return value is not used, e.g.
|
||||
`--pure-funcs Math.floor console.info`
|
||||
(requires `--compress`)
|
||||
```
|
||||
|
||||
Specify `--output` (`-o`) to declare the output file. Otherwise the output
|
||||
@@ -194,9 +203,10 @@ compressed JS by mapping every token in the compiled JS to its original
|
||||
location.
|
||||
|
||||
To use this feature you need to pass `--in-source-map
|
||||
/path/to/input/source.map`. Normally the input source map should also point
|
||||
to the file containing the generated JS, so if that's correct you can omit
|
||||
input files from the command line.
|
||||
/path/to/input/source.map` or `--in-source-map inline` if the source map is
|
||||
included inline with the sources. Normally the input source map should also
|
||||
point to the file containing the generated JS, so if that's correct you can
|
||||
omit input files from the command line.
|
||||
|
||||
## Mangler options
|
||||
|
||||
@@ -284,6 +294,32 @@ of mangled property names.
|
||||
Using the name cache is not necessary if you compress all your files in a
|
||||
single call to UglifyJS.
|
||||
|
||||
#### Mangling unquoted names (`--mangle-props=unquoted` or `--mangle-props=2`)
|
||||
|
||||
Using quoted property name (`o["foo"]`) reserves the property name (`foo`)
|
||||
so that it is not mangled throughout the entire script even when used in an
|
||||
unquoted style (`o.foo`). Example:
|
||||
|
||||
```
|
||||
$ echo 'var o={"foo":1, bar:3}; o.foo += o.bar; console.log(o.foo);' | uglifyjs --mangle-props=2 -mc
|
||||
var o={"foo":1,a:3};o.foo+=o.a,console.log(o.foo);
|
||||
```
|
||||
|
||||
#### Debugging property name mangling
|
||||
|
||||
You can also pass `--mangle-props-debug` in order to mangle property names
|
||||
without completely obscuring them. For example the property `o.foo`
|
||||
would mangle to `o._$foo$_` with this option. This allows property mangling
|
||||
of a large codebase while still being able to debug the code and identify
|
||||
where mangling is breaking things.
|
||||
|
||||
You can also pass a custom suffix using `--mangle-props-debug=XYZ`. This would then
|
||||
mangle `o.foo` to `o._$foo$XYZ_`. You can change this each time you compile a
|
||||
script to identify how a property got mangled. One technique is to pass a
|
||||
random number on every compile to simulate mangling changing with different
|
||||
inputs (e.g. as you update the input script with new properties), and to help
|
||||
identify mistakes like writing mangled keys to storage.
|
||||
|
||||
## Compressor options
|
||||
|
||||
You need to pass `--compress` (`-c`) to enable the compressor. Optionally
|
||||
@@ -316,6 +352,12 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
||||
comparison are switching. Compression only works if both `comparisons` and
|
||||
`unsafe_comps` are both set to true.
|
||||
|
||||
- `unsafe_math` (default: false) -- optimize numerical expressions like
|
||||
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
||||
|
||||
- `unsafe_proto` (default: false) -- optimize expressions like
|
||||
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
||||
|
||||
- `conditionals` -- apply optimizations for `if`-s and conditional
|
||||
expressions
|
||||
|
||||
@@ -331,7 +373,15 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
||||
- `loops` -- optimizations for `do`, `while` and `for` loops when we can
|
||||
statically determine the condition
|
||||
|
||||
- `unused` -- drop unreferenced functions and variables
|
||||
- `unused` -- drop unreferenced functions and variables (simple direct variable
|
||||
assignments do not count as references unless set to `"keep_assign"`)
|
||||
|
||||
- `toplevel` -- drop unreferenced functions (`"funcs"`) and/or variables (`"vars"`)
|
||||
in the toplevel scope (`false` by default, `true` to drop both unreferenced
|
||||
functions and variables)
|
||||
|
||||
- `top_retain` -- prevent specific toplevel functions and variables from `unused`
|
||||
removal (can be array, comma-separated, RegExp or function. Implies `toplevel`)
|
||||
|
||||
- `hoist_funs` -- hoist function declarations
|
||||
|
||||
@@ -345,8 +395,11 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
||||
- `cascade` -- small optimization for sequences, transform `x, x` into `x`
|
||||
and `x = something(), x` into `x = something()`
|
||||
|
||||
- `collapse_vars` -- default `false`. Collapse single-use `var` and `const`
|
||||
definitions when possible.
|
||||
- `collapse_vars` -- Collapse single-use `var` and `const` definitions
|
||||
when possible.
|
||||
|
||||
- `reduce_vars` -- Improve optimization on variables assigned with and
|
||||
used as constant values.
|
||||
|
||||
- `warnings` -- display warnings when dropping unreachable code or unused
|
||||
declarations etc.
|
||||
@@ -371,7 +424,12 @@ to set `true`; it's effectively a shortcut for `foo=true`).
|
||||
overhead (compression will be slower).
|
||||
|
||||
- `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
|
||||
compressor from discarding unused function arguments. You need this
|
||||
@@ -413,6 +471,8 @@ if (DEBUG) {
|
||||
}
|
||||
```
|
||||
|
||||
You can specify nested constants in the form of `--define env.DEBUG=false`.
|
||||
|
||||
UglifyJS will warn about the condition being always false and about dropping
|
||||
unreachable code; for now there is no option to turn off only this specific
|
||||
warning, you can pass `warnings=false` to turn off *all* warnings.
|
||||
@@ -423,8 +483,6 @@ separate file and include it into the build. For example you can have a
|
||||
```javascript
|
||||
const DEBUG = false;
|
||||
const PRODUCTION = true;
|
||||
// Alternative for environments that don't support `const`
|
||||
/** @const */ var STAGING = false;
|
||||
// etc.
|
||||
```
|
||||
|
||||
@@ -435,7 +493,8 @@ and build your code like this:
|
||||
UglifyJS will notice the constants and, since they cannot be altered, it
|
||||
will evaluate references to them to the value itself and drop unreachable
|
||||
code as usual. The 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>
|
||||
|
||||
@@ -570,7 +629,7 @@ function uglify(ast, options, mangle) {
|
||||
|
||||
// Compression
|
||||
uAST.figure_out_scope();
|
||||
uAST = uAST.transform(UglifyJS.Compressor(options));
|
||||
uAST = UglifyJS.Compressor(options).compress(uAST);
|
||||
|
||||
// Mangling (optional)
|
||||
if (mangle) {
|
||||
@@ -632,13 +691,22 @@ To generate a source map with the fromString option, you can also use an object:
|
||||
```javascript
|
||||
var result = UglifyJS.minify({"file1.js": "var a = function () {};"}, {
|
||||
outSourceMap: "out.js.map",
|
||||
outFileName: "out.js",
|
||||
fromString: true
|
||||
});
|
||||
```
|
||||
|
||||
Note that the source map is not saved in a file, it's just returned in
|
||||
`result.map`. The value passed for `outSourceMap` is only used to set the
|
||||
`file` attribute in the source map (see [the spec][sm-spec]).
|
||||
`result.map`. The value passed for `outSourceMap` is only used to set
|
||||
`//# sourceMappingURL=out.js.map` in `result.code`. The value of
|
||||
`outFileName` is only used to set `file` attribute in source map file.
|
||||
|
||||
The `file` attribute in the source map (see [the spec][sm-spec]) will
|
||||
use `outFileName` firstly, if it's falsy, then will be deduced from
|
||||
`outSourceMap` (by removing `'.map'`).
|
||||
|
||||
You can set option `sourceMapInline` to be `true` and source map will
|
||||
be appended to code.
|
||||
|
||||
You can also specify sourceRoot property to be included in source map:
|
||||
```javascript
|
||||
@@ -743,6 +811,7 @@ Other options:
|
||||
|
||||
- `regex` — Pass a RegExp to only mangle certain names (maps to the `--mangle-regex` CLI arguments option)
|
||||
- `ignore_quoted` – Only mangle unquoted property names (maps to the `--mangle-props 2` CLI arguments option)
|
||||
- `debug` – Mangle names with the original name still present (maps to the `--mangle-props-debug` CLI arguments option). Defaults to `false`. Pass an empty string to enable, or a non-empty string to set the suffix.
|
||||
|
||||
We could add more options to `UglifyJS.minify` — if you need additional
|
||||
functionality please suggest!
|
||||
@@ -804,7 +873,7 @@ toplevel.figure_out_scope()
|
||||
Like this:
|
||||
```javascript
|
||||
var compressor = UglifyJS.Compressor(options);
|
||||
var compressed_ast = toplevel.transform(compressor);
|
||||
var compressed_ast = compressor.compress(toplevel);
|
||||
```
|
||||
|
||||
The `options` can be missing. Available options are discussed above in
|
||||
@@ -849,8 +918,11 @@ which we care about here are `source_map` and `comments`.
|
||||
#### Keeping comments in the output
|
||||
|
||||
In order to keep certain comments in the output you need to pass the
|
||||
`comments` option. Pass a RegExp or a function. If you pass a RegExp, only
|
||||
those comments whose body matches the regexp will be kept. Note that body
|
||||
`comments` option. Pass a RegExp (as string starting and closing with `/`
|
||||
or pass a RegExp object), a boolean or a function. Stringified options
|
||||
`all` and `some` can be passed too, where `some` behaves like it's cli
|
||||
equivalent `--comments` without passing a value. If you pass a RegExp,
|
||||
only those comments whose body matches the RegExp will be kept. Note that body
|
||||
means without the initial `//` or `/*`. If you pass a function, it will be
|
||||
called for every comment in the tree and will receive two arguments: the
|
||||
node that the comment is attached to, and the comment token itself.
|
||||
@@ -905,3 +977,20 @@ The `source_map_options` (optional) can contain the following properties:
|
||||
[codegen]: http://lisperator.net/uglifyjs/codegen
|
||||
[compressor]: http://lisperator.net/uglifyjs/compress
|
||||
[parser]: http://lisperator.net/uglifyjs/parser
|
||||
|
||||
#### Harmony
|
||||
|
||||
If you wish to use the experimental [harmony](https://github.com/mishoo/UglifyJS2/commits/harmony)
|
||||
branch to minify ES2015+ (ES6+) code please use the following in your `package.json` file:
|
||||
|
||||
```
|
||||
"uglify-js": "git+https://github.com/mishoo/UglifyJS2.git#harmony"
|
||||
```
|
||||
|
||||
or to directly install the experimental harmony version of uglify:
|
||||
|
||||
```
|
||||
npm install --save-dev uglify-js@github:mishoo/UglifyJS2#harmony
|
||||
```
|
||||
|
||||
See [#448](https://github.com/mishoo/UglifyJS2/issues/448) for additional details.
|
||||
|
||||
179
bin/uglifyjs
179
bin/uglifyjs
@@ -8,7 +8,6 @@ var sys = require("util");
|
||||
var yargs = require("yargs");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var async = require("async");
|
||||
var acorn;
|
||||
var screw_ie8 = true;
|
||||
var ARGS = yargs
|
||||
@@ -23,10 +22,11 @@ mangling you need to use `-c` and `-m`.\
|
||||
.describe("source-map", "Specify an output file where to generate source map.")
|
||||
.describe("source-map-root", "The path to the original source to be included in the source map.")
|
||||
.describe("source-map-url", "The path to the source map to be added in //# sourceMappingURL. Defaults to the value passed with --source-map.")
|
||||
.describe("source-map-inline", "Write base64-encoded source map to the end of js output. Disabled by default")
|
||||
.describe("source-map-include-sources", "Pass this flag if you want to include the content of source files in the source map as sourcesContent property.")
|
||||
.describe("in-source-map", "Input source map, useful if you're compressing JS that was generated from some other original code.")
|
||||
.describe("screw-ie8", "Do not support Internet Explorer 6-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("screw-ie8", "Do not support Internet Explorer 6/7/8. This flag is enabled by default.")
|
||||
.describe("support-ie8", "Support non-standard Internet Explorer 6/7/8 javascript.")
|
||||
.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. \
|
||||
@@ -46,7 +46,7 @@ Use -c with no argument to use the default compression options.")
|
||||
By default this works like Google Closure, keeping JSDoc-style comments that contain \"@license\" or \"@preserve\". \
|
||||
You can optionally pass one of the following arguments to this flag:\n\
|
||||
- \"all\" to keep all comments\n\
|
||||
- a valid JS regexp (needs to start with a slash) to keep only comments that match.\n\
|
||||
- a valid JS RegExp like `/foo/`or `/^!/` to keep only matching comments.\n\
|
||||
\
|
||||
Note that currently not *all* comments can be kept when compression is on, \
|
||||
because of dead code removal or cascading statements into sequences.")
|
||||
@@ -76,6 +76,7 @@ You need to pass an argument to this option to specify the name that your module
|
||||
.describe("name-cache", "File to hold mangled names mappings")
|
||||
.describe("pure-funcs", "List of functions that can be safely removed if their return value is not used")
|
||||
.describe("dump-spidermonkey-ast", "Dump SpiderMonkey AST to stdout.")
|
||||
.describe("wrap-iife", "Wrap IIFEs in parenthesis. Note: this disables the negate_iife compression option")
|
||||
|
||||
.alias("p", "prefix")
|
||||
.alias("o", "output")
|
||||
@@ -96,6 +97,7 @@ You need to pass an argument to this option to specify the name that your module
|
||||
.string("beautify")
|
||||
.string("m")
|
||||
.string("mangle")
|
||||
.string("mangle-props-debug")
|
||||
.string("c")
|
||||
.string("compress")
|
||||
.string("d")
|
||||
@@ -112,6 +114,7 @@ You need to pass an argument to this option to specify the name that your module
|
||||
.array("pure-funcs")
|
||||
|
||||
.boolean("expr")
|
||||
.boolean("source-map-inline")
|
||||
.boolean("source-map-include-sources")
|
||||
.boolean("screw-ie8")
|
||||
.boolean("support-ie8")
|
||||
@@ -130,6 +133,7 @@ You need to pass an argument to this option to specify the name that your module
|
||||
.boolean("bare-returns")
|
||||
.boolean("keep-fnames")
|
||||
.boolean("reserve-domprops")
|
||||
.boolean("wrap-iife")
|
||||
|
||||
.wrap(80)
|
||||
|
||||
@@ -223,9 +227,10 @@ if (ARGS.mangle_props === true) {
|
||||
}
|
||||
|
||||
var OUTPUT_OPTIONS = {
|
||||
beautify : BEAUTIFY ? true : false,
|
||||
preamble : ARGS.preamble || null,
|
||||
quote_style : ARGS.quotes != null ? ARGS.quotes : 0
|
||||
beautify : BEAUTIFY ? true : false,
|
||||
max_line_len : 32000,
|
||||
preamble : ARGS.preamble || null,
|
||||
quote_style : ARGS.quotes != null ? ARGS.quotes : 0,
|
||||
};
|
||||
|
||||
if (ARGS.mangle_props == 2) {
|
||||
@@ -247,28 +252,18 @@ if (ARGS.keep_fnames) {
|
||||
if (MANGLE) MANGLE.keep_fnames = true;
|
||||
}
|
||||
|
||||
if (ARGS.wrap_iife) {
|
||||
if (COMPRESS) COMPRESS.negate_iife = false;
|
||||
OUTPUT_OPTIONS.wrap_iife = true;
|
||||
}
|
||||
|
||||
if (BEAUTIFY)
|
||||
UglifyJS.merge(OUTPUT_OPTIONS, BEAUTIFY);
|
||||
|
||||
if (ARGS.comments != 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 {
|
||||
OUTPUT_OPTIONS.comments = function(node, comment) {
|
||||
var text = comment.value;
|
||||
var type = comment.type;
|
||||
if (type == "comment2") {
|
||||
// multiline comment
|
||||
return /@preserve|@license|@cc_on/i.test(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ARGS.comments === "") {
|
||||
OUTPUT_OPTIONS.comments = "some";
|
||||
} else {
|
||||
OUTPUT_OPTIONS.comments = ARGS.comments;
|
||||
}
|
||||
|
||||
var files = ARGS._.slice();
|
||||
@@ -286,21 +281,29 @@ if (ARGS.self) {
|
||||
|
||||
var ORIG_MAP = ARGS.in_source_map;
|
||||
|
||||
if (ORIG_MAP) {
|
||||
if (ORIG_MAP && ORIG_MAP != "inline") {
|
||||
ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP));
|
||||
if (files.length == 0) {
|
||||
print_error("INFO: Using file from the input source map: " + ORIG_MAP.file);
|
||||
files = [ ORIG_MAP.file ];
|
||||
}
|
||||
if (ARGS.source_map_root == null) {
|
||||
ARGS.source_map_root = ORIG_MAP.sourceRoot;
|
||||
}
|
||||
}
|
||||
|
||||
if (files.length == 0) {
|
||||
files = [ "-" ];
|
||||
}
|
||||
|
||||
if (ORIG_MAP == "inline") {
|
||||
if (files.length > 1) {
|
||||
print_error("ERROR: Inline source map only works with singular input");
|
||||
process.exit(1);
|
||||
}
|
||||
if (ARGS.acorn || ARGS.spidermonkey) {
|
||||
print_error("ERROR: Inline source map only works with built-in parser");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (files.indexOf("-") >= 0 && ARGS.source_map) {
|
||||
print_error("ERROR: Source map doesn't work with input from STDIN");
|
||||
process.exit(1);
|
||||
@@ -312,37 +315,22 @@ if (files.filter(function(el){ return el == "-" }).length > 1) {
|
||||
}
|
||||
|
||||
var STATS = {};
|
||||
var OUTPUT_FILE = ARGS.o;
|
||||
var TOPLEVEL = null;
|
||||
var P_RELATIVE = ARGS.p && ARGS.p == "relative";
|
||||
var SOURCES_CONTENT = {};
|
||||
var index = 0;
|
||||
|
||||
var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({
|
||||
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) {
|
||||
!function cb() {
|
||||
if (index == files.length) return done();
|
||||
var file = files[index++];
|
||||
read_whole_file(file, function (err, code) {
|
||||
if (err) {
|
||||
print_error("ERROR: can't read file: " + file);
|
||||
process.exit(1);
|
||||
}
|
||||
if (ORIG_MAP == "inline") {
|
||||
ORIG_MAP = read_source_map(code);
|
||||
}
|
||||
if (ARGS.p != null) {
|
||||
if (P_RELATIVE) {
|
||||
file = path.relative(path.dirname(ARGS.source_map), file).replace(/\\/g, '/');
|
||||
@@ -378,7 +366,21 @@ async.eachLimit(files, 1, function (file, cb) {
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
||||
print_error("Parse error at " + file + ":" + ex.line + "," + ex.col);
|
||||
print_error(ex.message);
|
||||
var col = ex.col;
|
||||
var line = code.split(/\r?\n/)[ex.line - (col ? 1 : 2)];
|
||||
if (line) {
|
||||
if (col > 40) {
|
||||
line = line.slice(col - 40);
|
||||
col = 40;
|
||||
}
|
||||
if (col) {
|
||||
print_error(line.slice(0, 80));
|
||||
print_error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
||||
} else {
|
||||
print_error(line.slice(-40));
|
||||
print_error(line.slice(-40).replace(/\S/g, " ") + "^");
|
||||
}
|
||||
}
|
||||
print_error(ex.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -388,7 +390,31 @@ async.eachLimit(files, 1, function (file, cb) {
|
||||
});
|
||||
cb();
|
||||
});
|
||||
}, function () {
|
||||
}();
|
||||
|
||||
function done() {
|
||||
var OUTPUT_FILE = ARGS.o;
|
||||
|
||||
var SOURCE_MAP = (ARGS.source_map || ARGS.source_map_inline) ? UglifyJS.SourceMap({
|
||||
file: P_RELATIVE ? path.relative(path.dirname(ARGS.source_map), OUTPUT_FILE) : OUTPUT_FILE,
|
||||
root: ARGS.source_map_root || ORIG_MAP && ORIG_MAP.sourceRoot,
|
||||
orig: ORIG_MAP,
|
||||
}) : null;
|
||||
|
||||
OUTPUT_OPTIONS.source_map = SOURCE_MAP;
|
||||
|
||||
try {
|
||||
var output = UglifyJS.OutputStream(OUTPUT_OPTIONS);
|
||||
var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS);
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.DefaultsError) {
|
||||
print_error(ex.message);
|
||||
print_error("Supported options:");
|
||||
print_error(sys.inspect(ex.defs));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){
|
||||
TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL);
|
||||
});
|
||||
@@ -425,17 +451,19 @@ async.eachLimit(files, 1, function (file, cb) {
|
||||
cache : cache,
|
||||
only_cache : !ARGS.mangle_props,
|
||||
regex : regex,
|
||||
ignore_quoted : ARGS.mangle_props == 2
|
||||
ignore_quoted : ARGS.mangle_props == 2,
|
||||
debug : typeof ARGS.mangle_props_debug === "undefined" ? false : ARGS.mangle_props_debug
|
||||
});
|
||||
writeNameCache("props", cache);
|
||||
})();
|
||||
|
||||
var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint
|
||||
var TL_CACHE = readNameCache("vars");
|
||||
if (MANGLE) MANGLE.cache = TL_CACHE;
|
||||
|
||||
if (SCOPE_IS_NEEDED) {
|
||||
time_it("scope", function(){
|
||||
TOPLEVEL.figure_out_scope({ screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||
TOPLEVEL.figure_out_scope(MANGLE || { screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||
if (ARGS.lint) {
|
||||
TOPLEVEL.scope_warnings();
|
||||
}
|
||||
@@ -450,7 +478,7 @@ async.eachLimit(files, 1, function (file, cb) {
|
||||
|
||||
if (SCOPE_IS_NEEDED) {
|
||||
time_it("scope", function(){
|
||||
TOPLEVEL.figure_out_scope({ screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||
TOPLEVEL.figure_out_scope(MANGLE || { screw_ie8: screw_ie8, cache: TL_CACHE });
|
||||
if (MANGLE && !TL_CACHE) {
|
||||
TOPLEVEL.compute_char_frequency(MANGLE);
|
||||
}
|
||||
@@ -458,7 +486,6 @@ async.eachLimit(files, 1, function (file, cb) {
|
||||
}
|
||||
|
||||
if (MANGLE) time_it("mangle", function(){
|
||||
MANGLE.cache = TL_CACHE;
|
||||
TOPLEVEL.mangle_names(MANGLE);
|
||||
});
|
||||
|
||||
@@ -482,13 +509,18 @@ async.eachLimit(files, 1, function (file, cb) {
|
||||
output = output.get();
|
||||
|
||||
if (SOURCE_MAP) {
|
||||
fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
|
||||
var source_map_url = ARGS.source_map_url || (
|
||||
P_RELATIVE
|
||||
? path.relative(path.dirname(OUTPUT_FILE), ARGS.source_map)
|
||||
: ARGS.source_map
|
||||
);
|
||||
output += "\n//# sourceMappingURL=" + source_map_url;
|
||||
if (ARGS.source_map_inline) {
|
||||
var base64_string = new Buffer(SOURCE_MAP.toString()).toString('base64');
|
||||
output += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + base64_string;
|
||||
} else {
|
||||
fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8");
|
||||
var source_map_url = ARGS.source_map_url || (
|
||||
P_RELATIVE
|
||||
? path.relative(path.dirname(OUTPUT_FILE), ARGS.source_map)
|
||||
: ARGS.source_map
|
||||
);
|
||||
output += "\n//# sourceMappingURL=" + source_map_url;
|
||||
}
|
||||
}
|
||||
|
||||
if (OUTPUT_FILE) {
|
||||
@@ -509,7 +541,7 @@ async.eachLimit(files, 1, function (file, cb) {
|
||||
}));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* -----[ functions ]----- */
|
||||
|
||||
@@ -529,7 +561,7 @@ function getOptions(flag, constants) {
|
||||
|
||||
var ast;
|
||||
try {
|
||||
ast = UglifyJS.parse(x, { expression: true });
|
||||
ast = UglifyJS.parse(x, { cli: true, expression: true });
|
||||
} catch(ex) {
|
||||
if (ex instanceof UglifyJS.JS_Parse_Error) {
|
||||
print_error("Error parsing arguments for flag `" + flag + "': " + x);
|
||||
@@ -539,7 +571,7 @@ function getOptions(flag, constants) {
|
||||
ast.walk(new UglifyJS.TreeWalker(function(node){
|
||||
if (node instanceof UglifyJS.AST_Seq) return; // descend
|
||||
if (node instanceof UglifyJS.AST_Assign) {
|
||||
var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_");
|
||||
var name = node.left.print_to_string().replace(/-/g, "_");
|
||||
var value = node.right;
|
||||
if (constants)
|
||||
value = new Function("return (" + value.print_to_string() + ")")();
|
||||
@@ -547,7 +579,7 @@ function getOptions(flag, constants) {
|
||||
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, "_");
|
||||
var name = node.print_to_string().replace(/-/g, "_");
|
||||
ret[name] = true;
|
||||
return true; // no descend
|
||||
}
|
||||
@@ -574,6 +606,15 @@ function read_whole_file(filename, cb) {
|
||||
}
|
||||
}
|
||||
|
||||
function read_source_map(code) {
|
||||
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
|
||||
if (!match) {
|
||||
print_error("WARN: inline source map not found");
|
||||
return null;
|
||||
}
|
||||
return JSON.parse(new Buffer(match[2], "base64"));
|
||||
}
|
||||
|
||||
function time_it(name, cont) {
|
||||
var t1 = new Date().getTime();
|
||||
var ret = cont();
|
||||
|
||||
86
lib/ast.js
86
lib/ast.js
@@ -81,7 +81,9 @@ function DEFNODE(type, props, methods, base) {
|
||||
ctor.DEFMETHOD = function(name, method) {
|
||||
this.prototype[name] = method;
|
||||
};
|
||||
exports["AST_" + type] = ctor;
|
||||
if (typeof exports !== "undefined") {
|
||||
exports["AST_" + type] = ctor;
|
||||
}
|
||||
return ctor;
|
||||
};
|
||||
|
||||
@@ -89,9 +91,20 @@ var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos
|
||||
}, null);
|
||||
|
||||
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);
|
||||
},
|
||||
clone: function(deep) {
|
||||
return this._clone(deep);
|
||||
},
|
||||
$documentation: "Base class of all AST nodes",
|
||||
$propdoc: {
|
||||
start: "[AST_Token] The first token of this node",
|
||||
@@ -143,12 +156,13 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
|
||||
}, AST_Statement);
|
||||
|
||||
function walk_body(node, visitor) {
|
||||
if (node.body instanceof AST_Statement) {
|
||||
node.body._walk(visitor);
|
||||
var body = node.body;
|
||||
if (body instanceof AST_Statement) {
|
||||
body._walk(visitor);
|
||||
}
|
||||
else for (var i = 0, len = body.length; i < len; i++) {
|
||||
body[i]._walk(visitor);
|
||||
}
|
||||
else node.body.forEach(function(stat){
|
||||
stat._walk(visitor);
|
||||
});
|
||||
};
|
||||
|
||||
var AST_Block = DEFNODE("Block", "body", {
|
||||
@@ -196,6 +210,20 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
|
||||
this.label._walk(visitor);
|
||||
this.body._walk(visitor);
|
||||
});
|
||||
},
|
||||
clone: function(deep) {
|
||||
var node = this._clone(deep);
|
||||
if (deep) {
|
||||
var refs = node.label.references;
|
||||
var label = this.label;
|
||||
node.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_LoopControl
|
||||
&& node.label && node.label.thedef === label) {
|
||||
refs.push(node);
|
||||
}
|
||||
}));
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}, AST_StatementWithBody);
|
||||
|
||||
@@ -369,9 +397,10 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
if (this.name) this.name._walk(visitor);
|
||||
this.argnames.forEach(function(arg){
|
||||
arg._walk(visitor);
|
||||
});
|
||||
var argnames = this.argnames;
|
||||
for (var i = 0, len = argnames.length; i < len; i++) {
|
||||
argnames[i]._walk(visitor);
|
||||
}
|
||||
walk_body(this, visitor);
|
||||
});
|
||||
}
|
||||
@@ -531,9 +560,10 @@ var AST_Definitions = DEFNODE("Definitions", "definitions", {
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.definitions.forEach(function(def){
|
||||
def._walk(visitor);
|
||||
});
|
||||
var definitions = this.definitions;
|
||||
for (var i = 0, len = definitions.length; i < len; i++) {
|
||||
definitions[i]._walk(visitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AST_Statement);
|
||||
@@ -571,9 +601,10 @@ var AST_Call = DEFNODE("Call", "expression args", {
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.expression._walk(visitor);
|
||||
this.args.forEach(function(arg){
|
||||
arg._walk(visitor);
|
||||
});
|
||||
var args = this.args;
|
||||
for (var i = 0, len = args.length; i < len; i++) {
|
||||
args[i]._walk(visitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -740,9 +771,10 @@ var AST_Array = DEFNODE("Array", "elements", {
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.elements.forEach(function(el){
|
||||
el._walk(visitor);
|
||||
});
|
||||
var elements = this.elements;
|
||||
for (var i = 0, len = elements.length; i < len; i++) {
|
||||
elements[i]._walk(visitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -754,9 +786,10 @@ var AST_Object = DEFNODE("Object", "properties", {
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.properties.forEach(function(prop){
|
||||
prop._walk(visitor);
|
||||
});
|
||||
var properties = this.properties;
|
||||
for (var i = 0, len = properties.length; i < len; i++) {
|
||||
properties[i]._walk(visitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -804,9 +837,6 @@ var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
|
||||
|
||||
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
|
||||
$documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
|
||||
$propdoc: {
|
||||
init: "[AST_Node*/S] array of initializers for this declaration."
|
||||
}
|
||||
}, AST_Symbol);
|
||||
|
||||
var AST_SymbolVar = DEFNODE("SymbolVar", null, {
|
||||
@@ -954,8 +984,8 @@ TreeWalker.prototype = {
|
||||
push: function (node) {
|
||||
if (node instanceof AST_Lambda) {
|
||||
this.directives = Object.create(this.directives);
|
||||
} else if (node instanceof AST_Directive) {
|
||||
this.directives[node.value] = this.directives[node.value] ? "up" : true;
|
||||
} else if (node instanceof AST_Directive && !this.directives[node.value]) {
|
||||
this.directives[node.value] = node;
|
||||
}
|
||||
this.stack.push(node);
|
||||
},
|
||||
@@ -983,7 +1013,7 @@ TreeWalker.prototype = {
|
||||
for (var i = 0; i < node.body.length; ++i) {
|
||||
var st = node.body[i];
|
||||
if (!(st instanceof AST_Directive)) break;
|
||||
if (st.value == type) return true;
|
||||
if (st.value == type) return st;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
2235
lib/compress.js
2235
lib/compress.js
File diff suppressed because it is too large
Load Diff
247
lib/output.js
247
lib/output.js
@@ -45,6 +45,11 @@
|
||||
|
||||
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) {
|
||||
|
||||
options = defaults(options, {
|
||||
@@ -56,7 +61,7 @@ function OutputStream(options) {
|
||||
unescape_regexps : false,
|
||||
inline_script : false,
|
||||
width : 80,
|
||||
max_line_len : 32000,
|
||||
max_line_len : false,
|
||||
beautify : false,
|
||||
source_map : null,
|
||||
bracketize : false,
|
||||
@@ -67,9 +72,38 @@ function OutputStream(options) {
|
||||
screw_ie8 : true,
|
||||
preamble : null,
|
||||
quote_style : 0,
|
||||
keep_quoted_props: false
|
||||
keep_quoted_props: false,
|
||||
wrap_iife : false,
|
||||
}, 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 current_col = 0;
|
||||
var current_line = 1;
|
||||
@@ -155,16 +189,29 @@ function OutputStream(options) {
|
||||
|
||||
var might_need_space = false;
|
||||
var might_need_semicolon = false;
|
||||
var might_add_newline = 0;
|
||||
var last = null;
|
||||
|
||||
function last_char() {
|
||||
return last.charAt(last.length - 1);
|
||||
};
|
||||
|
||||
function maybe_newline() {
|
||||
if (options.max_line_len && current_col > options.max_line_len)
|
||||
print("\n");
|
||||
};
|
||||
var ensure_line_len = options.max_line_len ? function() {
|
||||
if (current_col > options.max_line_len) {
|
||||
if (might_add_newline) {
|
||||
var left = OUTPUT.slice(0, might_add_newline);
|
||||
var right = OUTPUT.slice(might_add_newline);
|
||||
OUTPUT = left + "\n" + right;
|
||||
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("( [ + * / - , .");
|
||||
|
||||
@@ -180,6 +227,7 @@ function OutputStream(options) {
|
||||
current_col++;
|
||||
current_pos++;
|
||||
} else {
|
||||
ensure_line_len();
|
||||
OUTPUT += "\n";
|
||||
current_pos++;
|
||||
current_line++;
|
||||
@@ -200,6 +248,7 @@ function OutputStream(options) {
|
||||
if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
|
||||
var target_line = stack[stack.length - 1].start.line;
|
||||
while (current_line < target_line) {
|
||||
ensure_line_len();
|
||||
OUTPUT += "\n";
|
||||
current_pos++;
|
||||
current_line++;
|
||||
@@ -211,8 +260,9 @@ function OutputStream(options) {
|
||||
if (might_need_space) {
|
||||
var prev = last_char();
|
||||
if ((is_identifier_char(prev)
|
||||
&& (is_identifier_char(ch) || ch == "\\"))
|
||||
|| (/^[\+\-\/]$/.test(ch) && ch == prev))
|
||||
&& (is_identifier_char(ch) || ch == "\\"))
|
||||
|| (ch == "/" && ch == prev)
|
||||
|| ((ch == "+" || ch == "-") && ch == last))
|
||||
{
|
||||
OUTPUT += " ";
|
||||
current_col++;
|
||||
@@ -220,16 +270,16 @@ function OutputStream(options) {
|
||||
}
|
||||
might_need_space = false;
|
||||
}
|
||||
OUTPUT += str;
|
||||
current_pos += str.length;
|
||||
var a = str.split(/\r?\n/), n = a.length - 1;
|
||||
current_line += n;
|
||||
if (n == 0) {
|
||||
current_col += a[n].length;
|
||||
} else {
|
||||
current_col += a[0].length;
|
||||
if (n > 0) {
|
||||
ensure_line_len();
|
||||
current_col = a[n].length;
|
||||
}
|
||||
current_pos += str.length;
|
||||
last = str;
|
||||
OUTPUT += str;
|
||||
};
|
||||
|
||||
var space = options.beautify ? function() {
|
||||
@@ -255,7 +305,10 @@ function OutputStream(options) {
|
||||
|
||||
var newline = options.beautify ? function() {
|
||||
print("\n");
|
||||
} : maybe_newline;
|
||||
} : options.max_line_len ? function() {
|
||||
ensure_line_len();
|
||||
might_add_newline = OUTPUT.length;
|
||||
} : noop;
|
||||
|
||||
var semicolon = options.beautify ? function() {
|
||||
print(";");
|
||||
@@ -332,13 +385,12 @@ function OutputStream(options) {
|
||||
} : noop;
|
||||
|
||||
function get() {
|
||||
if (might_add_newline) {
|
||||
ensure_line_len();
|
||||
}
|
||||
return OUTPUT;
|
||||
};
|
||||
|
||||
if (options.preamble) {
|
||||
print(options.preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
|
||||
}
|
||||
|
||||
var stack = [];
|
||||
return {
|
||||
get : get,
|
||||
@@ -376,12 +428,12 @@ function OutputStream(options) {
|
||||
with_square : with_square,
|
||||
add_mapping : add_mapping,
|
||||
option : function(opt) { return options[opt] },
|
||||
comment_filter : comment_filter,
|
||||
line : function() { return current_line },
|
||||
col : function() { return current_col },
|
||||
pos : function() { return current_pos },
|
||||
push_node : function(node) { stack.push(node) },
|
||||
pop_node : function() { return stack.pop() },
|
||||
stack : function() { return stack },
|
||||
parent : function(n) {
|
||||
return stack[stack.length - 2 - (n || 0)];
|
||||
}
|
||||
@@ -435,7 +487,7 @@ function OutputStream(options) {
|
||||
|
||||
AST_Node.DEFMETHOD("add_comments", function(output){
|
||||
if (output._readonly) return;
|
||||
var c = output.option("comments"), self = this;
|
||||
var self = this;
|
||||
var start = self.start;
|
||||
if (start && !start._comments_dumped) {
|
||||
start._comments_dumped = true;
|
||||
@@ -458,20 +510,19 @@ function OutputStream(options) {
|
||||
}));
|
||||
}
|
||||
|
||||
if (!c) {
|
||||
comments = comments.filter(function(comment) {
|
||||
return comment.type == "comment5";
|
||||
});
|
||||
} else if (c.test) {
|
||||
comments = comments.filter(function(comment){
|
||||
return comment.type == "comment5" || c.test(comment.value);
|
||||
});
|
||||
} else if (typeof c == "function") {
|
||||
comments = comments.filter(function(comment){
|
||||
return comment.type == "comment5" || c(self, comment);
|
||||
});
|
||||
if (output.pos() == 0) {
|
||||
if (comments.length > 0 && output.option("shebang") && comments[0].type == "comment5") {
|
||||
output.print("#!" + comments.shift().value + "\n");
|
||||
output.indent();
|
||||
}
|
||||
var preamble = output.option("preamble");
|
||||
if (preamble) {
|
||||
output.print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
comments = comments.filter(output.comment_filter, self);
|
||||
|
||||
// Keep single line comments after nlb, after nlb
|
||||
if (!output.option("beautify") && comments.length > 0 &&
|
||||
/comment[134]/.test(comments[0].type) &&
|
||||
@@ -494,10 +545,6 @@ function OutputStream(options) {
|
||||
output.space();
|
||||
}
|
||||
}
|
||||
else if (output.pos() === 0 && c.type == "comment5" && output.option("shebang")) {
|
||||
output.print("#!" + c.value + "\n");
|
||||
output.indent();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -521,7 +568,16 @@ function OutputStream(options) {
|
||||
// a function expression needs parens around it when it's provably
|
||||
// the first token to appear in a statement.
|
||||
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
|
||||
@@ -536,6 +592,15 @@ function OutputStream(options) {
|
||||
|| p instanceof AST_Call && p.expression === this;
|
||||
});
|
||||
|
||||
PARENS([ AST_Infinity, AST_NaN ], function(output){
|
||||
var p = output.parent();
|
||||
return p instanceof AST_PropAccess && p.expression === this
|
||||
|| p instanceof AST_Call && p.expression === this
|
||||
|| p instanceof AST_Unary && p.operator != "+" && p.operator != "-"
|
||||
|| p instanceof AST_Binary && p.right === this
|
||||
&& (p.operator == "/" || p.operator == "%");
|
||||
});
|
||||
|
||||
PARENS(AST_Seq, function(output){
|
||||
var p = output.parent();
|
||||
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|
||||
@@ -721,7 +786,7 @@ function OutputStream(options) {
|
||||
DEFPRINT(AST_Do, function(self, output){
|
||||
output.print("do");
|
||||
output.space();
|
||||
self._do_print_body(output);
|
||||
make_block(self.body, output);
|
||||
output.space();
|
||||
output.print("while");
|
||||
output.space();
|
||||
@@ -743,7 +808,7 @@ function OutputStream(options) {
|
||||
output.print("for");
|
||||
output.space();
|
||||
output.with_parens(function(){
|
||||
if (self.init && !(self.init instanceof AST_EmptyStatement)) {
|
||||
if (self.init) {
|
||||
if (self.init instanceof AST_Definitions) {
|
||||
self.init.print(output);
|
||||
} else {
|
||||
@@ -848,10 +913,10 @@ function OutputStream(options) {
|
||||
|
||||
/* -----[ if ]----- */
|
||||
function make_then(self, output) {
|
||||
if (output.option("bracketize")) {
|
||||
make_block(self.body, output);
|
||||
return;
|
||||
}
|
||||
var b = self.body;
|
||||
if (output.option("bracketize")
|
||||
|| !output.option("screw_ie8") && b instanceof AST_Do)
|
||||
return make_block(b, output);
|
||||
// The squeezer replaces "block"-s that contain only a single
|
||||
// statement with the statement itself; technically, the AST
|
||||
// is correct, but this can create problems when we output an
|
||||
@@ -859,18 +924,7 @@ function OutputStream(options) {
|
||||
// IF *without* an ELSE block (then the outer ELSE would refer
|
||||
// to the inner IF). This function checks for this case and
|
||||
// adds the block brackets if needed.
|
||||
if (!self.body)
|
||||
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;
|
||||
if (!b) return output.force_semicolon();
|
||||
while (true) {
|
||||
if (b instanceof AST_If) {
|
||||
if (!b.alternative) {
|
||||
@@ -898,7 +952,10 @@ function OutputStream(options) {
|
||||
output.space();
|
||||
output.print("else");
|
||||
output.space();
|
||||
force_statement(self.alternative, output);
|
||||
if (self.alternative instanceof AST_If)
|
||||
self.alternative.print(output);
|
||||
else
|
||||
force_statement(self.alternative, output);
|
||||
} else {
|
||||
self._do_print_body(output);
|
||||
}
|
||||
@@ -912,24 +969,24 @@ function OutputStream(options) {
|
||||
self.expression.print(output);
|
||||
});
|
||||
output.space();
|
||||
if (self.body.length > 0) output.with_block(function(){
|
||||
self.body.forEach(function(stmt, i){
|
||||
if (i) output.newline();
|
||||
var last = self.body.length - 1;
|
||||
if (last < 0) output.print("{}");
|
||||
else output.with_block(function(){
|
||||
self.body.forEach(function(branch, i){
|
||||
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){
|
||||
if (this.body.length > 0) {
|
||||
output.newline();
|
||||
this.body.forEach(function(stmt){
|
||||
output.indent();
|
||||
stmt.print(output);
|
||||
output.newline();
|
||||
this.body.forEach(function(stmt){
|
||||
output.indent();
|
||||
stmt.print(output);
|
||||
output.newline();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
DEFPRINT(AST_Default, function(self, output){
|
||||
output.print("default:");
|
||||
@@ -1206,10 +1263,18 @@ function OutputStream(options) {
|
||||
});
|
||||
DEFPRINT(AST_Hole, noop);
|
||||
DEFPRINT(AST_Infinity, function(self, output){
|
||||
output.print("Infinity");
|
||||
output.print("1");
|
||||
output.space();
|
||||
output.print("/");
|
||||
output.space();
|
||||
output.print("0");
|
||||
});
|
||||
DEFPRINT(AST_NaN, function(self, output){
|
||||
output.print("NaN");
|
||||
output.print("0");
|
||||
output.space();
|
||||
output.print("/");
|
||||
output.space();
|
||||
output.print("0");
|
||||
});
|
||||
DEFPRINT(AST_This, function(self, output){
|
||||
output.print("this");
|
||||
@@ -1276,15 +1341,7 @@ function OutputStream(options) {
|
||||
|
||||
function force_statement(stat, output) {
|
||||
if (output.option("bracketize")) {
|
||||
if (!stat || stat instanceof AST_EmptyStatement)
|
||||
output.print("{}");
|
||||
else if (stat instanceof AST_BlockStatement)
|
||||
stat.print(output);
|
||||
else output.with_block(function(){
|
||||
output.indent();
|
||||
stat.print(output);
|
||||
output.newline();
|
||||
});
|
||||
make_block(stat, output);
|
||||
} else {
|
||||
if (!stat || stat instanceof AST_EmptyStatement)
|
||||
output.force_semicolon();
|
||||
@@ -1293,30 +1350,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.
|
||||
function need_constructor_parens(self, output) {
|
||||
// Always print parentheses with arguments
|
||||
@@ -1357,11 +1390,11 @@ function OutputStream(options) {
|
||||
};
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
output.with_block(function(){
|
||||
else output.with_block(function(){
|
||||
output.indent();
|
||||
stmt.print(output);
|
||||
output.newline();
|
||||
|
||||
95
lib/parse.js
95
lib/parse.js
@@ -195,12 +195,11 @@ function JS_Parse_Error(message, filename, line, col, pos) {
|
||||
this.line = line;
|
||||
this.col = col;
|
||||
this.pos = pos;
|
||||
this.stack = new Error().stack;
|
||||
};
|
||||
|
||||
JS_Parse_Error.prototype.toString = function() {
|
||||
return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
|
||||
};
|
||||
JS_Parse_Error.prototype = Object.create(Error.prototype);
|
||||
JS_Parse_Error.prototype.constructor = JS_Parse_Error;
|
||||
JS_Parse_Error.prototype.name = "SyntaxError";
|
||||
configure_error_stack(JS_Parse_Error);
|
||||
|
||||
function js_error(message, filename, line, col, pos) {
|
||||
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 (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);
|
||||
if (!isNaN(valid)) {
|
||||
return token("num", valid);
|
||||
} else {
|
||||
parse_error("SyntaxError: Invalid syntax: " + num);
|
||||
parse_error("Invalid syntax: " + num);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -395,7 +394,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
// Parse
|
||||
if (ch === "0") return "\0";
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -404,18 +403,18 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
for (; n > 0; --n) {
|
||||
var digit = parseInt(next(true), 16);
|
||||
if (isNaN(digit))
|
||||
parse_error("SyntaxError: Invalid hex-character pattern in string");
|
||||
parse_error("Invalid hex-character pattern in string");
|
||||
num = (num << 4) | digit;
|
||||
}
|
||||
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 = "";
|
||||
for (;;) {
|
||||
var ch = next(true, 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;
|
||||
ret += ch;
|
||||
}
|
||||
@@ -440,7 +439,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
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 i = find("*/", true);
|
||||
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 {
|
||||
if (ch != "u") parse_error("SyntaxError: Expecting UnicodeEscapeSequence -- uXXXX");
|
||||
if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
|
||||
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;
|
||||
backslash = false;
|
||||
}
|
||||
@@ -474,10 +473,10 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
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;
|
||||
while ((ch = next(true))) if (NEWLINE_CHARS(ch)) {
|
||||
parse_error("SyntaxError: Unexpected line terminator");
|
||||
parse_error("Unexpected line terminator");
|
||||
} else if (prev_backslash) {
|
||||
regexp += "\\" + ch;
|
||||
prev_backslash = false;
|
||||
@@ -498,7 +497,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
try {
|
||||
return token("regexp", new RegExp(regexp, mods));
|
||||
} 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) {
|
||||
if (force_regexp != null)
|
||||
return read_regexp(force_regexp);
|
||||
if (shebang && S.pos == 0 && looking_at("#!")) {
|
||||
start_token();
|
||||
forward(2);
|
||||
skip_line_comment("comment5");
|
||||
}
|
||||
for (;;) {
|
||||
skip_whitespace();
|
||||
start_token();
|
||||
@@ -590,16 +594,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
||||
if (PUNC_CHARS(ch)) return token("punc", next());
|
||||
if (OPERATOR_CHARS(ch)) return read_operator();
|
||||
if (code == 92 || is_identifier_start(code)) return read_word();
|
||||
if (shebang) {
|
||||
if (S.pos == 0 && looking_at("#!")) {
|
||||
forward(2);
|
||||
skip_line_comment("comment5");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
parse_error("SyntaxError: Unexpected character '" + ch + "'");
|
||||
parse_error("Unexpected character '" + ch + "'");
|
||||
};
|
||||
|
||||
next_token.context = function(nc) {
|
||||
@@ -698,6 +695,7 @@ function parse($TEXT, options) {
|
||||
html5_comments : true,
|
||||
bare_returns : false,
|
||||
shebang : true,
|
||||
cli : false,
|
||||
});
|
||||
|
||||
var S = {
|
||||
@@ -756,14 +754,14 @@ function parse($TEXT, options) {
|
||||
function unexpected(token) {
|
||||
if (token == null)
|
||||
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) {
|
||||
if (is(type, val)) {
|
||||
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); };
|
||||
@@ -892,7 +890,7 @@ function parse($TEXT, options) {
|
||||
|
||||
case "return":
|
||||
if (S.in_function == 0 && !options.bare_returns)
|
||||
croak("SyntaxError: 'return' outside of function");
|
||||
croak("'return' outside of function");
|
||||
return new AST_Return({
|
||||
value: ( is("punc", ";")
|
||||
? (next(), null)
|
||||
@@ -909,7 +907,7 @@ function parse($TEXT, options) {
|
||||
|
||||
case "throw":
|
||||
if (S.token.nlb)
|
||||
croak("SyntaxError: Illegal newline after 'throw'");
|
||||
croak("Illegal newline after 'throw'");
|
||||
return new AST_Throw({
|
||||
value: (tmp = expression(true), semicolon(), tmp)
|
||||
});
|
||||
@@ -925,17 +923,15 @@ function parse($TEXT, options) {
|
||||
|
||||
case "with":
|
||||
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({
|
||||
expression : parenthesised(),
|
||||
body : statement()
|
||||
});
|
||||
|
||||
default:
|
||||
unexpected();
|
||||
}
|
||||
}
|
||||
unexpected();
|
||||
});
|
||||
|
||||
function labeled_statement() {
|
||||
@@ -945,7 +941,7 @@ function parse($TEXT, options) {
|
||||
// syntactically incorrect if it contains a
|
||||
// LabelledStatement that is enclosed by a
|
||||
// LabelledStatement with the same Identifier as label.
|
||||
croak("SyntaxError: Label " + label.name + " defined twice");
|
||||
croak("Label " + label.name + " defined twice");
|
||||
}
|
||||
expect(":");
|
||||
S.labels.push(label);
|
||||
@@ -958,7 +954,7 @@ function parse($TEXT, options) {
|
||||
label.references.forEach(function(ref){
|
||||
if (ref instanceof AST_Continue) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
@@ -978,11 +974,11 @@ function parse($TEXT, options) {
|
||||
if (label != null) {
|
||||
ldef = find_if(function(l){ return l.name == label.name }, S.labels);
|
||||
if (!ldef)
|
||||
croak("SyntaxError: Undefined label " + label.name);
|
||||
croak("Undefined label " + label.name);
|
||||
label.thedef = ldef;
|
||||
}
|
||||
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();
|
||||
var stat = new type({ label: label });
|
||||
if (ldef) ldef.references.push(stat);
|
||||
@@ -998,7 +994,7 @@ function parse($TEXT, options) {
|
||||
: expression(true, true);
|
||||
if (is("operator", "in")) {
|
||||
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();
|
||||
return for_in(init);
|
||||
}
|
||||
@@ -1148,7 +1144,7 @@ function parse($TEXT, options) {
|
||||
});
|
||||
}
|
||||
if (!bcatch && !bfinally)
|
||||
croak("SyntaxError: Missing catch/finally blocks");
|
||||
croak("Missing catch/finally blocks");
|
||||
return new AST_Try({
|
||||
body : body,
|
||||
bcatch : bcatch,
|
||||
@@ -1242,7 +1238,7 @@ function parse($TEXT, options) {
|
||||
break;
|
||||
case "operator":
|
||||
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);
|
||||
}
|
||||
ret = _make_symbol(AST_SymbolRef);
|
||||
@@ -1308,6 +1304,10 @@ function parse($TEXT, options) {
|
||||
});
|
||||
});
|
||||
|
||||
var create_accessor = embed_tokens(function() {
|
||||
return function_(AST_Accessor);
|
||||
});
|
||||
|
||||
var object_ = embed_tokens(function() {
|
||||
expect("{");
|
||||
var first = true, a = [];
|
||||
@@ -1324,7 +1324,7 @@ function parse($TEXT, options) {
|
||||
a.push(new AST_ObjectGetter({
|
||||
start : start,
|
||||
key : as_atom_node(),
|
||||
value : function_(AST_Accessor),
|
||||
value : create_accessor(),
|
||||
end : prev()
|
||||
}));
|
||||
continue;
|
||||
@@ -1333,7 +1333,7 @@ function parse($TEXT, options) {
|
||||
a.push(new AST_ObjectSetter({
|
||||
start : start,
|
||||
key : as_atom_node(),
|
||||
value : function_(AST_Accessor),
|
||||
value : create_accessor(),
|
||||
end : prev()
|
||||
}));
|
||||
continue;
|
||||
@@ -1393,7 +1393,7 @@ function parse($TEXT, options) {
|
||||
|
||||
function as_symbol(type, noerror) {
|
||||
if (!is("name")) {
|
||||
if (!noerror) croak("SyntaxError: Name expected");
|
||||
if (!noerror) croak("Name expected");
|
||||
return null;
|
||||
}
|
||||
var sym = _make_symbol(type);
|
||||
@@ -1457,7 +1457,7 @@ function parse($TEXT, options) {
|
||||
|
||||
function make_unary(ctor, op, expr) {
|
||||
if ((op == "++" || op == "--") && !is_assignable(expr))
|
||||
croak("SyntaxError: Invalid use of " + op + " operator");
|
||||
croak("Invalid use of " + op + " operator", null, ctor === AST_UnaryPrefix ? expr.start.col - 1 : null);
|
||||
return new ctor({ operator: op, expression: expr });
|
||||
};
|
||||
|
||||
@@ -1502,9 +1502,8 @@ function parse($TEXT, options) {
|
||||
};
|
||||
|
||||
function is_assignable(expr) {
|
||||
if (!options.strict) return true;
|
||||
if (expr instanceof AST_This) return false;
|
||||
return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol);
|
||||
if (options.cli) return true;
|
||||
return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef;
|
||||
};
|
||||
|
||||
var maybe_assign = function(no_in) {
|
||||
@@ -1521,7 +1520,7 @@ function parse($TEXT, options) {
|
||||
end : prev()
|
||||
});
|
||||
}
|
||||
croak("SyntaxError: Invalid assignment");
|
||||
croak("Invalid assignment");
|
||||
}
|
||||
return left;
|
||||
};
|
||||
|
||||
@@ -66,7 +66,8 @@ function mangle_properties(ast, options) {
|
||||
cache : null,
|
||||
only_cache : false,
|
||||
regex : null,
|
||||
ignore_quoted : false
|
||||
ignore_quoted : false,
|
||||
debug : false
|
||||
});
|
||||
|
||||
var reserved = options.reserved;
|
||||
@@ -84,6 +85,15 @@ function mangle_properties(ast, options) {
|
||||
var regex = options.regex;
|
||||
var ignore_quoted = options.ignore_quoted;
|
||||
|
||||
// note debug is either false (disabled), or a string of the debug suffix to use (enabled).
|
||||
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
|
||||
// the same as passing an empty string.
|
||||
var debug = (options.debug !== false);
|
||||
var debug_name_suffix;
|
||||
if (debug) {
|
||||
debug_name_suffix = (options.debug === true ? "" : options.debug);
|
||||
}
|
||||
|
||||
var names_to_mangle = [];
|
||||
var unmangleable = [];
|
||||
var ignored = {};
|
||||
@@ -139,6 +149,7 @@ function mangle_properties(ast, options) {
|
||||
// only function declarations after this line
|
||||
|
||||
function can_mangle(name) {
|
||||
if (!is_identifier(name)) return false;
|
||||
if (unmangleable.indexOf(name) >= 0) return false;
|
||||
if (reserved.indexOf(name) >= 0) return false;
|
||||
if (options.only_cache) {
|
||||
@@ -177,9 +188,25 @@ function mangle_properties(ast, options) {
|
||||
|
||||
var mangled = cache.props.get(name);
|
||||
if (!mangled) {
|
||||
do {
|
||||
mangled = base54(++cache.cname);
|
||||
} while (!can_mangle(mangled));
|
||||
if (debug) {
|
||||
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
|
||||
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
|
||||
|
||||
if (can_mangle(debug_mangled) && !(ignore_quoted && debug_mangled in ignored)) {
|
||||
mangled = debug_mangled;
|
||||
}
|
||||
}
|
||||
|
||||
// either debug mode is off, or it is on and we could not use the mangled name
|
||||
if (!mangled) {
|
||||
// note can_mangle() does not check if the name collides with the 'ignored' set
|
||||
// (filled with quoted properties when ignore_quoted set). Make sure we add this
|
||||
// check so we don't collide with a quoted name.
|
||||
do {
|
||||
mangled = base54(++cache.cname);
|
||||
} while (!can_mangle(mangled) || (ignore_quoted && mangled in ignored));
|
||||
}
|
||||
|
||||
cache.props.set(name, mangled);
|
||||
}
|
||||
return mangled;
|
||||
|
||||
149
lib/scope.js
149
lib/scope.js
@@ -51,7 +51,6 @@ function SymbolDef(scope, index, orig) {
|
||||
this.global = false;
|
||||
this.mangled_name = null;
|
||||
this.undeclared = false;
|
||||
this.constant = false;
|
||||
this.index = index;
|
||||
this.id = SymbolDef.next_id++;
|
||||
};
|
||||
@@ -76,9 +75,14 @@ SymbolDef.prototype = {
|
||||
}
|
||||
else if (!this.mangled_name && !this.unmangleable(options)) {
|
||||
var s = this.scope;
|
||||
if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda)
|
||||
var sym = this.orig[0];
|
||||
if (!options.screw_ie8 && sym instanceof AST_SymbolLambda)
|
||||
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) {
|
||||
cache.set(this.name, this.mangled_name);
|
||||
}
|
||||
@@ -97,26 +101,23 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
var scope = self.parent_scope = null;
|
||||
var labels = new Dictionary();
|
||||
var defun = null;
|
||||
var last_var_had_const_pragma = false;
|
||||
var nesting = 0;
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (options.screw_ie8 && node instanceof AST_Catch) {
|
||||
if (node instanceof AST_Catch) {
|
||||
var save_scope = scope;
|
||||
scope = new AST_Scope(node);
|
||||
scope.init_scope_vars(nesting);
|
||||
scope.parent_scope = save_scope;
|
||||
scope.init_scope_vars(save_scope);
|
||||
descend();
|
||||
scope = save_scope;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Scope) {
|
||||
node.init_scope_vars(nesting);
|
||||
var save_scope = node.parent_scope = scope;
|
||||
node.init_scope_vars(scope);
|
||||
var save_scope = scope;
|
||||
var save_defun = defun;
|
||||
var save_labels = labels;
|
||||
defun = scope = node;
|
||||
labels = new Dictionary();
|
||||
++nesting; descend(); --nesting;
|
||||
descend();
|
||||
scope = save_scope;
|
||||
defun = save_defun;
|
||||
labels = save_labels;
|
||||
@@ -155,18 +156,20 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
// later.
|
||||
(node.scope = defun.parent_scope).def_function(node);
|
||||
}
|
||||
else if (node instanceof AST_Var) {
|
||||
last_var_had_const_pragma = node.has_const_pragma();
|
||||
}
|
||||
else if (node instanceof AST_SymbolVar
|
||||
|| node instanceof AST_SymbolConst) {
|
||||
var def = defun.def_variable(node);
|
||||
def.constant = node instanceof AST_SymbolConst || last_var_had_const_pragma;
|
||||
def.init = tw.parent().value;
|
||||
|| node instanceof AST_SymbolConst) {
|
||||
defun.def_variable(node);
|
||||
if (defun !== scope) {
|
||||
node.mark_enclosed(options);
|
||||
var def = scope.find_variable(node);
|
||||
if (node.thedef !== def) {
|
||||
node.thedef = def;
|
||||
node.reference(options);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node instanceof AST_SymbolCatch) {
|
||||
(options.screw_ie8 ? scope : defun)
|
||||
.def_variable(node);
|
||||
scope.def_variable(node).defun = defun;
|
||||
}
|
||||
else if (node instanceof AST_LabelRef) {
|
||||
var sym = labels.get(node.name);
|
||||
@@ -203,64 +206,93 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
}
|
||||
}
|
||||
var sym = node.scope.find_variable(name);
|
||||
if (!sym) {
|
||||
var g;
|
||||
if (globals.has(name)) {
|
||||
g = globals.get(name);
|
||||
} else {
|
||||
g = new SymbolDef(self, globals.size(), node);
|
||||
g.undeclared = true;
|
||||
g.global = true;
|
||||
globals.set(name, g);
|
||||
}
|
||||
node.thedef = g;
|
||||
if (func && name == "arguments") {
|
||||
func.uses_arguments = true;
|
||||
}
|
||||
} else {
|
||||
node.thedef = sym;
|
||||
if (node.scope instanceof AST_Lambda && name == "arguments") {
|
||||
node.scope.uses_arguments = true;
|
||||
}
|
||||
node.reference();
|
||||
if (!sym) {
|
||||
sym = self.def_global(node);
|
||||
}
|
||||
node.thedef = sym;
|
||||
node.reference(options);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
self.walk(tw);
|
||||
|
||||
// pass 3: fix up any scoping issue with IE8
|
||||
if (!options.screw_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) {
|
||||
this.cname = options.cache.cname;
|
||||
}
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
|
||||
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
||||
this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
|
||||
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
||||
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
||||
this.parent_scope = null; // the parent scope
|
||||
this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
|
||||
this.cname = -1; // the current index for mangling functions/variables
|
||||
this.nesting = nesting; // the nesting level of this scope (0 means toplevel)
|
||||
AST_Toplevel.DEFMETHOD("def_global", function(node){
|
||||
var globals = this.globals, name = node.name;
|
||||
if (globals.has(name)) {
|
||||
return globals.get(name);
|
||||
} else {
|
||||
var g = new SymbolDef(this, globals.size(), node);
|
||||
g.undeclared = true;
|
||||
g.global = true;
|
||||
globals.set(name, g);
|
||||
return g;
|
||||
}
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("init_scope_vars", function(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_Scope.prototype.init_scope_vars.apply(this, arguments);
|
||||
this.uses_arguments = false;
|
||||
|
||||
var symbol = new AST_VarDef({ name: "arguments", start: this.start, end: this.end });
|
||||
var def = new SymbolDef(this, this.variables.size(), symbol);
|
||||
this.variables.set(symbol.name, def);
|
||||
this.def_variable(new AST_SymbolVar({
|
||||
name: "arguments",
|
||||
start: this.start,
|
||||
end: this.end
|
||||
}));
|
||||
});
|
||||
|
||||
AST_SymbolRef.DEFMETHOD("reference", function() {
|
||||
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
|
||||
var def = this.definition();
|
||||
def.references.push(this);
|
||||
var s = this.scope;
|
||||
while (s) {
|
||||
push_uniq(s.enclosed, def);
|
||||
if (options.keep_fnames) {
|
||||
s.functions.each(function(d) {
|
||||
push_uniq(def.scope.enclosed, d);
|
||||
});
|
||||
}
|
||||
if (s === def.scope) break;
|
||||
s = s.parent_scope;
|
||||
}
|
||||
this.frame = this.scope.nesting - def.scope.nesting;
|
||||
});
|
||||
|
||||
AST_Symbol.DEFMETHOD("reference", function(options) {
|
||||
this.definition().references.push(this);
|
||||
this.mark_enclosed(options);
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("find_variable", function(name){
|
||||
@@ -325,11 +357,6 @@ 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){
|
||||
return this.definition().unmangleable(options);
|
||||
});
|
||||
@@ -369,12 +396,6 @@ AST_Symbol.DEFMETHOD("global", function(){
|
||||
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){
|
||||
return defaults(options, {
|
||||
except : [],
|
||||
|
||||
@@ -60,7 +60,7 @@ function SourceMap(options) {
|
||||
var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
|
||||
|
||||
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);
|
||||
if (sourceContent) {
|
||||
generator.setSourceContent(source, sourceContent);
|
||||
|
||||
50
lib/utils.js
50
lib/utils.js
@@ -78,13 +78,28 @@ function repeat_string(str, i) {
|
||||
return d;
|
||||
};
|
||||
|
||||
function configure_error_stack(fn) {
|
||||
Object.defineProperty(fn.prototype, "stack", {
|
||||
get: function() {
|
||||
var err = new Error(this.message);
|
||||
err.name = this.name;
|
||||
try {
|
||||
throw err;
|
||||
} catch(e) {
|
||||
return e.stack;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function DefaultsError(msg, defs) {
|
||||
Error.call(this, msg);
|
||||
this.msg = msg;
|
||||
this.message = msg;
|
||||
this.defs = defs;
|
||||
};
|
||||
DefaultsError.prototype = Object.create(Error.prototype);
|
||||
DefaultsError.prototype.constructor = DefaultsError;
|
||||
DefaultsError.prototype.name = "DefaultsError";
|
||||
configure_error_stack(DefaultsError);
|
||||
|
||||
DefaultsError.croak = function(msg, defs) {
|
||||
throw new DefaultsError(msg, defs);
|
||||
@@ -111,7 +126,11 @@ function merge(obj, ext) {
|
||||
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(){
|
||||
function MAP(a, f, backwards) {
|
||||
@@ -168,7 +187,7 @@ function push_uniq(array, el) {
|
||||
|
||||
function string_template(text, props) {
|
||||
return text.replace(/\{(.+?)\}/g, function(str, p){
|
||||
return props[p];
|
||||
return props && props[p];
|
||||
});
|
||||
};
|
||||
|
||||
@@ -318,3 +337,26 @@ Dictionary.fromObject = function(obj) {
|
||||
function HOP(obj, prop) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||
}
|
||||
|
||||
// return true if the node at the top of the stack (that means the
|
||||
// innermost node in the current output) is lexically the first in
|
||||
// a statement.
|
||||
function first_in_statement(stack) {
|
||||
var node = stack.parent(-1);
|
||||
for (var i = 0, p; p = stack.parent(i); i++) {
|
||||
if (p instanceof AST_Statement && p.body === node)
|
||||
return true;
|
||||
if ((p instanceof AST_Seq && p.car === node ) ||
|
||||
(p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||
|
||||
(p instanceof AST_Dot && p.expression === node ) ||
|
||||
(p instanceof AST_Sub && p.expression === node ) ||
|
||||
(p instanceof AST_Conditional && p.condition === node ) ||
|
||||
(p instanceof AST_Binary && p.left === node ) ||
|
||||
(p instanceof AST_UnaryPostfix && p.expression === node ))
|
||||
{
|
||||
node = p;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
"homepage": "http://lisperator.net/uglifyjs",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "2.7.1",
|
||||
"version": "2.8.20",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
@@ -29,9 +29,7 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"async": "~0.2.6",
|
||||
"source-map": "~0.5.1",
|
||||
"uglify-to-browserify": "~1.0.0",
|
||||
"yargs": "~3.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -41,13 +39,15 @@
|
||||
"estraverse": "~1.5.1",
|
||||
"mocha": "~2.3.4"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"uglify-to-browserify": "~1.0.0"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
"uglify-to-browserify"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"shrinkwrap": "rm ./npm-shrinkwrap.json; rm -rf ./node_modules; npm i && npm shrinkwrap && npm outdated",
|
||||
"test": "node test/run-tests.js"
|
||||
},
|
||||
"keywords": ["uglify", "uglify-js", "minify", "minifier"]
|
||||
|
||||
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", "warnings=false");
|
||||
}
|
||||
args.push("--stats");
|
||||
var urls = [
|
||||
"https://code.jquery.com/jquery-3.1.1.js",
|
||||
"https://code.angularjs.org/1.6.1/angular.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.9.0/math.js",
|
||||
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
|
||||
"https://unpkg.com/react@15.3.2/dist/react.js",
|
||||
"http://builds.emberjs.com/tags/v2.11.0/ember.prod.js",
|
||||
"https://cdn.jsdelivr.net/lodash/4.17.4/lodash.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.js",
|
||||
];
|
||||
var results = {};
|
||||
var remaining = 2 * urls.length;
|
||||
function done() {
|
||||
if (!--remaining) {
|
||||
var failures = [];
|
||||
urls.forEach(function(url) {
|
||||
var info = results[url];
|
||||
console.log();
|
||||
console.log(url);
|
||||
console.log(info.log);
|
||||
var elapsed = 0;
|
||||
info.log.replace(/: ([0-9]+\.[0-9]{3})s/g, function(match, time) {
|
||||
elapsed += parseFloat(time);
|
||||
});
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -21,10 +21,19 @@ constant_join: {
|
||||
input: {
|
||||
var a = [ "foo", "bar", "baz" ].join("");
|
||||
var a1 = [ "foo", "bar", "baz" ].join();
|
||||
var a2 = [ "foo", "bar", "baz" ].join(null);
|
||||
var a3 = [ "foo", "bar", "baz" ].join(void 0);
|
||||
var a4 = [ "foo", , "baz" ].join();
|
||||
var a5 = [ "foo", null, "baz" ].join();
|
||||
var a6 = [ "foo", void 0, "baz" ].join();
|
||||
var b = [ "foo", 1, 2, 3, "bar" ].join("");
|
||||
var c = [ boo(), "foo", 1, 2, 3, "bar", bar() ].join("");
|
||||
var c1 = [ boo(), bar(), "foo", 1, 2, 3, "bar", bar() ].join("");
|
||||
var c2 = [ 1, 2, "foo", "bar", baz() ].join("");
|
||||
var c3 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join("");
|
||||
var c4 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join("");
|
||||
var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join();
|
||||
var c6 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join();
|
||||
var d = [ "foo", 1 + 2 + "bar", "baz" ].join("-");
|
||||
var e = [].join(foo + bar);
|
||||
var f = [].join("");
|
||||
@@ -33,10 +42,19 @@ constant_join: {
|
||||
expect: {
|
||||
var a = "foobarbaz";
|
||||
var a1 = "foo,bar,baz";
|
||||
var a2 = "foonullbarnullbaz";
|
||||
var a3 = "foo,bar,baz";
|
||||
var a4 = "foo,,baz";
|
||||
var a5 = "foo,,baz";
|
||||
var a6 = "foo,,baz";
|
||||
var b = "foo123bar";
|
||||
var c = boo() + "foo123bar" + bar();
|
||||
var c1 = "" + boo() + bar() + "foo123bar" + bar();
|
||||
var c2 = "12foobar" + baz();
|
||||
var c3 = boo() + bar() + "foo123bar" + bar() + "foo";
|
||||
var c4 = "12foobar" + baz();
|
||||
var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join();
|
||||
var c6 = [ "1,2,,,foo,bar", baz() ].join();
|
||||
var d = "foo-3bar-baz";
|
||||
var e = [].join(foo + bar);
|
||||
var f = "";
|
||||
@@ -72,3 +90,88 @@ constant_join_2: {
|
||||
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]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,13 +90,13 @@ asm_mixed: {
|
||||
}
|
||||
function no_asm_GeometricMean(stdlib, foreign, buffer) {
|
||||
function logSum(start, end) {
|
||||
start = 0 | start, end = 0 | end;
|
||||
start |= 0, end |= 0;
|
||||
var sum = 0, p = 0, q = 0;
|
||||
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
|
||||
return +sum;
|
||||
}
|
||||
function geometricMean(start, end) {
|
||||
return start = 0 | 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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ collapse_vars_side_effects_1: {
|
||||
z = i += 4;
|
||||
log(x, z, y, i);
|
||||
}
|
||||
f1(), f2(), f3(), f4();
|
||||
}
|
||||
expect: {
|
||||
function f1() {
|
||||
@@ -73,7 +74,9 @@ collapse_vars_side_effects_1: {
|
||||
y = i += 3;
|
||||
log(x, i += 4, y, i);
|
||||
}
|
||||
f1(), f2(), f3(), f4();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
collapse_vars_side_effects_2: {
|
||||
@@ -338,14 +341,15 @@ collapse_vars_while: {
|
||||
collapse_vars_do_while: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:false, loops:false, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
comparisons:true, evaluate:true, booleans:false, loops:false, unused:"keep_assign",
|
||||
hoist_funs:true, keep_fargs:true, if_return:true, join_vars:true, cascade:true,
|
||||
side_effects:true
|
||||
}
|
||||
input: {
|
||||
function f1(y) {
|
||||
// The constant do-while condition `c` will be replaced.
|
||||
// The constant do-while condition `c` will not be replaced.
|
||||
var c = 9;
|
||||
do { } while (c === 77);
|
||||
do {} while (c === 77);
|
||||
}
|
||||
function f2(y) {
|
||||
// The non-constant do-while condition `c` will not be replaced.
|
||||
@@ -380,7 +384,8 @@ collapse_vars_do_while: {
|
||||
}
|
||||
expect: {
|
||||
function f1(y) {
|
||||
do ; while (false);
|
||||
var c = 9;
|
||||
do ; while (77 === c);
|
||||
}
|
||||
function f2(y) {
|
||||
var c = 5 - y;
|
||||
@@ -409,6 +414,80 @@ collapse_vars_do_while: {
|
||||
}
|
||||
}
|
||||
|
||||
collapse_vars_do_while_drop_assign: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:false, loops:false, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
}
|
||||
input: {
|
||||
function f1(y) {
|
||||
// The constant do-while condition `c` will be not replaced.
|
||||
var c = 9;
|
||||
do {} while (c === 77);
|
||||
}
|
||||
function f2(y) {
|
||||
// The non-constant do-while condition `c` will not be replaced.
|
||||
var c = 5 - y;
|
||||
do { } while (c);
|
||||
}
|
||||
function f3(y) {
|
||||
// The constant `x` will be replaced in the do loop body.
|
||||
function fn(n) { console.log(n); }
|
||||
var a = 2, x = 7;
|
||||
do {
|
||||
fn(a = x);
|
||||
break;
|
||||
} while (y);
|
||||
}
|
||||
function f4(y) {
|
||||
// The non-constant `a` will not be replaced in the do loop body.
|
||||
var a = y / 4;
|
||||
do {
|
||||
return a;
|
||||
} while (y);
|
||||
}
|
||||
function f5(y) {
|
||||
function p(x) { console.log(x); }
|
||||
do {
|
||||
// The non-constant `a` will be replaced in p(a)
|
||||
// because it is declared in same block.
|
||||
var a = y - 3;
|
||||
p(a);
|
||||
} while (--y);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1(y) {
|
||||
var c = 9;
|
||||
do ; while (77 === c);
|
||||
}
|
||||
function f2(y) {
|
||||
var c = 5 - y;
|
||||
do ; while (c);
|
||||
}
|
||||
function f3(y) {
|
||||
function fn(n) { console.log(n); }
|
||||
do {
|
||||
fn(7);
|
||||
break;
|
||||
} while (y);
|
||||
}
|
||||
function f4(y) {
|
||||
var a = y / 4;
|
||||
do
|
||||
return a;
|
||||
while (y);
|
||||
}
|
||||
function f5(y) {
|
||||
function p(x) { console.log(x); }
|
||||
do {
|
||||
p(y - 3);
|
||||
} while (--y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collapse_vars_seq: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
@@ -567,8 +646,9 @@ collapse_vars_assignment: {
|
||||
collapse_vars_lvalues: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:"keep_assign",
|
||||
hoist_funs:true, keep_fargs:true, if_return:true, join_vars:true, cascade:true,
|
||||
side_effects:true
|
||||
}
|
||||
input: {
|
||||
function f0(x) { var i = ++x; return x += i; }
|
||||
@@ -593,7 +673,38 @@ collapse_vars_lvalues: {
|
||||
function f7(x) { var w = e1(), v = e2(), c = v - x; return (w = x) - c; }
|
||||
function f8(x) { var w = e1(), v = e2(); return (w = x) - (v - x); }
|
||||
function f9(x) { var w = e1(); return e2() - x - (w = x); }
|
||||
}
|
||||
}
|
||||
|
||||
collapse_vars_lvalues_drop_assign: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
}
|
||||
input: {
|
||||
function f0(x) { var i = ++x; return x += i; }
|
||||
function f1(x) { var a = (x -= 3); return x += a; }
|
||||
function f2(x) { var z = x, a = ++z; return z += a; }
|
||||
function f3(x) { var a = (x -= 3), b = x + a; return b; }
|
||||
function f4(x) { var a = (x -= 3); return x + a; }
|
||||
function f5(x) { var w = e1(), v = e2(), c = v = --x, b = w = x; return b - c; }
|
||||
function f6(x) { var w = e1(), v = e2(), c = v = --x, b = w = x; return c - b; }
|
||||
function f7(x) { var w = e1(), v = e2(), c = v - x, b = w = x; return b - c; }
|
||||
function f8(x) { var w = e1(), v = e2(), b = w = x, c = v - x; return b - c; }
|
||||
function f9(x) { var w = e1(), v = e2(), b = w = x, c = v - x; return c - b; }
|
||||
}
|
||||
expect: {
|
||||
function f0(x) { var i = ++x; return x += i; }
|
||||
function f1(x) { var a = (x -= 3); return x += a; }
|
||||
function f2(x) { var z = x, a = ++z; return z += a; }
|
||||
function f3(x) { var a = (x -= 3); return x + a; }
|
||||
function f4(x) { var a = (x -= 3); return x + a; }
|
||||
function f5(x) { var v = (e1(), e2()), c = v = --x; return x - c; }
|
||||
function f6(x) { e1(), e2(); return --x - x; }
|
||||
function f7(x) { var v = (e1(), e2()), c = v - x; return x - c; }
|
||||
function f8(x) { var v = (e1(), e2()); return x - (v - x); }
|
||||
function f9(x) { e1(); return e2() - x - x; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,6 +826,7 @@ collapse_vars_repeated: {
|
||||
console.log(e + "!");
|
||||
})("!");
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
collapse_vars_closures: {
|
||||
@@ -782,7 +894,8 @@ collapse_vars_unary: {
|
||||
}
|
||||
expect: {
|
||||
function f0(o, p) {
|
||||
delete o[p];
|
||||
var x = o[p];
|
||||
delete x;
|
||||
}
|
||||
function f1(n) {
|
||||
return n > +!!n
|
||||
@@ -1001,6 +1114,7 @@ collapse_vars_eval_and_with: {
|
||||
return function() { with (o) console.log(a) };
|
||||
})()();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
collapse_vars_constants: {
|
||||
@@ -1035,7 +1149,7 @@ collapse_vars_constants: {
|
||||
function f3(x) {
|
||||
var b = x.prop;
|
||||
sideeffect1();
|
||||
return b + (function() { return -9; })();
|
||||
return b + -9;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1044,7 +1158,8 @@ collapse_vars_arguments: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
toplevel:true
|
||||
}
|
||||
input: {
|
||||
var outer = function() {
|
||||
@@ -1059,6 +1174,7 @@ collapse_vars_arguments: {
|
||||
(function(){console.log(arguments);})(7, 1);
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
collapse_vars_short_circuit: {
|
||||
@@ -1203,9 +1319,275 @@ collapse_vars_regexp: {
|
||||
};
|
||||
}
|
||||
(function(){
|
||||
var result, rx = /ab*/g;
|
||||
while (result = rx.exec('acdabcdeabbb'))
|
||||
var result, s = "acdabcdeabbb", rx = /ab*/g;
|
||||
while (result = rx.exec(s))
|
||||
console.log(result[0]);
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1537: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var k = '';
|
||||
for (k in {prop: 'val'}){}
|
||||
}
|
||||
expect: {
|
||||
var k = '';
|
||||
for (k in {prop: 'val'});
|
||||
}
|
||||
}
|
||||
|
||||
issue_1562: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var v = 1, B = 2;
|
||||
for (v in objs) f(B);
|
||||
|
||||
var x = 3, C = 10;
|
||||
while(x + 2) bar(C);
|
||||
|
||||
var y = 4, D = 20;
|
||||
do bar(D); while(y + 2);
|
||||
|
||||
var z = 5, E = 30;
|
||||
for (; f(z + 2) ;) bar(E);
|
||||
}
|
||||
expect: {
|
||||
var v = 1;
|
||||
for (v in objs) f(2);
|
||||
|
||||
var x = 3;
|
||||
while(x + 2) bar(10);
|
||||
|
||||
var y = 4;
|
||||
do bar(20); while(y + 2);
|
||||
|
||||
var z = 5;
|
||||
for (; f(z + 2) ;) bar(30);
|
||||
}
|
||||
}
|
||||
|
||||
issue_1605_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: false,
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
var y = x;
|
||||
return y;
|
||||
}
|
||||
var o = new Object;
|
||||
o.p = 1;
|
||||
}
|
||||
expect: {
|
||||
function foo(x) {
|
||||
return x;
|
||||
}
|
||||
var o = new Object;
|
||||
o.p = 1;
|
||||
}
|
||||
}
|
||||
|
||||
issue_1605_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: "vars",
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
var y = x;
|
||||
return y;
|
||||
}
|
||||
var o = new Object;
|
||||
o.p = 1;
|
||||
}
|
||||
expect: {
|
||||
function foo(x) {
|
||||
return x;
|
||||
}
|
||||
(new Object).p = 1;
|
||||
}
|
||||
}
|
||||
|
||||
issue_1631_1: {
|
||||
options = {
|
||||
cascade: true,
|
||||
collapse_vars: true,
|
||||
hoist_funs: true,
|
||||
join_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var pc = 0;
|
||||
function f(x) {
|
||||
pc = 200;
|
||||
return 100;
|
||||
}
|
||||
function x() {
|
||||
var t = f();
|
||||
pc += t;
|
||||
return pc;
|
||||
}
|
||||
console.log(x());
|
||||
}
|
||||
expect: {
|
||||
function f(x) {
|
||||
return pc = 200, 100;
|
||||
}
|
||||
function x() {
|
||||
var t = f();
|
||||
return pc += t;
|
||||
}
|
||||
var pc = 0;
|
||||
console.log(x());
|
||||
}
|
||||
expect_stdout: "300"
|
||||
}
|
||||
|
||||
issue_1631_2: {
|
||||
options = {
|
||||
cascade: true,
|
||||
collapse_vars: true,
|
||||
hoist_funs: true,
|
||||
join_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a = 0, b = 1;
|
||||
function f() {
|
||||
a = 2;
|
||||
return 4;
|
||||
}
|
||||
function g() {
|
||||
var t = f();
|
||||
b = a + t;
|
||||
return b;
|
||||
}
|
||||
console.log(g());
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return a = 2, 4;
|
||||
}
|
||||
function g() {
|
||||
var t = f();
|
||||
return b = a + t;
|
||||
}
|
||||
var a = 0, b = 1;
|
||||
console.log(g());
|
||||
}
|
||||
expect_stdout: "6"
|
||||
}
|
||||
|
||||
issue_1631_3: {
|
||||
options = {
|
||||
cascade: true,
|
||||
collapse_vars: true,
|
||||
hoist_funs: true,
|
||||
join_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function g() {
|
||||
var a = 0, b = 1;
|
||||
function f() {
|
||||
a = 2;
|
||||
return 4;
|
||||
}
|
||||
var t = f();
|
||||
b = a + t;
|
||||
return b;
|
||||
}
|
||||
console.log(g());
|
||||
}
|
||||
expect: {
|
||||
function g() {
|
||||
function f() {
|
||||
return a = 2, 4;
|
||||
}
|
||||
var a = 0, b = 1, t = f();
|
||||
return b = a + t;
|
||||
}
|
||||
console.log(g());
|
||||
}
|
||||
expect_stdout: "6"
|
||||
}
|
||||
|
||||
var_side_effects_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var print = console.log.bind(console);
|
||||
function foo(x) {
|
||||
var twice = x * 2;
|
||||
print('Foo:', twice);
|
||||
}
|
||||
foo(10);
|
||||
}
|
||||
expect: {
|
||||
var print = console.log.bind(console);
|
||||
function foo(x) {
|
||||
print('Foo:', 2 * x);
|
||||
}
|
||||
foo(10);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
var_side_effects_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var print = console.log.bind(console);
|
||||
function foo(x) {
|
||||
var twice = x.y * 2;
|
||||
print('Foo:', twice);
|
||||
}
|
||||
foo({ y: 10 });
|
||||
}
|
||||
expect: {
|
||||
var print = console.log.bind(console);
|
||||
function foo(x) {
|
||||
var twice = 2 * x.y;
|
||||
print('Foo:', twice);
|
||||
}
|
||||
foo({ y: 10 });
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
var_side_effects_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: true,
|
||||
}
|
||||
input: {
|
||||
var print = console.log.bind(console);
|
||||
function foo(x) {
|
||||
var twice = x.y * 2;
|
||||
print('Foo:', twice);
|
||||
}
|
||||
foo({ y: 10 });
|
||||
}
|
||||
expect: {
|
||||
var print = console.log.bind(console);
|
||||
function foo(x) {
|
||||
print('Foo:', 2 * x.y);
|
||||
}
|
||||
foo({ y: 10 });
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -24,3 +24,200 @@ concat_1: {
|
||||
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,
|
||||
dead_code : true,
|
||||
evaluate : true,
|
||||
booleans : true
|
||||
booleans : true,
|
||||
side_effects : true,
|
||||
};
|
||||
input: {
|
||||
var x, y;
|
||||
@@ -135,16 +136,28 @@ ifs_6: {
|
||||
comparisons: true
|
||||
};
|
||||
input: {
|
||||
var x;
|
||||
var x, y;
|
||||
if (!foo && !bar && !baz && !boo) {
|
||||
x = 10;
|
||||
} else {
|
||||
x = 20;
|
||||
}
|
||||
if (y) {
|
||||
x[foo] = 10;
|
||||
} else {
|
||||
x[foo] = 20;
|
||||
}
|
||||
if (foo) {
|
||||
x[bar] = 10;
|
||||
} else {
|
||||
x[bar] = 20;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var x;
|
||||
var x, y;
|
||||
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 {
|
||||
do_something(y);
|
||||
}
|
||||
if (some_condition()) {
|
||||
side_effects(x);
|
||||
} else {
|
||||
side_effects(y);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var do_something;
|
||||
do_something(some_condition() ? x : y);
|
||||
some_condition() ? side_effects(x) : side_effects(y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,10 +232,16 @@ cond_4: {
|
||||
} else {
|
||||
do_something();
|
||||
}
|
||||
if (some_condition()) {
|
||||
side_effects();
|
||||
} else {
|
||||
side_effects();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var do_something;
|
||||
some_condition(), do_something();
|
||||
some_condition(), side_effects();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +275,8 @@ cond_5: {
|
||||
cond_7: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true
|
||||
evaluate : true,
|
||||
side_effects: true,
|
||||
};
|
||||
input: {
|
||||
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 : {
|
||||
options = {
|
||||
conditionals: true,
|
||||
@@ -874,6 +740,7 @@ issue_1154: {
|
||||
conditionals: true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
side_effects: true,
|
||||
};
|
||||
input: {
|
||||
function f1(x) { return x ? -1 : -1; }
|
||||
@@ -902,7 +769,196 @@ issue_1154: {
|
||||
function g2() { return g(), 2; }
|
||||
function g3() { return g(), -4; }
|
||||
function g4() { return g(), !1; }
|
||||
function g5() { return g(), void 0; }
|
||||
function g5() { return void g(); }
|
||||
function g6() { return g(), "number"; }
|
||||
}
|
||||
}
|
||||
|
||||
no_evaluate: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : false,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f(b) {
|
||||
a = b ? !0 : !0;
|
||||
a = b ? ~1 : ~1;
|
||||
a = b ? -2 : -2;
|
||||
a = b ? +3 : +3;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(b) {
|
||||
a = !0;
|
||||
a = ~1;
|
||||
a = -2;
|
||||
a = +3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(0/0),
|
||||
f(0/0, "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(0/0),
|
||||
f(0/0, "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"
|
||||
}
|
||||
|
||||
166
test/compress/const.js
Normal file
166
test/compress/const.js
Normal file
@@ -0,0 +1,166 @@
|
||||
issue_1191: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function foo(rot) {
|
||||
const rotTol = 5;
|
||||
if (rot < -rotTol || rot > rotTol)
|
||||
bar();
|
||||
baz();
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(rot) {
|
||||
(rot < -5 || rot > 5) && bar();
|
||||
baz();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1194: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function f1() {const a = "X"; return a + a;}
|
||||
function f2() {const aa = "X"; return aa + aa;}
|
||||
function f3() {const aaa = "X"; return aaa + aaa;}
|
||||
}
|
||||
expect: {
|
||||
function f1(){return"XX"}
|
||||
function f2(){return"XX"}
|
||||
function f3(){return"XX"}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1396: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
function foo(a) {
|
||||
const VALUE = 1;
|
||||
console.log(2 | VALUE);
|
||||
console.log(VALUE + 1);
|
||||
console.log(VALUE);
|
||||
console.log(a & VALUE);
|
||||
}
|
||||
function bar() {
|
||||
const s = "01234567890123456789";
|
||||
console.log(s + s + s + s + s);
|
||||
|
||||
const CONSTANT = "abc";
|
||||
console.log(CONSTANT + CONSTANT + CONSTANT + CONSTANT + CONSTANT);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(a) {
|
||||
console.log(3);
|
||||
console.log(2);
|
||||
console.log(1);
|
||||
console.log(1 & a);
|
||||
}
|
||||
function bar() {
|
||||
const s = "01234567890123456789";
|
||||
console.log(s + s + s + s + s);
|
||||
|
||||
console.log("abcabcabcabcabc");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unused_regexp_literal: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
}
|
||||
input: {
|
||||
function f(){ var a = /b/; }
|
||||
}
|
||||
expect: {
|
||||
function f(){}
|
||||
}
|
||||
}
|
||||
|
||||
regexp_literal_not_const: {
|
||||
options = {
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
comparisons : true,
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
side_effects : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
sequences : false,
|
||||
collapse_vars : false,
|
||||
reduce_vars : true,
|
||||
}
|
||||
input: {
|
||||
(function(){
|
||||
var result;
|
||||
const s = 'acdabcdeabbb';
|
||||
const REGEXP_LITERAL = /ab*/g;
|
||||
while (result = REGEXP_LITERAL.exec(s)) {
|
||||
console.log(result[0]);
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var result;
|
||||
const REGEXP_LITERAL = /ab*/g;
|
||||
while (result = REGEXP_LITERAL.exec("acdabcdeabbb")) console.log(result[0]);
|
||||
})();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
@@ -1,206 +1,258 @@
|
||||
dead_code_1: {
|
||||
options = {
|
||||
dead_code: true
|
||||
};
|
||||
input: {
|
||||
function f() {
|
||||
a();
|
||||
b();
|
||||
x = 10;
|
||||
return;
|
||||
if (x) {
|
||||
y();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
a();
|
||||
b();
|
||||
x = 10;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_2_should_warn: {
|
||||
options = {
|
||||
dead_code: true
|
||||
};
|
||||
input: {
|
||||
function f() {
|
||||
g();
|
||||
x = 10;
|
||||
throw "foo";
|
||||
// completely discarding the `if` would introduce some
|
||||
// bugs. UglifyJS v1 doesn't deal with this issue; in v2
|
||||
// we copy any declarations to the upper scope.
|
||||
if (x) {
|
||||
y();
|
||||
var x;
|
||||
function g(){};
|
||||
// but nested declarations should not be kept.
|
||||
(function(){
|
||||
var q;
|
||||
function y(){};
|
||||
})();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
g();
|
||||
x = 10;
|
||||
throw "foo";
|
||||
var x;
|
||||
function g(){};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_constant_boolean_should_warn_more: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
while (!((foo && bar) || (x + "0"))) {
|
||||
console.log("unreachable");
|
||||
var foo;
|
||||
function bar() {}
|
||||
}
|
||||
for (var x = 10, y; x && (y || x) && (!typeof x); ++x) {
|
||||
asdf();
|
||||
foo();
|
||||
var moo;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var foo;
|
||||
function bar() {}
|
||||
// nothing for the while
|
||||
// as for the for, it should keep:
|
||||
var x = 10, y;
|
||||
var moo;
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_const_declaration: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
const CONST_FOO = false;
|
||||
if (CONST_FOO) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
const CONST_FOO = !1;
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_const_annotation: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
/** @const */ var CONST_FOO_ANN = false;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
var CONST_FOO_ANN = !1;
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_const_annotation_regex: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
// @constraint this shouldn't be a constant
|
||||
var CONST_FOO_ANN = false;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("reachable");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
var CONST_FOO_ANN = !1;
|
||||
CONST_FOO_ANN && console.log('reachable');
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_const_annotation_complex_scope: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true
|
||||
};
|
||||
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');
|
||||
}
|
||||
}
|
||||
dead_code_1: {
|
||||
options = {
|
||||
dead_code: true
|
||||
};
|
||||
input: {
|
||||
function f() {
|
||||
a();
|
||||
b();
|
||||
x = 10;
|
||||
return;
|
||||
if (x) {
|
||||
y();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
a();
|
||||
b();
|
||||
x = 10;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_2_should_warn: {
|
||||
options = {
|
||||
dead_code: true
|
||||
};
|
||||
input: {
|
||||
function f() {
|
||||
g();
|
||||
x = 10;
|
||||
throw "foo";
|
||||
// completely discarding the `if` would introduce some
|
||||
// bugs. UglifyJS v1 doesn't deal with this issue; in v2
|
||||
// we copy any declarations to the upper scope.
|
||||
if (x) {
|
||||
y();
|
||||
var x;
|
||||
function g(){};
|
||||
// but nested declarations should not be kept.
|
||||
(function(){
|
||||
var q;
|
||||
function y(){};
|
||||
})();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
g();
|
||||
x = 10;
|
||||
throw "foo";
|
||||
var x;
|
||||
function g(){};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_constant_boolean_should_warn_more: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
side_effects : true,
|
||||
};
|
||||
input: {
|
||||
while (!((foo && bar) || (x + "0"))) {
|
||||
console.log("unreachable");
|
||||
var foo;
|
||||
function bar() {}
|
||||
}
|
||||
for (var x = 10, y; x && (y || x) && (!typeof x); ++x) {
|
||||
asdf();
|
||||
foo();
|
||||
var moo;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var foo;
|
||||
function bar() {}
|
||||
// nothing for the while
|
||||
// as for the for, it should keep:
|
||||
var x = 10, y;
|
||||
var moo;
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_const_declaration: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
const CONST_FOO = false;
|
||||
if (CONST_FOO) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
const CONST_FOO = !1;
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_const_annotation: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
toplevel : true,
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
/** @const */ var CONST_FOO_ANN = false;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
var CONST_FOO_ANN = !1;
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_const_annotation_regex: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
var unused;
|
||||
// @constraint this shouldn't be a constant
|
||||
var CONST_FOO_ANN = false;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("reachable");
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused;
|
||||
var CONST_FOO_ANN = !1;
|
||||
CONST_FOO_ANN && console.log('reachable');
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dead_code_const_annotation_complex_scope: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
reduce_vars : true,
|
||||
toplevel : true,
|
||||
};
|
||||
input: {
|
||||
var unused_var;
|
||||
/** @const */ var test = 'test';
|
||||
// @const
|
||||
var CONST_FOO_ANN = false;
|
||||
var unused_var_2;
|
||||
if (CONST_FOO_ANN) {
|
||||
console.log("unreachable");
|
||||
var moo;
|
||||
function bar() {}
|
||||
}
|
||||
if (test === 'test') {
|
||||
var beef = 'good';
|
||||
/** @const */ var meat = 'beef';
|
||||
var pork = 'bad';
|
||||
if (meat === 'pork') {
|
||||
console.log('also unreachable');
|
||||
} else if (pork === 'good') {
|
||||
console.log('reached, not const');
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var unused_var;
|
||||
var test = 'test';
|
||||
var CONST_FOO_ANN = !1;
|
||||
var unused_var_2;
|
||||
var moo;
|
||||
function bar() {}
|
||||
var beef = 'good';
|
||||
var meat = 'beef';
|
||||
var pork = 'bad';
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
try_catch_finally: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
var a = 1;
|
||||
!function() {
|
||||
try {
|
||||
if (false) throw x;
|
||||
} catch (a) {
|
||||
var a = 2;
|
||||
console.log("FAIL");
|
||||
} finally {
|
||||
a = 3;
|
||||
console.log("PASS");
|
||||
}
|
||||
}();
|
||||
try {
|
||||
console.log(a);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a = 1;
|
||||
!function() {
|
||||
var a;
|
||||
a = 3;
|
||||
console.log("PASS");
|
||||
}();
|
||||
try {
|
||||
console.log(a);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"PASS",
|
||||
"1",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
drop_console_1: {
|
||||
options = {};
|
||||
input: {
|
||||
console.log('foo');
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
expect: {
|
||||
console.log('foo');
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
drop_console_1: {
|
||||
options = { drop_console: true };
|
||||
input: {
|
||||
console.log('foo');
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
expect: {
|
||||
// with regular compression these will be stripped out as well
|
||||
void 0;
|
||||
void 0;
|
||||
}
|
||||
}
|
||||
drop_console_1: {
|
||||
options = {};
|
||||
input: {
|
||||
console.log('foo');
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
expect: {
|
||||
console.log('foo');
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
drop_console_2: {
|
||||
options = { drop_console: true };
|
||||
input: {
|
||||
console.log('foo');
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
expect: {
|
||||
// with regular compression these will be stripped out as well
|
||||
void 0;
|
||||
void 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,3 +177,800 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
const_assign: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
const b = 2;
|
||||
return 1 + b;
|
||||
}
|
||||
|
||||
function g() {
|
||||
const b = 2;
|
||||
b = 3;
|
||||
return 1 + b;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
function g() {
|
||||
const b = 2;
|
||||
b = 3;
|
||||
return 1 + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1539: {
|
||||
options = {
|
||||
cascade: true,
|
||||
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 y() {
|
||||
const y = 2;
|
||||
return y;
|
||||
}(),
|
||||
function z() {
|
||||
function z() {}
|
||||
return z;
|
||||
}()
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
console.log(
|
||||
function() {
|
||||
var x = 1;
|
||||
return x;
|
||||
}(),
|
||||
function() {
|
||||
const y = 2;
|
||||
return y;
|
||||
}(),
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -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 = 0/0;
|
||||
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") && 0/0;
|
||||
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") || 0/0;
|
||||
a = console.log("c") || 0;
|
||||
a = 2 * condition || void 0;
|
||||
a = condition + 3 || null;
|
||||
}
|
||||
}
|
||||
|
||||
unary_prefix: {
|
||||
options = {
|
||||
evaluate: true
|
||||
}
|
||||
input: {
|
||||
a = !0 && b;
|
||||
a = !0 || b;
|
||||
a = ~1 && b;
|
||||
a = ~1 || b;
|
||||
a = -2 && b;
|
||||
a = -2 || b;
|
||||
a = +3 && b;
|
||||
a = +3 || b;
|
||||
}
|
||||
expect: {
|
||||
a = b;
|
||||
a = !0;
|
||||
a = b;
|
||||
a = -2;
|
||||
a = b;
|
||||
a = -2;
|
||||
a = b;
|
||||
a = 3;
|
||||
}
|
||||
}
|
||||
|
||||
negative_zero: {
|
||||
options = { evaluate: true }
|
||||
input: {
|
||||
@@ -12,10 +196,11 @@ negative_zero: {
|
||||
console.log(
|
||||
-0,
|
||||
0,
|
||||
1 / (-0),
|
||||
1 / (-0)
|
||||
-1/0,
|
||||
-1/0
|
||||
);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
positive_zero: {
|
||||
@@ -32,8 +217,588 @@ positive_zero: {
|
||||
console.log(
|
||||
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,
|
||||
0/0,
|
||||
"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,
|
||||
}
|
||||
input: {
|
||||
const a = 1;
|
||||
console.log(a);
|
||||
+function(a) {
|
||||
return a;
|
||||
}(a);
|
||||
}
|
||||
expect: {
|
||||
const a = 1;
|
||||
console.log(1);
|
||||
+(1, 1);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
call_args_drop_param: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
keep_fargs: false,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
const a = 1;
|
||||
console.log(a);
|
||||
+function(a) {
|
||||
return a;
|
||||
}(a, b);
|
||||
}
|
||||
expect: {
|
||||
const a = 1;
|
||||
console.log(1);
|
||||
+(b, 1);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
95
test/compress/functions.js
Normal file
95
test/compress/functions.js
Normal file
@@ -0,0 +1,95 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
147
test/compress/global_defs.js
Normal file
147
test/compress/global_defs.js
Normal file
@@ -0,0 +1,147 @@
|
||||
must_replace: {
|
||||
options = {
|
||||
global_defs: {
|
||||
D: "foo bar",
|
||||
}
|
||||
}
|
||||
input: {
|
||||
console.log(D);
|
||||
}
|
||||
expect: {
|
||||
console.log("foo bar");
|
||||
}
|
||||
}
|
||||
|
||||
keyword: {
|
||||
options = {
|
||||
global_defs: {
|
||||
undefined: 0,
|
||||
NaN: 1,
|
||||
Infinity: 2,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
console.log(undefined, NaN, Infinity);
|
||||
}
|
||||
expect: {
|
||||
console.log(0, 1, 2);
|
||||
}
|
||||
}
|
||||
|
||||
object: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
global_defs: {
|
||||
CONFIG: {
|
||||
DEBUG: [ 0 ],
|
||||
VALUE: 42,
|
||||
},
|
||||
},
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
function f(CONFIG) {
|
||||
// CONFIG not global - do not replace
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function g() {
|
||||
var CONFIG = { VALUE: 1 };
|
||||
// CONFIG not global - do not replace
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function h() {
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
if (CONFIG.DEBUG[0])
|
||||
console.debug("foo");
|
||||
}
|
||||
expect: {
|
||||
function f(CONFIG) {
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function g() {
|
||||
var CONFIG = { VALUE: 1 };
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function h() {
|
||||
return 42;
|
||||
}
|
||||
if (0)
|
||||
console.debug("foo");
|
||||
}
|
||||
}
|
||||
|
||||
expanded: {
|
||||
options = {
|
||||
global_defs: {
|
||||
"CONFIG.DEBUG": [ 0 ],
|
||||
"CONFIG.VALUE": 42,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
function f(CONFIG) {
|
||||
// CONFIG not global - do not replace
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function g() {
|
||||
var CONFIG = { VALUE: 1 };
|
||||
// CONFIG not global - do not replace
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function h() {
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
if (CONFIG.DEBUG[0])
|
||||
console.debug("foo");
|
||||
}
|
||||
expect: {
|
||||
function f(CONFIG) {
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function g() {
|
||||
var CONFIG = { VALUE: 1 };
|
||||
return CONFIG.VALUE;
|
||||
}
|
||||
function h() {
|
||||
return 42;
|
||||
}
|
||||
if ([0][0])
|
||||
console.debug("foo");
|
||||
}
|
||||
}
|
||||
|
||||
mixed: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
global_defs: {
|
||||
"CONFIG.VALUE": 42,
|
||||
"FOO.BAR": "moo",
|
||||
},
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
const FOO = { BAR: 0 };
|
||||
console.log(FOO.BAR);
|
||||
console.log(++CONFIG.DEBUG);
|
||||
console.log(++CONFIG.VALUE);
|
||||
console.log(++CONFIG["VAL" + "UE"]);
|
||||
console.log(++DEBUG[CONFIG.VALUE]);
|
||||
CONFIG.VALUE.FOO = "bar";
|
||||
console.log(CONFIG);
|
||||
}
|
||||
expect: {
|
||||
const FOO = { BAR: 0 };
|
||||
console.log("moo");
|
||||
console.log(++CONFIG.DEBUG);
|
||||
console.log(++CONFIG.VALUE);
|
||||
console.log(++CONFIG.VALUE);
|
||||
console.log(++DEBUG[42]);
|
||||
CONFIG.VALUE.FOO = "bar";
|
||||
console.log(CONFIG);
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:126,22]',
|
||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]',
|
||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:129,8]',
|
||||
]
|
||||
}
|
||||
90
test/compress/hoist_vars.js
Normal file
90
test/compress/hoist_vars.js
Normal file
@@ -0,0 +1,90 @@
|
||||
statements: {
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a = 1;
|
||||
var b = 2;
|
||||
var c = 3;
|
||||
function g() {}
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
var a = 1, b = 2, c = 3;
|
||||
function g() {}
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
statements_funs: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a = 1;
|
||||
var b = 2;
|
||||
var c = 3;
|
||||
function g() {}
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
function g() {}
|
||||
var a = 1, b = 2, c = 3;
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sequences: {
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a = 1, b = 2;
|
||||
function g() {}
|
||||
var c = 3;
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
var c, a = 1, b = 2;
|
||||
function g() {}
|
||||
c = 3;
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sequences_funs: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
hoist_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
var a = 1, b = 2;
|
||||
function g() {}
|
||||
var c = 3;
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
function g() {}
|
||||
var a = 1, b = 2, c = 3;
|
||||
return g(a, b, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,22 +47,6 @@ html_comment_in_greater_than_or_equal: {
|
||||
expect_exact: "function f(a,b){return a-- >=b}";
|
||||
}
|
||||
|
||||
html_comment_in_right_shift_assign: {
|
||||
input: {
|
||||
// Note: illegal javascript
|
||||
function f(a, b) { return a-- >>= b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >>=b}";
|
||||
}
|
||||
|
||||
html_comment_in_zero_fill_right_shift_assign: {
|
||||
input: {
|
||||
// Note: illegal javascript
|
||||
function f(a, b) { return a-- >>>= b; }
|
||||
}
|
||||
expect_exact: "function f(a,b){return a-- >>>=b}";
|
||||
}
|
||||
|
||||
html_comment_in_string_literal: {
|
||||
input: {
|
||||
function f() { return "<!--HTML-->comment in<!--string literal-->"; }
|
||||
|
||||
@@ -170,8 +170,51 @@ if_return_7: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
// suboptimal
|
||||
function f(x){return!!x||(foo(),void bar())}
|
||||
function f(x){if(x)return!0;foo(),bar()}
|
||||
}
|
||||
}
|
||||
|
||||
if_return_8: {
|
||||
options = {
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
side_effects : true,
|
||||
}
|
||||
input: {
|
||||
function f(e) {
|
||||
if (2 == e) return foo();
|
||||
if (3 == e) return bar();
|
||||
if (4 == e) return baz();
|
||||
fail(e);
|
||||
}
|
||||
|
||||
function g(e) {
|
||||
if (a(e)) return foo();
|
||||
if (b(e)) return bar();
|
||||
if (c(e)) return baz();
|
||||
fail(e);
|
||||
}
|
||||
|
||||
function h(e) {
|
||||
if (a(e)) return foo();
|
||||
else if (b(e)) return bar();
|
||||
else if (c(e)) return baz();
|
||||
else fail(e);
|
||||
}
|
||||
|
||||
function i(e) {
|
||||
if (a(e)) return foo();
|
||||
else if (b(e)) return bar();
|
||||
else if (c(e)) return baz();
|
||||
fail(e);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(e){return 2==e?foo():3==e?bar():4==e?baz():void fail(e)}
|
||||
function g(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
|
||||
function h(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
|
||||
function i(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
||||
if_return: true, join_vars: true, cascade: true, side_effects: true,
|
||||
collapse_vars: false, passes: 2
|
||||
collapse_vars: false, passes: 2, warnings: "verbose"
|
||||
}
|
||||
input: {
|
||||
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: Dropping unreachable code [test/compress/issue-1034.js:56,12]",
|
||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]",
|
||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]"
|
||||
"WARN: Dropping 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: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]",
|
||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:95,20]",
|
||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:97,16]"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@ const_declaration: {
|
||||
|
||||
const_pragma: {
|
||||
options = {
|
||||
evaluate: true
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
};
|
||||
|
||||
input: {
|
||||
@@ -27,7 +28,8 @@ const_pragma: {
|
||||
// for completeness' sake
|
||||
not_const: {
|
||||
options = {
|
||||
evaluate: true
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
};
|
||||
|
||||
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 }
|
||||
}
|
||||
@@ -195,11 +195,12 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
|
||||
sequences: false,
|
||||
}
|
||||
input: {
|
||||
var f = console.log;
|
||||
var o = {
|
||||
undefined : 3,
|
||||
NaN : 4,
|
||||
Infinity : 5,
|
||||
}
|
||||
};
|
||||
if (o) {
|
||||
f(undefined, void 0);
|
||||
f(NaN, 0/0);
|
||||
@@ -216,25 +217,25 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
var f = console.log, o = {
|
||||
undefined : 3,
|
||||
NaN : 4,
|
||||
Infinity : 5
|
||||
}
|
||||
};
|
||||
if (o) {
|
||||
f(void 0, void 0);
|
||||
f(NaN, NaN);
|
||||
f(0/0, 0/0);
|
||||
f(1/0, 1/0);
|
||||
f(-(1/0), -(1/0));
|
||||
f(NaN, NaN);
|
||||
f(-1/0, -1/0);
|
||||
f(0/0, 0/0);
|
||||
}
|
||||
with (o) {
|
||||
f(undefined, void 0);
|
||||
f(NaN, 0/0);
|
||||
f(Infinity, 1/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: Boolean || always true [test/compress/issue-1261.js:130,8]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:130,8]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:131,23]",
|
||||
"WARN: Boolean && always false [test/compress/issue-1261.js:132,8]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:132,8]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:133,23]",
|
||||
"WARN: + in boolean context always true [test/compress/issue-1261.js:134,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:134,31]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:134,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,24]",
|
||||
"WARN: Condition always true [test/compress/issue-1261.js:136,8]",
|
||||
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,31]",
|
||||
"WARN: Condition always false [test/compress/issue-1261.js:137,8]",
|
||||
]
|
||||
}
|
||||
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 = {
|
||||
ignore_quoted: true
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
x.foo = 1;
|
||||
x["a"] = 2 * x.foo;
|
||||
console.log(x.foo, x["a"]);
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.b = 1;
|
||||
x["a"] = 2 * x.b;
|
||||
console.log(x.b, x["a"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1321_debug: {
|
||||
mangle_props = {
|
||||
ignore_quoted: true,
|
||||
debug: ""
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
x.foo = 1;
|
||||
x["_$foo$_"] = 2 * x.foo;
|
||||
console.log(x.foo, x["_$foo$_"]);
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.a = 1;
|
||||
x["_$foo$_"] = 2 * x.a;
|
||||
console.log(x.a, x["_$foo$_"]);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1321_with_quoted: {
|
||||
mangle_props = {
|
||||
ignore_quoted: false
|
||||
}
|
||||
input: {
|
||||
var x = {};
|
||||
x.foo = 1;
|
||||
x["a"] = 2 * x.foo;
|
||||
console.log(x.foo, x["a"]);
|
||||
}
|
||||
expect: {
|
||||
var x = {};
|
||||
x.a = 1;
|
||||
x["b"] = 2 * x.a;
|
||||
console.log(x.a, x["b"]);
|
||||
}
|
||||
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,
|
||||
screw_ie8: false
|
||||
}
|
||||
input: {
|
||||
var a = typeof b != "undefined";
|
||||
b = typeof a != "undefined";
|
||||
var c = typeof d.e !== "undefined";
|
||||
var f = "undefined" === typeof g;
|
||||
g = "undefined" === typeof f;
|
||||
var h = "undefined" == typeof i.j;
|
||||
}
|
||||
expect: {
|
||||
var a = "undefined" != typeof b;
|
||||
b = void 0 !== a;
|
||||
var c = "undefined" != typeof d.e;
|
||||
var f = "undefined" == typeof g;
|
||||
g = void 0 === f;
|
||||
var h = "undefined" == typeof i.j;
|
||||
}
|
||||
}
|
||||
|
||||
undefined_redefined: {
|
||||
options = {
|
||||
comparisons: true
|
||||
}
|
||||
input: {
|
||||
function f(undefined) {
|
||||
var n = 1;
|
||||
return typeof n == "undefined";
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(undefined){var n=1;return void 0===n}"
|
||||
}
|
||||
|
||||
undefined_redefined_mangle: {
|
||||
options = {
|
||||
comparisons: true
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
function f(undefined) {
|
||||
var n = 1;
|
||||
return typeof n == "undefined";
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(n){var r=1;return void 0===r}"
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
99
test/compress/issue-1588.js
Normal file
99
test/compress/issue-1588.js
Normal file
@@ -0,0 +1,99 @@
|
||||
screw_ie8: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: true,
|
||||
}
|
||||
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 = {
|
||||
screw_ie8: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
runtime_error: {
|
||||
input: {
|
||||
const a = 1;
|
||||
console.log(a++);
|
||||
}
|
||||
expect: {
|
||||
const a = 1;
|
||||
console.log(a++);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
56
test/compress/issue-1609.js
Normal file
56
test/compress/issue-1609.js
Normal file
@@ -0,0 +1,56 @@
|
||||
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() {
|
||||
var c;
|
||||
c = f(1);
|
||||
c.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() {
|
||||
var a = "long piece of string";
|
||||
(function() {
|
||||
var c;
|
||||
c = f(a);
|
||||
c.bar = a;
|
||||
})();
|
||||
})();
|
||||
}
|
||||
}
|
||||
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 a = 100, b = 10;",
|
||||
"",
|
||||
"!function() {",
|
||||
" for (;b = a, !1; ) ;",
|
||||
"}(), console.log(a, 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 = {
|
||||
screw_ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_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(o){a="PASS"}console.log(a);'
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
mangle_catch_ie8: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_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(args){a="PASS"}console.log(a);'
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
mangle_catch_var: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_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(o){var a="PASS"}console.log(a);'
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
mangle_catch_var_ie8: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_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(args){var a="PASS"}console.log(a);'
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
mangle_catch_toplevel: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_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_ie8_toplevel: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_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_var_toplevel: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_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_var_ie8_toplevel: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_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_redef_1: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_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_ie8: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_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_toplevel: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_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_1_ie8_toplevel: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_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_2: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_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_ie8: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
toplevel: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_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_toplevel: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_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"
|
||||
}
|
||||
|
||||
mangle_catch_redef_2_ie8_toplevel: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
toplevel: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_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"
|
||||
}
|
||||
97
test/compress/issue-1733.js
Normal file
97
test/compress/issue-1733.js
Normal file
@@ -0,0 +1,97 @@
|
||||
function_iife_catch: {
|
||||
mangle = {
|
||||
screw_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(c){var o=1;console.log(c,o)}}()}f();"
|
||||
expect_stdout: "0 1"
|
||||
}
|
||||
|
||||
function_iife_catch_ie8: {
|
||||
mangle = {
|
||||
screw_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(o){var c=1;console.log(o,c)}}()}f();"
|
||||
expect_stdout: "0 1"
|
||||
}
|
||||
|
||||
function_catch_catch: {
|
||||
mangle = {
|
||||
screw_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",
|
||||
]
|
||||
}
|
||||
|
||||
function_catch_catch_ie8: {
|
||||
mangle = {
|
||||
screw_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",
|
||||
]
|
||||
}
|
||||
@@ -1,11 +1,70 @@
|
||||
do_not_update_lhs: {
|
||||
options = { global_defs: { DEBUG: false } };
|
||||
input: { DEBUG = false; }
|
||||
expect: { DEBUG = false; }
|
||||
options = {
|
||||
global_defs: { DEBUG: 0 }
|
||||
}
|
||||
input: {
|
||||
DEBUG++;
|
||||
DEBUG += 1;
|
||||
DEBUG = 1;
|
||||
}
|
||||
expect: {
|
||||
DEBUG++;
|
||||
DEBUG += 1;
|
||||
DEBUG = 1;
|
||||
}
|
||||
}
|
||||
|
||||
do_update_rhs: {
|
||||
options = { global_defs: { DEBUG: false } };
|
||||
input: { MY_DEBUG = DEBUG; }
|
||||
expect: { MY_DEBUG = false; }
|
||||
options = {
|
||||
global_defs: { DEBUG: 0 }
|
||||
}
|
||||
input: {
|
||||
MY_DEBUG = DEBUG;
|
||||
MY_DEBUG += DEBUG;
|
||||
}
|
||||
expect: {
|
||||
MY_DEBUG = 0;
|
||||
MY_DEBUG += 0;
|
||||
}
|
||||
}
|
||||
|
||||
mixed: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
global_defs: {
|
||||
DEBUG: 0,
|
||||
ENV: 1,
|
||||
FOO: 2,
|
||||
}
|
||||
}
|
||||
input: {
|
||||
const ENV = 3;
|
||||
var FOO = 4;
|
||||
f(ENV * 10);
|
||||
--FOO;
|
||||
DEBUG = 1;
|
||||
DEBUG++;
|
||||
DEBUG += 1;
|
||||
f(DEBUG);
|
||||
x = DEBUG;
|
||||
}
|
||||
expect: {
|
||||
const ENV = 3;
|
||||
var FOO = 4;
|
||||
f(10);
|
||||
--FOO;
|
||||
DEBUG = 1;
|
||||
DEBUG++;
|
||||
DEBUG += 1;
|
||||
f(0);
|
||||
x = 0;
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,14]',
|
||||
'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]',
|
||||
'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]',
|
||||
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]',
|
||||
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:46,8]',
|
||||
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:47,8]',
|
||||
]
|
||||
}
|
||||
|
||||
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: {
|
||||
(1/0).toString();
|
||||
NaN.toString(); // transformation to 0/0 dropped
|
||||
(0/0).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,3 +23,105 @@ NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: {
|
||||
NaN.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(true) : console.log(false), 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 })() ? foo(true) : bar(false), 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 })() ? foo(true) : bar(false), 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);
|
||||
}
|
||||
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: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
};
|
||||
input: {
|
||||
var c = a; c();
|
||||
|
||||
@@ -42,6 +42,7 @@ eval_collapse_vars: {
|
||||
eval("console.log(a);");
|
||||
})(eval);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
eval_unused: {
|
||||
|
||||
@@ -82,7 +82,7 @@ issue979_test_negated_is_best: {
|
||||
1!=a||2!=b||foo();
|
||||
}
|
||||
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: {
|
||||
foo || console.log("bar");
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
labels_2: {
|
||||
@@ -40,6 +41,7 @@ labels_3: {
|
||||
for (var i = 0; i < 5; ++i)
|
||||
i < 3 || console.log(i);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
labels_4: {
|
||||
@@ -54,6 +56,7 @@ labels_4: {
|
||||
for (var i = 0; i < 5; ++i)
|
||||
i < 3 || console.log(i);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
labels_5: {
|
||||
|
||||
@@ -166,6 +166,7 @@ keep_collapse_const_in_own_block_scope: {
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
keep_collapse_const_in_own_block_scope_2: {
|
||||
@@ -186,4 +187,274 @@ keep_collapse_const_in_own_block_scope_2: {
|
||||
console.log(i);
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
evaluate: {
|
||||
options = {
|
||||
loops: true,
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
};
|
||||
input: {
|
||||
while (true) {
|
||||
a();
|
||||
}
|
||||
while (false) {
|
||||
b();
|
||||
}
|
||||
do {
|
||||
c();
|
||||
} while (true);
|
||||
do {
|
||||
d();
|
||||
} while (false);
|
||||
}
|
||||
expect: {
|
||||
for(;;)
|
||||
a();
|
||||
for(;;)
|
||||
c();
|
||||
// rule disabled due to issue_1532
|
||||
do d(); while (false);
|
||||
}
|
||||
}
|
||||
|
||||
issue_1532: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
function f(x, y) {
|
||||
do {
|
||||
if (x) break;
|
||||
foo();
|
||||
} while (false);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f(x, y) {
|
||||
do {
|
||||
if (x) break;
|
||||
foo();
|
||||
} while (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_186: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
screw_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_ie8: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
screw_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: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
screw_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_ie8: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
screw_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: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
bracketize: true,
|
||||
screw_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_ie8: {
|
||||
beautify = {
|
||||
beautify: false,
|
||||
bracketize: true,
|
||||
screw_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: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
bracketize: true,
|
||||
screw_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_ie8: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
bracketize: true,
|
||||
screw_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_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;);}"
|
||||
}
|
||||
|
||||
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,6 +10,16 @@ negate_iife_1: {
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_1_off: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
};
|
||||
input: {
|
||||
(function(){ stuff() })();
|
||||
}
|
||||
expect_exact: '(function(){stuff()})();'
|
||||
}
|
||||
|
||||
negate_iife_2: {
|
||||
options = {
|
||||
negate_iife: true
|
||||
@@ -22,44 +32,151 @@ negate_iife_2: {
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_3: {
|
||||
negate_iife_2_side_effects: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
};
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
(function(){ return {} })().x = 10; // should not transform this one
|
||||
}
|
||||
expect: {
|
||||
!function(){ return true }() ? console.log(false) : console.log(true);
|
||||
(function(){ return {} })().x = 10;
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_3: {
|
||||
options = {
|
||||
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: {
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
}
|
||||
expect: {
|
||||
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_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 = {
|
||||
negate_iife: true,
|
||||
conditionals: true,
|
||||
sequences: true
|
||||
};
|
||||
input: {
|
||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
||||
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||
(function(){
|
||||
console.log("something");
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
!function(){ return true }() ? console.log(false) : console.log(true), function(){
|
||||
!function(){ return t }() ? console.log(false) : console.log(true), function(){
|
||||
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 = {
|
||||
negate_iife: true,
|
||||
sequences: true,
|
||||
conditionals: true,
|
||||
};
|
||||
input: {
|
||||
if ((function(){ return true })()) {
|
||||
if ((function(){ return t })()) {
|
||||
foo(true);
|
||||
} else {
|
||||
bar(false);
|
||||
@@ -69,7 +186,30 @@ negate_iife_4: {
|
||||
})();
|
||||
}
|
||||
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");
|
||||
}();
|
||||
}
|
||||
@@ -105,6 +245,40 @@ negate_iife_nested: {
|
||||
}(7);
|
||||
}).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: {
|
||||
@@ -129,4 +303,116 @@ negate_iife_issue_1073: {
|
||||
};
|
||||
}(7))();
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1254_negate_iife_false: {
|
||||
options = {
|
||||
negate_iife: false,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
return function() {
|
||||
console.log('test')
|
||||
};
|
||||
})()();
|
||||
}
|
||||
expect_exact: '(function(){return function(){console.log("test")}})()();'
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
issue_1254_negate_iife_true: {
|
||||
options = {
|
||||
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 = {
|
||||
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);"
|
||||
}
|
||||
|
||||
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);"
|
||||
}
|
||||
|
||||
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, 0/0, 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
|
||||
}
|
||||
|
||||
@@ -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[0/0] = 6;
|
||||
a[null] = 7;
|
||||
a[void 0] = 8;
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_array_length: {
|
||||
options = {
|
||||
properties: true,
|
||||
unsafe: true,
|
||||
evaluate: true
|
||||
};
|
||||
input: {
|
||||
a = [1, 2, 3].length;
|
||||
a = [1, 2, 3].join()["len" + "gth"];
|
||||
a = [1, 2, b].length;
|
||||
a = [1, 2, 3].join(b).length;
|
||||
}
|
||||
expect: {
|
||||
a = 3;
|
||||
a = 5;
|
||||
a = [1, 2, b].length;
|
||||
a = [1, 2, 3].join(b).length;
|
||||
}
|
||||
}
|
||||
|
||||
evaluate_string_length: {
|
||||
options = {
|
||||
properties: true,
|
||||
unsafe: true,
|
||||
@@ -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_ignore_quoted: {
|
||||
options = {
|
||||
properties: false
|
||||
}
|
||||
mangle_props = {
|
||||
ignore_quoted: true,
|
||||
debug: "XYZ",
|
||||
reserved: []
|
||||
}
|
||||
beautify = {
|
||||
beautify: false,
|
||||
quote_style: 3,
|
||||
keep_quoted_props: true,
|
||||
}
|
||||
input: {
|
||||
a.top = 1;
|
||||
function f1() {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
a.stuff = 2;
|
||||
x = {"bar": 10, size: 7};
|
||||
a.size = 9;
|
||||
}
|
||||
function f2() {
|
||||
a.foo = "bar";
|
||||
a['color'] = "red";
|
||||
x = {bar: 10, size: 7};
|
||||
a.size = 9;
|
||||
a.stuff = 3;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
a._$top$XYZ_ = 1;
|
||||
function f1() {
|
||||
a["foo"] = "bar";
|
||||
a.color = "red";
|
||||
a._$stuff$XYZ_ = 2;
|
||||
x = {"bar": 10, _$size$XYZ_: 7};
|
||||
a._$size$XYZ_ = 9;
|
||||
}
|
||||
function f2() {
|
||||
a.foo = "bar";
|
||||
a['color'] = "red";
|
||||
x = {bar: 10, _$size$XYZ_: 7};
|
||||
a._$size$XYZ_ = 9;
|
||||
a._$stuff$XYZ_ = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
first_256_chars_as_properties: {
|
||||
beautify = {
|
||||
ascii_only: true,
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
1856
test/compress/reduce_vars.js
Normal file
1856
test/compress/reduce_vars.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,233 @@
|
||||
do_screw: {
|
||||
options = { screw_ie8: true };
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
}
|
||||
beautify = {
|
||||
screw_ie8: true,
|
||||
ascii_only: true
|
||||
};
|
||||
|
||||
input: f("\v");
|
||||
expect_exact: 'f("\\v");';
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
f("\v");
|
||||
}
|
||||
expect_exact: 'f("\\v");'
|
||||
}
|
||||
|
||||
dont_screw: {
|
||||
options = { screw_ie8: false };
|
||||
beautify = { screw_ie8: false, ascii_only: true };
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
}
|
||||
beautify = {
|
||||
screw_ie8: false,
|
||||
ascii_only: true,
|
||||
}
|
||||
input: {
|
||||
f("\v");
|
||||
}
|
||||
expect_exact: 'f("\\x0B");'
|
||||
}
|
||||
|
||||
input: f("\v");
|
||||
expect_exact: 'f("\\x0B");';
|
||||
}
|
||||
do_screw_constants: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
}
|
||||
input: {
|
||||
f(undefined, Infinity);
|
||||
}
|
||||
expect_exact: "f(void 0,1/0);"
|
||||
}
|
||||
|
||||
dont_screw_constants: {
|
||||
options = {
|
||||
screw_ie8: false,
|
||||
}
|
||||
input: {
|
||||
f(undefined, Infinity);
|
||||
}
|
||||
expect_exact: "f(undefined,Infinity);"
|
||||
}
|
||||
|
||||
do_screw_try_catch: {
|
||||
options = { screw_ie8: true };
|
||||
mangle = { screw_ie8: true };
|
||||
beautify = { screw_ie8: true };
|
||||
input: {
|
||||
good = function(e){
|
||||
return function(error){
|
||||
try{
|
||||
e()
|
||||
} catch(e) {
|
||||
error(e)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
good = function(n){
|
||||
return function(t){
|
||||
try{
|
||||
n()
|
||||
} catch(n) {
|
||||
t(n)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
dont_screw_try_catch: {
|
||||
options = { screw_ie8: false };
|
||||
mangle = { screw_ie8: false };
|
||||
beautify = { screw_ie8: false };
|
||||
input: {
|
||||
bad = function(e){
|
||||
return function(error){
|
||||
try{
|
||||
e()
|
||||
} catch(e) {
|
||||
error(e)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
bad = function(n){
|
||||
return function(t){
|
||||
try{
|
||||
n()
|
||||
} catch(n) {
|
||||
t(n)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
do_screw_try_catch_undefined: {
|
||||
options = { screw_ie8: true };
|
||||
mangle = { screw_ie8: true };
|
||||
beautify = { screw_ie8: true };
|
||||
input: {
|
||||
function a(b){
|
||||
try {
|
||||
throw 'Stuff';
|
||||
} catch (undefined) {
|
||||
console.log('caught: ' + undefined);
|
||||
}
|
||||
console.log('undefined is ' + undefined);
|
||||
return b === undefined;
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
function a(o){
|
||||
try{
|
||||
throw "Stuff"
|
||||
} catch (o) {
|
||||
console.log("caught: "+o)
|
||||
}
|
||||
console.log("undefined is " + void 0);
|
||||
return void 0===o
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
dont_screw_try_catch_undefined: {
|
||||
options = { screw_ie8: false };
|
||||
mangle = { screw_ie8: false };
|
||||
beautify = { screw_ie8: false };
|
||||
input: {
|
||||
function a(b){
|
||||
try {
|
||||
throw 'Stuff';
|
||||
} catch (undefined) {
|
||||
console.log('caught: ' + undefined);
|
||||
}
|
||||
console.log('undefined is ' + undefined);
|
||||
return b === undefined;
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
function a(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,
|
||||
screw_ie8: false,
|
||||
unused: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
}
|
||||
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 = {
|
||||
screw_ie8: false,
|
||||
}
|
||||
mangle = {
|
||||
screw_ie8: false,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
try {
|
||||
x();
|
||||
} catch (err) {
|
||||
console.log(err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect_exact: "function f(){try{x()}catch(c){console.log(c.message)}}"
|
||||
}
|
||||
|
||||
issue_1586_2: {
|
||||
options = {
|
||||
screw_ie8: true,
|
||||
}
|
||||
mangle = {
|
||||
screw_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)}}"
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ make_sequences_4: {
|
||||
switch (x = 5, y) {}
|
||||
with (x = 5, obj);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
lift_sequences_1: {
|
||||
@@ -103,15 +104,18 @@ lift_sequences_1: {
|
||||
lift_sequences_2: {
|
||||
options = { sequences: true, evaluate: true };
|
||||
input: {
|
||||
var foo, bar;
|
||||
var foo = 1, bar;
|
||||
foo.x = (foo = {}, 10);
|
||||
bar = (bar = {}, 10);
|
||||
console.log(foo, bar);
|
||||
}
|
||||
expect: {
|
||||
var foo, bar;
|
||||
var foo = 1, bar;
|
||||
foo.x = (foo = {}, 10),
|
||||
bar = {}, bar = 10;
|
||||
bar = {}, bar = 10,
|
||||
console.log(foo, bar);
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
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: {
|
||||
options = { sequences: true };
|
||||
input: {
|
||||
@@ -169,3 +190,253 @@ for_sequences: {
|
||||
for (y = 5; false;);
|
||||
}
|
||||
}
|
||||
|
||||
limit_1: {
|
||||
options = {
|
||||
sequences: 3,
|
||||
};
|
||||
input: {
|
||||
a;
|
||||
b;
|
||||
c;
|
||||
d;
|
||||
e;
|
||||
f;
|
||||
g;
|
||||
h;
|
||||
i;
|
||||
j;
|
||||
k;
|
||||
}
|
||||
expect: {
|
||||
a, b, c;
|
||||
d, e, f;
|
||||
g, h, i;
|
||||
j, k;
|
||||
}
|
||||
}
|
||||
|
||||
limit_2: {
|
||||
options = {
|
||||
sequences: 3,
|
||||
};
|
||||
input: {
|
||||
a, b;
|
||||
c, d;
|
||||
e, f;
|
||||
g, h;
|
||||
i, j;
|
||||
k;
|
||||
}
|
||||
expect: {
|
||||
a, b, c, d;
|
||||
e, f, g, h;
|
||||
i, j, k;
|
||||
}
|
||||
}
|
||||
|
||||
negate_iife_for: {
|
||||
options = {
|
||||
sequences: true,
|
||||
negate_iife: true,
|
||||
};
|
||||
input: {
|
||||
(function() {})();
|
||||
for (i = 0; i < 5; i++) console.log(i);
|
||||
|
||||
(function() {})();
|
||||
for (; i < 5; i++) console.log(i);
|
||||
}
|
||||
expect: {
|
||||
for (!function() {}(), i = 0; i < 5; i++) console.log(i);
|
||||
for (function() {}(); i < 5; i++) console.log(i);
|
||||
}
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -258,3 +258,466 @@ keep_default: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_1663: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: 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,
|
||||
}
|
||||
input: {
|
||||
switch (foo) {
|
||||
case 'bar': baz(); break;
|
||||
case 'moo':
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
switch (foo) {
|
||||
case 'bar': baz();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keep_case: {
|
||||
options = {
|
||||
dead_code: 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,
|
||||
}
|
||||
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,
|
||||
}
|
||||
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,
|
||||
}
|
||||
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,
|
||||
}
|
||||
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,
|
||||
}
|
||||
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,
|
||||
}
|
||||
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,
|
||||
}
|
||||
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,
|
||||
}
|
||||
input: {
|
||||
switch (console.log("PASS")) {}
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_1690_2: {
|
||||
options = {
|
||||
dead_code: false,
|
||||
}
|
||||
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,
|
||||
}
|
||||
input: {
|
||||
if (a) switch(typeof b) {}
|
||||
}
|
||||
expect: {
|
||||
a;
|
||||
}
|
||||
}
|
||||
|
||||
issue_1698: {
|
||||
options = {
|
||||
side_effects: 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,
|
||||
}
|
||||
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,
|
||||
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,
|
||||
}
|
||||
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;",
|
||||
"}",
|
||||
]
|
||||
}
|
||||
|
||||
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';
|
||||
}
|
||||
}
|
||||
|
||||
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")})()})()();'
|
||||
}
|
||||
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/eof.js
Normal file
1
test/input/invalid/eof.js
Normal file
@@ -0,0 +1 @@
|
||||
foo, bar(
|
||||
1
test/input/invalid/loop-no-body.js
Normal file
1
test/input/invalid/loop-no-body.js
Normal file
@@ -0,0 +1 @@
|
||||
for (var i = 0; i < 1; i++)
|
||||
1
test/input/invalid/simple.js
Normal file
1
test/input/invalid/simple.js
Normal file
@@ -0,0 +1 @@
|
||||
function f(a{}
|
||||
1
test/input/invalid/tab.js
Normal file
1
test/input/invalid/tab.js
Normal file
@@ -0,0 +1 @@
|
||||
foo( xyz, 0abc);
|
||||
7
test/input/issue-1323/sample.js
Normal file
7
test/input/issue-1323/sample.js
Normal file
@@ -0,0 +1,7 @@
|
||||
var bar = (function () {
|
||||
function foo (bar) {
|
||||
return bar;
|
||||
}
|
||||
|
||||
return foo;
|
||||
})();
|
||||
14
test/input/issue-1431/sample.js
Normal file
14
test/input/issue-1431/sample.js
Normal file
@@ -0,0 +1,14 @@
|
||||
function f(x) {
|
||||
return function() {
|
||||
function n(a) {
|
||||
return a * a;
|
||||
}
|
||||
return x(n);
|
||||
};
|
||||
}
|
||||
|
||||
function g(op) {
|
||||
return op(1) + op(2);
|
||||
}
|
||||
|
||||
console.log(f(g)() == 5);
|
||||
73
test/input/issue-1482/bracketize.js
Normal file
73
test/input/issue-1482/bracketize.js
Normal file
@@ -0,0 +1,73 @@
|
||||
if (x) {
|
||||
foo();
|
||||
}
|
||||
|
||||
if (x) {
|
||||
foo();
|
||||
} else {
|
||||
baz();
|
||||
}
|
||||
|
||||
if (x) {
|
||||
foo();
|
||||
} else if (y) {
|
||||
bar();
|
||||
} else {
|
||||
baz();
|
||||
}
|
||||
|
||||
if (x) {
|
||||
if (y) {
|
||||
foo();
|
||||
} else {
|
||||
bar();
|
||||
}
|
||||
} else {
|
||||
baz();
|
||||
}
|
||||
|
||||
if (x) {
|
||||
foo();
|
||||
} else if (y) {
|
||||
bar();
|
||||
} else if (z) {
|
||||
baz();
|
||||
} else {
|
||||
moo();
|
||||
}
|
||||
|
||||
function f() {
|
||||
if (x) {
|
||||
foo();
|
||||
}
|
||||
if (x) {
|
||||
foo();
|
||||
} else {
|
||||
baz();
|
||||
}
|
||||
if (x) {
|
||||
foo();
|
||||
} else if (y) {
|
||||
bar();
|
||||
} else {
|
||||
baz();
|
||||
}
|
||||
if (x) {
|
||||
if (y) {
|
||||
foo();
|
||||
} else {
|
||||
bar();
|
||||
}
|
||||
} else {
|
||||
baz();
|
||||
}
|
||||
if (x) {
|
||||
foo();
|
||||
} else if (y) {
|
||||
bar();
|
||||
} else if (z) {
|
||||
baz();
|
||||
} else {
|
||||
moo();
|
||||
}
|
||||
}
|
||||
17
test/input/issue-1482/default.js
Normal file
17
test/input/issue-1482/default.js
Normal file
@@ -0,0 +1,17 @@
|
||||
if (x) foo();
|
||||
|
||||
if (x) foo(); else baz();
|
||||
|
||||
if (x) foo(); else if (y) bar(); else baz();
|
||||
|
||||
if (x) if (y) foo(); else bar(); else baz();
|
||||
|
||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||
|
||||
function f() {
|
||||
if (x) foo();
|
||||
if (x) foo(); else baz();
|
||||
if (x) foo(); else if (y) bar(); else baz();
|
||||
if (x) if (y) foo(); else bar(); else baz();
|
||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||
}
|
||||
12
test/input/issue-1482/input.js
Normal file
12
test/input/issue-1482/input.js
Normal file
@@ -0,0 +1,12 @@
|
||||
if (x) foo();
|
||||
if (x) foo(); else baz();
|
||||
if (x) foo(); else if (y) bar(); else baz();
|
||||
if (x) if (y) foo(); else bar(); else baz();
|
||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||
function f() {
|
||||
if (x) foo();
|
||||
if (x) foo(); else baz();
|
||||
if (x) foo(); else if (y) bar(); else baz();
|
||||
if (x) if (y) foo(); else bar(); else baz();
|
||||
if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
|
||||
}
|
||||
1
test/input/issue-1632/^{foo}[bar](baz)+$.js
Normal file
1
test/input/issue-1632/^{foo}[bar](baz)+$.js
Normal file
@@ -0,0 +1 @@
|
||||
console.log(x);
|
||||
3
test/input/issue-520/input.js
Normal file
3
test/input/issue-520/input.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var Foo = function Foo(){console.log(1+2);}; new Foo();
|
||||
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLElBQU0sR0FBRyxHQUFDLEFBQUUsWUFBVyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEFBQUUsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDOyJ9
|
||||
2
test/input/issue-520/output.js
Normal file
2
test/input/issue-520/output.js
Normal file
@@ -0,0 +1,2 @@
|
||||
new function(){console.log(3)};
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxHQUFyQyxZQUFnQkEsUUFBUUMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl19
|
||||
87
test/jetstream.js
Normal file
87
test/jetstream.js
Normal file
@@ -0,0 +1,87 @@
|
||||
#! /usr/bin/env node
|
||||
// -*- js -*-
|
||||
|
||||
"use strict";
|
||||
|
||||
var site = "http://browserbench.org/JetStream/";
|
||||
if (typeof phantom == "undefined") {
|
||||
// workaround for tty output truncation upon process.exit()
|
||||
[process.stdout, process.stderr].forEach(function(stream){
|
||||
if (stream._handle && stream._handle.setBlocking)
|
||||
stream._handle.setBlocking(true);
|
||||
});
|
||||
var args = process.argv.slice(2);
|
||||
if (!args.length) {
|
||||
args.push("-mc", "warnings=false");
|
||||
}
|
||||
args.push("--stats");
|
||||
var child_process = require("child_process");
|
||||
try {
|
||||
require("phantomjs-prebuilt");
|
||||
} catch(e) {
|
||||
child_process.execSync("npm install phantomjs-prebuilt@2.1.14");
|
||||
}
|
||||
var http = require("http");
|
||||
var server = http.createServer(function(request, response) {
|
||||
request.resume();
|
||||
var url = decodeURIComponent(request.url.slice(1));
|
||||
var stderr = "";
|
||||
var uglifyjs = child_process.fork("bin/uglifyjs", args, {
|
||||
silent: true
|
||||
}).on("exit", function(code) {
|
||||
console.log("uglifyjs", url.indexOf(site) == 0 ? url.slice(site.length) : url, args.join(" "));
|
||||
console.log(stderr);
|
||||
if (code) throw new Error("uglifyjs failed with code " + code);
|
||||
});
|
||||
uglifyjs.stderr.on("data", function(data) {
|
||||
stderr += data;
|
||||
}).setEncoding("utf8");
|
||||
uglifyjs.stdout.pipe(response);
|
||||
http.get(url, function(res) {
|
||||
res.pipe(uglifyjs.stdin);
|
||||
});
|
||||
}).listen().on("listening", function() {
|
||||
var phantomjs = require("phantomjs-prebuilt");
|
||||
var program = phantomjs.exec(process.argv[1], server.address().port);
|
||||
program.stdout.pipe(process.stdout);
|
||||
program.stderr.pipe(process.stderr);
|
||||
program.on("exit", function(code) {
|
||||
server.close();
|
||||
if (code) throw new Error("JetStream failed!");
|
||||
console.log("JetStream completed successfully.");
|
||||
});
|
||||
});
|
||||
server.timeout = 0;
|
||||
} else {
|
||||
var page = require("webpage").create();
|
||||
page.onError = function(msg, trace) {
|
||||
var body = [ msg ];
|
||||
if (trace) trace.forEach(function(t) {
|
||||
body.push(" " + (t.function || "Anonymous function") + " (" + t.file + ":" + t.line + ")");
|
||||
});
|
||||
console.error(body.join("\n"));
|
||||
phantom.exit(1);
|
||||
};
|
||||
var url = "http://localhost:" + require("system").args[1] + "/";
|
||||
page.onResourceRequested = function(requestData, networkRequest) {
|
||||
if (/\.js$/.test(requestData.url))
|
||||
networkRequest.changeUrl(url + encodeURIComponent(requestData.url));
|
||||
}
|
||||
page.onConsoleMessage = function(msg) {
|
||||
if (/Error:/i.test(msg)) {
|
||||
console.error(msg);
|
||||
phantom.exit(1);
|
||||
}
|
||||
console.log(msg);
|
||||
if (~msg.indexOf("Raw results:")) {
|
||||
phantom.exit();
|
||||
}
|
||||
};
|
||||
page.open(site, function(status) {
|
||||
if (status != "success") phantomjs.exit(1);
|
||||
page.evaluate(function() {
|
||||
JetStream.switchToQuick();
|
||||
JetStream.start();
|
||||
});
|
||||
});
|
||||
}
|
||||
32
test/mocha/accessorTokens-1492.js
Normal file
32
test/mocha/accessorTokens-1492.js
Normal file
@@ -0,0 +1,32 @@
|
||||
var UglifyJS = require('../../');
|
||||
var assert = require("assert");
|
||||
|
||||
describe("Accessor tokens", function() {
|
||||
it("Should fill the token information for accessors (issue #1492)", function() {
|
||||
// location 0 1 2 3 4
|
||||
// 01234567890123456789012345678901234567890123456789
|
||||
var ast = UglifyJS.parse("var obj = { get latest() { return undefined; } }");
|
||||
|
||||
// test all AST_ObjectProperty tokens are set as expected
|
||||
var checkedAST_ObjectProperty = false;
|
||||
var checkWalker = new UglifyJS.TreeWalker(function(node, descend) {
|
||||
if (node instanceof UglifyJS.AST_ObjectProperty) {
|
||||
checkedAST_ObjectProperty = true;
|
||||
|
||||
assert.equal(node.start.pos, 12);
|
||||
assert.equal(node.end.endpos, 46);
|
||||
|
||||
assert(node.key instanceof UglifyJS.AST_SymbolRef);
|
||||
assert.equal(node.key.start.pos, 16);
|
||||
assert.equal(node.key.end.endpos, 22);
|
||||
|
||||
assert(node.value instanceof UglifyJS.AST_Accessor);
|
||||
assert.equal(node.value.start.pos, 22);
|
||||
assert.equal(node.value.end.endpos, 46);
|
||||
|
||||
}
|
||||
});
|
||||
ast.walk(checkWalker);
|
||||
assert(checkedAST_ObjectProperty, "AST_ObjectProperty not found");
|
||||
});
|
||||
});
|
||||
@@ -19,4 +19,12 @@ describe("arguments", function() {
|
||||
value // Select function as scope
|
||||
);
|
||||
});
|
||||
|
||||
it("Should recognize when a function uses arguments", function() {
|
||||
var ast = UglifyJS.parse("function a(){function b(){function c(){}; return arguments[0];}}");
|
||||
ast.figure_out_scope();
|
||||
assert.strictEqual(ast.body[0].uses_arguments, false);
|
||||
assert.strictEqual(ast.body[0].body[0].uses_arguments, true);
|
||||
assert.strictEqual(ast.body[0].body[0].body[0].uses_arguments, false);
|
||||
});
|
||||
});
|
||||
@@ -1,12 +1,13 @@
|
||||
var assert = require("assert");
|
||||
var exec = require("child_process").exec;
|
||||
var readFileSync = require("fs").readFileSync;
|
||||
|
||||
describe("bin/uglifyjs", function () {
|
||||
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||
it("should produce a functional build when using --self", function (done) {
|
||||
this.timeout(5000);
|
||||
this.timeout(15000);
|
||||
|
||||
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
|
||||
var command = uglifyjs + ' --self -cm --wrap WrappedUglifyJS';
|
||||
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
@@ -19,4 +20,290 @@ describe("bin/uglifyjs", function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should be able to filter comments correctly with `--comment all`", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/comments/filter.js --comments all';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "// foo\n/*@preserve*/\n// bar\n\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should be able to filter comments correctly with `--comment <RegExp>`", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/comments/filter.js --comments /r/';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "/*@preserve*/\n// bar\n\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should be able to filter comments correctly with just `--comment`", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/comments/filter.js --comments';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "/*@preserve*/\n\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should append source map to output when using --source-map-inline", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1323/sample.js --source-map-inline';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" +
|
||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxHQUFJQSxLQUFNLFdBQ04sUUFBU0MsS0FBS0QsS0FDVixNQUFPQSxLQUdYLE1BQU9DIn0=\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should not append source map to output when not using --source-map-inline", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1323/sample.js';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --keep-fnames (mangle only)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --keep-fnames (mangle & compress)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c unused=false';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with keep_fnames under mangler options", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fnames=true';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --define (simple)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/global_defs/simple.js --define D=5 -c';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "console.log(5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --define (nested)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/global_defs/nested.js --define C.D=5,C.V=3 -c';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "console.log(3,5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with --define (AST_Node)", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/global_defs/simple.js --define console.log=stdout.println -c';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "stdout.println(D);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with `--beautify`", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, readFileSync("test/input/issue-1482/default.js", "utf8"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should work with `--beautify bracketize`", function (done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b bracketize';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, readFileSync("test/input/issue-1482/bracketize.js", "utf8"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should process inline source map", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-520/input.js -mc toplevel --in-source-map inline --source-map-inline';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, readFileSync("test/input/issue-520/output.js", "utf8"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should warn for missing inline source map", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1323/sample.js --in-source-map inline';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n");
|
||||
assert.strictEqual(stderr, "WARN: inline source map not found\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should fail with multiple input and inline source map", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-520/input.js test/input/issue-520/output.js --in-source-map inline --source-map-inline';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stderr, "ERROR: Inline source map only works with singular input\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should fail with acorn and inline source map", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-520/input.js --in-source-map inline --source-map-inline --acorn';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stderr, "ERROR: Inline source map only works with built-in parser\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should fail with SpiderMonkey and inline source map", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-520/input.js --in-source-map inline --source-map-inline --spidermonkey';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stderr, "ERROR: Inline source map only works with built-in parser\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should fail with invalid syntax", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/simple.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
var lines = stderr.split(/\n/);
|
||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12");
|
||||
assert.strictEqual(lines[1], "function f(a{}");
|
||||
assert.strictEqual(lines[2], " ^");
|
||||
assert.strictEqual(lines[3], "SyntaxError: Unexpected token punc «{», expected punc «,»");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should fail with correct marking of tabs", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/tab.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
var lines = stderr.split(/\n/);
|
||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/tab.js:1,12");
|
||||
assert.strictEqual(lines[1], "\t\tfoo(\txyz, 0abc);");
|
||||
assert.strictEqual(lines[2], "\t\t \t ^");
|
||||
assert.strictEqual(lines[3], "SyntaxError: Invalid syntax: 0abc");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should fail with correct marking at start of line", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/eof.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
var lines = stderr.split(/\n/);
|
||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0");
|
||||
assert.strictEqual(lines[1], "foo, bar(");
|
||||
assert.strictEqual(lines[2], " ^");
|
||||
assert.strictEqual(lines[3], "SyntaxError: Unexpected token: eof (undefined)");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should fail with a missing loop body", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/loop-no-body.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
var lines = stderr.split(/\n/);
|
||||
assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0");
|
||||
assert.strictEqual(lines[1], "for (var i = 0; i < 1; i++) ");
|
||||
assert.strictEqual(lines[2], " ^");
|
||||
assert.strictEqual(lines[3], "SyntaxError: Unexpected token: eof (undefined)");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should support hyphen as shorthand", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep-fnames=true';
|
||||
|
||||
exec(command, function (err, stdout) {
|
||||
if (err) throw err;
|
||||
|
||||
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (5--)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_1.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/assign_1.js:1,18",
|
||||
"console.log(1 || 5--);",
|
||||
" ^",
|
||||
"SyntaxError: Invalid use of -- operator"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (Math.random() /= 2)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_2.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/assign_2.js:1,32",
|
||||
"console.log(2 || (Math.random() /= 2));",
|
||||
" ^",
|
||||
"SyntaxError: Invalid assignment"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should throw syntax error (++this)", function(done) {
|
||||
var command = uglifyjscmd + ' test/input/invalid/assign_3.js';
|
||||
|
||||
exec(command, function (err, stdout, stderr) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/assign_3.js:1,18",
|
||||
"console.log(3 || ++this);",
|
||||
" ^",
|
||||
"SyntaxError: Invalid use of ++ operator"
|
||||
].join("\n"));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,11 +2,21 @@ var UglifyJS = require('../../');
|
||||
var assert = require("assert");
|
||||
|
||||
describe("comment filters", function() {
|
||||
it("Should be able to filter comments by passing regex", function() {
|
||||
it("Should be able to filter comments by passing regexp", function() {
|
||||
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
|
||||
assert.strictEqual(ast.print_to_string({comments: /^!/}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
|
||||
});
|
||||
|
||||
it("Should be able to filter comments with the 'all' option", function() {
|
||||
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
|
||||
assert.strictEqual(ast.print_to_string({comments: "all"}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8\n");
|
||||
});
|
||||
|
||||
it("Should be able to filter commments with the 'some' option", function() {
|
||||
var ast = UglifyJS.parse("// foo\n/*@preserve*/\n// bar\n/*@license*/\n//@license with the wrong comment type\n/*@cc_on something*/");
|
||||
assert.strictEqual(ast.print_to_string({comments: "some"}), "/*@preserve*/\n/*@license*/\n/*@cc_on something*/\n");
|
||||
});
|
||||
|
||||
it("Should be able to filter comments by passing a function", function() {
|
||||
var ast = UglifyJS.parse("/*TEST 123*/\n//An other comment\n//8 chars.");
|
||||
var f = function(node, comment) {
|
||||
@@ -16,6 +26,11 @@ describe("comment filters", function() {
|
||||
assert.strictEqual(ast.print_to_string({comments: f}), "/*TEST 123*/\n//8 chars.\n");
|
||||
});
|
||||
|
||||
it("Should be able to filter comments by passing regex in string format", function() {
|
||||
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
|
||||
assert.strictEqual(ast.print_to_string({comments: "/^!/"}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
|
||||
});
|
||||
|
||||
it("Should be able to get the comment and comment type when using a function", function() {
|
||||
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
|
||||
var f = function(node, comment) {
|
||||
@@ -42,4 +57,35 @@ describe("comment filters", function() {
|
||||
|
||||
assert.strictEqual(ast.print_to_string({comments: f}), "#!Random comment\n//test1\n/*test2*/\n");
|
||||
});
|
||||
|
||||
it("Should never be able to filter comment5 when using 'some' as filter", function() {
|
||||
var ast = UglifyJS.parse("#!foo\n//foo\n/*@preserve*/\n/* please hide me */");
|
||||
assert.strictEqual(ast.print_to_string({comments: "some"}), "#!foo\n/*@preserve*/\n");
|
||||
});
|
||||
|
||||
it("Should have no problem on multiple calls", function() {
|
||||
const options = {
|
||||
comments: /ok/
|
||||
};
|
||||
|
||||
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
|
||||
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
|
||||
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
|
||||
});
|
||||
|
||||
it("Should handle shebang and preamble correctly", function() {
|
||||
var code = UglifyJS.minify("#!/usr/bin/node\nvar x = 10;", {
|
||||
fromString: true,
|
||||
output: { preamble: "/* Build */" }
|
||||
}).code;
|
||||
assert.strictEqual(code, "#!/usr/bin/node\n/* Build */\nvar x=10;");
|
||||
});
|
||||
|
||||
it("Should handle preamble without shebang correctly", function() {
|
||||
var code = UglifyJS.minify("var x = 10;", {
|
||||
fromString: true,
|
||||
output: { preamble: "/* Build */" }
|
||||
}).code;
|
||||
assert.strictEqual(code, "/* Build */\nvar x=10;");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ describe("Comment", function() {
|
||||
|
||||
var fail = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
e.message === "SyntaxError: Unexpected token: operator (>)" &&
|
||||
e.message === "Unexpected token: operator (>)" &&
|
||||
e.line === 2 &&
|
||||
e.col === 0;
|
||||
}
|
||||
@@ -36,7 +36,7 @@ describe("Comment", function() {
|
||||
|
||||
var fail = function(e) {
|
||||
return e instanceof uglify.JS_Parse_Error &&
|
||||
e.message === "SyntaxError: Unexpected token: operator (>)" &&
|
||||
e.message === "Unexpected token: operator (>)" &&
|
||||
e.line === 5 &&
|
||||
e.col === 0;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ describe("comment before constant", function() {
|
||||
it("Should test comment before constant is retained and output after mangle.", function() {
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true,
|
||||
compress: { collapse_vars: false },
|
||||
compress: { collapse_vars: false, reduce_vars: false },
|
||||
mangle: {},
|
||||
output: { comments: true },
|
||||
});
|
||||
@@ -17,9 +17,9 @@ describe("comment before constant", function() {
|
||||
it("Should test code works when comments disabled.", function() {
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true,
|
||||
compress: { collapse_vars: false },
|
||||
compress: { collapse_vars: false, reduce_vars: false },
|
||||
mangle: {},
|
||||
output: {},
|
||||
output: { comments: false },
|
||||
});
|
||||
assert.strictEqual(result.code, 'function f(){var n=!1;return n}');
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user