fix corner case with lexical variables (#5244)
authorAlex Lam S.L <alexlamsl@gmail.com>
Wed, 29 Dec 2021 21:15:53 +0000 (21:15 +0000)
committerGitHub <noreply@github.com>
Wed, 29 Dec 2021 21:15:53 +0000 (05:15 +0800)
lib/scope.js
test/compress/let.js

index 89c6671..a0b7c64 100644 (file)
@@ -214,10 +214,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
         } else if (node instanceof AST_SymbolDefun) {
             var def = defun.def_function(node, tw.parent());
             if (exported) def.exported = true;
-            entangle(defun, scope);
         } else if (node instanceof AST_SymbolFunarg) {
             defun.def_variable(node);
-            entangle(defun, scope);
         } else if (node instanceof AST_SymbolLambda) {
             var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
             if (options.ie) def.defun = defun.parent_scope.resolve();
@@ -227,7 +225,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
         } else if (node instanceof AST_SymbolVar) {
             var def = defun.def_variable(node, node instanceof AST_SymbolImport ? undefined : null);
             if (exported) def.exported = true;
-            entangle(defun, scope);
         }
 
         function walk_scope(descend) {
@@ -240,16 +237,6 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
             scope = save_scope;
             defun = save_defun;
         }
-
-        function entangle(defun, scope) {
-            if (defun === scope) return;
-            node.mark_enclosed(options);
-            var def = scope.find_variable(node.name);
-            if (node.thedef === def) return;
-            node.thedef = def;
-            def.orig.push(node);
-            node.mark_enclosed(options);
-        }
     });
     self.make_def = function(orig, init) {
         return new SymbolDef(++next_def_id, this, orig, init);
@@ -270,6 +257,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
         }
         if (node instanceof AST_Lambda) {
             in_arg.push(node);
+            if (node.name) node.name.walk(tw);
             node.argnames.forEach(function(argname) {
                 argname.walk(tw);
             });
@@ -296,6 +284,16 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
                 // ensure compression works if `const` reuses a scope variable
                 var redef = def.redefined();
                 if (redef) redef.const_redefs = true;
+            } else if (def.scope !== node.scope && (node instanceof AST_SymbolDefun
+                || node instanceof AST_SymbolFunarg
+                || node instanceof AST_SymbolVar)) {
+                node.mark_enclosed(options);
+                var redef = node.scope.find_variable(node.name);
+                if (node.thedef !== redef) {
+                    node.thedef = redef;
+                    redef.orig.push(node);
+                    node.mark_enclosed(options);
+                }
             }
             if (node.name != "arguments") return true;
             var parent = node instanceof AST_SymbolVar && tw.parent();
index 629119e..3f4f75d 100644 (file)
@@ -1,4 +1,4 @@
-retain_block: {
+retain_block_1: {
     options = {}
     input: {
         "use strict";
@@ -20,6 +20,94 @@ retain_block: {
     node_version: ">=4"
 }
 
+retain_block_2: {
+    options = {
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        "use strict";
+        {
+            var a;
+            let a;
+        }
+    }
+    expect: {
+        "use strict";
+        {
+            var a;
+            let a;
+        }
+    }
+    expect_stdout: true
+    node_version: ">=4"
+}
+
+retain_block_2_mangle: {
+    rename = true
+    mangle = {
+        toplevel: true,
+    }
+    input: {
+        "use strict";
+        {
+            var a;
+            let a;
+        }
+    }
+    expect: {
+        "use strict";
+        {
+            var t;
+            let t;
+        }
+    }
+}
+
+retain_block_3: {
+    options = {
+        toplevel: true,
+        unused: true,
+    }
+    input: {
+        "use strict";
+        {
+            let a;
+            var a;
+        }
+    }
+    expect: {
+        "use strict";
+        {
+            let a;
+            var a;
+        }
+    }
+    expect_stdout: true
+    node_version: ">=4"
+}
+
+retain_block_3_mangle: {
+    rename = true
+    mangle = {
+        toplevel: true,
+    }
+    input: {
+        "use strict";
+        {
+            let a;
+            var a;
+        }
+    }
+    expect: {
+        "use strict";
+        {
+            let t;
+            var t;
+        }
+    }
+}
+
 retain_assignment: {
     options = {
         dead_code: true,