Compare commits

...

131 Commits

Author SHA1 Message Date
Alex Lam S.L
01bb08b553 harmony-v3.3.0 2017-12-24 22:58:15 +08:00
alexlamsl
fc3010bec5 add tests for #2613 2017-12-24 22:18:34 +08:00
alexlamsl
7de541f9c8 fix tests 2017-12-24 19:21:31 +08:00
alexlamsl
dbf8684287 Merge branch 'master' into harmony-v3.3.0 2017-12-24 19:19:24 +08:00
Alex Lam S.L
f1556cb945 v3.3.0 2017-12-24 17:34:56 +08:00
Alex Lam S.L
efffb81735 fix comments output & improve /*@__PURE__*/
- fix whitespace around comments
- fix comment parsing around parentheses
- consider parentheses when parsing `/*@__PURE__*/`
- remove all `/*@__PURE__*/` on output

fixes #2638
2017-12-24 12:38:45 +08:00
Alex Lam S.L
202f90ef8f fix corner cases with collapse_vars, inline & reduce_vars (#2637)
fixes #2630
2017-12-24 01:24:12 +08:00
Alex Lam S.L
c07ea17c01 fix escape analysis on AST_PropAccess (#2636) 2017-12-24 00:36:46 +08:00
Alex Lam S.L
edb4e3bd52 make comments output more robust (#2633)
- improve handling of comments right after `return`
- retain comments after `OutputStream`
- preserve trailing comments
- fix handling of new line before comments
- handle comments around parentheses

fixes #88
fixes #112
fixes #218
fixes #372
fixes #2629
2017-12-22 04:59:54 +08:00
kzc
8d156b51fe arrows fix for object literal methods containing arguments (#2632)
fixes #2631
2017-12-21 17:50:26 +08:00
Alex Lam S.L
4113609dd4 extend test/ufuzz.js to inline & reduce_funcs (#2620)
- forward call `fN()`
- allow forward call functions to be single-use
- avoid generating `AST_Defun` within blocks
2017-12-20 23:52:18 +08:00
Alex Lam S.L
7ac7b0872f remove AST hack from inline (#2627) 2017-12-20 17:05:53 +08:00
Alex Lam S.L
86ae5881b7 disable hoist_funs by default (#2626) 2017-12-20 17:05:40 +08:00
Alex Lam S.L
fac003c64f avoid inline of function with special argument names (#2625) 2017-12-20 02:48:04 +08:00
Alex Lam S.L
2273655c17 fix inline after single-use reduce_vars (#2623) 2017-12-19 22:19:33 +08:00
Ondřej Španěl
01057cf76d Transform can be simplified when clone is not done. (#2621) 2017-12-19 17:56:16 +08:00
Alex Lam S.L
032f096b7f add test for #2613 (#2618) 2017-12-19 05:22:05 +08:00
Alex Lam S.L
4b334edf49 handle global constant collision with local variable after inline (#2617)
fixes #2616
2017-12-19 03:05:30 +08:00
Alex Lam S.L
8ddcbc39e6 compress apply() & call() of function (#2613)
- `fn.apply(a, [ ... ])` => `fn.call(a, ...)`
- `fn.call(a, ... )` => `a, fn(...)`

where `fn` can be `function` literal or symbol reference linked through `reduce_vars`
2017-12-18 16:23:39 +08:00
Alex Lam S.L
0b0eac1d5d drop property assignment to constants (#2612) 2017-12-18 12:07:53 +08:00
kzc
85bfa17139 fix slowness in unused for blocks (#2614)
fixes #2609
2017-12-18 12:06:14 +08:00
Alex Lam S.L
b29fc8b27c improve transversal efficiency in collapse_vars (#2611)
fixes #2603
2017-12-18 03:00:05 +08:00
kzc
80c8dfcde6 fix export default of anonymous generators and async functions (#2607)
fixes #2606
2017-12-18 00:11:52 +08:00
Alex Lam S.L
5de369fa67 export parse() (#2608) 2017-12-17 23:12:23 +08:00
Alex Lam S.L
7918a50d52 improve reset_opt_flags() (#2610) 2017-12-17 23:01:08 +08:00
Alex Lam S.L
21794c9b8d account for catch variable when inline (#2605)
fixes #2604
2017-12-16 15:21:09 +08:00
Alex Lam S.L
6c686ce593 fix nested inline (#2602)
fixes #2601
2017-12-16 02:16:35 +08:00
Alex Lam S.L
db902af4c6 fix escape analysis on || and && (#2600)
fixes #2598
2017-12-15 19:48:14 +08:00
Alex Lam S.L
7d6907cb99 fix dead_code on nested try (#2599)
fixes #2597
2017-12-15 19:41:28 +08:00
Alex Lam S.L
092d9affb8 fix reduce_vars on do...while (#2596) 2017-12-15 16:33:19 +08:00
Alex Lam S.L
8f681b1d17 handle inline of function arguments (#2590)
fixes #2476
2017-12-15 13:28:30 +08:00
Alex Lam S.L
90313875f7 inline single-use function across loop (#2594) 2017-12-14 19:24:54 +08:00
Alex Lam S.L
3f18a61532 fix reduce_vars on single AST_Defun reference across loop (#2593) 2017-12-14 18:47:05 +08:00
Alex Lam S.L
02a6ce07eb improve reduce_vars (#2592)
- account for hoisting nature of `var`
2017-12-14 15:32:13 +08:00
Alex Lam S.L
738fd52bc4 improve collapse_vars (#2591)
- handle single-use assignments other than `AST_VarDef`
- scan `AST_Call` for candidates
2017-12-14 15:31:35 +08:00
kzc
d18979bb23 improve dead_code tests (#2589)
for #2588
2017-12-14 12:12:06 +08:00
Alex Lam S.L
8266993c6e fix dead_code on return/throw within try (#2588) 2017-12-14 04:38:21 +08:00
Alex Lam S.L
9a137e8613 drop local assign-only variable in return (#2587) 2017-12-14 02:59:59 +08:00
Alex Lam S.L
ef618332ea fold cascade functionality into collapse_vars (#2586) 2017-12-14 01:20:36 +08:00
Alex Lam S.L
7f418978c9 recover lost opportunities from #2574 (#2584) 2017-12-13 18:20:53 +08:00
Alex Lam S.L
04cc395c35 improve collapse_vars on side-effect-free replacements (#2583) 2017-12-13 04:52:54 +08:00
Alex Lam S.L
e008dc1bde minor clean-up for IIFE (#2582)
- faster exact type match
- aggressively convert to `!`
2017-12-13 01:27:26 +08:00
Alex Lam S.L
ddf96cfda2 avoid Function.prototype pollution by test/sandbox.js (#2581) 2017-12-12 05:02:01 +08:00
Alex Lam S.L
ebfd5c5c74 fix AST_VarDef.may_throw() (#2580) 2017-12-12 03:30:25 +08:00
Alex Lam S.L
f2ad542679 fix collapse_vars on switch (#2578) 2017-12-11 18:11:09 +08:00
Alex Lam S.L
c43118be4f remove unused code (#2579)
fixes #2577
2017-12-11 17:39:08 +08:00
Alex Lam S.L
93f3b2b114 escape consecutive unpaired surrogates (#2576)
fixes #2569
2017-12-11 01:15:44 +08:00
Alex Lam S.L
bf000beae7 rename tests (#2575) 2017-12-11 00:24:54 +08:00
Alex Lam S.L
f8ff349ba7 harmony-v3.2.2 2017-12-11 00:16:36 +08:00
Alex Lam S.L
0e16d92786 handle exceptional flow correctly in collapse_vars (#2574)
fixes #2571
2017-12-11 00:16:02 +08:00
alexlamsl
f2b179ae94 fix escape analysis for AST_Expansion 2017-12-10 23:05:22 +08:00
alexlamsl
c7e8fc4830 fix escape analysis for `AST_Await
fixes #2566
2017-12-10 23:03:29 +08:00
alexlamsl
f778a0aa01 fix escape analysis for AST_Yield
fixes #2565
2017-12-10 23:02:20 +08:00
alexlamsl
7fd4b66eaa fix tests 2017-12-10 14:16:54 +08:00
alexlamsl
21c986ff5b Merge branch 'master' into harmony-v3.2.2 2017-12-10 14:12:24 +08:00
Alex Lam S.L
2441827408 v3.2.2 2017-12-10 13:46:17 +08:00
Alex Lam S.L
0aff037a35 improve unused on assign-only symbols (#2568) 2017-12-09 06:19:29 +08:00
Alex Lam S.L
74a2f53683 fix escape analysis for AST_Throw (#2564) 2017-12-08 02:54:37 +08:00
Alex Lam S.L
e20935c3f2 fix escape analysis for AST_Conditional & AST_Sequence (#2563)
fixes #2560
2017-12-08 01:50:38 +08:00
Alex Lam S.L
3e34f62a1c account for side-effects in conditional call inversion (#2562)
fixes #2560
2017-12-08 01:15:31 +08:00
Alex Lam S.L
d21cb84696 eliminate noop calls more aggressively (#2559) 2017-12-07 01:22:08 +08:00
Alex Lam S.L
3dd495ecdd improve if_return (#2558)
`return void x()` => `x()`
2017-12-07 01:01:52 +08:00
Alex Lam S.L
87bae623e9 simplify computed properties for methods, getters & setters (#2555)
fixes #2554
2017-12-04 00:18:48 +08:00
Alex Lam S.L
606f7a5b37 harmony-v3.2.1 2017-12-03 13:51:27 +08:00
alexlamsl
b91a2e018a fix tests 2017-12-03 12:14:31 +08:00
alexlamsl
c9dbe9deb1 Merge branch 'master' into harmony-v3.2.1 2017-12-03 11:59:41 +08:00
Alex Lam S.L
b9f3ddfb30 v3.2.1 2017-12-03 11:39:51 +08:00
Alex Lam S.L
77332a0315 fix dead_code on for (#2552) 2017-12-02 15:46:05 +08:00
Alex Lam S.L
85c56adbd1 more tests for #2535 (#2551) 2017-12-02 02:26:56 +08:00
Alex Lam S.L
8da3754e51 improve evaluate on typeof (#2550)
- gated through `typeofs`
2017-12-02 02:18:33 +08:00
Alex Lam S.L
9a6b11f8e6 improve boolean compression (#2548)
fixes #2535
2017-12-01 22:41:35 +08:00
Alex Lam S.L
7ac6fdcc99 improve switch case compression (#2547) 2017-12-01 14:32:00 +08:00
Alex Lam S.L
f6610baaa8 improve AST_For.init & AST_Switch.expression compression (#2546) 2017-12-01 12:53:59 +08:00
Alex Lam S.L
09b320e8a5 convert to number under boolean context (#2545) 2017-12-01 12:52:36 +08:00
Alex Lam S.L
5a1e99d713 improve compression of if conditions (#2544) 2017-12-01 06:18:31 +08:00
Alex Lam S.L
b762f2d6f4 improve compression of loop conditions (#2543) 2017-12-01 05:52:33 +08:00
Alex Lam S.L
172079a47f improve code reuse (#2542) 2017-12-01 03:40:46 +08:00
Alex Lam S.L
c58d3936a3 fix corner case in call binding (#2541) 2017-12-01 03:18:20 +08:00
Alex Lam S.L
18302bf8e9 backport test from #2526 (#2534) 2017-11-29 13:32:00 +08:00
Alex Lam S.L
bc5047c1e7 fix inline on nested substitutions (#2533)
fixes #2531
2017-11-29 13:31:41 +08:00
kzc
1885f91f13 document top level minify() option safari10 (#2532) 2017-11-29 05:48:33 +08:00
Alex Lam S.L
736c366d93 introduce --safari10 (#2530) 2017-11-29 03:34:47 +08:00
kzc
1646c5844f document the new output option safari10 (#2529) 2017-11-29 02:29:23 +08:00
Alex Lam S.L
aacf760fb4 add Safari workaround for await (#2528)
fixes #2344
2017-11-29 00:20:36 +08:00
Alex Lam S.L
755e2a62c6 extend hoist_props to AST_Arrow & AST_Class (#2527)
fixes #2503
2017-11-28 22:54:44 +08:00
Alex Lam S.L
62d2817d6c reduce this in block scopes (#2526)
fixes #2455
2017-11-28 22:54:21 +08:00
Alex Lam S.L
37cbd7080c replace single-use class definitions (#2524)
fixes #2416
2017-11-28 20:57:15 +08:00
Alex Lam S.L
206a54a746 fix nested hoist_props substitution (#2523)
fixes #2519
2017-11-28 14:39:00 +08:00
Alex Lam S.L
32def5ebf5 improve synergy between collapse_vars & unused (#2521) 2017-11-28 14:02:39 +08:00
Alex Lam S.L
ecc9f6b770 drop assignment in AST_VarDef.value (#2522)
fixes #2516
2017-11-28 13:08:40 +08:00
Alex Lam S.L
b84c99ef5c harmony-v3.2.0 2017-11-26 06:02:49 +08:00
alexlamsl
4f08c2f504 Merge branch 'master' into harmony-v3.2.0 2017-11-26 04:23:57 +08:00
Alex Lam S.L
b37a68c84f v3.2.0 2017-11-26 04:08:35 +08:00
Alex Lam S.L
c141ae6f8d fix argument/atom collision by properties (#2514)
fixes #2513
2017-11-25 22:52:46 +08:00
Alex Lam S.L
97c464dbf5 fix wording and formatting (#2512) 2017-11-25 19:07:46 +08:00
kzc
ba4894af18 document top level minify option keep_classnames (#2511) 2017-11-25 16:33:03 +08:00
Alex Lam S.L
f1e3ef5262 separate keep_classnames & keep_fnames (#2510)
fixes #2418
2017-11-25 16:31:52 +08:00
Alex Lam S.L
3b28b915eb extend escape analysis on constant expression properties (#2509)
fixes #2508
2017-11-24 14:07:39 +08:00
Alex Lam S.L
eb001dc1d9 fix argument/atom collision by collapse_vars (#2507)
fixes #2506
2017-11-24 07:26:22 +08:00
Alex Lam S.L
aa9bdf416e make AST_Lambda.contains_this() less magical (#2505) 2017-11-24 07:03:37 +08:00
Alex Lam S.L
bbf38dc9c0 fix reduce_vars on arrow functions with this (#2504)
fixes #2496
2017-11-24 06:21:49 +08:00
Alex Lam S.L
8987780db6 eliminate invalid state caching in collapse_vars (#2502)
fixes #2497
2017-11-24 04:12:37 +08:00
Alex Lam S.L
30cfea2e7a fix rename (#2501)
- suppress spurious `rename` from `commander`
- handle `AST_SymbolCatch` correctly
2017-11-24 03:05:43 +08:00
kzc
3d8341a7ab fix properties for array literal with spread (#2499)
fixes #2498
2017-11-24 02:04:26 +08:00
Alex Lam S.L
f4e2fb9864 expand symbol space to improve compression (#2460)
- give globally distinct names to distinct variables
- improve ability to compress cross-scoped
- introduce `options.rename` to `minify()`
- default `true` if both `compress` & `mangle`
2017-11-19 19:29:51 +08:00
Alex Lam S.L
567cb0e4e3 harmony-v3.1.10 2017-11-19 15:53:22 +08:00
Alex Lam S.L
b80062c490 enable hoist_props by default (#2492) 2017-11-19 14:56:23 +08:00
alexlamsl
227b58812d Merge branch 'master' into harmony-v3.1.10 2017-11-19 14:34:27 +08:00
kzc
f25bd13be6 fix keyword shorthand property output for ecma >= 6 (#2493)
fixes #2491
2017-11-19 13:53:42 +08:00
Alex Lam S.L
667fc4d08b v3.1.10 2017-11-18 23:56:33 +08:00
kzc
6142117cdd document the webkit output option (#2490)
- workaround for WebKit bugs
- PhantomJS users should enable this output option

closes #2489
2017-11-17 13:46:49 +08:00
kzc
e826973b76 fix template expression parse of regex and sequence (#2488)
fixes #2487
2017-11-17 01:34:57 +08:00
Alex Lam S.L
ae28a24c7f fix cross-scope inlining of AST_Functions (#2486)
fixes #2485
2017-11-16 10:04:30 +08:00
Alex Lam S.L
ebe761cad0 minor consolidations (#2484)
- unique symbol generation
- `unsafe` on `AST_Call`
2017-11-16 04:37:37 +08:00
kzc
fa7a7c5c5a Update ISSUE_TEMPLATE.md (#2481) 2017-11-15 06:00:51 +08:00
kzc
557636f3b7 update documentation for reduce_funcs (#2478) 2017-11-14 16:03:25 +08:00
Alex Lam S.L
49fbe9c5ac fix replacement logic in collapse_vars (#2475) 2017-11-13 07:37:42 +08:00
Alex Lam S.L
2ac5086831 fix top_retain on hoist_props (#2474)
fixes #2473
2017-11-13 00:59:41 +08:00
Alex Lam S.L
c6cfa04d10 allow symbol replacement on multiple occurrences (#2472)
- all-or-nothing replacement
- avoid unmangleable names

fixes #2436
2017-11-12 22:31:47 +08:00
Alex Lam S.L
9632f79e46 harmony-v3.1.9 2017-11-11 19:21:09 +08:00
alexlamsl
a3fbb27194 update tests 2017-11-11 15:57:47 +08:00
alexlamsl
11c0b1e1f9 Merge branch 'master' into harmony-v3.1.9 2017-11-11 15:45:34 +08:00
Alex Lam S.L
346fa12e0e v3.1.9 2017-11-11 15:31:13 +08:00
Alex Lam S.L
cda27b0970 extend reduce_funcs to cover cross-scope substitutions (#2469)
fixes #2468
2017-11-11 15:30:17 +08:00
Alex Lam S.L
3c74047368 implement compress option reduce_funcs (#2466)
- inline single-use function declarations as expressions when permissible
- depend on `reduce_vars`
- enabled by default
- disable for speed critical code

fixes #2464
2017-11-11 05:59:35 +08:00
Alex Lam S.L
650d5d5c9b suppress hoist_props on export (#2463)
Miscellaneous
- fix double semi-colons from `beautify` in `export`

fixes #2462
2017-11-10 17:38:31 +08:00
Alex Lam S.L
94525d859f fix object literal tracing in reduce_vars (#2461) 2017-11-10 05:47:10 +08:00
Alex Lam S.L
1127a2caf3 fix multiple nested function substitutions (#2458)
fixes #2449
2017-11-09 23:30:00 +08:00
Alex Lam S.L
246d9d4e83 remove hack in collapse_vars (#2457)
fixes #2456
2017-11-09 20:00:58 +08:00
Alex Lam S.L
4c0b0177b6 preserve function identity in reduce_vars (#2451)
fixes #2450
2017-11-08 03:28:46 +08:00
Alex Lam S.L
dd0a36119b fix const under collapse_vars without unused (#2454)
fixes #2453
2017-11-08 02:10:46 +08:00
80 changed files with 8748 additions and 1601 deletions

View File

@@ -15,6 +15,8 @@
UglifyJS alone - without third party tools or libraries.
Ideally the input should be as small as possible.
Post a link to a gist if necessary.
Issues without a reproducible test case will be closed.
-->
**The `uglifyjs` CLI command executed or `minify()` options used.**

112
README.md
View File

@@ -107,9 +107,15 @@ a double dash to prevent input files being used as option arguments:
Equivalent to setting `ie8: true` in `minify()`
for `compress`, `mangle` and `output` options.
By default UglifyJS will not try to be IE-proof.
--keep-classnames Do not mangle/drop class names.
--keep-fnames Do not mangle/drop function names. Useful for
code relying on Function.prototype.name.
--name-cache <file> File to hold mangled name mappings.
--safari10 Support non-standard Safari 10/11.
Equivalent to setting `safari10: true` in `minify()`
for `mangle` and `output` options.
By default `uglify-es` will not work around
Safari 10/11 bugs.
--self Build UglifyJS as a library (implies --wrap UglifyJS)
--source-map [options] Enable source map/specify source map options:
`base` Path to compute relative paths from input files.
@@ -509,8 +515,17 @@ if (result.error) throw result.error;
- `ie8` (default `false`) - set to `true` to support IE8.
- `keep_classnames` (default: `undefined`) - pass `true` to prevent discarding or mangling
of class names.
- `keep_fnames` (default: `false`) - pass `true` to prevent discarding or mangling
of function names. Useful for code relying on `Function.prototype.name`.
of function names. Useful for code relying on `Function.prototype.name`. If the
top level minify option `keep_classnames` is `undefined` it will be overriden with
the value of the top level minify option `keep_fnames`.
- `safari10` (default: `false`) - pass `true` to work around Safari 10/11 bugs in
loop scoping and `await`. See `safari10` options in [`mangle`](#mangle-options)
and [`output`](#output-options) for details.
## Minify options structure
@@ -536,9 +551,12 @@ if (result.error) throw result.error;
// source map options
},
ecma: 5, // specify one of: 5, 6, 7 or 8
nameCache: null, // or specify a name cache object
toplevel: false,
keep_classnames: false,
keep_fnames: false,
ie8: false,
nameCache: null, // or specify a name cache object
safari10: false,
toplevel: false,
warnings: false,
}
```
@@ -609,17 +627,14 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
the resultant code is shorter: `m(){return x}` becomes `m:()=>x`.
This transform requires that the `ecma` compress option is set to `6` or greater.
- `booleans` (default: `true`) -- various optimizations for boolean context, for example `!!a
? b : c → a ? b : c`
- `booleans` (default: `true`) -- various optimizations for boolean context,
for example `!!a ? b : c → a ? b : c`
- `cascade` (default: `true`) -- small optimization for sequences, transform `x, x` into `x`
and `x = something(), x` into `x = something()`
- `collapse_vars` (default: `true`) -- Collapse single-use non-constant variables,
side effects permitting.
- `collapse_vars` (default: `true`) -- Collapse single-use non-constant variables - side
effects permitting.
- `comparisons` (default: `true`) -- apply certain optimizations to binary nodes, for example:
`!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary
- `comparisons` (default: `true`) -- apply certain optimizations to binary nodes,
e.g. `!(a <= b) → a > b` (only when `unsafe_comps`), attempts to negate binary
nodes, e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
- `computed_props` (default: `true`) -- Transforms constant computed properties
@@ -630,7 +645,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `dead_code` (default: `true`) -- remove unreachable code
- `drop_console` (default: `false`) -- default `false`. Pass `true` to discard calls to
- `drop_console` (default: `false`) -- Pass `true` to discard calls to
`console.*` functions. If you wish to drop a specific function call
such as `console.info` and/or retain side effects from function arguments
after dropping the function call then use `pure_funcs` instead.
@@ -642,14 +657,14 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `evaluate` (default: `true`) -- attempt to evaluate constant expressions
- `expression` (default: `false`) -- default `false`. Pass `true` to preserve completion values
- `expression` (default: `false`) -- Pass `true` to preserve completion values
from terminal statements without `return`, e.g. in bookmarklets.
- `global_defs` (default: `{}`) -- see [conditional compilation](#conditional-compilation)
- `hoist_funs` (default: `true`) -- hoist function declarations
- `hoist_funs` (default: `false`) -- hoist function declarations
- `hoist_props` (default: `false`) -- hoist properties from constant object and
- `hoist_props` (default: `true`) -- hoist properties from constant object and
array literals into regular variables subject to a set of constraints. For example:
`var o={p:1, q:2}; f(o.p, o.q);` is converted to `f(1, 2);`. Note: `hoist_props`
works best with `mangle` enabled, the `compress` option `passes` set to `2` or higher,
@@ -664,19 +679,22 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `join_vars` (default: `true`) -- join consecutive `var` statements
- `keep_fargs` (default: `true`) -- default `true`. Prevents the
compressor from discarding unused function arguments. You need this
for code which relies on `Function.length`.
- `keep_classnames` (default: `false`) -- Pass `true` to prevent the
compressor from discarding class names. See also: the `keep_classnames`
[mangle option](#mangle).
- `keep_fargs` (default: `true`) -- Prevents the compressor from discarding unused
function arguments. You need this for code which relies on `Function.length`.
- `keep_fnames` (default: `false`) -- Pass `true` to prevent the
compressor from discarding function names. Useful for code relying on
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
- `keep_infinity` (default: `false`) -- default `false`. Pass `true` to prevent `Infinity` from
- `keep_infinity` (default: `false`) -- Pass `true` to prevent `Infinity` from
being compressed into `1/0`, which may cause performance issues on Chrome.
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops when we can
statically determine the condition
- `loops` (default: `true`) -- optimizations for `do`, `while` and `for` loops
when we can statically determine the condition.
- `negate_iife` (default: `true`) -- negate "Immediately-Called Function Expressions"
where the return value is discarded, to avoid the parens that the
@@ -706,6 +724,12 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
Specify `"strict"` to treat `foo.bar` as side-effect-free only when
`foo` is certain to not throw, i.e. not `null` or `undefined`.
- `reduce_funcs` (default: `true`) -- Allows single-use functions to be
inlined as function expressions when permissible allowing further
optimization. Enabled by default. Option depends on `reduce_vars`
being enabled. Some code runs faster in the Chrome V8 engine if this
option is disabled. Does not negatively impact other major browsers.
- `reduce_vars` (default: `true`) -- Improve optimization on variables assigned with and
used as constant values.
@@ -718,21 +742,22 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
occasions the default sequences limit leads to very slow compress times in which
case a value of `20` or less is recommended.
- `side_effects` (default: `true`) -- default `true`. Pass `false` to disable potentially dropping
- `side_effects` (default: `true`) -- Pass `false` to disable potentially dropping
functions marked as "pure". A function call is marked as "pure" if a comment
annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
example: `/*@__PURE__*/foo();`
- `switches` (default: `true`) -- de-duplicate and remove unreachable `switch` branches
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or variables (`"vars"`)
in the top level scope (`false` by default, `true` to drop both unreferenced
functions and variables)
- `toplevel` (default: `false`) -- drop unreferenced functions (`"funcs"`) and/or
variables (`"vars"`) in the top level scope (`false` by default, `true` to drop
both unreferenced functions and variables)
- `top_retain` (default: `null`) -- prevent specific toplevel functions and variables from `unused`
removal (can be array, comma-separated, RegExp or function. Implies `toplevel`)
- `top_retain` (default: `null`) -- prevent specific toplevel functions and
variables from `unused` removal (can be array, comma-separated, RegExp or
function. Implies `toplevel`)
- `typeofs` (default: `true`) -- default `true`. Transforms `typeof foo == "undefined"` into
- `typeofs` (default: `true`) -- Transforms `typeof foo == "undefined"` into
`foo === void 0`. Note: recommend to set this value to `false` for IE10 and
earlier versions due to known issues.
@@ -770,32 +795,34 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `unsafe_regexp` (default: `false`) -- enable substitutions of variables with
`RegExp` values the same way as if they are constants.
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple direct variable
assignments do not count as references unless set to `"keep_assign"`)
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
direct variable assignments do not count as references unless set to `"keep_assign"`)
- `warnings` (default: `false`) -- display warnings when dropping unreachable code or unused
declarations etc.
- `warnings` (default: `false`) -- display warnings when dropping unreachable
code or unused declarations etc.
## Mangle options
- `eval` (default `false`). Pass `true` to mangle names visible in scopes
- `eval` (default `false`) -- Pass `true` to mangle names visible in scopes
where `eval` or `with` are used.
- `keep_classnames` (default `false`). Pass `true` to not mangle class names.
- `keep_classnames` (default `false`) -- Pass `true` to not mangle class names.
See also: the `keep_classnames` [compress option](#compress-options).
- `keep_fnames` (default `false`). Pass `true` to not mangle function names.
- `keep_fnames` (default `false`) -- Pass `true` to not mangle function names.
Useful for code relying on `Function.prototype.name`. See also: the `keep_fnames`
[compress option](#compress-options).
- `reserved` (default `[]`). Pass an array of identifiers that should be
- `reserved` (default `[]`) -- Pass an array of identifiers that should be
excluded from mangling. Example: `["foo", "bar"]`.
- `toplevel` (default `false`). Pass `true` to mangle names declared in the
- `toplevel` (default `false`) -- Pass `true` to mangle names declared in the
top level scope.
- `safari10` (default `false`). Pass `true` to work around the Safari 10 loop
- `safari10` (default `false`) -- Pass `true` to work around the Safari 10 loop
iterator [bug](https://bugs.webkit.org/show_bug.cgi?id=171041)
"Cannot declare a let variable twice".
See also: the `safari10` [output option](#output-options).
Examples:
@@ -895,6 +922,10 @@ can pass additional arguments that control the code output:
- `2` -- always use double quotes
- `3` -- always use the original quotes
- `safari10` (default `false`) -- set this option to `true` to work around
the [Safari 10/11 await bug](https://bugs.webkit.org/show_bug.cgi?id=176685).
See also: the `safari10` [mangle option](#mangle-options).
- `semicolons` (default `true`) -- separate statements with semicolons. If
you pass `false` then whenever possible we will use a newline instead of a
semicolon, leading to more readable output of uglified code (size before
@@ -902,6 +933,9 @@ can pass additional arguments that control the code output:
- `shebang` (default `true`) -- preserve shebang `#!` in preamble (bash scripts)
- `webkit` (default `false`) -- enable workarounds for WebKit bugs.
PhantomJS users should set this option to `true`.
- `width` (default `80`) -- only takes effect when beautification is on, this
specifies an (orientative) line width that the beautifier will try to
obey. It refers to the width of the line text (excluding indentation).

View File

@@ -15,7 +15,7 @@ var path = require("path");
var program = require("commander");
var UglifyJS = require("../tools/node");
var skip_keys = [ "cname", "enclosed", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
var skip_keys = [ "cname", "enclosed", "inlined", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
var files = {};
var options = {
compress: false,
@@ -46,8 +46,11 @@ program.option("--config-file <file>", "Read minify() options from JSON file.");
program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define"));
program.option("--ecma <version>", "Specify ECMAScript release: 5, 6, 7 or 8.");
program.option("--ie8", "Support non-standard Internet Explorer 8.");
program.option("--keep-classnames", "Do not mangle/drop class names.");
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
program.option("--name-cache <file>", "File to hold mangled name mappings.");
program.option("--no-rename", "Disable symbol expansion.");
program.option("--safari10", "Support non-standard Safari 10.");
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_source_map());
program.option("--timings", "Display operations run time on STDERR.")
@@ -66,11 +69,14 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
"compress",
"ie8",
"mangle",
"rename",
"safari10",
"sourceMap",
"toplevel",
"wrap"
].forEach(function(name) {
if (name in program) {
if (name == "rename" && program[name]) return;
options[name] = program[name];
}
});
@@ -95,6 +101,9 @@ if (program.define) {
options.compress.global_defs[expr] = program.define[expr];
}
}
if (program.keepClassnames) {
options.keep_classnames = true;
}
if (program.keepFnames) {
options.keep_fnames = true;
}

View File

@@ -87,7 +87,7 @@ function DEFNODE(type, props, methods, base) {
return ctor;
};
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before file raw", {
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before comments_after file raw", {
}, null);
var AST_Node = DEFNODE("Node", "start end", {
@@ -313,9 +313,9 @@ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
},
get_defun_scope: function () {
get_defun_scope: function() {
var self = this;
while (self.is_block_scope() && self.parent_scope) {
while (self.is_block_scope()) {
self = self.parent_scope;
}
return self;
@@ -389,15 +389,15 @@ var AST_Accessor = DEFNODE("Accessor", null, {
$documentation: "A setter/getter function. The `name` property is always null."
}, AST_Lambda);
var AST_Function = DEFNODE("Function", null, {
var AST_Function = DEFNODE("Function", "inlined", {
$documentation: "A function expression"
}, AST_Lambda);
var AST_Arrow = DEFNODE("Arrow", null, {
var AST_Arrow = DEFNODE("Arrow", "inlined", {
$documentation: "An ES6 Arrow function ((a) => b)"
}, AST_Lambda);
var AST_Defun = DEFNODE("Defun", null, {
var AST_Defun = DEFNODE("Defun", "inlined", {
$documentation: "A function definition"
}, AST_Lambda);
@@ -908,7 +908,7 @@ var AST_ConciseMethod = DEFNODE("ConciseMethod", "quote static is_generator asyn
$documentation: "An ES6 concise method inside an object or class"
}, AST_ObjectProperty);
var AST_Class = DEFNODE("Class", "name extends properties", {
var AST_Class = DEFNODE("Class", "name extends properties inlined", {
$propdoc: {
name: "[AST_SymbolClass|AST_SymbolDefClass?] optional class name.",
extends: "[AST_Node]? optional parent class",
@@ -1203,24 +1203,6 @@ TreeWalker.prototype = {
}
}
},
in_boolean_context: function() {
var stack = this.stack;
var i = stack.length, self = stack[--i];
while (i > 0) {
var p = stack[--i];
if ((p instanceof AST_If && p.condition === self) ||
(p instanceof AST_Conditional && p.condition === self) ||
(p instanceof AST_DWLoop && p.condition === self) ||
(p instanceof AST_For && p.condition === self) ||
(p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self))
{
return true;
}
if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||")))
return false;
self = p;
}
},
loopcontrol_target: function(node) {
var stack = this.stack;
if (node.label) for (var i = stack.length; --i >= 0;) {

File diff suppressed because it is too large Load Diff

View File

@@ -51,11 +51,14 @@ function minify(files, options) {
compress: {},
ecma: undefined,
ie8: false,
keep_classnames: undefined,
keep_fnames: false,
mangle: {},
nameCache: null,
output: {},
parse: {},
rename: undefined,
safari10: false,
sourceMap: false,
timings: false,
toplevel: false,
@@ -65,9 +68,17 @@ function minify(files, options) {
var timings = options.timings && {
start: Date.now()
};
if (options.keep_classnames === undefined) {
options.keep_classnames = options.keep_fnames;
}
if (options.rename === undefined) {
options.rename = options.compress && options.mangle;
}
set_shorthand("ecma", options, [ "parse", "compress", "output" ]);
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
set_shorthand("keep_classnames", options, [ "compress", "mangle" ]);
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
set_shorthand("safari10", options, [ "mangle", "output" ]);
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
set_shorthand("warnings", options, [ "compress" ]);
var quoted_props;
@@ -141,6 +152,11 @@ function minify(files, options) {
if (options.wrap) {
toplevel = toplevel.wrap_commonjs(options.wrap);
}
if (timings) timings.rename = Date.now();
if (options.rename) {
toplevel.figure_out_scope(options.mangle);
toplevel.expand_names(options.mangle);
}
if (timings) timings.compress = Date.now();
if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
if (timings) timings.scope = Date.now();
@@ -201,7 +217,8 @@ function minify(files, options) {
if (timings) {
timings.end = Date.now();
result.timings = {
parse: 1e-3 * (timings.compress - timings.parse),
parse: 1e-3 * (timings.rename - timings.parse),
rename: 1e-3 * (timings.compress - timings.rename),
compress: 1e-3 * (timings.scope - timings.compress),
scope: 1e-3 * (timings.mangle - timings.scope),
mangle: 1e-3 * (timings.properties - timings.mangle),

View File

@@ -52,6 +52,7 @@ function is_some_comments(comment) {
function OutputStream(options) {
var readonly = !options;
options = defaults(options, {
ascii_only : false,
beautify : false,
@@ -68,6 +69,7 @@ function OutputStream(options) {
preserve_line : false,
quote_keys : false,
quote_style : 0,
safari10 : false,
semicolons : true,
shebang : true,
shorthand : undefined,
@@ -132,11 +134,16 @@ function OutputStream(options) {
}
});
} : function(str) {
return str.replace(/[\ud800-\udbff](?![\udc00-\udfff])/g, function(ch) {
return "\\u" + ch.charCodeAt(0).toString(16);
}).replace(/(^|[^\ud800-\udbff])([\udc00-\udfff])/g, function(match, prefix, ch) {
return prefix + "\\u" + ch.charCodeAt(0).toString(16);
});
var s = "";
for (var i = 0, len = str.length; i < len; i++) {
if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
|| is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
s += "\\u" + str.charCodeAt(i).toString(16);
} else {
s += str[i];
}
}
return s;
};
function make_string(str, quote) {
@@ -209,6 +216,9 @@ function OutputStream(options) {
var might_need_space = false;
var might_need_semicolon = false;
var might_add_newline = 0;
var need_newline_indented = false;
var need_space = false;
var newline_insert = -1;
var last = "";
var mapping_token, mapping_name, mappings = options.source_map && [];
@@ -268,6 +278,21 @@ function OutputStream(options) {
str = String(str);
var ch = get_full_char(str, 0);
var prev = get_full_char(last, last.length - 1);
if (need_newline_indented && ch) {
need_newline_indented = false;
if (ch != "\n") {
print("\n");
indent();
}
}
if (need_space && ch) {
need_space = false;
if (!/[\s;})]/.test(ch)) {
space();
}
}
newline_insert = -1;
var prev = last.charAt(last.length - 1);
if (might_need_semicolon) {
might_need_semicolon = false;
@@ -369,7 +394,13 @@ function OutputStream(options) {
} : function(col, cont) { return cont() };
var newline = options.beautify ? function() {
print("\n");
if (newline_insert < 0) return print("\n");
if (OUTPUT[newline_insert] != "\n") {
OUTPUT = OUTPUT.slice(0, newline_insert) + "\n" + OUTPUT.slice(newline_insert);
current_pos++;
current_line++;
}
newline_insert++;
} : options.max_line_len ? function() {
ensure_line_len();
might_add_newline = OUTPUT.length;
@@ -441,6 +472,118 @@ function OutputStream(options) {
return OUTPUT;
};
function prepend_comments(node) {
var self = this;
var start = node.start;
if (!start) return;
if (!(start.comments_before && start.comments_before._dumped === self)) {
var comments = start.comments_before;
if (!comments) {
comments = start.comments_before = [];
}
comments._dumped = self;
if (node instanceof AST_Exit && node.value) {
var tw = new TreeWalker(function(node) {
var parent = tw.parent();
if (parent instanceof AST_Exit
|| parent instanceof AST_Binary && parent.left === node
|| parent.TYPE == "Call" && parent.expression === node
|| parent instanceof AST_Conditional && parent.condition === node
|| parent instanceof AST_Dot && parent.expression === node
|| parent instanceof AST_Sequence && parent.expressions[0] === node
|| parent instanceof AST_Sub && parent.expression === node
|| parent instanceof AST_UnaryPostfix) {
if (!node.start) return;
var text = node.start.comments_before;
if (text && text._dumped !== self) {
text._dumped = self;
comments = comments.concat(text);
}
} else {
return true;
}
});
tw.push(node);
node.value.walk(tw);
}
if (current_pos == 0) {
if (comments.length > 0 && options.shebang && comments[0].type == "comment5") {
print("#!" + comments.shift().value + "\n");
indent();
}
var preamble = options.preamble;
if (preamble) {
print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
}
}
comments = comments.filter(comment_filter, node);
if (comments.length == 0) return;
var last_nlb = /(^|\n) *$/.test(OUTPUT);
comments.forEach(function(c, i) {
if (!last_nlb) {
if (c.nlb) {
print("\n");
indent();
last_nlb = true;
} else if (i > 0) {
space();
}
}
if (/comment[134]/.test(c.type)) {
print("//" + c.value.replace(/[@#]__PURE__/g, ' ') + "\n");
indent();
last_nlb = true;
} else if (c.type == "comment2") {
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
last_nlb = false;
}
});
if (!last_nlb) {
if (start.nlb) {
print("\n");
indent();
} else {
space();
}
}
}
}
function append_comments(node, tail) {
var self = this;
var token = node.end;
if (!token) return;
var comments = token[tail ? "comments_before" : "comments_after"];
if (comments && comments._dumped !== self) {
comments._dumped = self;
var insert = OUTPUT.length;
comments.filter(comment_filter, node).forEach(function(c, i) {
need_space = false;
if (need_newline_indented) {
print("\n");
indent();
need_newline_indented = false;
} else if (c.nlb && (i > 0 || !/(^|\n) *$/.test(OUTPUT))) {
print("\n");
indent();
} else if (i > 0 || !tail) {
space();
}
if (/comment[134]/.test(c.type)) {
print("//" + c.value.replace(/[@#]__PURE__/g, ' '));
need_newline_indented = true;
} else if (c.type == "comment2") {
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
need_space = true;
}
});
if (OUTPUT.length > insert) newline_insert = insert;
}
}
var stack = [];
return {
get : get,
@@ -483,7 +626,8 @@ function OutputStream(options) {
with_square : with_square,
add_mapping : add_mapping,
option : function(opt) { return options[opt] },
comment_filter : comment_filter,
prepend_comments: readonly ? noop : prepend_comments,
append_comments : readonly ? noop : append_comments,
line : function() { return current_line },
col : function() { return current_col },
pos : function() { return current_pos },
@@ -519,9 +663,10 @@ function OutputStream(options) {
use_asm = active_scope;
}
function doit() {
self.add_comments(stream);
stream.prepend_comments(self);
self.add_source_map(stream);
generator(self, stream);
stream.append_comments(self);
}
stream.push_node(self);
if (force_parens || self.needs_parens(stream)) {
@@ -538,77 +683,10 @@ function OutputStream(options) {
AST_Node.DEFMETHOD("print_to_string", function(options){
var s = OutputStream(options);
if (!options) s._readonly = true;
this.print(s);
return s.get();
});
/* -----[ comments ]----- */
AST_Node.DEFMETHOD("add_comments", function(output){
if (output._readonly) return;
var self = this;
var start = self.start;
if (start && !start._comments_dumped) {
start._comments_dumped = true;
var comments = start.comments_before || [];
// XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112
// and https://github.com/mishoo/UglifyJS2/issues/372
if (self instanceof AST_Exit && self.value) {
self.value.walk(new TreeWalker(function(node){
if (node.start && node.start.comments_before) {
comments = comments.concat(node.start.comments_before);
node.start.comments_before = [];
}
if (node instanceof AST_Function ||
node instanceof AST_Array ||
node instanceof AST_Object)
{
return true; // don't go inside.
}
}));
}
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) &&
output.col() !== 0 && comments[0].nlb)
{
output.print("\n");
}
comments.forEach(function(c){
if (/comment[134]/.test(c.type)) {
output.print("//" + c.value + "\n");
output.indent();
}
else if (c.type == "comment2") {
output.print("/*" + c.value + "*/");
if (start.nlb) {
output.print("\n");
output.indent();
} else {
output.space();
}
}
});
}
});
/* -----[ PARENTHESES ]----- */
function PARENS(nodetype, func) {
@@ -677,7 +755,8 @@ function OutputStream(options) {
PARENS(AST_Await, function(output){
var p = output.parent();
return p instanceof AST_PropAccess && p.expression === this
|| p instanceof AST_Call && p.expression === this;
|| p instanceof AST_Call && p.expression === this
|| output.option("safari10") && p instanceof AST_UnaryPrefix;
});
PARENS(AST_Sequence, function(output){
@@ -895,14 +974,21 @@ function OutputStream(options) {
self.body.print(output);
output.semicolon();
});
function print_bracketed(body, output, allow_directives) {
if (body.length > 0) output.with_block(function(){
display_body(body, false, output, allow_directives);
});
else output.print("{}");
function print_bracketed(self, output, allow_directives) {
if (self.body.length > 0) {
output.with_block(function() {
display_body(self.body, false, output, allow_directives);
});
} else {
output.print("{");
output.with_indent(output.next_indent(), function() {
output.append_comments(self, true);
});
output.print("}");
}
};
DEFPRINT(AST_BlockStatement, function(self, output){
print_bracketed(self.body, output);
print_bracketed(self, output);
});
DEFPRINT(AST_EmptyStatement, function(self, output){
output.semicolon();
@@ -1014,7 +1100,7 @@ function OutputStream(options) {
});
});
output.space();
print_bracketed(self.body, output, true);
print_bracketed(self, output, true);
});
DEFPRINT(AST_Lambda, function(self, output){
self._do_print(output);
@@ -1069,7 +1155,7 @@ function OutputStream(options) {
if (self.body instanceof AST_Node) {
self.body.print(output);
} else {
print_bracketed(self.body, output);
print_bracketed(self, output);
}
if (needs_parens) { output.print(")") }
});
@@ -1226,7 +1312,7 @@ function OutputStream(options) {
DEFPRINT(AST_Try, function(self, output){
output.print("try");
output.space();
print_bracketed(self.body, output);
print_bracketed(self, output);
if (self.bcatch) {
output.space();
self.bcatch.print(output);
@@ -1243,12 +1329,12 @@ function OutputStream(options) {
self.argname.print(output);
});
output.space();
print_bracketed(self.body, output);
print_bracketed(self, output);
});
DEFPRINT(AST_Finally, function(self, output){
output.print("finally");
output.space();
print_bracketed(self.body, output);
print_bracketed(self, output);
});
/* -----[ var/const ]----- */
@@ -1361,6 +1447,7 @@ function OutputStream(options) {
self.exported_value.print(output);
} else if (self.exported_definition) {
self.exported_definition.print(output);
if (self.exported_definition instanceof AST_Definitions) return;
}
if (self.module_name) {
output.space();
@@ -1623,7 +1710,8 @@ function OutputStream(options) {
if (allowShortHand &&
self.value instanceof AST_Symbol &&
is_identifier_string(self.key) &&
get_name(self.value) === self.key
get_name(self.value) === self.key &&
is_identifier(self.key)
) {
print_property_name(self.key, self.quote, output);

View File

@@ -365,11 +365,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
}
if (!is_comment) {
ret.comments_before = S.comments_before;
S.comments_before = [];
// make note of any newlines in the comments that came before
for (var i = 0, len = ret.comments_before.length; i < len; i++) {
ret.nlb = ret.nlb || ret.comments_before[i].nlb;
}
ret.comments_after = S.comments_before = [];
}
S.newline_before = false;
return new AST_Token(ret);
@@ -982,7 +978,7 @@ function parse($TEXT, options) {
}
};
var statement = embed_tokens(function() {
var statement = embed_tokens(function(is_export_default) {
handle_regexp();
switch (S.token.type) {
case "string":
@@ -1011,7 +1007,7 @@ function parse($TEXT, options) {
if (S.token.value == "async" && is_token(peek(), "keyword", "function")) {
next();
next();
return function_(AST_Defun, false, true);
return function_(AST_Defun, false, true, is_export_default);
}
if (S.token.value == "import" && !is_token(peek(), "punc", "(")) {
next();
@@ -1085,7 +1081,7 @@ function parse($TEXT, options) {
case "function":
next();
return function_(AST_Defun);
return function_(AST_Defun, false, false, is_export_default);
case "if":
next();
@@ -1308,9 +1304,9 @@ function parse($TEXT, options) {
});
};
var function_ = function(ctor, is_generator_property, is_async) {
var function_ = function(ctor, is_generator_property, is_async, is_export_default) {
if (is_generator_property && is_async) croak("generators cannot be async");
var start = S.token
var start = S.token;
var in_statement = ctor === AST_Defun;
var is_generator = is("operator", "*");
@@ -1319,8 +1315,13 @@ function parse($TEXT, options) {
}
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
if (in_statement && !name)
unexpected();
if (in_statement && !name) {
if (is_export_default) {
ctor = AST_Function;
} else {
unexpected();
}
}
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
unexpected(prev());
@@ -2053,8 +2054,29 @@ function parse($TEXT, options) {
}) : exprs.length == 1 ? exprs[0] : new AST_Sequence({
expressions: exprs
});
if (ex.start) {
var len = start.comments_before.length;
[].unshift.apply(ex.start.comments_before, start.comments_before);
start.comments_before = ex.start.comments_before;
start.comments_before_length = len;
if (len == 0 && start.comments_before.length > 0) {
var comment = start.comments_before[0];
if (!comment.nlb) {
comment.nlb = start.nlb;
start.nlb = false;
}
}
start.comments_after = ex.start.comments_after;
}
ex.start = start;
ex.end = S.token;
var end = prev();
if (ex.end) {
end.comments_before = ex.end.comments_before;
[].push.apply(ex.end.comments_after, end.comments_after);
end.comments_after = ex.end.comments_after;
}
ex.end = end;
if (ex instanceof AST_Call) mark_pure(ex);
return subscripts(ex, allow_calls);
case "[":
return subscripts(array_(), allow_calls);
@@ -2107,7 +2129,8 @@ function parse($TEXT, options) {
}));
while (S.token.end === false) {
next();
segments.push(expression());
handle_regexp();
segments.push(expression(true));
if (!is_token("template_substitution")) {
unexpected();
@@ -2527,9 +2550,9 @@ function parse($TEXT, options) {
&& is_token(peek(), "punc")) {
exported_value = expression(false);
semicolon();
} else if ((node = statement()) instanceof AST_Definitions && is_default) {
} else if ((node = statement(is_default)) instanceof AST_Definitions && is_default) {
unexpected(node.start);
} else if (node instanceof AST_Definitions || node instanceof AST_Defun || node instanceof AST_DefClass) {
} else if (node instanceof AST_Definitions || node instanceof AST_Lambda || node instanceof AST_DefClass) {
exported_definition = node;
} else if (node instanceof AST_SimpleStatement) {
exported_value = node.body;
@@ -2619,6 +2642,19 @@ function parse($TEXT, options) {
return sym;
};
function mark_pure(call) {
var start = call.start;
var comments = start.comments_before;
var i = HOP(start, "comments_before_length") ? start.comments_before_length : comments.length;
while (--i >= 0) {
var comment = comments[i];
if (/[@#]__PURE__/.test(comment.value)) {
call.pure = comment;
break;
}
}
}
var subscripts = function(expr, allow_calls) {
var start = expr.start;
if (is("punc", ".")) {
@@ -2643,12 +2679,14 @@ function parse($TEXT, options) {
}
if (allow_calls && is("punc", "(")) {
next();
return subscripts(new AST_Call({
var call = new AST_Call({
start : start,
expression : expr,
args : call_args(),
end : prev()
}), true);
});
mark_pure(call);
return subscripts(call, true);
}
if (is("template_head")) {
return subscripts(new AST_PrefixedTemplateString({
@@ -2730,7 +2768,8 @@ function parse($TEXT, options) {
var op = is("operator") ? S.token.value : null;
if (op == "in" && no_in) op = null;
if (op == "**" && left instanceof AST_UnaryPrefix
&& left.end === S.prev /* unary token in front not allowed, but allowed if prev is for example `)` */
/* unary token in front not allowed - parenthesis required */
&& !is_token(left.start, "punc", "(")
&& left.operator !== "--" && left.operator !== "++")
unexpected(left.start);
var prec = op != null ? PRECEDENCE[op] : null;

View File

@@ -104,7 +104,7 @@ function reserve_quoted_keys(ast, reserved) {
function addStrings(node, add) {
node.walk(new TreeWalker(function(node) {
if (node instanceof AST_Sequence) {
addStrings(node.expressions[node.expressions.length - 1], add);
addStrings(node.tail_node(), add);
} else if (node instanceof AST_String) {
add(node.value);
} else if (node instanceof AST_Conditional) {

View File

@@ -43,16 +43,17 @@
"use strict";
function SymbolDef(scope, index, orig) {
function SymbolDef(scope, orig) {
this.name = orig.name;
this.orig = [ orig ];
this.eliminated = 0;
this.scope = scope;
this.references = [];
this.replaced = 0;
this.global = false;
this.export = false;
this.mangled_name = null;
this.undeclared = false;
this.index = index;
this.id = SymbolDef.next_id++;
};
@@ -182,11 +183,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
// scope when we encounter the AST_Defun node (which is
// instanceof AST_Scope) but we get to the symbol a bit
// later.
var parent_lambda = defun.parent_scope;
while (parent_lambda.is_block_scope()) {
parent_lambda = parent_lambda.parent_scope;
}
mark_export((node.scope = parent_lambda).def_function(node), 1);
mark_export((node.scope = defun.parent_scope.get_defun_scope()).def_function(node), 1);
}
else if (node instanceof AST_SymbolClass) {
mark_export(defun.def_variable(node), 1);
@@ -344,7 +341,7 @@ AST_Toplevel.DEFMETHOD("def_global", function(node){
if (globals.has(name)) {
return globals.get(name);
} else {
var g = new SymbolDef(this, globals.size(), node);
var g = new SymbolDef(this, node);
g.undeclared = true;
g.global = true;
globals.set(name, g);
@@ -415,7 +412,7 @@ AST_Scope.DEFMETHOD("def_function", function(symbol){
AST_Scope.DEFMETHOD("def_variable", function(symbol){
var def;
if (!this.variables.has(symbol.name)) {
def = new SymbolDef(this, this.variables.size(), symbol);
def = new SymbolDef(this, symbol);
this.variables.set(symbol.name, def);
def.global = !this.parent_scope;
} else {
@@ -433,7 +430,7 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
// shadow a name reserved from mangling.
if (options.reserved.indexOf(m) >= 0) continue;
if (member(m, options.reserved)) continue;
// we must ensure that the mangled name does not shadow a name
// from some parent scope that is referenced in this or in
@@ -485,7 +482,7 @@ AST_Symbol.DEFMETHOD("global", function(){
return this.definition().global;
});
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
options = defaults(options, {
eval : false,
ie8 : false,
@@ -495,15 +492,14 @@ AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
toplevel : false,
});
if (!Array.isArray(options.reserved)) options.reserved = [];
// Never mangle arguments
push_uniq(options.reserved, "arguments");
return options;
});
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
options = this._default_mangler_options(options);
// Never mangle arguments
options.reserved.push('arguments');
// We only need to mangle declaration nodes. Special logic wired
// into the code generator will display the mangled name if it's
// present (and for AST_SymbolRef-s it'll use the mangled name of
@@ -512,11 +508,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
var to_mangle = [];
if (options.cache) {
this.globals.each(function(symbol){
if (options.reserved.indexOf(symbol.name) < 0) {
to_mangle.push(symbol);
}
});
this.globals.each(collect);
}
var tw = new TreeWalker(function(node, descend){
@@ -528,13 +520,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
return true; // don't descend again in TreeWalker
}
if (node instanceof AST_Scope) {
var p = tw.parent(), a = [];
node.variables.each(function(symbol){
if (options.reserved.indexOf(symbol.name) < 0) {
a.push(symbol);
}
});
to_mangle.push.apply(to_mangle, a);
node.variables.each(collect);
return;
}
if (node instanceof AST_Label) {
@@ -559,6 +545,79 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
if (options.cache) {
options.cache.cname = this.cname;
}
function collect(symbol) {
if (!member(symbol.name, options.reserved)) {
to_mangle.push(symbol);
}
}
});
AST_Toplevel.DEFMETHOD("find_unique_prefix", function(options) {
var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
var cache = options.cache && options.cache.props;
var prefixes = Object.create(null);
options.reserved.forEach(add_prefix);
this.globals.each(add_def);
this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(add_def);
if (node instanceof AST_SymbolCatch) add_def(node.definition());
}));
var prefix, i = 0;
do {
prefix = create_name(i++);
} while (prefixes[prefix]);
return prefix;
function add_prefix(name) {
if (/[0-9]$/.test(name)) {
prefixes[name.replace(/[0-9]+$/, "")] = true;
}
}
function add_def(def) {
var name = def.name;
if (def.global && cache && cache.has(name)) name = cache.get(name);
else if (!def.unmangleable(options)) return;
add_prefix(name);
}
function create_name(num) {
var name = "";
do {
name += letters[num % letters.length];
num = Math.floor(num / letters.length);
} while (num);
return name;
}
});
AST_Toplevel.DEFMETHOD("expand_names", function(options) {
options = this._default_mangler_options(options);
var prefix = this.find_unique_prefix(options);
this.globals.each(rename);
this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(rename);
if (node instanceof AST_SymbolCatch) rename(node.definition());
}));
function rename(def) {
if (def.global || def.unmangleable(options)) return;
if (member(def.name, options.reserved)) return;
var d = def.redefined();
def.name = d ? d.name : prefix + def.id;
def.orig.forEach(function(sym) {
sym.name = def.name;
});
def.references.forEach(function(sym) {
sym.name = def.name;
});
}
});
AST_Node.DEFMETHOD("tail_node", return_this);
AST_Sequence.DEFMETHOD("tail_node", function() {
return this.expressions[this.expressions.length - 1];
});
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
@@ -589,7 +648,7 @@ AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
skip_string(node.consequent);
skip_string(node.alternative);
} else if (node instanceof AST_Sequence) {
skip_string(node.expressions[node.expressions.length - 1]);
skip_string(node.tail_node());
}
}
});

View File

@@ -60,12 +60,9 @@ TreeTransformer.prototype = new TreeWalker;
tw.push(this);
if (tw.before) x = tw.before(this, descend, in_list);
if (x === undefined) {
if (!tw.after) {
x = this;
descend(x, tw);
} else {
tw.stack[tw.stack.length - 1] = x = this;
descend(x, tw);
x = this;
descend(x, tw);
if (tw.after) {
y = tw.after(x, in_list);
if (y !== undefined) x = y;
}

View File

@@ -43,10 +43,6 @@
"use strict";
function slice(a, start) {
return Array.prototype.slice.call(a, start || 0);
};
function characters(str) {
return str.split("");
};
@@ -214,18 +210,6 @@ function mergeSort(array, cmp) {
return _ms(array);
};
function set_difference(a, b) {
return a.filter(function(el){
return b.indexOf(el) < 0;
});
};
function set_intersection(a, b) {
return a.filter(function(el){
return b.indexOf(el) >= 0;
});
};
// this function is taken from Acorn [1], written by Marijn Haverbeke
// [1] https://github.com/marijnh/acorn
function makePredicate(words) {
@@ -340,7 +324,7 @@ function first_in_statement(stack) {
if (p instanceof AST_Statement && p.body === node)
return true;
if ((p instanceof AST_Sequence && p.expressions[0] === node) ||
(p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||
(p.TYPE == "Call" && p.expression === node ) ||
(p instanceof AST_Dot && p.expression === node ) ||
(p instanceof AST_Sub && p.expression === node ) ||
(p instanceof AST_Conditional && p.condition === node ) ||

View File

@@ -4,7 +4,7 @@
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.1.8",
"version": "3.3.0",
"engines": {
"node": ">=0.8.0"
},
@@ -26,11 +26,11 @@
"LICENSE"
],
"dependencies": {
"commander": "~2.11.0",
"commander": "~2.12.1",
"source-map": "~0.6.1"
},
"devDependencies": {
"acorn": "~5.1.1",
"acorn": "~5.2.1",
"mocha": "~3.5.1",
"semver": "~5.4.1"
},

View File

@@ -204,6 +204,7 @@ constant_join_3: {
for_loop: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unsafe: true,
unused: true,
@@ -260,6 +261,7 @@ for_loop: {
index: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
@@ -278,6 +280,7 @@ index: {
length: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
@@ -296,6 +299,7 @@ length: {
index_length: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,

View File

@@ -288,6 +288,7 @@ issue_2105_1: {
ecma: 6,
inline: true,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unsafe_methods: true,
@@ -330,6 +331,7 @@ issue_2105_2: {
collapse_vars: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -401,6 +403,7 @@ issue_2136_3: {
evaluate: true,
inline: true,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -428,6 +431,7 @@ call_args: {
ecma: 6,
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
}
input: {
@@ -452,6 +456,7 @@ call_args_drop_param: {
evaluate: true,
inline: true,
keep_fargs: false,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -478,6 +483,7 @@ issue_485_crashing_1530: {
ecma: 6,
evaluate: true,
inline: true,
side_effects: true,
}
input: {
(function(a) {
@@ -485,9 +491,7 @@ issue_485_crashing_1530: {
var b = 42;
})(this);
}
expect: {
this, void 0;
}
expect: {}
}
issue_2084: {
@@ -499,6 +503,7 @@ issue_2084: {
evaluate: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,

View File

@@ -16,7 +16,6 @@ asm_mixed: {
hoist_vars : true,
if_return : true,
join_vars : true,
cascade : true,
side_effects : true,
negate_iife : true
};

View File

@@ -141,6 +141,7 @@ async_inline: {
evaluate: true,
inline: true,
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -292,3 +293,31 @@ async_arrow_iife_negate_iife: {
}
expect_exact: "(async()=>{await fetch()})();(()=>{plain()})();"
}
issue_2344_1: {
beautify = {
safari10: false,
}
input: {
async () => {
+await x;
await y;
return await z;
};
}
expect_exact: "async()=>{+await x;await y;return await z};"
}
issue_2344_2: {
beautify = {
safari10: true,
}
input: {
async () => {
+await x;
await y;
return await z;
};
}
expect_exact: "async()=>{+(await x);await y;return await z};"
}

File diff suppressed because it is too large Load Diff

View File

@@ -96,6 +96,7 @@ self_comparison_1: {
self_comparison_2: {
options = {
comparisons: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}

View File

@@ -166,22 +166,24 @@ cond_1: {
conditionals: true
};
input: {
var do_something; // if undeclared it's assumed to have side-effects
if (some_condition()) {
do_something(x);
} else {
do_something(y);
}
if (some_condition()) {
side_effects(x);
} else {
side_effects(y);
function foo(do_something, some_condition) {
if (some_condition) {
do_something(x);
} else {
do_something(y);
}
if (some_condition) {
side_effects(x);
} else {
side_effects(y);
}
}
}
expect: {
var do_something;
do_something(some_condition() ? x : y);
some_condition() ? side_effects(x) : side_effects(y);
function foo(do_something, some_condition) {
do_something(some_condition ? x : y);
some_condition ? side_effects(x) : side_effects(y);
}
}
}
@@ -190,16 +192,18 @@ cond_2: {
conditionals: true
};
input: {
var x, FooBar;
if (some_condition()) {
x = new FooBar(1);
} else {
x = new FooBar(2);
function foo(x, FooBar, some_condition) {
if (some_condition) {
x = new FooBar(1);
} else {
x = new FooBar(2);
}
}
}
expect: {
var x, FooBar;
x = new FooBar(some_condition() ? 1 : 2);
function foo(x, FooBar, some_condition) {
x = new FooBar(some_condition ? 1 : 2);
}
}
}
@@ -605,11 +609,47 @@ cond_8c: {
}
}
cond_9: {
options = {
conditionals: true,
}
input: {
function f(x, y) {
g() ? x(1) : x(2);
x ? (y || x)() : (y || x)();
x ? y(a, b) : y(d, b, c);
x ? y(a, b, c) : y(a, b, c);
x ? y(a, b, c) : y(a, b, f);
x ? y(a, b, c) : y(a, e, c);
x ? y(a, b, c) : y(a, e, f);
x ? y(a, b, c) : y(d, b, c);
x ? y(a, b, c) : y(d, b, f);
x ? y(a, b, c) : y(d, e, c);
x ? y(a, b, c) : y(d, e, f);
}
}
expect: {
function f(x, y) {
g() ? x(1) : x(2);
x, (y || x)();
x ? y(a, b) : y(d, b, c);
x, y(a, b, c);
y(a, b, x ? c : f);
y(a, x ? b : e, c);
x ? y(a, b, c) : y(a, e, f);
y(x ? a : d, b, c);
x ? y(a, b, c) : y(d, b, f);
x ? y(a, b, c) : y(d, e, c);
x ? y(a, b, c) : y(d, e, f);
}
}
}
ternary_boolean_consequent: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
keep_fargs:true, if_return:true, join_vars:true, side_effects:true
}
input: {
function f1() { return a == b ? true : x; }
@@ -637,7 +677,7 @@ ternary_boolean_alternative: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
keep_fargs:true, if_return:true, join_vars:true, side_effects:true
}
input: {
function f1() { return a == b ? x : true; }
@@ -1015,3 +1055,151 @@ delete_conditional_2: {
}
expect_stdout: true
}
issue_2535_1: {
options = {
booleans: true,
conditionals: true,
evaluate: true,
passes: 2,
side_effects: true,
}
input: {
if (true || x()) y();
if (true && x()) y();
if (x() || true) y();
if (x() && true) y();
if (false || x()) y();
if (false && x()) y();
if (x() || false) y();
if (x() && false) y();
}
expect: {
y();
x() && y();
(x(), 1) && y();
x() && y();
x() && y();
x() && y();
(x(), 0) && y();
}
}
issue_2535_2: {
options = {
booleans: true,
conditionals: true,
evaluate: true,
side_effects: true,
}
input: {
function x() {}
function y() {
return "foo";
}
console.log((x() || true) || y());
console.log((y() || true) || x());
console.log((x() || true) && y());
console.log((y() || true) && x());
console.log((x() && true) || y());
console.log((y() && true) || x());
console.log((x() && true) && y());
console.log((y() && true) && x());
console.log((x() || false) || y());
console.log((y() || false) || x());
console.log((x() || false) && y());
console.log((y() || false) && x());
console.log((x() && false) || y());
console.log((y() && false) || x());
console.log((x() && false) && y());
console.log((y() && false) && x());
}
expect: {
function x() {}
function y() {
return "foo";
}
console.log(x() || !0);
console.log(y() || !0);
console.log((x(), y()));
console.log((y(), x()));
console.log(!!x() || y());
console.log(!!y() || x());
console.log(x() && y());
console.log(y() && x());
console.log(x() || y());
console.log(y() || x());
console.log(!!x() && y());
console.log(!!y() && x());
console.log((x(), y()));
console.log((y(), x()));
console.log(x() && !1);
console.log(y() && !1);
}
expect_stdout: [
"true",
"foo",
"foo",
"undefined",
"foo",
"true",
"undefined",
"undefined",
"foo",
"foo",
"false",
"undefined",
"foo",
"undefined",
"undefined",
"false",
]
}
issue_2560: {
options = {
conditionals: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function log(x) {
console.log(x);
}
function foo() {
return log;
}
function bar() {
if (x !== (x = foo())) {
x(1);
} else {
x(2);
}
}
var x = function() {
console.log("init");
};
bar();
bar();
}
expect: {
function log(x) {
console.log(x);
}
function bar() {
x !== (x = log) ? x(1) : x(2);
}
var x = function() {
console.log("init");
};
bar();
bar();
}
expect_stdout: [
"1",
"2",
]
}

View File

@@ -12,6 +12,7 @@ issue_1191: {
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_funcs : true,
reduce_vars : true,
}
input: {
@@ -44,6 +45,7 @@ issue_1194: {
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_funcs : true,
reduce_vars : true,
}
input: {
@@ -72,6 +74,7 @@ issue_1396: {
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_funcs : true,
reduce_vars : true,
}
input: {
@@ -143,6 +146,7 @@ regexp_literal_not_const: {
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_funcs : true,
reduce_vars : true,
}
input: {

View File

@@ -129,8 +129,8 @@ dead_code_constant_boolean_should_warn_more: {
var bar;
// nothing for the while
// as for the for, it should keep:
var x = 10, y;
var moo;
var x = 10, y;
bar();
}
expect_stdout: true
@@ -165,8 +165,8 @@ dead_code_constant_boolean_should_warn_more_strict: {
var foo;
// nothing for the while
// as for the for, it should keep:
var x = 10, y;
var moo;
var x = 10, y;
bar();
}
expect_stdout: true
@@ -175,10 +175,11 @@ dead_code_constant_boolean_should_warn_more_strict: {
dead_code_block_decls_die: {
options = {
dead_code : true,
conditionals : true,
booleans : true,
evaluate : true
booleans: true,
conditionals: true,
dead_code: true,
evaluate: true,
side_effects: true,
};
input: {
if (0) {
@@ -197,12 +198,14 @@ dead_code_block_decls_die: {
dead_code_const_declaration: {
options = {
dead_code : true,
loops : true,
booleans : true,
conditionals : true,
evaluate : true,
reduce_vars : true,
booleans: true,
conditionals: true,
dead_code: true,
evaluate: true,
loops: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
};
input: {
var unused;
@@ -224,13 +227,15 @@ dead_code_const_declaration: {
dead_code_const_annotation: {
options = {
dead_code : true,
loops : true,
booleans : true,
conditionals : true,
evaluate : true,
reduce_vars : true,
toplevel : true,
booleans: true,
conditionals: true,
dead_code: true,
evaluate: true,
loops: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
};
input: {
var unused;
@@ -276,13 +281,16 @@ dead_code_const_annotation_regex: {
dead_code_const_annotation_complex_scope: {
options = {
dead_code : true,
loops : true,
booleans : true,
conditionals : true,
evaluate : true,
reduce_vars : true,
toplevel : true,
booleans: true,
conditionals: true,
dead_code: true,
evaluate: true,
loops: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
};
input: {
var unused_var;
@@ -325,6 +333,8 @@ try_catch_finally: {
conditionals: true,
dead_code: true,
evaluate: true,
passes: 2,
side_effects: true,
}
input: {
var a = 1;
@@ -439,6 +449,7 @@ global_timeout_and_interval_symbols: {
issue_2233_2: {
options = {
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unsafe: true,
@@ -470,6 +481,7 @@ issue_2233_2: {
issue_2233_3: {
options = {
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -566,6 +578,7 @@ issue_2383_1: {
conditionals: true,
dead_code: true,
evaluate: true,
side_effects: true,
}
input: {
if (0) {
@@ -582,6 +595,7 @@ issue_2383_2: {
conditionals: true,
dead_code: true,
evaluate: true,
side_effects: true,
}
input: {
if (0) {
@@ -605,6 +619,7 @@ issue_2383_3: {
conditionals: true,
dead_code: true,
evaluate: true,
side_effects: true,
}
input: {
var b = 7, y = 8;
@@ -621,3 +636,414 @@ issue_2383_3: {
expect_stdout: "undefined undefined 8 undefined 7"
node_version: ">=6"
}
collapse_vars_assignment: {
options = {
collapse_vars: true,
dead_code: true,
passes: 2,
unused: true,
}
input: {
function f0(c) {
var a = 3 / c;
return a = a;
}
}
expect: {
function f0(c) {
return 3 / c;
}
}
}
collapse_vars_lvalues_drop_assign: {
options = {
collapse_vars: true,
dead_code: true,
unused: true,
}
input: {
function f0(x) { var i = ++x; return x += i; }
function f1(x) { var a = (x -= 3); return x += a; }
function f2(x) { var z = x, a = ++z; return z += a; }
}
expect: {
function f0(x) { var i = ++x; return x + i; }
function f1(x) { var a = (x -= 3); return x + a; }
function f2(x) { var z = x, a = ++z; return z + a; }
}
}
collapse_vars_misc1: {
options = {
collapse_vars: true,
dead_code: true,
unused: true,
}
input: {
function f10(x) { var a = 5, b = 3; return a += b; }
function f11(x) { var a = 5, b = 3; return a += --b; }
}
expect: {
function f10(x) { return 5 + 3; }
function f11(x) { var b = 3; return 5 + --b; }
}
}
return_assignment: {
options = {
dead_code: true,
unused: true,
}
input: {
function f1(a, b, c) {
return a = x(), b = y(), b = a && (c >>= 5);
}
function f2() {
return e = x();
}
function f3(e) {
return e = x();
}
function f4() {
var e;
return e = x();
}
function f5(a) {
try {
return a = x();
} catch (b) {
console.log(a);
}
}
function f6(a) {
try {
return a = x();
} finally {
console.log(a);
}
}
function y() {
console.log("y");
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6 ].forEach(function(f, i) {
e = null;
try {
i += 1;
console.log("result " + f(10 * i, 100 * i, 1000 * i));
} catch (x) {
console.log("caught " + x);
}
if (null !== e) console.log("e: " + e);
});
}
var x, e;
test(1);
test(-1);
}
expect: {
function f1(a, b, c) {
return a = x(), y(), a && (c >> 5);
}
function f2() {
return e = x();
}
function f3(e) {
return x();
}
function f4() {
return x();
}
function f5(a) {
try {
return x();
} catch (b) {
console.log(a);
}
}
function f6(a) {
try {
return a = x();
} finally {
console.log(a);
}
}
function y() {
console.log("y");
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6 ].forEach(function(f, i) {
e = null;
try {
i += 1;
console.log("result " + f(10 * i, 100 * i, 1000 * i));
} catch (x) {
console.log("caught " + x);
}
if (null !== e) console.log("e: " + e);
});
}
var x, e;
test(1);
test(-1);
}
expect_stdout: [
"y",
"result 31",
"result 2",
"e: 2",
"result 3",
"result 4",
"result 5",
"6",
"result 6",
"caught -1",
"caught -2",
"caught -3",
"caught -4",
"50",
"result undefined",
"60",
"caught -6",
]
}
throw_assignment: {
options = {
dead_code: true,
unused: true,
}
input: {
function f1() {
throw a = x();
}
function f2(a) {
throw a = x();
}
function f3() {
var a;
throw a = x();
}
function f4() {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f5(a) {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f6() {
var a;
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f7() {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f8(a) {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f9() {
var a;
try {
throw a = x();
} finally {
console.log(a);
}
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6, f7, f8, f9 ].forEach(function(f, i) {
a = null;
try {
f(10 * (1 + i));
} catch (x) {
console.log("caught " + x);
}
if (null !== a) console.log("a: " + a);
});
}
var x, a;
test(1);
test(-1);
}
expect: {
function f1() {
throw a = x();
}
function f2(a) {
throw x();
}
function f3() {
throw x();
}
function f4() {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f5(a) {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f6() {
var a;
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f7() {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f8(a) {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f9() {
var a;
try {
throw a = x();
} finally {
console.log(a);
}
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6, f7, f8, f9 ].forEach(function(f, i) {
a = null;
try {
f(10 * (1 + i));
} catch (x) {
console.log("caught " + x);
}
if (null !== a) console.log("a: " + a);
});
}
var x, a;
test(1);
test(-1);
}
expect_stdout: [
"caught 1",
"a: 1",
"caught 2",
"caught 3",
"4",
"a: 4",
"5",
"6",
"7",
"caught 7",
"a: 7",
"8",
"caught 8",
"9",
"caught 9",
"caught -1",
"caught -2",
"caught -3",
"null",
"50",
"undefined",
"null",
"caught -7",
"80",
"caught -8",
"undefined",
"caught -9",
]
}
issue_2597: {
options = {
dead_code: true,
}
input: {
function f(b) {
try {
try {
throw "foo";
} catch (e) {
return b = true;
}
} finally {
b && (a = "PASS");
}
}
var a = "FAIL";
f();
console.log(a);
}
expect: {
function f(b) {
try {
try {
throw "foo";
} catch (e) {
return b = true;
}
} finally {
b && (a = "PASS");
}
}
var a = "FAIL";
f();
console.log(a);
}
expect_stdout: "PASS"
}

View File

@@ -262,6 +262,7 @@ destructuring_dont_evaluate_with_undefined_as_default_assignment: {
reduce_vars: {
options = {
reduce_funcs: true,
reduce_vars: true,
}
input: {

View File

@@ -260,7 +260,9 @@ keep_fnames: {
}
drop_assign: {
options = { unused: true };
options = {
unused: true,
}
input: {
function f1() {
var a;
@@ -281,7 +283,7 @@ drop_assign: {
var a;
return function() {
a = 1;
}
};
}
}
expect: {
@@ -298,16 +300,17 @@ drop_assign: {
return 1;
}
function f5() {
var a;
return function() {
a = 1;
}
1;
};
}
}
}
keep_assign: {
options = { unused: "keep_assign" };
options = {
unused: "keep_assign",
}
input: {
function f1() {
var a;
@@ -328,7 +331,7 @@ keep_assign: {
var a;
return function() {
a = 1;
}
};
}
}
expect: {
@@ -351,19 +354,22 @@ keep_assign: {
var a;
return function() {
a = 1;
}
};
}
}
}
drop_toplevel_funcs: {
options = { toplevel: "funcs", unused: true };
options = {
toplevel: "funcs",
unused: true,
}
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
}
};
}
a = 2;
function g() {}
@@ -379,13 +385,16 @@ drop_toplevel_funcs: {
}
drop_toplevel_vars: {
options = { toplevel: "vars", unused: true };
options = {
toplevel: "vars",
unused: true,
}
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
}
};
}
a = 2;
function g() {}
@@ -393,11 +402,10 @@ drop_toplevel_vars: {
console.log(b = 3);
}
expect: {
var c = g;
function f(d) {
return function() {
c = 2;
}
2;
};
}
2;
function g() {}
@@ -407,13 +415,17 @@ drop_toplevel_vars: {
}
drop_toplevel_vars_fargs: {
options = { keep_fargs: false, toplevel: "vars", unused: true };
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() {}
@@ -421,11 +433,10 @@ drop_toplevel_vars_fargs: {
console.log(b = 3);
}
expect: {
var c = g;
function f() {
return function() {
c = 2;
}
2;
};
}
2;
function g() {}
@@ -435,13 +446,16 @@ drop_toplevel_vars_fargs: {
}
drop_toplevel_all: {
options = { toplevel: true, unused: true };
options = {
toplevel: true,
unused: true
}
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
}
};
}
a = 2;
function g() {}
@@ -455,13 +469,16 @@ drop_toplevel_all: {
}
drop_toplevel_retain: {
options = { top_retain: "f,a,o", unused: true };
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() {}
@@ -469,26 +486,28 @@ drop_toplevel_retain: {
console.log(b = 3);
}
expect: {
var a, c = g;
var a;
function f(d) {
return function() {
c = 2;
}
2;
};
}
a = 2;
function g() {}
console.log(3);
}
}
drop_toplevel_retain_array: {
options = { top_retain: [ "f", "a", "o" ], unused: true };
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() {}
@@ -496,26 +515,28 @@ drop_toplevel_retain_array: {
console.log(b = 3);
}
expect: {
var a, c = g;
var a;
function f(d) {
return function() {
c = 2;
}
2;
};
}
a = 2;
function g() {}
console.log(3);
}
}
drop_toplevel_retain_regex: {
options = { top_retain: /^[fao]$/, unused: true };
options = {
top_retain: /^[fao]$/,
unused: true,
}
input: {
var a, b = 1, c = g;
function f(d) {
return function() {
c = 2;
}
};
}
a = 2;
function g() {}
@@ -523,26 +544,29 @@ drop_toplevel_retain_regex: {
console.log(b = 3);
}
expect: {
var a, c = g;
var a;
function f(d) {
return function() {
c = 2;
}
2;
};
}
a = 2;
function g() {}
console.log(3);
}
}
drop_toplevel_all_retain: {
options = { toplevel: true, top_retain: "f,a,o", unused: true };
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() {}
@@ -550,26 +574,29 @@ drop_toplevel_all_retain: {
console.log(b = 3);
}
expect: {
var a, c = g;
var a;
function f(d) {
return function() {
c = 2;
}
2;
};
}
a = 2;
function g() {}
console.log(3);
}
}
drop_toplevel_funcs_retain: {
options = { toplevel: "funcs", top_retain: "f,a,o", unused: true };
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() {}
@@ -581,7 +608,7 @@ drop_toplevel_funcs_retain: {
function f(d) {
return function() {
c = 2;
}
};
}
a = 2;
function g() {}
@@ -590,13 +617,17 @@ drop_toplevel_funcs_retain: {
}
drop_toplevel_vars_retain: {
options = { toplevel: "vars", top_retain: "f,a,o", unused: true };
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() {}
@@ -604,11 +635,11 @@ drop_toplevel_vars_retain: {
console.log(b = 3);
}
expect: {
var a, c = g;
var a;
function f(d) {
return function() {
c = 2;
}
2;
};
}
a = 2;
function g() {}
@@ -618,13 +649,16 @@ drop_toplevel_vars_retain: {
}
drop_toplevel_keep_assign: {
options = { toplevel: true, unused: "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() {}
@@ -733,6 +767,7 @@ drop_value: {
const_assign: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -763,7 +798,7 @@ const_assign: {
issue_1539: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
unused: true,
@@ -785,6 +820,7 @@ issue_1539: {
vardef_value: {
options = {
keep_fnames: false,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -809,7 +845,7 @@ vardef_value: {
assign_binding: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
unused: true,
}
@@ -846,6 +882,7 @@ assign_chain: {
issue_1583: {
options = {
keep_fargs: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -863,11 +900,11 @@ issue_1583: {
expect: {
function m(t) {
(function(e) {
t = function() {
(function() {
return (function(a) {
return function(a) {};
})();
}();
})();
})();
}
}
@@ -1200,6 +1237,7 @@ var_catch_toplevel: {
options = {
conditionals: true,
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -1231,7 +1269,7 @@ var_catch_toplevel: {
reassign_const: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
unused: true,
@@ -1298,7 +1336,8 @@ issue_2105_1: {
options = {
collapse_vars: true,
inline: true,
passes: 2,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -1338,9 +1377,10 @@ issue_2105_2: {
options = {
collapse_vars: true,
inline: true,
passes: 2,
passes: 3,
properties: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unsafe: true,
@@ -1422,6 +1462,7 @@ issue_2136_3: {
evaluate: true,
inline: true,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -1507,7 +1548,7 @@ issue_2226_1: {
issue_2226_2: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
unused: true,
@@ -1520,8 +1561,8 @@ issue_2226_2: {
}
expect: {
console.log(function(a, b) {
return a += b;
}(1, 2));
return a += 2;
}(1));
}
expect_stdout: "3"
}
@@ -1562,8 +1603,186 @@ issue_2288: {
expect: {
function foo(o) {
o.a;
for (i = 0; i < 0; i++);
for (var i = 0; i < 0; i++);
for (i = 0; i < 0; i++);
}
}
}
issue_2516_1: {
options = {
collapse_vars: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
function foo() {
function qux(x) {
bar.call(null, x);
}
function bar(x) {
var FOUR = 4;
var trouble = x || never_called();
var value = (FOUR - 1) * trouble;
console.log(value == 6 ? "PASS" : value);
}
Baz = qux;
}
var Baz;
foo();
Baz(2);
}
expect: {
function foo() {
Baz = function(x) {
(function(x) {
var trouble = x || never_called();
var value = (4 - 1) * trouble;
console.log(6 == value ? "PASS" : value);
}).call(null, x);
};
}
var Baz;
foo();
Baz(2);
}
}
issue_2516_2: {
options = {
collapse_vars: true,
reduce_funcs: true,
reduce_vars: true,
passes: 2,
unused: true,
}
input: {
function foo() {
function qux(x) {
bar.call(null, x);
}
function bar(x) {
var FOUR = 4;
var trouble = x || never_called();
var value = (FOUR - 1) * trouble;
console.log(value == 6 ? "PASS" : value);
}
Baz = qux;
}
var Baz;
foo();
Baz(2);
}
expect: {
function foo() {
Baz = function(x) {
(function(x) {
var value = (4 - 1) * (x || never_called());
console.log(6 == value ? "PASS" : value);
}).call(null, x);
};
}
var Baz;
foo();
Baz(2);
}
}
issue_2418_1: {
options = {
unused: true,
}
input: {
class C {}
function F() {}
(class c {});
(function f() {});
}
expect: {
class C {}
function F() {}
(class {});
(function() {});
}
}
issue_2418_2: {
options = {
keep_classnames: false,
keep_fnames: false,
unused: true,
}
input: {
class C {}
function F() {}
(class c {});
(function f() {});
}
expect: {
class C {}
function F() {}
(class {});
(function() {});
}
}
issue_2418_3: {
options = {
keep_classnames: false,
keep_fnames: true,
unused: true,
}
input: {
class C {}
function F() {}
(class c {});
(function f() {});
}
expect: {
class C {}
function F() {}
(class {});
(function f() {});
}
}
issue_2418_4: {
options = {
keep_classnames: true,
keep_fnames: false,
unused: true,
}
input: {
class C {}
function F() {}
(class c {});
(function f() {});
}
expect: {
class C {}
function F() {}
(class c {});
(function() {});
}
}
issue_2418_5: {
options = {
keep_classnames: true,
keep_fnames: true,
unused: true,
}
input: {
class C {}
function F() {}
(class c {});
(function f() {});
}
expect: {
class C {}
function F() {}
(class c {});
(function f() {});
}
}

View File

@@ -1,6 +1,7 @@
and: {
options = {
evaluate: true
evaluate: true,
side_effects: true,
}
input: {
var a;
@@ -76,7 +77,8 @@ and: {
or: {
options = {
evaluate: true
evaluate: true,
side_effects: true,
}
input: {
var a;
@@ -158,7 +160,8 @@ or: {
unary_prefix: {
options = {
evaluate: true
evaluate: true,
side_effects: true,
}
input: {
a = !0 && b;
@@ -345,6 +348,7 @@ unsafe_constant: {
unsafe_object: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
@@ -373,6 +377,7 @@ unsafe_object: {
unsafe_object_nested: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
@@ -401,6 +406,7 @@ unsafe_object_nested: {
unsafe_object_complex: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
@@ -429,6 +435,7 @@ unsafe_object_complex: {
unsafe_object_repeated: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
@@ -457,6 +464,7 @@ unsafe_object_repeated: {
unsafe_object_accessor: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unsafe: true,
}
@@ -757,6 +765,7 @@ call_args: {
options = {
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
}
input: {
@@ -779,6 +788,7 @@ call_args_drop_param: {
evaluate: true,
inline: true,
keep_fargs: false,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -1109,6 +1119,7 @@ Infinity_NaN_undefined_LHS: {
issue_1964_1: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unsafe_regexp: false,
unused: true,
@@ -1138,6 +1149,7 @@ issue_1964_1: {
issue_1964_2: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unsafe_regexp: true,
unused: true,
@@ -1294,6 +1306,7 @@ issue_2231_2: {
self_comparison_1: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
@@ -1314,6 +1327,7 @@ self_comparison_2: {
evaluate: true,
hoist_props: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -1327,3 +1341,95 @@ self_comparison_2: {
}
expect_stdout: "false false true true 'number'"
}
issue_2535_1: {
options = {
booleans: true,
evaluate: true,
sequences: true,
side_effects: true,
}
input: {
if ((x() || true) || y()) z();
if ((x() || true) && y()) z();
if ((x() && true) || y()) z();
if ((x() && true) && y()) z();
if ((x() || false) || y()) z();
if ((x() || false) && y()) z();
if ((x() && false) || y()) z();
if ((x() && false) && y()) z();
}
expect: {
if (x(), 1) z();
if (x(), y()) z();
if (x() || y()) z();
if (x() && y()) z();
if (x() || y()) z();
if (x() && y()) z();
if (x(), y()) z();
if (x(), 0) z();
}
}
issue_2535_2: {
options = {
booleans: true,
evaluate: true,
sequences: true,
side_effects: true,
}
input: {
(x() || true) || y();
(x() || true) && y();
(x() && true) || y();
(x() && true) && y();
(x() || false) || y();
(x() || false) && y();
(x() && false) || y();
(x() && false) && y();
}
expect: {
x(),
x(), y(),
x() || y(),
x() && y(),
x() || y(),
x() && y(),
x(), y(),
x();
}
}
issue_2535_3: {
options = {
booleans: true,
evaluate: true,
}
input: {
console.log(Object(1) && 1 && 2);
console.log(Object(1) && true && 1 && 2 && Object(2));
console.log(Object(1) && true && 1 && null && 2 && Object(2));
console.log(2 == Object(1) || 0 || void 0 || null);
console.log(2 == Object(1) || 0 || void 0 || null || Object(2));
console.log(2 == Object(1) || 0 || void 0 || "ok" || null || Object(2));
}
expect: {
console.log(Object(1) && 2);
console.log(Object(1) && Object(2));
console.log(Object(1) && null);
console.log(2 == Object(1) || null);
console.log(2 == Object(1) || Object(2));
console.log(2 == Object(1) || "ok");
}
expect_stdout: true
expect_warnings: [
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1409,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1410,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1411,20]",
"WARN: Condition left of && always false [test/compress/evaluate.js:1411,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1412,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1413,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1414,20]",
"WARN: Condition left of || always true [test/compress/evaluate.js:1414,20]",
]
}

View File

@@ -36,19 +36,19 @@ avoid_spread_in_ternary: {
function print(...x) {
console.log(...x);
}
var a = [1, 2], b = [3, 4];
var a = [1, 2], b = [3, 4], m = Math;
if (Math)
if (m)
print(a);
else
print(b);
if (Math)
if (m)
print(...a);
else
print(b);
if (Math.no_such_property)
if (m.no_such_property)
print(a);
else
print(...b);
@@ -57,10 +57,10 @@ avoid_spread_in_ternary: {
function print(...x) {
console.log(...x);
}
var a = [ 1, 2 ], b = [ 3, 4 ];
print(Math ? a : b);
Math ? print(...a) : print(b);
Math.no_such_property ? print(a) : print(...b);
var a = [ 1, 2 ], b = [ 3, 4 ], m = Math;
print(m ? a : b);
m ? print(...a) : print(b);
m.no_such_property ? print(a) : print(...b);
}
expect_stdout: [
"[ 1, 2 ]",

View File

@@ -124,6 +124,7 @@ async_func: {
issue_2134_1: {
options = {
keep_fargs: false,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -141,6 +142,7 @@ issue_2134_1: {
issue_2134_2: {
options = {
keep_fargs: false,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -250,3 +252,195 @@ dynamic_import: {
r.foo();
}
}
trailing_comma: {
beautify = {
beautify: true,
}
input: {
export const a = 1;
}
expect_exact: "export const a = 1;"
}
export_default_anonymous_function: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default function () {
foo();
}
}
expect_exact: "export default function(){foo()};"
}
export_default_arrow: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default () => foo();
}
expect_exact: "export default()=>foo();"
}
export_default_anonymous_generator: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default function * () {
yield foo();
}
}
expect_exact: "export default function*(){yield foo()};"
}
export_default_anonymous_async_function: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default async function() {
return await foo();
}
}
expect_exact: "export default async function(){return await foo()};"
}
export_default_async_arrow_function: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default async () => await foo();
}
expect_exact: "export default async()=>await foo();"
}
export_default_named_generator: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default function * gen() {
yield foo();
}
}
expect_exact: "export default function*gen(){yield foo()};"
}
export_default_named_async_function: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default async function bar() {
return await foo();
}
}
expect_exact: "export default async function bar(){return await foo()};"
}
export_default_anonymous_class: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default class {
constructor() {
foo();
}
};
}
expect_exact: "export default class{constructor(){foo()}};"
}
export_default_anonymous_function_not_call: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default function(){}(foo);
}
// FIXME: should be `export default function(){};foo;`
expect_exact: "export default function(){}(foo);"
}
export_default_anonymous_generator_not_call: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default function*(){}(foo);
}
// agrees with `acorn` and `babylon 7`
expect_exact: "export default function*(){};foo;"
}
export_default_anonymous_async_function_not_call: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default async function(){}(foo);
}
// agrees with `acorn` and `babylon 7`
expect_exact: "export default async function(){};foo;"
}

View File

@@ -19,8 +19,9 @@ iifes_returning_constants_keep_fargs_true: {
booleans : true,
if_return : true,
join_vars : true,
reduce_funcs : true,
reduce_vars : true,
cascade : true,
collapse_vars : true,
inline : true,
}
input: {
@@ -55,8 +56,9 @@ iifes_returning_constants_keep_fargs_false: {
booleans : true,
if_return : true,
join_vars : true,
reduce_funcs : true,
reduce_vars : true,
cascade : true,
collapse_vars : true,
inline : true,
}
input: {
@@ -85,6 +87,7 @@ issue_485_crashing_1530: {
dead_code: true,
evaluate: true,
inline: true,
side_effects: true,
}
input: {
(function(a) {
@@ -92,15 +95,14 @@ issue_485_crashing_1530: {
var b = 42;
})(this);
}
expect: {
this, void 0;
}
expect: {}
}
issue_1841_1: {
options = {
keep_fargs: false,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -127,6 +129,7 @@ issue_1841_2: {
options = {
keep_fargs: false,
pure_getters: false,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -154,6 +157,7 @@ function_returning_constant_literal: {
inline: true,
passes: 2,
properties: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -305,6 +309,7 @@ issue_2084: {
evaluate: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -340,6 +345,7 @@ issue_2084: {
issue_2097: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -417,9 +423,9 @@ inner_ref: {
issue_2107: {
options = {
cascade: true,
collapse_vars: true,
inline: true,
passes: 3,
sequences: true,
side_effects: true,
unused: true,
@@ -513,8 +519,9 @@ issue_2428: {
options = {
collapse_vars: true,
inline: true,
passes: 2,
passes: 3,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -546,3 +553,906 @@ issue_2428: {
"PASS",
]
}
issue_2531_1: {
options = {
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
function outer() {
function inner(value) {
function closure() {
return value;
}
return function() {
return closure();
};
}
return inner("Hello");
}
console.log("Greeting:", outer()());
}
expect: {
function outer() {
return value = "Hello", function() {
return value;
};
var value;
}
console.log("Greeting:", outer()());
}
expect_stdout: "Greeting: Hello"
}
issue_2531_2: {
options = {
evaluate: true,
inline: true,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
function outer() {
function inner(value) {
function closure() {
return value;
}
return function() {
return closure();
};
}
return inner("Hello");
}
console.log("Greeting:", outer()());
}
expect: {
function outer() {
return function() {
return "Hello";
};
}
console.log("Greeting:", outer()());
}
expect_stdout: "Greeting: Hello"
}
issue_2531_3: {
options = {
evaluate: true,
inline: true,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function outer() {
function inner(value) {
function closure() {
return value;
}
return function() {
return closure();
};
}
return inner("Hello");
}
console.log("Greeting:", outer()());
}
expect: {
console.log("Greeting:", "Hello");
}
expect_stdout: "Greeting: Hello"
}
empty_body: {
options = {
reduce_vars: true,
side_effects: true,
}
input: {
function f() {
function noop() {}
noop();
return noop;
}
}
expect: {
function f() {
function noop() {}
return noop;
}
}
}
inline_loop_1: {
options = {
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
return x();
}
for (;;) f();
}
expect: {
for (;;) x();
}
}
inline_loop_2: {
options = {
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
for (;;) f();
function f() {
return x();
}
}
expect: {
for (;;) x();
}
}
inline_loop_3: {
options = {
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var f = function() {
return x();
};
for (;;) f();
}
expect: {
for (;;) x();
}
}
inline_loop_4: {
options = {
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
for (;;) f();
var f = function() {
return x();
};
}
expect: {
for (;;) f();
var f = function() {
return x();
};
}
}
issue_2476: {
options = {
inline: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function foo(x, y, z) {
return x < y ? x * y + z : x * z - y;
}
for (var sum = 0, i = 0; i < 10; i++)
sum += foo(i, i + 1, 3 * i);
console.log(sum);
}
expect: {
for (var sum = 0, i = 0; i < 10; i++)
sum += (x = i, y = i + 1, z = 3 * i, x < y ? x * y + z : x * z - y);
var x, y, z;
console.log(sum);
}
expect_stdout: "465"
}
issue_2601_1: {
options = {
inline: true,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
var a = "FAIL";
(function() {
function f(b) {
function g(b) {
b && b();
}
g();
(function() {
b && (a = "PASS");
})();
}
f("foo");
})();
console.log(a);
}
expect: {
var a = "FAIL";
(function() {
b = "foo",
function(b) {
b && b();
}(),
b && (a = "PASS");
var b;
})(),
console.log(a);
}
expect_stdout: "PASS"
}
issue_2601_2: {
rename = true
options = {
evaluate: true,
inline: true,
passes: 3,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
mangle = {}
input: {
var a = "FAIL";
(function() {
function f(b) {
function g(b) {
b && b();
}
g();
(function() {
b && (a = "PASS");
})();
}
f("foo");
})();
console.log(a);
}
expect: {
var a = "FAIL";
a = "PASS",
console.log(a);
}
expect_stdout: "PASS"
}
issue_2604_1: {
options = {
inline: true,
side_effects: true,
unused: true,
}
input: {
var a = "FAIL";
(function() {
try {
throw 1;
} catch (b) {
(function f(b) {
b && b();
})();
b && (a = "PASS");
}
})();
console.log(a);
}
expect: {
var a = "FAIL";
(function() {
try {
throw 1;
} catch (b) {
(function(b) {
b && b();
})();
b && (a = "PASS");
}
})();
console.log(a);
}
expect_stdout: "PASS"
}
issue_2604_2: {
rename = true
options = {
evaluate: true,
inline: true,
passes: 3,
reduce_vars: true,
side_effects: true,
unused: true,
}
mangle = {}
input: {
var a = "FAIL";
(function() {
try {
throw 1;
} catch (b) {
(function f(b) {
b && b();
})();
b && (a = "PASS");
}
})();
console.log(a);
}
expect: {
var a = "FAIL";
(function() {
try {
throw 1;
} catch (o) {
o && (a = "PASS");
}
})();
console.log(a);
}
expect_stdout: "PASS"
}
unsafe_apply_1: {
options = {
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
(function(a, b) {
console.log(a, b);
}).apply("foo", [ "bar" ]);
(function(a, b) {
console.log(this, a, b);
}).apply("foo", [ "bar" ]);
(function(a, b) {
console.log(a, b);
}).apply("foo", [ "bar" ], "baz");
}
expect: {
console.log("bar", void 0);
(function(a, b) {
console.log(this, a, b);
}).call("foo", "bar");
(function(a, b) {
console.log(a, b);
}).apply("foo", [ "bar" ], "baz");
}
expect_stdout: true
}
unsafe_apply_2: {
options = {
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
}
input: {
function foo() {
console.log(a, b);
}
var bar = function(a, b) {
console.log(this, a, b);
}
(function() {
foo.apply("foo", [ "bar" ]);
bar.apply("foo", [ "bar" ]);
})();
}
expect: {
function foo() {
console.log(a, b);
}
var bar = function(a, b) {
console.log(this, a, b);
}
(function() {
foo("bar");
bar.call("foo", "bar");
})();
}
expect_stdout: true
}
unsafe_apply_expansion: {
options = {
unsafe: true,
}
input: {
console.log.apply(console, [1, ...[2, 3], 4]);
}
expect: {
console.log.call(console, 1, ...[2, 3], 4);
}
expect_stdout: "1 2 3 4"
node_version: ">=6"
}
unsafe_call_1: {
options = {
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
(function(a, b) {
console.log(a, b);
}).call("foo", "bar");
(function(a, b) {
console.log(this, a, b);
}).call("foo", "bar");
}
expect: {
console.log("bar", void 0);
(function(a, b) {
console.log(this, a, b);
}).call("foo", "bar");
}
expect_stdout: true
}
unsafe_call_2: {
options = {
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
}
input: {
function foo() {
console.log(a, b);
}
var bar = function(a, b) {
console.log(this, a, b);
}
(function() {
foo.call("foo", "bar");
bar.call("foo", "bar");
})();
}
expect: {
function foo() {
console.log(a, b);
}
var bar = function(a, b) {
console.log(this, a, b);
}
(function() {
foo("bar");
bar.call("foo", "bar");
})();
}
expect_stdout: true
}
unsafe_call_3: {
options = {
side_effects: true,
unsafe: true,
}
input: {
console.log(function() {
return arguments[0] + eval("arguments")[1];
}.call(0, 1, 2));
}
expect: {
console.log(function() {
return arguments[0] + eval("arguments")[1];
}(1, 2));
}
expect_stdout: "3"
}
unsafe_call_expansion: {
options = {
unsafe: true,
}
input: {
(function(...a) {
console.log(...a);
}).call(console, 1, ...[2, 3], 4);
}
expect: {
console,
(function(...a) {
console.log(...a);
})(1, ...[2, 3], 4);
}
expect_stdout: "1 2 3 4"
node_version: ">=6"
}
issue_2616: {
options = {
evaluate: true,
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var c = "FAIL";
(function() {
function f() {
function g(NaN) {
(true << NaN) - 0/0 || (c = "PASS");
}
g([]);
}
f();
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function() {
!function(NaN) {
(true << NaN) - 0/0 || (c = "PASS");
}([]);
})();
console.log(c);
}
expect_stdout: "PASS"
}
issue_2620_1: {
options = {
inline: true,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
var c = "FAIL";
(function() {
function f(a) {
var b = function g(a) {
a && a();
}();
if (a) {
var d = c = "PASS";
}
}
f(1);
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function() {
(function(a) {
if (function(a) {
a && a();
}(), a) c = "PASS";
})(1);
})(),
console.log(c);
}
expect_stdout: "PASS"
}
issue_2620_2: {
options = {
conditionals: true,
evaluate: true,
inline: true,
passes: 2,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
var c = "FAIL";
(function() {
function f(a) {
var b = function g(a) {
a && a();
}();
if (a) {
var d = c = "PASS";
}
}
f(1);
})();
console.log(c);
}
expect: {
var c = "FAIL";
c = "PASS",
console.log(c);
}
expect_stdout: "PASS"
}
issue_2620_3: {
options = {
evaluate: true,
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var c = "FAIL";
(function() {
function f(a, NaN) {
function g() {
switch (a) {
case a:
break;
case c = "PASS", NaN:
break;
}
}
g();
}
f(0/0);
})();
console.log(c);
}
expect: {
var c = "FAIL";
(function() {
(function(a, NaN) {
(function() {
switch (a) {
case a:
break;
case c = "PASS", NaN:
break;
}
})();
})(NaN);
})();
console.log(c);
}
expect_stdout: "PASS"
}
issue_2620_4: {
rename = true,
options = {
evaluate: true,
dead_code: true,
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
switches: true,
unused: true,
}
input: {
var c = "FAIL";
(function() {
function f(a, NaN) {
function g() {
switch (a) {
case a:
break;
case c = "PASS", NaN:
break;
}
}
g();
}
f(0/0);
})();
console.log(c);
}
expect: {
var c = "FAIL";
!function() {
switch (NaN) {
case void (c = "PASS"):
}
}();
console.log(c);
}
expect_stdout: "PASS"
}
issue_2630_1: {
options = {
collapse_vars: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
var c = 0;
(function() {
while (f());
function f() {
var a = function() {
var b = c++, d = c = 1 + c;
}();
}
})();
console.log(c);
}
expect: {
var c = 0;
(function() {
while (c++, void (c = 1 + c));
})(),
console.log(c);
}
expect_stdout: "2"
}
issue_2630_2: {
options = {
collapse_vars: true,
inline: true,
passes: 2,
reduce_vars: true,
sequences: true,
unused: true,
}
input: {
var c = 0;
!function() {
while (f()) {}
function f() {
var not_used = function() {
c = 1 + c;
}(c = c + 1);
}
}();
console.log(c);
}
expect: {
var c = 0;
!function() {
while (c += 1, void (c = 1 + c));
}(), console.log(c);
}
expect_stdout: "2"
}
issue_2630_3: {
options = {
inline: true,
reduce_vars: true,
unused: true,
}
input: {
var x = 2, a = 1;
(function() {
function f1(a) {
f2();
--x >= 0 && f1({});
}
f1(a++);
function f2() {
a++;
}
})();
console.log(a);
}
expect: {
var x = 2, a = 1;
(function() {
function f1(a) {
f2();
--x >= 0 && f1({});
}
f1(a++);
function f2() {
a++;
}
})();
console.log(a);
}
expect_stdout: "5"
}
issue_2630_4: {
options = {
collapse_vars: true,
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var x = 3, a = 1, b = 2;
(function() {
(function f1() {
while (--x >= 0 && f2());
}());
function f2() {
a++ + (b += a);
}
})();
console.log(a);
}
expect: {
var x = 3, a = 1, b = 2;
(function() {
(function() {
while (--x >= 0 && void (a++, b += a));
})();
})();
console.log(a);
}
expect_stdout: "2"
}
issue_2630_5: {
options = {
collapse_vars: true,
inline: true,
reduce_vars: true,
unused: true,
}
input: {
var c = 1;
!function() {
do {
c *= 10;
} while (f());
function f() {
return function() {
return (c = 2 + c) < 100;
}(c = c + 3);
}
}();
console.log(c);
}
expect: {
var c = 1;
!function() {
do {
c *= 10;
} while (c += 3, (c = 2 + c) < 100);
}();
console.log(c);
}
expect_stdout: "155"
}

View File

@@ -184,6 +184,7 @@ issue_2167: {
global_defs: {
"@isDevMode": "function(){}",
},
passes: 2,
side_effects: true,
}
input: {

View File

@@ -13,7 +13,8 @@ arrow_function_parens_2: {
typeof_arrow_functions: {
options = {
evaluate: true
evaluate: true,
typeofs: true,
}
input: {
var foo = typeof (x => null);
@@ -736,6 +737,7 @@ object_spread_unsafe: {
evaluate: true,
join_vars: true,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -903,6 +905,7 @@ issue_2349b: {
inline: true,
passes: 3,
properties: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
side_effects: true,
@@ -935,3 +938,262 @@ issue_2349b: {
]
node_version: ">=7"
}
shorthand_keywords: {
beautify = {
ecma: 6,
}
input: {
var foo = 0,
async = 1,
await = 2,
implements = 3,
package = 4,
private = 5,
protected = 6,
static = 7,
yield = 8;
console.log({
foo: foo,
0: 0,
NaN: NaN,
async: async,
await: await,
false: false,
implements: implements,
null: null,
package: package,
private: private,
protected: protected,
static: static,
this: this,
true: true,
undefined: undefined,
yield: yield,
});
}
expect_exact: "var foo=0,async=1,await=2,implements=3,package=4,private=5,protected=6,static=7,yield=8;console.log({foo,0:0,NaN:NaN,async,await,false:false,implements:implements,null:null,package:package,private:private,protected:protected,static:static,this:this,true:true,undefined:void 0,yield});"
expect_stdout: true
node_version: ">=4"
}
array_literal_with_spread_1: {
options = {
properties: true,
side_effects: true,
}
input: {
var f = (x) => [...x][0];
console.log(f(["PASS"]));
}
expect: {
var f = x => [ ...x ][0];
console.log(f([ "PASS" ]));
}
expect_stdout: "PASS"
node_version: ">=6"
}
array_literal_with_spread_2: {
options = {
properties: true,
side_effects: true,
}
input: {
console.log([10, ...[], 20, ...[30, 40], 50]["length"]);
console.log([10, ...[], 20, ...[30, 40], 50][0]);
console.log([10, ...[], 20, ...[30, 40], 50][1]);
console.log([10, ...[], 20, ...[30, 40], 50][2]);
console.log([10, ...[], 20, ...[30, 40], 50][3]);
console.log([10, ...[], 20, ...[30, 40], 50][4]);
console.log([10, ...[], 20, ...[30, 40], 50][5]);
}
expect: {
console.log([ 10, ...[], 20, ...[ 30, 40 ], 50 ]["length"]);
console.log(10);
console.log([ 10, ...[], 20, ...[ 30, 40 ], 50 ][1]);
console.log([ 10, ...[], 20, ...[ 30, 40 ], 50 ][2]);
console.log([ 10, ...[], 20, ...[ 30, 40 ], 50 ][3]);
console.log([ 10, ...[], 20, ...[ 30, 40 ], 50 ][4]);
console.log([ 10, ...[], 20, ...[ 30, 40 ], 50 ][5]);
}
expect_stdout: [
"5",
"10",
"20",
"30",
"40",
"50",
"undefined",
]
node_version: ">=6"
}
array_literal_with_spread_3: {
options = {
properties: true,
side_effects: true,
}
input: {
console.log([10, 20][0]);
console.log([10, 20][1]);
console.log([10, 20][2]);
console.log([...[], 10, 20][0]);
console.log([...[], 10, 20][1]);
console.log([...[], 10, 20][2]);
console.log([10, ...[], 20][0]);
console.log([10, ...[], 20][1]);
console.log([10, ...[], 20][2]);
console.log([10, 20, ...[]][0]);
console.log([10, 20, ...[]][1]);
console.log([10, 20, ...[]][2]);
}
expect: {
console.log(10);
console.log(20);
console.log([ 10, 20 ][2]);
console.log([...[], 10, 20][0]);
console.log([...[], 10, 20][1]);
console.log([...[], 10, 20][2]);
console.log(10);
console.log([10, ...[], 20][1]);
console.log([10, ...[], 20][2]);
console.log(10);
console.log(20);
console.log([10, 20, ...[]][2]);
}
expect_stdout: [
"10",
"20",
"undefined",
"10",
"20",
"undefined",
"10",
"20",
"undefined",
"10",
"20",
"undefined",
]
node_version: ">=6"
}
array_literal_with_spread_4: {
options = {
properties: true,
side_effects: true,
}
input: {
function t(x) {
console.log("(" + x + ")");
return 10 * x;
}
console.log([t(1), t(2)][0]);
console.log([t(1), t(2)][1]);
console.log([t(1), t(2)][2]);
console.log([...[], t(1), t(2)][0]);
console.log([...[], t(1), t(2)][1]);
console.log([...[], t(1), t(2)][2]);
console.log([t(1), ...[], t(2)][0]);
console.log([t(1), ...[], t(2)][1]);
console.log([t(1), ...[], t(2)][2]);
console.log([t(1), t(2), ...[]][0]);
console.log([t(1), t(2), ...[]][1]);
console.log([t(1), t(2), ...[]][2]);
}
expect: {
function t(x) {
console.log("(" + x + ")");
return 10 * x;
}
console.log([ t(1), t(2) ][0]);
console.log((t(1), t(2)));
console.log([ t(1), t(2) ][2]);
console.log([ ...[], t(1), t(2) ][0]);
console.log([ ...[], t(1), t(2) ][1]);
console.log([ ...[], t(1), t(2) ][2]);
console.log([ t(1), t(2) ][0]);
console.log([ t(1), ...[], t(2) ][1]);
console.log([ t(1), ...[], t(2) ][2]);
console.log([ t(1), t(2) ][0]);
console.log((t(1), t(2)));
console.log([ t(1), t(2), ...[] ][2]);
}
expect_stdout: [
"(1)", "(2)", "10",
"(1)", "(2)", "20",
"(1)", "(2)", "undefined",
"(1)", "(2)", "10",
"(1)", "(2)", "20",
"(1)", "(2)", "undefined",
"(1)", "(2)", "10",
"(1)", "(2)", "20",
"(1)", "(2)", "undefined",
"(1)", "(2)", "10",
"(1)", "(2)", "20",
"(1)", "(2)", "undefined",
]
node_version: ">=6"
}
object_literal_method_using_arguments: {
options = {
arrows: true,
}
input: {
console.log(({
m() {
return arguments[0];
}
}).m("PASS"));
}
expect: {
console.log(({
m() {
return arguments[0];
}
}).m("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
class_method_using_arguments: {
options = {
arrows: true,
}
input: {
console.log(new class {
m() {
return arguments[0];
}
}().m("PASS"));
}
expect: {
console.log(new class {
m() {
return arguments[0];
}
}().m("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -3,6 +3,7 @@ issue_2377_1: {
evaluate: true,
inline: true,
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -35,6 +36,7 @@ issue_2377_2: {
inline: true,
hoist_props: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -53,9 +55,8 @@ issue_2377_2: {
console.log(obj.foo, obj.cube(3));
}
expect: {
console.log(1, function(x) {
return x * x * x;
}(3));
console.log(1, (x = 3, x * x * x));
var x;
}
expect_stdout: "1 27"
}
@@ -65,8 +66,10 @@ issue_2377_3: {
evaluate: true,
inline: true,
hoist_props: true,
passes: 3,
passes: 4,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
@@ -92,6 +95,7 @@ issue_2377_3: {
direct_access_1: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -120,6 +124,7 @@ direct_access_1: {
direct_access_2: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -143,6 +148,7 @@ direct_access_2: {
direct_access_3: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -163,6 +169,7 @@ direct_access_3: {
single_use: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -187,6 +194,7 @@ single_use: {
name_collision_1: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
@@ -224,6 +232,7 @@ name_collision_1: {
name_collision_2: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
@@ -257,6 +266,7 @@ name_collision_2: {
name_collision_3: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
@@ -293,6 +303,7 @@ contains_this_1: {
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -318,6 +329,7 @@ contains_this_2: {
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -345,6 +357,7 @@ contains_this_3: {
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -376,8 +389,10 @@ hoist_class: {
evaluate: true,
hoist_props: true,
inline: true,
keep_classnames: true,
keep_fnames: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -418,8 +433,10 @@ hoist_class_with_new: {
evaluate: true,
hoist_props: true,
inline: true,
keep_classnames: true,
keep_fnames: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -437,17 +454,12 @@ hoist_class_with_new: {
console.log(o.p.name, o.p === o.p, new o.p(o.x).value, new o.p(o.y).value);
}
expect: {
// FIXME: class `o.p` not hoisted due to `new`
var o = {
p: class Foo {
constructor(value) {
this.value = 10 * value;
}
},
x: 1,
y: 2
var o_p = class Foo {
constructor(value) {
this.value = 10 * value;
}
};
console.log(o.p.name, o.p == o.p, new o.p(o.x).value, new o.p(o.y).value);
console.log(o_p.name, true, new o_p(1).value, new o_p(2).value);
}
node_version: ">=6"
expect_stdout: "Foo true 10 20"
@@ -461,6 +473,7 @@ hoist_function_with_call: {
inline: true,
keep_fnames: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -476,10 +489,14 @@ hoist_function_with_call: {
console.log(o.p.name, o.p === o.p, o.p(o.x), o.p(o.y));
}
expect: {
var o_p = function Foo(value){
return 10 * value
var o = {
p: function Foo(value) {
return 10 * value;
},
x: 1,
y: 2
};
console.log(o_p.name, true, o_p(1), o_p(2));
console.log(o.p.name, o.p == o.p, o.p(o.x), o.p(o.y));
}
expect_stdout: "Foo true 10 20"
}
@@ -490,6 +507,7 @@ new_this: {
hoist_props: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -511,3 +529,301 @@ new_this: {
}
expect_stdout: "1 2"
}
issue_2462: {
options = {
hoist_props: true,
reduce_funcs: true,
reduce_vars: true,
}
input: {
export const Foo = {
a: 1,
b: () => 2
};
}
expect: {
export const Foo = {
a: 1,
b: () => 2
};
}
}
issue_2473_1: {
options = {
hoist_props: false,
reduce_vars: true,
top_retain: [ "x", "y" ],
toplevel: true,
unused: true,
}
input: {
var x = {};
var y = [];
var z = {};
}
expect: {
var x = {};
var y = [];
}
}
issue_2473_2: {
options = {
hoist_props: true,
reduce_vars: true,
top_retain: [ "x", "y" ],
toplevel: true,
unused: true,
}
input: {
var x = {};
var y = [];
var z = {};
}
expect: {
var x = {};
var y = [];
}
}
issue_2473_3: {
options = {
hoist_props: true,
reduce_vars: true,
top_retain: "o",
toplevel: true,
unused: true,
}
input: {
var o = {
a: 1,
b: 2,
};
console.log(o.a, o.b);
}
expect: {
var o = {
a: 1,
b: 2,
};
console.log(o.a, o.b);
}
expect_stdout: "1 2"
}
issue_2473_4: {
options = {
hoist_props: true,
reduce_vars: true,
top_retain: "o",
toplevel: true,
unused: true,
}
input: {
(function() {
var o = {
a: 1,
b: 2,
};
console.log(o.a, o.b);
})();
}
expect: {
(function() {
var o_a = 1, o_b = 2;
console.log(o_a, o_b);
})();
}
expect_stdout: "1 2"
}
issue_2508_1: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: [ 1 ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
(function(x) {
console.log(x);
})([ 1 ]);
}
expect_stdout: true
}
issue_2508_2: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: { b: 2 },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
(function(x) {
console.log(x);
})({ b: 2 });
}
expect_stdout: true
}
issue_2508_3: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: [ o ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
var o = {
a: [ o ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect_stdout: true
}
issue_2508_4: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: { b: o },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
var o = {
a: { b: o },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect_stdout: true
}
issue_2508_5: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
f: function(x) {
console.log(x);
}
};
o.f(o.f);
}
expect: {
var o_f = function(x) {
console.log(x);
};
o_f(o_f);
}
expect_stdout: true
}
issue_2508_6: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
f: x => {
console.log(x);
}
};
o.f(o.f);
}
expect: {
var o_f = x => {
console.log(x);
};
o_f(o_f);
}
expect_stdout: true
}
issue_2519: {
options = {
collapse_vars: true,
evaluate: true,
hoist_props: true,
reduce_vars: true,
unused: true,
}
input: {
function testFunc() {
var dimensions = {
minX: 5,
maxX: 6,
};
var scale = 1;
var d = {
x: (dimensions.maxX + dimensions.minX) / 2,
};
return d.x * scale;
}
console.log(testFunc());
}
expect: {
function testFunc() {
return 1 * ((6 + 5) / 2);
}
console.log(testFunc());
}
expect_stdout: "5.5"
}

View File

@@ -2,7 +2,7 @@ non_hoisted_function_after_return: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true
if_return: true, join_vars: true, side_effects: true
}
input: {
function foo(x) {
@@ -38,7 +38,7 @@ non_hoisted_function_after_return_2a: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true,
if_return: true, join_vars: true, side_effects: true,
collapse_vars: false, passes: 2, warnings: "verbose"
}
input: {
@@ -85,7 +85,7 @@ non_hoisted_function_after_return_2b: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true,
if_return: true, join_vars: true, side_effects: true,
collapse_vars: false
}
input: {
@@ -123,7 +123,7 @@ non_hoisted_function_after_return_strict: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true
if_return: true, join_vars: true, side_effects: true
}
input: {
"use strict";
@@ -164,7 +164,7 @@ non_hoisted_function_after_return_2a_strict: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true,
if_return: true, join_vars: true, side_effects: true,
collapse_vars: false, passes: 2, warnings: "verbose"
}
input: {
@@ -216,7 +216,7 @@ non_hoisted_function_after_return_2b_strict: {
options = {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true,
if_return: true, join_vars: true, side_effects: true,
collapse_vars: false
}
input: {

View File

@@ -14,6 +14,7 @@ const_declaration: {
const_pragma: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
};
@@ -29,6 +30,7 @@ const_pragma: {
not_const: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
};

View File

@@ -190,7 +190,6 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
sequences: false,
keep_infinity: false,
@@ -253,7 +252,6 @@ assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: {
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
sequences: false,
keep_infinity: true,

View File

@@ -14,7 +14,7 @@ issue_1212_debug_false: {
keep_fargs : true,
if_return : true,
join_vars : true,
cascade : true,
collapse_vars : true,
side_effects : true,
}
input: {
@@ -52,7 +52,7 @@ issue_1212_debug_true: {
keep_fargs : true,
if_return : true,
join_vars : true,
cascade : true,
collapse_vars : true,
side_effects : true,
}
input: {

View File

@@ -8,7 +8,6 @@ pure_function_calls: {
unused : true,
if_return : true,
join_vars : true,
cascade : true,
negate_iife : true,
}
input: {
@@ -49,13 +48,13 @@ pure_function_calls: {
a.b(), f.g();
}
expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:17,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:17,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:30,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:30,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:28,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:38,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:39,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:16,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:29,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:29,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:27,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:37,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:38,31]",
]
}
@@ -69,7 +68,6 @@ pure_function_calls_toplevel: {
unused : true,
if_return : true,
join_vars : true,
cascade : true,
negate_iife : true,
toplevel : true,
}
@@ -112,17 +110,17 @@ pure_function_calls_toplevel: {
a.b(), f.g();
}
expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:79,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:79,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:92,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:92,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:90,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:107,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:108,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:84,33]",
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:84,12]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,45]",
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:100,12]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:77,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:77,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:90,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:90,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:88,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:105,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:106,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:82,33]",
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:82,12]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:98,45]",
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:98,12]",
]
}
@@ -157,29 +155,29 @@ should_warn: {
baz();
}
expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,61]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,23]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:137,23]",
"WARN: Boolean || always true [test/compress/issue-1261.js:138,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,61]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:135,23]",
"WARN: Boolean || always true [test/compress/issue-1261.js:136,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,23]",
"WARN: Condition always true [test/compress/issue-1261.js:136,23]",
"WARN: Condition left of || always true [test/compress/issue-1261.js:137,8]",
"WARN: Condition always true [test/compress/issue-1261.js:137,8]",
"WARN: Boolean && always false [test/compress/issue-1261.js:138,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:138,23]",
"WARN: Condition always true [test/compress/issue-1261.js:138,23]",
"WARN: Condition left of || always true [test/compress/issue-1261.js:139,8]",
"WARN: Condition always true [test/compress/issue-1261.js:139,8]",
"WARN: Boolean && always false [test/compress/issue-1261.js:140,23]",
"WARN: Condition always false [test/compress/issue-1261.js:138,23]",
"WARN: Condition left of && always false [test/compress/issue-1261.js:139,8]",
"WARN: Condition always false [test/compress/issue-1261.js:139,8]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:140,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:140,23]",
"WARN: Condition always false [test/compress/issue-1261.js:140,23]",
"WARN: Condition left of && always false [test/compress/issue-1261.js:141,8]",
"WARN: Condition always false [test/compress/issue-1261.js:141,8]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:142,23]",
"WARN: Condition always true [test/compress/issue-1261.js:140,23]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:141,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:141,31]",
"WARN: Condition always true [test/compress/issue-1261.js:141,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:142,23]",
"WARN: Condition always true [test/compress/issue-1261.js:142,23]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:143,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:143,24]",
"WARN: Condition always true [test/compress/issue-1261.js:143,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:145,24]",
"WARN: Condition always true [test/compress/issue-1261.js:145,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:146,31]",
"WARN: Condition always false [test/compress/issue-1261.js:146,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:144,31]",
"WARN: Condition always false [test/compress/issue-1261.js:144,8]",
]
}

View File

@@ -9,7 +9,6 @@ string_plus_optimization: {
unused : true,
if_return : true,
join_vars : true,
cascade : true,
hoist_funs : true,
};
input: {

View File

@@ -32,7 +32,6 @@ conditional_false_stray_else_in_loop: {
hoist_vars : true,
join_vars : true,
if_return : true,
cascade : true,
conditionals : false,
}
input: {

View File

@@ -11,7 +11,6 @@ same_variable_in_multiple_for_loop: {
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
@@ -54,7 +53,6 @@ same_variable_in_multiple_forOf: {
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
@@ -96,7 +94,6 @@ same_variable_in_multiple_forIn: {
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
@@ -138,7 +135,6 @@ different_variable_in_multiple_for_loop: {
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
@@ -181,7 +177,6 @@ different_variable_in_multiple_forOf: {
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
@@ -223,7 +218,6 @@ different_variable_in_multiple_forIn: {
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}
@@ -265,7 +259,6 @@ more_variable_in_multiple_for: {
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
collapse_vars: true,
}

View File

@@ -2,6 +2,7 @@ chained_evaluation_1: {
options = {
collapse_vars: true,
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -28,6 +29,7 @@ chained_evaluation_2: {
options = {
collapse_vars: true,
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}

View File

@@ -2,7 +2,7 @@
issue_1639_1: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
conditionals: true,
evaluate: true,
join_vars: true,
@@ -26,7 +26,7 @@ issue_1639_1: {
}
expect: {
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
if (--b, !1) var ignore = 0;
if (--b, 0) var ignore = 0;
console.log(a, b);
}
expect_stdout: true
@@ -35,7 +35,7 @@ issue_1639_1: {
issue_1639_2: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
conditionals: true,
evaluate: true,
join_vars: true,
@@ -57,7 +57,7 @@ issue_1639_2: {
expect: {
var a = 100, b = 10;
function f19() {
++a, 1;
++a, 0;
}
f19(),
console.log(a, b);
@@ -68,7 +68,7 @@ issue_1639_2: {
issue_1639_3: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
conditionals: true,
evaluate: true,
sequences: true,

View File

@@ -1,7 +1,6 @@
f7: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
comparisons: true,
conditionals: true,
@@ -15,6 +14,7 @@ f7: {
negate_iife: true,
passes: 3,
properties: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -38,7 +38,7 @@ f7: {
"var b = 10;",
"",
"!function() {",
" for (;b = 100, !1; ) ;",
" b = 100;",
"}(), console.log(100, b);",
]
expect_stdout: true

View File

@@ -1,5 +1,6 @@
side_effects_catch: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -34,6 +35,7 @@ side_effects_catch: {
side_effects_else: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -62,6 +64,7 @@ side_effects_else: {
side_effects_finally: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -98,6 +101,7 @@ side_effects_finally: {
side_effects_label: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -130,6 +134,7 @@ side_effects_label: {
side_effects_switch: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,

View File

@@ -7,7 +7,7 @@ case_1: {
input: {
var a = 0, b = 1;
switch (true) {
case a, true:
case a || true:
default:
b = 2;
case true:
@@ -17,7 +17,7 @@ case_1: {
expect: {
var a = 0, b = 1;
switch (true) {
case a, true:
case a || true:
b = 2;
}
console.log(a, b);

View File

@@ -2,6 +2,7 @@ unary_prefix: {
options = {
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}

View File

@@ -1,6 +1,7 @@
iife_for: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -26,6 +27,7 @@ iife_for: {
iife_for_in: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -51,6 +53,7 @@ iife_for_in: {
iife_do: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -80,6 +83,7 @@ iife_do: {
iife_while: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -130,5 +134,5 @@ label_while: {
L: while (0) continue L;
}
}
expect_exact: "function f(){L:;}"
expect_exact: "function f(){L:0}"
}

View File

@@ -3,6 +3,7 @@ collapse_vars_constants: {
collapse_vars: true,
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -240,6 +241,7 @@ negate_iife_issue_1073: {
evaluate: true,
inline: true,
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
unused: true,
@@ -267,6 +269,7 @@ issue_1288_side_effects: {
evaluate: true,
inline: true,
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -299,6 +302,7 @@ inner_var_for_in_1: {
options = {
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
}
input: {
@@ -330,6 +334,7 @@ issue_1595_3: {
evaluate: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -448,7 +453,7 @@ pure_annotation_2: {
drop_fargs: {
options = {
cascade: true,
collapse_vars: true,
inline: true,
keep_fargs: false,
side_effects: true,
@@ -471,7 +476,7 @@ drop_fargs: {
keep_fargs: {
options = {
cascade: true,
collapse_vars: true,
inline: true,
keep_fargs: true,
side_effects: true,

View File

@@ -1,6 +1,6 @@
collapse: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
unused: true,
@@ -41,7 +41,7 @@ collapse: {
return void 0 !== ('function' === typeof b ? b() : b) && c();
}
function f2(b) {
return b = c(), 'stirng' == typeof ('function' === typeof b ? b() : b) && d();
return 'stirng' == typeof ('function' === typeof (b = c()) ? b() : b) && d();
}
function f3(c) {
var a;

View File

@@ -17,6 +17,6 @@ wrongly_optimized: {
foo();
}
// TODO: optimize to `func(), bar()`
(func(), 0) || bar();
(func(), 1) && bar();
}
}

View File

@@ -100,7 +100,7 @@ wrongly_optimized: {
foo();
}
// TODO: optimize to `func(), bar()`
if (func(), !0) bar();
if (func(), 1) bar();
}
}

View File

@@ -18,7 +18,6 @@ dont_mangle_arguments: {
hoist_vars : true,
if_return : true,
join_vars : true,
cascade : true,
side_effects : true,
negate_iife : false
};

View File

@@ -1,7 +1,8 @@
this_binding_conditionals: {
options = {
conditionals: true,
evaluate : true
evaluate: true,
side_effects: true,
};
input: {
(1 && a)();

View File

@@ -2,7 +2,7 @@ eval_collapse_vars: {
options = {
collapse_vars:true, sequences:false, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
keep_fargs:true, if_return:true, join_vars:true, side_effects:true
};
input: {
function f1() {

View File

@@ -2,7 +2,7 @@ issue979_reported: {
options = {
sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
keep_fargs:true, if_return:true, join_vars:true, side_effects:true
}
input: {
function f1() {
@@ -32,7 +32,7 @@ issue979_test_negated_is_best: {
options = {
sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
keep_fargs:true, if_return:true, join_vars:true, side_effects:true
}
input: {
function f3() {

View File

@@ -192,9 +192,11 @@ keep_collapse_const_in_own_block_scope_2: {
evaluate: {
options = {
loops: true,
dead_code: true,
evaluate: true,
loops: true,
passes: 2,
side_effects: true,
};
input: {
while (true) {
@@ -494,3 +496,43 @@ in_parenthesis_2: {
}
expect_exact: 'for(function(){"foo"in{}};0;);'
}
init_side_effects: {
options = {
loops: true,
side_effects: true,
};
input: {
for (function() {}(), i = 0; i < 5; i++) console.log(i);
for (function() {}(); i < 10; i++) console.log(i);
}
expect: {
for (i = 0; i < 5; i++) console.log(i);
for (; i < 10; i++) console.log(i);
}
expect_stdout: true
}
dead_code_condition: {
options = {
dead_code: true,
evaluate: true,
loops: true,
sequences: true,
}
input: {
for (var a = 0, b = 5; (a += 1, 3) - 3 && b > 0; b--) {
var c = function() {
b--;
}(a++);
}
console.log(a);
}
expect: {
var c;
var a = 0, b = 5;
a += 1, 0,
console.log(a);
}
expect_stdout: "1"
}

View File

@@ -812,3 +812,204 @@ prop_arrow_with_nested_this: {
]
node_version: ">=4"
}
issue_2554_1: {
options = {
computed_props: true,
evaluate: true,
}
input: {
var obj = {
["x" + ""]: 1,
["method" + ""]() {
this.s = "PASS";
},
get ["g" + ""]() {
return this.x;
},
set ["s" + ""](value) {
this.x = value;
}
};
obj.method();
console.log(obj.g);
}
expect: {
var obj = {
x: 1,
method() {
this.s = "PASS";
},
get g() {
return this.x;
},
set s(value) {
this.x = value;
}
};
obj.method();
console.log(obj.g);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_2554_2: {
options = {
computed_props: true,
evaluate: true,
}
input: {
var instance = new class {
constructor() {
this.x = 2;
}
["method" + ""]() {
this.s = "PASS";
}
get ["g" + ""]() {
return this.x;
}
set ["s" + ""](value) {
this.x = value;
}
}();
instance.method();
console.log(instance.g);
}
expect: {
var instance = new class {
constructor() {
this.x = 2;
}
method() {
this.s = "PASS";
}
get g() {
return this.x;
}
set s(value) {
this.x = value;
}
}();
instance.method();
console.log(instance.g);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_2554_3: {
options = {
computed_props: true,
evaluate: true,
}
input: {
var foo = {
[1 + 0]: 1,
[2 + 0]() {
this[4] = "PASS";
},
get [3 + 0]() {
return this[1];
},
set [4 + 0](value) {
this[1] = value;
}
};
foo[2]();
console.log(foo[3]);
}
expect: {
var foo = {
1: 1,
2() {
this[4] = "PASS";
},
get 3() {
return this[1];
},
set 4(value) {
this[1] = value;
}
};
foo[2]();
console.log(foo[3]);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_2554_4: {
options = {
computed_props: true,
evaluate: true,
}
input: {
var bar = new class {
constructor() {
this[1] = 2;
}
[2 + 0]() {
this[4] = "PASS";
}
get [3 + 0]() {
return this[1];
}
set [4 + 0](value) {
this[1] = value;
}
}();
bar[2]();
console.log(bar[3]);
}
expect: {
var bar = new class {
constructor() {
this[1] = 2;
}
2() {
this[4] = "PASS";
}
get 3() {
return this[1];
}
set 4(value) {
this[1] = value;
}
}();
bar[2]();
console.log(bar[3]);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_2554_5: {
options = {
computed_props: true,
evaluate: true,
}
input: {
new class {
["constructor"]() {
console.log("FAIL");
}
"constructor"() {
console.log("PASS");
}
}();
}
expect: {
new class {
["constructor"]() {
console.log("FAIL");
}
constructor() {
console.log("PASS");
}
}();
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -940,6 +940,7 @@ methods_keep_quoted_from_dead_code: {
dead_code: true,
ecma: 6,
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unsafe_methods: true,
@@ -1085,6 +1086,7 @@ lhs_prop_2: {
evaluate: true,
inline: true,
properties: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -1131,6 +1133,7 @@ prop_side_effects_1: {
evaluate: true,
inline: true,
properties: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -1167,6 +1170,7 @@ prop_side_effects_2: {
inline: true,
passes: 2,
properties: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -1301,3 +1305,69 @@ new_this: {
}(42);
}
}
issue_2513: {
options = {
evaluate: true,
properties: true,
}
input: {
!function(Infinity, NaN, undefined) {
console.log("a"[1/0], "b"["Infinity"]);
console.log("c"[0/0], "d"["NaN"]);
console.log("e"[void 0], "f"["undefined"]);
}(0, 0, 0);
}
expect: {
!function(Infinity, NaN, undefined) {
console.log("a"[1/0], "b"[1/0]);
console.log("c".NaN, "d".NaN);
console.log("e"[void 0], "f"[void 0]);
}(0, 0, 0);
}
expect_stdout: [
"undefined undefined",
"undefined undefined",
"undefined undefined",
]
}
const_prop_assign_strict: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
function Simulator() {
/abc/.index = 1;
this._aircraft = [];
}
(function() {}).prototype.destroy = x();
}
expect: {
function Simulator() {
this._aircraft = [];
}
x();
}
}
const_prop_assign_pure: {
options = {
pure_getters: true,
side_effects: true,
}
input: {
function Simulator() {
/abc/.index = 1;
this._aircraft = [];
}
(function() {}).prototype.destroy = x();
}
expect: {
function Simulator() {
this._aircraft = [];
}
x();
}
}

View File

@@ -293,3 +293,124 @@ unary: {
bar();
}
}
issue_2629_1: {
options = {
side_effects: true,
}
beautify = {
comments: "all",
}
input: {
/*@__PURE__*/ a();
/*@__PURE__*/ (b());
(/*@__PURE__*/ c)();
(/*@__PURE__*/ d());
}
expect_exact: [
"/* */c();",
]
}
issue_2629_2: {
options = {
side_effects: true,
}
beautify = {
comments: "all",
}
input: {
/*@__PURE__*/ a(1)(2)(3);
/*@__PURE__*/ (b(1))(2)(3);
/*@__PURE__*/ (c(1)(2))(3);
/*@__PURE__*/ (d(1)(2)(3));
(/*@__PURE__*/ e)(1)(2)(3);
(/*@__PURE__*/ f(1))(2)(3);
(/*@__PURE__*/ g(1)(2))(3);
(/*@__PURE__*/ h(1)(2)(3));
}
expect_exact: [
"/* */e(1)(2)(3);",
"/* */f(1)(2)(3);",
"/* */g(1)(2)(3);",
]
}
issue_2629_3: {
options = {
side_effects: true,
}
beautify = {
comments: "all",
}
input: {
/*@__PURE__*/ a.x(1).y(2).z(3);
/*@__PURE__*/ (b.x)(1).y(2).z(3);
/*@__PURE__*/ (c.x(1)).y(2).z(3);
/*@__PURE__*/ (d.x(1).y)(2).z(3);
/*@__PURE__*/ (e.x(1).y(2)).z(3);
/*@__PURE__*/ (f.x(1).y(2).z)(3);
/*@__PURE__*/ (g.x(1).y(2).z(3));
(/*@__PURE__*/ h).x(1).y(2).z(3);
(/*@__PURE__*/ i.x)(1).y(2).z(3);
(/*@__PURE__*/ j.x(1)).y(2).z(3);
(/*@__PURE__*/ k.x(1).y)(2).z(3);
(/*@__PURE__*/ l.x(1).y(2)).z(3);
(/*@__PURE__*/ m.x(1).y(2).z)(3);
(/*@__PURE__*/ n.x(1).y(2).z(3));
}
expect_exact: [
"/* */h.x(1).y(2).z(3);",
"/* */i.x(1).y(2).z(3);",
"/* */j.x(1).y(2).z(3);",
"/* */k.x(1).y(2).z(3);",
"/* */l.x(1).y(2).z(3);",
"/* */m.x(1).y(2).z(3);",
]
}
issue_2629_4: {
options = {
side_effects: true,
}
input: {
(/*@__PURE__*/ x(), y());
(w(), /*@__PURE__*/ x(), y());
}
expect: {
y();
w(), y();
}
}
issue_2629_5: {
options = {
side_effects: true,
}
input: {
[ /*@__PURE__*/ x() ];
[ /*@__PURE__*/ x(), y() ];
[ w(), /*@__PURE__*/ x(), y() ];
}
expect: {
y();
w(), y();
}
}
issue_2638: {
options = {
side_effects: true,
}
beautify = {
comments: "all",
}
input: {
/*@__PURE__*/(g() || h())(x(), y());
(/*@__PURE__*/ (a() || b()))(c(), d());
}
expect_exact: [
"/* */x(),y();",
"/* */(a()||b())(c(),d());",
]
}

View File

@@ -1,6 +1,7 @@
strict: {
options = {
pure_getters: "strict",
reduce_funcs: false,
reduce_vars: false,
side_effects: true,
toplevel: true,
@@ -30,6 +31,7 @@ strict: {
strict_reduce_vars: {
options = {
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -58,6 +60,7 @@ strict_reduce_vars: {
unsafe: {
options = {
pure_getters: true,
reduce_funcs: false,
reduce_vars: false,
side_effects: true,
toplevel: true,
@@ -84,6 +87,7 @@ unsafe: {
unsafe_reduce_vars: {
options = {
pure_getters: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -181,10 +185,11 @@ impure_getter_2: {
issue_2110_1: {
options = {
cascade: true,
collapse_vars: true,
pure_getters: "strict",
sequences: true,
side_effects: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -215,6 +220,7 @@ issue_2110_2: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -247,6 +253,7 @@ set_immutable_1: {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -267,9 +274,10 @@ set_immutable_1: {
set_immutable_2: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -293,6 +301,7 @@ set_immutable_3: {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -315,9 +324,10 @@ set_immutable_3: {
set_immutable_4: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -343,6 +353,7 @@ set_mutable_1: {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -364,9 +375,10 @@ set_mutable_1: {
set_mutable_2: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -403,6 +415,7 @@ issue_2265_1: {
issue_2265_2: {
options = {
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -428,6 +441,7 @@ issue_2265_2: {
issue_2265_3: {
options = {
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -447,6 +461,7 @@ issue_2265_3: {
issue_2265_4: {
options = {
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
@@ -461,7 +476,7 @@ issue_2265_4: {
issue_2313_1: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: "strict",
sequences: true,
@@ -507,7 +522,7 @@ issue_2313_1: {
issue_2313_2: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: true,
sequences: true,

File diff suppressed because it is too large Load Diff

536
test/compress/rename.js Normal file
View File

@@ -0,0 +1,536 @@
mangle_catch: {
rename = true
options = {
ie8: false,
toplevel: false,
}
mangle = {
ie8: false,
toplevel: false,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
a = "PASS";
}
console.log(a);
}
expect_exact: 'var a="FAIL";try{throw 1}catch(o){a="PASS"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_ie8: {
rename = true
options = {
ie8: true,
toplevel: false,
}
mangle = {
ie8: true,
toplevel: false,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
a = "PASS";
}
console.log(a);
}
expect_exact: 'var a="FAIL";try{throw 1}catch(args){a="PASS"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_var: {
rename = true
options = {
ie8: false,
toplevel: false,
}
mangle = {
ie8: false,
toplevel: false,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
var a = "PASS";
}
console.log(a);
}
expect_exact: 'var a="FAIL";try{throw 1}catch(o){var a="PASS"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_var_ie8: {
rename = true
options = {
ie8: true,
toplevel: false,
}
mangle = {
ie8: true,
toplevel: false,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
var a = "PASS";
}
console.log(a);
}
expect_exact: 'var a="FAIL";try{throw 1}catch(args){var a="PASS"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_toplevel: {
rename = true
options = {
ie8: false,
toplevel: true,
}
mangle = {
ie8: false,
toplevel: true,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
a = "PASS";
}
console.log(a);
}
expect_exact: 'var o="FAIL";try{throw 1}catch(c){o="PASS"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_ie8_toplevel: {
rename = true
options = {
ie8: true,
toplevel: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
a = "PASS";
}
console.log(a);
}
expect_exact: 'var o="FAIL";try{throw 1}catch(c){o="PASS"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_var_toplevel: {
rename = true
options = {
ie8: false,
toplevel: true,
}
mangle = {
ie8: false,
toplevel: true,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
var a = "PASS";
}
console.log(a);
}
expect_exact: 'var o="FAIL";try{throw 1}catch(r){var o="PASS"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_var_ie8_toplevel: {
rename = true
options = {
ie8: true,
toplevel: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
var a = "FAIL";
try {
throw 1;
} catch (args) {
var a = "PASS";
}
console.log(a);
}
expect_exact: 'var o="FAIL";try{throw 1}catch(r){var o="PASS"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_redef_1: {
rename = true
options = {
ie8: false,
toplevel: false,
}
mangle = {
ie8: false,
toplevel: false,
}
input: {
var a = "PASS";
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'var a="PASS";try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_redef_1_ie8: {
rename = true
options = {
ie8: true,
toplevel: false,
}
mangle = {
ie8: true,
toplevel: false,
}
input: {
var a = "PASS";
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'var a="PASS";try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
expect_stdout: "PASS"
}
mangle_catch_redef_1_toplevel: {
rename = true
options = {
ie8: false,
toplevel: true,
}
mangle = {
ie8: false,
toplevel: true,
}
input: {
var a = "PASS";
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'var o="PASS";try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_redef_1_ie8_toplevel: {
rename = true
options = {
ie8: true,
toplevel: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
var a = "PASS";
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'var o="PASS";try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
expect_stdout: "PASS"
}
mangle_catch_redef_2: {
rename = true
options = {
ie8: false,
toplevel: false,
}
mangle = {
ie8: false,
toplevel: false,
}
input: {
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
expect_stdout: "undefined"
}
mangle_catch_redef_2_ie8: {
rename = true
options = {
ie8: true,
toplevel: false,
}
mangle = {
ie8: true,
toplevel: false,
}
input: {
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'try{throw"FAIL1"}catch(a){var a="FAIL2"}console.log(a);'
expect_stdout: "undefined"
}
mangle_catch_redef_2_toplevel: {
rename = true
options = {
ie8: false,
toplevel: true,
}
mangle = {
ie8: false,
toplevel: true,
}
input: {
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
expect_stdout: "undefined"
}
mangle_catch_redef_2_ie8_toplevel: {
rename = true
options = {
ie8: true,
toplevel: true,
}
mangle = {
ie8: true,
toplevel: true,
}
input: {
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
}
expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
expect_stdout: "undefined"
}
issue_2120_1: {
rename = true
mangle = {
ie8: false,
}
input: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (t) {
try {
throw 0;
} catch (a) {
if (t) b = "PASS";
}
}
console.log(b);
}
expect_stdout: "PASS"
}
issue_2120_2: {
rename = true
mangle = {
ie8: true,
}
input: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect: {
"aaaaaaaa";
var a = 1, b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
}
expect_stdout: "PASS"
}
function_iife_catch: {
rename = true
mangle = {
ie8: false,
}
input: {
function f(n) {
!function() {
try {
throw 0;
} catch (n) {
var a = 1;
console.log(n, a);
}
}();
}
f();
}
expect_exact: "function f(o){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();"
expect_stdout: "0 1"
}
function_iife_catch_ie8: {
rename = true
mangle = {
ie8: true,
}
input: {
function f(n) {
!function() {
try {
throw 0;
} catch (n) {
var a = 1;
console.log(n, a);
}
}();
}
f();
}
expect_exact: "function f(o){!function(){try{throw 0}catch(o){var c=1;console.log(o,c)}}()}f();"
expect_stdout: "0 1"
}
function_catch_catch: {
rename = true
mangle = {
ie8: false,
}
input: {
var o = 0;
function f() {
try {
throw 1;
} catch (c) {
try {
throw 2;
} catch (o) {
var o = 3;
console.log(o);
}
}
console.log(o);
}
f();
}
expect_exact: "var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();"
expect_stdout: [
"3",
"undefined",
]
}
function_catch_catch_ie8: {
rename = true
mangle = {
ie8: true,
}
input: {
var o = 0;
function f() {
try {
throw 1;
} catch (c) {
try {
throw 2;
} catch (o) {
var o = 3;
console.log(o);
}
}
console.log(o);
}
f();
}
expect_exact: "var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();"
expect_stdout: [
"3",
"undefined",
]
}

View File

@@ -17,7 +17,6 @@ return_undefined: {
keep_fnames : false,
hoist_vars : true,
join_vars : true,
cascade : true,
negate_iife : true
};
input: {
@@ -122,3 +121,25 @@ return_undefined: {
}
}
}
return_void: {
options = {
if_return: true,
inline: true,
reduce_vars: true,
unused: true,
}
input: {
function f() {
function g() {
h();
}
return g();
}
}
expect: {
function f() {
h();
}
}
}

View File

@@ -187,6 +187,7 @@ dont_screw_try_catch_undefined: {
reduce_vars: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
ie8: true,
unused: true,

View File

@@ -252,13 +252,12 @@ negate_iife_for: {
input: {
(function() {})();
for (i = 0; i < 5; i++) console.log(i);
(function() {})();
for (; i < 5; i++) console.log(i);
for (; i < 10; i++) console.log(i);
}
expect: {
for (!function() {}(), i = 0; i < 5; i++) console.log(i);
for (function() {}(); i < 5; i++) console.log(i);
for (!function() {}(); i < 10; i++) console.log(i);
}
expect_stdout: true
}
@@ -318,7 +317,7 @@ unsafe_undefined: {
issue_1685: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -342,7 +341,7 @@ issue_1685: {
func_def_1: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -362,7 +361,7 @@ func_def_1: {
func_def_2: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -380,7 +379,7 @@ func_def_2: {
func_def_3: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -402,7 +401,7 @@ func_def_3: {
func_def_4: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -428,7 +427,7 @@ func_def_4: {
func_def_5: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -635,7 +634,7 @@ side_effects: {
side_effects_cascade_1: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
sequences: true,
side_effects: true,
@@ -656,7 +655,7 @@ side_effects_cascade_1: {
side_effects_cascade_2: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -678,7 +677,7 @@ side_effects_cascade_2: {
side_effects_cascade_3: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
side_effects: true,
}
@@ -693,14 +692,14 @@ side_effects_cascade_3: {
expect: {
function f(a, b) {
!(b += a) && ((b = a) || (b -= a, b ^= a)),
--a;
a--;
}
}
}
issue_27: {
options = {
cascade: true,
collapse_vars: true,
passes: 2,
sequences: true,
side_effects: true,
@@ -722,7 +721,7 @@ issue_27: {
reassign_const: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
}
@@ -747,7 +746,7 @@ reassign_const: {
issue_2062: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
conditionals: true,
side_effects: true,
}
@@ -766,7 +765,7 @@ issue_2062: {
issue_2313: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
}
@@ -804,3 +803,20 @@ issue_2313: {
}
expect_stdout: "2 1"
}
cascade_assignment_in_return: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(a, b) {
return a = x(), b(a);
}
}
expect: {
function f(a, b) {
return b(x());
}
}
}

View File

@@ -714,6 +714,7 @@ issue_1705_2: {
options = {
dead_code: true,
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -816,3 +817,50 @@ issue_1758: {
}
expect_stdout: "0 3"
}
issue_2535: {
options = {
evaluate: true,
dead_code: true,
switches: true,
}
input: {
switch(w(), 42) {
case 13: x();
case 42: y();
default: z();
}
}
expect: {
w(), 42;
42;
y();
z();
}
}
issue_1750: {
options = {
dead_code: true,
evaluate: true,
switches: true,
}
input: {
var a = 0, b = 1;
switch (true) {
case a, true:
default:
b = 2;
case true:
}
console.log(a, b);
}
expect: {
var a = 0, b = 1;
true;
a, true;
b = 2;
console.log(a, b);
}
expect_stdout: "0 2"
}

View File

@@ -458,3 +458,51 @@ semicolons: {
}
expect_exact: "foo;`bar`\n"
}
regex_1: {
input: {
console.log(`${/a/} ${6/2} ${/b/.test("b")} ${1?/c/:/d/}`);
}
expect_exact: 'console.log(`${/a/} ${6/2} ${/b/.test("b")} ${1?/c/:/d/}`);'
expect_stdout: "/a/ 3 true /c/"
node_version: ">=4"
}
regex_2: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(`${/a/} ${6/2} ${/b/.test("b")} ${1?/c/:/d/}`);
}
expect: {
console.log("/a/ 3 true /c/");
}
expect_stdout: "/a/ 3 true /c/"
node_version: ">=4"
}
sequence_1: {
input: {
console.log(`${1,2} ${/a/,/b/}`);
}
expect_exact: 'console.log(`${1,2} ${/a/,/b/}`);'
expect_stdout: "2 /b/"
node_version: ">=4"
}
sequence_2: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log(`${1,2} ${/a/,/b/}`);
}
expect: {
console.log("2 /b/");
}
expect_stdout: "2 /b/"
node_version: ">=4"
}

View File

@@ -45,9 +45,9 @@ condition_evaluate: {
if (void 0 == null);
}
expect: {
while (!1);
for (; !0;);
if (!0);
while (0);
for (; 1;);
if (1);
}
}
@@ -68,6 +68,7 @@ label_if_break: {
conditionals: true,
dead_code: true,
evaluate: true,
side_effects: true,
}
input: {
L: if (true) {

View File

@@ -1,6 +1,7 @@
typeof_evaluation: {
options = {
evaluate: true
evaluate: true,
typeofs: true,
};
input: {
a = typeof 1;
@@ -44,7 +45,7 @@ typeof_in_boolean_context: {
function f2() { return g(), "Yes"; }
foo();
console.log(1);
var a = !(console.log(2), !0);
var a = !(console.log(2), 1);
foo();
}
}
@@ -57,6 +58,83 @@ issue_1668: {
if (typeof bar);
}
expect: {
if (!0);
if (1);
}
}
typeof_defun_1: {
options = {
evaluate: true,
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
typeofs: true,
unused: true,
}
input: {
function f() {
console.log("YES");
}
function g() {
h = 42;
console.log("NOPE");
}
function h() {
console.log("YUP");
}
g = 42;
"function" == typeof f && f();
"function" == typeof g && g();
"function" == typeof h && h();
}
expect: {
function g() {
h = 42;
console.log("NOPE");
}
function h() {
console.log("YUP");
}
g = 42;
console.log("YES");
"function" == typeof g && g();
h();
}
expect_stdout: [
"YES",
"YUP",
]
}
typeof_defun_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
typeofs: true,
}
input: {
var f = function() {
console.log(x);
};
var x = 0;
x++ < 2 && typeof f == "function" && f();
x++ < 2 && typeof f == "function" && f();
x++ < 2 && typeof f == "function" && f();
}
expect: {
var f = function() {
console.log(x);
};
var x = 0;
x++ < 2 && f();
x++ < 2 && f();
x++ < 2 && f();
}
expect_stdout: [
"1",
"2",
]
}

View File

@@ -119,3 +119,10 @@ issue_2242_4: {
}
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
}
issue_2569: {
input: {
new RegExp("[\udc42-\udcaa\udd74-\udd96\ude45-\ude4f\udea3-\udecc]");
}
expect_exact: 'new RegExp("[\\udc42-\\udcaa\\udd74-\\udd96\\ude45-\\ude4f\\udea3-\\udecc]");'
}

View File

@@ -10,13 +10,13 @@ function read(path) {
describe("bin/uglifyjs", function () {
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
it("should produce a functional build when using --self", function (done) {
this.timeout(60000);
this.timeout(120000);
var command = uglifyjscmd + ' --self -mc ecma=';
command += semver.satisfies(process.version, ">=4") ? "6" : "5";
command += ',passes=3,keep_fargs=false,unsafe --wrap WrappedUglifyJS';
exec(command, function (err, stdout) {
exec(command, { maxBuffer: 1048576 }, function (err, stdout) {
if (err) throw err;
eval(stdout);

View File

@@ -14,7 +14,7 @@ describe("comment filters", function() {
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");
assert.strictEqual(ast.print_to_string({comments: "some"}), "/*@preserve*/\n/*@license*/\n/*@cc_on something*/");
});
it("Should be able to filter comments by passing a function", function() {
@@ -55,12 +55,12 @@ describe("comment filters", function() {
return true;
};
assert.strictEqual(ast.print_to_string({comments: f}), "#!Random comment\n//test1\n/*test2*/\n");
assert.strictEqual(ast.print_to_string({comments: f}), "#!Random comment\n//test1\n/*test2*/");
});
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");
assert.strictEqual(ast.print_to_string({comments: "some"}), "#!foo\n/*@preserve*/");
});
it("Should have no problem on multiple calls", function() {

View File

@@ -48,4 +48,176 @@ describe("Comment", function() {
}, fail, tests[i]);
}
});
it("Should handle comment within return correctly", function() {
var result = uglify.minify([
"function unequal(x, y) {",
" return (",
" // Either one",
" x < y",
" ||",
" y < x",
" );",
"}",
].join("\n"), {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"function unequal(x, y) {",
" // Either one",
" return x < y || y < x;",
"}",
].join("\n"));
});
it("Should handle comment folded into return correctly", function() {
var result = uglify.minify([
"function f() {",
" /* boo */ x();",
" return y();",
"}",
].join("\n"), {
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"function f() {",
" /* boo */",
" return x(), y();",
"}",
].join("\n"));
});
it("Should not drop comments after first OutputStream", function() {
var code = "/* boo */\nx();";
var ast = uglify.parse(code);
var out1 = uglify.OutputStream({
beautify: true,
comments: "all",
});
ast.print(out1);
var out2 = uglify.OutputStream({
beautify: true,
comments: "all",
});
ast.print(out2);
assert.strictEqual(out1.get(), code);
assert.strictEqual(out2.get(), out1.get());
});
it("Should retain trailing comments", function() {
var code = [
"if (foo /* lost comment */ && bar /* lost comment */) {",
" // this one is kept",
" {/* lost comment */}",
" !function() {",
" // lost comment",
" }();",
" function baz() {/* lost comment */}",
" // lost comment",
"}",
"// comments right before EOF are lost as well",
].join("\n");
var result = uglify.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
it("Should correctly preserve new lines around comments", function() {
var tests = [
[
"// foo",
"// bar",
"x();",
].join("\n"),
[
"// foo",
"/* bar */",
"x();",
].join("\n"),
[
"// foo",
"/* bar */ x();",
].join("\n"),
[
"/* foo */",
"// bar",
"x();",
].join("\n"),
[
"/* foo */ // bar",
"x();",
].join("\n"),
[
"/* foo */",
"/* bar */",
"x();",
].join("\n"),
[
"/* foo */",
"/* bar */ x();",
].join("\n"),
[
"/* foo */ /* bar */",
"x();",
].join("\n"),
"/* foo */ /* bar */ x();",
].forEach(function(code) {
var result = uglify.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
});
it("Should preserve new line before comment without beautify", function() {
var code = [
"function f(){",
"/* foo */bar()}",
].join("\n");
var result = uglify.minify(code, {
compress: false,
mangle: false,
output: {
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
it("Should preserve comments around IIFE", function() {
var result = uglify.minify("/*a*/(/*b*/function(){/*c*/}/*d*/)/*e*/();", {
compress: false,
mangle: false,
output: {
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, "/*a*/ /*b*/(function(){/*c*/}/*d*/ /*e*/)();");
});
});

View File

@@ -11,7 +11,7 @@ describe("bin/uglifyjs with input file globs", function() {
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'function foo(o){print("Foo:",2*o)}var print=console.log.bind(console);\n');
assert.strictEqual(stdout, 'var print=console.log.bind(console);function foo(o){print("Foo:",2*o)}\n');
done();
});
});
@@ -26,7 +26,7 @@ describe("bin/uglifyjs with input file globs", function() {
});
});
it("bin/uglifyjs with multiple input file globs.", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1242/???.es5" "test/input/issue-1242/*.js" -mc toplevel,passes=2';
var command = uglifyjscmd + ' "test/input/issue-1242/???.es5" "test/input/issue-1242/*.js" -mc toplevel,passes=3';
exec(command, function(err, stdout) {
if (err) throw err;

View File

@@ -43,7 +43,7 @@ describe("minify", function() {
compressed += result.code;
});
assert.strictEqual(JSON.stringify(cache).slice(0, 20), '{"cname":5,"props":{');
assert.strictEqual(compressed, 'function n(n){return 3*n}function r(n){return n/2}function c(o){l("Foo:",2*o)}var l=console.log.bind(console);var f=n(3),i=r(12);l("qux",f,i),c(11);');
assert.strictEqual(compressed, 'function n(n){return 3*n}function r(n){return n/2}var c=console.log.bind(console);function l(o){c("Foo:",2*o)}var f=n(3),i=r(12);c("qux",f,i),l(11);');
assert.strictEqual(run_code(compressed), run_code(original));
});
@@ -69,7 +69,7 @@ describe("minify", function() {
compressed += result.code;
});
assert.strictEqual(JSON.stringify(cache).slice(0, 28), '{"vars":{"cname":5,"props":{');
assert.strictEqual(compressed, 'function n(n){return 3*n}function r(n){return n/2}function c(o){l("Foo:",2*o)}var l=console.log.bind(console);var f=n(3),i=r(12);l("qux",f,i),c(11);');
assert.strictEqual(compressed, 'function n(n){return 3*n}function r(n){return n/2}var c=console.log.bind(console);function l(o){c("Foo:",2*o)}var f=n(3),i=r(12);c("qux",f,i),l(11);');
assert.strictEqual(run_code(compressed), run_code(original));
});
@@ -248,7 +248,7 @@ describe("minify", function() {
var code = result.code;
assert.strictEqual(code, "// comment1 comment2\nbar();");
});
it("should not drop #__PURE__ hint if function is retained", function() {
it("should drop #__PURE__ hint if function is retained", function() {
var result = Uglify.minify("var a = /*#__PURE__*/(function(){ foo(); })();", {
output: {
comments: "all",
@@ -256,7 +256,7 @@ describe("minify", function() {
}
});
var code = result.code;
assert.strictEqual(code, "var a=/*#__PURE__*/function(){foo()}();");
assert.strictEqual(code, "var a=/* */function(){foo()}();");
})
});
@@ -328,4 +328,37 @@ describe("minify", function() {
});
});
});
describe("collapse_vars", function() {
it("Should not produce invalid AST", function() {
var code = [
"function f(a) {",
" a = x();",
" return a;",
"}",
"f();",
].join("\n");
var ast = Uglify.minify(code, {
compress: false,
mangle: false,
output: {
ast: true
},
}).ast;
assert.strictEqual(ast.TYPE, "Toplevel");
assert.strictEqual(ast.body.length, 2);
assert.strictEqual(ast.body[0].TYPE, "Defun");
assert.strictEqual(ast.body[0].body.length, 2);
assert.strictEqual(ast.body[0].body[0].TYPE, "SimpleStatement");
var stat = ast.body[0].body[0];
Uglify.minify(ast, {
compress: {
sequences: false
},
mangle: false
});
assert.ok(stat.body);
assert.strictEqual(stat.print_to_string(), "a=x()");
});
});
});

View File

@@ -10,7 +10,7 @@ describe("spidermonkey export/import sanity test", function() {
var command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " +
uglifyjs + " -p spidermonkey -cm";
exec(command, function(err, stdout) {
exec(command, { maxBuffer: 1048576 }, function(err, stdout) {
if (err) throw err;
eval(stdout);

View File

@@ -117,6 +117,10 @@ function run_compress_tests() {
test.mangle.properties.reserved = quoted_props;
U.reserve_quoted_keys(input, quoted_props);
}
if (test.rename) {
input.figure_out_scope(test.mangle);
input.expand_names(test.mangle);
}
var cmp = new U.Compressor(options, true);
var output = cmp.compress(input);
output.figure_out_scope(test.mangle);

View File

@@ -37,6 +37,7 @@ var FUNC_TOSTRING = [
' return "[Function: " + i + "]";',
" }",
"}();",
'Object.defineProperty(Function.prototype, "valueOf", { enumerable: false });',
]).join("\n");
exports.run_code = function(code) {
var stdout = "";

View File

@@ -263,10 +263,8 @@ var CAN_CONTINUE = true;
var CANNOT_CONTINUE = false;
var CAN_RETURN = false;
var CANNOT_RETURN = true;
var NOT_GLOBAL = true;
var IN_GLOBAL = true;
var ANY_TYPE = false;
var NO_DECL = true;
var NO_DEFUN = false;
var DEFUN_OK = true;
var DONT_STORE = true;
var VAR_NAMES = [
@@ -307,6 +305,7 @@ var TYPEOF_OUTCOMES = [
var unique_vars = [];
var loops = 0;
var funcs = 0;
var called = Object.create(null);
var labels = 10000;
function rng(max) {
@@ -323,21 +322,22 @@ function createTopLevelCode() {
unique_vars.length = 0;
loops = 0;
funcs = 0;
called = Object.create(null);
return [
strictMode(),
'var a = 100, b = 10, c = 0;',
'var _calls_ = 10, a = 100, b = 10, c = 0;',
rng(2) == 0
? createStatements(3, MAX_GENERATION_RECURSION_DEPTH, CANNOT_THROW, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, 0)
: createFunctions(rng(MAX_GENERATED_TOPLEVELS_PER_RUN) + 1, MAX_GENERATION_RECURSION_DEPTH, IN_GLOBAL, ANY_TYPE, CANNOT_THROW, 0),
: createFunctions(rng(MAX_GENERATED_TOPLEVELS_PER_RUN) + 1, MAX_GENERATION_RECURSION_DEPTH, DEFUN_OK, CANNOT_THROW, 0),
'console.log(null, a, b, c);' // preceding `null` makes for a cleaner output (empty string still shows up etc)
].join('\n');
}
function createFunctions(n, recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
function createFunctions(n, recurmax, allowDefun, canThrow, stmtDepth) {
if (--recurmax < 0) { return ';'; }
var s = '';
while (n-- > 0) {
s += createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) + '\n';
s += createFunction(recurmax, allowDefun, canThrow, stmtDepth) + '\n';
}
return s;
}
@@ -363,16 +363,16 @@ function filterDirective(s) {
return s;
}
function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
if (--recurmax < 0) { return ';'; }
if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;
var func = funcs++;
var namesLenBefore = VAR_NAMES.length;
var name;
if (inGlobal || rng(5) > 0) name = 'f' + func;
else {
if (allowDefun || rng(5) > 0) {
name = 'f' + funcs++;
} else {
unique_vars.push('a', 'b', 'c');
name = createVarName(MANDATORY, noDecl);
name = createVarName(MANDATORY, !allowDefun);
unique_vars.length -= 3;
}
var s = [
@@ -381,7 +381,7 @@ function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
];
if (rng(5) === 0) {
// functions with functions. lower the recursion to prevent a mess.
s.push(createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), NOT_GLOBAL, ANY_TYPE, canThrow, stmtDepth));
s.push(createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), DEFUN_OK, canThrow, stmtDepth));
} else {
// functions with statements
s.push(createStatements(3, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth));
@@ -391,12 +391,16 @@ function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
VAR_NAMES.length = namesLenBefore;
if (noDecl) s = 'var ' + createVarName(MANDATORY) + ' = ' + s;
// avoid "function statements" (decl inside statements)
else if (inGlobal || rng(10) > 0) s += 'var ' + createVarName(MANDATORY) + ' = ' + name;
s += '(' + createArgs(recurmax, stmtDepth, canThrow) + ');';
if (!allowDefun) {
// avoid "function statements" (decl inside statements)
s = 'var ' + createVarName(MANDATORY) + ' = ' + s;
s += '(' + createArgs(recurmax, stmtDepth, canThrow) + ')';
} else if (!(name in called) || rng(3) > 0) {
s += 'var ' + createVarName(MANDATORY) + ' = ' + name;
s += '(' + createArgs(recurmax, stmtDepth, canThrow) + ')';
}
return s;
return s + ';';
}
function createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {
@@ -541,7 +545,7 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
case STMT_FUNC_EXPR:
// "In non-strict mode code, functions can only be declared at top level, inside a block, or ..."
// (dont both with func decls in `if`; it's only a parser thing because you cant call them without a block)
return '{' + createFunction(recurmax, NOT_GLOBAL, NO_DECL, canThrow, stmtDepth) + '}';
return '{' + createFunction(recurmax, NO_DEFUN, canThrow, stmtDepth) + '}';
case STMT_TRY:
// catch var could cause some problems
// note: the "blocks" are syntactically mandatory for try/catch/finally
@@ -648,7 +652,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
'(function ' + name + '(){',
strictMode(),
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
'})()'
rng(2) == 0 ? '})' : '})()'
);
break;
case 1:
@@ -687,7 +691,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
}
s.push(
createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),
'}'
rng(2) == 0 ? '}' : '}()'
);
break;
}
@@ -754,6 +758,13 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
case p++:
var name = getVarName();
return name + ' && ' + name + '.' + getDotKey();
case p++:
case p++:
case p++:
case p++:
var name = rng(3) == 0 ? getVarName() : 'f' + rng(funcs + 2);
called[name] = true;
return 'typeof ' + name + ' == "function" && --_calls_ >= 0 && ' + name + '(' + createArgs(recurmax, stmtDepth, canThrow) + ')';
}
_createExpression.N = p;
return _createExpression(recurmax, noComma, stmtDepth, canThrow);

View File

@@ -15,15 +15,12 @@
},
{},
{
"compress": {
"hoist_props": true
},
"toplevel": true
},
{
"compress": {
"keep_fargs": false,
"passes": 3
"passes": 100
}
}
]

View File

@@ -2,4 +2,5 @@ exports["Dictionary"] = Dictionary;
exports["TreeWalker"] = TreeWalker;
exports["TreeTransformer"] = TreeTransformer;
exports["minify"] = minify;
exports["parse"] = parse;
exports["_push_uniq"] = push_uniq;