Compare commits

...

76 Commits

Author SHA1 Message Date
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
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
Alex Lam S.L
b29fc8b27c improve transversal efficiency in collapse_vars (#2611)
fixes #2603
2017-12-18 03:00:05 +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
0e16d92786 handle exceptional flow correctly in collapse_vars (#2574)
fixes #2571
2017-12-11 00:16:02 +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
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
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
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
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
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
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
b80062c490 enable hoist_props by default (#2492) 2017-11-19 14:56:23 +08:00
59 changed files with 5666 additions and 1286 deletions

View File

@@ -598,17 +598,14 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
## Compress options
- `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.
- `conditionals` (default: `true`) -- apply optimizations for `if`-s and conditional
@@ -616,7 +613,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.
@@ -625,14 +622,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,
@@ -647,19 +644,18 @@ 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_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
@@ -690,11 +686,11 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
`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
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.
@@ -707,21 +703,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.
@@ -746,25 +743,25 @@ 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_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.
Examples:

View File

@@ -47,6 +47,7 @@ program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("d
program.option("--ie8", "Support non-standard Internet Explorer 8.");
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
program.option("--name-cache <file>", "File to hold mangled name mappings.");
program.option("--no-rename", "Disable symbol expansion.");
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_source_map());
program.option("--timings", "Display operations run time on STDERR.")
@@ -65,11 +66,13 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
"compress",
"ie8",
"mangle",
"rename",
"sourceMap",
"toplevel",
"wrap"
].forEach(function(name) {
if (name in program) {
if (name == "rename" && program[name]) return;
options[name] = program[name];
}
});

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", {
@@ -898,24 +898,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

@@ -55,6 +55,7 @@ function minify(files, options) {
nameCache: null,
output: {},
parse: {},
rename: undefined,
sourceMap: false,
timings: false,
toplevel: false,
@@ -64,6 +65,9 @@ function minify(files, options) {
var timings = options.timings && {
start: Date.now()
};
if (options.rename === undefined) {
options.rename = options.compress && options.mangle;
}
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
@@ -137,6 +141,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();
@@ -197,7 +206,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,
@@ -121,11 +122,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) {
@@ -194,6 +200,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 && [];
@@ -252,6 +261,20 @@ function OutputStream(options) {
function print(str) {
str = String(str);
var ch = str.charAt(0);
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;
@@ -350,7 +373,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;
@@ -422,6 +451,116 @@ function OutputStream(options) {
return OUTPUT;
};
function prepend_comments(node) {
var self = this;
var start = node.start;
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) {
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,
@@ -459,7 +598,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 },
@@ -495,9 +635,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)) {
@@ -514,77 +655,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) {
@@ -806,14 +880,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();
@@ -908,7 +989,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);
@@ -1039,7 +1120,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);
@@ -1056,12 +1137,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 ]----- */

View File

@@ -132,6 +132,18 @@ function is_letter(code) {
|| (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code)));
};
function is_surrogate_pair_head(code) {
if (typeof code == "string")
code = code.charCodeAt(0);
return code >= 0xd800 && code <= 0xdbff;
}
function is_surrogate_pair_tail(code) {
if (typeof code == "string")
code = code.charCodeAt(0);
return code >= 0xdc00 && code <= 0xdfff;
}
function is_digit(code) {
return code >= 48 && code <= 57;
};
@@ -305,11 +317,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);
@@ -1268,9 +1276,26 @@ function parse($TEXT, options) {
case "(":
next();
var ex = expression(true);
var len = start.comments_before.length;
[].unshift.apply(ex.start.comments_before, start.comments_before);
start.comments_before = ex.start.comments_before;
start.comments_before_length = len;
if (len == 0 && start.comments_before.length > 0) {
var comment = start.comments_before[0];
if (!comment.nlb) {
comment.nlb = start.nlb;
start.nlb = false;
}
}
start.comments_after = ex.start.comments_after;
ex.start = start;
ex.end = S.token;
expect(")");
var end = prev();
end.comments_before = ex.end.comments_before;
[].push.apply(ex.end.comments_after, end.comments_after);
end.comments_after = ex.end.comments_after;
ex.end = end;
if (ex instanceof AST_Call) mark_pure(ex);
return subscripts(ex, allow_calls);
case "[":
return subscripts(array_(), allow_calls);
@@ -1418,6 +1443,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", ".")) {
@@ -1442,12 +1480,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 : expr_list(")"),
end : prev()
}), true);
});
mark_pure(call);
return subscripts(call, true);
}
return expr;
};

View File

@@ -84,7 +84,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,7 +43,7 @@
"use strict";
function SymbolDef(scope, index, orig) {
function SymbolDef(scope, orig) {
this.name = orig.name;
this.orig = [ orig ];
this.eliminated = 0;
@@ -53,7 +53,6 @@ function SymbolDef(scope, index, orig) {
this.global = false;
this.mangled_name = null;
this.undeclared = false;
this.index = index;
this.id = SymbolDef.next_id++;
};
@@ -253,7 +252,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);
@@ -314,7 +313,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 {
@@ -332,7 +331,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
@@ -384,7 +383,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,
@@ -393,15 +392,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
@@ -410,11 +408,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){
@@ -426,13 +420,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) {
@@ -452,6 +440,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){
@@ -482,7 +543,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": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.1.10",
"version": "3.3.0",
"engines": {
"node": ">=0.8.0"
},
@@ -29,11 +29,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

@@ -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

@@ -2,7 +2,7 @@ collapse_vars_side_effects_1: {
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,
reduce_funcs: true, reduce_vars:true
}
input: {
@@ -83,7 +83,7 @@ collapse_vars_side_effects_2: {
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 fn(x) { return console.log(x), x; }
@@ -151,8 +151,8 @@ collapse_vars_issue_721: {
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,
reduce_funcs: true, reduce_vars:true
keep_fargs:true, if_return:true, join_vars:true, side_effects:true,
reduce_funcs: true, reduce_vars:true, passes:2
}
input: {
define(["require", "exports", 'handlebars'], function (require, exports, hb) {
@@ -218,7 +218,7 @@ collapse_vars_properties: {
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,
reduce_funcs: true, reduce_vars:true
}
input: {
@@ -246,7 +246,7 @@ collapse_vars_if: {
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,
reduce_funcs: true, reduce_vars:true
}
input: {
@@ -297,7 +297,7 @@ collapse_vars_while: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:false, 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,
reduce_funcs: true, reduce_vars:true
}
input: {
@@ -346,7 +346,7 @@ collapse_vars_do_while: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:false, loops:false, unused:"keep_assign",
hoist_funs:true, keep_fargs:true, if_return:true, join_vars:true, cascade:true,
hoist_funs:true, keep_fargs:true, if_return:true, join_vars:true,
side_effects:true
}
input: {
@@ -422,7 +422,7 @@ collapse_vars_do_while_drop_assign: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:false, loops:false, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
keep_fargs:true, if_return:true, join_vars:true, side_effects:true
}
input: {
function f1(y) {
@@ -497,7 +497,7 @@ collapse_vars_seq: {
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: {
var f1 = function(x, y) {
@@ -505,20 +505,23 @@ collapse_vars_seq: {
a = z, b = 7;
return a + b;
};
console.log(f1(1, 2));
}
expect: {
var f1 = function(x, y) {
var a, b, r = x + y;
return a = r * r - r, b = 7, a + b
var r = x + y;
return r * r - r + 7;
};
console.log(f1(1, 2));
}
expect_stdout: "13"
}
collapse_vars_throw: {
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: {
var f1 = function(x, y) {
@@ -526,20 +529,31 @@ collapse_vars_throw: {
a = z, b = 7;
throw a + b;
};
try {
f1(1, 2);
} catch (e) {
console.log(e);
}
}
expect: {
var f1 = function(x, y) {
var a, b, r = x + y;
throw a = r * r - r, b = 7, a + b
var r = x + y;
throw r * r - r + 7;
};
try {
f1(1, 2);
} catch (e) {
console.log(e);
}
}
expect_stdout: "13"
}
collapse_vars_switch: {
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() {
@@ -577,9 +591,9 @@ collapse_vars_switch: {
collapse_vars_assignment: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
collapse_vars:true, sequences:true, properties: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 log(x) { return console.log(x), x; }
@@ -625,7 +639,7 @@ collapse_vars_assignment: {
return a = a;
}
function f1(c) {
return 1 - 3 / c
return 1 - 3 / c;
}
function f2(c) {
return log(c = 3 / c - 7);
@@ -650,9 +664,9 @@ collapse_vars_assignment: {
collapse_vars_lvalues: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
collapse_vars:true, sequences:true, properties:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:"keep_assign",
hoist_funs:true, keep_fargs:true, if_return:true, join_vars:true, cascade:true,
hoist_funs:true, keep_fargs:true, if_return:true, join_vars:true,
side_effects:true
}
input: {
@@ -683,9 +697,9 @@ collapse_vars_lvalues: {
collapse_vars_lvalues_drop_assign: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
collapse_vars:true, sequences:true, properties: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, passes:3
}
input: {
function f0(x) { var i = ++x; return x += i; }
@@ -705,19 +719,19 @@ collapse_vars_lvalues_drop_assign: {
function f2(x) { var z = x, a = ++z; return z += a; }
function f3(x) { var a = (x -= 3); return x + a; }
function f4(x) { var a = (x -= 3); return x + a; }
function f5(x) { e1(); var v = e2(), c = v = --x; return x - c; }
function f6(x) { e1(), e2(); return --x - x; }
function f7(x) { e1(); return x - (e2() - x); }
function f8(x) { e1(); return x - (e2() - x); }
function f9(x) { e1(); return e2() - x - x; }
function f5(x) { e1(), e2(); var c = --x; return x - c; }
function f6(x) { return e1(), e2(), --x - x; }
function f7(x) { return e1(), x - (e2() - x); }
function f8(x) { return e1(), x - (e2() - x); }
function f9(x) { return e1(), e2() - x - x; }
}
}
collapse_vars_misc1: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
collapse_vars:true, sequences:true, properties: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,
reduce_funcs: true, reduce_vars:true
}
input: {
@@ -765,7 +779,7 @@ collapse_vars_self_reference: {
collapse_vars:true, unused:false,
sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops: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: {
// avoid bug in self-referential declaration.
@@ -795,7 +809,7 @@ collapse_vars_repeated: {
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,
reduce_funcs: true, reduce_vars:true
}
input: {
@@ -838,7 +852,7 @@ collapse_vars_closures: {
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,
reduce_funcs: true, reduce_vars:true
}
input: {
@@ -866,7 +880,7 @@ collapse_vars_unary: {
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 f0(o, p) {
@@ -929,7 +943,7 @@ collapse_vars_try: {
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,
reduce_funcs: true, reduce_vars:true
}
input: {
@@ -985,7 +999,7 @@ collapse_vars_array: {
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(x, y) {
@@ -1019,7 +1033,7 @@ collapse_vars_object: {
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 f0(x, y) {
@@ -1087,7 +1101,7 @@ collapse_vars_eval_and_with: {
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: {
// Don't attempt to collapse vars in presence of eval() or with statement.
@@ -1127,7 +1141,7 @@ collapse_vars_constants: {
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,
reduce_funcs: true, reduce_vars:true
}
input: {
@@ -1165,7 +1179,7 @@ collapse_vars_arguments: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
keep_fargs:true, if_return:true, join_vars:true, side_effects:true,
toplevel:true, reduce_funcs: true, reduce_vars:true
}
input: {
@@ -1188,7 +1202,7 @@ collapse_vars_short_circuit: {
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 f0(x) { var a = foo(), b = bar(); return b || x; }
@@ -1241,7 +1255,6 @@ collapse_vars_short_circuited_conditions: {
keep_fargs: true,
if_return: false,
join_vars: true,
cascade: true,
side_effects: true,
}
input: {
@@ -1279,7 +1292,6 @@ collapse_vars_short_circuited_conditions: {
collapse_vars_regexp: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
comparisons: true,
conditionals: true,
@@ -1443,7 +1455,6 @@ issue_1605_2: {
issue_1631_1: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
@@ -1479,7 +1490,6 @@ issue_1631_1: {
issue_1631_2: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
@@ -1515,7 +1525,6 @@ issue_1631_2: {
issue_1631_3: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
@@ -1690,7 +1699,7 @@ var_defs: {
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: {
var f1 = function(x, y) {
@@ -1748,7 +1757,7 @@ for_init: {
}
}
switch_case: {
switch_case_1: {
options = {
collapse_vars: true,
unused: true,
@@ -1767,16 +1776,71 @@ switch_case: {
}
expect: {
function f(x, y, z) {
var c = z;
switch (x()) {
default: d();
case y(): e();
case c: f();
case z: f();
}
}
}
}
switch_case_2: {
options = {
collapse_vars: true,
}
input: {
var a = 1, b = 2;
switch (b++) {
case b:
var c = a;
var a;
break;
}
console.log(a);
}
expect: {
var a = 1, b = 2;
switch (b++) {
case b:
var c = a;
var a;
break;
}
console.log(a);
}
expect_stdout: "1"
}
switch_case_3: {
options = {
collapse_vars: true,
}
input: {
var a = 1, b = 2;
switch (a) {
case a:
var b;
break;
case b:
break;
}
console.log(b);
}
expect: {
var a = 1, b = 2;
switch (a) {
case a:
var b;
break;
case b:
break;
}
console.log(b);
}
expect_stdout: "2"
}
issue_27: {
options = {
collapse_vars: true,
@@ -1929,10 +1993,8 @@ undeclared: {
}
expect: {
function f(x, y) {
var a;
a = x;
b = y;
return b + a;
return b + x;
}
}
}
@@ -2013,7 +2075,8 @@ chained_3: {
}
expect: {
console.log(function(a, b) {
var c = 1, c = b;
var c = 1;
c = b;
b++;
return c;
}(0, 2));
@@ -2081,7 +2144,7 @@ inner_lvalues: {
expect_stdout: true
}
double_def: {
double_def_1: {
options = {
collapse_vars: true,
unused: true,
@@ -2091,8 +2154,23 @@ double_def: {
a();
}
expect: {
var a = x;
(a = a && y)();
var a;
(a = (a = x) && y)();
}
}
double_def_2: {
options = {
collapse_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = x, a = a && y;
a();
}
expect: {
(x && y)();
}
}
@@ -2201,7 +2279,7 @@ lvalues_def: {
}
expect: {
var a = 0, b = 1;
var a = b++, b = +void 0;
a = b++, b = +void 0;
a && a[a++];
console.log(a, b);
}
@@ -2386,6 +2464,7 @@ duplicate_argname: {
issue_2298: {
options = {
collapse_vars: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
@@ -3073,10 +3152,9 @@ issue_2437: {
var result = !!req.onreadystatechange;
Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});
return result;
}
else {
} else {
var req = new XMLHttpRequest();
var detectFunc = function () { };
var detectFunc = function () {};
req.onreadystatechange = detectFunc;
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
req.onreadystatechange = null;
@@ -3087,13 +3165,14 @@ issue_2437: {
}
expect: {
!function() {
if (xhrDesc)
return result = !!(req = new XMLHttpRequest()).onreadystatechange,
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
if (xhrDesc) {
var result = !!(req = new XMLHttpRequest()).onreadystatechange;
return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
result;
var req = new XMLHttpRequest(), detectFunc = function() {};
req.onreadystatechange = detectFunc;
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
}
var req, detectFunc = function() {};
(req = new XMLHttpRequest()).onreadystatechange = detectFunc;
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
req.onreadystatechange = null;
}();
}
@@ -3238,15 +3317,14 @@ issue_2436_4: {
}(o));
}
expect: {
console.log(function(c) {
return {
x: c.a,
y: c.b,
};
}({
console.log({
x: (c = {
a: 1,
b: 2,
}));
}).a,
y: c.b,
});
var c;
}
expect_stdout: true
}
@@ -3369,12 +3447,11 @@ issue_2436_8: {
}(o));
}
expect: {
console.log(function(c) {
return {
x: c.a,
y: c.b,
};
}(o));
console.log({
x: (c = o).a,
y: c.b,
});
var c;
}
expect_stdout: true
}
@@ -3399,12 +3476,11 @@ issue_2436_9: {
}
expect: {
var o = console;
console.log(function(c) {
return {
x: c.a,
y: c.b,
};
}(o));
console.log({
x: (c = o).a,
y: c.b,
});
var c;
}
expect_stdout: true
}
@@ -3444,13 +3520,12 @@ issue_2436_10: {
o = { b: 3 };
return n;
}
console.log(function(c) {
return [
c.a,
f(c.b),
c.b,
];
}(o).join(" "));
console.log((c = o, [
c.a,
f(c.b),
c.b,
]).join(" "));
var c;
}
expect_stdout: "1 2 2"
}
@@ -3522,6 +3597,7 @@ issue_2436_12: {
issue_2436_13: {
options = {
collapse_vars: true,
passes: 2,
reduce_vars: true,
unused: true,
}
@@ -3578,3 +3654,361 @@ issue_2436_14: {
}
expect_stdout: true
}
issue_2497: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function sample() {
if (true) {
for (var i = 0; i < 1; ++i) {
for (var k = 0; k < 1; ++k) {
var value = 1;
var x = value;
value = x ? x + 1 : 0;
}
}
} else {
for (var i = 0; i < 1; ++i) {
for (var k = 0; k < 1; ++k) {
var value = 1;
}
}
}
}
}
expect: {
function sample() {
if (true)
for (var i = 0; i < 1; ++i)
for (var k = 0; k < 1; ++k) {
value = 1;
value = value ? value + 1 : 0;
}
else
for (i = 0; i < 1; ++i)
for (k = 0; k < 1; ++k)
var value = 1;
}
}
}
issue_2506: {
options = {
collapse_vars: true,
passes: 2,
reduce_vars: true,
unused: true,
}
input: {
var c = 0;
function f0(bar) {
function f1(Infinity_2) {
function f13(NaN) {
if (false <= NaN & this >> 1 >= 0) {
c++;
}
}
var b_2 = f13(NaN, c++);
}
var bar = f1(-3, -1);
}
f0(false);
console.log(c);
}
expect: {
var c = 0;
function f0(bar) {
(function(Infinity_2) {
(function(NaN) {
if (false <= 0/0 & this >> 1 >= 0)
c++;
})(0, c++);
})();
}
f0(false);
console.log(c);
}
expect_stdout: "1"
}
issue_2571_1: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
var b = 1;
try {
var a = function f0(c) {
throw c;
}(2);
var d = --b + a;
} catch (e) {
}
console.log(b);
}
expect: {
var b = 1;
try {
var a = function f0(c) {
throw c;
}(2);
var d = --b + a;
} catch (e) {
}
console.log(b);
}
expect_stdout: "1"
}
issue_2571_2: {
options = {
collapse_vars: true,
toplevel: true,
}
input: {
try {
var a = A, b = 1;
throw a;
} catch (e) {
console.log(b);
}
}
expect: {
try {
var a = A, b = 1;
throw a;
} catch (e) {
console.log(b);
}
}
expect_stdout: "undefined"
}
may_throw_1: {
options = {
collapse_vars: true,
}
input: {
function f() {
var a_2 = function() {
var a;
}();
}
}
expect: {
function f() {
var a_2 = function() {
var a;
}();
}
}
}
may_throw_2: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(b) {
try {
var a = x();
++b;
return b(a);
} catch(e) {}
console.log(b);
}
f(0);
}
expect: {
function f(b) {
try {
var a = x();
return (++b)(a);
} catch(e) {}
console.log(b);
}
f(0);
}
expect_stdout: "0"
}
side_effect_free_replacement: {
options = {
collapse_vars: true,
inline: true,
side_effects: true,
unused: true,
}
input: {
var b;
(function(a) {
x(a);
})(b);
}
expect: {
var b;
x(b);
}
}
recursive_function_replacement: {
rename = true
options = {
collapse_vars: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {}
input: {
function f(a) {
return x(g(a));
}
function g(a) {
return y(f(a));
}
console.log(f(c));
}
expect: {
function f(n) {
return x(y(f(n)));
}
console.log(f(c));
}
}
cascade_conditional: {
options = {
collapse_vars: true,
}
input: {
function f(a, b) {
(a = x(), a) ? a++ : (b = y(a), b(a));
}
}
expect: {
function f(a, b) {
(a = x()) ? a++ : (b = y(a))(a);
}
}
}
cascade_if_1: {
options = {
collapse_vars: true,
}
input: {
var a;
if (a = x(), a)
if (a == y()) z();
}
expect: {
var a;
if (a = x())
if (a == y()) z();
}
}
cascade_if_2: {
options = {
collapse_vars: true,
}
input: {
function f(a, b) {
if (a(), b = x()) return b;
}
}
expect: {
function f(a, b) {
if (a(), b = x()) return b;
}
}
}
cascade_return: {
options = {
collapse_vars: true,
}
input: {
function f(a) {
return a = x();
return a;
}
}
expect: {
function f(a) {
return a = x();
return a;
}
}
}
cascade_switch: {
options = {
collapse_vars: true,
}
input: {
function f(a, b) {
switch(a = x(), a) {
case a = x(), b(a):
break;
}
}
}
expect: {
function f(a, b) {
switch(a = x()) {
case b(a = x()):
break;
}
}
}
}
cascade_call: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(a) {
var b;
return x((b = a, y(b)));
}
}
expect: {
function f(a) {
return x(y(a));
}
}
}
replace_all_var: {
options = {
collapse_vars: true,
unused: true,
}
input: {
var a = "PASS";
(function() {
var b = b || c && c[a = "FAIL"], c = a;
})();
console.log(a);
}
expect: {
var a = "PASS";
(function() {
var b = b || c && c[a = "FAIL"], c = a;
})();
console.log(a);
}
expect_stdout: "PASS"
}

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

@@ -129,8 +129,8 @@ dead_code_constant_boolean_should_warn_more: {
function bar() {}
// nothing for the while
// as for the for, it should keep:
var x = 10, y;
var moo;
var x = 10, y;
bar();
}
expect_stdout: true
@@ -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
@@ -178,6 +178,8 @@ try_catch_finally: {
conditionals: true,
dead_code: true,
evaluate: true,
passes: 2,
side_effects: true,
}
input: {
var a = 1;
@@ -415,3 +417,414 @@ global_fns: {
"RangeError",
]
}
collapse_vars_assignment: {
options = {
collapse_vars: true,
dead_code: true,
passes: 2,
unused: true,
}
input: {
function f0(c) {
var a = 3 / c;
return a = a;
}
}
expect: {
function f0(c) {
return 3 / c;
}
}
}
collapse_vars_lvalues_drop_assign: {
options = {
collapse_vars: true,
dead_code: true,
unused: true,
}
input: {
function f0(x) { var i = ++x; return x += i; }
function f1(x) { var a = (x -= 3); return x += a; }
function f2(x) { var z = x, a = ++z; return z += a; }
}
expect: {
function f0(x) { var i = ++x; return x + i; }
function f1(x) { var a = (x -= 3); return x + a; }
function f2(x) { var z = x, a = ++z; return z + a; }
}
}
collapse_vars_misc1: {
options = {
collapse_vars: true,
dead_code: true,
unused: true,
}
input: {
function f10(x) { var a = 5, b = 3; return a += b; }
function f11(x) { var a = 5, b = 3; return a += --b; }
}
expect: {
function f10(x) { return 5 + 3; }
function f11(x) { var b = 3; return 5 + --b; }
}
}
return_assignment: {
options = {
dead_code: true,
unused: true,
}
input: {
function f1(a, b, c) {
return a = x(), b = y(), b = a && (c >>= 5);
}
function f2() {
return e = x();
}
function f3(e) {
return e = x();
}
function f4() {
var e;
return e = x();
}
function f5(a) {
try {
return a = x();
} catch (b) {
console.log(a);
}
}
function f6(a) {
try {
return a = x();
} finally {
console.log(a);
}
}
function y() {
console.log("y");
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6 ].forEach(function(f, i) {
e = null;
try {
i += 1;
console.log("result " + f(10 * i, 100 * i, 1000 * i));
} catch (x) {
console.log("caught " + x);
}
if (null !== e) console.log("e: " + e);
});
}
var x, e;
test(1);
test(-1);
}
expect: {
function f1(a, b, c) {
return a = x(), y(), a && (c >> 5);
}
function f2() {
return e = x();
}
function f3(e) {
return x();
}
function f4() {
return x();
}
function f5(a) {
try {
return x();
} catch (b) {
console.log(a);
}
}
function f6(a) {
try {
return a = x();
} finally {
console.log(a);
}
}
function y() {
console.log("y");
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6 ].forEach(function(f, i) {
e = null;
try {
i += 1;
console.log("result " + f(10 * i, 100 * i, 1000 * i));
} catch (x) {
console.log("caught " + x);
}
if (null !== e) console.log("e: " + e);
});
}
var x, e;
test(1);
test(-1);
}
expect_stdout: [
"y",
"result 31",
"result 2",
"e: 2",
"result 3",
"result 4",
"result 5",
"6",
"result 6",
"caught -1",
"caught -2",
"caught -3",
"caught -4",
"50",
"result undefined",
"60",
"caught -6",
]
}
throw_assignment: {
options = {
dead_code: true,
unused: true,
}
input: {
function f1() {
throw a = x();
}
function f2(a) {
throw a = x();
}
function f3() {
var a;
throw a = x();
}
function f4() {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f5(a) {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f6() {
var a;
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f7() {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f8(a) {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f9() {
var a;
try {
throw a = x();
} finally {
console.log(a);
}
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6, f7, f8, f9 ].forEach(function(f, i) {
a = null;
try {
f(10 * (1 + i));
} catch (x) {
console.log("caught " + x);
}
if (null !== a) console.log("a: " + a);
});
}
var x, a;
test(1);
test(-1);
}
expect: {
function f1() {
throw a = x();
}
function f2(a) {
throw x();
}
function f3() {
throw x();
}
function f4() {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f5(a) {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f6() {
var a;
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f7() {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f8(a) {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f9() {
var a;
try {
throw a = x();
} finally {
console.log(a);
}
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6, f7, f8, f9 ].forEach(function(f, i) {
a = null;
try {
f(10 * (1 + i));
} catch (x) {
console.log("caught " + x);
}
if (null !== a) console.log("a: " + a);
});
}
var x, a;
test(1);
test(-1);
}
expect_stdout: [
"caught 1",
"a: 1",
"caught 2",
"caught 3",
"4",
"a: 4",
"5",
"6",
"7",
"caught 7",
"a: 7",
"8",
"caught 8",
"9",
"caught 9",
"caught -1",
"caught -2",
"caught -3",
"null",
"50",
"undefined",
"null",
"caught -7",
"80",
"caught -8",
"undefined",
"caught -9",
]
}
issue_2597: {
options = {
dead_code: true,
}
input: {
function f(b) {
try {
try {
throw "foo";
} catch (e) {
return b = true;
}
} finally {
b && (a = "PASS");
}
}
var a = "FAIL";
f();
console.log(a);
}
expect: {
function f(b) {
try {
try {
throw "foo";
} catch (e) {
return b = true;
}
} finally {
b && (a = "PASS");
}
}
var a = "FAIL";
f();
console.log(a);
}
expect_stdout: "PASS"
}

View File

@@ -179,7 +179,9 @@ keep_fnames: {
}
drop_assign: {
options = { unused: true };
options = {
unused: true,
}
input: {
function f1() {
var a;
@@ -200,7 +202,7 @@ drop_assign: {
var a;
return function() {
a = 1;
}
};
}
}
expect: {
@@ -217,16 +219,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;
@@ -247,7 +250,7 @@ keep_assign: {
var a;
return function() {
a = 1;
}
};
}
}
expect: {
@@ -270,19 +273,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() {}
@@ -298,13 +304,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() {}
@@ -312,11 +321,10 @@ drop_toplevel_vars: {
console.log(b = 3);
}
expect: {
var c = g;
function f(d) {
return function() {
c = 2;
}
2;
};
}
2;
function g() {}
@@ -326,13 +334,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() {}
@@ -340,11 +352,10 @@ drop_toplevel_vars_fargs: {
console.log(b = 3);
}
expect: {
var c = g;
function f() {
return function() {
c = 2;
}
2;
};
}
2;
function g() {}
@@ -354,13 +365,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() {}
@@ -374,13 +388,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() {}
@@ -388,26 +405,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() {}
@@ -415,26 +434,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() {}
@@ -442,26 +463,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() {}
@@ -469,26 +493,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() {}
@@ -500,7 +527,7 @@ drop_toplevel_funcs_retain: {
function f(d) {
return function() {
c = 2;
}
};
}
a = 2;
function g() {}
@@ -509,13 +536,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() {}
@@ -523,11 +554,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() {}
@@ -537,13 +568,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() {}
@@ -651,7 +685,7 @@ drop_value: {
issue_1539: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
unused: true,
@@ -698,7 +732,7 @@ vardef_value: {
assign_binding: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
unused: true,
}
@@ -753,11 +787,11 @@ issue_1583: {
expect: {
function m(t) {
(function(e) {
t = function() {
(function() {
return (function(a) {
return function(a) {};
})();
}();
})();
})();
}
}
@@ -1239,7 +1273,7 @@ issue_2226_1: {
issue_2226_2: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
unused: true,
@@ -1252,8 +1286,8 @@ issue_2226_2: {
}
expect: {
console.log(function(a, b) {
return a += b;
}(1, 2));
return a += 2;
}(1));
}
expect_stdout: "3"
}
@@ -1294,8 +1328,88 @@ 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);
}
}

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;
@@ -1245,3 +1248,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:1316,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1317,20]",
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1318,20]",
"WARN: Condition left of && always false [test/compress/evaluate.js:1318,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1319,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1320,20]",
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1321,20]",
"WARN: Condition left of || always true [test/compress/evaluate.js:1321,20]",
]
}

View File

@@ -21,7 +21,7 @@ iifes_returning_constants_keep_fargs_true: {
join_vars : true,
reduce_funcs : true,
reduce_vars : true,
cascade : true,
collapse_vars : true,
inline : true,
}
input: {
@@ -58,7 +58,7 @@ iifes_returning_constants_keep_fargs_false: {
join_vars : true,
reduce_funcs : true,
reduce_vars : true,
cascade : true,
collapse_vars : true,
inline : true,
}
input: {
@@ -87,6 +87,7 @@ issue_485_crashing_1530: {
dead_code: true,
evaluate: true,
inline: true,
side_effects: true,
}
input: {
(function(a) {
@@ -94,9 +95,7 @@ issue_485_crashing_1530: {
var b = 42;
})(this);
}
expect: {
this, void 0;
}
expect: {}
}
issue_1841_1: {
@@ -424,9 +423,9 @@ inner_ref: {
issue_2107: {
options = {
cascade: true,
collapse_vars: true,
inline: true,
passes: 3,
sequences: true,
side_effects: true,
unused: true,
@@ -554,3 +553,873 @@ 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_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"
}
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

@@ -55,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"
}
@@ -67,9 +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,
}
@@ -500,3 +500,167 @@ issue_2473_4: {
}
expect_stdout: "1 2"
}
issue_2508_1: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: [ 1 ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
(function(x) {
console.log(x);
})([ 1 ]);
}
expect_stdout: true
}
issue_2508_2: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: { b: 2 },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
(function(x) {
console.log(x);
})({ b: 2 });
}
expect_stdout: true
}
issue_2508_3: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: [ o ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
var o = {
a: [ o ],
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect_stdout: true
}
issue_2508_4: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
a: { b: o },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect: {
var o = {
a: { b: o },
f: function(x) {
console.log(x);
}
};
o.f(o.a);
}
expect_stdout: true
}
issue_2508_5: {
options = {
collapse_vars: true,
hoist_props: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var o = {
f: function(x) {
console.log(x);
}
};
o.f(o.f);
}
expect: {
var o_f = function(x) {
console.log(x);
};
o_f(o_f);
}
expect_stdout: true
}
issue_2519: {
options = {
collapse_vars: true,
evaluate: true,
hoist_props: true,
reduce_vars: true,
unused: true,
}
input: {
function testFunc() {
var dimensions = {
minX: 5,
maxX: 6,
};
var scale = 1;
var d = {
x: (dimensions.maxX + dimensions.minX) / 2,
};
return d.x * scale;
}
console.log(testFunc());
}
expect: {
function testFunc() {
return 1 * ((6 + 5) / 2);
}
console.log(testFunc());
}
expect_stdout: "5.5"
}

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

@@ -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

@@ -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

@@ -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,
@@ -39,7 +38,7 @@ f7: {
"var b = 10;",
"",
"!function() {",
" for (;b = 100, !1; ) ;",
" b = 100;",
"}(), console.log(100, b);",
]
expect_stdout: 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

@@ -134,5 +134,5 @@ label_while: {
L: while (0) continue L;
}
}
expect_exact: "function f(){L:;}"
expect_exact: "function f(){L:0}"
}

View File

@@ -453,7 +453,7 @@ pure_annotation_2: {
drop_fargs: {
options = {
cascade: true,
collapse_vars: true,
inline: true,
keep_fargs: false,
side_effects: true,
@@ -476,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

@@ -148,9 +148,11 @@ parse_do_while_without_semicolon: {
evaluate: {
options = {
loops: true,
dead_code: true,
evaluate: true,
loops: true,
passes: 2,
side_effects: true,
};
input: {
while (true) {
@@ -450,3 +452,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

@@ -1028,3 +1028,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

@@ -185,7 +185,7 @@ impure_getter_2: {
issue_2110_1: {
options = {
cascade: true,
collapse_vars: true,
pure_getters: "strict",
sequences: true,
side_effects: true,
@@ -274,7 +274,7 @@ set_immutable_1: {
set_immutable_2: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: "strict",
reduce_funcs: true,
@@ -324,7 +324,7 @@ set_immutable_3: {
set_immutable_4: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: "strict",
reduce_funcs: true,
@@ -375,7 +375,7 @@ set_mutable_1: {
set_mutable_2: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: "strict",
reduce_funcs: true,
@@ -400,7 +400,7 @@ set_mutable_2: {
issue_2313_1: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: "strict",
sequences: true,
@@ -446,7 +446,7 @@ issue_2313_1: {
issue_2313_2: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: true,
sequences: true,

View File

@@ -972,8 +972,8 @@ inner_var_for_2: {
}
expect: {
!function() {
a = 1;
for (var b = 1; --b;) var a = 2;
var a = 1;
for (var b = 1; --b;) a = 2;
console.log(a);
}();
}
@@ -1209,6 +1209,7 @@ toplevel_on_loops_2: {
loops: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel:true,
unused: true,
}
@@ -1395,7 +1396,7 @@ defun_inline_3: {
options = {
evaluate: true,
inline: true,
passes: 2,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
@@ -2249,23 +2250,22 @@ redefine_farg_2: {
console.log(f([]), g([]), h([]));
}
expect: {
console.log(function(a) {
return typeof a;
}([]), "number",function(a, b) {
console.log((a = [], typeof a), "number",function(a, b) {
a = b;
return typeof a;
}([]));
var a;
}
expect_stdout: "object number undefined"
}
redefine_farg_3: {
options = {
cascade: true,
collapse_vars: true,
evaluate: true,
inline: true,
keep_fargs: false,
passes: 2,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
@@ -2346,7 +2346,7 @@ booleans: {
}
expect: {
console.log(function(a) {
if (!1);
if (0);
switch (!1) {
case 0:
return "FAIL";
@@ -3106,6 +3106,7 @@ obj_var_2: {
obj_arg_1: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
passes: 2,
@@ -3137,9 +3138,10 @@ obj_arg_1: {
obj_arg_2: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
passes: 2,
passes: 3,
properties: true,
reduce_funcs: true,
reduce_vars: true,
@@ -3420,6 +3422,37 @@ escaped_prop_1: {
}
escaped_prop_2: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
passes: 2,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var obj = { o: { a: 1 } };
(function(o) {
o.a++;
})(obj.o);
(function(o) {
console.log(o.a);
})(obj.o);
}
expect: {
var obj = { o: { a: 1 } };
obj.o.a++;
console.log(obj.o.a);
}
expect_stdout: "2"
}
escaped_prop_3: {
options = {
reduce_funcs: true,
reduce_vars: true,
@@ -4525,3 +4558,399 @@ issue_2485: {
}
expect_stdout: "6"
}
issue_2455: {
options = {
reduce_vars: true,
unused: true,
}
input: {
function foo() {
var that = this;
for (;;) that.bar();
}
}
expect: {
function foo() {
for (;;) this.bar();
}
}
}
escape_conditional: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function main() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("FAIL");
else
console.log("PASS");
}
function baz(s) {
return s ? foo : bar;
}
function foo() {}
function bar() {}
main();
}
expect: {
function baz(s) {
return s ? foo : bar;
}
function foo() {}
function bar() {}
(function() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("FAIL");
else
console.log("PASS");
})();
}
expect_stdout: "PASS"
}
escape_sequence: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function main() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("FAIL");
else
console.log("PASS");
}
function baz() {
return foo, bar;
}
function foo() {}
function bar() {}
main();
}
expect: {
function baz() {
return function() {}, bar;
}
function bar() {}
(function() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("FAIL");
else
console.log("PASS");
})();
}
expect_stdout: "PASS"
}
escape_throw: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function main() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("FAIL");
else
console.log("PASS");
}
function baz() {
try {
throw foo;
} catch (bar) {
return bar;
}
}
function foo() {}
main();
}
expect: {
function baz() {
try {
throw foo;
} catch (bar) {
return bar;
}
}
function foo() {}
(function() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("FAIL");
else
console.log("PASS");
})();
}
expect_stdout: "PASS"
}
escape_local_conditional: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function main() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("PASS");
else
console.log("FAIL");
}
function baz(s) {
function foo() {}
function bar() {}
return s ? foo : bar;
}
main();
}
expect: {
function baz(s) {
return s ? function() {} : function() {};
}
(function() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("PASS");
else
console.log("FAIL");
})();
}
expect_stdout: "PASS"
}
escape_local_sequence: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function main() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("PASS");
else
console.log("FAIL");
}
function baz() {
function foo() {}
function bar() {}
return foo, bar;
}
main();
}
expect: {
function baz() {
return function() {}, function() {};
}
(function() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("PASS");
else
console.log("FAIL");
})();
}
expect_stdout: "PASS"
}
escape_local_throw: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function main() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("PASS");
else
console.log("FAIL");
}
function baz() {
function foo() {}
try {
throw foo;
} catch (bar) {
return bar;
}
}
main();
}
expect: {
function baz() {
try {
throw function() {};
} catch (bar) {
return bar;
}
}
(function() {
var thing = baz();
if (thing !== (thing = baz()))
console.log("PASS");
else
console.log("FAIL");
})();
}
expect_stdout: "PASS"
}
inverted_var: {
options = {
evaluate: true,
inline: true,
passes: 3,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
console.log(function() {
var a = 1;
return a;
}(), function() {
var b;
b = 2;
return b;
}(), function() {
c = 3;
return c;
var c;
}(), function(c) {
c = 4;
return c;
}(), function (c) {
c = 5;
return c;
var c;
}(), function c() {
c = 6;
return c;
}(), function c() {
c = 7;
return c;
var c;
}(), function() {
c = 8;
return c;
var c = "foo";
}());
}
expect: {
console.log(1, 2, 3, 4, 5, function c() {
c = 6;
return c;
}(), 7, function() {
c = 8;
return c;
var c = "foo";
}());
}
expect_stdout: true
}
defun_single_use_loop: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
for (var x, i = 2; --i >= 0; ) {
var y = x;
x = f;
console.log(x === y);
}
function f() {};
}
expect: {
for (var x, i = 2; --i >= 0; ) {
var y = x;
x = f;
console.log(x === y);
}
function f() {};
}
expect_stdout: [
"false",
"true",
]
}
do_while: {
options = {
evaluate: true,
reduce_vars: true,
}
input: {
function f(a) {
do {
(function() {
a && (c = "PASS");
})();
} while (a = 0);
}
var c = "FAIL";
f(1);
console.log(c);
}
expect: {
function f(a) {
do {
(function() {
a && (c = "PASS");
})();
} while (a = 0);
}
var c = "FAIL";
f(1);
console.log(c);
}
expect_stdout: "PASS"
}
issue_2598: {
options = {
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {}
function g(a) {
return a || f;
}
console.log(g(false) === g(null));
}
expect: {
function f() {}
function g(a) {
return a || f;
}
console.log(g(false) === g(null));
}
expect_stdout: "true"
}

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

@@ -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,
@@ -723,7 +722,7 @@ issue_27: {
issue_2062: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
conditionals: true,
side_effects: true,
}
@@ -742,7 +741,7 @@ issue_2062: {
issue_2313: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
}
@@ -780,3 +779,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

@@ -817,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

@@ -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

@@ -55,3 +55,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

@@ -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

@@ -47,4 +47,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));
});
@@ -247,7 +247,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",
@@ -255,7 +255,7 @@ describe("minify", function() {
}
});
var code = result.code;
assert.strictEqual(code, "var a=/*#__PURE__*/function(){foo()}();");
assert.strictEqual(code, "var a=/* */function(){foo()}();");
})
});
@@ -323,7 +323,8 @@ describe("minify", function() {
Uglify.minify(ast, {
compress: {
sequences: false
}
},
mangle: false
});
assert.ok(stat.body);
assert.strictEqual(stat.print_to_string(), "a=x()");

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;