11function 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