11import * as ts from "typescript" ;
2- import { LuaTarget } from "../.." ;
2+ import { LuaLibFeature , LuaTarget } from "../.." ;
33import * as lua from "../../LuaAST" ;
4- import { FunctionVisitor } from "../context" ;
4+ import { FunctionVisitor , TransformationContext } from "../context" ;
55import { unsupportedForTarget , unsupportedForTargetButOverrideAvailable } from "../utils/diagnostics" ;
66import { createUnpackCall } from "../utils/lua-ast" ;
7- import { ScopeType } from "../utils/scope" ;
7+ import { transformLuaLibFunction } from "../utils/lualib" ;
8+ import { Scope , ScopeType } from "../utils/scope" ;
89import { isInAsyncFunction , isInGeneratorFunction } from "../utils/typescript" ;
10+ import { wrapInAsyncAwaiter } from "./async-await" ;
911import { transformScopeBlock } from "./block" ;
1012import { transformIdentifier } from "./identifier" ;
1113import { isInMultiReturnFunction } from "./language-extensions/multi" ;
1214import { createReturnStatement } from "./return" ;
1315
14- export const transformTryStatement : FunctionVisitor < ts . TryStatement > = ( statement , context ) => {
15- const [ tryBlock , tryScope ] = transformScopeBlock ( context , statement . tryBlock , ScopeType . Try ) ;
16+ const transformAsyncTry : FunctionVisitor < ts . TryStatement > = ( statement , context ) => {
17+ const [ tryBlock ] = transformScopeBlock ( context , statement . tryBlock , ScopeType . Try ) ;
1618
17- if (
18- context . options . luaTarget === LuaTarget . Lua51 &&
19- isInAsyncFunction ( statement ) &&
20- ! context . options . lua51AllowTryCatchInAsyncAwait
21- ) {
19+ if ( context . options . luaTarget === LuaTarget . Lua51 && ! context . options . lua51AllowTryCatchInAsyncAwait ) {
2220 context . diagnostics . push (
2321 unsupportedForTargetButOverrideAvailable (
2422 statement ,
@@ -30,6 +28,57 @@ export const transformTryStatement: FunctionVisitor<ts.TryStatement> = (statemen
3028 return tryBlock . statements ;
3129 }
3230
31+ // __TS__AsyncAwaiter(<catch block>)
32+ const awaiter = wrapInAsyncAwaiter ( context , tryBlock . statements , false ) ;
33+ const awaiterIdentifier = lua . createIdentifier ( "____try" ) ;
34+ const awaiterDefinition = lua . createVariableDeclarationStatement ( awaiterIdentifier , awaiter ) ;
35+
36+ // local ____try = __TS__AsyncAwaiter(<catch block>)
37+ const result : lua . Statement [ ] = [ awaiterDefinition ] ;
38+
39+ if ( statement . finallyBlock ) {
40+ const awaiterFinally = lua . createTableIndexExpression ( awaiterIdentifier , lua . createStringLiteral ( "finally" ) ) ;
41+ const finallyFunction = lua . createFunctionExpression (
42+ lua . createBlock ( context . transformStatements ( statement . finallyBlock . statements ) )
43+ ) ;
44+ const finallyCall = lua . createCallExpression (
45+ awaiterFinally ,
46+ [ awaiterIdentifier , finallyFunction ] ,
47+ statement . finallyBlock
48+ ) ;
49+ // ____try.finally(<finally function>)
50+ result . push ( lua . createExpressionStatement ( finallyCall ) ) ;
51+ }
52+
53+ if ( statement . catchClause ) {
54+ // ____try.catch(<catch function>)
55+ const [ catchFunction ] = transformCatchClause ( context , statement . catchClause ) ;
56+ if ( catchFunction . params ) {
57+ catchFunction . params . unshift ( lua . createAnonymousIdentifier ( ) ) ;
58+ }
59+
60+ const awaiterCatch = lua . createTableIndexExpression ( awaiterIdentifier , lua . createStringLiteral ( "catch" ) ) ;
61+ const catchCall = lua . createCallExpression ( awaiterCatch , [ awaiterIdentifier , catchFunction ] ) ;
62+
63+ // await ____try.catch(<catch function>)
64+ const promiseAwait = transformLuaLibFunction ( context , LuaLibFeature . Await , statement , catchCall ) ;
65+ result . push ( lua . createExpressionStatement ( promiseAwait , statement ) ) ;
66+ } else {
67+ // await ____try
68+ const promiseAwait = transformLuaLibFunction ( context , LuaLibFeature . Await , statement , awaiterIdentifier ) ;
69+ result . push ( lua . createExpressionStatement ( promiseAwait , statement ) ) ;
70+ }
71+
72+ return result ;
73+ } ;
74+
75+ export const transformTryStatement : FunctionVisitor < ts . TryStatement > = ( statement , context ) => {
76+ if ( isInAsyncFunction ( statement ) ) {
77+ return transformAsyncTry ( statement , context ) ;
78+ }
79+
80+ const [ tryBlock , tryScope ] = transformScopeBlock ( context , statement . tryBlock , ScopeType . Try ) ;
81+
3382 if ( context . options . luaTarget === LuaTarget . Lua51 && isInGeneratorFunction ( statement ) ) {
3483 context . diagnostics . push (
3584 unsupportedForTarget ( statement , "try/catch inside generator functions" , LuaTarget . Lua51 )
@@ -50,15 +99,7 @@ export const transformTryStatement: FunctionVisitor<ts.TryStatement> = (statemen
5099
51100 if ( statement . catchClause && statement . catchClause . block . statements . length > 0 ) {
52101 // try with catch
53- const [ catchBlock , catchScope ] = transformScopeBlock ( context , statement . catchClause . block , ScopeType . Catch ) ;
54-
55- const catchParameter = statement . catchClause . variableDeclaration
56- ? transformIdentifier ( context , statement . catchClause . variableDeclaration . name as ts . Identifier )
57- : undefined ;
58- const catchFunction = lua . createFunctionExpression (
59- catchBlock ,
60- catchParameter ? [ lua . cloneIdentifier ( catchParameter ) ] : [ ]
61- ) ;
102+ const [ catchFunction , catchScope ] = transformCatchClause ( context , statement . catchClause ) ;
62103 const catchIdentifier = lua . createIdentifier ( "____catch" ) ;
63104 result . push ( lua . createVariableDeclarationStatement ( catchIdentifier , catchFunction ) ) ;
64105
@@ -138,3 +179,20 @@ export const transformThrowStatement: FunctionVisitor<ts.ThrowStatement> = (stat
138179 statement
139180 ) ;
140181} ;
182+
183+ function transformCatchClause (
184+ context : TransformationContext ,
185+ catchClause : ts . CatchClause
186+ ) : [ lua . FunctionExpression , Scope ] {
187+ const [ catchBlock , catchScope ] = transformScopeBlock ( context , catchClause . block , ScopeType . Catch ) ;
188+
189+ const catchParameter = catchClause . variableDeclaration
190+ ? transformIdentifier ( context , catchClause . variableDeclaration . name as ts . Identifier )
191+ : undefined ;
192+ const catchFunction = lua . createFunctionExpression (
193+ catchBlock ,
194+ catchParameter ? [ lua . cloneIdentifier ( catchParameter ) ] : [ ]
195+ ) ;
196+
197+ return [ catchFunction , catchScope ] ;
198+ }
0 commit comments