diff --git a/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs b/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs index 34f35b33d083c8..b63c6ed907a71d 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs @@ -310,6 +310,13 @@ impl<'a, 'b> PeepholeRemoveDeadCode { Expression::FunctionExpression(function_expr) if function_expr.id.is_none() => { Some(ctx.ast.statement_empty(SPAN)) } + // `typeof x` -> `x`, `!x` -> `x`, `void x` -> `x`... + Expression::UnaryExpression(unary_expr) if !unary_expr.operator.is_delete() => { + Some(ctx.ast.statement_expression( + unary_expr.span, + ctx.ast.move_expression(&mut unary_expr.argument), + )) + } _ => None, }) } @@ -548,4 +555,25 @@ mod test { fold("([...a, b, ...c])", "([...a, ...c])"); fold_same("([...b, ...c])"); // It would also be fine if the spreads were split apart. } + + #[test] + fn test_fold_unary_expression_statement() { + fold("typeof x", "x"); + fold("typeof x?.y", "x?.y"); + fold("typeof x.y", "x.y"); + fold("typeof x.y.z()", "x.y.z()"); + fold("void x", "x"); + fold("void x?.y", "x?.y"); + fold("void x.y", "x.y"); + fold("void x.y.z()", "x.y.z()"); + fold("!x", "x"); + fold("!x?.y", "x?.y"); + fold("!x.y", "x.y"); + fold("!x.y.z()", "x.y.z()"); + fold("-x.y.z()", "x.y.z()"); + + fold_same("delete x"); + fold_same("delete x.y"); + fold_same("delete x.y.z()"); + } } diff --git a/crates/oxc_syntax/src/operator.rs b/crates/oxc_syntax/src/operator.rs index 76ac35d9e8bfc5..0d295d9204bf01 100644 --- a/crates/oxc_syntax/src/operator.rs +++ b/crates/oxc_syntax/src/operator.rs @@ -498,6 +498,11 @@ impl UnaryOperator { self == Self::Void } + /// Returns `true` if this is the [`delete`](UnaryOperator::Delete) operator. + pub fn is_delete(self) -> bool { + self == Self::Delete + } + /// Returns `true` if this operator is a keyword instead of punctuation. pub fn is_keyword(self) -> bool { matches!(self, Self::Typeof | Self::Void | Self::Delete) diff --git a/tasks/minsize/minsize.snap b/tasks/minsize/minsize.snap index 36875636bc1213..cb8dbf88029b24 100644 --- a/tasks/minsize/minsize.snap +++ b/tasks/minsize/minsize.snap @@ -21,7 +21,7 @@ Original | minified | minified | gzip | gzip | Fixture 3.20 MB | 1.01 MB | 1.01 MB | 331.90 kB | 331.56 kB | echarts.js -6.69 MB | 2.32 MB | 2.31 MB | 492.86 kB | 488.28 kB | antd.js +6.69 MB | 2.32 MB | 2.31 MB | 492.87 kB | 488.28 kB | antd.js -10.95 MB | 3.50 MB | 3.49 MB | 909.32 kB | 915.50 kB | typescript.js +10.95 MB | 3.50 MB | 3.49 MB | 909.30 kB | 915.50 kB | typescript.js