Skip to content

Commit 1755f43

Browse files
committed
fix(minifier): remove expression statement void 0
1 parent 066ffe8 commit 1755f43

File tree

2 files changed

+63
-52
lines changed

2 files changed

+63
-52
lines changed

crates/oxc_ecmascript/src/constant_evaluation/is_literal_value.rs

+8
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ pub fn is_immutable_value(expr: &Expression<'_>) -> bool {
2727
Expression::Identifier(ident) => {
2828
matches!(ident.name.as_str(), "undefined" | "Infinity" | "NaN")
2929
}
30+
Expression::UnaryExpression(e)
31+
if matches!(
32+
e.operator,
33+
UnaryOperator::Void | UnaryOperator::LogicalNot | UnaryOperator::UnaryNegation
34+
) =>
35+
{
36+
is_immutable_value(&e.argument)
37+
}
3038
// Operations on bigint can result type error.
3139
// Expression::BigIntLiteral(_) => false,
3240
_ => false,

crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs

+55-52
Original file line numberDiff line numberDiff line change
@@ -326,60 +326,55 @@ impl<'a, 'b> PeepholeRemoveDeadCode {
326326
}
327327
}
328328

329-
stmt.expression
330-
.is_literal_value(false)
331-
.then(|| Some(ctx.ast.statement_empty(stmt.span)))
332-
.unwrap_or_else(|| match &mut stmt.expression {
333-
Expression::ArrayExpression(expr) => Self::try_fold_array_expression(expr, ctx),
334-
Expression::ObjectExpression(object_expr) => {
335-
Self::try_fold_object_expression(object_expr, ctx)
336-
}
337-
Expression::TemplateLiteral(template_lit) => {
338-
if !template_lit.expressions.is_empty() {
339-
return None;
340-
}
341-
let mut expressions = ctx.ast.move_vec(&mut template_lit.expressions);
342-
if expressions.len() == 0 {
343-
return Some(ctx.ast.statement_empty(stmt.span));
344-
} else if expressions.len() == 1 {
345-
return Some(
346-
ctx.ast.statement_expression(
347-
template_lit.span,
348-
expressions.pop().unwrap(),
349-
),
350-
);
351-
}
352-
Some(ctx.ast.statement_expression(
353-
template_lit.span,
354-
ctx.ast.expression_sequence(template_lit.span, expressions),
355-
))
356-
}
357-
Expression::FunctionExpression(function_expr) if function_expr.id.is_none() => {
358-
Some(ctx.ast.statement_empty(stmt.span))
359-
}
360-
Expression::ArrowFunctionExpression(_) => Some(ctx.ast.statement_empty(stmt.span)),
361-
// `typeof x` -> ``
362-
Expression::UnaryExpression(unary_expr)
363-
if unary_expr.operator.is_typeof()
364-
&& unary_expr.argument.is_identifier_reference() =>
365-
{
366-
Some(ctx.ast.statement_empty(stmt.span))
329+
if stmt.expression.is_literal_value(false) {
330+
return Some(ctx.ast.statement_empty(stmt.span));
331+
}
332+
333+
match &mut stmt.expression {
334+
Expression::ArrayExpression(expr) => Self::try_fold_array_expression(expr, ctx),
335+
Expression::ObjectExpression(object_expr) => {
336+
Self::try_fold_object_expression(object_expr, ctx)
337+
}
338+
Expression::TemplateLiteral(template_lit) => {
339+
if !template_lit.expressions.is_empty() {
340+
return None;
367341
}
368-
// `typeof x.y` -> `x.y`, `void x` -> `x`
369-
// `+0n` -> `Uncaught TypeError: Cannot convert a BigInt value to a number`
370-
Expression::UnaryExpression(unary_expr)
371-
if matches!(
372-
unary_expr.operator,
373-
UnaryOperator::Typeof | UnaryOperator::Void
374-
) =>
375-
{
376-
Some(ctx.ast.statement_expression(
377-
unary_expr.span,
378-
ctx.ast.move_expression(&mut unary_expr.argument),
379-
))
342+
let mut expressions = ctx.ast.move_vec(&mut template_lit.expressions);
343+
if expressions.len() == 0 {
344+
return Some(ctx.ast.statement_empty(stmt.span));
345+
} else if expressions.len() == 1 {
346+
return Some(
347+
ctx.ast.statement_expression(template_lit.span, expressions.pop().unwrap()),
348+
);
380349
}
381-
_ => None,
382-
})
350+
Some(ctx.ast.statement_expression(
351+
template_lit.span,
352+
ctx.ast.expression_sequence(template_lit.span, expressions),
353+
))
354+
}
355+
Expression::FunctionExpression(function_expr) if function_expr.id.is_none() => {
356+
Some(ctx.ast.statement_empty(stmt.span))
357+
}
358+
Expression::ArrowFunctionExpression(_) => Some(ctx.ast.statement_empty(stmt.span)),
359+
// `typeof x` -> ``
360+
Expression::UnaryExpression(unary_expr)
361+
if unary_expr.operator.is_typeof()
362+
&& unary_expr.argument.is_identifier_reference() =>
363+
{
364+
Some(ctx.ast.statement_empty(stmt.span))
365+
}
366+
// `typeof x.y` -> `x.y`, `void x` -> `x`
367+
// `+0n` -> `Uncaught TypeError: Cannot convert a BigInt value to a number`
368+
Expression::UnaryExpression(unary_expr)
369+
if matches!(unary_expr.operator, UnaryOperator::Typeof | UnaryOperator::Void) =>
370+
{
371+
Some(ctx.ast.statement_expression(
372+
unary_expr.span,
373+
ctx.ast.move_expression(&mut unary_expr.argument),
374+
))
375+
}
376+
_ => None,
377+
}
383378
}
384379

385380
fn try_fold_try(s: &mut TryStatement<'a>, ctx: Ctx<'a, 'b>) -> Option<Statement<'a>> {
@@ -837,4 +832,12 @@ mod test {
837832
test("class Foo { static {}; foo }", "class Foo { foo }");
838833
test_same("class Foo { static { foo() }");
839834
}
835+
836+
#[test]
837+
fn remove_expression_statement() {
838+
test("void 0", "");
839+
test("-1", "");
840+
test("!1", "");
841+
test("1", "");
842+
}
840843
}

0 commit comments

Comments
 (0)