oxc_minifier/
compressor.rs

1use oxc_allocator::Allocator;
2use oxc_ast::ast::*;
3use oxc_semantic::{Scoping, SemanticBuilder};
4use oxc_traverse::ReusableTraverseCtx;
5
6use crate::{
7    CompressOptions,
8    peephole::{DeadCodeElimination, Normalize, NormalizeOptions, PeepholeOptimizations},
9    state::MinifierState,
10};
11
12pub struct Compressor<'a> {
13    allocator: &'a Allocator,
14}
15
16impl<'a> Compressor<'a> {
17    pub fn new(allocator: &'a Allocator) -> Self {
18        Self { allocator }
19    }
20
21    pub fn build(self, program: &mut Program<'a>, options: CompressOptions) {
22        let scoping = SemanticBuilder::new().build(program).semantic.into_scoping();
23        self.build_with_scoping(program, scoping, options);
24    }
25
26    /// Returns total number of iterations ran.
27    pub fn build_with_scoping(
28        self,
29        program: &mut Program<'a>,
30        scoping: Scoping,
31        options: CompressOptions,
32    ) -> u8 {
33        let max_iterations = options.max_iterations;
34        let state = MinifierState::new(program.source_type, options);
35        let mut ctx = ReusableTraverseCtx::new(state, scoping, self.allocator);
36        let normalize_options = NormalizeOptions {
37            convert_while_to_fors: true,
38            convert_const_to_let: true,
39            remove_unnecessary_use_strict: true,
40        };
41        Normalize::new(normalize_options).build(program, &mut ctx);
42        PeepholeOptimizations::new(max_iterations).run_in_loop(program, &mut ctx)
43    }
44
45    pub fn dead_code_elimination(self, program: &mut Program<'a>, options: CompressOptions) -> u8 {
46        let scoping = SemanticBuilder::new().build(program).semantic.into_scoping();
47        self.dead_code_elimination_with_scoping(program, scoping, options)
48    }
49
50    /// Returns total number of iterations ran.
51    pub fn dead_code_elimination_with_scoping(
52        self,
53        program: &mut Program<'a>,
54        scoping: Scoping,
55        options: CompressOptions,
56    ) -> u8 {
57        let max_iterations = options.max_iterations;
58        let state = MinifierState::new(program.source_type, options);
59        let mut ctx = ReusableTraverseCtx::new(state, scoping, self.allocator);
60        let normalize_options = NormalizeOptions {
61            convert_while_to_fors: false,
62            convert_const_to_let: false,
63            remove_unnecessary_use_strict: false,
64        };
65        Normalize::new(normalize_options).build(program, &mut ctx);
66        DeadCodeElimination::new(max_iterations).run_in_loop(program, &mut ctx)
67    }
68}