Skip to content

Commit e2df528

Browse files
committed
Adding tryCatch TCO support
1 parent 84d8ed7 commit e2df528

File tree

1 file changed

+53
-4
lines changed

1 file changed

+53
-4
lines changed

src/BabelPlugin.js

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
function Plugin(babel) {
22
const t = babel.types;
3+
const tryStack = [];
4+
const finalStack = [];
35
function markTailCall(expr) {
46
if (expr.type === "CallExpression") {
57
expr.isTailCall = true;
@@ -386,15 +388,25 @@ function Plugin(babel) {
386388
));
387389
}
388390
}
389-
if (isTailCall) {
390-
path.node.expressions[0].argument.arguments.push(t.booleanLiteral(true));
391+
if (isTailCall && (tryStack.length === 0 || finalStack.length > 0)) {
392+
if (tryStack.length > 0) {
393+
const inTryCatch = tryStack[tryStack.length - 1];
394+
if (path.getFunctionParent().node !== inTryCatch.function.node || finalStack.length > 0) {
395+
const inFinalizer = finalStack[finalStack.length - 1];
396+
if ("finalizer" in inTryCatch.node && inFinalizer === inTryCatch.node.finalizer) {
397+
path.node.expressions[0].argument.arguments.push(t.booleanLiteral(true));
398+
}
399+
}
400+
} else {
401+
path.node.expressions[0].argument.arguments.push(t.booleanLiteral(true));
402+
}
391403
}
392404
path.skip();
393405
}
394406
},
395407
"ReturnStatement": {
396408
enter: function (path) {
397-
if (retStmt.argument !== null) markTailCall(retStmt.argument);
409+
if (path.node.argument !== null) markTailCall(path.node.argument);
398410
},
399411
exit: function (path) {
400412
const parentPath = path.getFunctionParent();
@@ -412,12 +424,49 @@ function Plugin(babel) {
412424
])];
413425
}
414426
},
427+
"BlockStatement": {
428+
enter: function (path) {
429+
if (tryStack.length > 0) {
430+
const stmtParent = path.getStatementParent();
431+
if (
432+
stmtParent.node.type === "TryStatement"
433+
&& "finalizer" in stmtParent.node
434+
&& stmtParent.node.finalizer === path.node
435+
) {
436+
finalStack.push(path.node);
437+
}
438+
}
439+
},
440+
exit: function (path) {
441+
if (tryStack.length > 0 && finalStack.length > 0) {
442+
const stmtParent = path.getStatementParent();
443+
if (
444+
stmtParent.node.type === "TryStatement"
445+
&& "finalizer" in stmtParent.node
446+
&& stmtParent.node.finalizer === path.node
447+
) {
448+
finalStack.pop();
449+
}
450+
}
451+
}
452+
},
453+
"TryStatement": {
454+
enter: function (path) {
455+
tryStack.push({
456+
node: path.node,
457+
function: path.getFunctionParent()
458+
});
459+
},
460+
exit: function (path) {
461+
if (tryStack.length > 0) tryStack.pop();
462+
}
463+
},
415464
"YieldExpression": {
416465
exit: function (path) {
417466
if (path.node.argument === null) path.node.argument = hzYield();
418467
else path.node.argument = hzYieldArg(path.node.argument);
419468
}
420-
},
469+
}
421470
/*
422471
"SpawnExpression": {
423472
exit: function (path) {

0 commit comments

Comments
 (0)