From 2c2e483d35b1f51f3c0cbae206fc5dcd7e132b31 Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Wed, 8 Jan 2025 09:11:28 +0000 Subject: [PATCH] feat(minifier): fold object spread `({ ...null })` -> `({})` (#8339) --- .../src/ast_passes/peephole_fold_constants.rs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs index 48da758ae4660..93e330c4711f7 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs @@ -37,6 +37,7 @@ impl<'a> Traverse<'a> for PeepholeFoldConstants { Expression::LogicalExpression(e) => Self::try_fold_logical_expr(e, ctx), Expression::ChainExpression(e) => Self::try_fold_optional_chain(e, ctx), Expression::CallExpression(e) => Self::try_fold_number_constructor(e, ctx), + Expression::ObjectExpression(e) => self.fold_object_spread(e, ctx), _ => None, } { *expr = folded_expr; @@ -654,6 +655,38 @@ impl<'a, 'b> PeepholeFoldConstants { None } + + fn fold_object_spread( + &mut self, + e: &mut ObjectExpression<'a>, + ctx: Ctx<'a, 'b>, + ) -> Option> { + let len = e.properties.len(); + e.properties.retain(|p| { + if let ObjectPropertyKind::SpreadProperty(spread_element) = p { + let e = &spread_element.argument; + if e.is_literal() || ctx.is_expression_undefined(e) { + return false; + } + if let Expression::ObjectExpression(o) = e { + if o.properties.is_empty() { + return false; + } + } + if let Expression::ArrayExpression(o) = e { + if o.elements.is_empty() { + return false; + } + } + return true; + } + true + }); + if e.properties.len() != len { + self.changed = true; + } + None + } } /// @@ -1830,5 +1863,20 @@ mod test { test_same("{ valueOf: function() { return 0n; } } != 0n"); test_same("{ toString: function() { return '0'; } } != 0n"); } + + #[test] + fn test_fold_object_spread() { + test_same("({ z, ...a })"); + let result = "({ z })"; + test("({ z, ...[] })", result); + test("({ z, ...{} })", result); + test("({ z, ...undefined })", result); + test("({ z, ...void 0 })", result); + test("({ z, ...null })", result); + test("({ z, ...true })", result); + test("({ z, ...1 })", result); + test("({ z, ...1n })", result); + test("({ z, .../asdf/ })", result); + } } }