fix corner case in `functions` (#3930)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 28 May 2020 12:07:36 +0000 (13:07 +0100)
committerGitHub <noreply@github.com>
Thu, 28 May 2020 12:07:36 +0000 (20:07 +0800)
fixes #3929

lib/compress.js
test/compress/functions.js

index cc2d1ec..9ddbfa4 100644 (file)
@@ -4360,7 +4360,7 @@ merge(Compressor.prototype, {
                         if (def.value && indexOf_assign(sym, def) < 0) {
                             def.value = def.value.drop_side_effect_free(compressor);
                         }
-                        var var_defs = var_defs_by_id.get(sym.id);
+                        var old_def, var_defs = var_defs_by_id.get(sym.id);
                         if (!def.value) {
                             if (var_defs.length > 1) {
                                 AST_Node.warn("Dropping duplicated declaration of variable {name} [{file}:{line},{col}]", template(def.name));
@@ -4375,23 +4375,23 @@ merge(Compressor.prototype, {
                             && sym.assignments == 0
                             && def.value === def.name.fixed_value()
                             && def.value instanceof AST_Function
-                            && !(def.value.name && def.value.name.definition().assignments)
+                            && (!def.value.name || (old_def = def.value.name.definition()).assignments == 0
+                                && (old_def.name == def.name.name || all(old_def.references, function(ref) {
+                                    return ref.scope.find_variable(def.name) === def.name.definition();
+                                })))
                             && can_rename(def.value, def.name.name)
                             && (!compressor.has_directive("use strict") || parent instanceof AST_Scope)) {
                             AST_Node.warn("Declaring {name} as function [{file}:{line},{col}]", template(def.name));
                             var defun = make_node(AST_Defun, def, def.value);
                             defun.name = make_node(AST_SymbolDefun, def.name, def.name);
                             var name_def = def.name.scope.resolve().def_function(defun.name);
-                            if (def.value.name) {
-                                var old_def = def.value.name.definition();
-                                def.value.walk(new TreeWalker(function(node) {
-                                    if (node instanceof AST_SymbolRef && node.definition() === old_def) {
-                                        node.name = name_def.name;
-                                        node.thedef = name_def;
-                                        node.reference({});
-                                    }
-                                }));
-                            }
+                            if (old_def) def.value.walk(new TreeWalker(function(node) {
+                                if (node instanceof AST_SymbolRef && node.definition() === old_def) {
+                                    node.name = name_def.name;
+                                    node.thedef = name_def;
+                                    node.reference({});
+                                }
+                            }));
                             body.push(defun);
                         } else {
                             if (var_defs.length > 1 && sym.orig.indexOf(def.name) > sym.eliminated) {
index 7ad6ff0..9607c59 100644 (file)
@@ -4705,3 +4705,44 @@ issue_3911: {
     }
     expect_stdout: "PASS"
 }
+
+issue_3929: {
+    options = {
+        functions: true,
+        reduce_vars: true,
+        unused: true,
+    }
+    input: {
+        (function() {
+            var abc = function f() {
+                (function() {
+                    switch (f) {
+                    default:
+                        var abc = 0;
+                    case 0:
+                        abc.p;
+                    }
+                    console.log(typeof f);
+                })();
+            };
+            typeof abc && abc();
+        })();
+    }
+    expect: {
+        (function() {
+            var abc = function f() {
+                (function() {
+                    switch (f) {
+                    default:
+                        var abc = 0;
+                    case 0:
+                        abc.p;
+                    }
+                    console.log(typeof f);
+                })();
+            };
+            typeof abc && abc();
+        })();
+    }
+    expect_stdout: "function"
+}