aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compress.js41
-rw-r--r--test/compress/sequences.js56
2 files changed, 86 insertions, 11 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 60293187..49abc54b 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -908,7 +908,7 @@ merge(Compressor.prototype, {
// the func (becomes lexical instead of global).
function maintain_this_binding(parent, orig, val) {
if (parent instanceof AST_UnaryPrefix && parent.operator == "delete"
- || parent instanceof AST_Call && parent.expression === orig
+ || parent.TYPE == "Call" && parent.expression === orig
&& (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name == "eval")) {
return make_sequence(orig, [ make_node(AST_Number, orig, { value: 0 }), val ]);
}
@@ -4456,7 +4456,24 @@ merge(Compressor.prototype, {
return self;
});
- OPT(AST_Call, function(self, compressor){
+ 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 (tail instanceof AST_PropAccess && !(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);
+ });
+
+ OPT(AST_Call, function(self, compressor) {
+ var seq = self.lift_sequences(compressor);
+ if (seq !== self) {
+ return seq;
+ }
var exp = self.expression;
var fn = exp;
if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) {
@@ -4964,7 +4981,11 @@ merge(Compressor.prototype, {
}
});
- OPT(AST_New, function(self, compressor){
+ OPT(AST_New, function(self, compressor) {
+ var seq = self.lift_sequences(compressor);
+ if (seq !== self) {
+ return seq;
+ }
if (compressor.option("unsafe")) {
var exp = self.expression;
if (is_undeclared_ref(exp)) {
@@ -5020,14 +5041,12 @@ merge(Compressor.prototype, {
});
AST_Unary.DEFMETHOD("lift_sequences", function(compressor){
- if (compressor.option("sequences")) {
- if (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);
- }
+ 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;
});
diff --git a/test/compress/sequences.js b/test/compress/sequences.js
index 12acbcf7..8aede12b 100644
--- a/test/compress/sequences.js
+++ b/test/compress/sequences.js
@@ -876,3 +876,59 @@ forin: {
}
expect_stdout: "PASS"
}
+
+call: {
+ options = {
+ sequences: true,
+ }
+ input: {
+ var a = function() {
+ return this;
+ }();
+ function b() {
+ console.log("foo");
+ }
+ b.c = function() {
+ console.log(this === b ? "bar" : "baz");
+ };
+ (a, b)();
+ (a, b.c)();
+ (a, function() {
+ console.log(this === a);
+ })();
+ new (a, b)();
+ new (a, b.c)();
+ new (a, function() {
+ console.log(this === a);
+ })();
+ }
+ expect: {
+ var a = function() {
+ return this;
+ }();
+ function b() {
+ console.log("foo");
+ }
+ b.c = function() {
+ console.log(this === b ? "bar" : "baz");
+ },
+ a, b(),
+ (a, b.c)(),
+ a, function() {
+ console.log(this === a);
+ }(),
+ a, new b(),
+ a, new b.c(),
+ a, new function() {
+ console.log(this === a);
+ }();
+ }
+ expect_stdout: [
+ "foo",
+ "baz",
+ "true",
+ "foo",
+ "baz",
+ "false",
+ ]
+}