Repository: swc-project/swc (rust)

Issue:
Infinite loop code generated with JSX + ES5 onChange attribute via anonymous function
### Describe the bug

Hi there,

I discovered this bug while working on my big Next.js 12 application using SWC and then reduced it to a very simple example on a fresh new create-next-app with Next.js 12. And I was able to reproduce it on the SWC playground too.

PS: The playground share functionality is not working at the moment.

### Input code

```tsx
function App() {
  return <Form />
}

function Form({ onChange = function () {} }) {
  return (
    <input
      onChange={function () {
        onChange();
      }}
    />
  );
}
```

### Output code

```js
function App() {
    return React.createElement(Form, null);
}
function Form(param) {
    var _onChange = param.onChange, onChange = _onChange === void 0 ? function() {
    } : _onChange;
    return React.createElement("input", {
        onChange: function onChange() {
            onChange();
        }
    });
}
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": true
    },
    "target": "es5",
    "loose": false,
    "minify": {
      "compress": false,
      "mangle": false
    }
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}
```


### Playground link

_SWC playground share functionality not working at the moment_

### Expected behavior

The generated code should not trigger an infinite loop

### Version

1.2.11

### Additional context

Do we need to rename anonymous functions when compiling to ES5?

Here's a live Next.js demo:
- https://swc-maximum-call-stack-error.vercel.app/
- https://github.com/vvo/swc-maximum-call-stack-error

Pull request description:
fix(es/resolver): Ignore names of jsx attributes
<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->

**Description:**

swc_ecma_transforms_base:
 - Ignore names of jsx attributes. (Closes #2854)

<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->

**BREAKING CHANGE:**
<!--
If this PR introduces a breaking change, it must contain a notice for it to be included in the CHANGELOG. Add description or remove entirely if not breaking.

You may need to update `MIGRATION.md` for the breaking changes.
-->

**Related issue (if exists):**


 - Closes #2854.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b55c1c3f6f..3423b341de 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,12 @@
 
 - **(es/minifier)** Inline into interpolations in tagged template literals (#3287) ([fa5c063](https://github.com/swc-project/swc/commit/fa5c063144246ce634305399787e08498765eb8f))
 
+### Features
+
+
+
+- **(es/compat)** Use remove useless source map entries generated by `classes` (#3242) ([2352920](https://github.com/swc-project/swc/commit/2352920889c217be41dd5d18c2af6088e1cd0473))
+
 ## [1.2.130] - 2022-01-17
 
 ### Bug Fixes
diff --git a/Cargo.lock b/Cargo.lock
index 391198669e..dc7424369c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2652,7 +2652,7 @@ dependencies = [
 
 [[package]]
 name = "swc"
-version = "0.116.2"
+version = "0.116.3"
 dependencies = [
  "ahash",
  "anyhow",
@@ -3096,7 +3096,7 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_transforms"
-version = "0.113.0"
+version = "0.113.1"
 dependencies = [
  "pretty_assertions 0.7.2",
  "sourcemap",
@@ -3156,7 +3156,7 @@ dependencies = [
 
 [[package]]
 name = "swc_ecma_transforms_compat"
-version = "0.68.0"
+version = "0.68.1"
 dependencies = [
  "ahash",
  "arrayvec 0.7.2",
@@ -3365,7 +3365,7 @@ dependencies = [
 
 [[package]]
 name = "swc_ecmascript"
-version = "0.110.2"
+version = "0.110.3"
 dependencies = [
  "swc_ecma_ast",
  "swc_ecma_codegen",
diff --git a/crates/swc/Cargo.toml b/crates/swc/Cargo.toml
index 2fe4b42f58..4351e6ac65 100644
--- a/crates/swc/Cargo.toml
+++ b/crates/swc/Cargo.toml
@@ -9,7 +9,7 @@ include = ["Cargo.toml", "src/**/*.rs"]
 license = "Apache-2.0"
 name = "swc"
 repository = "https://github.com/swc-project/swc.git"
-version = "0.116.2"
+version = "0.116.3"
 
 [lib]
 name = "swc"
@@ -55,7 +55,7 @@ swc_ecma_loader = {version = "0.27.0", path = "../swc_ecma_loader", features = [
 swc_ecma_minifier = {version = "0.70.2", path = "../swc_ecma_minifier"}
 swc_ecma_parser = {version = "0.87.0", path = "../swc_ecma_parser"}
 swc_ecma_preset_env = {version = "0.86.0", path = "../swc_ecma_preset_env"}
-swc_ecma_transforms = {version = "0.113.0", path = "../swc_ecma_transforms", features = [
+swc_ecma_transforms = {version = "0.113.1", path = "../swc_ecma_transforms", features = [
   "compat",
   "module",
   "optimization",
@@ -64,11 +64,11 @@ swc_ecma_transforms = {version = "0.113.0", path = "../swc_ecma_transforms", fea
   "typescript",
 ]}
 swc_ecma_transforms_base = {version = "0.57.0", path = "../swc_ecma_transforms_base"}
-swc_ecma_transforms_compat = {version = "0.68.0", path = "../swc_ecma_transforms_compat"}
+swc_ecma_transforms_compat = {version = "0.68.1", path = "../swc_ecma_transforms_compat"}
 swc_ecma_transforms_optimization = {version = "0.83.0", path = "../swc_ecma_transforms_optimization"}
 swc_ecma_utils = {version = "0.64.0", path = "../swc_ecma_utils"}
 swc_ecma_visit = {version = "0.51.0", path = "../swc_ecma_visit"}
-swc_ecmascript = {version = "0.110.2", path = "../swc_ecmascript"}
+swc_ecmascript = {version = "0.110.3", path = "../swc_ecmascript"}
 swc_node_comments = {version = "0.4.0", path = "../swc_node_comments"}
 swc_plugin_runner = {version = "0.30.0", path = "../swc_plugin_runner", optional = true}
 swc_visit = {version = "0.3.0", path = "../swc_visit"}
diff --git a/crates/swc_ecma_transforms/Cargo.toml b/crates/swc_ecma_transforms/Cargo.toml
index 6f50546082..27ec93a624 100644
--- a/crates/swc_ecma_transforms/Cargo.toml
+++ b/crates/swc_ecma_transforms/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 license = "Apache-2.0"
 name = "swc_ecma_transforms"
 repository = "https://github.com/swc-project/swc.git"
-version = "0.113.0"
+version = "0.113.1"
 
 [package.metadata.docs.rs]
 all-features = true
@@ -28,7 +28,7 @@ swc_common = {version = "0.17.0", path = "../swc_common"}
 swc_ecma_ast = {version = "0.65.0", path = "../swc_ecma_ast"}
 swc_ecma_parser = {version = "0.87.0", path = "../swc_ecma_parser"}
 swc_ecma_transforms_base = {version = "0.57.0", path = "../swc_ecma_transforms_base"}
-swc_ecma_transforms_compat = {version = "0.68.0", path = "../swc_ecma_transforms_compat", optional = true}
+swc_ecma_transforms_compat = {version = "0.68.1", path = "../swc_ecma_transforms_compat", optional = true}
 swc_ecma_transforms_module = {version = "0.74.0", path = "../swc_ecma_transforms_module", optional = true}
 swc_ecma_transforms_optimization = {version = "0.83.0", path = "../swc_ecma_transforms_optimization", optional = true}
 swc_ecma_transforms_proposal = {version = "0.74.0", path = "../swc_ecma_transforms_proposal", optional = true}
diff --git a/crates/swc_ecma_transforms_base/src/resolver/mod.rs b/crates/swc_ecma_transforms_base/src/resolver/mod.rs
index 8bfb04a095..c887b9accf 100644
--- a/crates/swc_ecma_transforms_base/src/resolver/mod.rs
+++ b/crates/swc_ecma_transforms_base/src/resolver/mod.rs
@@ -488,19 +488,6 @@ impl<'a> VisitMut for Resolver<'a> {
         }
     }
 
-    fn visit_mut_switch_stmt(&mut self, s: &mut SwitchStmt) {
-        s.discriminant.visit_mut_with(self);
-
-        let child_mark = Mark::fresh(Mark::root());
-
-        let mut child_folder = Resolver::new(
-            Scope::new(ScopeKind::Block, child_mark, Some(&self.current)),
-            self.handle_types,
-        );
-
-        s.cases.visit_mut_with(&mut child_folder);
-    }
-
     fn visit_mut_catch_clause(&mut self, c: &mut CatchClause) {
         let child_mark = Mark::fresh(Mark::root());
 
@@ -827,6 +814,11 @@ impl<'a> VisitMut for Resolver<'a> {
         self.ident_type = old;
     }
 
+    /// Ignore.
+    ///
+    /// See https://github.com/swc-project/swc/issues/2854
+    fn visit_mut_jsx_attr_name(&mut self, _: &mut JSXAttrName) {}
+
     /// Leftmost one of a member expression should be resolved.
     fn visit_mut_member_expr(&mut self, e: &mut MemberExpr) {
         e.obj.visit_mut_with(self);
@@ -852,11 +844,6 @@ impl<'a> VisitMut for Resolver<'a> {
         };
     }
 
-    // TODO: How should I handle this?
-    typed!(visit_mut_ts_namespace_export_decl, TsNamespaceExportDecl);
-
-    track_ident_mut!();
-
     fn visit_mut_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
         if !self.in_ts_module && self.current.kind != ScopeKind::Fn {
             return stmts.visit_mut_children_with(self);
@@ -877,6 +864,11 @@ impl<'a> VisitMut for Resolver<'a> {
         stmts.visit_mut_children_with(self)
     }
 
+    // TODO: How should I handle this?
+    typed!(visit_mut_ts_namespace_export_decl, TsNamespaceExportDecl);
+
+    track_ident_mut!();
+
     fn visit_mut_named_export(&mut self, e: &mut NamedExport) {
         if e.src.is_some() {
             return;
@@ -978,6 +970,19 @@ impl<'a> VisitMut for Resolver<'a> {
         }
     }
 
+    fn visit_mut_switch_stmt(&mut self, s: &mut SwitchStmt) {
+        s.discriminant.visit_mut_with(self);
+
+        let child_mark = Mark::fresh(Mark::root());
+
+        let mut child_folder = Resolver::new(
+            Scope::new(ScopeKind::Block, child_mark, Some(&self.current)),
+            self.handle_types,
+        );
+
+        s.cases.visit_mut_with(&mut child_folder);
+    }
+
     fn visit_mut_ts_as_expr(&mut self, n: &mut TsAsExpr) {
         if self.handle_types {
             n.type_ann.visit_mut_with(self);
diff --git a/crates/swc_ecma_transforms_compat/Cargo.toml b/crates/swc_ecma_transforms_compat/Cargo.toml
index 921c19bd75..ccf27f9e81 100644
--- a/crates/swc_ecma_transforms_compat/Cargo.toml
+++ b/crates/swc_ecma_transforms_compat/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 license = "Apache-2.0"
 name = "swc_ecma_transforms_compat"
 repository = "https://github.com/swc-project/swc.git"
-version = "0.68.0"
+version = "0.68.1"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [features]
diff --git a/crates/swc_ecmascript/Cargo.toml b/crates/swc_ecmascript/Cargo.toml
index 453ad28110..01dc93eeb1 100644
--- a/crates/swc_ecmascript/Cargo.toml
+++ b/crates/swc_ecmascript/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 license = "Apache-2.0"
 name = "swc_ecmascript"
 repository = "https://github.com/swc-project/swc.git"
-version = "0.110.2"
+version = "0.110.3"
 
 [package.metadata.docs.rs]
 all-features = true
@@ -39,7 +39,7 @@ swc_ecma_dep_graph = {version = "0.58.0", path = "../swc_ecma_dep_graph", option
 swc_ecma_minifier = {version = "0.70.2", path = "../swc_ecma_minifier", optional = true}
 swc_ecma_parser = {version = "0.87.0", path = "../swc_ecma_parser", optional = true, default-features = false}
 swc_ecma_preset_env = {version = "0.86.0", path = "../swc_ecma_preset_env", optional = true}
-swc_ecma_transforms = {version = "0.113.0", path = "../swc_ecma_transforms", optional = true}
+swc_ecma_transforms = {version = "0.113.1", path = "../swc_ecma_transforms", optional = true}
 swc_ecma_utils = {version = "0.64.0", path = "../swc_ecma_utils", optional = true}
 swc_ecma_visit = {version = "0.51.0", path = "../swc_ecma_visit", optional = true}
 


Test patch:
diff --git a/crates/swc/tests/fixture/issue-2854/1/input/.swcrc b/crates/swc/tests/fixture/issue-2854/1/input/.swcrc
new file mode 100644
index 0000000000..0c08f2dee9
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2854/1/input/.swcrc
@@ -0,0 +1,18 @@
+{
+    "jsc": {
+        "parser": {
+            "syntax": "ecmascript",
+            "jsx": true
+        },
+        "target": "es5",
+        "loose": false,
+        "minify": {
+            "compress": false,
+            "mangle": false
+        }
+    },
+    "module": {
+        "type": "es6"
+    },
+    "minify": false
+}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issue-2854/1/input/index.js b/crates/swc/tests/fixture/issue-2854/1/input/index.js
new file mode 100644
index 0000000000..1afc8c376c
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2854/1/input/index.js
@@ -0,0 +1,13 @@
+export function App() {
+    return <Form />
+}
+
+export function Form({ onChange = function () { } }) {
+    return (
+        <input
+            onChange={function () {
+                onChange();
+            }}
+        />
+    );
+}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issue-2854/1/output/index.js b/crates/swc/tests/fixture/issue-2854/1/output/index.js
new file mode 100644
index 0000000000..91e947c2e4
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2854/1/output/index.js
@@ -0,0 +1,11 @@
+export function App() {
+    return React.createElement(Form, null);
+}
+export function Form(param) {
+    var _onChange = param.onChange, onChange = _onChange === void 0 ? function() {} : _onChange;
+    return React.createElement("input", {
+        onChange: function onChange1() {
+            onChange();
+        }
+    });
+}
diff --git a/crates/swc_ecma_transforms_base/tests/resolver/issues/2854/1/input.js b/crates/swc_ecma_transforms_base/tests/resolver/issues/2854/1/input.js
new file mode 100644
index 0000000000..1afc8c376c
--- /dev/null
+++ b/crates/swc_ecma_transforms_base/tests/resolver/issues/2854/1/input.js
@@ -0,0 +1,13 @@
+export function App() {
+    return <Form />
+}
+
+export function Form({ onChange = function () { } }) {
+    return (
+        <input
+            onChange={function () {
+                onChange();
+            }}
+        />
+    );
+}
\ No newline at end of file
diff --git a/crates/swc_ecma_transforms_base/tests/resolver/issues/2854/1/output.js b/crates/swc_ecma_transforms_base/tests/resolver/issues/2854/1/output.js
new file mode 100644
index 0000000000..c6becb55eb
--- /dev/null
+++ b/crates/swc_ecma_transforms_base/tests/resolver/issues/2854/1/output.js
@@ -0,0 +1,8 @@
+export function App() {
+    return <Form />;
+}
+export function Form({ onChange__2 =function() {}  }) {
+    return <input onChange__0={function() {
+        onChange__2();
+    }}/>;
+}
diff --git a/crates/swc_ecma_transforms_base/tests/resolver/vercel/next/server/render/1/output.js b/crates/swc_ecma_transforms_base/tests/resolver/vercel/next/server/render/1/output.js
index d02fa2c6e1..6adc23ad5a 100644
--- a/crates/swc_ecma_transforms_base/tests/resolver/vercel/next/server/render/1/output.js
+++ b/crates/swc_ecma_transforms_base/tests/resolver/vercel/next/server/render/1/output.js
@@ -226,7 +226,7 @@ export async function renderToHTML(req__7, res__7, pathname__7, query__7, render
 
 
 
-                <App__7 {...props__15} Component__7={Component__7} router__7={router__7}/>
+                <App__7 {...props__15} Component__0={Component__7} router__0={router__7}/>
 
 
 
@@ -259,15 +259,15 @@ export async function renderToHTML(req__7, res__7, pathname__7, query__7, render
     let head__7 = defaultHead(inAmpMode__7);
     let scriptLoader__7 = {};
     const nextExport__7 = !isSSG__7 && (renderOpts__7.nextExport || dev__7 && (isAutoExport__7 || isFallback__7));
-    const AppContainer__7 = ({ children__19  })=><RouterContext.Provider value={router__7}>
+    const AppContainer__7 = ({ children__19  })=><RouterContext.Provider value__0={router__7}>
 
 
 
-        <AmpStateContext.Provider value={ampState__7}>
+        <AmpStateContext.Provider value__0={ampState__7}>
 
 
 
-            <HeadManagerContext.Provider value={{
+            <HeadManagerContext.Provider value__0={{
             updateHead: (state__20)=>{
                 head__7 = state__20;
             },
@@ -280,12 +280,12 @@ export async function renderToHTML(req__7, res__7, pathname__7, query__7, render
 
 
 
-                <LoadableContext.Provider value={(moduleName__22)=>reactLoadableModules__7.push(moduleName__22)
+                <LoadableContext.Provider value__0={(moduleName__22)=>reactLoadableModules__7.push(moduleName__22)
         }>
 
 
 
-                    <StyleRegistry registry={jsxStyleRegistry__7}>
+                    <StyleRegistry registry__0={jsxStyleRegistry__7}>
 
 
 
@@ -525,7 +525,7 @@ export async function renderToHTML(req__7, res__7, pathname__7, query__7, render
         if (Document__7.getInitialProps) {
             const renderPage__33 = (options__34 = {})=>{
                 if (ctx__7.err && ErrorDebug__7) {
-                    const html__35 = ReactDOMServer.renderToString(<ErrorDebug__7 error={ctx__7.err}/>);
+                    const html__35 = ReactDOMServer.renderToString(<ErrorDebug__7 error__0={ctx__7.err}/>);
                     return {
                         html__35,
                         head__7
@@ -539,7 +539,7 @@ export async function renderToHTML(req__7, res__7, pathname__7, query__7, render
 
 
 
-                    <EnhancedApp__34 Component__7={EnhancedComponent__34} router__7={router__7} {...props__7}/>
+                    <EnhancedApp__34 Component__0={EnhancedComponent__34} router__0={router__7} {...props__7}/>
 
 
 
@@ -570,11 +570,11 @@ export async function renderToHTML(req__7, res__7, pathname__7, query__7, render
                 styles: docProps__33.styles
             };
         } else {
-            const content__38 = ctx__7.err && ErrorDebug__7 ? <ErrorDebug__7 error={ctx__7.err}/> : <AppContainer__7 >
+            const content__38 = ctx__7.err && ErrorDebug__7 ? <ErrorDebug__7 error__0={ctx__7.err}/> : <AppContainer__7 >
 
 
 
-                <App__7 {...props__7} Component__7={Component__7} router__7={router__7}/>
+                <App__7 {...props__7} Component__0={Component__7} router__0={router__7}/>
 
 
 
@@ -655,11 +655,11 @@ export async function renderToHTML(req__7, res__7, pathname__7, query__7, render
         styles: documentResult__7.styles,
         useMaybeDeferContent
     };
-    const documentHTML__7 = ReactDOMServer.renderToStaticMarkup(<AmpStateContext.Provider value={ampState__7}>
+    const documentHTML__7 = ReactDOMServer.renderToStaticMarkup(<AmpStateContext.Provider value__0={ampState__7}>
 
 
 
-        <HtmlContext.Provider value={htmlProps__7}>
+        <HtmlContext.Provider value__0={htmlProps__7}>