oxc 0.1.0-arm-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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +437 -0
  4. data/ext/oxc/extconf.rb +123 -0
  5. data/ext/oxc/include/oxc.h +40 -0
  6. data/ext/oxc/oxc.c +136 -0
  7. data/lib/oxc/3.2/oxc.so +0 -0
  8. data/lib/oxc/3.3/oxc.so +0 -0
  9. data/lib/oxc/3.4/oxc.so +0 -0
  10. data/lib/oxc/4.0/oxc.so +0 -0
  11. data/lib/oxc/backend.rb +41 -0
  12. data/lib/oxc/diagnosed.rb +33 -0
  13. data/lib/oxc/diagnostic.rb +86 -0
  14. data/lib/oxc/errors.rb +26 -0
  15. data/lib/oxc/minifier.rb +31 -0
  16. data/lib/oxc/minify_result.rb +25 -0
  17. data/lib/oxc/options.rb +113 -0
  18. data/lib/oxc/parse_result.rb +106 -0
  19. data/lib/oxc/result.rb +51 -0
  20. data/lib/oxc/transform_result.rb +47 -0
  21. data/lib/oxc/transformer.rb +31 -0
  22. data/lib/oxc/version.rb +5 -0
  23. data/lib/oxc.rb +52 -0
  24. data/licenses/README.md +12 -0
  25. data/licenses/oxc-MIT.txt +22 -0
  26. data/licenses/oxc-THIRD-PARTY.txt +763 -0
  27. data/oxc.gemspec +43 -0
  28. data/rust/Cargo.lock +1436 -0
  29. data/rust/Cargo.toml +32 -0
  30. data/rust/build.rs +52 -0
  31. data/rust/cbindgen.toml +24 -0
  32. data/rust/rustfmt.toml +3 -0
  33. data/rust/src/diagnostic.rs +75 -0
  34. data/rust/src/lib.rs +288 -0
  35. data/rust/src/module_record.rs +262 -0
  36. data/rust/src/options.rs +744 -0
  37. data/rust/src/parse.rs +93 -0
  38. data/rust/src/result.rs +55 -0
  39. data/rust/src/source_type.rs +26 -0
  40. data/rust/src/symbols.rs +101 -0
  41. data/rust/src/transform.rs +116 -0
  42. data/sig/oxc/backend.rbs +29 -0
  43. data/sig/oxc/diagnosed.rbs +23 -0
  44. data/sig/oxc/diagnostic.rbs +57 -0
  45. data/sig/oxc/errors.rbs +31 -0
  46. data/sig/oxc/minifier.rbs +21 -0
  47. data/sig/oxc/minify_result.rbs +11 -0
  48. data/sig/oxc/options.rbs +42 -0
  49. data/sig/oxc/parse_result.rbs +61 -0
  50. data/sig/oxc/result.rbs +32 -0
  51. data/sig/oxc/transform_result.rbs +22 -0
  52. data/sig/oxc/transformer.rbs +21 -0
  53. data/sig/oxc/types.rbs +96 -0
  54. data/sig/oxc/version.rbs +5 -0
  55. data/sig/oxc.rbs +15 -0
  56. metadata +107 -0
@@ -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
+ }