fix corner case with `nameCache` (#3338)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 14 Mar 2019 17:15:50 +0000 (01:15 +0800)
committerGitHub <noreply@github.com>
Thu, 14 Mar 2019 17:15:50 +0000 (01:15 +0800)
fixes #3301

lib/scope.js
test/mocha/minify.js

index c88ce8f..5e11441 100644 (file)
@@ -309,8 +309,12 @@ function names_in_use(scope, options) {
     if (!names) {
         scope.names_in_use = names = Object.create(scope.mangled_names || null);
         scope.cname_holes = [];
+        var cache = options.cache && options.cache.props;
         scope.enclosed.forEach(function(def) {
             if (def.unmangleable(options)) names[def.name] = true;
+            if (def.global && cache && cache.has(def.name)) {
+                names[cache.get(def.name)] = true;
+            }
         });
     }
     return names;
index 6e6c7a7..d11f40f 100644 (file)
@@ -87,7 +87,7 @@ describe("minify", function() {
         assert.strictEqual(run_code(compressed), run_code(original));
     });
 
-    it("Should avoid mangled names in cache", function() {
+    it("Should avoid cached names when mangling top-level variables", function() {
         var cache = {};
         var original = "";
         var compressed = "";
@@ -116,6 +116,30 @@ describe("minify", function() {
         assert.strictEqual(run_code(compressed), run_code(original));
     });
 
+    it("Should avoid cached names when mangling inner-scoped variables", function() {
+        var cache = {};
+        var original = "";
+        var compressed = "";
+        [
+            'var extend = function(a, b) { console.log("extend"); a(); b(); }; function A() { console.log("A"); };',
+            'var B = function(A) { function B() { console.log("B") }; extend(B, A); return B; }(A);',
+        ].forEach(function(code) {
+            var result = UglifyJS.minify(code, {
+                compress: false,
+                nameCache: cache,
+                toplevel: true,
+            });
+            if (result.error) throw result.error;
+            original += code;
+            compressed += result.code;
+        });
+        assert.strictEqual(compressed, [
+            'var o=function(o,n){console.log("extend");o();n()};function n(){console.log("A")}',
+            'var e=function(n){function e(){console.log("B")}o(e,n);return e}(n);',
+        ].join(""));
+        assert.strictEqual(run_code(compressed), run_code(original));
+    });
+
     it("Should not parse invalid use of reserved words", function() {
         assert.strictEqual(UglifyJS.minify("function enum(){}").error, undefined);
         assert.strictEqual(UglifyJS.minify("function static(){}").error, undefined);