diff --git a/crates/oxc_ecmascript/src/constant_evaluation/is_literal_value.rs b/crates/oxc_ecmascript/src/constant_evaluation/is_literal_value.rs index 01ffb6c23f5b41..22317a71002496 100644 --- a/crates/oxc_ecmascript/src/constant_evaluation/is_literal_value.rs +++ b/crates/oxc_ecmascript/src/constant_evaluation/is_literal_value.rs @@ -27,6 +27,14 @@ pub fn is_immutable_value(expr: &Expression<'_>) -> bool { Expression::Identifier(ident) => { matches!(ident.name.as_str(), "undefined" | "Infinity" | "NaN") } + Expression::UnaryExpression(e) + if matches!( + e.operator, + UnaryOperator::Void | UnaryOperator::LogicalNot | UnaryOperator::UnaryNegation + ) => + { + is_immutable_value(&e.argument) + } // Operations on bigint can result type error. // Expression::BigIntLiteral(_) => false, _ => false, 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 4054bad05d5172..a9d66b7e6fab51 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 @@ -326,60 +326,55 @@ impl<'a, 'b> PeepholeRemoveDeadCode { } } - stmt.expression - .is_literal_value(false) - .then(|| Some(ctx.ast.statement_empty(stmt.span))) - .unwrap_or_else(|| match &mut stmt.expression { - Expression::ArrayExpression(expr) => Self::try_fold_array_expression(expr, ctx), - Expression::ObjectExpression(object_expr) => { - Self::try_fold_object_expression(object_expr, ctx) - } - Expression::TemplateLiteral(template_lit) => { - if !template_lit.expressions.is_empty() { - return None; - } - let mut expressions = ctx.ast.move_vec(&mut template_lit.expressions); - if expressions.len() == 0 { - return Some(ctx.ast.statement_empty(stmt.span)); - } else if expressions.len() == 1 { - return Some( - ctx.ast.statement_expression( - template_lit.span, - expressions.pop().unwrap(), - ), - ); - } - Some(ctx.ast.statement_expression( - template_lit.span, - ctx.ast.expression_sequence(template_lit.span, expressions), - )) - } - Expression::FunctionExpression(function_expr) if function_expr.id.is_none() => { - Some(ctx.ast.statement_empty(stmt.span)) - } - Expression::ArrowFunctionExpression(_) => Some(ctx.ast.statement_empty(stmt.span)), - // `typeof x` -> `` - Expression::UnaryExpression(unary_expr) - if unary_expr.operator.is_typeof() - && unary_expr.argument.is_identifier_reference() => - { - Some(ctx.ast.statement_empty(stmt.span)) + if stmt.expression.is_literal_value(false) { + return Some(ctx.ast.statement_empty(stmt.span)); + } + + match &mut stmt.expression { + Expression::ArrayExpression(expr) => Self::try_fold_array_expression(expr, ctx), + Expression::ObjectExpression(object_expr) => { + Self::try_fold_object_expression(object_expr, ctx) + } + Expression::TemplateLiteral(template_lit) => { + if !template_lit.expressions.is_empty() { + return None; } - // `typeof x.y` -> `x.y`, `void x` -> `x` - // `+0n` -> `Uncaught TypeError: Cannot convert a BigInt value to a number` - Expression::UnaryExpression(unary_expr) - if matches!( - unary_expr.operator, - UnaryOperator::Typeof | UnaryOperator::Void - ) => - { - Some(ctx.ast.statement_expression( - unary_expr.span, - ctx.ast.move_expression(&mut unary_expr.argument), - )) + let mut expressions = ctx.ast.move_vec(&mut template_lit.expressions); + if expressions.len() == 0 { + return Some(ctx.ast.statement_empty(stmt.span)); + } else if expressions.len() == 1 { + return Some( + ctx.ast.statement_expression(template_lit.span, expressions.pop().unwrap()), + ); } - _ => None, - }) + Some(ctx.ast.statement_expression( + template_lit.span, + ctx.ast.expression_sequence(template_lit.span, expressions), + )) + } + Expression::FunctionExpression(function_expr) if function_expr.id.is_none() => { + Some(ctx.ast.statement_empty(stmt.span)) + } + Expression::ArrowFunctionExpression(_) => Some(ctx.ast.statement_empty(stmt.span)), + // `typeof x` -> `` + Expression::UnaryExpression(unary_expr) + if unary_expr.operator.is_typeof() + && unary_expr.argument.is_identifier_reference() => + { + Some(ctx.ast.statement_empty(stmt.span)) + } + // `typeof x.y` -> `x.y`, `void x` -> `x` + // `+0n` -> `Uncaught TypeError: Cannot convert a BigInt value to a number` + Expression::UnaryExpression(unary_expr) + if matches!(unary_expr.operator, UnaryOperator::Typeof | UnaryOperator::Void) => + { + Some(ctx.ast.statement_expression( + unary_expr.span, + ctx.ast.move_expression(&mut unary_expr.argument), + )) + } + _ => None, + } } fn try_fold_try(s: &mut TryStatement<'a>, ctx: Ctx<'a, 'b>) -> Option> { @@ -837,4 +832,12 @@ mod test { test("class Foo { static {}; foo }", "class Foo { foo }"); test_same("class Foo { static { foo() }"); } + + #[test] + fn remove_expression_statement() { + test("void 0", ""); + test("-1", ""); + test("!1", ""); + test("1", ""); + } }