feat(minfier): dce if (xxx) else if (false) { REMOVE } (#4407)

This commit is contained in:
Boshen 2024-07-22 21:57:35 +10:00 committed by GitHub
parent d79b60afc4
commit 0deb027e6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 40 additions and 12 deletions

View file

@ -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 => {}
}
}

View file

@ -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 }");