From 1314c9763b7ade5691d2245df6c93d3d20c18ecf Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Tue, 17 Dec 2024 04:47:13 +0000 Subject: [PATCH] refactor(minifier): expose dce as an API instead of an option (#7957) --- crates/oxc/src/compiler.rs | 8 ++++-- crates/oxc_minifier/src/compressor.rs | 28 +++++++++++++------ crates/oxc_minifier/src/options.rs | 12 ++------ .../tests/ast_passes/dead_code_elimination.rs | 19 +++++++++++-- crates/oxc_wasm/src/lib.rs | 1 - 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/crates/oxc/src/compiler.rs b/crates/oxc/src/compiler.rs index 664563780f893..2c8e170d53549 100644 --- a/crates/oxc/src/compiler.rs +++ b/crates/oxc/src/compiler.rs @@ -198,8 +198,12 @@ pub trait CompilerInterface { if let Some(options) = define_options { let ret = ReplaceGlobalDefines::new(&allocator, options).build(symbols, scopes, &mut program); - Compressor::new(&allocator, CompressOptions::dead_code_elimination()) - .build_with_symbols_and_scopes(ret.symbols, ret.scopes, &mut program); + Compressor::new(&allocator, CompressOptions::default()) + .dead_code_elimination_with_symbols_and_scopes( + ret.symbols, + ret.scopes, + &mut program, + ); // symbols = ret.symbols; // scopes = ret.scopes; } diff --git a/crates/oxc_minifier/src/compressor.rs b/crates/oxc_minifier/src/compressor.rs index a746093bd810c..dc1c6def1d8a3 100644 --- a/crates/oxc_minifier/src/compressor.rs +++ b/crates/oxc_minifier/src/compressor.rs @@ -35,20 +35,30 @@ impl<'a> Compressor<'a> { ) { let mut ctx = ReusableTraverseCtx::new(scopes, symbols, self.allocator); RemoveSyntax::new(self.options).build(program, &mut ctx); - - if self.options.dead_code_elimination { - Self::dead_code_elimination(program, &mut ctx); - return; - } - PeepholeOptimizations::new().build(program, &mut ctx); CollapsePass::new().build(program, &mut ctx); LatePeepholeOptimizations::new().run_in_loop(program, &mut ctx); PeepholeOptimizations::new().build(program, &mut ctx); } - fn dead_code_elimination(program: &mut Program<'a>, ctx: &mut ReusableTraverseCtx<'a>) { - PeepholeFoldConstants::new().build(program, ctx); - PeepholeRemoveDeadCode::new().build(program, ctx); + pub fn dead_code_elimination(self, program: &mut Program<'a>) { + let (symbols, scopes) = + SemanticBuilder::new().build(program).semantic.into_symbol_table_and_scope_tree(); + let mut ctx = ReusableTraverseCtx::new(scopes, symbols, self.allocator); + RemoveSyntax::new(self.options).build(program, &mut ctx); + PeepholeFoldConstants::new().build(program, &mut ctx); + PeepholeRemoveDeadCode::new().build(program, &mut ctx); + } + + pub fn dead_code_elimination_with_symbols_and_scopes( + self, + symbols: SymbolTable, + scopes: ScopeTree, + program: &mut Program<'a>, + ) { + let mut ctx = ReusableTraverseCtx::new(scopes, symbols, self.allocator); + RemoveSyntax::new(self.options).build(program, &mut ctx); + PeepholeFoldConstants::new().build(program, &mut ctx); + PeepholeRemoveDeadCode::new().build(program, &mut ctx); } } diff --git a/crates/oxc_minifier/src/options.rs b/crates/oxc_minifier/src/options.rs index 9a3c1f3b4c978..0cb3aa16e3724 100644 --- a/crates/oxc_minifier/src/options.rs +++ b/crates/oxc_minifier/src/options.rs @@ -1,7 +1,5 @@ #[derive(Debug, Clone, Copy)] pub struct CompressOptions { - pub dead_code_elimination: bool, - /// Remove `debugger;` statements. /// /// Default `true` @@ -16,20 +14,16 @@ pub struct CompressOptions { #[allow(clippy::derivable_impls)] impl Default for CompressOptions { fn default() -> Self { - Self { dead_code_elimination: false, drop_console: false, ..Self::all_true() } + Self { drop_console: false, ..Self::all_true() } } } impl CompressOptions { pub fn all_true() -> Self { - Self { dead_code_elimination: false, drop_debugger: true, drop_console: true } + Self { drop_debugger: true, drop_console: true } } pub fn all_false() -> Self { - Self { dead_code_elimination: false, drop_debugger: false, drop_console: false } - } - - pub fn dead_code_elimination() -> Self { - Self { dead_code_elimination: true, ..Self::all_false() } + Self { drop_debugger: false, drop_console: false } } } diff --git a/crates/oxc_minifier/tests/ast_passes/dead_code_elimination.rs b/crates/oxc_minifier/tests/ast_passes/dead_code_elimination.rs index f366e3fc60ae0..85759a07abff5 100644 --- a/crates/oxc_minifier/tests/ast_passes/dead_code_elimination.rs +++ b/crates/oxc_minifier/tests/ast_passes/dead_code_elimination.rs @@ -1,6 +1,19 @@ use cow_utils::CowUtils; +use oxc_allocator::Allocator; +use oxc_codegen::Codegen; use oxc_minifier::CompressOptions; +use oxc_minifier::Compressor; +use oxc_parser::Parser; +use oxc_span::SourceType; + +fn run(source_text: &str, source_type: SourceType) -> String { + let allocator = Allocator::default(); + let mut ret = Parser::new(&allocator, source_text, source_type).parse(); + let program = &mut ret.program; + Compressor::new(&allocator, CompressOptions::default()).dead_code_elimination(program); + Codegen::new().build(program).code +} fn test(source_text: &str, expected: &str) { let t = "('production' == 'production')"; @@ -8,8 +21,10 @@ fn test(source_text: &str, expected: &str) { let source_text = source_text.cow_replace("true", t); let source_text = source_text.cow_replace("false", f); - let options = CompressOptions::dead_code_elimination(); - crate::test(&source_text, expected, options); + let source_type = SourceType::default(); + let result = run(&source_text, source_type); + let expected = run(expected, source_type); + assert_eq!(result, expected, "\nfor source\n{source_text}\nexpect\n{expected}\ngot\n{result}"); } fn test_same(source_text: &str) { diff --git a/crates/oxc_wasm/src/lib.rs b/crates/oxc_wasm/src/lib.rs index f53839c540bb2..518f4fbe948a4 100644 --- a/crates/oxc_wasm/src/lib.rs +++ b/crates/oxc_wasm/src/lib.rs @@ -274,7 +274,6 @@ impl Oxc { CompressOptions { drop_console: compress_options.drop_console, drop_debugger: compress_options.drop_debugger, - ..CompressOptions::default() } } else { CompressOptions::all_false()