aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compress.js41
-rw-r--r--test/compress/conditionals.js31
2 files changed, 53 insertions, 19 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 4534d9c8..74c0febb 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -7463,6 +7463,15 @@ merge(Compressor.prototype, {
|| node instanceof AST_Object;
}
+ function repeatable(compressor, node) {
+ if (node instanceof AST_Dot) return repeatable(compressor, node.expression);
+ if (node instanceof AST_Sub) {
+ return repeatable(compressor, node.expression) && repeatable(compressor, node.property);
+ }
+ if (node instanceof AST_Symbol) return true;
+ return !node.has_side_effects(compressor);
+ }
+
OPT(AST_Binary, function(self, compressor) {
function reversible() {
return self.left.is_constant()
@@ -7531,7 +7540,7 @@ merge(Compressor.prototype, {
if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||
(self.left.is_number(compressor) && self.right.is_number(compressor)) ||
(self.left.is_boolean(compressor) && self.right.is_boolean(compressor)) ||
- can_self_compare(self.left) && self.left.equivalent_to(self.right)) {
+ repeatable(compressor, self.left) && self.left.equivalent_to(self.right)) {
self.operator = self.operator.slice(0, 2);
}
// XXX: intentionally falling down to the next case
@@ -8036,13 +8045,6 @@ merge(Compressor.prototype, {
}
return try_evaluate(compressor, self);
- function can_self_compare(node) {
- if (node instanceof AST_Dot) return can_self_compare(node.expression);
- if (node instanceof AST_Sub) return can_self_compare(node.expression) && can_self_compare(node.property);
- if (node instanceof AST_Symbol) return true;
- return !node.has_side_effects(compressor);
- }
-
function align(ref, op) {
switch (ref) {
case "-":
@@ -8504,14 +8506,13 @@ merge(Compressor.prototype, {
});
OPT(AST_Conditional, function(self, compressor) {
- if (!compressor.option("conditionals")) return self;
- // This looks like lift_sequences(), should probably be under "sequences"
- if (self.condition instanceof AST_Sequence) {
+ if (compressor.option("sequences") && self.condition instanceof AST_Sequence) {
var expressions = self.condition.expressions.slice();
self.condition = expressions.pop();
expressions.push(self);
return make_sequence(self, expressions);
}
+ if (!compressor.option("conditionals")) return self;
var condition = self.condition.is_truthy() || self.condition.evaluate(compressor, true);
if (!condition) {
AST_Node.warn("Condition always false [{file}:{line},{col}]", self.start);
@@ -8532,15 +8533,19 @@ merge(Compressor.prototype, {
}
var consequent = self.consequent;
var alternative = self.alternative;
- // x ? x : y => x || y
- if (condition instanceof AST_SymbolRef
- && consequent instanceof AST_SymbolRef
- && condition.definition() === consequent.definition()) {
- return make_node(AST_Binary, self, {
+ if (repeatable(compressor, condition)) {
+ // x ? x : y => x || y
+ if (condition.equivalent_to(consequent)) return make_node(AST_Binary, self, {
operator: "||",
left: condition,
- right: alternative
- });
+ right: alternative,
+ }).optimize(compressor);
+ // x ? y : x => x && y
+ if (condition.equivalent_to(alternative)) return make_node(AST_Binary, self, {
+ operator: "&&",
+ left: condition,
+ right: consequent,
+ }).optimize(compressor);
}
// if (foo) exp = something; else exp = something_else;
// |
diff --git a/test/compress/conditionals.js b/test/compress/conditionals.js
index 4d54b83a..5dfd17bc 100644
--- a/test/compress/conditionals.js
+++ b/test/compress/conditionals.js
@@ -1159,7 +1159,7 @@ issue_1645_2: {
expect_stdout: true
}
-condition_symbol_matches_consequent: {
+condition_matches_consequent: {
options = {
conditionals: true,
}
@@ -1188,6 +1188,35 @@ condition_symbol_matches_consequent: {
expect_stdout: "3 7 true 4"
}
+condition_matches_alternative: {
+ options = {
+ conditionals: true,
+ }
+ input: {
+ function foo(x, y) {
+ return x.p ? y[0] : x.p;
+ }
+ function bar() {
+ return g ? h : g;
+ }
+ var g = 4;
+ var h = 5;
+ console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());
+ }
+ expect: {
+ function foo(x, y) {
+ return x.p && y[0];
+ }
+ function bar() {
+ return g && h;
+ }
+ var g = 4;
+ var h = 5;
+ console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());
+ }
+ expect_stdout: "null 0 false 5"
+}
+
delete_conditional_1: {
options = {
booleans: true,
title='2012-10-03 20:03:17 +0300'>2012-10-03define AST_Node.from_mozilla_ast(ast)...returns an UglifyJS2 AST given a Mozilla AST. Still needs some work to do (need to create specific nodes like AST_SymbolRef, AST_SymbolLambda etc. instead of base AST_Symbol, in order for the mangler/compressor to work properly) Mihai Bazon