|
1 | 1 | function Plugin(babel) { |
2 | 2 | const t = babel.types; |
3 | | - function markTailCall(retStmt) { |
4 | | - if (retStmt.argument === null) return; |
5 | | - if (retStmt.argument.type === "CallExpression") { |
6 | | - retStmt.argument.isTailCall = true; |
7 | | - } else if (retStmt.argument.type === "SequenceExpression" && retStmt.argument.expressions.length > 0) { |
8 | | - const lastExp = retStmt.argument.expressions[retStmt.argument.expressions.length - 1]; |
9 | | - if (lastExp.type !== "CallExpression") return; |
10 | | - lastExp.isTailCall = true; |
| 3 | + const tcoTypes = [ |
| 4 | + "SequenceExpression", |
| 5 | + "LogicalExpression", |
| 6 | + "ConditionalExpression", |
| 7 | + "CallExpression" |
| 8 | + ]; |
| 9 | + function markTailCall(expr) { |
| 10 | + if (expr.type === "CallExpression") { |
| 11 | + expr.isTailCall = true; |
| 12 | + } else if (expr.type === "SequenceExpression" && expr.expressions.length > 0) { |
| 13 | + return markTailCall(expr.expressions[expr.expressions.length - 1]); |
| 14 | + } else if (expr.type === "LogicalExpression") { |
| 15 | + if (expr.operator === "&&" || expr.operator === "||") { |
| 16 | + return markTailCall(expr.right); |
| 17 | + } |
| 18 | + } else if (expr.type === "ConditionalExpression") { |
| 19 | + markTailCall(expr.consequent); |
| 20 | + return markTailCall(expr.alternate); |
11 | 21 | } |
12 | 22 | } |
13 | 23 | // Function call without arguments |
@@ -390,7 +400,7 @@ function Plugin(babel) { |
390 | 400 | }, |
391 | 401 | "ReturnStatement": { |
392 | 402 | enter: function (path) { |
393 | | - markTailCall(path.node); |
| 403 | + if (retStmt.argument !== null) markTailCall(retStmt.argument); |
394 | 404 | }, |
395 | 405 | exit: function (path) { |
396 | 406 | const parentPath = path.getFunctionParent(); |
|
0 commit comments