preserve non-constant value assignments with modifications (#2997)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 13 Mar 2018 09:35:34 +0000 (17:35 +0800)
committerGitHub <noreply@github.com>
Tue, 13 Mar 2018 09:35:34 +0000 (17:35 +0800)
fixes #2995

lib/compress.js
test/compress/drop-unused.js

index 1b52f83..cacffd3 100644 (file)
@@ -3114,6 +3114,8 @@ merge(Compressor.prototype, {
         var in_use = [];
         var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
         var fixed_ids = Object.create(null);
+        var value_read = Object.create(null);
+        var value_modified = Object.create(null);
         if (self instanceof AST_Toplevel && compressor.top_retain) {
             self.variables.each(function(def) {
                 if (compressor.top_retain(def) && !(def.id in in_use_ids)) {
@@ -3381,6 +3383,17 @@ merge(Compressor.prototype, {
         );
         self.transform(tt);
 
+        function verify_safe_usage(def, read, modified) {
+            if (def.id in in_use_ids) return;
+            if (read && modified) {
+                in_use_ids[def.id] = true;
+                in_use.push(def);
+            } else {
+                value_read[def.id] = read;
+                value_modified[def.id] = modified;
+            }
+        }
+
         function scan_ref_scoped(node, descend) {
             var node_def, props = [], sym = assign_as_unused(node, props);
             if (sym instanceof AST_SymbolRef
@@ -3390,8 +3403,18 @@ merge(Compressor.prototype, {
                 });
                 if (node instanceof AST_Assign) {
                     node.right.walk(tw);
-                    if (node.left === sym && !node_def.chained && sym.fixed_value() === node.right) {
-                        fixed_ids[node_def.id] = node;
+                    if (node.left === sym) {
+                        if (!node_def.chained && sym.fixed_value() === node.right) {
+                            fixed_ids[node_def.id] = node;
+                        }
+                        if (!node.write_only) {
+                            verify_safe_usage(node_def, true, value_modified[node_def.id]);
+                        }
+                    } else {
+                        var fixed = sym.fixed_value();
+                        if (!fixed || !fixed.is_constant()) {
+                            verify_safe_usage(node_def, value_read[node_def.id], true);
+                        }
                     }
                 }
                 return true;
index ee8e6c0..301bff1 100644 (file)
@@ -1785,3 +1785,32 @@ issue_805_2: {
         "bar",
     ]
 }
+
+issue_2995: {
+    options = {
+        pure_getters: "strict",
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        function f(a) {
+            var b;
+            a.b = b = function() {};
+            b.c = "PASS";
+        }
+        var o = {};
+        f(o);
+        console.log(o.b.c);
+    }
+    expect: {
+        function f(a) {
+            var b;
+            a.b = b = function() {};
+            b.c = "PASS";
+        }
+        var o = {};
+        f(o);
+        console.log(o.b.c);
+    }
+    expect_stdout: "PASS"
+}