Repository: swc-project/swc (rust)

Issue:
unknown field `parse`, expected one of `compress`, ...
https://swc.rs/docs/configuration/minification#replacing-terser implies that the swc minifier tries to by fully API-compatible with Terser.

Terser supports a `parse` options property: https://github.com/terser/terser#parse-options

But swc doesn't, leading to
```
unknown field `parse`, expected one of `compress`, `mangle`, `format`, `ecma`, `keep_classnames`, `keepClassnames`, 
`keep_fnames`, `keepFnames`, `module`, `safari10`, `toplevel`, `sourceMap`, `outputPath`, `inlineSourcesContent`, `emitSourceMapColumns`
```

Is this supposed to be allowed or should Parcel filter that out?


### Context


Parcel invokes the swc minifier here: https://github.com/parcel-bundler/parcel/blob/dd9435be8afed35c5ffc161cf4b586fd6c78fc1f/packages/optimizers/swc/src/SwcOptimizer.js#L41

(This was reported to Parcel in https://github.com/parcel-bundler/parcel/issues/9041)

Pull request description:
fix(es): Accept `parse` option for `minify()`
**Description:**

We don't support them. but this is to make API more compatible with `terser`.

**Related issue:**

 - Closes #7455.

Patch:
diff --git a/crates/swc/benches/minify.rs b/crates/swc/benches/minify.rs
index 3e8328bb67..e01780e983 100644
--- a/crates/swc/benches/minify.rs
+++ b/crates/swc/benches/minify.rs
@@ -39,17 +39,12 @@ fn bench_minify(b: &mut Bencher, filename: &str) {
                     &JsMinifyOptions {
                         compress: BoolOrDataConfig::from_bool(true),
                         mangle: BoolOrDataConfig::from_bool(true),
-                        format: Default::default(),
-                        ecma: Default::default(),
-                        keep_classnames: Default::default(),
-                        keep_fnames: Default::default(),
-                        module: Default::default(),
-                        safari10: Default::default(),
                         toplevel: true,
                         source_map: BoolOrDataConfig::from_bool(true),
                         output_path: Default::default(),
                         inline_sources_content: true,
                         emit_source_map_columns: true,
+                        ..Default::default()
                     },
                 )
             })
diff --git a/crates/swc/examples/minify.rs b/crates/swc/examples/minify.rs
index 51b0904e88..038a930d71 100644
--- a/crates/swc/examples/minify.rs
+++ b/crates/swc/examples/minify.rs
@@ -21,17 +21,7 @@ fn main() {
                     &JsMinifyOptions {
                         compress: BoolOrDataConfig::from_bool(true),
                         mangle: BoolOrDataConfig::from_bool(true),
-                        format: Default::default(),
-                        ecma: Default::default(),
-                        keep_classnames: Default::default(),
-                        keep_fnames: Default::default(),
-                        module: Default::default(),
-                        safari10: Default::default(),
-                        toplevel: Default::default(),
-                        source_map: Default::default(),
-                        output_path: Default::default(),
-                        inline_sources_content: Default::default(),
-                        emit_source_map_columns: Default::default(),
+                        ..Default::default()
                     },
                 )
                 .context("failed to minify")
diff --git a/crates/swc/src/config/mod.rs b/crates/swc/src/config/mod.rs
index 83f42299ed..dd00be61a9 100644
--- a/crates/swc/src/config/mod.rs
+++ b/crates/swc/src/config/mod.rs
@@ -1042,6 +1042,9 @@ pub struct Config {
 #[derive(Debug, Clone, Serialize, Deserialize, Default)]
 #[serde(deny_unknown_fields, rename_all = "camelCase")]
 pub struct JsMinifyOptions {
+    #[serde(default)]
+    pub parse: JsMinifyParseOptions,
+
     #[serde(default)]
     pub compress: BoolOrDataConfig<TerserCompressorOptions>,
 
@@ -1103,6 +1106,29 @@ pub struct TerserSourceMapOption {
     pub content: Option<String>,
 }
 
+/// Parser options for `minify()`, which should have the same API as terser.
+///
+/// `jsc.minify.parse` is ignored.
+#[derive(Debug, Clone, Default, Serialize, Deserialize)]
+#[serde(deny_unknown_fields, rename_all = "camelCase")]
+pub struct JsMinifyParseOptions {
+    /// Not supported.
+    #[serde(default, alias = "bare_returns")]
+    pub bare_returns: bool,
+
+    /// Ignored, and always parsed.
+    #[serde(default = "true_by_default", alias = "html5_comments")]
+    pub html5_comments: bool,
+
+    /// Ignored, and always parsed.
+    #[serde(default = "true_by_default")]
+    pub shebang: bool,
+
+    /// Not supported.
+    #[serde(default)]
+    pub spidermonkey: bool,
+}
+
 /// `jsc.minify.format`.
 #[derive(Debug, Clone, Default, Serialize, Deserialize)]
 #[serde(deny_unknown_fields, rename_all = "camelCase")]


Test patch:
diff --git a/crates/swc/tests/exec.rs b/crates/swc/tests/exec.rs
index 916d6f4d1f..5936947230 100644
--- a/crates/swc/tests/exec.rs
+++ b/crates/swc/tests/exec.rs
@@ -186,17 +186,7 @@ fn create_matrix(entry: &Path) -> Vec<Options> {
                             Some(JsMinifyOptions {
                                 compress: BoolOrDataConfig::from_bool(true),
                                 mangle: BoolOrDataConfig::from_bool(true),
-                                format: Default::default(),
-                                ecma: Default::default(),
-                                keep_classnames: Default::default(),
-                                keep_fnames: Default::default(),
-                                module: Default::default(),
-                                safari10: Default::default(),
-                                toplevel: Default::default(),
-                                source_map: Default::default(),
-                                output_path: Default::default(),
-                                inline_sources_content: Default::default(),
-                                emit_source_map_columns: Default::default(),
+                                ..Default::default()
                             })
                         } else {
                             None