enhance `side_effects` (#3410)
authorAlex Lam S.L <alexlamsl@gmail.com>
Mon, 13 May 2019 21:26:40 +0000 (05:26 +0800)
committerGitHub <noreply@github.com>
Mon, 13 May 2019 21:26:40 +0000 (05:26 +0800)
lib/compress.js
test/compress/loops.js
test/compress/pure_getters.js

index 57df130..71f2eae 100644 (file)
@@ -347,6 +347,12 @@ merge(Compressor.prototype, {
         }
     }
 
+    function is_arguments(def) {
+        if (def.name != "arguments") return false;
+        var orig = def.orig;
+        return orig.length == 1 && orig[0] instanceof AST_SymbolFunarg;
+    }
+
     (function(def) {
         def(AST_Node, noop);
 
@@ -444,9 +450,8 @@ merge(Compressor.prototype, {
             if (def.single_use == "m") return false;
             if (tw.safe_ids[def.id]) {
                 if (def.fixed == null) {
-                    var orig = def.orig[0];
-                    if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false;
-                    def.fixed = make_node(AST_Undefined, orig);
+                    if (is_arguments(def)) return false;
+                    def.fixed = make_node(AST_Undefined, def.orig);
                 }
                 return true;
             }
@@ -522,7 +527,9 @@ merge(Compressor.prototype, {
             if (!(node instanceof AST_Sub)) return;
             var expr = node.expression;
             var prop = node.property;
-            if (expr instanceof AST_SymbolRef && expr.name == "arguments" && prop instanceof AST_Number) {
+            if (expr instanceof AST_SymbolRef
+                && is_arguments(expr.definition())
+                && prop instanceof AST_Number) {
                 expr.definition().reassigned = true;
             }
         }
@@ -791,7 +798,7 @@ merge(Compressor.prototype, {
         });
         def(AST_Unary, function(tw, descend) {
             var node = this;
-            if (node.operator != "++" && node.operator != "--") return;
+            if (!unary_arithmetic[node.operator]) return;
             var exp = node.expression;
             if (!(exp instanceof AST_SymbolRef)) {
                 mark_assignment_to_arguments(exp);
@@ -1437,7 +1444,7 @@ merge(Compressor.prototype, {
                     extract_candidates(expr.expression);
                     expr.body.forEach(extract_candidates);
                 } else if (expr instanceof AST_Unary) {
-                    if (expr.operator == "++" || expr.operator == "--") {
+                    if (unary_arithmetic[expr.operator]) {
                         candidates.push(hit_stack.slice());
                     } else {
                         extract_candidates(expr.expression);
@@ -1507,9 +1514,9 @@ merge(Compressor.prototype, {
             function mangleable_var(var_def) {
                 var value = var_def.value;
                 if (!(value instanceof AST_SymbolRef)) return;
-                if (value.name == "arguments") return;
                 var def = value.definition();
                 if (def.undeclared) return;
+                if (is_arguments(def)) return;
                 return value_def = def;
             }
 
@@ -2313,6 +2320,7 @@ merge(Compressor.prototype, {
             if (!is_strict(compressor)) return false;
             if (is_undeclared_ref(this) && this.is_declared(compressor)) return false;
             if (this.is_immutable()) return false;
+            if (is_arguments(this.definition())) return false;
             var fixed = this.fixed_value();
             if (!fixed) return true;
             this._dot_throw = return_true;
@@ -2555,6 +2563,7 @@ merge(Compressor.prototype, {
     });
 
     var lazy_op = makePredicate("&& ||");
+    var unary_arithmetic = makePredicate("++ --");
     var unary_side_effects = makePredicate("delete ++ --");
 
     function is_lhs(node, parent) {
@@ -4412,8 +4421,9 @@ merge(Compressor.prototype, {
 
     OPT(AST_For, function(self, compressor) {
         if (!compressor.option("loops")) return self;
-        if (compressor.option("side_effects") && self.init) {
-            self.init = self.init.drop_side_effect_free(compressor);
+        if (compressor.option("side_effects")) {
+            if (self.init) self.init = self.init.drop_side_effect_free(compressor);
+            if (self.step) self.step = self.step.drop_side_effect_free(compressor);
         }
         if (self.condition) {
             var cond = self.condition.evaluate(compressor);
@@ -6644,8 +6654,7 @@ merge(Compressor.prototype, {
         var fn;
         if (compressor.option("arguments")
             && expr instanceof AST_SymbolRef
-            && expr.name == "arguments"
-            && expr.definition().orig.length == 1
+            && is_arguments(expr.definition())
             && prop instanceof AST_Number
             && (fn = expr.scope) === compressor.find_parent(AST_Lambda)) {
             var index = prop.getValue();
index 137fd9d..d835080 100644 (file)
@@ -673,3 +673,19 @@ issue_3371: {
     }
     expect_stdout: "PASS"
 }
+
+step: {
+    options = {
+        loops: true,
+        side_effects: true,
+    }
+    input: {
+        for (var i = 0; i < 42; "foo", i++, "bar");
+        console.log(i);
+    }
+    expect: {
+        for (var i = 0; i < 42; i++);
+        console.log(i);
+    }
+    expect_stdout: "42"
+}
index 61ce8a9..b6e42f9 100644 (file)
@@ -1161,3 +1161,29 @@ collapse_rhs_lhs: {
     }
     expect_stdout: "1 3"
 }
+
+drop_arguments: {
+    options = {
+        pure_getters: "strict",
+        side_effects: true,
+    }
+    input: {
+        (function() {
+            arguments.slice = function() {
+                console.log("PASS");
+            };
+            arguments[42];
+            arguments.length;
+            arguments.slice();
+        })();
+    }
+    expect: {
+        (function() {
+            arguments.slice = function() {
+                console.log("PASS");
+            };
+            arguments.slice();
+        })();
+    }
+    expect_stdout: "PASS"
+}