Skip to content

Commit

Permalink
enhance sequences (#3693)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Jan 28, 2020
1 parent e9e76dc commit a478f27
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 38 deletions.
82 changes: 46 additions & 36 deletions lib/compress.js
Expand Up @@ -5400,25 +5400,32 @@ merge(Compressor.prototype, {
return self.definitions.length ? self : make_node(AST_EmptyStatement, self);
});

AST_Call.DEFMETHOD("lift_sequences", function(compressor) {
if (!compressor.option("sequences")) return this;
var exp = this.expression;
if (!(exp instanceof AST_Sequence)) return this;
var tail = exp.tail_node();
if (needs_unbinding(compressor, tail) && !(this instanceof AST_New)) return this;
var expressions = exp.expressions.slice(0, -1);
var node = this.clone();
node.expression = tail;
expressions.push(node);
return make_sequence(this, expressions).optimize(compressor);
});
function lift_sequence_in_expression(node, compressor) {
var exp = node.expression;
if (!(exp instanceof AST_Sequence)) return node;
var x = exp.expressions.slice();
var e = node.clone();
e.expression = x.pop();
x.push(e);
return make_sequence(node, x);
}

OPT(AST_Call, function(self, compressor) {
var seq = self.lift_sequences(compressor);
if (seq !== self) {
return seq;
}
var exp = self.expression;
if (compressor.option("sequences")) {
if (exp instanceof AST_PropAccess) {
var seq = lift_sequence_in_expression(exp, compressor);
if (seq !== exp) {
var call = self.clone();
call.expression = seq.expressions.pop();
seq.expressions.push(call);
return seq.optimize(compressor);
}
} else if (!needs_unbinding(compressor, exp.tail_node())) {
var seq = lift_sequence_in_expression(self, compressor);
if (seq !== self) return seq.optimize(compressor);
}
}
var fn = exp;
if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) {
fn = fn.fixed_value();
Expand Down Expand Up @@ -5989,9 +5996,9 @@ merge(Compressor.prototype, {
});

OPT(AST_New, function(self, compressor) {
var seq = self.lift_sequences(compressor);
if (seq !== self) {
return seq;
if (compressor.option("sequences")) {
var seq = lift_sequence_in_expression(self, compressor);
if (seq !== self) return seq.optimize(compressor);
}
if (compressor.option("unsafe")) {
var exp = self.expression;
Expand Down Expand Up @@ -6047,19 +6054,12 @@ merge(Compressor.prototype, {
}
});

AST_Unary.DEFMETHOD("lift_sequences", function(compressor) {
if (compressor.option("sequences") && this.expression instanceof AST_Sequence) {
var x = this.expression.expressions.slice();
var e = this.clone();
e.expression = x.pop();
x.push(e);
return make_sequence(this, x).optimize(compressor);
}
return this;
});

OPT(AST_UnaryPostfix, function(self, compressor) {
return self.lift_sequences(compressor);
if (compressor.option("sequences")) {
var seq = lift_sequence_in_expression(self, compressor);
if (seq !== self) return seq.optimize(compressor);
}
return self;
});

OPT(AST_UnaryPrefix, function(self, compressor) {
Expand All @@ -6076,9 +6076,9 @@ merge(Compressor.prototype, {
}
return make_sequence(self, [ e, make_node(AST_True, self) ]).optimize(compressor);
}
var seq = self.lift_sequences(compressor);
if (seq !== self) {
return seq;
if (compressor.option("sequences")) {
var seq = lift_sequence_in_expression(self, compressor);
if (seq !== self) return seq.optimize(compressor);
}
if (compressor.option("side_effects") && self.operator == "void") {
e = e.drop_side_effect_free(compressor);
Expand Down Expand Up @@ -6211,7 +6211,8 @@ merge(Compressor.prototype, {
// result. hence, force switch.
reverse();
}
self = self.lift_sequences(compressor);
var seq = self.lift_sequences(compressor);
if (seq !== self) return seq;
if (compressor.option("assignments") && lazy_op[self.operator]) {
var assign = self.right;
// a || (a = x) => a = a || x
Expand Down Expand Up @@ -7127,7 +7128,8 @@ merge(Compressor.prototype, {
|| parent instanceof AST_UnaryPrefix);
}
}
self = self.lift_sequences(compressor);
var seq = self.lift_sequences(compressor);
if (seq !== self) return seq;
if (!compressor.option("assignments")) return self;
if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {
// x = expr1 OP expr2
Expand Down Expand Up @@ -7486,6 +7488,10 @@ merge(Compressor.prototype, {
}

OPT(AST_Sub, function(self, compressor) {
if (compressor.option("sequences") && compressor.parent().TYPE != "Call") {
var seq = lift_sequence_in_expression(self, compressor);
if (seq !== self) return seq.optimize(compressor);
}
var expr = self.expression;
var prop = self.property;
if (compressor.option("properties")) {
Expand Down Expand Up @@ -7650,6 +7656,10 @@ merge(Compressor.prototype, {
});

OPT(AST_Dot, function(self, compressor) {
if (compressor.option("sequences") && compressor.parent().TYPE != "Call") {
var seq = lift_sequence_in_expression(self, compressor);
if (seq !== self) return seq.optimize(compressor);
}
if (self.property == "arguments" || self.property == "caller") {
AST_Node.warn("Function.prototype.{prop} not supported [{file}:{line},{col}]", {
prop: self.property,
Expand Down
2 changes: 1 addition & 1 deletion test/compress/functions.js
Expand Up @@ -2244,7 +2244,7 @@ issue_3076: {
var c = "PASS";
(function(b) {
var n = 2;
while (--b + (e = void 0, e && (c = "FAIL"), e = 5, 1).toString() && --n > 0);
while (--b + (e = void 0, e && (c = "FAIL"), e = 5, 1..toString()) && --n > 0);
var e;
})(2),
console.log(c);
Expand Down
26 changes: 25 additions & 1 deletion test/compress/sequences.js
Expand Up @@ -910,15 +910,23 @@ call: {
console.log(this === b ? "bar" : "baz");
};
(a, b)();
(a, b).c();
(a, b.c)();
(a, b)["c"]();
(a, b["c"])();
(a, function() {
console.log(this === a);
})();
new (a, b)();
new (a, b).c();
new (a, b.c)();
new (a, b)["c"]();
new (a, b["c"])();
new (a, function() {
console.log(this === a);
})();
console.log(typeof (a, b).c);
console.log(typeof (a, b)["c"]);
}
expect: {
var a = function() {
Expand All @@ -931,23 +939,39 @@ call: {
console.log(this === b ? "bar" : "baz");
},
b(),
b.c(),
(a, b.c)(),
b["c"](),
(a, b["c"])(),
function() {
console.log(this === a);
}(),
new b(),
new b.c(),
new b.c(),
new b["c"](),
new b["c"](),
new function() {
console.log(this === a);
}();
}(),
console.log((a, typeof b.c)),
console.log((a, typeof b["c"]));
}
expect_stdout: [
"foo",
"bar",
"baz",
"bar",
"baz",
"true",
"foo",
"baz",
"baz",
"baz",
"baz",
"false",
"function",
"function",
]
}

Expand Down

0 comments on commit a478f27

Please sign in to comment.