more generator spring cleaning

This commit is contained in:
Sebastian McKenzie 2014-11-17 17:30:41 +11:00
parent 8e115ef3ed
commit 7b74c1c8ec
6 changed files with 124 additions and 117 deletions

View File

@ -15,10 +15,10 @@ var assert = require("assert");
var types = require("ast-types"); var types = require("ast-types");
var leap = require("./leap"); var leap = require("./leap");
var meta = require("./meta"); var meta = require("./meta");
var t = require("../../../types");
var _ = require("lodash"); var _ = require("lodash");
var runtimeKeysMethod = runtimeProperty("keys"); var runtimeKeysMethod = runtimeProperty("keys");
var b = types.builders;
var n = types.namedTypes; var n = types.namedTypes;
function Emitter(contextId) { function Emitter(contextId) {
@ -58,7 +58,7 @@ function Emitter(contextId) {
// location to be determined at any time, even after generating code that // location to be determined at any time, even after generating code that
// refers to the location. // refers to the location.
function loc() { function loc() {
return b.literal(-1); return t.literal(-1);
} }
// Sets the exact value of the given location to the offset of the next // Sets the exact value of the given location to the offset of the next
@ -78,7 +78,7 @@ Emitter.prototype.mark = function(loc) {
}; };
Emitter.prototype.emit = function(node) { Emitter.prototype.emit = function(node) {
if (n.Expression.check(node)) node = b.expressionStatement(node); if (t.isExpression(node)) node = t.expressionStatement(node);
n.Statement.assert(node); n.Statement.assert(node);
this.listing.push(node); this.listing.push(node);
}; };
@ -92,16 +92,16 @@ Emitter.prototype.emitAssign = function(lhs, rhs) {
// Shorthand for an assignment statement. // Shorthand for an assignment statement.
Emitter.prototype.assign = function(lhs, rhs) { Emitter.prototype.assign = function(lhs, rhs) {
return b.expressionStatement( return t.expressionStatement(
b.assignmentExpression("=", lhs, rhs)); t.assignmentExpression("=", lhs, rhs));
}; };
// Convenience function for generating expressions like context.next, // Convenience function for generating expressions like context.next,
// context.sent, and context.rval. // context.sent, and context.rval.
Emitter.prototype.contextProperty = function(name, computed) { Emitter.prototype.contextProperty = function(name, computed) {
return b.memberExpression( return t.memberExpression(
this.contextId, this.contextId,
computed ? b.literal(name) : b.identifier(name), computed ? t.literal(name) : t.identifier(name),
!!computed !!computed
); );
}; };
@ -117,15 +117,15 @@ var volatileContextPropertyNames = {
// that should probably be stored in a temporary variable when there's a // that should probably be stored in a temporary variable when there's a
// possibility the property will get overwritten. // possibility the property will get overwritten.
Emitter.prototype.isVolatileContextProperty = function(expr) { Emitter.prototype.isVolatileContextProperty = function(expr) {
if (n.MemberExpression.check(expr)) { if (t.isMemberExpression(expr)) {
if (expr.computed) { if (expr.computed) {
// If it's a computed property such as context[couldBeAnything], // If it's a computed property such as context[couldBeAnything],
// assume the worst in terms of volatility. // assume the worst in terms of volatility.
return true; return true;
} }
if (n.Identifier.check(expr.object) && if (t.isIdentifier(expr.object) &&
n.Identifier.check(expr.property) && t.isIdentifier(expr.property) &&
expr.object.name === this.contextId.name && expr.object.name === this.contextId.name &&
_.has(volatileContextPropertyNames, expr.property.name)) { _.has(volatileContextPropertyNames, expr.property.name)) {
return true; return true;
@ -156,7 +156,7 @@ Emitter.prototype.setReturnValue = function(valuePath) {
Emitter.prototype.clearPendingException = function(tryLoc, assignee) { Emitter.prototype.clearPendingException = function(tryLoc, assignee) {
n.Literal.assert(tryLoc); n.Literal.assert(tryLoc);
var catchCall = b.callExpression( var catchCall = t.callExpression(
this.contextProperty("catch", true), this.contextProperty("catch", true),
[tryLoc] [tryLoc]
); );
@ -172,7 +172,7 @@ Emitter.prototype.clearPendingException = function(tryLoc, assignee) {
// exact value of the location is not yet known. // exact value of the location is not yet known.
Emitter.prototype.jump = function(toLoc) { Emitter.prototype.jump = function(toLoc) {
this.emitAssign(this.contextProperty("next"), toLoc); this.emitAssign(this.contextProperty("next"), toLoc);
this.emit(b.breakStatement()); this.emit(t.breakStatement());
}; };
// Conditional jump. // Conditional jump.
@ -180,11 +180,11 @@ Emitter.prototype.jumpIf = function(test, toLoc) {
n.Expression.assert(test); n.Expression.assert(test);
n.Literal.assert(toLoc); n.Literal.assert(toLoc);
this.emit(b.ifStatement( this.emit(t.ifStatement(
test, test,
b.blockStatement([ t.blockStatement([
this.assign(this.contextProperty("next"), toLoc), this.assign(this.contextProperty("next"), toLoc),
b.breakStatement() t.breakStatement()
]) ])
)); ));
}; };
@ -195,18 +195,18 @@ Emitter.prototype.jumpIfNot = function(test, toLoc) {
n.Literal.assert(toLoc); n.Literal.assert(toLoc);
var negatedTest; var negatedTest;
if (n.UnaryExpression.check(test) && test.operator === "!") { if (t.isUnaryExpression(test) && test.operator === "!") {
// Avoid double negation. // Avoid double negation.
negatedTest = test.argument; negatedTest = test.argument;
} else { } else {
negatedTest = b.unaryExpression("!", test); negatedTest = t.unaryExpression("!", test);
} }
this.emit(b.ifStatement( this.emit(t.ifStatement(
negatedTest, negatedTest,
b.blockStatement([ t.blockStatement([
this.assign(this.contextProperty("next"), toLoc), this.assign(this.contextProperty("next"), toLoc),
b.breakStatement() t.breakStatement()
]) ])
)); ));
}; };
@ -222,10 +222,10 @@ Emitter.prototype.makeTempVar = function() {
}; };
Emitter.prototype.getContextFunction = function(id) { Emitter.prototype.getContextFunction = function(id) {
var node = b.functionExpression( var node = t.functionExpression(
id || null, id || null,
[this.contextId], [this.contextId],
b.blockStatement([this.getDispatchLoop()]), t.blockStatement([this.getDispatchLoop()]),
false, // Not a generator anymore! false, // Not a generator anymore!
false // Nor an expression. false // Nor an expression.
); );
@ -255,7 +255,7 @@ Emitter.prototype.getDispatchLoop = function() {
self.listing.forEach(function(stmt, i) { self.listing.forEach(function(stmt, i) {
if (self.marked.hasOwnProperty(i)) { if (self.marked.hasOwnProperty(i)) {
cases.push(b.switchCase(b.literal(i), current = [])); cases.push(t.switchCase(t.literal(i), current = []));
alreadyEnded = false; alreadyEnded = false;
} }
@ -271,24 +271,24 @@ Emitter.prototype.getDispatchLoop = function() {
this.finalLoc.value = this.listing.length; this.finalLoc.value = this.listing.length;
cases.push( cases.push(
b.switchCase(this.finalLoc, [ t.switchCase(this.finalLoc, [
// Intentionally fall through to the "end" case... // Intentionally fall through to the "end" case...
]), ]),
// So that the runtime can jump to the final location without having // So that the runtime can jump to the final location without having
// to know its offset, we provide the "end" case as a synonym. // to know its offset, we provide the "end" case as a synonym.
b.switchCase(b.literal("end"), [ t.switchCase(t.literal("end"), [
// This will check/clear both context.thrown and context.rval. // This will check/clear both context.thrown and context.rval.
b.returnStatement( t.returnStatement(
b.callExpression(this.contextProperty("stop"), []) t.callExpression(this.contextProperty("stop"), [])
) )
]) ])
); );
return b.whileStatement( return t.whileStatement(
b.literal(true), t.literal(true),
b.switchStatement( t.switchStatement(
b.assignmentExpression( t.assignmentExpression(
"=", "=",
this.contextProperty("prev"), this.contextProperty("prev"),
this.contextProperty("next") this.contextProperty("next")
@ -300,10 +300,10 @@ Emitter.prototype.getDispatchLoop = function() {
// See comment above re: alreadyEnded. // See comment above re: alreadyEnded.
function isSwitchCaseEnder(stmt) { function isSwitchCaseEnder(stmt) {
return n.BreakStatement.check(stmt) || return t.isBreakStatement(stmt) ||
n.ContinueStatement.check(stmt) || t.isContinueStatement(stmt) ||
n.ReturnStatement.check(stmt) || t.isReturnStatement(stmt) ||
n.ThrowStatement.check(stmt); t.isThrowStatement(stmt);
} }
Emitter.prototype.getTryEntryList = function() { Emitter.prototype.getTryEntryList = function() {
@ -315,7 +315,7 @@ Emitter.prototype.getTryEntryList = function() {
var lastLocValue = 0; var lastLocValue = 0;
return b.arrayExpression( return t.arrayExpression(
this.tryEntries.map(function(tryEntry) { this.tryEntries.map(function(tryEntry) {
var thisLocValue = tryEntry.firstLoc.value; var thisLocValue = tryEntry.firstLoc.value;
assert.ok(thisLocValue >= lastLocValue, "try entries out of order"); assert.ok(thisLocValue >= lastLocValue, "try entries out of order");
@ -334,7 +334,7 @@ Emitter.prototype.getTryEntryList = function() {
triple[2] = fe.firstLoc; triple[2] = fe.firstLoc;
} }
return b.arrayExpression(triple); return t.arrayExpression(triple);
}) })
); );
}; };
@ -354,13 +354,13 @@ Emitter.prototype.explode = function(path, ignoreResult) {
n.Node.assert(node); n.Node.assert(node);
if (n.Statement.check(node)) if (t.isStatement(node))
return self.explodeStatement(path); return self.explodeStatement(path);
if (n.Expression.check(node)) if (t.isExpression(node))
return self.explodeExpression(path, ignoreResult); return self.explodeExpression(path, ignoreResult);
if (n.Declaration.check(node)) if (t.isDeclaration(node))
throw getDeclError(node); throw getDeclError(node);
switch (node.type) { switch (node.type) {
@ -406,7 +406,7 @@ Emitter.prototype.explodeStatement = function(path, labelId) {
// Explode BlockStatement nodes even if they do not contain a yield, // Explode BlockStatement nodes even if they do not contain a yield,
// because we don't want or need the curly braces. // because we don't want or need the curly braces.
if (n.BlockStatement.check(stmt)) { if (t.isBlockStatement(stmt)) {
return path.get("body").each( return path.get("body").each(
self.explodeStatement, self.explodeStatement,
self self
@ -510,7 +510,7 @@ Emitter.prototype.explodeStatement = function(path, labelId) {
var keyIterNextFn = self.makeTempVar(); var keyIterNextFn = self.makeTempVar();
self.emitAssign( self.emitAssign(
keyIterNextFn, keyIterNextFn,
b.callExpression( t.callExpression(
runtimeKeysMethod, runtimeKeysMethod,
[self.explodeExpression(path.get("right"))] [self.explodeExpression(path.get("right"))]
) )
@ -520,13 +520,13 @@ Emitter.prototype.explodeStatement = function(path, labelId) {
var keyInfoTmpVar = self.makeTempVar(); var keyInfoTmpVar = self.makeTempVar();
self.jumpIf( self.jumpIf(
b.memberExpression( t.memberExpression(
b.assignmentExpression( t.assignmentExpression(
"=", "=",
keyInfoTmpVar, keyInfoTmpVar,
b.callExpression(keyIterNextFn, []) t.callExpression(keyIterNextFn, [])
), ),
b.identifier("done"), t.identifier("done"),
false false
), ),
after after
@ -534,9 +534,9 @@ Emitter.prototype.explodeStatement = function(path, labelId) {
self.emitAssign( self.emitAssign(
stmt.left, stmt.left,
b.memberExpression( t.memberExpression(
keyInfoTmpVar, keyInfoTmpVar,
b.identifier("value"), t.identifier("value"),
false false
) )
); );
@ -589,8 +589,8 @@ Emitter.prototype.explodeStatement = function(path, labelId) {
n.SwitchCase.assert(c); n.SwitchCase.assert(c);
if (c.test) { if (c.test) {
condition = b.conditionalExpression( condition = t.conditionalExpression(
b.binaryExpression("===", disc, c.test), t.binaryExpression("===", disc, c.test),
caseLocs[i] = loc(), caseLocs[i] = loc(),
condition condition
); );
@ -731,7 +731,7 @@ Emitter.prototype.explodeStatement = function(path, labelId) {
self.explodeStatement(path.get("finalizer")); self.explodeStatement(path.get("finalizer"));
}); });
self.emit(b.callExpression( self.emit(t.callExpression(
self.contextProperty("finish"), self.contextProperty("finish"),
[finallyEntry.firstLoc] [finallyEntry.firstLoc]
)); ));
@ -743,7 +743,7 @@ Emitter.prototype.explodeStatement = function(path, labelId) {
break; break;
case "ThrowStatement": case "ThrowStatement":
self.emit(b.throwStatement( self.emit(t.throwStatement(
self.explodeExpression(path.get("argument")) self.explodeExpression(path.get("argument"))
)); ));
@ -767,7 +767,7 @@ Emitter.prototype.emitAbruptCompletion = function(record) {
"normal completions are not abrupt" "normal completions are not abrupt"
); );
var abruptArgs = [b.literal(record.type)]; var abruptArgs = [t.literal(record.type)];
if (record.type === "break" || record.type === "continue") { if (record.type === "break" || record.type === "continue") {
n.Literal.assert(record.target); n.Literal.assert(record.target);
@ -780,8 +780,8 @@ Emitter.prototype.emitAbruptCompletion = function(record) {
} }
this.emit( this.emit(
b.returnStatement( t.returnStatement(
b.callExpression( t.callExpression(
this.contextProperty("abrupt"), this.contextProperty("abrupt"),
abruptArgs abruptArgs
) )
@ -797,7 +797,7 @@ function isValidCompletion(record) {
} }
if (type === "break" || type === "continue") { if (type === "break" || type === "continue") {
return !_.has(record, "value") && n.Literal.check(record.target); return !_.has(record, "value") && t.isLiteral(record.target);;
} }
if (type === "return" || type === "throw") { if (type === "return" || type === "throw") {
@ -818,7 +818,7 @@ function isValidCompletion(record) {
// targets, but minimizing the number of switch cases keeps the generated // targets, but minimizing the number of switch cases keeps the generated
// code shorter. // code shorter.
Emitter.prototype.getUnmarkedCurrentLoc = function() { Emitter.prototype.getUnmarkedCurrentLoc = function() {
return b.literal(this.listing.length); return t.literal(this.listing.length);
}; };
// The context.prev property takes the value of context.next whenever we // The context.prev property takes the value of context.next whenever we
@ -940,7 +940,7 @@ Emitter.prototype.explodeExpression = function(path, ignoreResult) {
return finish(self.explodeExpression(path.get("expression"))); return finish(self.explodeExpression(path.get("expression")));
case "MemberExpression": case "MemberExpression":
return finish(b.memberExpression( return finish(t.memberExpression(
self.explodeExpression(path.get("object")), self.explodeExpression(path.get("object")),
expr.computed ? explodeViaTempVar(null, path.get("property")) : expr.property, expr.computed ? explodeViaTempVar(null, path.get("property")) : expr.property,
expr.computed expr.computed
@ -956,15 +956,14 @@ Emitter.prototype.explodeExpression = function(path, ignoreResult) {
// MemberExpression, then we need to force it to be unqualified by // MemberExpression, then we need to force it to be unqualified by
// using the (0, object.property)(...) trick; otherwise, it will // using the (0, object.property)(...) trick; otherwise, it will
// receive the object of the MemberExpression as its `this` object. // receive the object of the MemberExpression as its `this` object.
if (!n.MemberExpression.check(oldCalleePath.node) && if (!t.isMemberExpression(oldCalleePath.node) && t.isMemberExpression(newCallee)) {
n.MemberExpression.check(newCallee)) { newCallee = t.sequenceExpression([
newCallee = b.sequenceExpression([ t.literal(0),
b.literal(0),
newCallee newCallee
]); ]);
} }
return finish(b.callExpression( return finish(t.callExpression(
newCallee, newCallee,
path.get("arguments").map(function(argPath) { path.get("arguments").map(function(argPath) {
return explodeViaTempVar(null, argPath); return explodeViaTempVar(null, argPath);
@ -972,7 +971,7 @@ Emitter.prototype.explodeExpression = function(path, ignoreResult) {
)); ));
case "NewExpression": case "NewExpression":
return finish(b.newExpression( return finish(t.newExpression(
explodeViaTempVar(null, path.get("callee")), explodeViaTempVar(null, path.get("callee")),
path.get("arguments").map(function(argPath) { path.get("arguments").map(function(argPath) {
return explodeViaTempVar(null, argPath); return explodeViaTempVar(null, argPath);
@ -980,9 +979,9 @@ Emitter.prototype.explodeExpression = function(path, ignoreResult) {
)); ));
case "ObjectExpression": case "ObjectExpression":
return finish(b.objectExpression( return finish(t.objectExpression(
path.get("properties").map(function(propPath) { path.get("properties").map(function(propPath) {
return b.property( return t.property(
propPath.value.kind, propPath.value.kind,
propPath.value.key, propPath.value.key,
explodeViaTempVar(null, propPath.get("value")) explodeViaTempVar(null, propPath.get("value"))
@ -991,7 +990,7 @@ Emitter.prototype.explodeExpression = function(path, ignoreResult) {
)); ));
case "ArrayExpression": case "ArrayExpression":
return finish(b.arrayExpression( return finish(t.arrayExpression(
path.get("elements").map(function(elemPath) { path.get("elements").map(function(elemPath) {
return explodeViaTempVar(null, elemPath); return explodeViaTempVar(null, elemPath);
}) })
@ -1054,7 +1053,7 @@ Emitter.prototype.explodeExpression = function(path, ignoreResult) {
return result; return result;
case "UnaryExpression": case "UnaryExpression":
return finish(b.unaryExpression( return finish(t.unaryExpression(
expr.operator, expr.operator,
// Can't (and don't need to) break up the syntax of the argument. // Can't (and don't need to) break up the syntax of the argument.
// Think about delete a[b]. // Think about delete a[b].
@ -1063,21 +1062,21 @@ Emitter.prototype.explodeExpression = function(path, ignoreResult) {
)); ));
case "BinaryExpression": case "BinaryExpression":
return finish(b.binaryExpression( return finish(t.binaryExpression(
expr.operator, expr.operator,
explodeViaTempVar(null, path.get("left")), explodeViaTempVar(null, path.get("left")),
explodeViaTempVar(null, path.get("right")) explodeViaTempVar(null, path.get("right"))
)); ));
case "AssignmentExpression": case "AssignmentExpression":
return finish(b.assignmentExpression( return finish(t.assignmentExpression(
expr.operator, expr.operator,
self.explodeExpression(path.get("left")), self.explodeExpression(path.get("left")),
self.explodeExpression(path.get("right")) self.explodeExpression(path.get("right"))
)); ));
case "UpdateExpression": case "UpdateExpression":
return finish(b.updateExpression( return finish(t.updateExpression(
expr.operator, expr.operator,
self.explodeExpression(path.get("argument")), self.explodeExpression(path.get("argument")),
expr.prefix expr.prefix
@ -1090,10 +1089,10 @@ Emitter.prototype.explodeExpression = function(path, ignoreResult) {
if (arg && expr.delegate) { if (arg && expr.delegate) {
result = self.makeTempVar(); result = self.makeTempVar();
self.emit(b.returnStatement(b.callExpression( self.emit(t.returnStatement(t.callExpression(
self.contextProperty("delegateYield"), [ self.contextProperty("delegateYield"), [
arg, arg,
b.literal(result.property.name), t.literal(result.property.name),
after after
] ]
))); )));
@ -1104,7 +1103,7 @@ Emitter.prototype.explodeExpression = function(path, ignoreResult) {
} }
self.emitAssign(self.contextProperty("next"), after); self.emitAssign(self.contextProperty("next"), after);
self.emit(b.returnStatement(arg || null)); self.emit(t.returnStatement(arg || null));
self.mark(after); self.mark(after);
return self.contextProperty("sent"); return self.contextProperty("sent");

View File

@ -3,17 +3,17 @@
* All rights reserved. * All rights reserved.
* *
* This source code is licensed under the BSD-style license found in the * This source code is licensed under the BSD-style license found in the
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An * https://raw.githut.com/facebook/regenerator/master/LICENSE file. An
* additional grant of patent rights can be found in the PATENTS file in * additional grant of patent rights can be found in the PATENTS file in
* the same directory. * the same directory.
*/ */
var assert = require("assert"); var assert = require("assert");
var types = require("ast-types"); var types = require("ast-types");
var t = require("../../../types");
var _ = require("lodash"); var _ = require("lodash");
var n = types.namedTypes; var n = types.namedTypes;
var b = types.builders;
// The hoist function takes a FunctionExpression or FunctionDeclaration // The hoist function takes a FunctionExpression or FunctionDeclaration
// and replaces any Declaration nodes in its body with assignments, then // and replaces any Declaration nodes in its body with assignments, then
@ -33,7 +33,7 @@ exports.hoist = function(funPath) {
vars[dec.id.name] = dec.id; vars[dec.id.name] = dec.id;
if (dec.init) { if (dec.init) {
exprs.push(b.assignmentExpression( exprs.push(t.assignmentExpression(
"=", dec.id, dec.init "=", dec.id, dec.init
)); ));
} else if (includeIdentifiers) { } else if (includeIdentifiers) {
@ -47,7 +47,7 @@ exports.hoist = function(funPath) {
if (exprs.length === 1) if (exprs.length === 1)
return exprs[0]; return exprs[0];
return b.sequenceExpression(exprs); return t.sequenceExpression(exprs);
} }
types.visit(funPath.get("body"), { types.visit(funPath.get("body"), {
@ -58,7 +58,7 @@ exports.hoist = function(funPath) {
} else { } else {
// We don't need to traverse this expression any further because // We don't need to traverse this expression any further because
// there can't be any new declarations inside an expression. // there can't be any new declarations inside an expression.
return b.expressionStatement(expr); return t.expressionStatement(expr);
} }
// Since the original node has been either removed or replaced, // Since the original node has been either removed or replaced,
@ -68,7 +68,7 @@ exports.hoist = function(funPath) {
visitForStatement: function(path) { visitForStatement: function(path) {
var init = path.value.init; var init = path.value.init;
if (n.VariableDeclaration.check(init)) { if (t.isVariableDeclaration(init)) {
path.get("init").replace(varDeclToExpr(init, false)); path.get("init").replace(varDeclToExpr(init, false));
} }
this.traverse(path); this.traverse(path);
@ -76,7 +76,7 @@ exports.hoist = function(funPath) {
visitForInStatement: function(path) { visitForInStatement: function(path) {
var left = path.value.left; var left = path.value.left;
if (n.VariableDeclaration.check(left)) { if (t.isVariableDeclaration(left)) {
path.get("left").replace(varDeclToExpr(left, true)); path.get("left").replace(varDeclToExpr(left, true));
} }
this.traverse(path); this.traverse(path);
@ -86,11 +86,11 @@ exports.hoist = function(funPath) {
var node = path.value; var node = path.value;
vars[node.id.name] = node.id; vars[node.id.name] = node.id;
var assignment = b.expressionStatement( var assignment = t.expressionStatement(
b.assignmentExpression( t.assignmentExpression(
"=", "=",
node.id, node.id,
b.functionExpression( t.functionExpression(
node.id, node.id,
node.params, node.params,
node.body, node.body,
@ -100,7 +100,7 @@ exports.hoist = function(funPath) {
) )
); );
if (n.BlockStatement.check(path.parent.node)) { if (t.isBlockStatement(path.parent.node)) {
// Insert the assignment form before the first statement in the // Insert the assignment form before the first statement in the
// enclosing block. // enclosing block.
path.parent.get("body").unshift(assignment); path.parent.get("body").unshift(assignment);
@ -129,7 +129,7 @@ exports.hoist = function(funPath) {
var paramNames = {}; var paramNames = {};
funPath.get("params").each(function(paramPath) { funPath.get("params").each(function(paramPath) {
var param = paramPath.value; var param = paramPath.value;
if (n.Identifier.check(param)) { if (t.isIdentifier(param)) {
paramNames[param.name] = param; paramNames[param.name] = param;
} else { } else {
// Variables declared by destructuring parameter patterns will be // Variables declared by destructuring parameter patterns will be
@ -141,7 +141,7 @@ exports.hoist = function(funPath) {
Object.keys(vars).forEach(function(name) { Object.keys(vars).forEach(function(name) {
if (!_.has(paramNames, name)) { if (!_.has(paramNames, name)) {
declarations.push(b.variableDeclarator(vars[name], null)); declarations.push(t.variableDeclarator(vars[name], null));
} }
}); });
@ -149,5 +149,5 @@ exports.hoist = function(funPath) {
return null; // Be sure to handle this case! return null; // Be sure to handle this case!
} }
return b.variableDeclaration("var", declarations); return t.variableDeclaration("var", declarations);
}; };

View File

@ -11,6 +11,7 @@
var assert = require("assert"); var assert = require("assert");
var types = require("ast-types"); var types = require("ast-types");
var m = require("private").makeAccessor(); var m = require("private").makeAccessor();
var t = require("../../../types");
var _ = require("lodash"); var _ = require("lodash");
var isArray = types.builtInTypes.array; var isArray = types.builtInTypes.array;

View File

@ -3,20 +3,22 @@
* All rights reserved. * All rights reserved.
* *
* This source code is licensed under the BSD-style license found in the * This source code is licensed under the BSD-style license found in the
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An * https://raw.githut.com/facebook/regenerator/master/LICENSE file. An
* additional grant of patent rights can be found in the PATENTS file in * additional grant of patent rights can be found in the PATENTS file in
* the same directory. * the same directory.
*/ */
var types = require("ast-types");
var n = types.namedTypes;
var b = types.builders;
var hoist = require("./hoist").hoist;
var Emitter = require("./emit").Emitter;
var runtimeProperty = require("./util").runtimeProperty; var runtimeProperty = require("./util").runtimeProperty;
var runtimeWrapMethod = runtimeProperty("wrap"); var Emitter = require("./emit").Emitter;
var runtimeMarkMethod = runtimeProperty("mark"); var hoist = require("./hoist").hoist;
var types = require("ast-types");
var t = require("../../../types");
var n = types.namedTypes;
var runtimeAsyncMethod = runtimeProperty("async"); var runtimeAsyncMethod = runtimeProperty("async");
var runtimeWrapMethod = runtimeProperty("wrap");
var runtimeMarkMethod = runtimeProperty("mark");
exports.transform = function transform(node) { exports.transform = function transform(node) {
return types.visit(node, visitor); return types.visit(node, visitor);
@ -38,8 +40,8 @@ var visitor = types.PathVisitor.fromMethodsObject({
if (node.expression) { if (node.expression) {
// Transform expression lambdas into normal functions. // Transform expression lambdas into normal functions.
node.expression = false; node.expression = false;
node.body = b.blockStatement([ node.body = t.blockStatement([
b.returnStatement(node.body) t.returnStatement(node.body)
]); ]);
} }
@ -51,7 +53,7 @@ var visitor = types.PathVisitor.fromMethodsObject({
node.id = path.scope.parent.declareTemporary("callee$") node.id = path.scope.parent.declareTemporary("callee$")
); );
var innerFnId = b.identifier(node.id.name + "$"); var innerFnId = t.identifier(node.id.name + "$");
var contextId = path.scope.declareTemporary("context$"); var contextId = path.scope.declareTemporary("context$");
var vars = hoist(path); var vars = hoist(path);
@ -68,8 +70,8 @@ var visitor = types.PathVisitor.fromMethodsObject({
emitter.getContextFunction(innerFnId), emitter.getContextFunction(innerFnId),
// Async functions don't care about the outer function because they // Async functions don't care about the outer function because they
// don't need it to be marked and don't inherit from its .prototype. // don't need it to be marked and don't inherit from its .prototype.
node.async ? b.literal(null) : outerFnId, node.async ? t.literal(null) : outerFnId,
b.thisExpression() t.thisExpression()
]; ];
var tryEntryList = emitter.getTryEntryList(); var tryEntryList = emitter.getTryEntryList();
@ -77,24 +79,23 @@ var visitor = types.PathVisitor.fromMethodsObject({
wrapArgs.push(tryEntryList); wrapArgs.push(tryEntryList);
} }
var wrapCall = b.callExpression( var wrapCall = t.callExpression(
node.async ? runtimeAsyncMethod : runtimeWrapMethod, node.async ? runtimeAsyncMethod : runtimeWrapMethod,
wrapArgs wrapArgs
); );
outerBody.push(b.returnStatement(wrapCall)); outerBody.push(t.returnStatement(wrapCall));
node.body = b.blockStatement(outerBody); node.body = t.blockStatement(outerBody);
if (node.async) { if (node.async) {
node.async = false; node.async = false;
return; return;
} }
if (n.FunctionDeclaration.check(node)) { if (t.isFunctionDeclaration(node)) {
var pp = path.parent; var pp = path.parent;
while (pp && !(n.BlockStatement.check(pp.value) || while (pp && !(t.isBlockStatement(pp.value) || t.isProgram(pp.value))) {
n.Program.check(pp.value))) {
pp = pp.parent; pp = pp.parent;
} }
@ -150,10 +151,10 @@ var visitor = types.PathVisitor.fromMethodsObject({
// declaration. Note that all the other fields are the same. // declaration. Note that all the other fields are the same.
node.type = "FunctionExpression"; node.type = "FunctionExpression";
var varDecl = b.variableDeclaration("var", [ var varDecl = t.variableDeclaration("var", [
b.variableDeclarator( t.variableDeclarator(
node.id, node.id,
b.callExpression(runtimeMarkMethod, [node]) t.callExpression(runtimeMarkMethod, [node])
) )
]); ]);
@ -179,7 +180,7 @@ var visitor = types.PathVisitor.fromMethodsObject({
} else { } else {
n.FunctionExpression.assert(node); n.FunctionExpression.assert(node);
return b.callExpression(runtimeMarkMethod, [node]); return t.callExpression(runtimeMarkMethod, [node]);
} }
} }
}); });
@ -190,17 +191,16 @@ function shouldNotHoistAbove(stmtPath) {
// If the first statement is a "use strict" declaration, make sure to // If the first statement is a "use strict" declaration, make sure to
// insert hoisted declarations afterwards. // insert hoisted declarations afterwards.
if (n.ExpressionStatement.check(value) && if (t.isExpressionStatement(value) &&
n.Literal.check(value.expression) && t.isLiteral(value.expression) &&
value.expression.value === "use strict") { value.expression.value === "use strict") {
return true; return true;
} }
if (n.VariableDeclaration.check(value)) { if (t.isVariableDeclaration(value)) {
for (var i = 0; i < value.declarations.length; ++i) { for (var i = 0; i < value.declarations.length; ++i) {
var decl = value.declarations[i]; var decl = value.declarations[i];
if (n.CallExpression.check(decl.init) && if (t.isCallExpression(decl.init) && types.astNodesAreEquivalent(decl.init.callee, runtimeMarkMethod)) {
types.astNodesAreEquivalent(decl.init.callee, runtimeMarkMethod)) {
return true; return true;
} }
} }
@ -216,6 +216,6 @@ var awaitVisitor = types.PathVisitor.fromMethodsObject({
visitAwaitExpression: function(path) { visitAwaitExpression: function(path) {
// Convert await expressions to yield expressions. // Convert await expressions to yield expressions.
return b.yieldExpression(path.value.argument, false); return t.yieldExpression(path.value.argument, false);
} }
}); });

View File

@ -19,6 +19,7 @@
"Property": ["kind", "key", "value", "computed"], "Property": ["kind", "key", "value", "computed"],
"ReturnStatement": ["argument"], "ReturnStatement": ["argument"],
"SequenceExpression": ["expressions"], "SequenceExpression": ["expressions"],
"ThrowExpression": ["argument"],
"UnaryExpression": ["operator", "argument", "prefix"], "UnaryExpression": ["operator", "argument", "prefix"],
"VariableDeclaration": ["kind", "declarations"], "VariableDeclaration": ["kind", "declarations"],
"VariableDeclarator": ["id", "init"], "VariableDeclarator": ["id", "init"],

View File

@ -50,6 +50,12 @@ _.each(_aliases, function (types, type) {
// //
t.isExpression = function (node) {
return !t.isDeclaration(node);
};
//
t.shallowEqual = function (actual, expected) { t.shallowEqual = function (actual, expected) {
var same = true; var same = true;