aboutsummaryrefslogtreecommitdiff
path: root/babel-plugin-async-to-promises/lib/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'babel-plugin-async-to-promises/lib/index.js')
-rw-r--r--babel-plugin-async-to-promises/lib/index.js123
1 files changed, 123 insertions, 0 deletions
diff --git a/babel-plugin-async-to-promises/lib/index.js b/babel-plugin-async-to-promises/lib/index.js
new file mode 100644
index 0000000..9d7952b
--- /dev/null
+++ b/babel-plugin-async-to-promises/lib/index.js
@@ -0,0 +1,123 @@
+'use strict';
+
+var _babelHelperHoistVariables = require('babel-helper-hoist-variables');
+
+var _babelHelperHoistVariables2 = _interopRequireDefault(_babelHelperHoistVariables);
+
+var _babelTypes = require('babel-types');
+
+var _refactor = require('./refactor');
+
+var _promisechain = require('./promisechain');
+
+var _promisechain2 = _interopRequireDefault(_promisechain);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+module.exports = function () {
+ return {
+ visitor: WrapperVisitor,
+ manipulateOptions: function manipulateOptions(opts, parserOpts) {
+ parserOpts.plugins.push('asyncFunctions');
+ }
+ };
+};
+
+var depth = 0;
+var respID = void 0,
+ errID = void 0;
+
+var WrapperVisitor = {
+ // Because only ES5 is really supported, force this plugin to run as late as
+ // possible. At least the normal (es2015 preset) transforms have happened by
+ // then.
+ Program: {
+ exit: function exit(path) {
+ respID = path.scope.generateUid('resp');
+ errID = path.scope.generateUid('err');
+ path.traverse(MainVisitor);
+ // inline functions
+ path.traverse(InliningVisitor);
+ }
+ }
+};
+
+var MainVisitor = {
+ Function: {
+ enter: function enter(path) {
+ depth++;
+ var node = path.node;
+
+ if (node.async) {
+ (function () {
+ var decls = [];
+ var addVarDecl = function addVarDecl(id) {
+ return decls.push((0, _babelTypes.variableDeclarator)(id));
+ };
+ // hoist variables
+ (0, _babelHelperHoistVariables2.default)(path, addVarDecl);
+
+ // info gathering for this/arguments during the refactoring
+ var argumentsID = (0, _babelTypes.identifier)(path.scope.generateUid('arguments'));
+ var used = { argumentsID: false };
+
+ var newBody = [];
+ var addFunctionDecl = function addFunctionDecl(func) {
+ return newBody.push(func);
+ };
+
+ // refactor code
+ var args = { argumentsID: argumentsID, used: used, addVarDecl: addVarDecl, addFunctionDecl: addFunctionDecl, respID: respID, errID: errID };
+ path.traverse(_refactor.RefactorVisitor, args);
+ // add this/arguments vars if necessary
+ if (used.argumentsID) {
+ decls.push((0, _babelTypes.variableDeclarator)(argumentsID, (0, _babelTypes.identifier)('arguments')));
+ }
+ if (decls.length) {
+ newBody.push((0, _babelTypes.variableDeclaration)('var', decls));
+ }
+
+ // transformations that can only be done after all others.
+ path.traverse(_refactor.IfRefactorVisitor);
+
+ // build the promise chain
+ var chain = new _promisechain2.default(depth > 1, node.dirtyAllowed, respID, errID);
+ chain.add(path.get('body.body'));
+ newBody.push((0, _babelTypes.returnStatement)(chain.toAST()));
+
+ // combine all the newly generated stuff.
+ node.body = (0, _babelTypes.blockStatement)(newBody);
+ node.async = false;
+ })();
+ }
+ },
+ exit: function exit() {
+ depth--;
+ }
+ }
+};
+
+var InliningVisitor = {
+ BlockStatement: function BlockStatement(path) {
+ // inline blocks. Included because babel-template otherwise creates empty
+ // blocks.
+ if ((0, _babelTypes.isBlockStatement)(path.parent)) {
+ path.replaceWithMultiple(path.node.body);
+ }
+ },
+ ReturnStatement: function ReturnStatement(path) {
+ // return function () { ...body... }() becomes: ...body...
+ var call = path.node.argument;
+ var inlineable = (0, _babelTypes.isCallExpression)(call) && !call.arguments.length && (0, _babelTypes.isFunctionExpression)(call.callee) && !call.callee.id && !call.callee.params.length && (0, _babelTypes.isBlockStatement)(call.callee.body) && !Object.keys(path.get('argument.callee').scope.bindings).length;
+ if (inlineable) {
+ path.replaceWithMultiple(call.callee.body.body);
+ }
+ },
+ CallExpression: function CallExpression(path) {
+ // function () { return x; }() becomes x
+ var inlineable = !path.node.arguments.length && (0, _babelTypes.isFunctionExpression)(path.node.callee) && !path.node.callee.id && !path.node.callee.params.length && (0, _babelTypes.isBlockStatement)(path.node.callee.body) && path.node.callee.body.body.length === 1 && (0, _babelTypes.isReturnStatement)(path.node.callee.body.body[0]) && path.node.callee.body.body[0].argument;
+ if (inlineable) {
+ path.replaceWith(path.node.callee.body.body[0].argument);
+ }
+ }
+}; \ No newline at end of file