Repository: swc-project/swc (rust)

Issue:
JsMinifyOptions.keep_fnames throws unknown field
### Describe the bug

```
Error: unknown field `keep_fnames`, expected one of `compress`, `mangle`, `format`, `ecma`, `keepClassnames`, `keepFnames`, `module`, `safari10`, `toplevel`, `sourceMap`, `outputPath`, `inlineSourcesContent`, `emitSourceMapColumns` at line 1 column 794
```

### Input code

_No response_

### Config

```json
{ "minify": { "keep_fnames": true } }
```


### Playground link

_No response_

### Expected behavior

recognizes JsMinifyOptions.keep_fnames to be compatible with TerserOptions, or correct the property name in https://github.com/swc-project/swc/blob/main/node-swc/src/types.ts#L17 perhaps

### Actual behavior

_No response_

### Version

1.3.36

### Additional context

payground prompts `keepFnames`, hence it's working properly

Pull request:
fix: accept both keep_fnames and keep_classnames in jsc minify options

**Description:**

att, closes #6996

**BREAKING CHANGE:**

this change is backward compatible

**Related issue (if exists):**

https://github.com/swc-project/swc/issues/6996

Patch:
diff --git a/crates/swc/src/config/issue-6996.json b/crates/swc/src/config/issue-6996.json
new file mode 100644
index 0000000000..7348210e63
--- /dev/null
+++ b/crates/swc/src/config/issue-6996.json
@@ -0,0 +1,19 @@
+{
+    "test": ".jsx?$",
+    "jsc": {
+        "parser": {
+            "syntax": "ecmascript",
+            "jsx": true,
+            "decorators": true,
+            "dynamicImport": true
+        },
+        "transform": {
+            "react": {
+                "refresh": true
+            }
+        },
+        "minify": {
+            "keep_fnames": true
+        }
+    }
+}
diff --git a/crates/swc/src/config/mod.rs b/crates/swc/src/config/mod.rs
index 12567f86a2..ad147b7aec 100644
--- a/crates/swc/src/config/mod.rs
+++ b/crates/swc/src/config/mod.rs
@@ -920,10 +920,10 @@ pub struct JsMinifyOptions {
     #[serde(default)]
     pub ecma: TerserEcmaVersion,
 
-    #[serde(default)]
+    #[serde(default, alias = "keep_classnames")]
     pub keep_classnames: bool,
 
-    #[serde(default)]
+    #[serde(default, alias = "keep_fnames")]
     pub keep_fnames: bool,
 
     #[serde(default)]


Test patch:
diff --git a/crates/swc/src/config/tests.rs b/crates/swc/src/config/tests.rs
index dbf2f96099..47411a88ad 100644
--- a/crates/swc/src/config/tests.rs
+++ b/crates/swc/src/config/tests.rs
@@ -26,3 +26,9 @@ fn jsonc() {
     let rc = parse_swcrc(include_str!("jsonc.json")).expect("failed to parse");
     dbg!(&rc);
 }
+
+#[test]
+fn issue_6996() {
+    let rc = parse_swcrc(include_str!("issue-6996.json")).expect("failed to parse");
+    dbg!(&rc);
+}
diff --git a/node-swc/__tests__/minify/issue_6996_test.mjs b/node-swc/__tests__/minify/issue_6996_test.mjs
new file mode 100644
index 0000000000..0272ffbfa2
--- /dev/null
+++ b/node-swc/__tests__/minify/issue_6996_test.mjs
@@ -0,0 +1,15 @@
+import swc from "../../..";
+
+it("should not throw when keep_fnames is on", async () => {
+    async function minify() {
+        const { code } = await swc.transform('function Foo() {}', {
+            jsc: {
+                minify: {
+                    keep_fnames: true,
+                },
+            },
+        });
+        return code;
+    }
+    await expect(minify()).resolves.toEqual('function Foo() {}\n');
+});