From 16d371300c4240fa6831c0f7cf28325418838035 Mon Sep 17 00:00:00 2001 From: Boopathi Rajaa Date: Sun, 13 May 2018 22:31:54 +0200 Subject: [PATCH] fix(mangle): handle inferred names for functions The t.NOT_LOCAL_BINDING symbol used in plugin-function-name (https://github.com/babel/babel/blob/bd98041321c60737ddcacd1ad7e056ef6de31879/packages/babel-helper-function-name/src/index.js#L206) is causing this issue. This was added in babel/babel#3298 The problem is the binding identifier is NOT registered (skipped) during crawl and the mangler finds the first safe identifier which ultimately collides with this name during runtime. So, we register the binding and don't respect the t.NOT_LOCAL_BINDING. Fix #829 --- .../src/index.js | 23 ++++++++ .../__tests__/minify-env-tests.js | 55 +++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/packages/babel-plugin-minify-mangle-names/src/index.js b/packages/babel-plugin-minify-mangle-names/src/index.js index 1b20fc8e5..9830779bb 100644 --- a/packages/babel-plugin-minify-mangle-names/src/index.js +++ b/packages/babel-plugin-minify-mangle-names/src/index.js @@ -139,6 +139,29 @@ module.exports = babel => { }); }, + /** + * This is required because after function name transformation + * plugin (part of es2015), the function name is NOT added to the + * scope's bindings. So to fix this issue, we simply add a hack to + * handle that case - fix it to the scope tree. + * + * Related: + * - https://github.com/babel/minify/issues/829 + */ + BindingIdentifier(path) { + const { scope } = path; + + if ( + // the parent has this id as the name + (path.parentPath.isFunctionExpression({ id: path.node }) || + path.parentPath.isClassExpression({ id: path.node })) && + // and the id isn't yet added to the scope + !hop.call(path.parentPath.scope.bindings, path.node.name) + ) { + path.parentPath.scope.registerBinding("local", path.parentPath); + } + }, + /** * This is necessary because, in Babel, the scope.references * does NOT contain the references in that scope. Only the program diff --git a/packages/babel-preset-minify/__tests__/minify-env-tests.js b/packages/babel-preset-minify/__tests__/minify-env-tests.js index b175e8b61..f29282053 100644 --- a/packages/babel-preset-minify/__tests__/minify-env-tests.js +++ b/packages/babel-preset-minify/__tests__/minify-env-tests.js @@ -196,4 +196,59 @@ describe("preset along with env", () => { console.log(foo); ` ); + + thePlugin( + "should fix issue#829 mangling after function name", + ` + function foo() { + let con = console; + + return { + a(bar) { + con.log(bar); + } + }; + } + `, + ` + function foo() { + var b = console; + return { + a: function d(c) { + b.log(c); + } + }; + } + ` + ); + + thePlugin( + "should fix issue#829 mangling after function name 2", + ` + function bar() { + var b = console; + return { + a: class { + constructor(bar) { + b.log(bar); + } + } + }; + } + `, + ` + function _classCallCheck(a, b) { if (!(a instanceof b)) throw new TypeError(\"Cannot call a class as a function\"); } + + function bar() { + var c = console; + return { + a: function b(a) { + "use strict"; + + _classCallCheck(this, b), c.log(a); + } + }; + } + ` + ); });