Anonymous functions sometimes given conflicting names, breaking code.
See original GitHub issueInput Code
index.js:
#!/usr/bin/node
'use strict';
const babel = require('babel-core');
console.log(babel.transform(`
'use strict';
(() => {
const con = console;
const obj = {
a() {
con.log('Hi.');
}
};
obj.a.log = str => {
con.log('OUCH, should never get here! Should be "' + str + '".');
};
obj.a();
})();
`, {presets: ['minify', 'env']}).code);
package.json:
{
"name": "babelbug",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "",
"private": true,
"dependencies": {
"babel-core": "^6.26.3",
"babel-preset-env": "^1.6.1",
"babel-preset-minify": "^0.4.0"
}
}
Actual Output
'use strict';(function(){var a=console,b={a:function a(){a.log('Hi.')}};b.a.log=function(b){
a.log('OUCH, should never get here! Should be "'+b+'".')},b.a()})();
Prints ‘OUCH, should never get here! Should be “Hi.”.’.
Expected Output
'use strict';(function(){var a=console,b={a:function(){a.log('Hi.')}};b.a.log=function(b){
a.log('OUCH, should never get here! Should be "'+b+'".')},b.a()})();
Prints ‘Hi.’.
Details
Note the incorrect function a()
instead of function()
, leading to the con
variable being clobbered.
Same thing if using babel-preset-es2015 with babel-preset-minify.
Can’t make a direct link to reproduce online – not sure why. But following this link, clicking on ‘Plugins’, on ‘Only official plugins’, typing ‘mangle’ and selecting minify-mangle-names reproduces it: https://babeljs.io/repl/#?babili=false&browsers=&build=&builtIns=false&code_lz=JAcgrgzgpgBBAuAnAlgY3iA3AKGACjwEoYBeAPhgG9dhUB7AOwRnodKoBs6BzALhgAepCgEMOURPDwDCAXxzBajZnQBGAK3bVFwEUSo1FrAHRdueEAAlkxkIQWLZNeTTXrjI0z3YJEwgzomZhYA8gCqAMKWADRwABZ0YBwAJjAMUABuEjDcUPAwcRJQAIQwAMoJSamqsABEIDAA1HBITTAgtbb2zg5uHkQKsoQD2EA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=true&fileSize=false&lineWrap=false&presets=es2015&prettier=false&targets=&version=6.26.0&envVersion=
Not sure whether this is a minify bug or a babel bug. Can’t reproduce if running ‘env’ on the output of ‘minify’ or when running ‘minify’ on the output of ‘env’, only if doing both in the same step.
Issue Analytics
- State:
- Created 5 years ago
- Comments:6 (5 by maintainers)
Top GitHub Comments
Somehow, when doing
{ a: function () {} }
,a.name
is still"a"
, at least in chromium and node. Seems doing anything more complicated than just putting brackets around the function makes it drop the.name
, though.I don’t think the minifier normally tries to preserve function names, since functions get renamed when minifying. Although there does seem to be some sort of weird (failed) attempt at preserving
.name
here:http://babeljs.io/repl/#?babili=true&browsers=&build=&builtIns=false&code_lz=MYewdgzgLgBCBGArGBeGBvAUDGBDANgKYBOUAFAJQbY55GlkAGAEgJYA0MAkgOQC2MYAXyswAcxgAiACToCJKADowuPoQC-kmADNiIATPQJEi-aWWqNkxYwoBuGuszqHx0_XL3MQA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=true&fileSize=false&lineWrap=false&presets=es2015%2Clatest%2Cbabili&prettier=true&targets=&version=6.26.0&envVersion=
becomes
when minified.
The
t.NOT_LOCAL_BINDING
symbol used inplugin-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 https://github.com/babel/babel/pull/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.