Commit 9ffad4f7 by kzc Committed by Marijn Haverbeke

Safari/WebKit bug workaround: rename function parameter if matches method name (#154)

* Rename parameters matching names of standalone FunctionExpressions.
* Fix unnecessary renaming of parameters of transpiled class methods.
parent 0708ad6d
Pipeline #5379179 passed with stage
in 3 minutes 33 seconds
......@@ -83,7 +83,7 @@ export default class ClassBody extends Node {
let lhs;
let methodName = method.key.name;
if ( scope.contains( methodName ) || reserved[ methodName ] ) methodName = scope.createIdentifier( methodName );
if ( reserved[ methodName ] ) methodName = scope.createIdentifier( methodName );
// when method name is a string or a number let's pretend it's a computed method
......
......@@ -15,5 +15,50 @@ export default class FunctionExpression extends Node {
}
super.initialise( transforms );
const parent = this.parent;
let methodName;
if ( transforms.conciseMethodProperty
&& parent.type === 'Property'
&& parent.kind === 'init'
&& parent.method
&& parent.key.type === 'Identifier' ) {
// object literal concise method
methodName = parent.key.name;
}
else if ( transforms.classes
&& parent.type === 'MethodDefinition'
&& parent.kind === 'method'
&& parent.key.type === 'Identifier' ) {
// method definition in a class
methodName = parent.key.name;
}
else if ( this.id && this.id.type === 'Identifier' ) {
// naked function expression
methodName = this.id.alias || this.id.name;
}
if ( methodName ) {
for ( const param of this.params ) {
if ( param.type === 'Identifier' && methodName === param.name ) {
// workaround for Safari 9/WebKit bug:
// https://gitlab.com/Rich-Harris/buble/issues/154
// change parameter name when same as method name
const scope = this.body.scope;
const declaration = scope.declarations[ methodName ];
const alias = scope.createIdentifier( methodName );
param.alias = alias;
for ( const identifier of declaration.instances ) {
identifier.alias = alias;
}
break;
}
}
}
}
}
......@@ -10,8 +10,14 @@ export default class Property extends Node {
let name;
if ( this.key.type === 'Literal' && typeof this.key.value === 'number' ) {
name = "";
} else if ( this.key.type === 'Identifier' ) {
if ( reserved[ this.key.name ] || ! /^[a-z_$][a-z0-9_$]*$/i.test( this.key.name ) ) {
name = this.findScope( true ).createIdentifier( this.key.name );
} else {
name = this.key.name;
}
} else {
name = this.findScope( true ).createIdentifier( this.key.type === 'Identifier' ? this.key.name : this.key.value );
name = this.findScope( true ).createIdentifier( this.key.value );
}
if ( this.value.generator ) code.remove( this.start, this.key.start );
......
......@@ -58,7 +58,7 @@ module.exports = [
},
{
description: 'deshadows method names',
description: 'no unnecessary deshadowing of method names',
input: `
var bar = 'x';
......@@ -74,7 +74,7 @@ module.exports = [
var Foo = function Foo () {};
Foo.prototype.bar = function bar$1 ( str ) {
Foo.prototype.bar = function bar ( str ) {
return str + 'bar';
};`
},
......
......@@ -93,5 +93,97 @@ module.exports = [
description: 'handles sparse arrays (#62)',
input: `var a = [ , 1 ], b = [ 1, ], c = [ 1, , 2 ], d = [ 1, , , ];`,
output: `var a = [ , 1 ], b = [ 1 ], c = [ 1, , 2 ], d = [ 1, , , ];`
}
},
{
description: 'Safari/WebKit bug workaround: parameter shadowing function expression name (#154)',
input: `
"use strict"; // necessary to trigger WebKit bug
class Foo {
bar (bar) {
return bar;
}
static baz (foo, bar, baz) {
return foo * baz - baz * bar;
}
}
var a = class Bar {
b (a, b, c) {
return a * b - c * b + b$1 - b$2;
}
};
var b = class {
b (a, b, c) {
return a * b - c * b;
}
};
var c = {
b (a, b, c) {
return a * b - c * b;
}
};
var d = function foo(foo) {
return foo;
};
// FunctionDeclaration is not subject to the WebKit bug
function bar(bar) {
return bar;
}
`,
output: `
"use strict"; // necessary to trigger WebKit bug
var Foo = function Foo () {};
Foo.prototype.bar = function bar (bar$1) {
return bar$1;
};
Foo.baz = function baz (foo, bar, baz$1) {
return foo * baz$1 - baz$1 * bar;
};
var a = (function () {
function Bar () {}
Bar.prototype.b = function b (a, b$3, c) {
return a * b$3 - c * b$3 + b$1 - b$2;
};
return Bar;
}());
var b = (function () {
function b () {}
b.prototype.b = function b (a, b$1, c) {
return a * b$1 - c * b$1;
};
return b;
}());
var c = {
b: function b (a, b$1, c) {
return a * b$1 - c * b$1;
}
};
var d = function foo(foo$1) {
return foo$1;
};
// FunctionDeclaration is not subject to the WebKit bug
function bar(bar) {
return bar;
}
`
},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment