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

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

View File

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

View File

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