Skip to main content

oxc_minifier/
options.rs

1use oxc_compat::EngineTargets;
2use rustc_hash::FxHashSet;
3
4pub use oxc_ecmascript::side_effects::PropertyReadSideEffects;
5
6#[derive(Debug, Clone)]
7pub struct CompressOptions {
8    /// Engine targets for feature detection.
9    ///
10    /// Used to determine which ES features are supported by the target engines
11    /// and whether transformations can be applied.
12    ///
13    /// Default: empty (supports all features)
14    pub target: EngineTargets,
15
16    /// Remove `debugger;` statements.
17    ///
18    /// Default `true`
19    pub drop_debugger: bool,
20
21    /// Remove `console.*` statements.
22    ///
23    /// Default `false`
24    pub drop_console: bool,
25
26    /// Join consecutive var, let and const statements.
27    ///
28    /// Default `true`
29    pub join_vars: bool,
30
31    /// Join consecutive simple statements using the comma operator.
32    ///
33    /// `a; b` -> `a, b`
34    ///
35    /// Default `true`
36    pub sequences: bool,
37
38    /// Drop unreferenced functions and variables.
39    pub unused: CompressOptionsUnused,
40
41    /// Keep function / class names.
42    pub keep_names: CompressOptionsKeepNames,
43
44    /// Treeshake Options .
45    /// <https://rollupjs.org/configuration-options/#treeshake>
46    pub treeshake: TreeShakeOptions,
47
48    /// Set of label names to drop from the code.
49    ///
50    /// Labeled statements matching these names will be removed during minification.
51    ///
52    /// Default: empty (no labels dropped)
53    pub drop_labels: FxHashSet<String>,
54
55    /// Limit the maximum number of iterations for debugging purpose.
56    pub max_iterations: Option<u8>,
57}
58
59impl Default for CompressOptions {
60    fn default() -> Self {
61        Self::smallest()
62    }
63}
64
65impl CompressOptions {
66    pub fn smallest() -> Self {
67        Self {
68            target: EngineTargets::default(),
69            keep_names: CompressOptionsKeepNames::all_false(),
70            drop_debugger: true,
71            drop_console: false,
72            join_vars: true,
73            sequences: true,
74            unused: CompressOptionsUnused::Remove,
75            treeshake: TreeShakeOptions::default(),
76            drop_labels: FxHashSet::default(),
77            max_iterations: None,
78        }
79    }
80
81    pub fn safest() -> Self {
82        Self {
83            target: EngineTargets::default(),
84            keep_names: CompressOptionsKeepNames::all_true(),
85            drop_debugger: false,
86            drop_console: false,
87            join_vars: true,
88            sequences: true,
89            unused: CompressOptionsUnused::Keep,
90            treeshake: TreeShakeOptions::default(),
91            drop_labels: FxHashSet::default(),
92            max_iterations: None,
93        }
94    }
95
96    pub fn dce() -> Self {
97        Self {
98            target: EngineTargets::default(),
99            keep_names: CompressOptionsKeepNames::all_true(),
100            drop_debugger: false,
101            drop_console: false,
102            join_vars: false,
103            sequences: false,
104            unused: CompressOptionsUnused::Remove,
105            treeshake: TreeShakeOptions::default(),
106            drop_labels: FxHashSet::default(),
107            max_iterations: None,
108        }
109    }
110}
111
112#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
113pub enum CompressOptionsUnused {
114    #[default]
115    Remove,
116    KeepAssign,
117    Keep,
118}
119
120#[derive(Debug, Clone, Copy, Default)]
121pub struct CompressOptionsKeepNames {
122    /// Keep function names so that `Function.prototype.name` is preserved.
123    ///
124    /// This does not guarantee that the `undefined` name is preserved.
125    ///
126    /// Default `false`
127    pub function: bool,
128
129    /// Keep class names so that `Class.prototype.name` is preserved.
130    ///
131    /// This does not guarantee that the `undefined` name is preserved.
132    ///
133    /// Default `false`
134    pub class: bool,
135}
136
137impl CompressOptionsKeepNames {
138    pub fn all_false() -> Self {
139        Self { function: false, class: false }
140    }
141
142    pub fn all_true() -> Self {
143        Self { function: true, class: true }
144    }
145
146    pub fn function_only() -> Self {
147        Self { function: true, class: false }
148    }
149
150    pub fn class_only() -> Self {
151        Self { function: false, class: true }
152    }
153}
154
155#[derive(Debug, Clone)]
156pub struct TreeShakeOptions {
157    /// Whether to respect the pure annotations.
158    ///
159    /// Pure annotations are the comments that marks that a expression is pure.
160    /// For example, `/* @__PURE__ */`, `/* #__NO_SIDE_EFFECTS__ */`.
161    ///
162    /// <https://rollupjs.org/configuration-options/#treeshake-annotations>
163    ///
164    /// Default `true`
165    pub annotations: bool,
166
167    /// Whether to treat this function call as pure.
168    ///
169    /// This function is called for normal function calls, new calls, and
170    /// tagged template calls (`foo()`, `new Foo()`, ``foo`b` ``).
171    ///
172    /// <https://rollupjs.org/configuration-options/#treeshake-manualpurefunctions>
173    pub manual_pure_functions: Vec<String>,
174
175    /// Whether property read accesses have side effects.
176    ///
177    /// <https://rollupjs.org/configuration-options/#treeshake-propertyreadsideeffects>
178    ///
179    /// Default [PropertyReadSideEffects::All]
180    pub property_read_side_effects: PropertyReadSideEffects,
181
182    /// Whether accessing a global variable has side effects.
183    ///
184    /// Accessing a non-existing global variable will throw an error.
185    /// Global variable may be a getter that has side effects.
186    ///
187    /// <https://rollupjs.org/configuration-options/#treeshake-unknownglobalsideeffects>
188    ///
189    /// Default `true`
190    pub unknown_global_side_effects: bool,
191
192    /// Whether invalid import statements have side effects.
193    ///
194    /// Accessing a non-existing import name will throw an error.
195    /// Also import statements that cannot be resolved will throw an error.
196    ///
197    /// Default `false`
198    pub invalid_import_side_effects: bool,
199}
200
201impl Default for TreeShakeOptions {
202    fn default() -> Self {
203        Self {
204            annotations: true,
205            manual_pure_functions: vec![],
206            property_read_side_effects: PropertyReadSideEffects::default(),
207            unknown_global_side_effects: true,
208            invalid_import_side_effects: false,
209        }
210    }
211}