11function Plugin ( babel ) {
22 const t = babel . types ;
33 const tryStack = [ ] ;
4- const finalStack = [ ] ;
54 // Traverses specific expression types and marks a CallExpression in tail position
65 function markTailCall ( expr ) {
76 if ( expr . type === "CallExpression" ) {
87 expr . isTailCall = true ;
98 } else if ( expr . type === "SequenceExpression" && expr . expressions . length > 0 ) {
109 return markTailCall ( expr . expressions [ expr . expressions . length - 1 ] ) ;
1110 } else if ( expr . type === "LogicalExpression" ) {
12- if ( expr . operator === "&&" || expr . operator === "||" ) {
11+ if ( expr . operator === "&&" || expr . operator === "||" )
1312 return markTailCall ( expr . right ) ;
14- }
1513 } else if ( expr . type === "ConditionalExpression" ) {
1614 markTailCall ( expr . consequent ) ;
1715 return markTailCall ( expr . alternate ) ;
1816 }
1917 }
18+ function addTailCallBool ( seqExp ) {
19+ seqExp . expressions [ 0 ] . argument . arguments . push ( t . booleanLiteral ( true ) ) ;
20+ }
2021 // HzTokens are unique single-instance objects for wrapping user instructions and data.
2122 // Type 1: Invocation Tokens,
2223 // Wrap userland functors and any operands needed to invoke them.
@@ -407,19 +408,19 @@ function Plugin(babel) {
407408 }
408409 if ( isTailCall ) {
409410 if ( tryStack . length > 0 ) {
410- const inTryCatch = tryStack [ tryStack . length - 1 ] ;
411- if ( path . getFunctionParent ( ) . node === inTryCatch . function . node ) {
412- if ( finalStack . length > 0 ) {
413- const inFinalizer = finalStack [ finalStack . length - 1 ] ;
414- if ( "finalizer" in inTryCatch . node && inFinalizer === inTryCatch . node . finalizer ) {
415- path . node . expressions [ 0 ] . argument . arguments . push ( t . booleanLiteral ( true ) ) ;
416- }
411+ const tryData = tryStack [ tryStack . length - 1 ] ;
412+ if ( path . getFunctionParent ( ) . node === tryData . functionParent ) {
413+ if (
414+ tryData . blockType === "finalizer"
415+ || tryData . blockType === "catch"
416+ ) {
417+ addTailCallBool ( path . node ) ;
417418 }
418419 } else {
419- path . node . expressions [ 0 ] . argument . arguments . push ( t . booleanLiteral ( true ) ) ;
420+ addTailCallBool ( path . node ) ;
420421 }
421422 } else {
422- path . node . expressions [ 0 ] . argument . arguments . push ( t . booleanLiteral ( true ) ) ;
423+ addTailCallBool ( path . node ) ;
423424 }
424425 }
425426 path . skip ( ) ;
@@ -449,27 +450,27 @@ function Plugin(babel) {
449450 "BlockStatement" : {
450451 // Records entry into the "finalizer" block of a TryStatement
451452 enter : function ( path ) {
452- if ( tryStack . length > 0 ) {
453+ if ( tryStack . length > 0 && tryStack [ tryStack . length - 1 ] . blockType === null ) {
453454 const stmtParent = path . getStatementParent ( ) ;
454- if (
455- stmtParent . node . type === "TryStatement"
456- && "finalizer" in stmtParent . node
457- && stmtParent . node . finalizer === path . node
458- ) {
459- finalStack . push ( path . node ) ;
455+ if ( stmtParent . node . type === "TryStatement" ) {
456+ if ( stmtParent . node . finalizer === path . node )
457+ tryStack [ tryStack . length - 1 ] . blockType = "finalizer" ;
458+ else if ( stmtParent . node . handler . body === path . node )
459+ tryStack [ tryStack . length - 1 ] . blockType = "catch" ;
460460 }
461461 }
462462 } ,
463463 // Records exit out of the "finalizer" block of a TryStatement
464464 exit : function ( path ) {
465- if ( tryStack . length > 0 && finalStack . length > 0 ) {
465+ if ( tryStack . length > 0 && tryStack [ tryStack . length - 1 ] . blockType !== null ) {
466466 const stmtParent = path . getStatementParent ( ) ;
467- if (
468- stmtParent . node . type === "TryStatement"
469- && "finalizer" in stmtParent . node
470- && stmtParent . node . finalizer === path . node
471- ) {
472- finalStack . pop ( ) ;
467+ if ( stmtParent . node . type === "TryStatement" ) {
468+ if (
469+ stmtParent . node . finalizer === path . node
470+ || stmtParent . node . handler . body === path . node
471+ ) {
472+ tryStack [ tryStack . length - 1 ] . blockType = null ;
473+ }
473474 }
474475 }
475476 }
@@ -478,8 +479,8 @@ function Plugin(babel) {
478479 // Records entry into a TryStatement
479480 enter : function ( path ) {
480481 tryStack . push ( {
481- node : path . node ,
482- function : path . getFunctionParent ( )
482+ functionParent : path . getFunctionParent ( ) . node ,
483+ blockType : null
483484 } ) ;
484485 } ,
485486 // Records exit out of a TryStatement
0 commit comments