Fix transform-arrow-functions in { spec: true } shadowing (#6760)

* Fix transform-arrow-functions in { spec: true } shadowing

The function name matching the variable declaration name could
shadow the actual function object inside the generated function,
leading to invalid behavior due to holding a reference to the
original unbound function.

* Combine it with transform-function-name just to be sure in spec: false

* Revert "Fix transform-arrow-functions in { spec: true } shadowing"

This reverts commit 1cafe2561d0b0ddd181b956a85eb074621da12e8.

* Much simpler version of the above fix

* Missing fixture updates

* Avoid using rest/spread to make the tests pass on node 4

* ...actually update _all_ the fixtures
This commit is contained in:
Diogo Franco 2017-11-09 07:21:30 +09:00 committed by Henry Zhu
parent c440f045f5
commit 81811bf1b9
11 changed files with 79 additions and 6 deletions

View File

@ -126,7 +126,11 @@ function visit(node, name, scope) {
return state;
}
export default function({ node, parent, scope, id }) {
/**
* @param {NodePath} param0
* @param {Boolean} localBinding whether a name could shadow a self-reference (e.g. converting arrow function)
*/
export default function({ node, parent, scope, id }, localBinding = false) {
// has an `id` so we don't need to infer one
if (node.id) return;
@ -141,7 +145,8 @@ export default function({ node, parent, scope, id }) {
// let foo = function () {};
id = parent.id;
if (t.isIdentifier(id)) {
// but not "let foo = () => {};" being converted to function expression
if (t.isIdentifier(id) && !localBinding) {
const binding = scope.parent.getBinding(id.name);
if (
binding &&

View File

@ -0,0 +1,6 @@
var fooCalls = []
var jumpTable = (name, arg) => { if (jumpTable[name]) { jumpTable[name](arg) } }
Object.assign(jumpTable, { foo (arg) { fooCalls.push(arg) } });
jumpTable('foo', 'bar')
assert.strictEqual(fooCalls[0], 'bar')

View File

@ -0,0 +1,6 @@
var fooCalls = []
var jumpTable = (name, arg) => { if (jumpTable[name]) { jumpTable[name](arg) } }
Object.assign(jumpTable, { foo (arg) { fooCalls.push(arg) } });
jumpTable('foo', 'bar')
assert.strictEqual(fooCalls[0], 'bar')

View File

@ -0,0 +1,16 @@
var fooCalls = [];
var jumpTable = function jumpTable(name, arg) {
if (jumpTable[name]) {
jumpTable[name](arg);
}
};
Object.assign(jumpTable, {
foo(arg) {
fooCalls.push(arg);
}
});
jumpTable('foo', 'bar');
assert.strictEqual(fooCalls[0], 'bar');

View File

@ -0,0 +1,3 @@
{
"plugins": ["external-helpers", ["transform-arrow-functions", { "spec": false }], "transform-function-name"]
}

View File

@ -0,0 +1,6 @@
var fooCalls = []
var jumpTable = (name, arg) => { if (jumpTable[name]) { jumpTable[name](arg) } }
Object.assign(jumpTable, { foo (arg) { fooCalls.push(arg) } });
jumpTable('foo', 'bar')
assert.strictEqual(fooCalls[0], 'bar')

View File

@ -0,0 +1,6 @@
var fooCalls = []
var jumpTable = (name, arg) => { if (jumpTable[name]) { jumpTable[name](arg) } }
Object.assign(jumpTable, { foo (arg) { fooCalls.push(arg) } });
jumpTable('foo', 'bar')
assert.strictEqual(fooCalls[0], 'bar')

View File

@ -0,0 +1,22 @@
var _this = this;
var fooCalls = [];
var _jumpTable = function jumpTable(name, arg) {
babelHelpers.newArrowCheck(this, _this);
if (_jumpTable[name]) {
_jumpTable[name](arg);
}
}.bind(this);
Object.assign(_jumpTable, {
foo(arg) {
fooCalls.push(arg);
}
});
_jumpTable('foo', 'bar');
assert.strictEqual(fooCalls[0], 'bar');

View File

@ -0,0 +1,3 @@
{
"plugins": ["external-helpers", ["transform-arrow-functions", { "spec": true }], "transform-function-name"]
}

View File

@ -1,9 +1,9 @@
var _this = this;
// These are actually handled by transform-arrow-functions
const x = function x() {
const _x = function x() {
babelHelpers.newArrowCheck(this, _this);
return x;
return _x;
}.bind(this);
const y = function y(x) {
@ -14,6 +14,6 @@ const y = function y(x) {
const z = {
z: function z() {
babelHelpers.newArrowCheck(this, _this);
return y(x);
return y(_x);
}.bind(this)
}.z;

View File

@ -144,7 +144,7 @@ export function arrowFunctionToExpression(
this.replaceWith(
t.callExpression(
t.memberExpression(
nameFunction(this) || this.node,
nameFunction(this, true) || this.node,
t.identifier("bind"),
),
[checkBinding ? t.identifier(checkBinding.name) : t.thisExpression()],