enhance `hoist_props` & `reduce_vars` (#5183)
authorAlex Lam S.L <alexlamsl@gmail.com>
Mon, 22 Nov 2021 16:31:10 +0000 (16:31 +0000)
committerGitHub <noreply@github.com>
Mon, 22 Nov 2021 16:31:10 +0000 (00:31 +0800)
closes #5182

lib/compress.js
test/compress/hoist_props.js
test/compress/varify.js

index 1f2af1f..f59a996 100644 (file)
@@ -703,6 +703,7 @@ merge(Compressor.prototype, {
                 if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1;
                 if (!d.escaped.depth || d.escaped.depth > depth) d.escaped.depth = depth;
                 if (d.scope.resolve() !== scope.resolve()) d.escaped.cross_scope = true;
+                if (d.fixed) d.fixed.escaped = d.escaped;
                 return;
             } else if (value_in_use(node, parent)) {
                 mark_escaped(tw, d, scope, parent, parent, level + 1, depth);
@@ -720,6 +721,7 @@ merge(Compressor.prototype, {
             if (parent instanceof AST_SimpleStatement) return;
             if (parent instanceof AST_Unary && !unary_side_effects[parent.operator]) return;
             d.direct_access = true;
+            if (d.fixed) d.fixed.direct_access = true;
         }
 
         function mark_assignment_to_arguments(node) {
@@ -1000,9 +1002,9 @@ merge(Compressor.prototype, {
                             d.single_use = false;
                         }
                         tw.loop_ids[d.id] = tw.in_loop;
-                        mark_escaped(tw, d, sym.scope, node, right, 0, 1);
                         sym.fixed = d.fixed = fixed;
                         sym.fixed.assigns = [ node ];
+                        mark_escaped(tw, d, sym.scope, node, right, 0, 1);
                     }
                 });
             }
@@ -7678,6 +7680,7 @@ merge(Compressor.prototype, {
                         right: prop.value,
                     }));
                 });
+                defs.value = node.right;
                 defs_by_id[node.left.definition().id] = defs;
                 self.body.splice(self.body.indexOf(this.stack[1]) + 1, 0, make_node(AST_Var, node, {
                     definitions: decls,
@@ -7690,12 +7693,16 @@ merge(Compressor.prototype, {
                 descend(node, this);
                 var defs = new Dictionary();
                 var var_defs = [];
+                var decl = node.clone();
+                decl.value = node.name instanceof AST_SymbolConst ? make_node(AST_Number, node, { value: 0 }) : null;
+                var_defs.push(decl);
                 node.value.properties.forEach(function(prop) {
                     var_defs.push(make_node(AST_VarDef, node, {
                         name: make_sym(node.name.CTOR, node.name, prop.key),
                         value: prop.value,
                     }));
                 });
+                defs.value = node.value;
                 defs_by_id[node.name.definition().id] = defs;
                 return List.splice(var_defs);
             }
@@ -7711,6 +7718,7 @@ merge(Compressor.prototype, {
                 if (!(node.expression instanceof AST_SymbolRef)) return;
                 var defs = defs_by_id[node.expression.definition().id];
                 if (!defs) return;
+                if (node.expression.fixed_value() !== defs.value) return;
                 var def = defs.get(node.get_property());
                 var sym = make_node(AST_SymbolRef, node, {
                     name: def.name,
@@ -7721,7 +7729,9 @@ merge(Compressor.prototype, {
                 return sym;
             }
             if (node instanceof AST_SymbolRef) {
-                if (!(node.definition().id in defs_by_id)) return;
+                var defs = defs_by_id[node.definition().id];
+                if (!defs) return;
+                if (node.fixed_value() !== defs.value) return;
                 return make_node(AST_Object, node, { properties: [] });
             }
         }));
@@ -7730,18 +7740,16 @@ merge(Compressor.prototype, {
             if (!(sym instanceof AST_Symbol)) return;
             var def = sym.definition();
             if (def.assignments != count) return;
-            if (def.direct_access) return;
-            if (def.escaped.depth == 1) return;
             if (def.references.length - def.replaced == count) return;
             if (def.single_use) return;
             if (top_retain(def)) return;
             if (sym.fixed_value() !== right) return;
+            var fixed = sym.fixed || def.fixed;
+            if (fixed.direct_access) return;
+            if (fixed.escaped && fixed.escaped.depth == 1) return;
             return right instanceof AST_Object
                 && right.properties.length > 0
                 && all(right.properties, can_hoist_property)
-                && all(def.references, function(ref) {
-                    return ref.fixed_value() === right;
-                })
                 && can_drop_symbol(sym, compressor);
         }
     });
index 2b4abff..ab9a16f 100644 (file)
@@ -217,7 +217,8 @@ name_collision_1: {
         var obj_foo = 1;
         var obj_bar = 2;
         function f() {
-            var obj_foo$0 = 3,
+            var obj,
+                obj_foo$0 = 3,
                 obj_bar = 4,
                 obj_b_r = 5,
                 obj_b_r$0 = 6,
@@ -249,7 +250,8 @@ name_collision_2: {
         console.log(o.p === o.p, o["+"](4), o["-"](5), o__$0, o__$1);
     }
     expect: {
-        var o_p = 1,
+        var o,
+            o_p = 1,
             o__ = function(x) {
                 return x;
             },
@@ -283,7 +285,8 @@ name_collision_3: {
         console.log(o.p === o.p, o["+"](4), o["-"](5));
     }
     expect: {
-        var o_p = 1,
+        var o,
+            o_p = 1,
             o__ = function(x) {
                 return x;
             },
@@ -315,7 +318,7 @@ name_collision_4: {
     }
     expect: {
         console.log(function() {
-            var o_p$0 = 0, o_q = "PASS";
+            var o, o_p$0 = 0, o_q = "PASS";
             return function(o_p) {
                 if (!o_p$0) return o_p;
             }(o_q);
@@ -768,7 +771,7 @@ issue_3046: {
     expect: {
         console.log(function(a) {
             do {
-                var b_c = a++;
+                var b, b_c = a++;
             } while (b_c && a);
             return a;
         }(0));
@@ -931,7 +934,7 @@ issue_3411: {
     expect: {
         var c = 1;
         !function f() {
-            var o_p = --c && f();
+            var o, o_p = --c && f();
             +{} || console.log("PASS");
         }();
     }
@@ -1042,9 +1045,7 @@ issue_3945_1: {
     expect: {
         function f() {
             o.p;
-            var o = {
-                q: 0,
-            };
+            var o, o_q = 0;
         }
     }
 }
@@ -1063,9 +1064,7 @@ issue_3945_2: {
     }
     expect: {
         console.log(typeof o);
-        var o = {
-            p: 0,
-        };
+        var o, o_p = 0;
     }
     expect_stdout: "undefined"
 }
@@ -1134,10 +1133,46 @@ issue_4985: {
         }());
     }
     expect: {
-        var a_p = 42;
+        var a, a_p = 42;
         console.log(function() {
             ({});
         }());
     }
     expect_stdout: "undefined"
 }
+
+issue_5182: {
+    options = {
+        hoist_props: true,
+        merge_vars: true,
+        passes: 2,
+        reduce_vars: true,
+        side_effects: true,
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        var o = console;
+        log = o.log;
+        o = {
+            p: function(a) {
+                console.log(a ? "PASS" : "FAIL");
+                return a;
+            },
+        };
+        log(o.p(42));
+    }
+    expect: {
+        var o_p = console;
+        log = o_p.log;
+        o_p = function(a) {
+            console.log(a ? "PASS" : "FAIL");
+            return a;
+        };
+        log(o_p(42));
+    }
+    expect_stdout: [
+        "PASS",
+        "42",
+    ]
+}
index d8b2bb4..4a90a95 100644 (file)
@@ -111,7 +111,7 @@ hoist_props_const: {
         }
     }
     expect: {
-        var o_p = "PASS";
+        var o = 0, o_p = "PASS";
         console.log(o_p);
     }
     expect_stdout: "PASS"
@@ -136,7 +136,7 @@ hoist_props_let: {
     }
     expect: {
         "use strict";
-        var o_p = "PASS";
+        var o, o_p = "PASS";
         console.log(o_p);
     }
     expect_stdout: "PASS"