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(`
(function () {
var ref = FUNCTION;
return function (PARAMS) {
return function NAME(PARAMS) {
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(`
(() => {
var ref = FUNCTION, _this = this;
@ -51,11 +61,15 @@ function classOrObjectMethod(path, callId) {
function plainFunction(path, callId) {
let node = path.node;
let isDeclaration = path.isFunctionDeclaration();
let asyncFnId = node.id;
let wrapper = buildWrapper;
if (path.isArrowFunctionExpression()) {
path.arrowFunctionToShadowed();
wrapper = arrowBuildWrapper;
} else if (!isDeclaration && asyncFnId) {
wrapper = namedBuildWrapper;
}
node.async = false;
@ -67,23 +81,19 @@ function plainFunction(path, callId) {
node.shadow = Object.assign({}, node.shadow, { arguments: false });
}
let asyncFnId = node.id;
node.id = null;
let isDeclaration = path.isFunctionDeclaration();
if (isDeclaration) {
node.type = "FunctionExpression";
}
let built = t.callExpression(callId, [node]);
let container = wrapper({
NAME: asyncFnId,
FUNCTION: built,
PARAMS: node.params.map(() => path.scope.generateUidIdentifier("x"))
}).expression;
let retFunction = container.body.body[1].argument;
if (isDeclaration) {
let declar = t.variableDeclaration("let", [
t.variableDeclarator(
@ -93,12 +103,10 @@ function plainFunction(path, callId) {
]);
declar._blockHoist = true;
retFunction.id = asyncFnId;
path.replaceWith(declar);
} else {
if (asyncFnId && asyncFnId.name) {
retFunction.id = asyncFnId;
} else {
let retFunction = container.body.body[1].argument;
if (!asyncFnId) {
nameFunction({
node: retFunction,
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
path.replaceWith(t.callExpression(container, []));
} else {

View File

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

View File

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