enhance conditionals (#3798)
This commit is contained in:
133
lib/compress.js
133
lib/compress.js
@@ -5222,50 +5222,53 @@ merge(Compressor.prototype, {
|
|||||||
self.body = self.alternative || make_node(AST_EmptyStatement, self);
|
self.body = self.alternative || make_node(AST_EmptyStatement, self);
|
||||||
self.alternative = tmp;
|
self.alternative = tmp;
|
||||||
}
|
}
|
||||||
if (self.body instanceof AST_SimpleStatement
|
var body = [], var_defs = [], refs = [];
|
||||||
&& self.alternative instanceof AST_SimpleStatement) {
|
var body_exprs = sequencesize(self.body, body, var_defs, refs);
|
||||||
return make_node(AST_SimpleStatement, self, {
|
var alt_exprs = sequencesize(self.alternative, body, var_defs, refs);
|
||||||
body: make_node(AST_Conditional, self, {
|
if (body_exprs && alt_exprs) {
|
||||||
condition : self.condition,
|
if (var_defs.length > 0) body.push(make_node(AST_Var, self, {
|
||||||
consequent : self.body.body,
|
definitions: var_defs
|
||||||
alternative : self.alternative.body
|
}));
|
||||||
})
|
if (body_exprs.length == 0) {
|
||||||
}).optimize(compressor);
|
body.push(make_node(AST_SimpleStatement, self.condition, {
|
||||||
}
|
body: alt_exprs.length > 0 ? make_node(AST_Binary, self, {
|
||||||
if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
|
operator : "||",
|
||||||
if (self_condition_length === negated_length && !negated_is_best
|
left : self.condition,
|
||||||
&& self.condition instanceof AST_Binary && self.condition.operator == "||") {
|
right : make_sequence(self.alternative, alt_exprs)
|
||||||
// although the code length of self.condition and negated are the same,
|
}).transform(compressor) : self.condition.clone()
|
||||||
// negated does not require additional surrounding parentheses.
|
}).optimize(compressor));
|
||||||
// see https://github.com/mishoo/UglifyJS2/issues/979
|
} else if (alt_exprs.length == 0) {
|
||||||
negated_is_best = true;
|
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, {
|
refs.forEach(function(ref) {
|
||||||
body: make_node(AST_Binary, self, {
|
ref.definition().references.push(ref);
|
||||||
operator : "||",
|
});
|
||||||
left : negated,
|
return make_node(AST_BlockStatement, self, {
|
||||||
right : self.body.body
|
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)
|
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (is_empty(self.body)) {
|
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, {
|
self = make_node(AST_If, self, {
|
||||||
condition: negated,
|
condition: negated,
|
||||||
body: self.alternative,
|
body: self.alternative,
|
||||||
@@ -5320,6 +5323,56 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (compressor.option("typeofs")) mark_locally_defined(self.condition, self.body, self.alternative);
|
if (compressor.option("typeofs")) mark_locally_defined(self.condition, self.body, self.alternative);
|
||||||
return self;
|
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) {
|
OPT(AST_Switch, function(self, compressor) {
|
||||||
|
|||||||
@@ -1384,7 +1384,7 @@ hoist_decl: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var a, b;
|
var a, b;
|
||||||
x() ? y() : z();
|
(x() ? y : z)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1173,6 +1173,7 @@ var_catch_toplevel: {
|
|||||||
x();
|
x();
|
||||||
} catch (a) {
|
} catch (a) {
|
||||||
var a;
|
var a;
|
||||||
|
var a;
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,10 @@ issue_1639_1: {
|
|||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
|
for (var a = 100, b = 10, L1 = 5; --L1 > 0;) {
|
||||||
if (--b, 0) var ignore = 0;
|
var ignore;
|
||||||
|
--b;
|
||||||
|
}
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
expect_stdout: "100 6"
|
expect_stdout: "100 6"
|
||||||
|
|||||||
Reference in New Issue
Block a user