From 9320d661f911ee598315554ee807c817f7a45900 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Mon, 5 Oct 2015 17:25:43 +0100 Subject: [PATCH] flesh out async-to-generator and bluebird-coroutines transformers, add babel-helper-async-to-generator module --- .../README.md | 5 ++ .../package.json | 15 ++++ .../src/index.js | 68 +++++++++++++++++++ .../package.json | 6 +- .../src/index.js | 16 ++++- .../package.json | 5 +- .../src/index.js | 12 +++- 7 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 packages/babel-helper-remap-async-to-generator/README.md create mode 100644 packages/babel-helper-remap-async-to-generator/package.json create mode 100644 packages/babel-helper-remap-async-to-generator/src/index.js diff --git a/packages/babel-helper-remap-async-to-generator/README.md b/packages/babel-helper-remap-async-to-generator/README.md new file mode 100644 index 0000000000..a7331914d6 --- /dev/null +++ b/packages/babel-helper-remap-async-to-generator/README.md @@ -0,0 +1,5 @@ +# babel-helper-remap-async-to-generator + +## Usage + +TODO diff --git a/packages/babel-helper-remap-async-to-generator/package.json b/packages/babel-helper-remap-async-to-generator/package.json new file mode 100644 index 0000000000..04fc955d16 --- /dev/null +++ b/packages/babel-helper-remap-async-to-generator/package.json @@ -0,0 +1,15 @@ +{ + "name": "babel-helper-remap-async-to-generator", + "version": "1.0.0", + "description": "", + "repository": "babel/babel", + "license": "MIT", + "main": "lib/index.js", + "dependencies": { + "babel-runtime": "^5.8.20", + "babel-types": "^5.8.20", + "babel-traverse": "^5.8.20", + "babel-helper-explode-class": "^5.0.0", + "babel-helper-function-name": "^5.0.0" + } +} diff --git a/packages/babel-helper-remap-async-to-generator/src/index.js b/packages/babel-helper-remap-async-to-generator/src/index.js new file mode 100644 index 0000000000..2a42feabdf --- /dev/null +++ b/packages/babel-helper-remap-async-to-generator/src/index.js @@ -0,0 +1,68 @@ +/* @flow */ + +import type { NodePath } from "babel-traverse"; +import explodeClass from "babel-helper-explode-class"; +import { bare as nameMethod } from "babel-helper-function-name"; +import * as t from "babel-types"; + +let awaitVisitor = { + Function(path) { + path.skip(); + }, + + AwaitExpression({ node }) { + node.type = "YieldExpression"; + } +}; + +let referenceVisitor = { + ReferencedIdentifier({ node, scope }, state) { + let name = state.id.name; + if (node.name === name && scope.bindingIdentifierEquals(name, state.id)) { + return state.ref = state.ref || scope.generateUidIdentifier(name); + } + } +}; + +export default function (path: NodePath, callId: Object) { + let node = path.node; + if (node.generator) return; + + node.async = false; + node.generator = true; + + path.traverse(awaitVisitor); + + let container = t.functionExpression(null, [], t.blockStatement([ + t.returnStatement(t.callExpression(callId, [node])) + ])); + node.shadow = container; + + if (path.isFunctionDeclaration()) { + let declar = t.variableDeclaration("let", [ + t.variableDeclarator(id, container) + ]); + declar._blockHoist = true; + + nameMethod({ + node: container, + parent: declar.declarations[0], + scope: path.scope + }); + + path.replaceWith(declar); + } else { + node.type = "FunctionExpression"; + + if (path.parentPath.isMethodDefinition({ value: node })) { + // we're a class method + let classPath = path.parentPath.parentPath.parentPath; + explodeClass(classPath); + + // remove method since we've injected ourselves already + path.parentPath.remove(); + } else { + path.replaceWith(container); + } + } +} diff --git a/packages/babel-plugin-transform-async-to-bluebird-coroutines/package.json b/packages/babel-plugin-transform-async-to-bluebird-coroutines/package.json index 8ed13dc485..1a389fdebe 100644 --- a/packages/babel-plugin-transform-async-to-bluebird-coroutines/package.json +++ b/packages/babel-plugin-transform-async-to-bluebird-coroutines/package.json @@ -7,5 +7,9 @@ "main": "lib/index.js", "keywords": [ "babel-plugin" - ] + ], + "dependencies": { + "babel-helper-remap-async-to-generator": "^5.0.0", + "babel-types": "^5.0.0" + } } diff --git a/packages/babel-plugin-transform-async-to-bluebird-coroutines/src/index.js b/packages/babel-plugin-transform-async-to-bluebird-coroutines/src/index.js index 6845446a11..cb9edf5203 100644 --- a/packages/babel-plugin-transform-async-to-bluebird-coroutines/src/index.js +++ b/packages/babel-plugin-transform-async-to-bluebird-coroutines/src/index.js @@ -1,7 +1,21 @@ +import remapAsyncToGenerator from "babel-helper-remap-async-to-generator"; +import * as t from "babel-types"; + export default function () { return { + manipulateOptions(opts, parserOpts) { + parserOpts.plugins.push("asyncFunctions"); + }, + visitor: { - // your visitor methods go here + Function(path, state) { + if (!path.node.async || path.node.generator) return; + + remapAsyncToGenerator( + path, + t.memberExpression(state.addImport("bluebird", null, "absolute"), t.identifier("coroutine")) + ); + } } }; } diff --git a/packages/babel-plugin-transform-async-to-generator/package.json b/packages/babel-plugin-transform-async-to-generator/package.json index 1f6dcf377a..760520838c 100644 --- a/packages/babel-plugin-transform-async-to-generator/package.json +++ b/packages/babel-plugin-transform-async-to-generator/package.json @@ -7,5 +7,8 @@ "main": "lib/index.js", "keywords": [ "babel-plugin" - ] + ], + "dependencies": { + "babel-helper-remap-async-to-generator": "^5.0.0" + } } diff --git a/packages/babel-plugin-transform-async-to-generator/src/index.js b/packages/babel-plugin-transform-async-to-generator/src/index.js index 6845446a11..63b1e3888b 100644 --- a/packages/babel-plugin-transform-async-to-generator/src/index.js +++ b/packages/babel-plugin-transform-async-to-generator/src/index.js @@ -1,7 +1,17 @@ +import remapAsyncToGenerator from "babel-helper-remap-async-to-generator"; + export default function () { return { + manipulateOptions(opts, parserOpts) { + parserOpts.plugins.push("asyncFunctions"); + }, + visitor: { - // your visitor methods go here + Function(path, state) { + if (!path.node.async || path.node.generator) return; + + remapAsyncToGenerator(path, state.addHelper("async-to-generator")); + } } }; }