oxc 0.1.0-aarch64-linux-gnu
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +437 -0
- data/ext/oxc/extconf.rb +123 -0
- data/ext/oxc/include/oxc.h +40 -0
- data/ext/oxc/oxc.c +136 -0
- data/lib/oxc/3.2/oxc.so +0 -0
- data/lib/oxc/3.3/oxc.so +0 -0
- data/lib/oxc/3.4/oxc.so +0 -0
- data/lib/oxc/4.0/oxc.so +0 -0
- data/lib/oxc/backend.rb +41 -0
- data/lib/oxc/diagnosed.rb +33 -0
- data/lib/oxc/diagnostic.rb +86 -0
- data/lib/oxc/errors.rb +26 -0
- data/lib/oxc/minifier.rb +31 -0
- data/lib/oxc/minify_result.rb +25 -0
- data/lib/oxc/options.rb +113 -0
- data/lib/oxc/parse_result.rb +106 -0
- data/lib/oxc/result.rb +51 -0
- data/lib/oxc/transform_result.rb +47 -0
- data/lib/oxc/transformer.rb +31 -0
- data/lib/oxc/version.rb +5 -0
- data/lib/oxc.rb +52 -0
- data/licenses/README.md +12 -0
- data/licenses/oxc-MIT.txt +22 -0
- data/licenses/oxc-THIRD-PARTY.txt +763 -0
- data/oxc.gemspec +43 -0
- data/rust/Cargo.lock +1436 -0
- data/rust/Cargo.toml +32 -0
- data/rust/build.rs +52 -0
- data/rust/cbindgen.toml +24 -0
- data/rust/rustfmt.toml +3 -0
- data/rust/src/diagnostic.rs +75 -0
- data/rust/src/lib.rs +288 -0
- data/rust/src/module_record.rs +262 -0
- data/rust/src/options.rs +744 -0
- data/rust/src/parse.rs +93 -0
- data/rust/src/result.rs +55 -0
- data/rust/src/source_type.rs +26 -0
- data/rust/src/symbols.rs +101 -0
- data/rust/src/transform.rs +116 -0
- data/sig/oxc/backend.rbs +29 -0
- data/sig/oxc/diagnosed.rbs +23 -0
- data/sig/oxc/diagnostic.rbs +57 -0
- data/sig/oxc/errors.rbs +31 -0
- data/sig/oxc/minifier.rbs +21 -0
- data/sig/oxc/minify_result.rbs +11 -0
- data/sig/oxc/options.rbs +42 -0
- data/sig/oxc/parse_result.rbs +61 -0
- data/sig/oxc/result.rbs +32 -0
- data/sig/oxc/transform_result.rbs +22 -0
- data/sig/oxc/transformer.rbs +21 -0
- data/sig/oxc/types.rbs +96 -0
- data/sig/oxc/version.rbs +5 -0
- data/sig/oxc.rbs +15 -0
- metadata +107 -0
data/rust/src/options.rs
ADDED
|
@@ -0,0 +1,744 @@
|
|
|
1
|
+
use std::collections::BTreeMap;
|
|
2
|
+
use std::fmt;
|
|
3
|
+
use std::marker::PhantomData;
|
|
4
|
+
use std::path::PathBuf;
|
|
5
|
+
|
|
6
|
+
use serde::de::value::MapAccessDeserializer;
|
|
7
|
+
use serde::de::{self, MapAccess, Visitor};
|
|
8
|
+
use serde::{Deserialize, Deserializer};
|
|
9
|
+
|
|
10
|
+
use oxc::codegen::{CodegenOptions as OxcCodegenOptions, LegalComment};
|
|
11
|
+
use oxc::span::SourceType;
|
|
12
|
+
use oxc::str::CompactStr;
|
|
13
|
+
use oxc::transformer_plugins::{InjectGlobalVariablesConfig, InjectImport, ReplaceGlobalDefinesConfig};
|
|
14
|
+
|
|
15
|
+
use oxc::isolated_declarations::IsolatedDeclarationsOptions;
|
|
16
|
+
use oxc::transformer::{
|
|
17
|
+
CompilerAssumptions, DecoratorOptions as OxcDecoratorOptions, EngineTargets, EnvOptions, HelperLoaderMode,
|
|
18
|
+
HelperLoaderOptions, JsxOptions as OxcJsxOptions, JsxRuntime, RewriteExtensionsMode,
|
|
19
|
+
TransformOptions as OxcTransformOptions, TypeScriptOptions as OxcTypeScriptOptions,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
use oxc::minifier::{
|
|
23
|
+
CompressOptions as OxcCompressOptions, CompressOptionsKeepNames, CompressOptionsUnused,
|
|
24
|
+
MangleOptions as OxcMangleOptions, MangleOptionsKeepNames, MinifierOptions, PropertyReadSideEffects,
|
|
25
|
+
TreeShakeOptions as OxcTreeShakeOptions,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
#[derive(Debug)]
|
|
29
|
+
pub enum Toggle<T> {
|
|
30
|
+
Flag(bool),
|
|
31
|
+
Settings(T),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
impl<'de, T: Deserialize<'de>> Deserialize<'de> for Toggle<T> {
|
|
35
|
+
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
|
36
|
+
deserializer.deserialize_any(ToggleVisitor { marker: PhantomData })
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
struct ToggleVisitor<T> {
|
|
41
|
+
marker: PhantomData<T>,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
impl<'de, T: Deserialize<'de>> Visitor<'de> for ToggleVisitor<T> {
|
|
45
|
+
type Value = Toggle<T>;
|
|
46
|
+
|
|
47
|
+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
48
|
+
formatter.write_str("true, false, or a hash of settings")
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
fn visit_bool<E: de::Error>(self, value: bool) -> Result<Self::Value, E> {
|
|
52
|
+
Ok(Toggle::Flag(value))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fn visit_map<A: MapAccess<'de>>(self, map: A) -> Result<Self::Value, A::Error> {
|
|
56
|
+
T::deserialize(MapAccessDeserializer::new(map)).map(Toggle::Settings)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
impl<T> Default for Toggle<T> {
|
|
61
|
+
fn default() -> Self {
|
|
62
|
+
Self::Flag(true)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
impl<T> Toggle<T> {
|
|
67
|
+
pub fn enabled(&self) -> bool {
|
|
68
|
+
!matches!(self, Self::Flag(false))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
pub fn settings(&self) -> Option<&T> {
|
|
72
|
+
match self {
|
|
73
|
+
Self::Settings(settings) => Some(settings),
|
|
74
|
+
Self::Flag(_) => None,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#[derive(Debug, Deserialize)]
|
|
80
|
+
#[serde(untagged)]
|
|
81
|
+
pub enum Target {
|
|
82
|
+
One(String),
|
|
83
|
+
Many(Vec<String>),
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
impl Target {
|
|
87
|
+
fn to_engine_targets(&self) -> Result<EngineTargets, String> {
|
|
88
|
+
match self {
|
|
89
|
+
Self::One(target) => EngineTargets::from_target(target),
|
|
90
|
+
Self::Many(targets) => EngineTargets::from_target_list(targets),
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// TODO: add mangle_props. `ManglePropertiesOptions` types `include` and `exclude` as
|
|
96
|
+
// `lazy_regex::Regex` and `reserved` as `FxHashSet<CompactStr>`, so it needs `lazy-regex` and
|
|
97
|
+
// `rustc-hash` here as direct dependencies, pinned to whatever oxc picked. It also needs the
|
|
98
|
+
// `cache` round-trip, since property names are otherwise inconsistent across files.
|
|
99
|
+
#[derive(Debug, Default, Deserialize)]
|
|
100
|
+
#[serde(default, deny_unknown_fields)]
|
|
101
|
+
pub struct MinifyOptions {
|
|
102
|
+
pub filename: Option<String>,
|
|
103
|
+
pub lang: Option<String>,
|
|
104
|
+
pub source_type: Option<String>,
|
|
105
|
+
pub compress: Toggle<CompressOptions>,
|
|
106
|
+
pub mangle: Toggle<MangleOptions>,
|
|
107
|
+
pub codegen: Toggle<CodegenOptions>,
|
|
108
|
+
pub sourcemap: bool,
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
impl MinifyOptions {
|
|
112
|
+
pub fn to_minifier_options(&self) -> Result<MinifierOptions, String> {
|
|
113
|
+
self.to_minifier_options_inheriting(None)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
pub fn to_minifier_options_inheriting(&self, inherited: Option<&Target>) -> Result<MinifierOptions, String> {
|
|
117
|
+
let compress = if self.compress.enabled() {
|
|
118
|
+
Some(match self.compress.settings() {
|
|
119
|
+
Some(settings) => settings.to_compress_options(inherited)?,
|
|
120
|
+
None => OxcCompressOptions {
|
|
121
|
+
target: match inherited {
|
|
122
|
+
Some(target) => target.to_engine_targets()?,
|
|
123
|
+
None => OxcCompressOptions::default().target,
|
|
124
|
+
},
|
|
125
|
+
..OxcCompressOptions::default()
|
|
126
|
+
},
|
|
127
|
+
})
|
|
128
|
+
} else {
|
|
129
|
+
None
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
let mangle = if self.mangle.enabled() {
|
|
133
|
+
Some(match self.mangle.settings() {
|
|
134
|
+
Some(settings) => settings.to_mangle_options(),
|
|
135
|
+
None => OxcMangleOptions::default(),
|
|
136
|
+
})
|
|
137
|
+
} else {
|
|
138
|
+
None
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
Ok(MinifierOptions {
|
|
142
|
+
compress,
|
|
143
|
+
mangle,
|
|
144
|
+
..MinifierOptions::default()
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
pub fn to_codegen_options(&self) -> Result<OxcCodegenOptions, String> {
|
|
149
|
+
let mut options = match self.codegen.settings() {
|
|
150
|
+
Some(settings) => settings.to_codegen_options()?,
|
|
151
|
+
None => CodegenOptions::whitespace(self.codegen.enabled()),
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
if self.sourcemap {
|
|
155
|
+
options.source_map_path = Some(PathBuf::from(self.filename.clone().unwrap_or_default()));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
Ok(options)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
#[derive(Debug, Default, Deserialize)]
|
|
163
|
+
#[serde(default, deny_unknown_fields)]
|
|
164
|
+
pub struct CompressOptions {
|
|
165
|
+
pub target: Option<Target>,
|
|
166
|
+
pub drop_console: Option<bool>,
|
|
167
|
+
pub drop_debugger: Option<bool>,
|
|
168
|
+
pub unused: Option<Unused>,
|
|
169
|
+
pub keep_names: Option<KeepNames>,
|
|
170
|
+
pub join_vars: Option<bool>,
|
|
171
|
+
pub sequences: Option<bool>,
|
|
172
|
+
pub drop_labels: Option<Vec<String>>,
|
|
173
|
+
pub max_iterations: Option<u8>,
|
|
174
|
+
pub treeshake: Option<TreeShakeOptions>,
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
impl CompressOptions {
|
|
178
|
+
fn to_compress_options(&self, inherited: Option<&Target>) -> Result<OxcCompressOptions, String> {
|
|
179
|
+
let default = OxcCompressOptions::default();
|
|
180
|
+
|
|
181
|
+
Ok(OxcCompressOptions {
|
|
182
|
+
target: match self.target.as_ref().or(inherited) {
|
|
183
|
+
Some(target) => target.to_engine_targets()?,
|
|
184
|
+
None => default.target,
|
|
185
|
+
},
|
|
186
|
+
drop_console: self.drop_console.unwrap_or(default.drop_console),
|
|
187
|
+
drop_debugger: self.drop_debugger.unwrap_or(default.drop_debugger),
|
|
188
|
+
join_vars: self.join_vars.unwrap_or(default.join_vars),
|
|
189
|
+
sequences: self.sequences.unwrap_or(default.sequences),
|
|
190
|
+
unused: match &self.unused {
|
|
191
|
+
Some(Unused::Flag(true)) => CompressOptionsUnused::Remove,
|
|
192
|
+
Some(Unused::Flag(false)) => CompressOptionsUnused::Keep,
|
|
193
|
+
Some(Unused::Named(name)) if name == "remove" => CompressOptionsUnused::Remove,
|
|
194
|
+
Some(Unused::Named(name)) if name == "keep" => CompressOptionsUnused::Keep,
|
|
195
|
+
Some(Unused::Named(name)) if name == "keep_assign" => CompressOptionsUnused::KeepAssign,
|
|
196
|
+
Some(Unused::Named(name)) => {
|
|
197
|
+
return Err(format!("Unknown unused: {name}. Expected remove, keep or keep_assign."));
|
|
198
|
+
}
|
|
199
|
+
None => default.unused,
|
|
200
|
+
},
|
|
201
|
+
keep_names: self
|
|
202
|
+
.keep_names
|
|
203
|
+
.as_ref()
|
|
204
|
+
.map(CompressOptionsKeepNames::from)
|
|
205
|
+
.unwrap_or_default(),
|
|
206
|
+
treeshake: match &self.treeshake {
|
|
207
|
+
Some(treeshake) => treeshake.to_treeshake_options()?,
|
|
208
|
+
None => OxcTreeShakeOptions::default(),
|
|
209
|
+
},
|
|
210
|
+
drop_labels: self
|
|
211
|
+
.drop_labels
|
|
212
|
+
.as_ref()
|
|
213
|
+
.map(|labels| labels.iter().cloned().collect())
|
|
214
|
+
.unwrap_or_default(),
|
|
215
|
+
max_iterations: self.max_iterations,
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
#[derive(Debug, Deserialize)]
|
|
221
|
+
#[serde(untagged)]
|
|
222
|
+
pub enum Unused {
|
|
223
|
+
Flag(bool),
|
|
224
|
+
Named(String),
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
#[derive(Debug, Default, Deserialize)]
|
|
228
|
+
#[serde(default, deny_unknown_fields)]
|
|
229
|
+
pub struct KeepNames {
|
|
230
|
+
pub function: bool,
|
|
231
|
+
pub class: bool,
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
impl From<&KeepNames> for CompressOptionsKeepNames {
|
|
235
|
+
fn from(names: &KeepNames) -> Self {
|
|
236
|
+
Self {
|
|
237
|
+
function: names.function,
|
|
238
|
+
class: names.class,
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
impl From<&KeepNames> for MangleOptionsKeepNames {
|
|
244
|
+
fn from(names: &KeepNames) -> Self {
|
|
245
|
+
Self {
|
|
246
|
+
function: names.function,
|
|
247
|
+
class: names.class,
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
#[derive(Debug, Default, Deserialize)]
|
|
253
|
+
#[serde(default, deny_unknown_fields)]
|
|
254
|
+
pub struct TreeShakeOptions {
|
|
255
|
+
pub annotations: Option<bool>,
|
|
256
|
+
pub manual_pure_functions: Option<Vec<String>>,
|
|
257
|
+
pub property_read_side_effects: Option<bool>,
|
|
258
|
+
pub property_write_side_effects: Option<bool>,
|
|
259
|
+
pub unknown_global_side_effects: Option<bool>,
|
|
260
|
+
pub invalid_import_side_effects: Option<bool>,
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
impl TreeShakeOptions {
|
|
264
|
+
fn to_treeshake_options(&self) -> Result<OxcTreeShakeOptions, String> {
|
|
265
|
+
let default = OxcTreeShakeOptions::default();
|
|
266
|
+
|
|
267
|
+
Ok(OxcTreeShakeOptions {
|
|
268
|
+
annotations: self.annotations.unwrap_or(default.annotations),
|
|
269
|
+
manual_pure_functions: self
|
|
270
|
+
.manual_pure_functions
|
|
271
|
+
.clone()
|
|
272
|
+
.unwrap_or(default.manual_pure_functions),
|
|
273
|
+
property_read_side_effects: match self.property_read_side_effects {
|
|
274
|
+
Some(true) => PropertyReadSideEffects::All,
|
|
275
|
+
Some(false) => PropertyReadSideEffects::None,
|
|
276
|
+
None => default.property_read_side_effects,
|
|
277
|
+
},
|
|
278
|
+
property_write_side_effects: self
|
|
279
|
+
.property_write_side_effects
|
|
280
|
+
.unwrap_or(default.property_write_side_effects),
|
|
281
|
+
unknown_global_side_effects: self
|
|
282
|
+
.unknown_global_side_effects
|
|
283
|
+
.unwrap_or(default.unknown_global_side_effects),
|
|
284
|
+
invalid_import_side_effects: self
|
|
285
|
+
.invalid_import_side_effects
|
|
286
|
+
.unwrap_or(default.invalid_import_side_effects),
|
|
287
|
+
})
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
#[derive(Debug, Default, Deserialize)]
|
|
292
|
+
#[serde(default, deny_unknown_fields)]
|
|
293
|
+
pub struct MangleOptions {
|
|
294
|
+
pub top_level: Option<bool>,
|
|
295
|
+
pub keep_names: Option<Toggle<KeepNames>>,
|
|
296
|
+
pub reserved: Option<Vec<String>>,
|
|
297
|
+
pub debug: Option<bool>,
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
impl MangleOptions {
|
|
301
|
+
fn to_mangle_options(&self) -> OxcMangleOptions {
|
|
302
|
+
let default = OxcMangleOptions::default();
|
|
303
|
+
|
|
304
|
+
OxcMangleOptions {
|
|
305
|
+
top_level: self.top_level,
|
|
306
|
+
keep_names: match &self.keep_names {
|
|
307
|
+
Some(Toggle::Flag(false)) => MangleOptionsKeepNames::all_false(),
|
|
308
|
+
Some(Toggle::Flag(true)) => MangleOptionsKeepNames::all_true(),
|
|
309
|
+
Some(Toggle::Settings(names)) => MangleOptionsKeepNames::from(names),
|
|
310
|
+
None => default.keep_names,
|
|
311
|
+
},
|
|
312
|
+
reserved: self.reserved.as_ref().map_or(default.reserved, |names| {
|
|
313
|
+
names.iter().map(|name| CompactStr::from(name.as_str())).collect()
|
|
314
|
+
}),
|
|
315
|
+
debug: self.debug.unwrap_or(default.debug),
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
#[derive(Debug, Default, Deserialize)]
|
|
321
|
+
#[serde(default, deny_unknown_fields)]
|
|
322
|
+
pub struct CodegenOptions {
|
|
323
|
+
pub remove_whitespace: Option<bool>,
|
|
324
|
+
pub legal_comments: Option<LegalComments>,
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
impl CodegenOptions {
|
|
328
|
+
fn whitespace(remove: bool) -> OxcCodegenOptions {
|
|
329
|
+
if remove {
|
|
330
|
+
OxcCodegenOptions::minify()
|
|
331
|
+
} else {
|
|
332
|
+
OxcCodegenOptions {
|
|
333
|
+
minify: false,
|
|
334
|
+
..OxcCodegenOptions::minify()
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
fn to_codegen_options(&self) -> Result<OxcCodegenOptions, String> {
|
|
340
|
+
let mut options = Self::whitespace(self.remove_whitespace.unwrap_or(true));
|
|
341
|
+
|
|
342
|
+
if let Some(legal) = &self.legal_comments {
|
|
343
|
+
options.comments.legal = legal.to_legal_comment()?;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
Ok(options)
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
#[derive(Debug, Deserialize)]
|
|
351
|
+
#[serde(untagged)]
|
|
352
|
+
pub enum LegalComments {
|
|
353
|
+
Mode(String),
|
|
354
|
+
Linked(LegalCommentsLinked),
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
impl LegalComments {
|
|
358
|
+
fn to_legal_comment(&self) -> Result<LegalComment, String> {
|
|
359
|
+
match self {
|
|
360
|
+
Self::Mode(mode) => match mode.as_str() {
|
|
361
|
+
"none" => Ok(LegalComment::None),
|
|
362
|
+
"inline" => Ok(LegalComment::Inline),
|
|
363
|
+
"eof" => Ok(LegalComment::Eof),
|
|
364
|
+
"external" => Ok(LegalComment::External),
|
|
365
|
+
other => Err(format!(
|
|
366
|
+
"Unknown legal_comments: {other}. Expected none, inline, eof, external or a linked path."
|
|
367
|
+
)),
|
|
368
|
+
},
|
|
369
|
+
Self::Linked(linked) => {
|
|
370
|
+
if linked.linked.is_empty() {
|
|
371
|
+
return Err("legal_comments linked has to be a path.".to_string());
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
Ok(LegalComment::Linked(linked.linked.clone()))
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
#[derive(Debug, Deserialize)]
|
|
381
|
+
#[serde(deny_unknown_fields)]
|
|
382
|
+
pub struct LegalCommentsLinked {
|
|
383
|
+
pub linked: String,
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
#[derive(Debug, Default, Deserialize)]
|
|
387
|
+
#[serde(default, deny_unknown_fields)]
|
|
388
|
+
pub struct TransformOptions {
|
|
389
|
+
pub filename: Option<String>,
|
|
390
|
+
pub lang: Option<String>,
|
|
391
|
+
pub source_type: Option<String>,
|
|
392
|
+
pub cwd: Option<String>,
|
|
393
|
+
pub target: Option<Target>,
|
|
394
|
+
pub jsx: Toggle<JsxOptions>,
|
|
395
|
+
pub typescript: Option<TypeScriptOptions>,
|
|
396
|
+
pub assumptions: Option<Assumptions>,
|
|
397
|
+
pub decorator: Option<DecoratorOptions>,
|
|
398
|
+
pub helpers: Option<Helpers>,
|
|
399
|
+
pub define: Option<BTreeMap<String, String>>,
|
|
400
|
+
pub inject: Option<BTreeMap<String, Injected>>,
|
|
401
|
+
pub minify: Option<Toggle<MinifyOptions>>,
|
|
402
|
+
pub codegen: Option<CodegenOptions>,
|
|
403
|
+
pub sourcemap: bool,
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
impl TransformOptions {
|
|
407
|
+
pub fn to_transform_options(&self) -> Result<OxcTransformOptions, String> {
|
|
408
|
+
let env = match &self.target {
|
|
409
|
+
Some(target) => match target {
|
|
410
|
+
Target::One(target) => EnvOptions::from_target(target)?,
|
|
411
|
+
Target::Many(targets) => EnvOptions::from_target_list(targets)?,
|
|
412
|
+
},
|
|
413
|
+
None => EnvOptions::default(),
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
Ok(OxcTransformOptions {
|
|
417
|
+
cwd: self.cwd.clone().map(PathBuf::from).unwrap_or_default(),
|
|
418
|
+
typescript: self
|
|
419
|
+
.typescript
|
|
420
|
+
.as_ref()
|
|
421
|
+
.map(TypeScriptOptions::to_typescript_options)
|
|
422
|
+
.unwrap_or_default(),
|
|
423
|
+
assumptions: self
|
|
424
|
+
.assumptions
|
|
425
|
+
.as_ref()
|
|
426
|
+
.map(Assumptions::to_compiler_assumptions)
|
|
427
|
+
.unwrap_or_default(),
|
|
428
|
+
decorator: self
|
|
429
|
+
.decorator
|
|
430
|
+
.as_ref()
|
|
431
|
+
.map(DecoratorOptions::to_decorator_options)
|
|
432
|
+
.unwrap_or_default(),
|
|
433
|
+
jsx: match (&self.jsx, self.jsx.settings()) {
|
|
434
|
+
(_, Some(settings)) => settings.to_jsx_options(),
|
|
435
|
+
(Toggle::Flag(false), _) => OxcJsxOptions::disable(),
|
|
436
|
+
_ => OxcJsxOptions::enable(),
|
|
437
|
+
},
|
|
438
|
+
env,
|
|
439
|
+
helper_loader: self
|
|
440
|
+
.helpers
|
|
441
|
+
.as_ref()
|
|
442
|
+
.map(Helpers::to_helper_loader_options)
|
|
443
|
+
.transpose()?
|
|
444
|
+
.unwrap_or_default(),
|
|
445
|
+
..OxcTransformOptions::default()
|
|
446
|
+
})
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
pub fn to_isolated_declarations_options(&self) -> Option<IsolatedDeclarationsOptions> {
|
|
450
|
+
let declaration = self
|
|
451
|
+
.typescript
|
|
452
|
+
.as_ref()
|
|
453
|
+
.and_then(|typescript| typescript.declaration.as_ref())?;
|
|
454
|
+
|
|
455
|
+
if !declaration.enabled() {
|
|
456
|
+
return None;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
Some(IsolatedDeclarationsOptions {
|
|
460
|
+
strip_internal: declaration.settings().is_some_and(|settings| settings.strip_internal),
|
|
461
|
+
})
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
pub fn to_define_config(&self) -> Result<Option<ReplaceGlobalDefinesConfig>, String> {
|
|
465
|
+
let Some(define) = &self.define else {
|
|
466
|
+
return Ok(None);
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
let entries = define
|
|
470
|
+
.iter()
|
|
471
|
+
.map(|(name, value)| (name.clone(), value.clone()))
|
|
472
|
+
.collect::<Vec<_>>();
|
|
473
|
+
|
|
474
|
+
ReplaceGlobalDefinesConfig::new(&entries)
|
|
475
|
+
.map(Some)
|
|
476
|
+
.map_err(|errors| errors.iter().map(ToString::to_string).collect::<Vec<_>>().join(", "))
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
pub fn to_inject_config(&self) -> Result<Option<InjectGlobalVariablesConfig>, String> {
|
|
480
|
+
let Some(inject) = &self.inject else {
|
|
481
|
+
return Ok(None);
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
let imports = inject
|
|
485
|
+
.iter()
|
|
486
|
+
.map(|(local, injected)| injected.to_import(local))
|
|
487
|
+
.collect::<Result<Vec<_>, String>>()?;
|
|
488
|
+
|
|
489
|
+
Ok(Some(InjectGlobalVariablesConfig::new(imports)))
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
pub fn minifying(&self) -> bool {
|
|
493
|
+
self.minify.as_ref().is_some_and(Toggle::enabled)
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
pub fn to_minifier_options(&self) -> Result<Option<MinifierOptions>, String> {
|
|
497
|
+
if !self.minifying() {
|
|
498
|
+
return Ok(None);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
let inherited = self.target.as_ref();
|
|
502
|
+
|
|
503
|
+
match self.minify.as_ref().and_then(Toggle::settings) {
|
|
504
|
+
Some(settings) => settings.to_minifier_options_inheriting(inherited).map(Some),
|
|
505
|
+
None => Ok(Some(
|
|
506
|
+
MinifyOptions::default().to_minifier_options_inheriting(inherited)?,
|
|
507
|
+
)),
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
pub fn to_codegen_options(&self) -> Result<OxcCodegenOptions, String> {
|
|
512
|
+
match &self.codegen {
|
|
513
|
+
Some(codegen) => codegen.to_codegen_options(),
|
|
514
|
+
None => Ok(OxcCodegenOptions {
|
|
515
|
+
minify: self.minifying(),
|
|
516
|
+
..OxcCodegenOptions::default()
|
|
517
|
+
}),
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
#[derive(Debug, Deserialize)]
|
|
523
|
+
#[serde(untagged)]
|
|
524
|
+
pub enum Injected {
|
|
525
|
+
Default(String),
|
|
526
|
+
Named(Vec<String>),
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
impl Injected {
|
|
530
|
+
fn to_import(&self, local: &str) -> Result<InjectImport, String> {
|
|
531
|
+
match self {
|
|
532
|
+
Self::Default(source) => Ok(InjectImport::default_specifier(source, local)),
|
|
533
|
+
Self::Named(parts) => {
|
|
534
|
+
if parts.len() != 2 {
|
|
535
|
+
return Err(format!(
|
|
536
|
+
"inject {local} has to be a source, or a pair of a source and a name."
|
|
537
|
+
));
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
let source = &parts[0];
|
|
541
|
+
|
|
542
|
+
Ok(if parts[1] == "*" {
|
|
543
|
+
InjectImport::namespace_specifier(source, local)
|
|
544
|
+
} else {
|
|
545
|
+
InjectImport::named_specifier(source, Some(&parts[1]), local)
|
|
546
|
+
})
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
#[derive(Debug, Default, Deserialize)]
|
|
553
|
+
#[serde(default, deny_unknown_fields)]
|
|
554
|
+
pub struct JsxOptions {
|
|
555
|
+
pub runtime: Option<String>,
|
|
556
|
+
pub development: Option<bool>,
|
|
557
|
+
pub throw_if_namespace: Option<bool>,
|
|
558
|
+
pub pure: Option<bool>,
|
|
559
|
+
pub import_source: Option<String>,
|
|
560
|
+
pub pragma: Option<String>,
|
|
561
|
+
pub pragma_frag: Option<String>,
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
impl JsxOptions {
|
|
565
|
+
fn to_jsx_options(&self) -> OxcJsxOptions {
|
|
566
|
+
let default = OxcJsxOptions::default();
|
|
567
|
+
|
|
568
|
+
OxcJsxOptions {
|
|
569
|
+
runtime: match self.runtime.as_deref() {
|
|
570
|
+
Some("classic") => JsxRuntime::Classic,
|
|
571
|
+
_ => JsxRuntime::Automatic,
|
|
572
|
+
},
|
|
573
|
+
development: self.development.unwrap_or(default.development),
|
|
574
|
+
throw_if_namespace: self.throw_if_namespace.unwrap_or(default.throw_if_namespace),
|
|
575
|
+
pure: self.pure.unwrap_or(default.pure),
|
|
576
|
+
import_source: self.import_source.clone(),
|
|
577
|
+
pragma: self.pragma.clone(),
|
|
578
|
+
pragma_frag: self.pragma_frag.clone(),
|
|
579
|
+
..OxcJsxOptions::default()
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
#[derive(Debug, Default, Deserialize)]
|
|
585
|
+
#[serde(default, deny_unknown_fields)]
|
|
586
|
+
pub struct TypeScriptOptions {
|
|
587
|
+
pub jsx_pragma: Option<String>,
|
|
588
|
+
pub jsx_pragma_frag: Option<String>,
|
|
589
|
+
pub only_remove_type_imports: Option<bool>,
|
|
590
|
+
pub allow_namespaces: Option<bool>,
|
|
591
|
+
pub allow_declare_fields: Option<bool>,
|
|
592
|
+
pub optimize_const_enums: Option<bool>,
|
|
593
|
+
pub optimize_enums: Option<bool>,
|
|
594
|
+
pub remove_class_fields_without_initializer: Option<bool>,
|
|
595
|
+
pub rewrite_import_extensions: Option<String>,
|
|
596
|
+
pub declaration: Option<Toggle<DeclarationOptions>>,
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
#[derive(Debug, Default, Deserialize)]
|
|
600
|
+
#[serde(default, deny_unknown_fields)]
|
|
601
|
+
pub struct DeclarationOptions {
|
|
602
|
+
pub strip_internal: bool,
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
#[derive(Debug, Default, Deserialize)]
|
|
606
|
+
#[serde(default, deny_unknown_fields)]
|
|
607
|
+
pub struct Assumptions {
|
|
608
|
+
pub ignore_function_length: Option<bool>,
|
|
609
|
+
pub no_document_all: Option<bool>,
|
|
610
|
+
pub object_rest_no_symbols: Option<bool>,
|
|
611
|
+
pub pure_getters: Option<bool>,
|
|
612
|
+
pub set_public_class_fields: Option<bool>,
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
impl Assumptions {
|
|
616
|
+
fn to_compiler_assumptions(&self) -> CompilerAssumptions {
|
|
617
|
+
let default = CompilerAssumptions::default();
|
|
618
|
+
|
|
619
|
+
CompilerAssumptions {
|
|
620
|
+
ignore_function_length: self.ignore_function_length.unwrap_or(default.ignore_function_length),
|
|
621
|
+
no_document_all: self.no_document_all.unwrap_or(default.no_document_all),
|
|
622
|
+
object_rest_no_symbols: self.object_rest_no_symbols.unwrap_or(default.object_rest_no_symbols),
|
|
623
|
+
pure_getters: self.pure_getters.unwrap_or(default.pure_getters),
|
|
624
|
+
set_public_class_fields: self.set_public_class_fields.unwrap_or(default.set_public_class_fields),
|
|
625
|
+
..default
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
#[derive(Debug, Default, Deserialize)]
|
|
631
|
+
#[serde(default, deny_unknown_fields)]
|
|
632
|
+
pub struct DecoratorOptions {
|
|
633
|
+
pub legacy: Option<bool>,
|
|
634
|
+
pub emit_decorator_metadata: Option<bool>,
|
|
635
|
+
pub strict_null_checks: Option<bool>,
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
impl DecoratorOptions {
|
|
639
|
+
fn to_decorator_options(&self) -> OxcDecoratorOptions {
|
|
640
|
+
let default = OxcDecoratorOptions::default();
|
|
641
|
+
|
|
642
|
+
OxcDecoratorOptions {
|
|
643
|
+
legacy: self.legacy.unwrap_or(default.legacy),
|
|
644
|
+
emit_decorator_metadata: self.emit_decorator_metadata.unwrap_or(default.emit_decorator_metadata),
|
|
645
|
+
strict_null_checks: self.strict_null_checks.unwrap_or(default.strict_null_checks),
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
impl TypeScriptOptions {
|
|
651
|
+
fn to_typescript_options(&self) -> OxcTypeScriptOptions {
|
|
652
|
+
let default = OxcTypeScriptOptions::default();
|
|
653
|
+
|
|
654
|
+
OxcTypeScriptOptions {
|
|
655
|
+
jsx_pragma: self.jsx_pragma.clone().map(Into::into).unwrap_or(default.jsx_pragma),
|
|
656
|
+
jsx_pragma_frag: self
|
|
657
|
+
.jsx_pragma_frag
|
|
658
|
+
.clone()
|
|
659
|
+
.map(Into::into)
|
|
660
|
+
.unwrap_or(default.jsx_pragma_frag),
|
|
661
|
+
only_remove_type_imports: self
|
|
662
|
+
.only_remove_type_imports
|
|
663
|
+
.unwrap_or(default.only_remove_type_imports),
|
|
664
|
+
allow_namespaces: self.allow_namespaces.unwrap_or(default.allow_namespaces),
|
|
665
|
+
allow_declare_fields: self.allow_declare_fields.unwrap_or(default.allow_declare_fields),
|
|
666
|
+
optimize_const_enums: self.optimize_const_enums.unwrap_or(default.optimize_const_enums),
|
|
667
|
+
optimize_enums: self.optimize_enums.unwrap_or(default.optimize_enums),
|
|
668
|
+
remove_class_fields_without_initializer: self
|
|
669
|
+
.remove_class_fields_without_initializer
|
|
670
|
+
.unwrap_or(default.remove_class_fields_without_initializer),
|
|
671
|
+
rewrite_import_extensions: match self.rewrite_import_extensions.as_deref() {
|
|
672
|
+
Some("rewrite") => Some(RewriteExtensionsMode::Rewrite),
|
|
673
|
+
Some("remove") => Some(RewriteExtensionsMode::Remove),
|
|
674
|
+
_ => None,
|
|
675
|
+
},
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
#[derive(Debug, Default, Deserialize)]
|
|
681
|
+
#[serde(default, deny_unknown_fields)]
|
|
682
|
+
pub struct Helpers {
|
|
683
|
+
pub mode: Option<String>,
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
impl Helpers {
|
|
687
|
+
fn to_helper_loader_options(&self) -> Result<HelperLoaderOptions, String> {
|
|
688
|
+
let mode = match self.mode.as_deref() {
|
|
689
|
+
Some("runtime") | None => HelperLoaderMode::Runtime,
|
|
690
|
+
Some("external") => HelperLoaderMode::External,
|
|
691
|
+
Some(other) => return Err(format!("Unknown helpers mode: {other}. Expected runtime or external.")),
|
|
692
|
+
};
|
|
693
|
+
|
|
694
|
+
Ok(HelperLoaderOptions {
|
|
695
|
+
mode,
|
|
696
|
+
..HelperLoaderOptions::default()
|
|
697
|
+
})
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
#[derive(Debug, Deserialize)]
|
|
702
|
+
#[serde(default, deny_unknown_fields)]
|
|
703
|
+
pub struct ParseOptions {
|
|
704
|
+
pub filename: Option<String>,
|
|
705
|
+
pub lang: Option<String>,
|
|
706
|
+
pub source_type: Option<String>,
|
|
707
|
+
pub ast_type: Option<String>,
|
|
708
|
+
pub ast: bool,
|
|
709
|
+
pub ranges: bool,
|
|
710
|
+
pub preserve_parens: bool,
|
|
711
|
+
pub comments: bool,
|
|
712
|
+
pub module_record: bool,
|
|
713
|
+
pub symbols: bool,
|
|
714
|
+
pub semantic_errors: bool,
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
impl Default for ParseOptions {
|
|
718
|
+
fn default() -> Self {
|
|
719
|
+
Self {
|
|
720
|
+
filename: None,
|
|
721
|
+
lang: None,
|
|
722
|
+
source_type: None,
|
|
723
|
+
ast_type: None,
|
|
724
|
+
ast: true,
|
|
725
|
+
ranges: false,
|
|
726
|
+
preserve_parens: true,
|
|
727
|
+
comments: true,
|
|
728
|
+
module_record: false,
|
|
729
|
+
symbols: false,
|
|
730
|
+
semantic_errors: false,
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
impl ParseOptions {
|
|
736
|
+
pub fn include_ts_fields(&self, source_type: &SourceType) -> Result<bool, String> {
|
|
737
|
+
match self.ast_type.as_deref() {
|
|
738
|
+
Some("js") => Ok(false),
|
|
739
|
+
Some("ts") => Ok(true),
|
|
740
|
+
Some(other) => Err(format!("Unknown ast_type: {other}. Expected js or ts.")),
|
|
741
|
+
None => Ok(!source_type.is_javascript()),
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|