enhance conditionals (#3798)

This commit is contained in:
Alex Lam S.L
2020-04-18 15:32:22 +01:00
committed by GitHub
parent 60d4e7b09f
commit fd6144d95b
4 changed files with 99 additions and 43 deletions

View File

@@ -5222,50 +5222,53 @@ merge(Compressor.prototype, {
self.body = self.alternative || make_node(AST_EmptyStatement, self);
self.alternative = tmp;
}
if (self.body instanceof AST_SimpleStatement
&& self.alternative instanceof AST_SimpleStatement) {
return make_node(AST_SimpleStatement, self, {
body: make_node(AST_Conditional, self, {
condition : self.condition,
consequent : self.body.body,
alternative : self.alternative.body
})
}).optimize(compressor);
}
if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
if (self_condition_length === negated_length && !negated_is_best
&& self.condition instanceof AST_Binary && self.condition.operator == "||") {
// although the code length of self.condition and negated are the same,
// negated does not require additional surrounding parentheses.
// see https://github.com/mishoo/UglifyJS2/issues/979
negated_is_best = true;
var body = [], var_defs = [], refs = [];
var body_exprs = sequencesize(self.body, body, var_defs, refs);
var alt_exprs = sequencesize(self.alternative, body, var_defs, refs);
if (body_exprs && alt_exprs) {
if (var_defs.length > 0) body.push(make_node(AST_Var, self, {
definitions: var_defs
}));
if (body_exprs.length == 0) {
body.push(make_node(AST_SimpleStatement, self.condition, {
body: alt_exprs.length > 0 ? make_node(AST_Binary, self, {
operator : "||",
left : self.condition,
right : make_sequence(self.alternative, alt_exprs)
}).transform(compressor) : self.condition.clone()
}).optimize(compressor));
} else if (alt_exprs.length == 0) {
if (self_condition_length === negated_length && !negated_is_best
&& self.condition instanceof AST_Binary && self.condition.operator == "||") {
// although the code length of self.condition and negated are the same,
// negated does not require additional surrounding parentheses.
// see https://github.com/mishoo/UglifyJS2/issues/979
negated_is_best = true;
}
body.push(make_node(AST_SimpleStatement, self, {
body: make_node(AST_Binary, self, {
operator : negated_is_best ? "||" : "&&",
left : negated_is_best ? negated : self.condition,
right : make_sequence(self.body, body_exprs)
}).transform(compressor)
}).optimize(compressor));
} else {
body.push(make_node(AST_SimpleStatement, self, {
body: make_node(AST_Conditional, self, {
condition : self.condition,
consequent : make_sequence(self.body, body_exprs),
alternative : make_sequence(self.alternative, alt_exprs)
})
}).optimize(compressor));
}
if (negated_is_best) return make_node(AST_SimpleStatement, self, {
body: make_node(AST_Binary, self, {
operator : "||",
left : negated,
right : self.body.body
}).transform(compressor)
}).optimize(compressor);
return make_node(AST_SimpleStatement, self, {
body: make_node(AST_Binary, self, {
operator : "&&",
left : self.condition,
right : self.body.body
}).transform(compressor)
refs.forEach(function(ref) {
ref.definition().references.push(ref);
});
return make_node(AST_BlockStatement, self, {
body: body
}).optimize(compressor);
}
if (is_empty(self.body)) {
if (is_empty(self.alternative)) return make_node(AST_SimpleStatement, self.condition, {
body: self.condition.clone()
}).optimize(compressor);
if (self.alternative instanceof AST_SimpleStatement) return make_node(AST_SimpleStatement, self, {
body: make_node(AST_Binary, self, {
operator : "||",
left : self.condition,
right : self.alternative.body
}).transform(compressor)
}).optimize(compressor);
self = make_node(AST_If, self, {
condition: negated,
body: self.alternative,
@@ -5320,6 +5323,56 @@ merge(Compressor.prototype, {
}
if (compressor.option("typeofs")) mark_locally_defined(self.condition, self.body, self.alternative);
return self;
function sequencesize(stat, defuns, var_defs, refs) {
if (stat == null) return [];
if (stat instanceof AST_BlockStatement) {
var exprs = [];
for (var i = 0; i < stat.body.length; i++) {
var line = stat.body[i];
if (line instanceof AST_Defun) {
defuns.push(line);
} else if (line instanceof AST_EmptyStatement) {
continue;
} else if (line instanceof AST_SimpleStatement) {
if (!compressor.option("sequences") && exprs.length > 0) return;
exprs.push(line.body);
} else if (line instanceof AST_Var) {
if (!compressor.option("sequences") && exprs.length > 0) return;
line.definitions.forEach(process_var_def);
} else {
return;
}
}
return exprs;
}
if (stat instanceof AST_Defun) {
defuns.push(stat);
return [];
}
if (stat instanceof AST_EmptyStatement) return [];
if (stat instanceof AST_SimpleStatement) return [ stat.body ];
if (stat instanceof AST_Var) {
var exprs = [];
stat.definitions.forEach(process_var_def);
return exprs;
}
function process_var_def(var_def) {
var_defs.push(make_node(AST_VarDef, var_def, {
name: var_def.name,
value: null
}));
if (!var_def.value) return;
var ref = make_node(AST_SymbolRef, var_def.name, var_def.name);
exprs.push(make_node(AST_Assign, var_def, {
operator: "=",
left: ref,
right: var_def.value
}));
refs.push(ref);
}
}
});
OPT(AST_Switch, function(self, compressor) {

View File

@@ -1384,7 +1384,7 @@ hoist_decl: {
}
expect: {
var a, b;
x() ? y() : z();
(x() ? y : z)();
}
}

View File

@@ -1173,6 +1173,7 @@ var_catch_toplevel: {
x();
} catch (a) {
var a;
var a;
}
}();
}

View File

@@ -22,8 +22,10 @@ issue_1639_1: {
console.log(a, b);
}
expect: {
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
if (--b, 0) var ignore = 0;
for (var a = 100, b = 10, L1 = 5; --L1 > 0;) {
var ignore;
--b;
}
console.log(a, b);
}
expect_stdout: "100 6"