Repro:
try {
try {
throw 'inner';
} catch {
throw 'rethrown';
} finally {
print('finally ran');
}
} catch {
print('outer caught');
}
Expected: prints finally ran then outer caught
Actual: prints only outer caught
We emit the finally body as plain statements after the ____catch(____error) call:
local ____try = pcall(function() error("inner", 0) end)
if not ____try then ____catch() end -- ____catch errors ("rethrown")
print("finally ran") -- never reached
When ____catch rethrows via error(...), the error propagates past the finally statements, so the finally never runs. Per ECMA-262 sec-try-statement, the Finally block must always run after Catch, including when Catch completes with a throw. Fix: wrap the ____catch call in its own pcall, stash any rethrown error, run the finally, then rethrow.
Repro:
Expected: prints
finally ranthenouter caughtActual: prints only
outer caughtWe emit the
finallybody as plain statements after the____catch(____error)call:When
____catchrethrows viaerror(...), the error propagates past the finally statements, so the finally never runs. Per ECMA-262 sec-try-statement, theFinallyblock must always run afterCatch, including whenCatchcompletes with a throw. Fix: wrap the____catchcall in its own pcall, stash any rethrown error, run the finally, then rethrow.