diff --git a/crates/oxc_minifier/src/ast_passes/remove_dead_code.rs b/crates/oxc_minifier/src/ast_passes/remove_dead_code.rs index a7bad43fc0fd9..8d0e1be6fbbee 100644 --- a/crates/oxc_minifier/src/ast_passes/remove_dead_code.rs +++ b/crates/oxc_minifier/src/ast_passes/remove_dead_code.rs @@ -44,7 +44,7 @@ impl<'a> RemoveDeadCode<'a> { fn dead_code_elimintation(&mut self, stmts: &mut Vec<'a, Statement<'a>>) { // Fold if statements for stmt in stmts.iter_mut() { - if self.fold_if_statement(stmt) {} + self.fold_if_statement(stmt); } // Remove code after `return` and `throw` statements @@ -80,13 +80,20 @@ impl<'a> RemoveDeadCode<'a> { } } - #[must_use] - fn fold_if_statement(&mut self, stmt: &mut Statement<'a>) -> bool { - let Statement::IfStatement(if_stmt) = stmt else { return false }; + fn fold_if_statement(&mut self, stmt: &mut Statement<'a>) { + let Statement::IfStatement(if_stmt) = stmt else { return }; + + // Descend and remove `else` blocks first. + if let Some(alternate) = &mut if_stmt.alternate { + self.fold_if_statement(alternate); + if matches!(alternate, Statement::EmptyStatement(_)) { + if_stmt.alternate = None; + } + } + match self.fold_expression_and_get_boolean_value(&mut if_stmt.test) { Some(true) => { *stmt = self.ast.move_statement(&mut if_stmt.consequent); - true } Some(false) => { *stmt = if let Some(alternate) = &mut if_stmt.alternate { @@ -95,15 +102,12 @@ impl<'a> RemoveDeadCode<'a> { // Keep hoisted `vars` from the consequent block. let mut keep_var = KeepVar::new(self.ast); keep_var.visit_statement(&if_stmt.consequent); - if let Some(stmt) = keep_var.get_variable_declaration_statement() { - stmt - } else { - self.ast.statement_empty(SPAN) - } + keep_var + .get_variable_declaration_statement() + .unwrap_or_else(|| self.ast.statement_empty(SPAN)) }; - true } - _ => false, + None => {} } } diff --git a/crates/oxc_minifier/tests/oxc/remove_dead_code.rs b/crates/oxc_minifier/tests/oxc/remove_dead_code.rs index 13a71266b0541..06b40f5667b62 100644 --- a/crates/oxc_minifier/tests/oxc/remove_dead_code.rs +++ b/crates/oxc_minifier/tests/oxc/remove_dead_code.rs @@ -30,6 +30,30 @@ fn dce_if_statement() { test("if (true) { foo } else { bar }", "{ foo }"); test("if (false) { foo } else { bar }", "{ bar }"); + test("if (xxx) { foo } else if (false) { bar }", "if (xxx) { foo }"); + test("if (xxx) { foo } else if (false) { bar } else { baz }", "if (xxx) { foo } else { baz }"); + test("if (xxx) { foo } else if (false) { bar } else if (false) { baz }", "if (xxx) { foo }"); + test( + "if (xxx) { foo } else if (false) { bar } else if (false) { baz } else { quaz }", + "if (xxx) { foo } else { quaz }", + ); + test( + "if (xxx) { foo } else if (true) { bar } else if (false) { baz }", + "if (xxx) { foo } else { bar }", + ); + test( + "if (xxx) { foo } else if (false) { bar } else if (true) { baz }", + "if (xxx) { foo } else { baz }", + ); + test( + "if (xxx) { foo } else if (true) { bar } else if (true) { baz }", + "if (xxx) { foo } else { bar }", + ); + test( + "if (xxx) { foo } else if (false) { var a; var b; } else if (false) { var c; var d; }", + "if (xxx) { foo } else var c, d;", + ); + test("if (!false) { foo }", "{ foo }"); test("if (!true) { foo } else { bar }", "{ bar }");