Fix: make sure function name doesn't collide with argument names

Usually the function name is dropped if the function is a function expression. But when `ie8` option is enabled, the function name is kept and mangled which may break legacy Safari for said reason. Since symbol names are now [mangled from within](https://github.com/mishoo/UglifyJS2/pull/2948#issuecomment-368095376), this fix adds argument names to existing names when mangling the name of a function expression.
This commit is contained in:
Chen Yangjian 2018-08-07 19:33:14 +08:00
parent fc78423f1d
commit 396a26e362
2 changed files with 35 additions and 0 deletions

View File

@ -320,6 +320,15 @@ function next_mangled_name(scope, options, def) {
var in_use = names_in_use(scope, options);
var holes = scope.cname_holes;
var names = Object.create(null);
// #179, #326
// in Safari strict mode, something like (function x(x){...}) is a syntax error;
// a function expression's argument cannot shadow the function expression's name
if (options.ie8 && (def.init instanceof AST_Function && def.init.argnames.length > 0)) {
for (var i = 0, len = def.init.argnames.length; i < len; i++) {
var arg = def.init.argnames[i];
names[arg.definition().mangled_name] = true;
}
}
var scopes = [ scope ];
def.references.forEach(function(sym) {
var scope = sym.scope;

26
test/mocha/safari9.js Normal file
View File

@ -0,0 +1,26 @@
var assert = require('assert');
var UglifyJS = require('../..');
describe('legacy safari', function() {
it('Should make sure mangled function name is different from its argument names', function () {
assert.strictEqual(
UglifyJS.minify([
'function main() {',
' "use strict";',
' ',
' function n(a,b,c) {',
' console.log(c)',
' }',
' E.on = function f2() {',
' E.on(function(e) {',
' return n(this,e)',
' })',
' }',
'}'
].join('\n'), {
ie8: true
}).code,
'function main(){"use strict";E.on=function(){E.on(function(n){return function c(n,o,t){console.log(t)}()})}}'
)
})
})