From 3dd495ecdd231a6b245ab002f61805b21114924b Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Thu, 7 Dec 2017 01:01:52 +0800 Subject: [PATCH 1/7] improve `if_return` (#2558) `return void x()` => `x()` --- lib/compress.js | 30 +++++++++++++++++++++++------- test/compress/return_undefined.js | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 914fdd06..3f0414e2 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1211,10 +1211,19 @@ merge(Compressor.prototype, { var stat = statements[i]; var next = statements[i + 1]; - if (in_lambda && stat instanceof AST_Return && !stat.value && !next) { - CHANGED = true; - statements.length--; - continue; + if (in_lambda && !next && stat instanceof AST_Return) { + if (!stat.value) { + CHANGED = true; + statements.length--; + continue; + } + if (stat.value instanceof AST_UnaryPrefix && stat.value.operator == "void") { + CHANGED = true; + statements[i] = make_node(AST_SimpleStatement, stat, { + body: stat.value.expression + }); + continue; + } } if (stat instanceof AST_If) { @@ -1301,9 +1310,16 @@ merge(Compressor.prototype, { && prev instanceof AST_If && prev.body instanceof AST_Return && i + 2 == statements.length && next instanceof AST_SimpleStatement) { CHANGED = true; - statements.push(make_node(AST_Return, next, { - value: null - }).transform(compressor)); + stat = stat.clone(); + stat.alternative = make_node(AST_BlockStatement, next, { + body: [ + next, + make_node(AST_Return, next, { + value: null + }) + ] + }); + statements.splice(i, 2, stat.transform(compressor)); continue; } } diff --git a/test/compress/return_undefined.js b/test/compress/return_undefined.js index 9662aa51..4d2b4257 100644 --- a/test/compress/return_undefined.js +++ b/test/compress/return_undefined.js @@ -122,3 +122,25 @@ return_undefined: { } } } + +return_void: { + options = { + if_return: true, + inline: true, + reduce_vars: true, + unused: true, + } + input: { + function f() { + function g() { + h(); + } + return g(); + } + } + expect: { + function f() { + h(); + } + } +} From d21cb84696f47f5cba25c88527d5575b7954191a Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Thu, 7 Dec 2017 01:22:08 +0800 Subject: [PATCH 2/7] eliminate noop calls more aggressively (#2559) --- lib/compress.js | 25 +++++++++++++------------ test/compress/functions.js | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 3f0414e2..4195ab24 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -3460,11 +3460,11 @@ merge(Compressor.prototype, { OPT(AST_Call, function(self, compressor){ var exp = self.expression; var fn = exp; + if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) { + fn = fn.fixed_value(); + } if (compressor.option("unused") - && (fn instanceof AST_Function - || compressor.option("reduce_vars") - && fn instanceof AST_SymbolRef - && (fn = fn.fixed_value()) instanceof AST_Function) + && fn instanceof AST_Function && !fn.uses_arguments && !fn.uses_eval) { var pos = 0, last = 0; @@ -3683,14 +3683,15 @@ merge(Compressor.prototype, { return make_sequence(self, args).optimize(compressor); } } - if (exp instanceof AST_Function) { + if (fn instanceof AST_Function) { if (compressor.option("inline") - && !exp.name - && !exp.uses_arguments - && !exp.uses_eval - && exp.body.length == 1 - && !exp.contains_this() - && all(exp.argnames, function(arg) { + && exp === fn + && !fn.name + && !fn.uses_arguments + && !fn.uses_eval + && fn.body.length == 1 + && !fn.contains_this() + && all(fn.argnames, function(arg) { return arg.__unused; }) && !self.has_pure_annotation(compressor)) { @@ -3708,7 +3709,7 @@ merge(Compressor.prototype, { return make_sequence(self, args).optimize(compressor); } } - if (compressor.option("side_effects") && all(exp.body, is_empty)) { + if (compressor.option("side_effects") && all(fn.body, is_empty)) { var args = self.args.concat(make_node(AST_Undefined, self)); return make_sequence(self, args).optimize(compressor); } diff --git a/test/compress/functions.js b/test/compress/functions.js index 7a336bb8..15727fc2 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -652,3 +652,23 @@ issue_2531_3: { } expect_stdout: "Greeting: Hello" } + +empty_body: { + options = { + reduce_vars: true, + side_effects: true, + } + input: { + function f() { + function noop() {} + noop(); + return noop; + } + } + expect: { + function f() { + function noop() {} + return noop; + } + } +} From 3e34f62a1c48ab45db34cfb08d8dd2118c5780f0 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Fri, 8 Dec 2017 01:15:31 +0800 Subject: [PATCH 3/7] account for side-effects in conditional call inversion (#2562) fixes #2560 --- lib/compress.js | 31 ++++++-- test/compress/conditionals.js | 128 ++++++++++++++++++++++++++++------ 2 files changed, 132 insertions(+), 27 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 4195ab24..e59dce63 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -4652,18 +4652,22 @@ merge(Compressor.prototype, { }); } // x ? y(a) : y(b) --> y(x ? a : b) + var arg_index; if (consequent instanceof AST_Call && alternative.TYPE === consequent.TYPE - && consequent.args.length == 1 - && alternative.args.length == 1 + && consequent.args.length > 0 + && consequent.args.length == alternative.args.length && consequent.expression.equivalent_to(alternative.expression) - && !consequent.expression.has_side_effects(compressor)) { - consequent.args[0] = make_node(AST_Conditional, self, { + && !self.condition.has_side_effects(compressor) + && !consequent.expression.has_side_effects(compressor) + && typeof (arg_index = single_arg_diff()) == "number") { + var node = consequent.clone(); + node.args[arg_index] = make_node(AST_Conditional, self, { condition: self.condition, - consequent: consequent.args[0], - alternative: alternative.args[0] + consequent: consequent.args[arg_index], + alternative: alternative.args[arg_index] }); - return consequent; + return node; } // x?y?z:a:a --> x&&y?z:a if (consequent instanceof AST_Conditional @@ -4760,6 +4764,19 @@ merge(Compressor.prototype, { && node.expression instanceof AST_Constant && node.expression.getValue()); } + + function single_arg_diff() { + var a = consequent.args; + var b = alternative.args; + for (var i = 0, len = a.length; i < len; i++) { + if (!a[i].equivalent_to(b[i])) { + for (var j = i + 1; j < len; j++) { + if (!a[j].equivalent_to(b[j])) return; + } + return i; + } + } + } }); OPT(AST_Boolean, function(self, compressor){ diff --git a/test/compress/conditionals.js b/test/compress/conditionals.js index 89c05263..143ece4a 100644 --- a/test/compress/conditionals.js +++ b/test/compress/conditionals.js @@ -166,22 +166,24 @@ cond_1: { conditionals: true }; input: { - var do_something; // if undeclared it's assumed to have side-effects - if (some_condition()) { - do_something(x); - } else { - do_something(y); - } - if (some_condition()) { - side_effects(x); - } else { - side_effects(y); + function foo(do_something, some_condition) { + if (some_condition) { + do_something(x); + } else { + do_something(y); + } + if (some_condition) { + side_effects(x); + } else { + side_effects(y); + } } } expect: { - var do_something; - do_something(some_condition() ? x : y); - some_condition() ? side_effects(x) : side_effects(y); + function foo(do_something, some_condition) { + do_something(some_condition ? x : y); + some_condition ? side_effects(x) : side_effects(y); + } } } @@ -190,16 +192,18 @@ cond_2: { conditionals: true }; input: { - var x, FooBar; - if (some_condition()) { - x = new FooBar(1); - } else { - x = new FooBar(2); + function foo(x, FooBar, some_condition) { + if (some_condition) { + x = new FooBar(1); + } else { + x = new FooBar(2); + } } } expect: { - var x, FooBar; - x = new FooBar(some_condition() ? 1 : 2); + function foo(x, FooBar, some_condition) { + x = new FooBar(some_condition ? 1 : 2); + } } } @@ -605,6 +609,42 @@ cond_8c: { } } +cond_9: { + options = { + conditionals: true, + } + input: { + function f(x, y) { + g() ? x(1) : x(2); + x ? (y || x)() : (y || x)(); + x ? y(a, b) : y(d, b, c); + x ? y(a, b, c) : y(a, b, c); + x ? y(a, b, c) : y(a, b, f); + x ? y(a, b, c) : y(a, e, c); + x ? y(a, b, c) : y(a, e, f); + x ? y(a, b, c) : y(d, b, c); + x ? y(a, b, c) : y(d, b, f); + x ? y(a, b, c) : y(d, e, c); + x ? y(a, b, c) : y(d, e, f); + } + } + expect: { + function f(x, y) { + g() ? x(1) : x(2); + x, (y || x)(); + x ? y(a, b) : y(d, b, c); + x, y(a, b, c); + y(a, b, x ? c : f); + y(a, x ? b : e, c); + x ? y(a, b, c) : y(a, e, f); + y(x ? a : d, b, c); + x ? y(a, b, c) : y(d, b, f); + x ? y(a, b, c) : y(d, e, c); + x ? y(a, b, c) : y(d, e, f); + } + } +} + ternary_boolean_consequent: { options = { collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true, @@ -1115,3 +1155,51 @@ issue_2535_2: { "false", ] } + +issue_2560: { + options = { + conditionals: true, + inline: true, + reduce_funcs: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + function log(x) { + console.log(x); + } + function foo() { + return log; + } + function bar() { + if (x !== (x = foo())) { + x(1); + } else { + x(2); + } + } + var x = function() { + console.log("init"); + }; + bar(); + bar(); + } + expect: { + function log(x) { + console.log(x); + } + function bar() { + x !== (x = log) ? x(1) : x(2); + } + var x = function() { + console.log("init"); + }; + bar(); + bar(); + } + expect_stdout: [ + "1", + "2", + ] +} From e20935c3f2a03779b15ad225ae4616a1d80c2ec5 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Fri, 8 Dec 2017 01:50:38 +0800 Subject: [PATCH 4/7] fix escape analysis for `AST_Conditional` & `AST_Sequence` (#2563) fixes #2560 --- lib/compress.js | 4 +- test/compress/reduce_vars.js | 77 ++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/lib/compress.js b/lib/compress.js index e59dce63..c80192dc 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -656,7 +656,9 @@ merge(Compressor.prototype, { || parent instanceof AST_VarDef && node === parent.value) { d.escaped = true; return; - } else if (parent instanceof AST_Array) { + } else if (parent instanceof AST_Array + || parent instanceof AST_Conditional && node !== parent.condition + || parent instanceof AST_Sequence && node === parent.tail_node()) { mark_escaped(d, scope, parent, parent, level + 1); } else if (parent instanceof AST_ObjectKeyVal && node === parent.value) { var obj = tw.parent(level + 1); diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 4a098f78..9a66d1cb 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -4544,3 +4544,80 @@ issue_2455: { } } } + +issue_2560_1: { + options = { + reduce_funcs: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + function main() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("FAIL"); + else + console.log("PASS"); + } + function baz(s) { + return s ? foo : bar; + } + function foo() {} + function bar() {} + main(); + } + expect: { + function baz(s) { + return s ? foo : bar; + } + function foo() {} + function bar() {} + (function() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("FAIL"); + else + console.log("PASS"); + })(); + } + expect_stdout: "PASS" +} + +issue_2560_2: { + options = { + reduce_funcs: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + function main() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("FAIL"); + else + console.log("PASS"); + } + function baz() { + return foo, bar; + } + function foo() {} + function bar() {} + main(); + } + expect: { + function baz() { + return function() {}, bar; + } + function bar() {} + (function() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("FAIL"); + else + console.log("PASS"); + })(); + } + expect_stdout: "PASS" +} From 74a2f53683e2b8788eadc10762583491e3dbc7ea Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Fri, 8 Dec 2017 02:54:37 +0800 Subject: [PATCH 5/7] fix escape analysis for `AST_Throw` (#2564) --- lib/compress.js | 2 +- test/compress/reduce_vars.js | 163 +++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) diff --git a/lib/compress.js b/lib/compress.js index c80192dc..7f1b46e3 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -652,7 +652,7 @@ merge(Compressor.prototype, { } if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right || parent instanceof AST_Call && node !== parent.expression - || parent instanceof AST_Return && node === parent.value && node.scope !== d.scope + || parent instanceof AST_Exit && node === parent.value && node.scope !== d.scope || parent instanceof AST_VarDef && node === parent.value) { d.escaped = true; return; diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 9a66d1cb..df2eb712 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -4621,3 +4621,166 @@ issue_2560_2: { } expect_stdout: "PASS" } + +issue_2560_3: { + options = { + reduce_funcs: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + function main() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("FAIL"); + else + console.log("PASS"); + } + function baz() { + try { + throw foo; + } catch (bar) { + return bar; + } + } + function foo() {} + main(); + } + expect: { + function baz() { + try { + throw foo; + } catch (bar) { + return bar; + } + } + function foo() {} + (function() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("FAIL"); + else + console.log("PASS"); + })(); + } + expect_stdout: "PASS" +} + +issue_2560_4: { + options = { + reduce_funcs: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + function main() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("PASS"); + else + console.log("FAIL"); + } + function baz(s) { + function foo() {} + function bar() {} + return s ? foo : bar; + } + main(); + } + expect: { + function baz(s) { + return s ? function() {} : function() {}; + } + (function() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("PASS"); + else + console.log("FAIL"); + })(); + } + expect_stdout: "PASS" +} + +issue_2560_5: { + options = { + reduce_funcs: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + function main() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("PASS"); + else + console.log("FAIL"); + } + function baz() { + function foo() {} + function bar() {} + return foo, bar; + } + main(); + } + expect: { + function baz() { + return function() {}, function() {}; + } + (function() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("PASS"); + else + console.log("FAIL"); + })(); + } + expect_stdout: "PASS" +} + +issue_2560_6: { + options = { + reduce_funcs: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + function main() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("PASS"); + else + console.log("FAIL"); + } + function baz() { + function foo() {} + try { + throw foo; + } catch (bar) { + return bar; + } + } + main(); + } + expect: { + function baz() { + try { + throw function() {}; + } catch (bar) { + return bar; + } + } + (function() { + var thing = baz(); + if (thing !== (thing = baz())) + console.log("PASS"); + else + console.log("FAIL"); + })(); + } + expect_stdout: "PASS" +} From 0aff037a3574dfcf856484f4db67dd1b0d66c1c8 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sat, 9 Dec 2017 06:19:29 +0800 Subject: [PATCH 6/7] improve `unused` on assign-only symbols (#2568) --- lib/compress.js | 38 +++++---- test/compress/drop-unused.js | 150 +++++++++++++++++++++-------------- 2 files changed, 113 insertions(+), 75 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 7f1b46e3..ce0fbdd5 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -2487,6 +2487,20 @@ merge(Compressor.prototype, { // pass 3: we should drop declarations not in_use var tt = new TreeTransformer( function before(node, descend, in_list) { + var parent = tt.parent(); + if (drop_vars) { + var sym = assign_as_unused(node); + if (sym instanceof AST_SymbolRef + && !(sym.definition().id in in_use_ids)) { + if (node instanceof AST_Assign) { + return maintain_this_binding(parent, node, node.right.transform(tt)); + } + return make_node(AST_Number, node, { + value: 0 + }); + } + } + if (scope !== self) return; if (node instanceof AST_Function && node.name && !compressor.option("keep_fnames")) { @@ -2520,9 +2534,7 @@ merge(Compressor.prototype, { def.eliminated++; return make_node(AST_EmptyStatement, node); } - return node; } - var parent = tt.parent(); if (node instanceof AST_Definitions && !(parent instanceof AST_ForIn && parent.init === node)) { // place uninitialized names at the start var body = [], head = [], tail = []; @@ -2602,18 +2614,6 @@ merge(Compressor.prototype, { }); } } - if (drop_vars) { - var sym = assign_as_unused(node); - if (sym instanceof AST_SymbolRef - && !(sym.definition().id in in_use_ids)) { - if (node instanceof AST_Assign) { - return maintain_this_binding(parent, node, node.right.transform(tt)); - } - return make_node(AST_Number, node, { - value: 0 - }); - } - } // certain combination of unused name + side effect leads to: // https://github.com/mishoo/UglifyJS2/issues/44 // https://github.com/mishoo/UglifyJS2/issues/1830 @@ -2645,8 +2645,13 @@ merge(Compressor.prototype, { } return node; } - if (node instanceof AST_Scope && node !== self) + if (node instanceof AST_Scope) { + var save_scope = scope; + scope = node; + descend(node, this); + scope = save_scope; return node; + } function template(sym) { return { @@ -2662,8 +2667,7 @@ merge(Compressor.prototype, { function scan_ref_scoped(node, descend) { var sym; - if (scope === self - && (sym = assign_as_unused(node)) instanceof AST_SymbolRef + if ((sym = assign_as_unused(node)) instanceof AST_SymbolRef && self.variables.get(sym.name) === sym.definition()) { if (node instanceof AST_Assign) node.right.walk(tw); return true; diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js index 189a0008..f9ef7877 100644 --- a/test/compress/drop-unused.js +++ b/test/compress/drop-unused.js @@ -179,7 +179,9 @@ keep_fnames: { } drop_assign: { - options = { unused: true }; + options = { + unused: true, + } input: { function f1() { var a; @@ -200,7 +202,7 @@ drop_assign: { var a; return function() { a = 1; - } + }; } } expect: { @@ -217,16 +219,17 @@ drop_assign: { return 1; } function f5() { - var a; return function() { - a = 1; - } + 1; + }; } } } keep_assign: { - options = { unused: "keep_assign" }; + options = { + unused: "keep_assign", + } input: { function f1() { var a; @@ -247,7 +250,7 @@ keep_assign: { var a; return function() { a = 1; - } + }; } } expect: { @@ -270,19 +273,22 @@ keep_assign: { var a; return function() { a = 1; - } + }; } } } drop_toplevel_funcs: { - options = { toplevel: "funcs", unused: true }; + options = { + toplevel: "funcs", + unused: true, + } input: { var a, b = 1, c = g; function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -298,13 +304,16 @@ drop_toplevel_funcs: { } drop_toplevel_vars: { - options = { toplevel: "vars", unused: true }; + options = { + toplevel: "vars", + unused: true, + } input: { var a, b = 1, c = g; function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -312,11 +321,10 @@ drop_toplevel_vars: { console.log(b = 3); } expect: { - var c = g; function f(d) { return function() { - c = 2; - } + 2; + }; } 2; function g() {} @@ -326,13 +334,17 @@ drop_toplevel_vars: { } drop_toplevel_vars_fargs: { - options = { keep_fargs: false, toplevel: "vars", unused: true }; + options = { + keep_fargs: false, + toplevel: "vars", + unused: true, + } input: { var a, b = 1, c = g; function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -340,11 +352,10 @@ drop_toplevel_vars_fargs: { console.log(b = 3); } expect: { - var c = g; function f() { return function() { - c = 2; - } + 2; + }; } 2; function g() {} @@ -354,13 +365,16 @@ drop_toplevel_vars_fargs: { } drop_toplevel_all: { - options = { toplevel: true, unused: true }; + options = { + toplevel: true, + unused: true + } input: { var a, b = 1, c = g; function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -374,13 +388,16 @@ drop_toplevel_all: { } drop_toplevel_retain: { - options = { top_retain: "f,a,o", unused: true }; + options = { + top_retain: "f,a,o", + unused: true, + } input: { var a, b = 1, c = g; function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -388,26 +405,28 @@ drop_toplevel_retain: { console.log(b = 3); } expect: { - var a, c = g; + var a; function f(d) { return function() { - c = 2; - } + 2; + }; } a = 2; - function g() {} console.log(3); } } drop_toplevel_retain_array: { - options = { top_retain: [ "f", "a", "o" ], unused: true }; + options = { + top_retain: [ "f", "a", "o" ], + unused: true, + } input: { var a, b = 1, c = g; function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -415,26 +434,28 @@ drop_toplevel_retain_array: { console.log(b = 3); } expect: { - var a, c = g; + var a; function f(d) { return function() { - c = 2; - } + 2; + }; } a = 2; - function g() {} console.log(3); } } drop_toplevel_retain_regex: { - options = { top_retain: /^[fao]$/, unused: true }; + options = { + top_retain: /^[fao]$/, + unused: true, + } input: { var a, b = 1, c = g; function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -442,26 +463,29 @@ drop_toplevel_retain_regex: { console.log(b = 3); } expect: { - var a, c = g; + var a; function f(d) { return function() { - c = 2; - } + 2; + }; } a = 2; - function g() {} console.log(3); } } drop_toplevel_all_retain: { - options = { toplevel: true, top_retain: "f,a,o", unused: true }; + options = { + toplevel: true, + top_retain: "f,a,o", + unused: true, + } input: { var a, b = 1, c = g; function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -469,26 +493,29 @@ drop_toplevel_all_retain: { console.log(b = 3); } expect: { - var a, c = g; + var a; function f(d) { return function() { - c = 2; - } + 2; + }; } a = 2; - function g() {} console.log(3); } } drop_toplevel_funcs_retain: { - options = { toplevel: "funcs", top_retain: "f,a,o", unused: true }; + options = { + toplevel: "funcs", + top_retain: "f,a,o", + unused: true, + } input: { var a, b = 1, c = g; function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -500,7 +527,7 @@ drop_toplevel_funcs_retain: { function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -509,13 +536,17 @@ drop_toplevel_funcs_retain: { } drop_toplevel_vars_retain: { - options = { toplevel: "vars", top_retain: "f,a,o", unused: true }; + options = { + toplevel: "vars", + top_retain: "f,a,o", + unused: true, + } input: { var a, b = 1, c = g; function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -523,11 +554,11 @@ drop_toplevel_vars_retain: { console.log(b = 3); } expect: { - var a, c = g; + var a; function f(d) { return function() { - c = 2; - } + 2; + }; } a = 2; function g() {} @@ -537,13 +568,16 @@ drop_toplevel_vars_retain: { } drop_toplevel_keep_assign: { - options = { toplevel: true, unused: "keep_assign" }; + options = { + toplevel: true, + unused: "keep_assign", + } input: { var a, b = 1, c = g; function f(d) { return function() { c = 2; - } + }; } a = 2; function g() {} @@ -753,11 +787,11 @@ issue_1583: { expect: { function m(t) { (function(e) { - t = function() { + (function() { return (function(a) { return function(a) {}; })(); - }(); + })(); })(); } } From 24418274084745a224a2715219a4c6029cbfee8f Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sun, 10 Dec 2017 13:46:17 +0800 Subject: [PATCH 7/7] v3.2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index adfc10a4..e3f21d63 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "homepage": "http://lisperator.net/uglifyjs", "author": "Mihai Bazon (http://lisperator.net/)", "license": "BSD-2-Clause", - "version": "3.2.1", + "version": "3.2.2", "engines": { "node": ">=0.8.0" },