Repository: swc-project/swc (rust)

Issue:
SimplifyExpr & Fixer should skip ParenExpr at ExportDefaultExpr
### Describe the bug

SimplifyExpr & Fixer should skip ParenExpr at ExportDefaultExpr

### Input code

```typescript
import someFunction from './b';

export default (function someFunction () {
});
```




### Expected behavior

Transform by SimplifyExpr & Fixer should be the origin code.

``` js
import someFunction from './b';

export default (function someFunction () {
});
```

### Actual behavior

But print the below code, the semantics has changed.
``` js
import someFunction from './b';

export default function someFunction () {
};
```

### Version

master code


Pull request description:
fix(es/fixer): Don't change default decls to default expr exports
**Description:**


**Related issue:**

 - Closes #7584.


Patch:
diff --git a/crates/swc_ecma_transforms_base/src/fixer.rs b/crates/swc_ecma_transforms_base/src/fixer.rs
index 453c1b4b0d..d2f8a874a4 100644
--- a/crates/swc_ecma_transforms_base/src/fixer.rs
+++ b/crates/swc_ecma_transforms_base/src/fixer.rs
@@ -438,6 +438,15 @@ impl VisitMut for Fixer<'_> {
     }
 
     fn visit_mut_export_default_expr(&mut self, node: &mut ExportDefaultExpr) {
+        if let Expr::Paren(p) = &mut *node.expr {
+            match &mut *p.expr {
+                Expr::Fn(..) | Expr::Class(..) => {
+                    p.expr.visit_mut_children_with(self);
+                    return;
+                }
+                _ => {}
+            }
+        }
         let old = self.ctx;
         self.ctx = Context::Default;
         node.visit_mut_children_with(self);
diff --git a/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs b/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs
index 9d58f679ff..4b69326f63 100644
--- a/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs
+++ b/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs
@@ -1448,6 +1448,23 @@ impl VisitMut for SimplifyExpr {
         };
     }
 
+    fn visit_mut_export_default_expr(&mut self, expr: &mut ExportDefaultExpr) {
+        fn is_paren_wrap_fn_or_class(expr: &mut Expr, visitor: &mut SimplifyExpr) -> bool {
+            match &mut *expr {
+                Expr::Fn(..) | Expr::Class(..) => {
+                    expr.visit_mut_children_with(visitor);
+                    true
+                }
+                Expr::Paren(p) => is_paren_wrap_fn_or_class(&mut p.expr, visitor),
+                _ => false,
+            }
+        }
+
+        if !is_paren_wrap_fn_or_class(&mut expr.expr, self) {
+            expr.visit_mut_children_with(self);
+        }
+    }
+
     fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {
         let mut child = SimplifyExpr {
             expr_ctx: self.expr_ctx.clone(),


Test patch:
diff --git a/crates/swc_ecma_transforms_optimization/src/simplify/expr/tests.rs b/crates/swc_ecma_transforms_optimization/src/simplify/expr/tests.rs
index b810fbfbf1..4b54925ce3 100644
--- a/crates/swc_ecma_transforms_optimization/src/simplify/expr/tests.rs
+++ b/crates/swc_ecma_transforms_optimization/src/simplify/expr/tests.rs
@@ -1544,3 +1544,10 @@ fn test_es6_features() {
         "function foo() {return `${false}`}",
     );
 }
+
+#[test]
+fn test_export_default_paren_expr() {
+    fold_same("import fn from './b'; export default (class fn {});");
+    fold_same("import fn from './b'; export default (function fn () {});");
+    fold("export default ((foo));", "export default foo;");
+}