diff --git a/packages/babel-helper-function-name/src/index.js b/packages/babel-helper-function-name/src/index.js index eae4f83f72..38e6b2d75d 100644 --- a/packages/babel-helper-function-name/src/index.js +++ b/packages/babel-helper-function-name/src/index.js @@ -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 && diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/actual.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/actual.js new file mode 100644 index 0000000000..f010a31695 --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/actual.js @@ -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') diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/exec.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/exec.js new file mode 100644 index 0000000000..f010a31695 --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/exec.js @@ -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') diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/expected.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/expected.js new file mode 100644 index 0000000000..e3f89867ea --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/expected.js @@ -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'); diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/options.json b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/options.json new file mode 100644 index 0000000000..476e663a3f --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/self-referential/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["external-helpers", ["transform-arrow-functions", { "spec": false }], "transform-function-name"] +} diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/actual.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/actual.js new file mode 100644 index 0000000000..f010a31695 --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/actual.js @@ -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') diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/exec.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/exec.js new file mode 100644 index 0000000000..f010a31695 --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/exec.js @@ -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') diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/expected.js b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/expected.js new file mode 100644 index 0000000000..21943d7a8f --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/expected.js @@ -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'); diff --git a/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/options.json b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/options.json new file mode 100644 index 0000000000..660f9d7503 --- /dev/null +++ b/packages/babel-plugin-transform-arrow-functions/test/fixtures/arrow-functions/spec-self-referential/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["external-helpers", ["transform-arrow-functions", { "spec": true }], "transform-function-name"] +} diff --git a/packages/babel-plugin-transform-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/expected.js b/packages/babel-plugin-transform-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/expected.js index fe1a7e83d5..8ac01aa738 100644 --- a/packages/babel-plugin-transform-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/expected.js +++ b/packages/babel-plugin-transform-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/expected.js @@ -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; diff --git a/packages/babel-traverse/src/path/conversion.js b/packages/babel-traverse/src/path/conversion.js index fe5b8ae9ee..34918fdbbe 100644 --- a/packages/babel-traverse/src/path/conversion.js +++ b/packages/babel-traverse/src/path/conversion.js @@ -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()],