aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ast.js12
-rw-r--r--lib/compress.js49
-rw-r--r--lib/output.js2
3 files changed, 62 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 ]