enhance `side_effects` (#4175)
authorAlex Lam S.L <alexlamsl@gmail.com>
Sun, 4 Oct 2020 15:43:49 +0000 (16:43 +0100)
committerGitHub <noreply@github.com>
Sun, 4 Oct 2020 15:43:49 +0000 (23:43 +0800)
lib/compress.js
test/compress/properties.js
test/compress/side_effects.js
test/input/issue-3294/output.js
test/input/issue-520/output.js

index a7e5eac..30757c4 100644 (file)
@@ -2911,6 +2911,9 @@ merge(Compressor.prototype, {
             this._dot_throw = return_false;
             return false;
         });
+        def(AST_This, function(compressor) {
+            return is_strict(compressor) && !this.scope.new;
+        });
         def(AST_UnaryPrefix, function() {
             return this.operator == "void";
         });
@@ -3944,7 +3947,15 @@ merge(Compressor.prototype, {
         def(AST_Array, function(compressor) {
             return any(this.elements, compressor);
         });
-        def(AST_Assign, return_true);
+        def(AST_Assign, function(compressor) {
+            var lhs = this.left;
+            if (!(lhs instanceof AST_PropAccess)) return true;
+            var node = lhs.expression;
+            return !(node instanceof AST_This)
+                || !node.scope.new
+                || lhs instanceof AST_Sub && lhs.property.has_side_effects(compressor)
+                || this.right.has_side_effects(compressor);
+        });
         def(AST_Binary, function(compressor) {
             return this.left.has_side_effects(compressor)
                 || this.right.has_side_effects(compressor)
@@ -5627,36 +5638,53 @@ merge(Compressor.prototype, {
             }
         });
         def(AST_Call, function(compressor, first_in_statement) {
-            if (!this.is_expr_pure(compressor)) {
-                var exp = this.expression;
-                if (this.is_call_pure(compressor)) {
-                    var exprs = this.args.slice();
-                    exprs.unshift(exp.expression);
-                    exprs = trim(exprs, compressor, first_in_statement);
-                    return exprs && make_sequence(this, exprs);
-                }
-                if (exp instanceof AST_Function) {
-                    if (exp.name) {
-                        var def = exp.name.definition();
-                        if (def.references.length > def.replaced) return this;
-                    }
-                    exp.process_expression(false, function(node) {
-                        var value = node.value && node.value.drop_side_effect_free(compressor, true);
-                        return value ? make_node(AST_SimpleStatement, node, {
-                            body: value
-                        }) : make_node(AST_EmptyStatement, node);
-                    });
-                    scan_local_returns(exp, function(node) {
-                        if (node.value) node.value = node.value.drop_side_effect_free(compressor);
+            var self = this;
+            if (self.is_expr_pure(compressor)) {
+                if (self.pure) AST_Node.warn("Dropping __PURE__ call [{file}:{line},{col}]", self.start);
+                var args = trim(self.args, compressor, first_in_statement);
+                return args && make_sequence(self, args);
+            }
+            var exp = self.expression;
+            if (self.is_call_pure(compressor)) {
+                var exprs = self.args.slice();
+                exprs.unshift(exp.expression);
+                exprs = trim(exprs, compressor, first_in_statement);
+                return exprs && make_sequence(self, exprs);
+            }
+            var def;
+            if (exp instanceof AST_Function
+                && !(exp.name && (def = exp.name.definition()).references.length > def.replaced)) {
+                exp.process_expression(false, function(node) {
+                    var value = node.value && node.value.drop_side_effect_free(compressor, true);
+                    return value ? make_node(AST_SimpleStatement, node, {
+                        body: value
+                    }) : make_node(AST_EmptyStatement, node);
+                });
+                scan_local_returns(exp, function(node) {
+                    if (node.value) node.value = node.value.drop_side_effect_free(compressor);
+                });
+                // always shallow clone to ensure stripping of negated IIFEs
+                self = self.clone();
+            }
+            if (self instanceof AST_New) {
+                var fn = exp;
+                if (fn instanceof AST_SymbolRef) fn = fn.fixed_value();
+                if (fn instanceof AST_Lambda) {
+                    fn.new = true;
+                    var assign_this_only = all(fn.body, function(stat) {
+                        return !stat.has_side_effects(compressor);
                     });
-                    // always shallow clone to ensure stripping of negated IIFEs
-                    return this.clone();
+                    delete fn.new;
+                    if (assign_this_only) {
+                        var exprs = self.args.slice();
+                        exprs.unshift(exp);
+                        exprs = trim(exprs, compressor, first_in_statement);
+                        return exprs && make_sequence(self, exprs);
+                    }
+                    if (!fn.contains_this()) return make_node(AST_Call, self, self);
                 }
-                return this;
             }
-            if (this.pure) AST_Node.warn("Dropping __PURE__ call [{file}:{line},{col}]", this.start);
-            var args = trim(this.args, compressor, first_in_statement);
-            return args && make_sequence(this, args);
+            return self;
         });
         def(AST_Conditional, function(compressor) {
             var consequent = this.consequent.drop_side_effect_free(compressor);
index 169dcd1..43f08b4 100644 (file)
@@ -1123,11 +1123,7 @@ new_this: {
             }
         }.f(42);
     }
-    expect: {
-        new function(a) {
-            this.a = a;
-        }(42);
-    }
+    expect: {}
 }
 
 issue_2513: {
index 0746a56..3c53dd2 100644 (file)
@@ -416,3 +416,20 @@ issue_4008: {
         "PASS",
     ]
 }
+
+trim_new: {
+    options = {
+        side_effects: true,
+    }
+    input: {
+        new function(a) {
+            console.log(a);
+        }("PASS");
+    }
+    expect: {
+        (function(a) {
+            console.log(a);
+        })("PASS");
+    }
+    expect_stdout: "PASS"
+}
index 33efadb..2e847e1 100644 (file)
@@ -1,2 +1,2 @@
-new function(){console.log(3)};
-//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSJ9
+console.log(3);
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSJ9
index 33efadb..2e847e1 100644 (file)
@@ -1,2 +1,2 @@
-new function(){console.log(3)};
-//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUErQyxJQUFyQyxXQUFnQkEsUUFBUUMsSUFBSSJ9
+console.log(3);
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSJ9