feat(minifier): remove empty class static block class Foo { static {} } (#8525)

This commit is contained in:
Boshen 2025-01-16 02:46:25 +00:00
parent 2857ae15cd
commit 06f14d526b
2 changed files with 27 additions and 5 deletions

View file

@ -60,7 +60,7 @@ impl PeepholeOptimizations {
x3_collapse_variable_declarations: CollapseVariableDeclarations::new(),
x4_peephole_fold_constants: PeepholeFoldConstants::new(),
x5_peephole_minimize_conditions: PeepholeMinimizeConditions::new(target),
x6_peephole_remove_dead_code: PeepholeRemoveDeadCode::new(),
x6_peephole_remove_dead_code: PeepholeRemoveDeadCode::new(in_fixed_loop),
x7_convert_to_dotted_properties: ConvertToDottedProperties::new(in_fixed_loop),
x8_peephole_replace_known_methods: PeepholeReplaceKnownMethods::new(),
x9_peephole_substitute_alternate_syntax: PeepholeSubstituteAlternateSyntax::new(
@ -149,6 +149,10 @@ impl<'a> Traverse<'a> for PeepholeOptimizations {
self.x1_minimize_exit_points.exit_function_body(body, ctx);
}
fn exit_class_body(&mut self, body: &mut ClassBody<'a>, ctx: &mut TraverseCtx<'a>) {
self.x6_peephole_remove_dead_code.exit_class_body(body, ctx);
}
fn exit_variable_declaration(
&mut self,
decl: &mut VariableDeclaration<'a>,
@ -236,7 +240,7 @@ impl DeadCodeElimination {
pub fn new() -> Self {
Self {
x1_peephole_fold_constants: PeepholeFoldConstants::new(),
x2_peephole_remove_dead_code: PeepholeRemoveDeadCode::new(),
x2_peephole_remove_dead_code: PeepholeRemoveDeadCode::new(false),
}
}
}

View file

@ -17,6 +17,8 @@ use crate::{ctx::Ctx, keep_var::KeepVar, CompressorPass};
/// <https://github.com/google/closure-compiler/blob/v20240609/src/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java>
pub struct PeepholeRemoveDeadCode {
pub(crate) changed: bool,
in_fixed_loop: bool,
}
impl<'a> CompressorPass<'a> for PeepholeRemoveDeadCode {
@ -70,11 +72,17 @@ impl<'a> Traverse<'a> for PeepholeRemoveDeadCode {
self.changed = true;
}
}
fn exit_class_body(&mut self, body: &mut ClassBody<'a>, _ctx: &mut TraverseCtx<'a>) {
if !self.in_fixed_loop {
Self::remove_empty_class_static_block(body);
}
}
}
impl<'a, 'b> PeepholeRemoveDeadCode {
pub fn new() -> Self {
Self { changed: false }
pub fn new(in_fixed_loop: bool) -> Self {
Self { changed: false, in_fixed_loop }
}
/// Removes dead code thats comes after `return` statements after inlining `if` statements
@ -562,6 +570,10 @@ impl<'a, 'b> PeepholeRemoveDeadCode {
};
(params_empty && body_empty).then(|| ctx.ast.statement_empty(e.span))
}
fn remove_empty_class_static_block(body: &mut ClassBody<'a>) {
body.body.retain(|e| !matches!(e, ClassElement::StaticBlock(s) if s.body.is_empty()));
}
}
/// <https://github.com/google/closure-compiler/blob/v20240609/test/com/google/javascript/jscomp/PeepholeRemoveDeadCodeTest.java>
@ -573,7 +585,7 @@ mod test {
fn test(source_text: &str, positive: &str) {
let allocator = Allocator::default();
let mut pass = super::PeepholeRemoveDeadCode::new();
let mut pass = super::PeepholeRemoveDeadCode::new(false);
tester::test(&allocator, source_text, positive, &mut pass);
}
@ -791,4 +803,10 @@ mod test {
// test("/* @__PURE__ */ (() => x)()", "");
// test("/* @__PURE__ */ (() => x)(y, z)", "y, z;");
}
#[test]
fn test_remove_empty_static_block() {
test("class Foo { static {}; foo }", "class Foo { foo }");
test_same("class Foo { static { foo() }");
}
}