aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ast.js12
-rw-r--r--lib/compress.js49
-rw-r--r--lib/output.js2
-rw-r--r--test/compress/sequences.js40
4 files changed, 102 insertions, 1 deletions
diff --git a/lib/ast.js b/lib/ast.js
index 44cbed12..32ec5380 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -581,6 +581,18 @@ var AST_Seq = DEFNODE("Seq", "car cdr", {
}
return list;
},
+ to_array: function() {
+ var p = this, a = [];
+ while (p) {
+ a.push(p.car);
+ if (p.cdr && !(p.cdr instanceof AST_Seq)) {
+ a.push(p.cdr);
+ break;
+ }
+ p = p.cdr;
+ }
+ return a;
+ },
add: function(node) {
var p = this;
while (p) {
diff --git a/lib/compress.js b/lib/compress.js
index 3e5b524d..22fb330e 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -1380,6 +1380,10 @@ merge(Compressor.prototype, {
});
OPT(AST_Seq, function(self, compressor){
+ if (!compressor.option("side_effects"))
+ return self;
+ if (!self.car.has_side_effects())
+ return self.cdr;
if (compressor.option("cascade")) {
if (self.car instanceof AST_Assign
&& !self.car.left.has_side_effects()
@@ -1395,7 +1399,26 @@ merge(Compressor.prototype, {
return self;
});
+ AST_Unary.DEFMETHOD("lift_sequences", function(compressor){
+ if (compressor.option("sequences")) {
+ if (this.expression instanceof AST_Seq) {
+ var seq = this.expression;
+ var x = seq.to_array();
+ this.expression = x.pop();
+ x.push(this);
+ seq = AST_Seq.from_array(x).transform(compressor);
+ return seq;
+ }
+ }
+ return this;
+ });
+
+ OPT(AST_UnaryPostfix, function(self, compressor){
+ return self.lift_sequences(compressor);
+ });
+
OPT(AST_UnaryPrefix, function(self, compressor){
+ self = self.lift_sequences(compressor);
var e = self.expression;
if (compressor.option("booleans") && compressor.in_boolean_context()) {
switch (self.operator) {
@@ -1418,7 +1441,32 @@ merge(Compressor.prototype, {
return self.evaluate(compressor)[0];
});
+ AST_Binary.DEFMETHOD("lift_sequences", function(compressor){
+ if (compressor.option("sequences")) {
+ if (this.left instanceof AST_Seq) {
+ var seq = this.left;
+ var x = seq.to_array();
+ this.left = x.pop();
+ x.push(this);
+ seq = AST_Seq.from_array(x).transform(compressor);
+ return seq;
+ }
+ if (this.right instanceof AST_Seq
+ && !(this.operator == "||" || this.operator == "&&")
+ && !this.left.has_side_effects()) {
+ var seq = this.right;
+ var x = seq.to_array();
+ this.right = x.pop();
+ x.push(this);
+ seq = AST_Seq.from_array(x).transform(compressor);
+ return seq;
+ }
+ }
+ return this;
+ });
+
OPT(AST_Binary, function(self, compressor){
+ self = self.lift_sequences(compressor);
if (compressor.option("comparisons")) switch (self.operator) {
case "===":
case "!==":
@@ -1557,6 +1605,7 @@ merge(Compressor.prototype, {
var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
OPT(AST_Assign, function(self, compressor){
+ self = self.lift_sequences(compressor);
if (self.operator == "="
&& self.left instanceof AST_SymbolRef
&& self.right instanceof AST_Binary
diff --git a/lib/output.js b/lib/output.js
index 8d2c4d39..4b515ecd 100644
--- a/lib/output.js
+++ b/lib/output.js
@@ -414,7 +414,7 @@ function OutputStream(options) {
var p = output.parent();
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
|| p instanceof AST_Unary // !(foo, bar, baz)
- || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 7
+ || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
|| p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4
|| p instanceof AST_Dot // (1, {foo:2}).foo ==> 2
|| p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
diff --git a/test/compress/sequences.js b/test/compress/sequences.js
index 513bc84b..d48eced2 100644
--- a/test/compress/sequences.js
+++ b/test/compress/sequences.js
@@ -87,3 +87,43 @@ make_sequences_4: {
with (x = 5, obj);
}
}
+
+lift_sequences_1: {
+ options = { sequences: true };
+ input: {
+ foo = !(x(), y(), bar());
+ }
+ expect: {
+ x(), y(), foo = !bar();
+ }
+}
+
+lift_sequences_2: {
+ options = { sequences: true, evaluate: true };
+ input: {
+ q = 1 + (foo(), bar(), 5) + 7 * (5 / (3 - (a(), (QW=ER), c(), 2))) - (x(), y(), 5);
+ }
+ expect: {
+ foo(), bar(), a(), QW = ER, c(), x(), y(), q = 36
+ }
+}
+
+lift_sequences_3: {
+ options = { sequences: true, conditionals: true };
+ input: {
+ x = (foo(), bar(), baz()) ? 10 : 20;
+ }
+ expect: {
+ foo(), bar(), x = baz() ? 10 : 20;
+ }
+}
+
+lift_sequences_4: {
+ options = { side_effects: true };
+ input: {
+ x = (foo, bar, baz);
+ }
+ expect: {
+ x = baz;
+ }
+}