From cdc39ff7e5f8f2dda6a2f745a38ffb8751888fa9 Mon Sep 17 00:00:00 2001 From: Boshen Date: Fri, 10 Jan 2025 18:16:55 +0800 Subject: [PATCH] feat(minifier): fold `ambiguous if else` --- .../oxc_minifier/src/ast_passes/normalize.rs | 25 +++++++++++++++++-- crates/oxc_minifier/tests/ast_passes/mod.rs | 19 ++++++++++++++ tasks/minsize/src/lib.rs | 1 + 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/crates/oxc_minifier/src/ast_passes/normalize.rs b/crates/oxc_minifier/src/ast_passes/normalize.rs index c99232e9911b0..c7b613838dc1b 100644 --- a/crates/oxc_minifier/src/ast_passes/normalize.rs +++ b/crates/oxc_minifier/src/ast_passes/normalize.rs @@ -1,4 +1,5 @@ use oxc_ast::ast::*; +use oxc_span::GetSpan; use oxc_syntax::scope::ScopeFlags; use oxc_traverse::{traverse_mut_with_ctx, ReusableTraverseCtx, Traverse, TraverseCtx}; @@ -23,8 +24,12 @@ impl<'a> CompressorPass<'a> for Normalize { impl<'a> Traverse<'a> for Normalize { fn exit_statement(&mut self, stmt: &mut Statement<'a>, ctx: &mut TraverseCtx<'a>) { - if matches!(stmt, Statement::WhileStatement(_)) { - Self::convert_while_to_for(stmt, ctx); + match stmt { + Statement::WhileStatement(_) => { + Self::convert_while_to_for(stmt, ctx); + } + Statement::IfStatement(s) => Self::wrap_to_avoid_ambiguous_else(s, ctx), + _ => {} } } @@ -68,6 +73,22 @@ impl<'a> Normalize { ctx.ast.expression_numeric_literal(ident.span, value, None, NumberBase::Decimal); } } + + // Wrap to avoid ambiguous else. + // `if (foo) if (bar) baz else quaz` -> `if (foo) { if (bar) baz else quaz }` + fn wrap_to_avoid_ambiguous_else(if_stmt: &mut IfStatement<'a>, ctx: &mut TraverseCtx<'a>) { + if let Statement::IfStatement(if2) = &mut if_stmt.consequent { + if if2.alternate.is_some() { + let scope_id = ctx.create_child_scope_of_current(ScopeFlags::empty()); + if_stmt.consequent = + Statement::BlockStatement(ctx.ast.alloc_block_statement_with_scope_id( + if_stmt.consequent.span(), + ctx.ast.vec1(ctx.ast.move_statement(&mut if_stmt.consequent)), + scope_id, + )); + } + } + } } #[cfg(test)] diff --git a/crates/oxc_minifier/tests/ast_passes/mod.rs b/crates/oxc_minifier/tests/ast_passes/mod.rs index ca5a0258a26f2..c58a2ecfc4f9c 100644 --- a/crates/oxc_minifier/tests/ast_passes/mod.rs +++ b/crates/oxc_minifier/tests/ast_passes/mod.rs @@ -13,6 +13,25 @@ fn test_same(source_text: &str) { // Oxc Integration Tests +#[test] +fn integration() { + test( + "function writeInteger(int) { + if (int >= 0) + if (int <= 0xffffffff) + return this.u32(int); + else if (int > -0x80000000) + return this.n32(int); + }", + "function writeInteger(int) { + if (int >= 0) { + if (int <= 4294967295) return this.u32(int); + if (int > -2147483648) return this.n32(int); + } + }", + ); +} + #[test] // https://github.com/oxc-project/oxc/issues/4341 fn tagged_template() { test_same("(1, o.f)()"); diff --git a/tasks/minsize/src/lib.rs b/tasks/minsize/src/lib.rs index 516e503c813fc..2a354e7e457e6 100644 --- a/tasks/minsize/src/lib.rs +++ b/tasks/minsize/src/lib.rs @@ -98,6 +98,7 @@ pub fn run() -> Result<(), io::Error> { let save_path = Path::new("./target/minifier").join(marker); for file in files.files() { + println!("{}", &file.file_name); let minified = minify_twice(file); fs::create_dir_all(&save_path).unwrap();