Skip to content

Commit

Permalink
Add function name to spec-transformed arrow functions (babel#5620)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Diogo Franco committed May 3, 2017
1 parent 79c1eed commit 86a5377
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 13 deletions.
Expand Up @@ -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"
}
}
@@ -1,15 +1,21 @@
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<BabelNodeArrowFunctionExpression>, state: Object) {
if (state.opts.spec) {
const { node } = path;
if (node.shadow) return;

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
Expand All @@ -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 {
Expand Down
@@ -0,0 +1,5 @@
[].map(x => x);

const f = x => x

const o = { k: x => x }
@@ -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) };
@@ -0,0 +1,3 @@
{
"plugins": ["external-helpers", ["transform-es2015-arrow-functions", { "spec": true }]]
}
Expand Up @@ -4,4 +4,7 @@ function foo() {
(function () {
return () => this;
})();
return {
g: () => this
}
}
Expand Up @@ -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);
Expand All @@ -17,4 +17,10 @@ function foo() {
return this;
}.bind(this);
})();
return {
g: function g() {
babelHelpers.newArrowCheck(this, _this);
return this;
}.bind(this)
};
}
@@ -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;
@@ -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;
}.bind(this) }.z;

0 comments on commit 86a5377

Please sign in to comment.