@@ -5,7 +5,7 @@ import { FunctionVisitor, TransformationContext } from "../context";
55import { unsupportedForTarget , unsupportedForTargetButOverrideAvailable } from "../utils/diagnostics" ;
66import { createUnpackCall } from "../utils/lua-ast" ;
77import { transformLuaLibFunction } from "../utils/lualib" ;
8- import { Scope , ScopeType } from "../utils/scope" ;
8+ import { findScope , LoopContinued , Scope , ScopeType } from "../utils/scope" ;
99import { isInAsyncFunction , isInGeneratorFunction } from "../utils/typescript" ;
1010import { wrapInAsyncAwaiter } from "./async-await" ;
1111import { transformScopeBlock } from "./block" ;
@@ -14,7 +14,7 @@ import { isInMultiReturnFunction } from "./language-extensions/multi";
1414import { createReturnStatement } from "./return" ;
1515
1616const transformAsyncTry : FunctionVisitor < ts . TryStatement > = ( statement , context ) => {
17- const [ tryBlock ] = transformScopeBlock ( context , statement . tryBlock , ScopeType . Try ) ;
17+ const [ tryBlock , tryScope ] = transformScopeBlock ( context , statement . tryBlock , ScopeType . Try ) ;
1818
1919 if (
2020 ( context . options . luaTarget === LuaTarget . Lua50 || context . options . luaTarget === LuaTarget . Lua51 ) &&
@@ -31,13 +31,14 @@ const transformAsyncTry: FunctionVisitor<ts.TryStatement> = (statement, context)
3131 return tryBlock . statements ;
3232 }
3333
34- // __TS__AsyncAwaiter(<catch block>)
34+ // __TS__AsyncAwaiter(<try block>)
3535 const awaiter = wrapInAsyncAwaiter ( context , tryBlock . statements , false ) ;
3636 const awaiterIdentifier = lua . createIdentifier ( "____try" ) ;
3737 const awaiterDefinition = lua . createVariableDeclarationStatement ( awaiterIdentifier , awaiter ) ;
3838
39- // local ____try = __TS__AsyncAwaiter(<catch block>)
40- const result : lua . Statement [ ] = [ awaiterDefinition ] ;
39+ // Transform catch/finally and collect scope info before building the result
40+ let catchScope : Scope | undefined ;
41+ const chainCalls : lua . Statement [ ] = [ ] ;
4142
4243 if ( statement . finallyBlock ) {
4344 const awaiterFinally = lua . createTableIndexExpression ( awaiterIdentifier , lua . createStringLiteral ( "finally" ) ) ;
@@ -49,27 +50,88 @@ const transformAsyncTry: FunctionVisitor<ts.TryStatement> = (statement, context)
4950 [ awaiterIdentifier , finallyFunction ] ,
5051 statement . finallyBlock
5152 ) ;
52- // ____try.finally(<finally function>)
53- result . push ( lua . createExpressionStatement ( finallyCall ) ) ;
53+ chainCalls . push ( lua . createExpressionStatement ( finallyCall ) ) ;
5454 }
5555
5656 if ( statement . catchClause ) {
57- // ____try.catch(<catch function>)
58- const [ catchFunction ] = transformCatchClause ( context , statement . catchClause ) ;
57+ const [ catchFunction , cScope ] = transformCatchClause ( context , statement . catchClause ) ;
58+ catchScope = cScope ;
5959 if ( catchFunction . params ) {
6060 catchFunction . params . unshift ( lua . createAnonymousIdentifier ( ) ) ;
6161 }
6262
6363 const awaiterCatch = lua . createTableIndexExpression ( awaiterIdentifier , lua . createStringLiteral ( "catch" ) ) ;
6464 const catchCall = lua . createCallExpression ( awaiterCatch , [ awaiterIdentifier , catchFunction ] ) ;
65-
66- // await ____try.catch(<catch function>)
6765 const promiseAwait = transformLuaLibFunction ( context , LuaLibFeature . Await , statement , catchCall ) ;
68- result . push ( lua . createExpressionStatement ( promiseAwait , statement ) ) ;
66+ chainCalls . push ( lua . createExpressionStatement ( promiseAwait , statement ) ) ;
6967 } else {
70- // await ____try
7168 const promiseAwait = transformLuaLibFunction ( context , LuaLibFeature . Await , statement , awaiterIdentifier ) ;
72- result . push ( lua . createExpressionStatement ( promiseAwait , statement ) ) ;
69+ chainCalls . push ( lua . createExpressionStatement ( promiseAwait , statement ) ) ;
70+ }
71+
72+ const hasReturn = tryScope . asyncTryHasReturn ?? catchScope ?. asyncTryHasReturn ;
73+ const hasBreak = tryScope . asyncTryHasBreak ?? catchScope ?. asyncTryHasBreak ;
74+ const hasContinue = tryScope . asyncTryHasContinue ?? catchScope ?. asyncTryHasContinue ;
75+
76+ // Build result in output order: flag declarations, awaiter, chain calls, post-checks
77+ const result : lua . Statement [ ] = [ ] ;
78+
79+ if ( hasReturn || hasBreak || hasContinue !== undefined ) {
80+ const flagDecls : lua . Identifier [ ] = [ ] ;
81+ if ( hasReturn ) {
82+ flagDecls . push ( lua . createIdentifier ( "____hasReturned" ) ) ;
83+ flagDecls . push ( lua . createIdentifier ( "____returnValue" ) ) ;
84+ }
85+ if ( hasBreak ) {
86+ flagDecls . push ( lua . createIdentifier ( "____hasBroken" ) ) ;
87+ }
88+ if ( hasContinue !== undefined ) {
89+ flagDecls . push ( lua . createIdentifier ( "____hasContinued" ) ) ;
90+ }
91+ result . push ( lua . createVariableDeclarationStatement ( flagDecls ) ) ;
92+ }
93+
94+ result . push ( awaiterDefinition ) ;
95+ result . push ( ...chainCalls ) ;
96+
97+ if ( hasReturn ) {
98+ result . push (
99+ lua . createIfStatement (
100+ lua . createIdentifier ( "____hasReturned" ) ,
101+ lua . createBlock ( [ createReturnStatement ( context , [ lua . createIdentifier ( "____returnValue" ) ] , statement ) ] )
102+ )
103+ ) ;
104+ }
105+
106+ if ( hasBreak ) {
107+ result . push (
108+ lua . createIfStatement ( lua . createIdentifier ( "____hasBroken" ) , lua . createBlock ( [ lua . createBreakStatement ( ) ] ) )
109+ ) ;
110+ }
111+
112+ if ( hasContinue !== undefined ) {
113+ const loopScope = findScope ( context , ScopeType . Loop ) ;
114+ const label = `__continue${ loopScope ?. id ?? "" } ` ;
115+
116+ const continueStatements : lua . Statement [ ] = [ ] ;
117+ switch ( hasContinue ) {
118+ case LoopContinued . WithGoto :
119+ continueStatements . push ( lua . createGotoStatement ( label ) ) ;
120+ break ;
121+ case LoopContinued . WithContinue :
122+ continueStatements . push ( lua . createContinueStatement ( ) ) ;
123+ break ;
124+ case LoopContinued . WithRepeatBreak :
125+ continueStatements . push (
126+ lua . createAssignmentStatement ( lua . createIdentifier ( label ) , lua . createBooleanLiteral ( true ) )
127+ ) ;
128+ continueStatements . push ( lua . createBreakStatement ( ) ) ;
129+ break ;
130+ }
131+
132+ result . push (
133+ lua . createIfStatement ( lua . createIdentifier ( "____hasContinued" ) , lua . createBlock ( continueStatements ) )
134+ ) ;
73135 }
74136
75137 return result ;
0 commit comments