Compare commits

..

73 Commits

Author SHA1 Message Date
Alex Lam S.L
53600e9869 harmony-v3.3.3 2017-12-29 04:36:27 +08:00
alexlamsl
7dea749f58 Merge branch 'master' into harmony-v3.3.3 2017-12-29 03:30:53 +08:00
Alex Lam S.L
8ca49155a8 v3.3.3 2017-12-29 03:07:39 +08:00
Alex Lam S.L
b95e3338d9 fix pure_getters on AST_Binary (#2681)
fixes #2678
2017-12-28 17:01:01 +08:00
Alex Lam S.L
e40a0ee9c6 improve assignment variations (#2671) 2017-12-28 15:36:55 +08:00
Alex Lam S.L
0a3fac6e68 fix parenthesis output of AST_ClassExpression (#2677)
fixes #2676
2017-12-28 05:07:19 +08:00
Alex Lam S.L
cb62bd98d3 fix function inlining within loops (#2675)
fixes #2663
2017-12-28 02:53:14 +08:00
Alex Lam S.L
9f7d1f7ac6 fix reduce_vars on AST_Destructuring (#2672)
fixes #2669
fixes #2670
fixes #2673
2017-12-27 16:30:57 +08:00
Alex Lam S.L
f30790b11b fix dead_code on return assignments (#2668)
fixes #2666
2017-12-27 07:40:34 +08:00
Alex Lam S.L
5205dbcbf4 retain recursive function names (#2667)
fixes #2665
2017-12-27 07:00:12 +08:00
Alex Lam S.L
3ff625de7e fix bugs on substituted AST_Defun (#2661)
fixes #2660
2017-12-27 05:31:37 +08:00
Alex Lam S.L
4832bc5d88 replace single-use recursive functions (#2659)
fixes #2628
2017-12-26 21:25:35 +08:00
Alex Lam S.L
7f342cb3e3 suppress inline within substituted AST_Scope (#2658)
fixes #2657
2017-12-26 18:56:59 +08:00
Alex Lam S.L
05e7d34ed4 improve unused over duplicate variable names (#2656) 2017-12-26 18:29:28 +08:00
Alex Lam S.L
ef74f2eaaf harmony-v3.3.2 2017-12-26 05:21:31 +08:00
alexlamsl
96082f7a9b Merge branch 'master' into harmony-v3.3.2 2017-12-26 01:46:22 +08:00
Alex Lam S.L
86607156e3 v3.3.2 2017-12-26 01:38:56 +08:00
Alex Lam S.L
0fe259e9c5 parse LF & comment correctly (#2653)
fixes #2652
2017-12-26 01:38:01 +08:00
Alex Lam S.L
a53784e0c5 harmony-v3.3.1 2017-12-25 18:32:00 +08:00
alexlamsl
a3b8dec347 Merge branch 'master' into harmony-v3.3.1 2017-12-25 17:34:16 +08:00
Alex Lam S.L
49ce573971 handle non-ES5 node types in inline (#2648)
fixes #2647
2017-12-25 17:25:38 +08:00
Alex Lam S.L
8701a99a15 v3.3.1 2017-12-25 03:08:28 +08:00
Alex Lam S.L
1476c78b53 add html-minifier to benchmarks (#2646) 2017-12-25 03:07:46 +08:00
Alex Lam S.L
cb6a92892f fix infinite loop during inline (#2645)
fixes #2644
2017-12-25 01:57:11 +08:00
Alex Lam S.L
01bb08b553 harmony-v3.3.0 2017-12-24 22:58:15 +08:00
alexlamsl
fc3010bec5 add tests for #2613 2017-12-24 22:18:34 +08:00
alexlamsl
7de541f9c8 fix tests 2017-12-24 19:21:31 +08:00
alexlamsl
dbf8684287 Merge branch 'master' into harmony-v3.3.0 2017-12-24 19:19:24 +08:00
Alex Lam S.L
f1556cb945 v3.3.0 2017-12-24 17:34:56 +08:00
Alex Lam S.L
efffb81735 fix comments output & improve /*@__PURE__*/
- fix whitespace around comments
- fix comment parsing around parentheses
- consider parentheses when parsing `/*@__PURE__*/`
- remove all `/*@__PURE__*/` on output

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

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

where `fn` can be `function` literal or symbol reference linked through `reduce_vars`
2017-12-18 16:23:39 +08:00
Alex Lam S.L
0b0eac1d5d drop property assignment to constants (#2612) 2017-12-18 12:07:53 +08:00
kzc
85bfa17139 fix slowness in unused for blocks (#2614)
fixes #2609
2017-12-18 12:06:14 +08:00
Alex Lam S.L
b29fc8b27c improve transversal efficiency in collapse_vars (#2611)
fixes #2603
2017-12-18 03:00:05 +08:00
kzc
80c8dfcde6 fix export default of anonymous generators and async functions (#2607)
fixes #2606
2017-12-18 00:11:52 +08:00
Alex Lam S.L
5de369fa67 export parse() (#2608) 2017-12-17 23:12:23 +08:00
Alex Lam S.L
7918a50d52 improve reset_opt_flags() (#2610) 2017-12-17 23:01:08 +08:00
Alex Lam S.L
21794c9b8d account for catch variable when inline (#2605)
fixes #2604
2017-12-16 15:21:09 +08:00
Alex Lam S.L
6c686ce593 fix nested inline (#2602)
fixes #2601
2017-12-16 02:16:35 +08:00
Alex Lam S.L
db902af4c6 fix escape analysis on || and && (#2600)
fixes #2598
2017-12-15 19:48:14 +08:00
Alex Lam S.L
7d6907cb99 fix dead_code on nested try (#2599)
fixes #2597
2017-12-15 19:41:28 +08:00
Alex Lam S.L
092d9affb8 fix reduce_vars on do...while (#2596) 2017-12-15 16:33:19 +08:00
Alex Lam S.L
8f681b1d17 handle inline of function arguments (#2590)
fixes #2476
2017-12-15 13:28:30 +08:00
Alex Lam S.L
90313875f7 inline single-use function across loop (#2594) 2017-12-14 19:24:54 +08:00
Alex Lam S.L
3f18a61532 fix reduce_vars on single AST_Defun reference across loop (#2593) 2017-12-14 18:47:05 +08:00
Alex Lam S.L
02a6ce07eb improve reduce_vars (#2592)
- account for hoisting nature of `var`
2017-12-14 15:32:13 +08:00
Alex Lam S.L
738fd52bc4 improve collapse_vars (#2591)
- handle single-use assignments other than `AST_VarDef`
- scan `AST_Call` for candidates
2017-12-14 15:31:35 +08:00
kzc
d18979bb23 improve dead_code tests (#2589)
for #2588
2017-12-14 12:12:06 +08:00
Alex Lam S.L
8266993c6e fix dead_code on return/throw within try (#2588) 2017-12-14 04:38:21 +08:00
Alex Lam S.L
9a137e8613 drop local assign-only variable in return (#2587) 2017-12-14 02:59:59 +08:00
Alex Lam S.L
ef618332ea fold cascade functionality into collapse_vars (#2586) 2017-12-14 01:20:36 +08:00
Alex Lam S.L
7f418978c9 recover lost opportunities from #2574 (#2584) 2017-12-13 18:20:53 +08:00
Alex Lam S.L
04cc395c35 improve collapse_vars on side-effect-free replacements (#2583) 2017-12-13 04:52:54 +08:00
Alex Lam S.L
e008dc1bde minor clean-up for IIFE (#2582)
- faster exact type match
- aggressively convert to `!`
2017-12-13 01:27:26 +08:00
Alex Lam S.L
ddf96cfda2 avoid Function.prototype pollution by test/sandbox.js (#2581) 2017-12-12 05:02:01 +08:00
Alex Lam S.L
ebfd5c5c74 fix AST_VarDef.may_throw() (#2580) 2017-12-12 03:30:25 +08:00
Alex Lam S.L
f2ad542679 fix collapse_vars on switch (#2578) 2017-12-11 18:11:09 +08:00
Alex Lam S.L
c43118be4f remove unused code (#2579)
fixes #2577
2017-12-11 17:39:08 +08:00
Alex Lam S.L
93f3b2b114 escape consecutive unpaired surrogates (#2576)
fixes #2569
2017-12-11 01:15:44 +08:00
Alex Lam S.L
bf000beae7 rename tests (#2575) 2017-12-11 00:24:54 +08:00
Alex Lam S.L
0e16d92786 handle exceptional flow correctly in collapse_vars (#2574)
fixes #2571
2017-12-11 00:16:02 +08:00
48 changed files with 4260 additions and 954 deletions

View File

@@ -630,9 +630,6 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `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.
@@ -665,7 +662,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
- `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: `true`) -- hoist properties from constant object and
array literals into regular variables subject to a set of constraints. For example:

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", {

File diff suppressed because it is too large Load Diff

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,
@@ -133,11 +134,16 @@ function OutputStream(options) {
}
});
} : function(str) {
return str.replace(/[\ud800-\udbff](?![\udc00-\udfff])/g, function(ch) {
return "\\u" + ch.charCodeAt(0).toString(16);
}).replace(/(^|[^\ud800-\udbff])([\udc00-\udfff])/g, function(match, prefix, ch) {
return prefix + "\\u" + ch.charCodeAt(0).toString(16);
});
var s = "";
for (var i = 0, len = str.length; i < len; i++) {
if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
|| is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
s += "\\u" + str.charCodeAt(i).toString(16);
} else {
s += str[i];
}
}
return s;
};
function make_string(str, quote) {
@@ -210,6 +216,9 @@ function OutputStream(options) {
var might_need_space = false;
var might_need_semicolon = false;
var might_add_newline = 0;
var need_newline_indented = false;
var need_space = false;
var newline_insert = -1;
var last = "";
var mapping_token, mapping_name, mappings = options.source_map && [];
@@ -269,6 +278,21 @@ function OutputStream(options) {
str = String(str);
var ch = get_full_char(str, 0);
var prev = get_full_char(last, last.length - 1);
if (need_newline_indented && ch) {
need_newline_indented = false;
if (ch != "\n") {
print("\n");
indent();
}
}
if (need_space && ch) {
need_space = false;
if (!/[\s;})]/.test(ch)) {
space();
}
}
newline_insert = -1;
var prev = last.charAt(last.length - 1);
if (might_need_semicolon) {
might_need_semicolon = false;
@@ -370,7 +394,13 @@ function OutputStream(options) {
} : function(col, cont) { return cont() };
var newline = options.beautify ? function() {
print("\n");
if (newline_insert < 0) return print("\n");
if (OUTPUT[newline_insert] != "\n") {
OUTPUT = OUTPUT.slice(0, newline_insert) + "\n" + OUTPUT.slice(newline_insert);
current_pos++;
current_line++;
}
newline_insert++;
} : options.max_line_len ? function() {
ensure_line_len();
might_add_newline = OUTPUT.length;
@@ -442,6 +472,118 @@ function OutputStream(options) {
return OUTPUT;
};
function prepend_comments(node) {
var self = this;
var start = node.start;
if (!start) return;
if (!(start.comments_before && start.comments_before._dumped === self)) {
var comments = start.comments_before;
if (!comments) {
comments = start.comments_before = [];
}
comments._dumped = self;
if (node instanceof AST_Exit && node.value) {
var tw = new TreeWalker(function(node) {
var parent = tw.parent();
if (parent instanceof AST_Exit
|| parent instanceof AST_Binary && parent.left === node
|| parent.TYPE == "Call" && parent.expression === node
|| parent instanceof AST_Conditional && parent.condition === node
|| parent instanceof AST_Dot && parent.expression === node
|| parent instanceof AST_Sequence && parent.expressions[0] === node
|| parent instanceof AST_Sub && parent.expression === node
|| parent instanceof AST_UnaryPostfix) {
if (!node.start) return;
var text = node.start.comments_before;
if (text && text._dumped !== self) {
text._dumped = self;
comments = comments.concat(text);
}
} else {
return true;
}
});
tw.push(node);
node.value.walk(tw);
}
if (current_pos == 0) {
if (comments.length > 0 && options.shebang && comments[0].type == "comment5") {
print("#!" + comments.shift().value + "\n");
indent();
}
var preamble = options.preamble;
if (preamble) {
print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
}
}
comments = comments.filter(comment_filter, node);
if (comments.length == 0) return;
var last_nlb = /(^|\n) *$/.test(OUTPUT);
comments.forEach(function(c, i) {
if (!last_nlb) {
if (c.nlb) {
print("\n");
indent();
last_nlb = true;
} else if (i > 0) {
space();
}
}
if (/comment[134]/.test(c.type)) {
print("//" + c.value.replace(/[@#]__PURE__/g, ' ') + "\n");
indent();
last_nlb = true;
} else if (c.type == "comment2") {
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
last_nlb = false;
}
});
if (!last_nlb) {
if (start.nlb) {
print("\n");
indent();
} else {
space();
}
}
}
}
function append_comments(node, tail) {
var self = this;
var token = node.end;
if (!token) return;
var comments = token[tail ? "comments_before" : "comments_after"];
if (comments && comments._dumped !== self) {
comments._dumped = self;
var insert = OUTPUT.length;
comments.filter(comment_filter, node).forEach(function(c, i) {
need_space = false;
if (need_newline_indented) {
print("\n");
indent();
need_newline_indented = false;
} else if (c.nlb && (i > 0 || !/(^|\n) *$/.test(OUTPUT))) {
print("\n");
indent();
} else if (i > 0 || !tail) {
space();
}
if (/comment[134]/.test(c.type)) {
print("//" + c.value.replace(/[@#]__PURE__/g, ' '));
need_newline_indented = true;
} else if (c.type == "comment2") {
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
need_space = true;
}
});
if (OUTPUT.length > insert) newline_insert = insert;
}
}
var stack = [];
return {
get : get,
@@ -484,7 +626,8 @@ function OutputStream(options) {
with_square : with_square,
add_mapping : add_mapping,
option : function(opt) { return options[opt] },
comment_filter : comment_filter,
prepend_comments: readonly ? noop : prepend_comments,
append_comments : readonly ? noop : append_comments,
line : function() { return current_line },
col : function() { return current_col },
pos : function() { return current_pos },
@@ -520,9 +663,10 @@ function OutputStream(options) {
use_asm = active_scope;
}
function doit() {
self.add_comments(stream);
stream.prepend_comments(self);
self.add_source_map(stream);
generator(self, stream);
stream.append_comments(self);
}
stream.push_node(self);
if (force_parens || self.needs_parens(stream)) {
@@ -539,77 +683,10 @@ function OutputStream(options) {
AST_Node.DEFMETHOD("print_to_string", function(options){
var s = OutputStream(options);
if (!options) s._readonly = true;
this.print(s);
return s.get();
});
/* -----[ comments ]----- */
AST_Node.DEFMETHOD("add_comments", function(output){
if (output._readonly) return;
var self = this;
var start = self.start;
if (start && !start._comments_dumped) {
start._comments_dumped = true;
var comments = start.comments_before || [];
// XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112
// and https://github.com/mishoo/UglifyJS2/issues/372
if (self instanceof AST_Exit && self.value) {
self.value.walk(new TreeWalker(function(node){
if (node.start && node.start.comments_before) {
comments = comments.concat(node.start.comments_before);
node.start.comments_before = [];
}
if (node instanceof AST_Function ||
node instanceof AST_Array ||
node instanceof AST_Object)
{
return true; // don't go inside.
}
}));
}
if (output.pos() == 0) {
if (comments.length > 0 && output.option("shebang") && comments[0].type == "comment5") {
output.print("#!" + comments.shift().value + "\n");
output.indent();
}
var preamble = output.option("preamble");
if (preamble) {
output.print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
}
}
comments = comments.filter(output.comment_filter, self);
// Keep single line comments after nlb, after nlb
if (!output.option("beautify") && comments.length > 0 &&
/comment[134]/.test(comments[0].type) &&
output.col() !== 0 && comments[0].nlb)
{
output.print("\n");
}
comments.forEach(function(c){
if (/comment[134]/.test(c.type)) {
output.print("//" + c.value + "\n");
output.indent();
}
else if (c.type == "comment2") {
output.print("/*" + c.value + "*/");
if (start.nlb) {
output.print("\n");
output.indent();
} else {
output.space();
}
}
});
}
});
/* -----[ PARENTHESES ]----- */
function PARENS(nodetype, func) {
@@ -653,15 +730,9 @@ function OutputStream(options) {
return p instanceof AST_PropAccess && p.expression === this;
});
PARENS(AST_ClassExpression, function(output){
return output.parent() instanceof AST_SimpleStatement;
});
// same goes for an object literal, because otherwise it would be
// interpreted as a block of code.
PARENS(AST_Object, function(output){
return first_in_statement(output);
});
PARENS([ AST_ClassExpression, AST_Object ], first_in_statement);
PARENS(AST_Unary, function(output){
var p = output.parent();
@@ -897,14 +968,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();
@@ -1016,7 +1094,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);
@@ -1071,7 +1149,7 @@ function OutputStream(options) {
if (self.body instanceof AST_Node) {
self.body.print(output);
} else {
print_bracketed(self.body, output);
print_bracketed(self, output);
}
if (needs_parens) { output.print(")") }
});
@@ -1228,7 +1306,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);
@@ -1245,12 +1323,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

@@ -365,11 +365,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
}
if (!is_comment) {
ret.comments_before = S.comments_before;
S.comments_before = [];
// make note of any newlines in the comments that came before
for (var i = 0, len = ret.comments_before.length; i < len; i++) {
ret.nlb = ret.nlb || ret.comments_before[i].nlb;
}
ret.comments_after = S.comments_before = [];
}
S.newline_before = false;
return new AST_Token(ret);
@@ -938,10 +934,15 @@ function parse($TEXT, options) {
function expect(punc) { return expect_token("punc", punc); };
function has_newline_before(token) {
return token.nlb || !all(token.comments_before, function(comment) {
return !comment.nlb;
});
}
function can_insert_semicolon() {
return !options.strict && (
S.token.nlb || is("eof") || is("punc", "}")
);
return !options.strict
&& (is("eof") || is("punc", "}") || has_newline_before(S.token));
};
function is_in_generator() {
@@ -982,17 +983,17 @@ function parse($TEXT, options) {
}
};
var statement = embed_tokens(function() {
var statement = embed_tokens(function(is_export_default) {
handle_regexp();
switch (S.token.type) {
case "string":
if (S.in_directives) {
var token = peek();
if (S.token.raw.indexOf("\\") == -1
&& (token.nlb
|| is_token(token, "eof")
|| is_token(token, "punc", ";")
|| is_token(token, "punc", "}"))) {
&& (is_token(token, "punc", ";")
|| is_token(token, "punc", "}")
|| has_newline_before(token)
|| is_token(token, "eof"))) {
S.input.add_directive(S.token.value);
} else {
S.in_directives = false;
@@ -1011,7 +1012,7 @@ function parse($TEXT, options) {
if (S.token.value == "async" && is_token(peek(), "keyword", "function")) {
next();
next();
return function_(AST_Defun, false, true);
return function_(AST_Defun, false, true, is_export_default);
}
if (S.token.value == "import" && !is_token(peek(), "punc", "(")) {
next();
@@ -1085,7 +1086,7 @@ function parse($TEXT, options) {
case "function":
next();
return function_(AST_Defun);
return function_(AST_Defun, false, false, is_export_default);
case "if":
next();
@@ -1115,7 +1116,7 @@ function parse($TEXT, options) {
case "throw":
next();
if (S.token.nlb)
if (has_newline_before(S.token))
croak("Illegal newline after 'throw'");
var value = expression(true);
semicolon();
@@ -1291,7 +1292,7 @@ function parse($TEXT, options) {
};
var arrow_function = function(start, argnames, is_async) {
if (S.token.nlb) {
if (has_newline_before(S.token)) {
croak("Unexpected newline before arrow (=>)");
}
@@ -1308,9 +1309,9 @@ function parse($TEXT, options) {
});
};
var function_ = function(ctor, is_generator_property, is_async) {
var function_ = function(ctor, is_generator_property, is_async, is_export_default) {
if (is_generator_property && is_async) croak("generators cannot be async");
var start = S.token
var start = S.token;
var in_statement = ctor === AST_Defun;
var is_generator = is("operator", "*");
@@ -1319,8 +1320,13 @@ function parse($TEXT, options) {
}
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
if (in_statement && !name)
unexpected();
if (in_statement && !name) {
if (is_export_default) {
ctor = AST_Function;
} else {
unexpected();
}
}
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))
unexpected(prev());
@@ -2053,8 +2059,29 @@ function parse($TEXT, options) {
}) : exprs.length == 1 ? exprs[0] : new AST_Sequence({
expressions: exprs
});
if (ex.start) {
var len = start.comments_before.length;
[].unshift.apply(ex.start.comments_before, start.comments_before);
start.comments_before = ex.start.comments_before;
start.comments_before_length = len;
if (len == 0 && start.comments_before.length > 0) {
var comment = start.comments_before[0];
if (!comment.nlb) {
comment.nlb = start.nlb;
start.nlb = false;
}
}
start.comments_after = ex.start.comments_after;
}
ex.start = start;
ex.end = S.token;
var end = prev();
if (ex.end) {
end.comments_before = ex.end.comments_before;
[].push.apply(ex.end.comments_after, end.comments_after);
end.comments_after = ex.end.comments_after;
}
ex.end = end;
if (ex instanceof AST_Call) mark_pure(ex);
return subscripts(ex, allow_calls);
case "[":
return subscripts(array_(), allow_calls);
@@ -2528,9 +2555,9 @@ function parse($TEXT, options) {
&& is_token(peek(), "punc")) {
exported_value = expression(false);
semicolon();
} else if ((node = statement()) instanceof AST_Definitions && is_default) {
} else if ((node = statement(is_default)) instanceof AST_Definitions && is_default) {
unexpected(node.start);
} else if (node instanceof AST_Definitions || node instanceof AST_Defun || node instanceof AST_DefClass) {
} else if (node instanceof AST_Definitions || node instanceof AST_Lambda || node instanceof AST_DefClass) {
exported_definition = node;
} else if (node instanceof AST_SimpleStatement) {
exported_value = node.body;
@@ -2620,6 +2647,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", ".")) {
@@ -2644,12 +2684,14 @@ function parse($TEXT, options) {
}
if (allow_calls && is("punc", "(")) {
next();
return subscripts(new AST_Call({
var call = new AST_Call({
start : start,
expression : expr,
args : call_args(),
end : prev()
}), true);
});
mark_pure(call);
return subscripts(call, true);
}
if (is("template_head")) {
return subscripts(new AST_PrefixedTemplateString({
@@ -2701,7 +2743,7 @@ function parse($TEXT, options) {
return ex;
}
var val = expr_atom(allow_calls, allow_arrows);
while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
while (is("operator") && UNARY_POSTFIX(S.token.value) && !has_newline_before(S.token)) {
if (val instanceof AST_Arrow) unexpected();
val = make_unary(AST_UnaryPostfix, S.token, val);
val.start = start;
@@ -2731,7 +2773,8 @@ function parse($TEXT, options) {
var op = is("operator") ? S.token.value : null;
if (op == "in" && no_in) op = null;
if (op == "**" && left instanceof AST_UnaryPrefix
&& left.end === S.prev /* unary token in front not allowed, but allowed if prev is for example `)` */
/* unary token in front not allowed - parenthesis required */
&& !is_token(left.start, "punc", "(")
&& left.operator !== "--" && left.operator !== "++")
unexpected(left.start);
var prec = op != null ? PRECEDENCE[op] : null;

View File

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

View File

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

View File

@@ -4,7 +4,7 @@
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.2.2",
"version": "3.3.3",
"engines": {
"node": ">=0.8.0"
},

View File

@@ -21,6 +21,7 @@ var urls = [
"http://builds.emberjs.com/tags/v2.11.0/ember.prod.js",
"https://cdn.jsdelivr.net/lodash/4.17.4/lodash.js",
"https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.js",
"https://raw.githubusercontent.com/kangax/html-minifier/v3.5.7/dist/htmlminifier.js",
];
var results = {};
var remaining = 2 * urls.length;

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; }
@@ -706,18 +720,18 @@ collapse_vars_lvalues_drop_assign: {
function f3(x) { var a = (x -= 3); return x + a; }
function f4(x) { var a = (x -= 3); return x + a; }
function f5(x) { e1(), e2(); var c = --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 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,
@@ -1542,7 +1554,6 @@ issue_1605_2: {
issue_1631_1: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
@@ -1578,7 +1589,6 @@ issue_1631_1: {
issue_1631_2: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
@@ -1614,7 +1624,6 @@ issue_1631_2: {
issue_1631_3: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
@@ -1789,7 +1798,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) {
@@ -1847,7 +1856,7 @@ for_init: {
}
}
switch_case: {
switch_case_1: {
options = {
collapse_vars: true,
unused: true,
@@ -1866,16 +1875,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,
@@ -2028,10 +2092,8 @@ undeclared: {
}
expect: {
function f(x, y) {
var a;
a = x;
b = y;
return b + a;
return b + x;
}
}
}
@@ -3557,15 +3619,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
}
@@ -3688,12 +3749,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
}
@@ -3718,12 +3778,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
}
@@ -3763,13 +3822,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"
}
@@ -3977,3 +4035,281 @@ issue_2506: {
}
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: {
console.log(function n(o) {
return x(y(n(o)));
}(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

@@ -649,7 +649,7 @@ 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; }
@@ -677,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; }

View File

@@ -636,3 +636,441 @@ issue_2383_3: {
expect_stdout: "undefined undefined 8 undefined 7"
node_version: ">=6"
}
collapse_vars_assignment: {
options = {
collapse_vars: true,
dead_code: true,
passes: 2,
unused: true,
}
input: {
function f0(c) {
var a = 3 / c;
return a = a;
}
}
expect: {
function f0(c) {
return 3 / c;
}
}
}
collapse_vars_lvalues_drop_assign: {
options = {
collapse_vars: true,
dead_code: true,
unused: true,
}
input: {
function f0(x) { var i = ++x; return x += i; }
function f1(x) { var a = (x -= 3); return x += a; }
function f2(x) { var z = x, a = ++z; return z += a; }
}
expect: {
function f0(x) { var i = ++x; return x + i; }
function f1(x) { var a = (x -= 3); return x + a; }
function f2(x) { var z = x, a = ++z; return z + a; }
}
}
collapse_vars_misc1: {
options = {
collapse_vars: true,
dead_code: true,
unused: true,
}
input: {
function f10(x) { var a = 5, b = 3; return a += b; }
function f11(x) { var a = 5, b = 3; return a += --b; }
}
expect: {
function f10(x) { return 5 + 3; }
function f11(x) { var b = 3; return 5 + --b; }
}
}
return_assignment: {
options = {
dead_code: true,
unused: true,
}
input: {
function f1(a, b, c) {
return a = x(), b = y(), b = a && (c >>= 5);
}
function f2() {
return e = x();
}
function f3(e) {
return e = x();
}
function f4() {
var e;
return e = x();
}
function f5(a) {
try {
return a = x();
} catch (b) {
console.log(a);
}
}
function f6(a) {
try {
return a = x();
} finally {
console.log(a);
}
}
function y() {
console.log("y");
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6 ].forEach(function(f, i) {
e = null;
try {
i += 1;
console.log("result " + f(10 * i, 100 * i, 1000 * i));
} catch (x) {
console.log("caught " + x);
}
if (null !== e) console.log("e: " + e);
});
}
var x, e;
test(1);
test(-1);
}
expect: {
function f1(a, b, c) {
return a = x(), y(), a && (c >> 5);
}
function f2() {
return e = x();
}
function f3(e) {
return x();
}
function f4() {
return x();
}
function f5(a) {
try {
return x();
} catch (b) {
console.log(a);
}
}
function f6(a) {
try {
return a = x();
} finally {
console.log(a);
}
}
function y() {
console.log("y");
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6 ].forEach(function(f, i) {
e = null;
try {
i += 1;
console.log("result " + f(10 * i, 100 * i, 1000 * i));
} catch (x) {
console.log("caught " + x);
}
if (null !== e) console.log("e: " + e);
});
}
var x, e;
test(1);
test(-1);
}
expect_stdout: [
"y",
"result 31",
"result 2",
"e: 2",
"result 3",
"result 4",
"result 5",
"6",
"result 6",
"caught -1",
"caught -2",
"caught -3",
"caught -4",
"50",
"result undefined",
"60",
"caught -6",
]
}
throw_assignment: {
options = {
dead_code: true,
unused: true,
}
input: {
function f1() {
throw a = x();
}
function f2(a) {
throw a = x();
}
function f3() {
var a;
throw a = x();
}
function f4() {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f5(a) {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f6() {
var a;
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f7() {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f8(a) {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f9() {
var a;
try {
throw a = x();
} finally {
console.log(a);
}
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6, f7, f8, f9 ].forEach(function(f, i) {
a = null;
try {
f(10 * (1 + i));
} catch (x) {
console.log("caught " + x);
}
if (null !== a) console.log("a: " + a);
});
}
var x, a;
test(1);
test(-1);
}
expect: {
function f1() {
throw a = x();
}
function f2(a) {
throw x();
}
function f3() {
throw x();
}
function f4() {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f5(a) {
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f6() {
var a;
try {
throw a = x();
} catch (b) {
console.log(a);
}
}
function f7() {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f8(a) {
try {
throw a = x();
} finally {
console.log(a);
}
}
function f9() {
var a;
try {
throw a = x();
} finally {
console.log(a);
}
}
function test(inc) {
var counter = 0;
x = function() {
counter += inc;
if (inc < 0) throw counter;
return counter;
};
[ f1, f2, f3, f4, f5, f6, f7, f8, f9 ].forEach(function(f, i) {
a = null;
try {
f(10 * (1 + i));
} catch (x) {
console.log("caught " + x);
}
if (null !== a) console.log("a: " + a);
});
}
var x, a;
test(1);
test(-1);
}
expect_stdout: [
"caught 1",
"a: 1",
"caught 2",
"caught 3",
"4",
"a: 4",
"5",
"6",
"7",
"caught 7",
"a: 7",
"8",
"caught 8",
"9",
"caught 9",
"caught -1",
"caught -2",
"caught -3",
"null",
"50",
"undefined",
"null",
"caught -7",
"80",
"caught -8",
"undefined",
"caught -9",
]
}
issue_2597: {
options = {
dead_code: true,
}
input: {
function f(b) {
try {
try {
throw "foo";
} catch (e) {
return b = true;
}
} finally {
b && (a = "PASS");
}
}
var a = "FAIL";
f();
console.log(a);
}
expect: {
function f(b) {
try {
try {
throw "foo";
} catch (e) {
return b = true;
}
} finally {
b && (a = "PASS");
}
}
var a = "FAIL";
f();
console.log(a);
}
expect_stdout: "PASS"
}
issue_2666: {
options = {
dead_code: true,
}
input: {
function f(a) {
return a = {
p: function() {
return a;
}
};
}
console.log(typeof f().p());
}
expect: {
function f(a) {
return a = {
p: function() {
return a;
}
};
}
console.log(typeof f().p());
}
expect_stdout: "object"
}

View File

@@ -798,7 +798,7 @@ const_assign: {
issue_1539: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
unused: true,
@@ -845,7 +845,7 @@ vardef_value: {
assign_binding: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
unused: true,
}
@@ -1269,7 +1269,7 @@ var_catch_toplevel: {
reassign_const: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
unused: true,
@@ -1548,7 +1548,7 @@ issue_2226_1: {
issue_2226_2: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
unused: true,
@@ -1561,8 +1561,8 @@ issue_2226_2: {
}
expect: {
console.log(function(a, b) {
return a += b;
}(1, 2));
return a += 2;
}(1));
}
expect_stdout: "3"
}
@@ -1786,3 +1786,112 @@ issue_2418_5: {
(function f() {});
}
}
defun_lambda_same_name: {
options = {
toplevel: true,
unused: true,
}
input: {
function f(n) {
return n ? n * f(n - 1) : 1;
}
console.log(function f(n) {
return n ? n * f(n - 1) : 1;
}(5));
}
expect: {
console.log(function f(n) {
return n ? n * f(n - 1) : 1;
}(5));
}
expect_stdout: "120"
}
issue_2660_1: {
options = {
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 2;
function f(b) {
return b && f() || a--;
}
f(1);
console.log(a);
}
expect: {
var a = 2;
(function f(b) {
return b && f() || a--;
})(1);
console.log(a);
}
expect_stdout: "1"
}
issue_2660_2: {
options = {
collapse_vars: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = 1;
function f(b) {
b && f();
--a, a.toString();
}
f();
console.log(a);
}
expect: {
var a = 1;
(function f(b) {
b && f(),
(--a).toString();
})(),
console.log(a);
}
expect_stdout: "0"
}
issue_2665: {
options = {
evaluate: true,
inline: true,
keep_fargs: false,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
typeofs: true,
unused: true,
}
input: {
var a = 1;
function g() {
a-- && g();
}
typeof h == "function" && h();
function h() {
typeof g == "function" && g();
}
console.log(a);
}
expect: {
var a = 1;
!function g() {
a-- && g();
}();
console.log(a);
}
expect_stdout: "-1"
}

View File

@@ -262,3 +262,185 @@ trailing_comma: {
}
expect_exact: "export const a = 1;"
}
export_default_anonymous_function: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default function () {
foo();
}
}
expect_exact: "export default function(){foo()};"
}
export_default_arrow: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default () => foo();
}
expect_exact: "export default()=>foo();"
}
export_default_anonymous_generator: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default function * () {
yield foo();
}
}
expect_exact: "export default function*(){yield foo()};"
}
export_default_anonymous_async_function: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default async function() {
return await foo();
}
}
expect_exact: "export default async function(){return await foo()};"
}
export_default_async_arrow_function: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default async () => await foo();
}
expect_exact: "export default async()=>await foo();"
}
export_default_named_generator: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default function * gen() {
yield foo();
}
}
expect_exact: "export default function*gen(){yield foo()};"
}
export_default_named_async_function: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default async function bar() {
return await foo();
}
}
expect_exact: "export default async function bar(){return await foo()};"
}
export_default_anonymous_class: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default class {
constructor() {
foo();
}
};
}
expect_exact: "export default class{constructor(){foo()}};"
}
export_default_anonymous_function_not_call: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default function(){}(foo);
}
// FIXME: should be `export default function(){};foo;`
expect_exact: "export default function(){}(foo);"
}
export_default_anonymous_generator_not_call: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default function*(){}(foo);
}
// agrees with `acorn` and `babylon 7`
expect_exact: "export default function*(){};foo;"
}
export_default_anonymous_async_function_not_call: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
mangle = {
toplevel: true,
}
input: {
export default async function(){}(foo);
}
// agrees with `acorn` and `babylon 7`
expect_exact: "export default async function(){};foo;"
}

File diff suppressed because it is too large Load Diff

View File

@@ -1153,3 +1153,62 @@ array_literal_with_spread_4: {
]
node_version: ">=6"
}
object_literal_method_using_arguments: {
options = {
arrows: true,
}
input: {
console.log(({
m() {
return arguments[0];
}
}).m("PASS"));
}
expect: {
console.log(({
m() {
return arguments[0];
}
}).m("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
class_method_using_arguments: {
options = {
arrows: true,
}
input: {
console.log(new class {
m() {
return arguments[0];
}
}().m("PASS"));
}
expect: {
console.log(new class {
m() {
return arguments[0];
}
}().m("PASS"));
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_2676: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
class A {}
A.a = 42;
}
expect: {
(class {}).a = 42;
}
}

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,
}
@@ -489,10 +489,14 @@ hoist_function_with_call: {
console.log(o.p.name, o.p === o.p, o.p(o.x), o.p(o.y));
}
expect: {
var o_p = function Foo(value){
return 10 * value
var o = {
p: function Foo(value) {
return 10 * value;
},
x: 1,
y: 2
};
console.log(o_p.name, true, o_p(1), o_p(2));
console.log(o.p.name, o.p == o.p, o.p(o.x), o.p(o.y));
}
expect_stdout: "Foo true 10 20"
}

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

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -2,7 +2,7 @@
issue_1639_1: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
conditionals: true,
evaluate: true,
join_vars: 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,
@@ -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,

View File

@@ -0,0 +1,33 @@
insert_semicolon: {
beautify = {
beautify: true,
comments: "all",
}
input: {
var a
/* foo */ var b
}
expect_exact: [
"var a",
"/* foo */;",
"",
"var b;",
]
}
unary_postfix: {
beautify = {
beautify: true,
comments: "all",
}
input: {
a
/* foo */++b
}
expect_exact: [
"a",
"/* foo */;",
"",
"++b;",
]
}

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

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

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

@@ -1331,3 +1331,43 @@ issue_2513: {
"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,
@@ -476,7 +476,7 @@ issue_2265_4: {
issue_2313_1: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: "strict",
sequences: true,
@@ -522,7 +522,7 @@ issue_2313_1: {
issue_2313_2: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
pure_getters: true,
sequences: true,
@@ -735,3 +735,35 @@ issue_2313_7: {
expect_stdout: "2 1"
node_version: ">=6"
}
issue_2678: {
options = {
pure_getters: "strict",
side_effects: true,
}
input: {
var a = 1, c = "FAIL";
(function f() {
(a-- && f()).p;
return {
get p() {
c = "PASS";
}
};
})();
console.log(c);
}
expect: {
var a = 1, c = "FAIL";
(function f() {
(a-- && f()).p;
return {
get p() {
c = "PASS";
}
};
})();
console.log(c);
}
expect_stdout: "PASS"
}

View File

@@ -1355,10 +1355,9 @@ defun_inline_1: {
function f() {
return function(b) {
return b;
}(2) + h();
function h() {
}(2) + function h() {
return h();
}
}();
}
}
}
@@ -1382,12 +1381,11 @@ defun_inline_2: {
}
expect: {
function f() {
function h() {
return h();
}
return function(b) {
return b;
}(2) + h();
}(2) + function h() {
return h();
}();
}
}
}
@@ -1396,7 +1394,7 @@ defun_inline_3: {
options = {
evaluate: true,
inline: true,
passes: 2,
passes: 3,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
@@ -2250,23 +2248,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,
@@ -3217,6 +3214,7 @@ obj_var_2: {
obj_arg_1: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
passes: 2,
@@ -3248,9 +3246,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,
@@ -3671,6 +3670,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,
@@ -4907,7 +4937,7 @@ issue_2455: {
}
}
issue_2560_1: {
escape_conditional: {
options = {
reduce_funcs: true,
reduce_vars: true,
@@ -4946,7 +4976,7 @@ issue_2560_1: {
expect_stdout: "PASS"
}
issue_2560_2: {
escape_sequence: {
options = {
reduce_funcs: true,
reduce_vars: true,
@@ -4984,7 +5014,7 @@ issue_2560_2: {
expect_stdout: "PASS"
}
issue_2560_3: {
escape_throw: {
options = {
reduce_funcs: true,
reduce_vars: true,
@@ -5029,7 +5059,7 @@ issue_2560_3: {
expect_stdout: "PASS"
}
issue_2560_4: {
escape_local_conditional: {
options = {
reduce_funcs: true,
reduce_vars: true,
@@ -5066,7 +5096,7 @@ issue_2560_4: {
expect_stdout: "PASS"
}
issue_2560_5: {
escape_local_sequence: {
options = {
reduce_funcs: true,
reduce_vars: true,
@@ -5103,7 +5133,7 @@ issue_2560_5: {
expect_stdout: "PASS"
}
issue_2560_6: {
escape_local_throw: {
options = {
reduce_funcs: true,
reduce_vars: true,
@@ -5276,3 +5306,182 @@ escape_expansion: {
expect_stdout: "PASS"
node_version: ">=6"
}
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"
}
issue_2669: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
let foo;
console.log(([ foo ] = [ "PASS" ]) && foo);
}
expect: {
let foo;
console.log(([ foo ] = [ "PASS" ]) && foo);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_2670: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
const obj = {};
obj.prop = "PASS";
const {prop: value} = obj;
console.log(value);
}
expect: {
const obj = {};
obj.prop = "PASS";
const {prop: value} = obj;
console.log(value);
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -17,7 +17,6 @@ return_undefined: {
keep_fnames : false,
hoist_vars : true,
join_vars : true,
cascade : true,
negate_iife : true
};
input: {

View File

@@ -317,7 +317,7 @@ unsafe_undefined: {
issue_1685: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -341,7 +341,7 @@ issue_1685: {
func_def_1: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -361,7 +361,7 @@ func_def_1: {
func_def_2: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -379,7 +379,7 @@ func_def_2: {
func_def_3: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -401,7 +401,7 @@ func_def_3: {
func_def_4: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -427,7 +427,7 @@ func_def_4: {
func_def_5: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -634,7 +634,7 @@ side_effects: {
side_effects_cascade_1: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
sequences: true,
side_effects: true,
@@ -655,7 +655,7 @@ side_effects_cascade_1: {
side_effects_cascade_2: {
options = {
cascade: true,
collapse_vars: true,
side_effects: true,
}
input: {
@@ -677,7 +677,7 @@ side_effects_cascade_2: {
side_effects_cascade_3: {
options = {
cascade: true,
collapse_vars: true,
conditionals: true,
side_effects: true,
}
@@ -692,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,
@@ -721,7 +721,7 @@ issue_27: {
reassign_const: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
}
@@ -746,7 +746,7 @@ reassign_const: {
issue_2062: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
conditionals: true,
side_effects: true,
}
@@ -765,7 +765,7 @@ issue_2062: {
issue_2313: {
options = {
cascade: true,
collapse_vars: true,
sequences: true,
side_effects: true,
}
@@ -803,3 +803,20 @@ issue_2313: {
}
expect_stdout: "2 1"
}
cascade_assignment_in_return: {
options = {
collapse_vars: true,
unused: true,
}
input: {
function f(a, b) {
return a = x(), b(a);
}
}
expect: {
function f(a, b) {
return b(x());
}
}
}

View File

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

View File

@@ -14,7 +14,7 @@ describe("comment filters", function() {
it("Should be able to filter commments with the 'some' option", function() {
var ast = UglifyJS.parse("// foo\n/*@preserve*/\n// bar\n/*@license*/\n//@license with the wrong comment type\n/*@cc_on something*/");
assert.strictEqual(ast.print_to_string({comments: "some"}), "/*@preserve*/\n/*@license*/\n/*@cc_on something*/\n");
assert.strictEqual(ast.print_to_string({comments: "some"}), "/*@preserve*/\n/*@license*/\n/*@cc_on something*/");
});
it("Should be able to filter comments by passing a function", function() {
@@ -55,12 +55,12 @@ describe("comment filters", function() {
return true;
};
assert.strictEqual(ast.print_to_string({comments: f}), "#!Random comment\n//test1\n/*test2*/\n");
assert.strictEqual(ast.print_to_string({comments: f}), "#!Random comment\n//test1\n/*test2*/");
});
it("Should never be able to filter comment5 when using 'some' as filter", function() {
var ast = UglifyJS.parse("#!foo\n//foo\n/*@preserve*/\n/* please hide me */");
assert.strictEqual(ast.print_to_string({comments: "some"}), "#!foo\n/*@preserve*/\n");
assert.strictEqual(ast.print_to_string({comments: "some"}), "#!foo\n/*@preserve*/");
});
it("Should have no problem on multiple calls", function() {

View File

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

View File

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

View File

@@ -43,7 +43,7 @@ describe("minify", function() {
compressed += result.code;
});
assert.strictEqual(JSON.stringify(cache).slice(0, 20), '{"cname":5,"props":{');
assert.strictEqual(compressed, 'function n(n){return 3*n}function r(n){return n/2}function c(o){l("Foo:",2*o)}var l=console.log.bind(console);var f=n(3),i=r(12);l("qux",f,i),c(11);');
assert.strictEqual(compressed, 'function n(n){return 3*n}function r(n){return n/2}var c=console.log.bind(console);function l(o){c("Foo:",2*o)}var f=n(3),i=r(12);c("qux",f,i),l(11);');
assert.strictEqual(run_code(compressed), run_code(original));
});
@@ -69,7 +69,7 @@ describe("minify", function() {
compressed += result.code;
});
assert.strictEqual(JSON.stringify(cache).slice(0, 28), '{"vars":{"cname":5,"props":{');
assert.strictEqual(compressed, 'function n(n){return 3*n}function r(n){return n/2}function c(o){l("Foo:",2*o)}var l=console.log.bind(console);var f=n(3),i=r(12);l("qux",f,i),c(11);');
assert.strictEqual(compressed, 'function n(n){return 3*n}function r(n){return n/2}var c=console.log.bind(console);function l(o){c("Foo:",2*o)}var f=n(3),i=r(12);c("qux",f,i),l(11);');
assert.strictEqual(run_code(compressed), run_code(original));
});
@@ -248,7 +248,7 @@ describe("minify", function() {
var code = result.code;
assert.strictEqual(code, "// comment1 comment2\nbar();");
});
it("should not drop #__PURE__ hint if function is retained", function() {
it("should drop #__PURE__ hint if function is retained", function() {
var result = Uglify.minify("var a = /*#__PURE__*/(function(){ foo(); })();", {
output: {
comments: "all",
@@ -256,7 +256,7 @@ describe("minify", function() {
}
});
var code = result.code;
assert.strictEqual(code, "var a=/*#__PURE__*/function(){foo()}();");
assert.strictEqual(code, "var a=/* */function(){foo()}();");
})
});

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,23 @@ 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),
'console.log(null, a, b, c);' // preceding `null` makes for a cleaner output (empty string still shows up etc)
: createFunctions(rng(MAX_GENERATED_TOPLEVELS_PER_RUN) + 1, MAX_GENERATION_RECURSION_DEPTH, DEFUN_OK, CANNOT_THROW, 0),
// preceding `null` makes for a cleaner output (empty string still shows up etc)
'console.log(null, a, b, c, Infinity, NaN, undefined);'
].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 +364,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 +382,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 +392,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 +546,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
@@ -631,6 +636,8 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
case p++:
case p++:
return getVarName();
case p++:
return getVarName() + createAssignment() + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
case p++:
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
case p++:
@@ -648,7 +655,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 +694,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 +761,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;