enhance `reduce_vars` (#4088)
authorAlex Lam S.L <alexlamsl@gmail.com>
Wed, 2 Sep 2020 03:30:46 +0000 (04:30 +0100)
committerGitHub <noreply@github.com>
Wed, 2 Sep 2020 03:30:46 +0000 (11:30 +0800)
lib/compress.js

index 2c21217..6761c24 100644 (file)
@@ -325,22 +325,22 @@ merge(Compressor.prototype, {
         }
         var lhs = is_lhs(node, parent);
         if (lhs) return lhs;
-        if (!immutable
-            && parent instanceof AST_Call
-            && parent.expression === node
-            && !parent.is_expr_pure(compressor)
-            && (!(value instanceof AST_Function)
-                || !(parent instanceof AST_New) && value.contains_this())) {
-            return true;
-        }
-        if (parent instanceof AST_Array) {
-            return is_modified(compressor, tw, parent, parent, level + 1);
-        }
-        if (parent instanceof AST_ObjectKeyVal && node === parent.value) {
+        if (parent instanceof AST_Array) return is_modified(compressor, tw, parent, parent, level + 1);
+        if (parent instanceof AST_Call) {
+            return !immutable
+                && parent.expression === node
+                && !parent.is_expr_pure(compressor)
+                && (!(value instanceof AST_Function)
+                    || !(parent instanceof AST_New) && value.contains_this());
+        }
+        if (parent instanceof AST_ForIn) return parent.init === node;
+        if (parent instanceof AST_ObjectKeyVal) {
+            if (parent.value !== node) return;
             var obj = tw.parent(level + 1);
             return is_modified(compressor, tw, obj, obj, level + 2);
         }
-        if (parent instanceof AST_PropAccess && parent.expression === node) {
+        if (parent instanceof AST_PropAccess) {
+            if (parent.expression !== node) return;
             var prop = read_property(value, parent);
             return (!immutable || recursive) && is_modified(compressor, tw, parent, prop, level + 1);
         }
@@ -514,33 +514,41 @@ merge(Compressor.prototype, {
                 || value instanceof AST_This;
         }
 
+        function has_escaped(d, node, parent) {
+            if (parent instanceof AST_Assign) return parent.operator == "=" && parent.right === node;
+            if (parent instanceof AST_Call) return parent.expression !== node || parent instanceof AST_New;
+            if (parent instanceof AST_Exit) return parent.value === node && node.scope !== d.scope;
+            if (parent instanceof AST_VarDef) return parent.value === node;
+        }
+
+        function value_in_use(node, parent) {
+            if (parent instanceof AST_Array) return true;
+            if (parent instanceof AST_Binary) return lazy_op[parent.operator];
+            if (parent instanceof AST_Conditional) return parent.condition !== node;
+            if (parent instanceof AST_Sequence) return parent.tail_node() === node;
+        }
+
         function mark_escaped(tw, d, scope, node, value, level, depth) {
             var parent = tw.parent(level);
             if (value && value.is_constant()) return;
-            if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
-                || parent instanceof AST_Call && (node !== parent.expression || parent instanceof AST_New)
-                || parent instanceof AST_Exit && node === parent.value && node.scope !== d.scope
-                || parent instanceof AST_VarDef && node === parent.value) {
+            if (has_escaped(d, node, parent)) {
                 d.escaped.push(parent);
                 if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1;
                 if (!d.escaped.depth || d.escaped.depth > depth) d.escaped.depth = depth;
                 return;
-            } else if (parent instanceof AST_Array
-                || parent instanceof AST_Binary && lazy_op[parent.operator]
-                || parent instanceof AST_Conditional && node !== parent.condition
-                || parent instanceof AST_Sequence && node === parent.tail_node()) {
+            } else if (value_in_use(node, parent)) {
                 mark_escaped(tw, d, scope, parent, parent, level + 1, depth);
-            } else if (parent instanceof AST_ObjectKeyVal && node === parent.value) {
+            } else if (parent instanceof AST_ObjectKeyVal && parent.value === node) {
                 var obj = tw.parent(level + 1);
                 mark_escaped(tw, d, scope, obj, obj, level + 2, depth);
-            } else if (parent instanceof AST_PropAccess && node === parent.expression) {
+            } else if (parent instanceof AST_PropAccess && parent.expression === node) {
                 value = read_property(value, parent);
                 mark_escaped(tw, d, scope, parent, value, level + 1, depth + 1);
                 if (value) return;
             }
             if (level > 0) return;
-            if (parent instanceof AST_Call && node === parent.expression) return;
-            if (parent instanceof AST_Sequence && node !== parent.tail_node()) return;
+            if (parent instanceof AST_Call && parent.expression === node) return;
+            if (parent instanceof AST_Sequence && parent.tail_node() !== node) return;
             if (parent instanceof AST_SimpleStatement) return;
             if (parent instanceof AST_Unary && !unary_side_effects[parent.operator]) return;
             d.direct_access = true;
@@ -739,13 +747,11 @@ merge(Compressor.prototype, {
             push(tw);
             var init = this.init;
             init.walk(tw);
-            if (init instanceof AST_Var) {
-                init = init.definitions[0].name;
-            } else while (init instanceof AST_PropAccess) {
-                init = init.expression.tail_node();
+            if (init instanceof AST_SymbolRef) {
+                init.definition().fixed = false;
+            } else if (init instanceof AST_Var) {
+                init.definitions[0].name.definition().fixed = false;
             }
-            var def = init.definition();
-            if (def) def.fixed = false;
             this.body.walk(tw);
             pop(tw);
             tw.in_loop = saved_loop;