fix(minifier): correct issue with try finally termination (#25185)

fix bug with termination detection for `try finally`, 

when try has termination stmt and finally is missing it and we do not
have catch stmt current code passes it and allows stmt to fold

```js
// base
function f() {
	if (a) try { return g(); } finally {}
	else i();
}
// main
function f() {
	if (a) try { return g(); } finally {}
	i();
}
// this branch
function f() {
	if (a) try { return g(); } finally {}
	else i();
}
```

this issue has been introduced by
https://github.com/oxc-project/oxc/pull/24441 and copied over by
https://github.com/oxc-project/oxc/pull/24950


fixes #25214
This commit is contained in:
Armano authored and GitHub committed 2026-08-11 10:27:54 +08:00
1 parent 1645d93cfb
commit 5fcf6839ce
2 files changed
+27 -1

No files matched your search

+1 -1
View File
@@ -32,7 +32,7 @@ impl IsTerminated for TryStatement<'_> {
// present (an exception thrown before the try block's jump lands there).
self.finalizer.as_ref().is_some_and(|f| f.is_terminated())
|| (self.block.is_terminated()
&& self.handler.as_ref().is_none_or(|h| h.body.is_terminated()))
&& self.handler.as_ref().is_some_and(|h| h.body.is_terminated()))
}
}
@@ -319,6 +319,32 @@ fn test_dont_remove_break_in_try_finally() {
test_same("function f() {b:try{throw 9} finally {break b} return 1;}");
}
#[test]
fn test_try_catch_termination() {
test_same("function f(){if(a)try{b}catch{c}else throw i()}");
test_same("function f(){if(a)try{return g()}catch{c}else throw i()}");
test_same("function f(){if(a)try{b}catch{return g()}else throw i()}");
test(
"function f(){if(a)try{return g()}catch{return g()}else throw i()}",
"function f(){if(a)try{return g()}catch{return g()}throw i()}",
);
test_same("function f(){if(a)try{b}finally{d}else throw i()}");
test_same("function f(){if(a)try{return g()}finally{d}else throw i()}");
test(
"function f(){if(a)try{b}finally{return g()}else throw i()}",
"function f(){if(a)try{b}finally{return g()}throw i()}",
);
test_same("function f(){if(a)try{b}catch{c}finally{d}else throw i()}");
test_same("function f(){if(a)try{return g()}catch{d}finally{d}else throw i()}");
test_same("function f(){if(a)try{b}catch{return g()}finally{d}else throw i()}");
test(
"function f(){if(a)try{b}catch{c}finally{return g(d)}else throw i()}",
"function f(){if(a)try{b}catch{c}finally{return g(d)}throw i()}",
);
}
/**
* The 'break' prevents the 'b=false' from being evaluated. If we test the do-while to
* 'do;while(b=false)' the code will be incorrect.