compress `new` `function` containing `this` (#2417)
authorAlex Lam S.L <alexlamsl@gmail.com>
Mon, 30 Oct 2017 15:19:27 +0000 (23:19 +0800)
committerGitHub <noreply@github.com>
Mon, 30 Oct 2017 15:19:27 +0000 (23:19 +0800)
lib/compress.js
test/compress/hoist_props.js
test/compress/properties.js

index a1db985..99ab7b7 100644 (file)
@@ -592,7 +592,7 @@ merge(Compressor.prototype, {
                 || !immutable
                     && parent instanceof AST_Call
                     && parent.expression === node
-                    && (!(value instanceof AST_Function) || value.contains_this())) {
+                    && (!(value instanceof AST_Function) || value.contains_this(parent))) {
                 return true;
             } else if (parent instanceof AST_Array || parent instanceof AST_Object) {
                 return is_modified(parent, parent, level + 1);
@@ -4561,11 +4561,11 @@ merge(Compressor.prototype, {
             }
         }
         if (is_lhs(self, compressor.parent())) return self;
-        if (compressor.option("properties") && key !== prop) {
-            var node = self.flatten_object(property);
-            if (node) {
-                expr = self.expression = node.expression;
-                prop = self.property = node.property;
+        if (key !== prop) {
+            var sub = self.flatten_object(property, compressor);
+            if (sub) {
+                expr = self.expression = sub.expression;
+                prop = self.property = sub.property;
             }
         }
         if (compressor.option("properties") && compressor.option("side_effects")
@@ -4611,7 +4611,8 @@ merge(Compressor.prototype, {
         return self;
     });
 
-    AST_Lambda.DEFMETHOD("contains_this", function() {
+    AST_Lambda.DEFMETHOD("contains_this", function(grandparent) {
+        if (grandparent instanceof AST_New) return false;
         var result;
         var self = this;
         self.walk(new TreeWalker(function(node) {
@@ -4622,7 +4623,8 @@ merge(Compressor.prototype, {
         return result;
     });
 
-    AST_PropAccess.DEFMETHOD("flatten_object", function(key) {
+    AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
+        if (!compressor.option("properties")) return;
         var expr = this.expression;
         if (expr instanceof AST_Object) {
             var props = expr.properties;
@@ -4633,7 +4635,8 @@ merge(Compressor.prototype, {
                         return prop instanceof AST_ObjectKeyVal;
                     })) break;
                     var value = prop.value;
-                    if (value instanceof AST_Function && value.contains_this()) break;
+                    if (value instanceof AST_Function
+                        && value.contains_this(compressor.parent())) break;
                     return make_node(AST_Sub, this, {
                         expression: make_node(AST_Array, expr, {
                             elements: props.map(function(prop) {
@@ -4677,10 +4680,8 @@ merge(Compressor.prototype, {
             }
         }
         if (is_lhs(self, compressor.parent())) return self;
-        if (compressor.option("properties")) {
-            var node = self.flatten_object(self.property);
-            if (node) return node.optimize(compressor);
-        }
+        var sub = self.flatten_object(self.property, compressor);
+        if (sub) return sub.optimize(compressor);
         var ev = self.evaluate(compressor);
         if (ev !== self) {
             ev = make_node_from_constant(ev, self).optimize(compressor);
index 2e8343a..ccfc76f 100644 (file)
@@ -369,3 +369,31 @@ contains_this_3: {
     }
     expect_stdout: "1 1 true"
 }
+
+new_this: {
+    options = {
+        evaluate: true,
+        hoist_props: true,
+        inline: true,
+        passes: 2,
+        reduce_vars: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var o = {
+            a: 1,
+            b: 2,
+            f: function(a) {
+                this.b = a;
+            }
+        };
+        console.log(new o.f(o.a).b, o.b);
+    }
+    expect: {
+        console.log(new function(a) {
+            this.b = a;
+        }(1).b, 2);
+    }
+    expect_stdout: "1 2"
+}
index 1b5e7fc..ab20252 100644 (file)
@@ -1006,3 +1006,22 @@ array_hole: {
     }
     expect_stdout: "2 undefined 3"
 }
+
+new_this: {
+    options = {
+        properties: true,
+        side_effects: true,
+    }
+    input: {
+        new {
+            f: function(a) {
+                this.a = a;
+            }
+        }.f(42);
+    }
+    expect: {
+        new function(a) {
+            this.a = a;
+        }(42);
+    }
+}