aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkzc <zaxxon2011@gmail.com>2015-11-24 13:27:50 -0500
committerkzc <zaxxon2011@gmail.com>2015-11-24 13:27:50 -0500
commit774bda13cdf8de39de7f236ed95ae3da4fc7d822 (patch)
tree9a116ff09dc276a730ce569d18ae8d1179049887
parent15b5f70338695c435cab05b7ac2de29cad230360 (diff)
downloadtracifyjs-774bda13cdf8de39de7f236ed95ae3da4fc7d822.tar.gz
tracifyjs-774bda13cdf8de39de7f236ed95ae3da4fc7d822.zip
#873 Fix `conditionals` optimizations with default compress options
-rw-r--r--lib/compress.js66
-rw-r--r--test/compress/conditionals.js204
2 files changed, 253 insertions, 17 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 32833ebf..44e19799 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -726,6 +726,32 @@ merge(Compressor.prototype, {
return [ this ];
}
});
+ AST_Node.DEFMETHOD("is_constant", function(compressor){
+ // Accomodate when compress option evaluate=false
+ // as well as the common constant expressions !0 and !1
+ return this instanceof AST_Constant
+ || (this instanceof AST_UnaryPrefix && this.operator == "!"
+ && this.expression instanceof AST_Constant)
+ || this.evaluate(compressor).length > 1;
+ });
+ // Obtain the constant value of an expression already known to be constant.
+ // Result only valid iff this.is_constant(compressor) is true.
+ AST_Node.DEFMETHOD("constant_value", function(compressor){
+ // Accomodate when option evaluate=false.
+ if (this instanceof AST_Constant) return this.value;
+ // Accomodate the common constant expressions !0 and !1 when option evaluate=false.
+ if (this instanceof AST_UnaryPrefix
+ && this.operator == "!"
+ && this.expression instanceof AST_Constant) {
+ return !this.expression.value;
+ }
+ var result = this.evaluate(compressor)
+ if (result.length > 1) {
+ return result[1];
+ }
+ // should never be reached
+ return undefined;
+ });
def(AST_Statement, function(){
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
});
@@ -2427,32 +2453,48 @@ merge(Compressor.prototype, {
alternative: alternative
});
}
- // x=y?1:1 --> x=1
- if (consequent instanceof AST_Constant
- && alternative instanceof AST_Constant
+ // y?1:1 --> 1
+ if (consequent.is_constant(compressor)
+ && alternative.is_constant(compressor)
&& consequent.equivalent_to(alternative)) {
+ var consequent_value = consequent.constant_value();
if (self.condition.has_side_effects(compressor)) {
- return AST_Seq.from_array([self.condition, make_node_from_constant(compressor, consequent.value, self)]);
+ return AST_Seq.from_array([self.condition, make_node_from_constant(compressor, consequent_value, self)]);
} else {
- return make_node_from_constant(compressor, consequent.value, self);
-
+ return make_node_from_constant(compressor, consequent_value, self);
}
}
- // x=y?true:false --> x=!!y
- if (consequent instanceof AST_True
- && alternative instanceof AST_False) {
+
+ // y?true:false --> !!y
+ if (is_true(consequent) && is_false(alternative)) {
self.condition = self.condition.negate(compressor);
return make_node(AST_UnaryPrefix, self.condition, {
operator: "!",
expression: self.condition
});
}
- // x=y?false:true --> x=!y
- if (consequent instanceof AST_False
- && alternative instanceof AST_True) {
+ // y?false:true --> !y
+ if (is_false(consequent) && is_true(alternative)) {
return self.condition.negate(compressor)
}
return self;
+
+ // AST_True or !0
+ function is_true(node) {
+ return node instanceof AST_True
+ || (node instanceof AST_UnaryPrefix
+ && node.operator == "!"
+ && node.expression instanceof AST_Constant
+ && !node.expression.value);
+ }
+ // AST_False or !1
+ function is_false(node) {
+ return node instanceof AST_False
+ || (node instanceof AST_UnaryPrefix
+ && node.operator == "!"
+ && node.expression instanceof AST_Constant
+ && !!node.expression.value);
+ }
});
OPT(AST_Boolean, function(self, compressor){
diff --git a/test/compress/conditionals.js b/test/compress/conditionals.js
index 16ef6d66..65cfea64 100644
--- a/test/compress/conditionals.js
+++ b/test/compress/conditionals.js
@@ -332,53 +332,247 @@ cond_7_1: {
cond_8: {
options = {
conditionals: true,
- evaluate : true
+ evaluate : true,
+ booleans : false
};
input: {
var a;
// compress these
a = condition ? true : false;
-
a = !condition ? true : false;
-
a = condition() ? true : false;
+ a = condition ? !0 : !1;
+ a = !condition ? !null : !2;
+ a = condition() ? !0 : !-3.5;
+
if (condition) {
a = true;
} else {
a = false;
}
- a = condition ? false : true;
+ if (condition) {
+ a = !0;
+ } else {
+ a = !1;
+ }
+ a = condition ? false : true;
a = !condition ? false : true;
-
a = condition() ? false : true;
+ a = condition ? !3 : !0;
+ a = !condition ? !2 : !0;
+ a = condition() ? !1 : !0;
+
if (condition) {
a = false;
} else {
a = true;
}
+ if (condition) {
+ a = !1;
+ } else {
+ a = !0;
+ }
+
// don't compress these
a = condition ? 1 : false;
+ a = !condition ? true : 0;
+ a = condition ? 1 : 0;
+ }
+ expect: {
+ var a;
+ a = !!condition;
+ a = !condition;
+ a = !!condition();
+
+ a = !!condition;
+ a = !condition;
+ a = !!condition();
+
+ a = !!condition;
+ a = !!condition;
+
+ a = !condition;
+ a = !!condition;
+ a = !condition();
+
+ a = !condition;
+ a = !!condition;
+ a = !condition();
+
+ a = !condition;
+ a = !condition;
+
+ a = condition ? 1 : false;
+ a = condition ? 0 : true;
+ a = condition ? 1 : 0;
+ }
+}
+cond_8b: {
+ options = {
+ conditionals: true,
+ evaluate : true,
+ booleans : true
+ };
+ input: {
+ var a;
+ // compress these
+ a = condition ? true : false;
+ a = !condition ? true : false;
+ a = condition() ? true : false;
+
+ a = condition ? !0 : !1;
+ a = !condition ? !null : !2;
+ a = condition() ? !0 : !-3.5;
+
+ if (condition) {
+ a = true;
+ } else {
+ a = false;
+ }
+
+ if (condition) {
+ a = !0;
+ } else {
+ a = !1;
+ }
+
+ a = condition ? false : true;
+ a = !condition ? false : true;
+ a = condition() ? false : true;
+
+ a = condition ? !3 : !0;
+ a = !condition ? !2 : !0;
+ a = condition() ? !1 : !0;
+
+ if (condition) {
+ a = false;
+ } else {
+ a = true;
+ }
+
+ if (condition) {
+ a = !1;
+ } else {
+ a = !0;
+ }
+
+ a = condition ? 1 : false;
a = !condition ? true : 0;
+ a = condition ? 1 : 0;
+ }
+ expect: {
+ var a;
+ a = !!condition;
+ a = !condition;
+ a = !!condition();
+ a = !!condition;
+ a = !condition;
+ a = !!condition();
+
+ a = !!condition;
+ a = !!condition;
+
+ a = !condition;
+ a = !!condition;
+ a = !condition();
+
+ a = !condition;
+ a = !!condition;
+ a = !condition();
+
+ a = !condition;
+ a = !condition;
+
+ a = condition ? 1 : !1;
+ a = condition ? 0 : !0;
a = condition ? 1 : 0;
+ }
+}
+
+cond_8c: {
+ options = {
+ conditionals: true,
+ evaluate : false,
+ booleans : false
+ };
+ input: {
+ var a;
+ // compress these
+ a = condition ? true : false;
+ a = !condition ? true : false;
+ a = condition() ? true : false;
+ a = condition ? !0 : !1;
+ a = !condition ? !null : !2;
+ a = condition() ? !0 : !-3.5;
+
+ if (condition) {
+ a = true;
+ } else {
+ a = false;
+ }
+
+ if (condition) {
+ a = !0;
+ } else {
+ a = !1;
+ }
+
+ a = condition ? false : true;
+ a = !condition ? false : true;
+ a = condition() ? false : true;
+
+ a = condition ? !3 : !0;
+ a = !condition ? !2 : !0;
+ a = condition() ? !1 : !0;
+
+ if (condition) {
+ a = false;
+ } else {
+ a = true;
+ }
+
+ if (condition) {
+ a = !1;
+ } else {
+ a = !0;
+ }
+
+ a = condition ? 1 : false;
+ a = !condition ? true : 0;
+ a = condition ? 1 : 0;
}
expect: {
var a;
a = !!condition;
a = !condition;
a = !!condition();
+
+ a = !!condition;
+ a = !condition;
+ a = condition() ? !0 : !-3.5;
+
+ a = !!condition;
+ a = !!condition;
+
+ a = !condition;
a = !!condition;
+ a = !condition();
+
a = !condition;
a = !!condition;
a = !condition();
+
a = !condition;
+ a = !condition;
+
a = condition ? 1 : false;
a = condition ? 0 : true;
a = condition ? 1 : 0;