Repository: swc-project/swc (rust)

Issue:
`/*#__PURE__*/` comment in the wrong place
### Describe the bug

We're upgrading to a new version of `rollup` (by way of `vite`) and started seeing a bunch of errors that look like this:

```
(!) src/index.js (2:36): A comment

"/*#__PURE__*/"

in "src/index.js" contains an annotation that Rollup cannot interpret due to the position of the comment. The comment will be removed to avoid issues.
```

We're using SWC for transpilation from TypeScript to JavaScript, and I think what's happening is that the new version of rollup is better at detecting incorrect SWC output than the previous version. 

### Input code

```typescript
const createFragment = (key: { name: string }): JSX.Element => (
    <>Key Name: {key.name ?? "None"}</>
);
```


### Config

```json
{
  "sourceMaps": true,
  "module": {
    "type": "es6",
    "strictMode": true,
    "noInterop": false
  },
  "jsc": {
    "externalHelpers": false,
    "target": "es2017",
    "parser": {
      "syntax": "typescript",
      "tsx": true,
      "decorators": true,
      "dynamicImport": true
    },
    "transform": {
      "legacyDecorator": true,
      "decoratorMetadata": false,
      "react": {
        "throwIfNamespace": false,
        "useBuiltins": false,
        "pragma": "React.createElement",
        "pragmaFrag": "React.Fragment",
        "importSource": "react",
        "runtime": "automatic"
      }
    },
    "keepClassNames": true,
    "paths": {},
    "baseUrl": "../.."
  }
}
```


### Playground link (or link to the minimal reproduction)

https://play.swc.rs/?version=1.6.5&code=H4sIAAAAAAAAA0vOzysuUUguSk0sSXUrSkzPTc0rUbBV0MhOrbRSqFbIS8xNtVIoLinKzEtXqNW0UvAKjtBzzUmFKLNT0OBSAAIbO%2B%2FUSgU%2FsNpqoE49kDYFe3sFJb%2F8vFSlWht9Oy5NawDqpaNrawAAAA%3D%3D&config=H4sIAAAAAAAAA3VSy07DMBC89yuqnKvwOIDEkZfooRxAfMDibIvBL%2B1uRKMq%2F443TdqkwMXSzoxnxivvZvN5wbEmgytIXNzMhWpcKOpjVTvMyC5PeZYm6VQgXxWLPcRC1sgqVji6mPEQl0GQYsrwGhxjhtvO9JPN0RG3WRTAPaFLSDyIexMB2qDsEy%2FPL66H0ATESAcXrdEEga0qtSMbskl6tfrwdtIuQxWaSCCR%2BBfTBPDWLH2KJD3Zce3QiiDwOpIfF3C4AdPcD67%2Fxq1QoAKB6UuzghCMjBw16IPi93L9DB45gcHTO1lSM97W1okN%2FAebCDZeo4oXdS9NDhF8cOgxHNdzED7m8yjW6VRnu6W8dp9FlfvSIwHVQazvOKglehBrip5uJ1v8Qkx3Dpi7500%2FTwL5UGg3iN%2BB8Y2c2pblWVmqZTtrZz81fnyAvAIAAA%3D%3D

### SWC Info output

    Operating System:
        Platform: darwin
        Arch: arm64
        Machine Type: arm64
        Version: Darwin Kernel Version 23.5.0: Wed May  1 20:13:18 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T6030
        CPU: (12 cores)
            Models: Apple M3 Pro

    Binaries:
        Node: 20.5.1
        npm: 9.8.0
        Yarn: ⚠️  We've switched to PNPM; Yarn is no longer available.

    Relevant Packages:
        @swc/core: 1.6.5
        @swc/helpers: N/A
        @swc/types: N/A
        typescript: 5.4.5

    SWC Config:
        output: N/A
        .swcrc path: N/A

    Next.js info:
        output: N/A

### Expected behavior

Correct placement (or omission?) of the `/*#__PURE__*/` comment

### Actual behavior

The `/*#__PURE__*/` comment is emitted in a bad location

### Version

@swc/core@1.6.5

### Additional context

Related issues: 
- https://github.com/swc-project/swc/issues/8419
- https://github.com/swc-project/swc/issues/8199

Pull request:
fix(es/compat): Do not reuse span
**Description:**


**Related issue:**

 - Closes #9108

Patch:
diff --git a/crates/swc_ecma_compat_es2020/src/nullish_coalescing.rs b/crates/swc_ecma_compat_es2020/src/nullish_coalescing.rs
index 66240fb3dd..c4b14e5113 100644
--- a/crates/swc_ecma_compat_es2020/src/nullish_coalescing.rs
+++ b/crates/swc_ecma_compat_es2020/src/nullish_coalescing.rs
@@ -1,7 +1,7 @@
 use std::mem::take;
 
 use serde::Deserialize;
-use swc_common::{util::take::Take, Span, Spanned, DUMMY_SP};
+use swc_common::{util::take::Take, Span, DUMMY_SP};
 use swc_ecma_ast::*;
 use swc_ecma_utils::{alias_ident_for_simple_assign_tatget, alias_if_required, StmtLike};
 use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
@@ -192,7 +192,6 @@ impl VisitMut for NullishCoalescing {
             if let BlockStmtOrExpr::Expr(expr) = n {
                 // expr
                 // { var decl = init; return expr; }
-                let span = expr.span();
                 let stmts = vec![
                     VarDecl {
                         span: DUMMY_SP,
@@ -206,7 +205,10 @@ impl VisitMut for NullishCoalescing {
                         arg: Some(expr.take()),
                     }),
                 ];
-                *n = BlockStmtOrExpr::BlockStmt(BlockStmt { span, stmts });
+                *n = BlockStmtOrExpr::BlockStmt(BlockStmt {
+                    span: DUMMY_SP,
+                    stmts,
+                });
             }
         }
 


Test patch:
diff --git a/crates/swc/tests/fixture/issues-9xxx/9110/input/.swcrc b/crates/swc/tests/fixture/issues-9xxx/9110/input/.swcrc
new file mode 100644
index 0000000000..ed708c9e4d
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-9xxx/9110/input/.swcrc
@@ -0,0 +1,31 @@
+{
+    "module": {
+        "type": "es6",
+        "strictMode": true,
+        "noInterop": false
+    },
+    "jsc": {
+        "externalHelpers": false,
+        "target": "es2017",
+        "parser": {
+            "syntax": "typescript",
+            "tsx": true,
+            "decorators": true,
+            "dynamicImport": true
+        },
+        "transform": {
+            "legacyDecorator": true,
+            "decoratorMetadata": false,
+            "react": {
+                "throwIfNamespace": false,
+                "useBuiltins": false,
+                "pragma": "React.createElement",
+                "pragmaFrag": "React.Fragment",
+                "importSource": "react",
+                "runtime": "automatic"
+            }
+        },
+        "keepClassNames": true,
+        "paths": {},
+    }
+}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issues-9xxx/9110/input/1.js b/crates/swc/tests/fixture/issues-9xxx/9110/input/1.js
new file mode 100644
index 0000000000..57750c1e14
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-9xxx/9110/input/1.js
@@ -0,0 +1,3 @@
+const createFragment = (key: { name: string }): JSX.Element => (
+    <>Key Name: {key.name ?? "None"}</>
+);
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issues-9xxx/9110/output/1.js b/crates/swc/tests/fixture/issues-9xxx/9110/output/1.js
new file mode 100644
index 0000000000..48d9d30bfd
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-9xxx/9110/output/1.js
@@ -0,0 +1,10 @@
+const { jsxs: _jsxs, Fragment: _Fragment } = require("react/jsx-runtime");
+const createFragment = (key)=>{
+    var _key_name;
+    return /*#__PURE__*/ _jsxs(_Fragment, {
+        children: [
+            "Key Name: ",
+            (_key_name = key.name) !== null && _key_name !== void 0 ? _key_name : "None"
+        ]
+    });
+};