@@ -165,6 +165,7 @@ export const transformTryStatement: FunctionVisitor<ts.TryStatement> = (statemen
165165
166166 const tryResultIdentifier = lua . createIdentifier ( "____try" ) ;
167167 const returnValueIdentifier = lua . createIdentifier ( "____returnValue" ) ;
168+ const rethrowIdentifier = lua . createIdentifier ( "____rethrow" ) ;
168169
169170 const result : lua . Statement [ ] = [ ] ;
170171
@@ -191,20 +192,36 @@ export const transformTryStatement: FunctionVisitor<ts.TryStatement> = (statemen
191192 }
192193 }
193194 result . push ( lua . createVariableDeclarationStatement ( tryReturnIdentifiers , tryCall ) ) ;
195+ if ( statement . finallyBlock ) {
196+ result . push ( lua . createVariableDeclarationStatement ( rethrowIdentifier ) ) ;
197+ }
194198
195199 const catchCall = lua . createCallExpression (
196200 catchIdentifier ,
197201 statement . catchClause . variableDeclaration ? [ lua . cloneIdentifier ( returnedIdentifier ) ] : [ ]
198202 ) ;
199203 const catchCallStatement = hasReturn
200204 ? lua . createAssignmentStatement (
201- [ lua . cloneIdentifier ( returnedIdentifier ) , lua . cloneIdentifier ( returnValueIdentifier ) ] ,
202- catchCall
203- )
205+ [ lua . cloneIdentifier ( returnedIdentifier ) , lua . cloneIdentifier ( returnValueIdentifier ) ] ,
206+ catchCall
207+ )
204208 : lua . createExpressionStatement ( catchCall ) ;
205209
210+ const catchCallFunction = lua . createFunctionExpression ( lua . createBlock ( [ catchCallStatement ] ) ) ;
211+
212+ const tryCatchCall = lua . createCallExpression ( pCall , [ catchCallFunction ] ) ;
213+
214+ const tryCatchCallStatement = lua . createAssignmentStatement (
215+ [ lua . cloneIdentifier ( tryResultIdentifier ) , lua . cloneIdentifier ( rethrowIdentifier ) ] ,
216+ tryCatchCall
217+ ) ;
218+
206219 const notTryCondition = lua . createUnaryExpression ( tryResultIdentifier , lua . SyntaxKind . NotOperator ) ;
207- result . push ( lua . createIfStatement ( notTryCondition , lua . createBlock ( [ catchCallStatement ] ) ) ) ;
220+ result . push ( lua . createIfStatement ( notTryCondition , lua . createBlock (
221+ statement . finallyBlock
222+ ? [ tryCatchCallStatement ]
223+ : [ catchCallStatement ]
224+ ) ) ) ;
208225 } else if ( tryScope . functionReturned ) {
209226 // try with return, but no catch
210227 // returnedIdentifier = lua.createIdentifier("____returned");
@@ -230,21 +247,31 @@ export const transformTryStatement: FunctionVisitor<ts.TryStatement> = (statemen
230247 result . push ( ...context . transformStatements ( statement . finallyBlock ) ) ;
231248 }
232249
233- // Re-throw error if try had no catch but had a finally.
250+ // Re-throw error if try had a finally.
234251 // On pcall failure the error is the second return value, which lands in
235- // ____hasReturned (when functionReturned) or ____error (otherwise).
236- if ( ! statement . catchClause && statement . finallyBlock ) {
252+ // ____hasReturned (when functionReturned), ____rethrow
253+ // (catch throw/re-throw), or ____error (otherwise).
254+ if ( statement . finallyBlock ) {
237255 const notTryCondition = lua . createUnaryExpression (
238256 lua . cloneIdentifier ( tryResultIdentifier ) ,
239257 lua . SyntaxKind . NotOperator
240258 ) ;
241- const errorIdentifier = tryScope . functionReturned
242- ? lua . cloneIdentifier ( returnedIdentifier )
243- : lua . createIdentifier ( "____error" ) ;
244- const rethrow = lua . createExpressionStatement (
245- lua . createCallExpression ( lua . createIdentifier ( "error" ) , [ errorIdentifier , lua . createNumericLiteral ( 0 ) ] )
246- ) ;
247- result . push ( lua . createIfStatement ( notTryCondition , lua . createBlock ( [ rethrow ] ) ) ) ;
259+
260+ if ( ! statement . catchClause ) {
261+ const errorIdentifier = tryScope . functionReturned
262+ ? lua . cloneIdentifier ( returnedIdentifier )
263+ : lua . createIdentifier ( "____error" ) ;
264+ const rethrow = lua . createExpressionStatement (
265+ lua . createCallExpression ( lua . createIdentifier ( "error" ) , [ errorIdentifier , lua . createNumericLiteral ( 0 ) ] )
266+ ) ;
267+ result . push ( lua . createIfStatement ( notTryCondition , lua . createBlock ( [ rethrow ] ) ) ) ;
268+ } else if ( statement . catchClause . block . statements . length > 0 ) {
269+ // Re-throw is possible only from non-empty blocks.
270+ const rethrow = lua . createExpressionStatement (
271+ lua . createCallExpression ( lua . createIdentifier ( "error" ) , [ rethrowIdentifier , lua . createNumericLiteral ( 0 ) ] )
272+ ) ;
273+ result . push ( lua . createIfStatement ( notTryCondition , lua . createBlock ( [ rethrow ] ) ) ) ;
274+ }
248275 }
249276
250277 if ( returnCondition && returnedIdentifier ) {
0 commit comments