diff --git a/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js b/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js index 0eab4a8cc..cefc465a7 100644 --- a/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js +++ b/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js @@ -1129,4 +1129,24 @@ describe("mangle-names", () => { `); expect(transform(source)).toBe(expected); }); + + it("should fix issue#365 - classDeclaration with unsafe parent scope", () => { + const source = unpad(` + function foo() { + eval(""); + class A {} + class B {} + } + `); + expect(transform(source)).toBe(source); + }); + + it("should fix classDeclaration with unsafe program scope", () => { + const source = unpad(` + eval(""); + class A {} + class B {} + `); + expect(transform(source, { topLevel: true })).toBe(source); + }); }); diff --git a/packages/babel-plugin-minify-mangle-names/src/index.js b/packages/babel-plugin-minify-mangle-names/src/index.js index 26e650bf6..a75108681 100644 --- a/packages/babel-plugin-minify-mangle-names/src/index.js +++ b/packages/babel-plugin-minify-mangle-names/src/index.js @@ -93,7 +93,16 @@ module.exports = ({ types: t, traverse }) => { Scopable(path) { const {scope} = path; - if (!mangler.eval && hasEval(scope)) return; + if (!mangler.eval) { + if (hasEval(scope)) return; + + // ClassDeclaration has binding in two scopes + // 1. The scope in which it is declared + // 2. The class's own scope + // So, when the scope.1 is an unsafeScope, mangling happens in scope.2 + // To avoid that, we check if it's a class declaration + if (path.isClassDeclaration() && hasEval(path.parentPath.scope)) return; + } if (mangler.visitedScopes.has(scope)) return; mangler.visitedScopes.add(scope); @@ -170,7 +179,11 @@ module.exports = ({ types: t, traverse }) => { if (isTopLevel) { mangler.rename(mangler.program.scope, oldName, next); } + // mark the binding as renamed + // this is redundant and exists to work around a bug in babel + // ClassDeclarations have binding in two scopes + // - https://github.com/babel/babel/issues/5156 binding.renamed = true; } }