From cbe0e8239d35d2095864f5bb0f6efecfb51649f4 Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Sun, 26 Jan 2025 10:30:33 +0000 Subject: [PATCH] feat(minifier): minimize `foo(...[])` -> `foo()` (#8726) --- crates/oxc_minifier/src/peephole/mod.rs | 8 ++++++++ .../src/peephole/remove_dead_code.rs | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/crates/oxc_minifier/src/peephole/mod.rs b/crates/oxc_minifier/src/peephole/mod.rs index a8558c03f5353..87d319ce13178 100644 --- a/crates/oxc_minifier/src/peephole/mod.rs +++ b/crates/oxc_minifier/src/peephole/mod.rs @@ -306,6 +306,14 @@ impl<'a> Traverse<'a> for LatePeepholeOptimizations { fn exit_catch_clause(&mut self, catch: &mut CatchClause<'a>, ctx: &mut TraverseCtx<'a>) { self.substitute_catch_clause(catch, Ctx(ctx)); } + + fn exit_call_expression(&mut self, e: &mut CallExpression<'a>, _ctx: &mut TraverseCtx<'a>) { + Self::remove_empty_spread_arguments(&mut e.arguments); + } + + fn exit_new_expression(&mut self, e: &mut NewExpression<'a>, _ctx: &mut TraverseCtx<'a>) { + Self::remove_empty_spread_arguments(&mut e.arguments); + } } pub struct DeadCodeElimination { diff --git a/crates/oxc_minifier/src/peephole/remove_dead_code.rs b/crates/oxc_minifier/src/peephole/remove_dead_code.rs index bd76163110170..b9a9e8941e163 100644 --- a/crates/oxc_minifier/src/peephole/remove_dead_code.rs +++ b/crates/oxc_minifier/src/peephole/remove_dead_code.rs @@ -620,6 +620,17 @@ impl<'a> LatePeepholeOptimizations { pub fn remove_dead_code_exit_class_body(body: &mut ClassBody<'a>, _ctx: Ctx<'a, '_>) { body.body.retain(|e| !matches!(e, ClassElement::StaticBlock(s) if s.body.is_empty())); } + + pub fn remove_empty_spread_arguments(args: &mut Vec<'a, Argument<'a>>) { + if args.len() != 1 { + return; + } + let Argument::SpreadElement(e) = &args[0] else { return }; + let Expression::ArrayExpression(e) = &e.argument else { return }; + if e.elements.is_empty() { + args.drain(..); + } + } } /// @@ -898,4 +909,10 @@ mod test { test_same("throw foo; export let bar"); test_same("throw foo; export default bar"); } + + #[test] + fn remove_empty_spread_arguments() { + test("foo(...[])", "foo()"); + test("new Foo(...[])", "new Foo()"); + } }