107
lib/compress.js
107
lib/compress.js
@@ -8223,35 +8223,86 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
|
||||
function fuzzy_eval(compressor, node, nullish) {
|
||||
if (node.truthy) return true;
|
||||
if (node.falsy && !nullish) return false;
|
||||
if (node.is_truthy()) return true;
|
||||
return node.evaluate(compressor, true);
|
||||
}
|
||||
|
||||
function mark_duplicate_condition(compressor, node) {
|
||||
for (var level = 0, child = compressor.self(), parent; ; child = parent) {
|
||||
parent = compressor.parent(level++);
|
||||
if (parent instanceof AST_Binary) {
|
||||
var op = parent.operator;
|
||||
if (!lazy_op[op]) return;
|
||||
var left = parent.left;
|
||||
if (left === child) continue;
|
||||
if (node.equivalent_to(left)) node[op == "&&" ? "truthy" : "falsy"] = true;
|
||||
} else if (parent instanceof AST_Conditional) {
|
||||
var cond = parent.condition;
|
||||
if (cond === child) continue;
|
||||
if (node.equivalent_to(cond)) switch (child) {
|
||||
case parent.consequent:
|
||||
node.truthy = true;
|
||||
break;
|
||||
case parent.alternative:
|
||||
node.falsy = true;
|
||||
break;
|
||||
}
|
||||
} else if (parent instanceof AST_Exit) {
|
||||
break;
|
||||
} else if (parent instanceof AST_If) {
|
||||
break;
|
||||
} else if (parent instanceof AST_Sequence) {
|
||||
if (parent.expressions[0] === child) continue;
|
||||
} else if (parent instanceof AST_SimpleStatement) {
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
while (true) {
|
||||
child = parent;
|
||||
parent = compressor.parent(level++);
|
||||
if (parent instanceof AST_BlockStatement) {
|
||||
if (parent.body[0] === child) continue;
|
||||
} else if (parent instanceof AST_If) {
|
||||
var cond = parent.condition;
|
||||
if (cond === child) continue;
|
||||
if (node.equivalent_to(cond)) switch (child) {
|
||||
case parent.body:
|
||||
node.truthy = true;
|
||||
break;
|
||||
case parent.alternative:
|
||||
node.falsy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
OPT(AST_If, function(self, compressor) {
|
||||
if (is_empty(self.alternative)) self.alternative = null;
|
||||
|
||||
if (!compressor.option("conditionals")) return self;
|
||||
if (compressor.option("booleans")) mark_duplicate_condition(compressor, self.condition);
|
||||
// if condition can be statically determined, warn and drop
|
||||
// one of the blocks. note, statically determined implies
|
||||
// “has no side effects”; also it doesn't work for cases like
|
||||
// `x && true`, though it probably should.
|
||||
if (compressor.option("dead_code")) {
|
||||
var cond = self.condition.evaluate(compressor);
|
||||
if (cond instanceof AST_Node) {
|
||||
cond = self.condition.is_truthy() || self.condition.evaluate(compressor, true);
|
||||
}
|
||||
var cond = fuzzy_eval(compressor, self.condition);
|
||||
if (!cond) {
|
||||
AST_Node.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
|
||||
var body = [
|
||||
make_node(AST_SimpleStatement, self.condition, {
|
||||
body: self.condition
|
||||
}),
|
||||
];
|
||||
var body = [ make_node(AST_SimpleStatement, self.condition, { body: self.condition }) ];
|
||||
extract_declarations_from_unreachable_code(compressor, self.body, body);
|
||||
if (self.alternative) body.push(self.alternative);
|
||||
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
||||
} else if (!(cond instanceof AST_Node)) {
|
||||
AST_Node.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
|
||||
var body = [
|
||||
make_node(AST_SimpleStatement, self.condition, {
|
||||
body: self.condition
|
||||
}),
|
||||
make_node(AST_SimpleStatement, self.condition, { body: self.condition }),
|
||||
self.body,
|
||||
];
|
||||
if (self.alternative) extract_declarations_from_unreachable_code(compressor, self.alternative, body);
|
||||
@@ -8275,9 +8326,7 @@ merge(Compressor.prototype, {
|
||||
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 (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, {
|
||||
@@ -10221,7 +10270,18 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
break;
|
||||
}
|
||||
var in_bool = compressor.option("booleans") && compressor.in_boolean_context();
|
||||
var in_bool = false;
|
||||
var parent = compressor.parent();
|
||||
if (compressor.option("booleans")) {
|
||||
var lhs = self.left;
|
||||
if (lazy_op[self.operator] && !lhs.has_side_effects(compressor)) {
|
||||
if (lhs.equivalent_to(self.right)) {
|
||||
return maintain_this_binding(compressor, parent, compressor.self(), lhs).optimize(compressor);
|
||||
}
|
||||
mark_duplicate_condition(compressor, lhs);
|
||||
}
|
||||
in_bool = compressor.in_boolean_context();
|
||||
}
|
||||
if (in_bool) switch (self.operator) {
|
||||
case "+":
|
||||
var ll = self.left.evaluate(compressor);
|
||||
@@ -10255,7 +10315,6 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
break;
|
||||
}
|
||||
var parent = compressor.parent();
|
||||
if (compressor.option("comparisons") && self.is_boolean(compressor)) {
|
||||
if (!(parent instanceof AST_Binary) || parent instanceof AST_Assign) {
|
||||
var negated = best_of(compressor, self, make_node(AST_UnaryPrefix, self, {
|
||||
@@ -10313,7 +10372,7 @@ merge(Compressor.prototype, {
|
||||
var associative = true;
|
||||
switch (self.operator) {
|
||||
case "&&":
|
||||
var ll = fuzzy_eval(self.left);
|
||||
var ll = fuzzy_eval(compressor, self.left);
|
||||
if (!ll) {
|
||||
AST_Node.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
||||
return maintain_this_binding(compressor, parent, compressor.self(), self.left).optimize(compressor);
|
||||
@@ -10349,7 +10408,7 @@ merge(Compressor.prototype, {
|
||||
case "??":
|
||||
var nullish = true;
|
||||
case "||":
|
||||
var ll = fuzzy_eval(self.left, nullish);
|
||||
var ll = fuzzy_eval(compressor, self.left, nullish);
|
||||
if (nullish ? ll == null : !ll) {
|
||||
AST_Node.warn("Condition left of {operator} always {value} [{file}:{line},{col}]", {
|
||||
operator: self.operator,
|
||||
@@ -10732,13 +10791,6 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
}
|
||||
|
||||
function fuzzy_eval(node, nullish) {
|
||||
if (node.truthy) return true;
|
||||
if (node.falsy && !nullish) return false;
|
||||
if (node.is_truthy()) return true;
|
||||
return node.evaluate(compressor, true);
|
||||
}
|
||||
|
||||
function is_indexFn(node) {
|
||||
return node.TYPE == "Call"
|
||||
&& node.expression instanceof AST_Dot
|
||||
@@ -11286,7 +11338,8 @@ merge(Compressor.prototype, {
|
||||
return make_sequence(self, expressions);
|
||||
}
|
||||
if (!compressor.option("conditionals")) return self;
|
||||
var condition = self.condition.is_truthy() || self.condition.evaluate(compressor, true);
|
||||
if (compressor.option("booleans")) mark_duplicate_condition(compressor, self.condition);
|
||||
var condition = fuzzy_eval(compressor, self.condition);
|
||||
if (!condition) {
|
||||
AST_Node.warn("Condition always false [{file}:{line},{col}]", self.start);
|
||||
return make_sequence(self, [ self.condition, self.alternative ]).optimize(compressor);
|
||||
|
||||
Reference in New Issue
Block a user