oxc_minifier/
lib.rs

1//! ECMAScript Minifier
2
3#![allow(clippy::literal_string_with_formatting_args, clippy::needless_pass_by_ref_mut)]
4
5mod compressor;
6mod ctx;
7mod keep_var;
8mod options;
9mod peephole;
10mod state;
11mod symbol_value;
12
13#[cfg(test)]
14mod tester;
15
16use oxc_allocator::Allocator;
17use oxc_ast::ast::Program;
18use oxc_mangler::Mangler;
19use oxc_semantic::{Scoping, SemanticBuilder};
20
21pub use oxc_mangler::{MangleOptions, MangleOptionsKeepNames};
22
23pub use crate::{compressor::Compressor, options::*};
24
25#[derive(Debug, Clone)]
26pub struct MinifierOptions {
27    pub mangle: Option<MangleOptions>,
28    pub compress: Option<CompressOptions>,
29}
30
31impl Default for MinifierOptions {
32    fn default() -> Self {
33        Self { mangle: Some(MangleOptions::default()), compress: Some(CompressOptions::default()) }
34    }
35}
36
37pub struct MinifierReturn {
38    pub scoping: Option<Scoping>,
39
40    /// Total number of iterations ran. Useful for debugging performance issues.
41    pub iterations: u8,
42}
43
44pub struct Minifier {
45    options: MinifierOptions,
46}
47
48impl Minifier {
49    pub fn new(options: MinifierOptions) -> Self {
50        Self { options }
51    }
52
53    pub fn build<'a>(self, allocator: &'a Allocator, program: &mut Program<'a>) -> MinifierReturn {
54        let (stats, iterations) = self
55            .options
56            .compress
57            .map(|options| {
58                let semantic = SemanticBuilder::new().build(program).semantic;
59                let stats = semantic.stats();
60                let scoping = semantic.into_scoping();
61                let iterations =
62                    Compressor::new(allocator).build_with_scoping(program, scoping, options);
63                (stats, iterations)
64            })
65            .unwrap_or_default();
66        let scoping = self.options.mangle.map(|options| {
67            let mut semantic = SemanticBuilder::new()
68                .with_stats(stats)
69                .with_scope_tree_child_ids(true)
70                .build(program)
71                .semantic;
72            Mangler::default().with_options(options).build_with_semantic(&mut semantic, program);
73            semantic.into_scoping()
74        });
75        MinifierReturn { scoping, iterations }
76    }
77}