fix async function remap helper from outputing incorrect calls causing wrong scoping - fixes #2708 - fixes #2715

This commit is contained in:
Sebastian McKenzie
2015-11-01 04:39:31 +00:00
parent f89724929e
commit 39bdecb119
15 changed files with 124 additions and 49 deletions

View File

@@ -13,6 +13,11 @@ _Note: Gaps between patch versions are faulty, broken or test releases._
See [CHANGELOG - 6to5](CHANGELOG-6to5.md) for the pre-4.0.0 version changelog.
## 6.0.15
* **Bug Fix**
* Fix async function remap helper from outputing incorrect calls causing wrong scoping.
## 6.0.14
* **Spec Compliancy**

View File

@@ -1,5 +1,8 @@
var foo = function () {
return babelHelpers.asyncToGenerator(function* () {
var foo = (function () {
var ref = babelHelpers.asyncToGenerator(function* () {
var wat = yield bar();
})();
};
});
return function foo() {
return ref.apply(this, arguments);
};
})();

View File

@@ -1,5 +1,3 @@
var foo = async function bar() {
console.log(bar);
};
foo();

View File

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

View File

@@ -0,0 +1,3 @@
foo(async function () {
});

View File

@@ -0,0 +1 @@
foo(babelHelpers.asyncToGenerator(function* () {}));

View File

@@ -0,0 +1,3 @@
async function foo(bar) {
}

View File

@@ -0,0 +1,6 @@
let foo = (function () {
var ref = babelHelpers.asyncToGenerator(function* foo(bar) {});
return function foo(_x) {
return ref.apply(this, arguments);
};
})();

View File

@@ -1,5 +1,8 @@
let foo = function foo() {
return babelHelpers.asyncToGenerator(function* foo() {
let foo = (function () {
var ref = babelHelpers.asyncToGenerator(function* foo() {
var wat = yield bar();
})();
};
});
return function foo() {
return ref.apply(this, arguments);
};
})();

View File

@@ -1,6 +1,10 @@
import { coroutine as _coroutine } from "bluebird";
var foo = function () {
return _coroutine(function* () {
var foo = (function () {
var ref = _coroutine(function* () {
var wat = yield bar();
})();
};
});
return function foo() {
return ref.apply(this, arguments);
};
})();

View File

@@ -1,5 +1,3 @@
var foo = async function bar() {
console.log(bar);
};
foo();

View File

@@ -1,8 +1,10 @@
import { coroutine as _coroutine } from "bluebird";
var foo = function () {
return _coroutine(function* bar() {
var foo = (function () {
var ref = _coroutine(function* bar() {
console.log(bar);
})();
};
});
foo();
return function foo() {
return ref.apply(this, arguments);
};
})();

View File

@@ -1,7 +1,11 @@
import { coroutine as _coroutine } from "bluebird";
let foo = function foo() {
return _coroutine(function* foo() {
let foo = (function () {
var ref = _coroutine(function* foo() {
var wat = yield bar();
})();
};
});
return function foo() {
return ref.apply(this, arguments);
};
})();

View File

@@ -7,8 +7,9 @@
"main": "lib/index.js",
"dependencies": {
"babel-runtime": "^5.0.0",
"babel-template": "^6.0.14",
"babel-types": "^6.0.14",
"babel-traverse": "^6.0.14",
"babel-helper-function-name": "^6.0.14"
}
}
}

View File

@@ -2,8 +2,18 @@
import type { NodePath } from "babel-traverse";
import nameFunction from "babel-helper-function-name";
import template from "babel-template";
import * as t from "babel-types";
let buildWrapper = template(`
(function () {
var ref = FUNCTION;
return function (PARAMS) {
return ref.apply(this, arguments);
};
})
`);
let awaitVisitor = {
Function(path) {
path.skip();
@@ -14,45 +24,78 @@ let awaitVisitor = {
}
};
export default function (path: NodePath, callId: Object) {
function classMethod(path: NodePath, callId: Object) {
let node = path.node;
if (node.generator) return;
let body = node.body;
if (path.isClassMethod()) {
node.async = false;
node.async = false;
let body = node.body;
let container = t.functionExpression(null, [], t.blockStatement(body.body), true);
container.shadow = true;
body.body = [
t.returnStatement(t.callExpression(
t.callExpression(callId, [container]),
[]
))
];
}
let container = t.functionExpression(null, [], t.blockStatement(body.body), true);
container.shadow = true;
body.body = [t.returnStatement(t.callExpression(t.callExpression(callId, [container]), []))];
return;
}
function plainFunction(path: NodePath, callId: Object) {
let node = path.node;
node.async = false;
node.generator = true;
path.traverse(awaitVisitor);
let container = t.functionExpression(null, [], t.blockStatement([
t.returnStatement(t.callExpression(t.callExpression(callId, [node]), []))
]));
node.shadow = container;
let built = t.callExpression(callId, [node]);
let container = buildWrapper({
FUNCTION: built,
PARAMS: node.params.map(() => path.scope.generateUidIdentifier("x"))
}).expression;
let retFunction = container.body.body[1].argument;
if (path.isFunctionDeclaration()) {
let declar = t.variableDeclaration("let", [
t.variableDeclarator(t.identifier(node.id.name), container)
t.variableDeclarator(
t.identifier(node.id.name),
t.callExpression(container, [])
)
]);
declar._blockHoist = true;
nameFunction({
node: container,
node: retFunction,
parent: declar.declarations[0],
scope: path.scope
});
path.replaceWith(declar);
} else {
path.replaceWith(container);
nameFunction({
node: retFunction,
parent: path.parent,
scope: path.scope
});
if (retFunction.id || node.params.length) {
// we have an inferred function id or params so we need this wrapper
path.replaceWith(t.callExpression(container, []));
} else {
// we can omit this wrapper as the conditions it protects for do not apply
path.replaceWith(built);
}
}
}
export default function (path: NodePath, callId: Object) {
let node = path.node;
if (node.generator) return;
if (path.isClassMethod()) {
return classMethod(path, callId);
} else {
return plainFunction(path, callId);
}
}