X Tutup
Skip to content

Commit 9e25767

Browse files
committed
fix try/finally not re-throwing errors when there is no catch clause (#1667)
When a try block had a finally but no catch, pcall's error result was discarded, silently swallowing the exception. Now the error is captured and re-thrown after the finally block executes.
1 parent 1bdbed8 commit 9e25767

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

src/transformation/visitors/errors.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ export const transformTryStatement: FunctionVisitor<ts.TryStatement> = (statemen
146146
returnedIdentifier,
147147
lua.SyntaxKind.AndOperator
148148
);
149+
} else if (statement.finallyBlock) {
150+
// try without catch, but with finally — need to capture error for re-throw
151+
const errorIdentifier = lua.createIdentifier("____error");
152+
result.push(lua.createVariableDeclarationStatement([tryResultIdentifier, errorIdentifier], tryCall));
149153
} else {
150154
// try without return or catch
151155
result.push(lua.createExpressionStatement(tryCall));
@@ -155,6 +159,22 @@ export const transformTryStatement: FunctionVisitor<ts.TryStatement> = (statemen
155159
result.push(...context.transformStatements(statement.finallyBlock));
156160
}
157161

162+
// Re-throw error if try had no catch but had a finally
163+
if (!statement.catchClause && statement.finallyBlock) {
164+
const notTryCondition = lua.createUnaryExpression(
165+
lua.cloneIdentifier(tryResultIdentifier),
166+
lua.SyntaxKind.NotOperator
167+
);
168+
const errorIdentifier = lua.createIdentifier("____error");
169+
const rethrow = lua.createExpressionStatement(
170+
lua.createCallExpression(lua.createIdentifier("error"), [
171+
lua.cloneIdentifier(errorIdentifier),
172+
lua.createNumericLiteral(0),
173+
])
174+
);
175+
result.push(lua.createIfStatement(notTryCondition, lua.createBlock([rethrow])));
176+
}
177+
158178
if (returnCondition && returnedIdentifier) {
159179
const returnValues: lua.Expression[] = [];
160180

test/unit/error.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,25 @@ test("multi return from catch->finally", () => {
256256
.expectToMatchJsResult();
257257
});
258258

259+
test("throw propagates through finally to outer catch", () => {
260+
util.testFunction`
261+
function test() {
262+
try {
263+
throw "Test error";
264+
} finally {
265+
}
266+
}
267+
268+
let result = 0;
269+
try {
270+
test();
271+
} catch (e) {
272+
result += 1;
273+
}
274+
return result;
275+
`.expectToMatchJsResult();
276+
});
277+
259278
test("return from nested finally", () => {
260279
util.testFunction`
261280
let x = "";

0 commit comments

Comments
 (0)
X Tutup