enhance join_vars (#5162)

This commit is contained in:
Alex Lam S.L
2021-11-02 11:33:24 +08:00
committed by GitHub
parent 6d94242318
commit 3acb5a329e
2 changed files with 130 additions and 19 deletions

View File

@@ -3476,15 +3476,26 @@ merge(Compressor.prototype, {
var exprs = extract_exprs(body); var exprs = extract_exprs(body);
if (!exprs) return; if (!exprs) return;
var trimmed = false; var trimmed = false;
for (var i = exprs.length - 1; --i >= 0;) { for (var i = exprs.length; --i >= 0;) {
var expr = exprs[i]; var expr = exprs[i];
if (!(expr instanceof AST_Assign)) continue; if (!can_trim(expr)) continue;
if (expr.operator != "=") continue; var tail;
if (!(expr.left instanceof AST_SymbolRef)) continue; if (expr.left instanceof AST_SymbolRef) {
var tail = exprs.slice(i + 1); tail = exprs.slice(i + 1);
} else if (expr.left instanceof AST_PropAccess && can_trim(expr.left.expression)) {
tail = exprs.slice(i + 1);
var flattened = expr.clone();
expr = expr.left.expression;
flattened.left = flattened.left.clone();
flattened.left.expression = expr.left.clone();
tail.unshift(flattened);
} else {
continue;
}
if (tail.length == 0) continue;
if (!trim_assigns(expr.left, expr.right, tail)) continue; if (!trim_assigns(expr.left, expr.right, tail)) continue;
trimmed = true; trimmed = true;
exprs = exprs.slice(0, i + 1).concat(tail); exprs = exprs.slice(0, i).concat(expr, tail);
} }
if (defn instanceof AST_Definitions) { if (defn instanceof AST_Definitions) {
keep = keep || 0; keep = keep || 0;
@@ -3498,6 +3509,10 @@ merge(Compressor.prototype, {
if (defn instanceof AST_Var && join_var_assign(defn.definitions, exprs, keep)) trimmed = true; if (defn instanceof AST_Var && join_var_assign(defn.definitions, exprs, keep)) trimmed = true;
} }
return trimmed && exprs; return trimmed && exprs;
function can_trim(node) {
return node instanceof AST_Assign && node.operator == "=";
}
} }
function merge_assigns(prev, defn) { function merge_assigns(prev, defn) {
@@ -3554,22 +3569,35 @@ merge(Compressor.prototype, {
} }
function trim_assigns(name, value, exprs) { function trim_assigns(name, value, exprs) {
var names = Object.create(null);
names[name.name] = true;
while (value instanceof AST_Assign && value.operator == "=") {
if (value.left instanceof AST_SymbolRef) names[value.left.name] = true;
value = value.right;
}
if (!(value instanceof AST_Object)) return; if (!(value instanceof AST_Object)) return;
var trimmed = false; var trimmed = false;
do { do {
var node = exprs[0]; if (!try_join(exprs[0])) break;
if (!(node instanceof AST_Assign)) break; exprs.shift();
if (node.operator != "=") break; trimmed = true;
if (!(node.left instanceof AST_PropAccess)) break; } while (exprs.length);
return trimmed;
function try_join(node) {
if (!(node instanceof AST_Assign)) return;
if (node.operator != "=") return;
if (!(node.left instanceof AST_PropAccess)) return;
var sym = node.left.expression; var sym = node.left.expression;
if (!(sym instanceof AST_SymbolRef)) break; if (!(sym instanceof AST_SymbolRef)) return;
if (name.name != sym.name) break; if (!names[sym.name]) return;
if (!node.right.is_constant_expression(scope)) break; if (!node.right.is_constant_expression(scope)) return;
var prop = node.left.property; var prop = node.left.property;
if (prop instanceof AST_Node) { if (prop instanceof AST_Node) {
if (try_join(prop)) prop = node.left.property = prop.right;
prop = prop.evaluate(compressor); prop = prop.evaluate(compressor);
} }
if (prop instanceof AST_Node) break; if (prop instanceof AST_Node) return;
prop = "" + prop; prop = "" + prop;
var diff = prop == "__proto__" || compressor.has_directive("use strict") ? function(node) { var diff = prop == "__proto__" || compressor.has_directive("use strict") ? function(node) {
var key = node.key; var key = node.key;
@@ -3581,15 +3609,13 @@ merge(Compressor.prototype, {
} }
return key !== "__proto__"; return key !== "__proto__";
}; };
if (!all(value.properties, diff)) break; if (!all(value.properties, diff)) return;
value.properties.push(make_node(AST_ObjectKeyVal, node, { value.properties.push(make_node(AST_ObjectKeyVal, node, {
key: prop, key: prop,
value: node.right value: node.right
})); }));
exprs.shift(); return true;
trimmed = true; }
} while (exprs.length);
return trimmed;
} }
function join_consecutive_vars(statements) { function join_consecutive_vars(statements) {

View File

@@ -489,6 +489,91 @@ join_object_assignments_regex: {
expect_stdout: "1" expect_stdout: "1"
} }
chained_assignments: {
options = {
join_vars: true,
}
input: {
var a, b = a = {};
b.p = "PASS";
console.log(a.p);
}
expect: {
var a, b = a = {
p: "PASS",
};
console.log(a.p);
}
expect_stdout: "PASS"
}
folded_assignments: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var a = {};
a[a.PASS = 42] = "PASS";
console.log(a[42], a.PASS);
}
expect: {
var a = {
PASS: 42,
42: "PASS",
};
console.log(a[42], a.PASS);
}
expect_stdout: "PASS 42"
}
inlined_assignments: {
options = {
join_vars: true,
unused: true,
}
input: {
var a;
(a = {}).p = "PASS";
console.log(a.p);
}
expect: {
var a = {
p: "PASS",
};
console.log(a.p);
}
expect_stdout: "PASS"
}
typescript_enum: {
rename = true
options = {
assignments: true,
evaluate: true,
hoist_props: true,
inline: true,
join_vars: true,
passes: 4,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var Enum;
(function (Enum) {
Enum[Enum.PASS = 42] = "PASS";
})(Enum || (Enum = {}));
console.log(Enum[42], Enum.PASS);
}
expect: {
console.log("PASS", 42);
}
expect_stdout: "PASS 42"
}
issue_2816: { issue_2816: {
options = { options = {
join_vars: true, join_vars: true,