diff --git a/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs b/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs index dba1cde889e25..4bbb09eb0a87e 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs @@ -142,7 +142,8 @@ impl<'a> Traverse<'a> for PeepholeSubstituteAlternateSyntax { Expression::LogicalExpression(e) => Self::try_compress_is_null_or_undefined(e, ctx), Expression::NewExpression(e) => Self::try_fold_new_expression(e, ctx), Expression::TemplateLiteral(t) => Self::try_fold_template_literal(t, ctx), - Expression::BinaryExpression(e) => Self::try_compress_typeof_undefined(e, ctx), + Expression::BinaryExpression(e) => Self::try_fold_loose_equals_undefined(e, ctx) + .or_else(|| Self::try_compress_typeof_undefined(e, ctx)), Expression::CallExpression(e) => { Self::try_fold_literal_constructor_call_expression(e, ctx) .or_else(|| Self::try_fold_simple_function_call(e, ctx)) @@ -448,6 +449,32 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax { } None } + fn try_fold_loose_equals_undefined( + e: &mut BinaryExpression<'a>, + ctx: Ctx<'a, 'b>, + ) -> Option> { + // `foo == void 0` -> `foo == null`, `foo == undefined` -> `foo == null` + // `foo != void 0` -> `foo == null`, `foo == undefined` -> `foo == null` + if e.operator == BinaryOperator::Inequality || e.operator == BinaryOperator::Equality { + let (left, right) = if e.right.is_undefined() || e.right.is_void_0() { + ( + ctx.ast.move_expression(&mut e.left), + ctx.ast.expression_null_literal(e.right.span()), + ) + } else if e.left.is_undefined() || e.left.is_void_0() { + ( + ctx.ast.move_expression(&mut e.right), + ctx.ast.expression_null_literal(e.left.span()), + ) + } else { + return None; + }; + + return Some(ctx.ast.expression_binary(e.span, left, e.operator, right)); + } + + None + } /// Removes redundant argument of `ReturnStatement` /// @@ -1328,6 +1355,15 @@ mod test { test_same("foo !== void 0 && bar !== null"); } + #[test] + fn test_fold_loose_equals_undefined() { + test_same("foo != null"); + test("foo != undefined", "foo != null"); + test("foo != void 0", "foo != null"); + test("undefined != foo", "foo != null"); + test("void 0 != foo", "foo != null"); + } + #[test] fn test_try_compress_type_of_equal_string() { test("typeof foo === 'number'", "typeof foo == 'number'");