Fix named FunctionExpression scoping issue.

This commit is contained in:
keijokapp 2016-02-29 16:07:59 +02:00
parent 1271d2cd52
commit 105299f26d
3 changed files with 28 additions and 15 deletions

View File

@ -6,12 +6,22 @@ import * as t from "babel-types";
let buildWrapper = template(` let buildWrapper = template(`
(function () { (function () {
var ref = FUNCTION; var ref = FUNCTION;
return function (PARAMS) { return function NAME(PARAMS) {
return ref.apply(this, arguments); return ref.apply(this, arguments);
}; };
}) })
`); `);
let namedBuildWrapper = template(`
(function () {
var ref = FUNCTION;
function NAME(PARAMS) {
return ref.apply(this, arguments);
}
return NAME;
})
`);
let arrowBuildWrapper = template(` let arrowBuildWrapper = template(`
(() => { (() => {
var ref = FUNCTION, _this = this; var ref = FUNCTION, _this = this;
@ -51,11 +61,15 @@ function classOrObjectMethod(path, callId) {
function plainFunction(path, callId) { function plainFunction(path, callId) {
let node = path.node; let node = path.node;
let isDeclaration = path.isFunctionDeclaration();
let asyncFnId = node.id;
let wrapper = buildWrapper; let wrapper = buildWrapper;
if (path.isArrowFunctionExpression()) { if (path.isArrowFunctionExpression()) {
path.arrowFunctionToShadowed(); path.arrowFunctionToShadowed();
wrapper = arrowBuildWrapper; wrapper = arrowBuildWrapper;
} else if (!isDeclaration && asyncFnId) {
wrapper = namedBuildWrapper;
} }
node.async = false; node.async = false;
@ -67,23 +81,19 @@ function plainFunction(path, callId) {
node.shadow = Object.assign({}, node.shadow, { arguments: false }); node.shadow = Object.assign({}, node.shadow, { arguments: false });
} }
let asyncFnId = node.id;
node.id = null; node.id = null;
let isDeclaration = path.isFunctionDeclaration();
if (isDeclaration) { if (isDeclaration) {
node.type = "FunctionExpression"; node.type = "FunctionExpression";
} }
let built = t.callExpression(callId, [node]); let built = t.callExpression(callId, [node]);
let container = wrapper({ let container = wrapper({
NAME: asyncFnId,
FUNCTION: built, FUNCTION: built,
PARAMS: node.params.map(() => path.scope.generateUidIdentifier("x")) PARAMS: node.params.map(() => path.scope.generateUidIdentifier("x"))
}).expression; }).expression;
let retFunction = container.body.body[1].argument;
if (isDeclaration) { if (isDeclaration) {
let declar = t.variableDeclaration("let", [ let declar = t.variableDeclaration("let", [
t.variableDeclarator( t.variableDeclarator(
@ -93,12 +103,10 @@ function plainFunction(path, callId) {
]); ]);
declar._blockHoist = true; declar._blockHoist = true;
retFunction.id = asyncFnId;
path.replaceWith(declar); path.replaceWith(declar);
} else { } else {
if (asyncFnId && asyncFnId.name) { let retFunction = container.body.body[1].argument;
retFunction.id = asyncFnId; if (!asyncFnId) {
} else {
nameFunction({ nameFunction({
node: retFunction, node: retFunction,
parent: path.parent, parent: path.parent,
@ -106,7 +114,7 @@ function plainFunction(path, callId) {
}); });
} }
if (retFunction.id || node.params.length) { if (!retFunction || retFunction.id || node.params.length) {
// we have an inferred function id or params so we need this wrapper // we have an inferred function id or params so we need this wrapper
path.replaceWith(t.callExpression(container, [])); path.replaceWith(t.callExpression(container, []));
} else { } else {

View File

@ -2,7 +2,10 @@ var foo = function () {
var ref = babelHelpers.asyncToGenerator(function* () { var ref = babelHelpers.asyncToGenerator(function* () {
console.log(bar); console.log(bar);
}); });
return function bar() {
function bar() {
return ref.apply(this, arguments); return ref.apply(this, arguments);
}; }
return bar;
}(); }();

View File

@ -4,7 +4,9 @@ var foo = function () {
console.log(bar); console.log(bar);
}); });
return function bar() { function bar() {
return ref.apply(this, arguments); return ref.apply(this, arguments);
}; }
return bar;
}(); }();