Describe the bug
(The bug report was written by GLM 5.1 with opencode)
When a function contains a try/catch/finally with an empty finally block, and the try block contains an if statement with a return that is not taken, control flow is lost after the finally block. The function returns undefined instead of continuing to subsequent statements.
To Reproduce
This JavaScript code reproduces the issue:
function f(x) {
try {
if (x) return -1;
} catch (e) {}
return 42;
}
f(0); // → 42 ✓ (correct)
Adding an empty finally {} breaks it:
function g(x) {
try {
if (x) return -1;
} catch (e) {} finally {}
return 42;
}
g(0); // → undefined ✗ (should be 42)
The only difference is the addition of finally {}. The if (x) condition is false (since 0 is falsy), so the return -1 inside the try block is never executed. Control should fall through the empty finally and reach return 42, but instead the function returns undefined.
Expected behavior
Both functions should return 42. The empty finally {} block should be a no-op, and control flow should continue to return 42.
Build environment
- OS: macOS
- Version: 15.7.3
- Target triple: x86_64-apple-darwin
- Rustc version: rustc 1.94.1 (e408947bf 2026-03-25)
- Boa version: git revision
3ce87f0fa03c5c037fb667f7f21a4996abbbc714 (Note: this appears to be a regression. The bug does not reproduce on the released boa_engine version 0.21.1)
Additional context
This was discovered while running React 19's react-reconciler inside Boa. React's dispatchSetStateInternal function uses the exact pattern if (cond) try { ... } catch (e) {} finally {}, causing all React state updates to silently fail — the function returns undefined, and the code that schedules a re-render (after the finally) is never reached.
Describe the bug
(The bug report was written by GLM 5.1 with opencode)
When a function contains a
try/catch/finallywith an emptyfinallyblock, and thetryblock contains anifstatement with areturnthat is not taken, control flow is lost after thefinallyblock. The function returnsundefinedinstead of continuing to subsequent statements.To Reproduce
This JavaScript code reproduces the issue:
Adding an empty
finally {}breaks it:The only difference is the addition of
finally {}. Theif (x)condition isfalse(since0is falsy), so thereturn -1inside thetryblock is never executed. Control should fall through the emptyfinallyand reachreturn 42, but instead the function returnsundefined.Expected behavior
Both functions should return
42. The emptyfinally {}block should be a no-op, and control flow should continue toreturn 42.Build environment
3ce87f0fa03c5c037fb667f7f21a4996abbbc714(Note: this appears to be a regression. The bug does not reproduce on the releasedboa_engineversion0.21.1)Additional context
This was discovered while running React 19's
react-reconcilerinside Boa. React'sdispatchSetStateInternalfunction uses the exact patternif (cond) try { ... } catch (e) {} finally {}, causing all React state updates to silently fail — the function returnsundefined, and the code that schedules a re-render (after thefinally) is never reached.