implement keep_fargs for mangle (#5307)

closes #4657
This commit is contained in:
Alex Lam S.L
2022-01-20 21:13:26 +00:00
committed by GitHub
parent efed55f42d
commit e24b255350
20 changed files with 507 additions and 267 deletions

View File

@@ -115,6 +115,7 @@ a double dash to prevent input files being used as option arguments:
Equivalent to setting `ie: true` in `minify()` Equivalent to setting `ie: true` in `minify()`
for `compress`, `mangle` and `output` options. for `compress`, `mangle` and `output` options.
By default UglifyJS will not try to be IE-proof. By default UglifyJS will not try to be IE-proof.
--keep-fargs Do not mangle/drop function arguments.
--keep-fnames Do not mangle/drop function names. Useful for --keep-fnames Do not mangle/drop function names. Useful for
code relying on Function.prototype.name. code relying on Function.prototype.name.
--name-cache <file> File to hold mangled name mappings. --name-cache <file> File to hold mangled name mappings.
@@ -504,6 +505,9 @@ if (result.error) throw result.error;
- `ie` (default: `false`) — enable workarounds for Internet Explorer bugs. - `ie` (default: `false`) — enable workarounds for Internet Explorer bugs.
- `keep_fargs` (default: `false`) — pass `true` to prevent discarding or mangling
of function arguments.
- `keep_fnames` (default: `false`) — pass `true` to prevent discarding or mangling - `keep_fnames` (default: `false`) — pass `true` to prevent discarding or mangling
of function names. Useful for code relying on `Function.prototype.name`. of function names. Useful for code relying on `Function.prototype.name`.
@@ -868,6 +872,9 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
- `debug` (default: `false`) — Mangle names with the original name still present. - `debug` (default: `false`) — Mangle names with the original name still present.
Pass an empty string `""` to enable, or a non-empty string to set the debug suffix. Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
- `keep_fargs` (default: `false`) — Use `true` to prevent mangling of function
arguments.
- `keep_quoted` (default: `false`) — Only mangle unquoted property names. - `keep_quoted` (default: `false`) — Only mangle unquoted property names.
- `regex` (default: `null`) — Pass a RegExp literal to only mangle property - `regex` (default: `null`) — Pass a RegExp literal to only mangle property

View File

@@ -72,6 +72,7 @@ function process_option(name, no_value) {
} else { } else {
if (padding.length < name.length) padding = Array(name.length + 1).join(" "); if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
toplevels.push([ { toplevels.push([ {
keep_fargs: "keep-fargs",
keep_fnames: "keep-fnames", keep_fnames: "keep-fnames",
nameCache: "name-cache", nameCache: "name-cache",
}[name] || name, option ]); }[name] || name, option ]);
@@ -104,6 +105,7 @@ function process_option(name, no_value) {
" -d, --define <expr>[=value] Global definitions.", " -d, --define <expr>[=value] Global definitions.",
" -e, --enclose [arg[,...][:value[,...]]] Embed everything in a big function, with configurable argument(s) & value(s).", " -e, --enclose [arg[,...][:value[,...]]] Embed everything in a big function, with configurable argument(s) & value(s).",
" --ie Support non-standard Internet Explorer.", " --ie Support non-standard Internet Explorer.",
" --keep-fargs Do not mangle/drop function arguments.",
" --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.", " --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.",
" --name-cache <file> File to hold mangled name mappings.", " --name-cache <file> File to hold mangled name mappings.",
" --rename Force symbol expansion.", " --rename Force symbol expansion.",
@@ -160,6 +162,9 @@ function process_option(name, no_value) {
case "no-annotations": case "no-annotations":
options.annotations = false; options.annotations = false;
break; break;
case "keep-fargs":
options.keep_fargs = true;
break;
case "keep-fnames": case "keep-fnames":
options.keep_fnames = true; options.keep_fnames = true;
break; break;

View File

@@ -443,10 +443,6 @@ Compressor.prototype.compress = function(node) {
return def.name == "arguments" && def.scope.uses_arguments; return def.name == "arguments" && def.scope.uses_arguments;
} }
function is_funarg(def) {
return def.orig[0] instanceof AST_SymbolFunarg || def.orig[1] instanceof AST_SymbolFunarg;
}
function cross_scope(def, sym) { function cross_scope(def, sym) {
do { do {
if (def === sym) return false; if (def === sym) return false;
@@ -2053,7 +2049,7 @@ Compressor.prototype.compress = function(node) {
} }
return make_node(AST_Assign, candidate, { return make_node(AST_Assign, candidate, {
operator: "=", operator: "=",
left: make_node(AST_SymbolRef, candidate.name, candidate.name), left: node,
right: rvalue, right: rvalue,
}); });
} }
@@ -6229,51 +6225,46 @@ Compressor.prototype.compress = function(node) {
var changed = false; var changed = false;
var merged = Object.create(null); var merged = Object.create(null);
while (first.length && last.length) { while (first.length && last.length) {
var head = first.pop(); var tail = last.shift();
var def = head.definition; if (!tail) continue;
if (!(def.id in prev)) continue; var def = tail.definition;
if (!references[def.id]) continue; var tail_refs = references[def.id];
var head_refs = { if (!tail_refs) continue;
start: references[def.id].start, tail_refs = { end: tail_refs.end };
};
while (def.id in merged) def = merged[def.id]; while (def.id in merged) def = merged[def.id];
head_refs.end = references[def.id].end; tail_refs.start = references[def.id].start;
var skipped = []; var skipped = [];
do { do {
var tail = last.pop(); var head = first.shift();
if (!tail) continue;
if (tail.index > head.index) continue; if (tail.index > head.index) continue;
var id = tail.definition.id; var id = head.definition.id;
var tail_refs = references[id]; if (!(id in prev)) continue;
if (!tail_refs) continue; var head_refs = references[id];
if (!head_refs) continue;
if (head_refs.start.block !== tail_refs.start.block if (head_refs.start.block !== tail_refs.start.block
|| !mergeable(head_refs, tail_refs) || !mergeable(head_refs, tail_refs)
|| (head_refs.start.loop || !same_scope(def)) && !mergeable(tail_refs, head_refs) || (head_refs.start.loop || !same_scope(def)) && !mergeable(tail_refs, head_refs)
|| compressor.option("webkit") && is_funarg(def) !== is_funarg(tail.definition) || compressor.option("webkit") && is_funarg(def) !== is_funarg(head.definition)
|| !all(tail_refs, function(sym) { || !safe_to_rename(head_refs, def)
return sym.scope.find_variable(def.name) === def; || !safe_to_rename(references[def.id], head.definition)) {
})) { skipped.push(head);
skipped.unshift(tail);
continue; continue;
} }
var orig = [], refs = []; head_refs.forEach(function(sym) {
tail_refs.forEach(function(sym) {
sym.thedef = def; sym.thedef = def;
sym.name = def.name; sym.name = def.name;
if (sym instanceof AST_SymbolRef) { if (sym instanceof AST_SymbolRef) {
refs.push(sym); def.references.push(sym);
} else { } else {
orig.push(sym); def.orig.push(sym);
} }
}); });
def.orig = orig.concat(def.orig); if (!head.definition.fixed) def.fixed = false;
def.references = refs.concat(def.references);
def.fixed = tail.definition.fixed && def.fixed;
merged[id] = def; merged[id] = def;
changed = true; changed = true;
break; break;
} while (last.length); } while (first.length);
if (skipped.length) last = last.concat(skipped); if (skipped.length) first = skipped.concat(first);
} }
return changed; return changed;
@@ -6357,6 +6348,12 @@ Compressor.prototype.compress = function(node) {
function mergeable(head, tail) { function mergeable(head, tail) {
return must_visit(head.start, head.end) || must_visit(head.start, tail.start); return must_visit(head.start, head.end) || must_visit(head.start, tail.start);
} }
function safe_to_rename(refs, def) {
return all(refs, function(sym) {
return sym.scope.find_variable(def.name) === def;
});
}
}); });
function fill_holes(orig, elements) { function fill_holes(orig, elements) {
@@ -8072,9 +8069,7 @@ Compressor.prototype.compress = function(node) {
return exp.drop_side_effect_free(compressor, first_in_statement); return exp.drop_side_effect_free(compressor, first_in_statement);
} }
function convert_spread(node) { function convert_spread(node) {
return node instanceof AST_Spread ? make_node(AST_Array, node, { return node instanceof AST_Spread ? make_node(AST_Array, node, { elements: [ node ] }) : node;
elements: [ node ]
}) : node;
} }
def(AST_Node, return_this); def(AST_Node, return_this);
def(AST_Accessor, return_null); def(AST_Accessor, return_null);
@@ -8396,20 +8391,20 @@ Compressor.prototype.compress = function(node) {
node = alternative ? make_node(AST_Binary, this, { node = alternative ? make_node(AST_Binary, this, {
operator: "||", operator: "||",
left: this.condition, left: this.condition,
right: alternative right: alternative,
}) : this.condition.drop_side_effect_free(compressor); }) : this.condition.drop_side_effect_free(compressor);
} else if (!alternative) { } else if (!alternative) {
node = make_node(AST_Binary, this, { node = make_node(AST_Binary, this, {
operator: "&&", operator: "&&",
left: this.condition, left: this.condition,
right: consequent right: consequent,
}); });
} else { } else {
node = this.clone(); node = this.clone();
node.consequent = consequent; node.consequent = consequent;
node.alternative = alternative; node.alternative = alternative;
} }
if (!compressor.option("ie")) return node; if (!exprs) return node;
if (node) exprs.push(node); if (node) exprs.push(node);
return exprs.length == 0 ? null : make_sequence(this, exprs); return exprs.length == 0 ? null : make_sequence(this, exprs);
}); });
@@ -8442,9 +8437,7 @@ Compressor.prototype.compress = function(node) {
return !(node instanceof AST_Spread); return !(node instanceof AST_Spread);
})) return this; })) return this;
return make_sequence(this, values.map(function(node) { return make_sequence(this, values.map(function(node) {
return node instanceof AST_Spread ? make_node(AST_Object, node, { return node instanceof AST_Spread ? make_node(AST_Object, node, { properties: [ node ] }) : node;
properties: [ node ],
}) : node;
})); }));
}); });
def(AST_ObjectIdentity, return_null); def(AST_ObjectIdentity, return_null);

View File

@@ -78,6 +78,7 @@ function minify(files, options) {
enclose: false, enclose: false,
ie: false, ie: false,
ie8: false, ie8: false,
keep_fargs: false,
keep_fnames: false, keep_fnames: false,
mangle: {}, mangle: {},
nameCache: null, nameCache: null,
@@ -99,6 +100,7 @@ function minify(files, options) {
if (options.annotations !== undefined) set_shorthand("annotations", options, [ "compress", "output" ]); if (options.annotations !== undefined) set_shorthand("annotations", options, [ "compress", "output" ]);
if (options.ie8) options.ie = options.ie || options.ie8; if (options.ie8) options.ie = options.ie || options.ie8;
if (options.ie) set_shorthand("ie", options, [ "compress", "mangle", "output" ]); if (options.ie) set_shorthand("ie", options, [ "compress", "mangle", "output" ]);
if (options.keep_fargs) set_shorthand("keep_fargs", options, [ "compress", "mangle" ]);
if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle" ]); if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
if (options.toplevel) set_shorthand("toplevel", options, [ "compress", "mangle" ]); if (options.toplevel) set_shorthand("toplevel", options, [ "compress", "mangle" ]);
if (options.v8) set_shorthand("v8", options, [ "mangle", "output" ]); if (options.v8) set_shorthand("v8", options, [ "mangle", "output" ]);
@@ -109,6 +111,7 @@ function minify(files, options) {
cache: options.nameCache && (options.nameCache.vars || {}), cache: options.nameCache && (options.nameCache.vars || {}),
eval: false, eval: false,
ie: false, ie: false,
keep_fargs: false,
keep_fnames: false, keep_fnames: false,
properties: false, properties: false,
reserved: [], reserved: [],

View File

@@ -92,15 +92,19 @@ SymbolDef.prototype = {
if (def && def !== self) return def.redefined() || def; if (def && def !== self) return def.redefined() || def;
}, },
unmangleable: function(options) { unmangleable: function(options) {
return this.global && !options.toplevel if (this.exported) return true;
|| this.exported if (this.undeclared) return true;
|| this.undeclared if (!options.eval && this.scope.pinned()) return true;
|| !options.eval && this.scope.pinned() if (options.keep_fargs && is_funarg(this)) return true;
|| options.keep_fnames if (options.keep_fnames) {
&& (this.orig[0] instanceof AST_SymbolClass var sym = this.orig[0];
|| this.orig[0] instanceof AST_SymbolDefClass if (sym instanceof AST_SymbolClass) return true;
|| this.orig[0] instanceof AST_SymbolDefun if (sym instanceof AST_SymbolDefClass) return true;
|| this.orig[0] instanceof AST_SymbolLambda); if (sym instanceof AST_SymbolDefun) return true;
if (sym instanceof AST_SymbolLambda) return true;
}
if (!options.toplevel && this.global) return true;
return false;
}, },
}; };
@@ -113,6 +117,10 @@ DEF_BITPROPS(SymbolDef, [
"undeclared", "undeclared",
]); ]);
function is_funarg(def) {
return def.orig[0] instanceof AST_SymbolFunarg || def.orig[1] instanceof AST_SymbolFunarg;
}
var unary_side_effects = makePredicate("delete ++ --"); var unary_side_effects = makePredicate("delete ++ --");
function is_lhs(node, parent) { function is_lhs(node, parent) {
@@ -473,8 +481,11 @@ AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
push_uniq(s.enclosed, def); push_uniq(s.enclosed, def);
if (!options) { if (!options) {
s._var_names = undefined; s._var_names = undefined;
} else if (options.keep_fnames) { } else {
s.functions.each(function(d) { if (options.keep_fargs && s instanceof AST_Lambda) s.each_argname(function(arg) {
push_uniq(def.scope.enclosed, arg.definition());
});
if (options.keep_fnames) s.functions.each(function(d) {
push_uniq(def.scope.enclosed, d); push_uniq(def.scope.enclosed, d);
}); });
} }
@@ -579,6 +590,7 @@ function _default_mangler_options(options) {
options = defaults(options, { options = defaults(options, {
eval : false, eval : false,
ie : false, ie : false,
keep_fargs : false,
keep_fnames : false, keep_fnames : false,
reserved : [], reserved : [],
toplevel : false, toplevel : false,

View File

@@ -1746,10 +1746,10 @@ issue_4454_2: {
f("PASS"); f("PASS");
} }
expect: { expect: {
function f(b) { function f(a) {
(async function(c = console.log(b)) {})(); (async function(c = console.log(a)) {})();
var b = 42..toString(); var a = 42..toString();
console.log(b); console.log(a);
} }
f("PASS"); f("PASS");
} }
@@ -2449,9 +2449,9 @@ issue_5032_normal: {
console.log(value); console.log(value);
return value; return value;
} }
async function f(c) { async function f(a) {
var b = log(c), c = b; var a = log(a), c = a;
log(b); log(a);
log(c); log(c);
} }
f("PASS"); f("PASS");

View File

@@ -220,6 +220,32 @@ merge_vars_3: {
expect_stdout: true expect_stdout: true
} }
merge_vars_4: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
var a = 1;
console.log(typeof a);
{
var b = console;
console.log(typeof b);
const a = 0;
}
}
expect: {
var a = 1;
console.log(typeof a);
{
var b = console;
console.log(typeof b);
const a = 0;
}
}
expect_stdout: true
}
use_before_init_1: { use_before_init_1: {
options = { options = {
reduce_vars: true, reduce_vars: true,

View File

@@ -1845,13 +1845,13 @@ issue_4294: {
expect: { expect: {
A = "PASS"; A = "PASS";
(function() { (function() {
var b = function({ var a = function({
[b]: {}, [a]: {},
}) {}({ }) {}({
[b]: 0, [a]: 0,
}); });
var b = A; var a = A;
console.log(b); console.log(a);
})(); })();
} }
expect_stdout: "PASS" expect_stdout: "PASS"

View File

@@ -7605,11 +7605,11 @@ issue_5230: {
}()); }());
} }
expect: { expect: {
while (void (f = function(c) { while (void (f = function(a) {
var b = 42; var b = 42;
console; console;
var c; var a;
for (var k in c = [ c ]) for (var k in a = [ a ])
console.log(b++); console.log(b++);
})(f)); })(f));
var f; var f;

View File

@@ -1163,13 +1163,13 @@ issue_5182: {
log(o.p(42)); log(o.p(42));
} }
expect: { expect: {
var o_p = console; var o = console;
log = o_p.log; log = o.log;
o_p = function(a) { o = function(a) {
console.log(a ? "PASS" : "FAIL"); console.log(a ? "PASS" : "FAIL");
return a; return a;
}; };
log(o_p(42)); log(o(42));
} }
expect_stdout: [ expect_stdout: [
"PASS", "PASS",

View File

@@ -3109,9 +3109,9 @@ issue_5081_call: {
})); }));
} }
expect: { expect: {
function f(b) { function f(a) {
// IE5-10: TypeError: Function expected // IE5-10: TypeError: Function expected
return b(b = "A") + (b += "SS"); return a(a = "A") + (a += "SS");
} }
console.log(f(function() { console.log(f(function() {
return "P"; return "P";
@@ -3161,8 +3161,8 @@ issue_5081_property_access: {
console.log(f({ A: "P" })); console.log(f({ A: "P" }));
} }
expect: { expect: {
function f(b) { function f(a) {
return b[b = "A"] + (b += "SS"); return a[a = "A"] + (a += "SS");
} }
// IE9-11: undefinedASS // IE9-11: undefinedASS
console.log(f({ A: "P" })); console.log(f({ A: "P" }));

View File

@@ -925,6 +925,28 @@ duplicate_lambda_defun_name_2: {
expect_stdout: "0" expect_stdout: "0"
} }
function_argument_mangle: {
mangle = {
keep_fargs: true,
toplevel: true,
}
input: {
A = "PASS";
var a = A;
(function(o) {
console.log(a);
})("FAIL");
}
expect: {
A = "PASS";
var n = A;
(function(o) {
console.log(n);
})("FAIL");
}
expect_stdout: "PASS"
}
function_name_mangle: { function_name_mangle: {
options = { options = {
keep_fargs: false, keep_fargs: false,

View File

@@ -280,6 +280,38 @@ merge_vars_3: {
node_version: ">=4" node_version: ">=4"
} }
merge_vars_4: {
options = {
merge_vars: true,
toplevel: true,
}
input: {
"use strict";
var a = 1;
console.log(typeof a);
{
var b = console;
console.log(typeof b);
let a = 0;
}
}
expect: {
"use strict";
var a = 1;
console.log(typeof a);
{
var b = console;
console.log(typeof b);
let a = 0;
}
}
expect_stdout: [
"number",
"object",
]
node_version: ">=4"
}
use_before_init_1: { use_before_init_1: {
options = { options = {
evaluate: true, evaluate: true,

View File

@@ -19,11 +19,11 @@ merge: {
expect: { expect: {
var a = "foo"; var a = "foo";
console.log(a); console.log(a);
function f(c) { function f(b) {
var c; var b;
console.log(c); console.log(b);
c = "bar"; b = "bar";
console.log(c); console.log(b);
} }
f("baz"); f("baz");
var d = "moo"; var d = "moo";
@@ -56,17 +56,17 @@ merge_toplevel: {
console.log(d); console.log(d);
} }
expect: { expect: {
var d = "foo"; var a = "foo";
console.log(d); console.log(a);
function f(c) { function f(b) {
var c; var b;
console.log(c); console.log(b);
c = "bar"; b = "bar";
console.log(c); console.log(b);
} }
f("baz"); f("baz");
var d = "moo"; var a = "moo";
console.log(d); console.log(a);
} }
expect_stdout: [ expect_stdout: [
"foo", "foo",
@@ -94,16 +94,16 @@ segment: {
console.log(d); console.log(d);
} }
expect: { expect: {
var d = "foo"; var a = "foo";
console.log(d); console.log(a);
for (var c, i = 0; i < 1; i++) { for (var b, i = 0; i < 1; i++) {
var c = "bar"; var b = "bar";
console.log(c); console.log(b);
c = "baz"; b = "baz";
console.log(c); console.log(b);
} }
var d = "moo"; var a = "moo";
console.log(d); console.log(a);
} }
expect_stdout: [ expect_stdout: [
"foo", "foo",
@@ -298,6 +298,89 @@ read_before_assign_2: {
expect_stdout: "PASS" expect_stdout: "PASS"
} }
collapse_vars_1: {
options = {
collapse_vars: true,
merge_vars: true,
toplevel: true,
}
input: {
var a = a && a.p;
var b = "PASS";
var b = b && console.log(b);
}
expect: {
var a = a && a.p;
var a;
var a = (a = "PASS") && console.log(a);
}
expect_stdout: "PASS"
}
collapse_vars_2: {
options = {
collapse_vars: true,
merge_vars: true,
}
input: {
"use strict";
var log = console.log;
(function g(a) {
var b = a;
var c = Math.random();
var c = b;
log(c);
return c;
})("PASS");
}
expect: {
"use strict";
var log = console.log;
(function g(a) {
var a = a;
var c = Math.random();
var c;
log(c = a);
return c;
})("PASS");
}
expect_stdout: "PASS"
}
not_redefined: {
options = {
inline: true,
join_vars: true,
merge_vars: true,
reduce_vars: true,
unused: true,
varify: true,
}
input: {
var log = console.log;
(function() {
return f("PASS");
function f(a) {
const b = a;
const c = log(b);
const d = log;
c && log(d);
}
})();
}
expect: {
var log = console.log;
(function() {
return a = "PASS",
a = log(a),
d = log,
void (a && log(d));
var a, d;
})();
}
expect_stdout: "PASS"
}
issue_4103: { issue_4103: {
options = { options = {
merge_vars: true, merge_vars: true,
@@ -325,7 +408,7 @@ issue_4103: {
] ]
} }
issue_4107: { issue_4107_1: {
options = { options = {
keep_fargs: false, keep_fargs: false,
merge_vars: true, merge_vars: true,
@@ -342,6 +425,38 @@ issue_4107: {
})(); })();
console.log(typeof a); console.log(typeof a);
} }
expect: {
(function() {
(function(c) {
c = console || c;
console.log(typeof c);
})();
})();
console.log(typeof a);
}
expect_stdout: [
"object",
"undefined",
]
}
issue_4107_2: {
options = {
keep_fargs: false,
merge_vars: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
function f(b, b, a) {
var d = 1 && c, c = console || a;
console.log(typeof c);
}
f();
})();
console.log(typeof a);
}
expect: { expect: {
(function() { (function() {
(function(a) { (function(a) {
@@ -538,12 +653,12 @@ cross_branch_1_1: {
expect: { expect: {
var a; var a;
function f() { function f() {
var y, y; var x, x;
if (a) if (a)
y = "foo"; x = "foo";
console.log(y); console.log(x);
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
a = 0; a = 0;
f(); f();
@@ -581,13 +696,13 @@ cross_branch_1_2: {
expect: { expect: {
var a; var a;
function f() { function f() {
var y, y; var x, x;
if (a) { if (a) {
y = "foo"; x = "foo";
console.log(y); console.log(x);
} }
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
a = 0; a = 0;
f(); f();
@@ -624,13 +739,13 @@ cross_branch_1_3: {
expect: { expect: {
var a; var a;
function f() { function f() {
var y, y; var x, x;
if (a) { if (a) {
y = "foo"; x = "foo";
console.log(y); console.log(x);
y = "bar"; x = "bar";
} }
console.log(y); console.log(x);
} }
a = 0; a = 0;
f(); f();
@@ -666,12 +781,12 @@ cross_branch_1_4: {
expect: { expect: {
var a; var a;
function f() { function f() {
var y, y; var x, x;
y = "foo"; x = "foo";
if (a) if (a)
console.log(y); console.log(x);
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
a = 0; a = 0;
f(); f();
@@ -751,12 +866,12 @@ cross_branch_1_6: {
expect: { expect: {
var a; var a;
function f() { function f() {
var y, y; var x, x;
y = "foo"; x = "foo";
if (a) { if (a) {
console.log(y); console.log(x);
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
} }
a = 0; a = 0;
@@ -835,12 +950,12 @@ cross_branch_1_8: {
expect: { expect: {
var a; var a;
function f() { function f() {
var y, y; var x, x;
y = "foo"; x = "foo";
console.log(y); console.log(x);
if (a) { if (a) {
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
} }
a = 0; a = 0;
@@ -877,12 +992,12 @@ cross_branch_1_9: {
expect: { expect: {
var a; var a;
function f() { function f() {
var y, y; var x, x;
y = "foo"; x = "foo";
console.log(y); console.log(x);
y = "bar"; x = "bar";
if (a) if (a)
console.log(y); console.log(x);
} }
a = 0; a = 0;
f(); f();
@@ -924,14 +1039,14 @@ cross_branch_2a_1: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) { if (a) {
if (b) if (b)
y = "foo"; x = "foo";
console.log(y); console.log(x);
} }
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
a = 0, b = 0; a = 0, b = 0;
f(); f();
@@ -980,14 +1095,14 @@ cross_branch_2a_2: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) { if (a) {
y = "foo"; x = "foo";
if (b) if (b)
console.log(y); console.log(x);
} }
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
a = 0, b = 0; a = 0, b = 0;
f(); f();
@@ -1035,14 +1150,14 @@ cross_branch_2a_3: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) { if (a) {
if (b) if (b)
y = "foo"; x = "foo";
console.log(y); console.log(x);
y = "bar"; x = "bar";
} }
console.log(y); console.log(x);
} }
a = 0, b = 0; a = 0, b = 0;
f(); f();
@@ -1092,15 +1207,15 @@ cross_branch_2a_4: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) { if (a) {
if (b) { if (b) {
y = "foo"; x = "foo";
console.log(y); console.log(x);
} }
y = "bar"; x = "bar";
} }
console.log(y); console.log(x);
} }
a = 0, b = 0; a = 0, b = 0;
f(); f();
@@ -1148,14 +1263,14 @@ cross_branch_2a_5: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) { if (a) {
y = "foo"; x = "foo";
if (b) if (b)
console.log(y); console.log(x);
y = "bar"; x = "bar";
} }
console.log(y); console.log(x);
} }
a = 0, b = 0; a = 0, b = 0;
f(); f();
@@ -1427,13 +1542,13 @@ cross_branch_2a_10: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
y = "foo"; x = "foo";
if (a) { if (a) {
if (b) if (b)
console.log(y); console.log(x);
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
} }
a = 0, b = 0; a = 0, b = 0;
@@ -1590,13 +1705,13 @@ cross_branch_2a_13: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
y = "foo"; x = "foo";
if (a) { if (a) {
console.log(y); console.log(x);
if (b) { if (b) {
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
} }
} }
@@ -1644,13 +1759,13 @@ cross_branch_2a_14: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
y = "foo"; x = "foo";
if (a) { if (a) {
console.log(y); console.log(x);
y = "bar"; x = "bar";
if (b) if (b)
console.log(y); console.log(x);
} }
} }
a = 0, b = 0; a = 0, b = 0;
@@ -1753,13 +1868,13 @@ cross_branch_2a_16: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
y = "foo"; x = "foo";
console.log(y); console.log(x);
if (a) { if (a) {
y = "bar"; x = "bar";
if (b) if (b)
console.log(y); console.log(x);
} }
} }
a = 0, b = 0; a = 0, b = 0;
@@ -1807,13 +1922,13 @@ cross_branch_2b_1: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) if (a)
y = "foo"; x = "foo";
if (b) if (b)
console.log(y); console.log(x);
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
a = 0, b = 0; a = 0, b = 0;
f(); f();
@@ -1918,13 +2033,13 @@ cross_branch_2b_3: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) if (a)
y = "foo"; x = "foo";
if (b) { if (b) {
console.log(y); console.log(x);
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
} }
a = 0, b = 0; a = 0, b = 0;
@@ -2028,13 +2143,13 @@ cross_branch_2b_5: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) if (a)
y = "foo"; x = "foo";
console.log(y); console.log(x);
if (b) { if (b) {
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
} }
a = 0, b = 0; a = 0, b = 0;
@@ -2141,14 +2256,14 @@ cross_branch_2b_7: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) { if (a) {
y = "foo"; x = "foo";
console.log(y); console.log(x);
} }
if (b) { if (b) {
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
} }
a = 0, b = 0; a = 0, b = 0;
@@ -2195,13 +2310,13 @@ cross_branch_2b_8: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) if (a)
y = "foo"; x = "foo";
console.log(y); console.log(x);
y = "bar"; x = "bar";
if (b) if (b)
console.log(y); console.log(x);
} }
a = 0, b = 0; a = 0, b = 0;
f(); f();
@@ -2250,14 +2365,14 @@ cross_branch_2b_9: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) { if (a) {
y = "foo"; x = "foo";
console.log(y); console.log(x);
} }
y = "bar"; x = "bar";
if (b) if (b)
console.log(y); console.log(x);
} }
a = 0, b = 0; a = 0, b = 0;
f(); f();
@@ -2304,14 +2419,14 @@ cross_branch_2b_10: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
if (a) { if (a) {
y = "foo"; x = "foo";
console.log(y); console.log(x);
y = "bar"; x = "bar";
} }
if (b) if (b)
console.log(y); console.log(x);
} }
a = 0, b = 0; a = 0, b = 0;
f(); f();
@@ -2412,13 +2527,13 @@ cross_branch_2b_12: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
y = "foo"; x = "foo";
if (a) if (a)
console.log(y); console.log(x);
if (b) { if (b) {
y = "bar"; x = "bar";
console.log(y); console.log(x);
} }
} }
a = 0, b = 0; a = 0, b = 0;
@@ -2465,13 +2580,13 @@ cross_branch_2b_13: {
expect: { expect: {
var a, b; var a, b;
function f() { function f() {
var y, y; var x, x;
y = "foo"; x = "foo";
if (a) if (a)
console.log(y); console.log(x);
y = "bar"; x = "bar";
if (b) if (b)
console.log(y); console.log(x);
} }
a = 0, b = 0; a = 0, b = 0;
f(); f();
@@ -2620,11 +2735,11 @@ issue_4126_1: {
try { try {
console.log("PASS"); console.log("PASS");
} catch (e) { } catch (e) {
var c = a; var b = a;
} finally { } finally {
var c = c; var a = b;
} }
console.log(c); console.log(a);
} }
f("FAIL"); f("FAIL");
} }
@@ -2816,11 +2931,11 @@ conditional_write: {
console.log(b); console.log(b);
} }
expect: { expect: {
var b = "FAIL", b; var a = "FAIL", a;
if (console) if (console)
b = "PASS"; a = "PASS";
b = [b, 42].join(); a = [a, 42].join();
console.log(b); console.log(a);
} }
expect_stdout: "PASS,42" expect_stdout: "PASS,42"
} }
@@ -2994,13 +3109,13 @@ issue_4168_use_strict: {
expect: { expect: {
"use strict"; "use strict";
var o = { var o = {
f: function(d, e, f) { f: function(a, b, c) {
var d = d.d; var a = a.d;
var e = e.e; var b = b.e;
var f = f.f; var c = c.f;
this.g(arguments); this.g(arguments);
if (d) if (a)
console.log(e, f); console.log(b, c);
}, },
g: function(args) { g: function(args) {
console.log(args[0], args[1], args[2]); console.log(args[0], args[1], args[2]);

View File

@@ -457,11 +457,11 @@ issue_5091: {
console.log(f("FAIL 1") || "PASS"); console.log(f("FAIL 1") || "PASS");
} }
expect: { expect: {
function f(b) { function f(a) {
var b = b.p; var a = a.p;
var c; var c;
b?.[c = "FAIL 2"]; a?.[c = "FAIL 2"];
return b || c; return a || c;
} }
console.log(f("FAIL 1") || "PASS"); console.log(f("FAIL 1") || "PASS");
} }

View File

@@ -436,9 +436,9 @@ merge_funarg: {
})(); })();
} }
expect: { expect: {
(function(...b) { (function(...a) {
var b = b.length; var a = a.length;
console.log(b); console.log(a);
})(); })();
} }
expect_stdout: "0" expect_stdout: "0"
@@ -456,9 +456,9 @@ merge_funarg_destructured_array: {
})([]); })([]);
} }
expect: { expect: {
(function([ ...b ]) { (function([ ...a ]) {
var b = b.length; var a = a.length;
console.log(b); console.log(a);
})([]); })([]);
} }
expect_stdout: "0" expect_stdout: "0"
@@ -476,9 +476,9 @@ merge_funarg_destructured_object: {
})([ "PASS" ]); })([ "PASS" ]);
} }
expect: { expect: {
(function({ ...b }) { (function({ ...a }) {
var b = b[0]; var a = a[0];
console.log(b); console.log(a);
})([ "PASS" ]); })([ "PASS" ]);
} }
expect_stdout: "PASS" expect_stdout: "PASS"

View File

@@ -13,10 +13,10 @@ reduce_merge_const: {
console.log(b); console.log(b);
} }
expect: { expect: {
var b = console; var a = console;
console.log(typeof b); console.log(typeof a);
b = typeof b; a = typeof a;
console.log(b); console.log(a);
} }
expect_stdout: [ expect_stdout: [
"object", "object",
@@ -41,10 +41,10 @@ reduce_merge_let: {
} }
expect: { expect: {
"use strict"; "use strict";
var b = console; var a = console;
console.log(typeof b); console.log(typeof a);
b = typeof b; a = typeof a;
console.log(b); console.log(a);
} }
expect_stdout: [ expect_stdout: [
"object", "object",

View File

@@ -976,10 +976,10 @@ issue_4454_2: {
f("PASS"); f("PASS");
} }
expect: { expect: {
function f(b) { function f(a) {
(function*(c = console.log(b)) {})(); (function*(c = console.log(a)) {})();
var b = 42..toString(); var a = 42..toString();
console.log(b); console.log(a);
} }
f("PASS"); f("PASS");
} }
@@ -1289,9 +1289,9 @@ issue_5032_normal: {
console.log(value); console.log(value);
return value; return value;
} }
function *f(c) { function *f(a) {
var b = log(c), c = b; var a = log(a), c = a;
log(b); log(a);
log(c); log(c);
} }
f("PASS").next(); f("PASS").next();

View File

@@ -188,6 +188,30 @@ describe("bin/uglifyjs", function() {
child.stdin.end(read("test/input/issue-3040/input.js")); child.stdin.end(read("test/input/issue-3040/input.js"));
}, 1000); }, 1000);
}); });
it("Should work with --keep-fargs (mangle only)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fargs -m';
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\n");
done();
});
});
it("Should work with --keep-fargs (mangle & compress)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fargs -m -c';
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){return x(function(a){return a*a})}}function g(op){return op(1)+op(2)}console.log(5==f(g)());\n");
done();
});
});
it("Should work with keep_fargs under mangler options", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fargs=true';
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\n");
done();
});
});
it("Should work with --keep-fnames (mangle only)", function(done) { it("Should work with --keep-fnames (mangle only)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m'; var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
@@ -197,10 +221,10 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with --keep-fnames (mangle & compress)", function(done) { it("Should work with --keep-fnames (mangle & compress)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c unused=false'; var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c';
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n"); assert.strictEqual(stdout, "function f(n){return function(){return n(function n(r){return r*r})}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n");
done(); done();
}); });
}); });

View File

@@ -26,6 +26,7 @@
"passes": 1e6, "passes": 1e6,
"unsafe": true "unsafe": true
}, },
"keep_fargs": true,
"keep_fnames": true, "keep_fnames": true,
"toplevel": true "toplevel": true
}, },