Invoke Regenerator on async/generator Function nodes, not whole AST.

This should help (dramatically?) with
https://github.com/babel/babel/issues/1486#issuecomment-101491605,
although I'm not sure how to run the benchmarks myself.
This commit is contained in:
Ben Newman 2015-05-14 13:34:43 -05:00
parent b8a01a9919
commit cc611cb71c

View File

@ -1,11 +1,69 @@
import regenerator from "regenerator";
import * as t from "../../../types";
import { NodePath } from "ast-types";
export var metadata = {
group: "regenerator"
};
export function Program(ast) {
regenerator.transform(ast);
this.stop();
export function Func/*tion*/(node) {
if (node.async || node.generator) {
// Although this code transforms only the subtree rooted at the given
// Function node, that node might contain other generator functions
// that will also be transformed. It might help performance to ignore
// nested functions, and rely on the traversal to visit them later,
// but that's a small optimization. Starting here instead of at the
// root of the AST is the key optimization, since huge async/generator
// functions are relatively rare.
regenerator.transform(convertTraversalPathToNodePath(this));
}
}
// Given a TraversalPath, return a NodePath that includes full ancestry
// information (up to and including the Program node). This is complicated
// by having to include intermediate objects like blockStatement.body
// arrays, in addition to Node objects.
function convertTraversalPathToNodePath(path) {
var programNode;
var keysAlongPath = [];
while (path) {
var pp = path.parentPath;
var parentNode = pp && pp.node;
if (parentNode) {
keysAlongPath.push(path.key);
if (parentNode !== path.container) {
var found = Object.keys(parentNode).some(containerKey => {
if (parentNode[containerKey] === path.container) {
keysAlongPath.push(containerKey);
return true;
}
});
if (!found) {
throw new Error("Failed to find container object in parent node");
}
}
if (t.isProgram(parentNode)) {
programNode = parentNode;
break;
}
}
path = pp;
}
if (!programNode) {
throw new Error("Failed to find root Program node");
}
var nodePath = new NodePath(programNode);
while (keysAlongPath.length > 0) {
nodePath = nodePath.get(keysAlongPath.pop());
}
return nodePath;
}