more generator spring cleaning
This commit is contained in:
parent
8e115ef3ed
commit
7b74c1c8ec
@ -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");
|
||||||
|
|||||||
@ -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);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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"],
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user