From 86a53773f1bcf20f778b756c902fae0d3ff116ea Mon Sep 17 00:00:00 2001 From: Diogo Franco Date: Wed, 3 May 2017 11:50:37 +0900 Subject: [PATCH] Add function name to spec-transformed arrow functions (#5620) While it may appear that this should be done by es2015-function-name, another way to think about it is that es2015-function-name implements the naming that javascript engines are supposed to do; and javascript engines cannot name function expressions that are the object of a member expression. --- .../package.json | 7 ++++++- .../src/index.js | 17 +++++++++++++---- .../arrow-functions/spec-naming/actual.js | 5 +++++ .../arrow-functions/spec-naming/expected.js | 16 ++++++++++++++++ .../arrow-functions/spec-naming/options.json | 3 +++ .../fixtures/arrow-functions/spec/actual.js | 3 +++ .../fixtures/arrow-functions/spec/expected.js | 8 +++++++- .../actual.js | 3 +-- .../expected.js | 9 ++++----- 9 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/actual.js create mode 100644 packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/expected.js create mode 100644 packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/options.json diff --git a/packages/babel-plugin-transform-es2015-arrow-functions/package.json b/packages/babel-plugin-transform-es2015-arrow-functions/package.json index bf1692d0b0..cfbb6983e6 100644 --- a/packages/babel-plugin-transform-es2015-arrow-functions/package.json +++ b/packages/babel-plugin-transform-es2015-arrow-functions/package.json @@ -8,7 +8,12 @@ "keywords": [ "babel-plugin" ], + "dependencies": { + "babel-helper-function-name": "7.0.0-alpha.7" + }, "devDependencies": { - "babel-helper-plugin-test-runner": "7.0.0-alpha.9" + "babel-helper-plugin-test-runner": "7.0.0-alpha.9", + "babel-traverse": "7.0.0-alpha.9", + "babel-types": "7.0.0-alpha.9" } } diff --git a/packages/babel-plugin-transform-es2015-arrow-functions/src/index.js b/packages/babel-plugin-transform-es2015-arrow-functions/src/index.js index 31c1193482..c3971f5d98 100644 --- a/packages/babel-plugin-transform-es2015-arrow-functions/src/index.js +++ b/packages/babel-plugin-transform-es2015-arrow-functions/src/index.js @@ -1,7 +1,13 @@ -export default function ({ types: t }) { +// @flow + +import nameFunction from "babel-helper-function-name"; +import { type NodePath } from "babel-traverse"; +import typeof * as babelTypes from "babel-types"; + +export default function ({ types: t }: { types: babelTypes }) { return { visitor: { - ArrowFunctionExpression(path, state) { + ArrowFunctionExpression(path: NodePath, state: Object) { if (state.opts.spec) { const { node } = path; if (node.shadow) return; @@ -9,7 +15,7 @@ export default function ({ types: t }) { node.shadow = { this: false }; node.type = "FunctionExpression"; - const boundThis = t.thisExpression(); + const boundThis: any = t.thisExpression(); boundThis._forceShadow = path; // make sure that arrow function won't be instantiated @@ -22,8 +28,11 @@ export default function ({ types: t }) { ])) ); + const replacement = nameFunction(path); + const named = replacement || node; + path.replaceWith(t.callExpression( - t.memberExpression(node, t.identifier("bind")), + t.memberExpression(named, t.identifier("bind")), [t.thisExpression()] )); } else { diff --git a/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/actual.js b/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/actual.js new file mode 100644 index 0000000000..8466a4c4de --- /dev/null +++ b/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/actual.js @@ -0,0 +1,5 @@ +[].map(x => x); + +const f = x => x + +const o = { k: x => x } diff --git a/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/expected.js b/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/expected.js new file mode 100644 index 0000000000..0bc1c85ebd --- /dev/null +++ b/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/expected.js @@ -0,0 +1,16 @@ +var _this = this; + +[].map(function (x) { + babelHelpers.newArrowCheck(this, _this); + return x; +}.bind(this)); + +const f = function f(x) { + babelHelpers.newArrowCheck(this, _this); + return x; +}.bind(this); + +const o = { k: function k(x) { + babelHelpers.newArrowCheck(this, _this); + return x; + }.bind(this) }; \ No newline at end of file diff --git a/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/options.json b/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/options.json new file mode 100644 index 0000000000..1653d169a3 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec-naming/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["external-helpers", ["transform-es2015-arrow-functions", { "spec": true }]] +} diff --git a/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec/actual.js b/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec/actual.js index b6f6e218f9..f84ea4ed38 100644 --- a/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec/actual.js +++ b/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec/actual.js @@ -4,4 +4,7 @@ function foo() { (function () { return () => this; })(); + return { + g: () => this + } } diff --git a/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec/expected.js b/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec/expected.js index 51a320d177..db9eae6efc 100644 --- a/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec/expected.js +++ b/packages/babel-plugin-transform-es2015-arrow-functions/test/fixtures/arrow-functions/spec/expected.js @@ -5,7 +5,7 @@ function foo() { babelHelpers.newArrowCheck(this, _this); return x * x; }.bind(this)); - var f = function (x, y) { + var f = function f(x, y) { babelHelpers.newArrowCheck(this, _this); return x * y; }.bind(this); @@ -17,4 +17,10 @@ function foo() { return this; }.bind(this); })(); + return { + g: function g() { + babelHelpers.newArrowCheck(this, _this); + return this; + }.bind(this) + }; } diff --git a/packages/babel-plugin-transform-es2015-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/actual.js b/packages/babel-plugin-transform-es2015-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/actual.js index f56af5c601..61388cd093 100644 --- a/packages/babel-plugin-transform-es2015-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/actual.js +++ b/packages/babel-plugin-transform-es2015-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/actual.js @@ -1,5 +1,4 @@ -// I don't know if this is a bug with arrow-functions spec: true -// or with function-name, but the functions are missing their names. +// These are actually handled by transform-es2015-arrow-function const x = () => x; const y = x => x(); const z = { z: () => y(x) }.z; diff --git a/packages/babel-plugin-transform-es2015-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/expected.js b/packages/babel-plugin-transform-es2015-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/expected.js index b842455dae..011d45f281 100644 --- a/packages/babel-plugin-transform-es2015-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/expected.js +++ b/packages/babel-plugin-transform-es2015-function-name/test/fixtures/function-name/with-arrow-functions-transform-spec/expected.js @@ -1,16 +1,15 @@ var _this = this; -// I don't know if this is a bug with arrow-functions spec: true -// or with function-name, but the functions are missing their names. -const x = function () { +// These are actually handled by transform-es2015-arrow-function +const x = function x() { babelHelpers.newArrowCheck(this, _this); return x; }.bind(this); -const y = function (x) { +const y = function y(x) { babelHelpers.newArrowCheck(this, _this); return x(); }.bind(this); const z = { z: function z() { babelHelpers.newArrowCheck(this, _this); return y(x); - }.bind(this) }.z; \ No newline at end of file + }.bind(this) }.z;