Repository: swc-project/swc (rust)

Issue:
minify.format.ascii_only results in invalid escape sequences
### Describe the bug

Sometimes ascii_only results in invalid escape sequences.

### Input code

```typescript
function p(µ, σ) {}
console.log(p);
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": false
    },
    "target": "es5",
    "loose": false,
    "minify": {
      "compress": false,
      "mangle": false,
      "format": {
        "ascii_only": true
      }
    },
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}
```


### Playground link (or link to the minimal reproduction)

https://play.swc.rs/?version=1.3.94-nightly-20231016.1&code=H4sIAAAAAAAAA0srzUsuyczPUyjQOLRVR%2BF8s6ZCdS1Xcn5ecX5Oql5OfrpGgaY1AJi68IYlAAAA&config=H4sIAAAAAAAAA2WPSw7DIAxE9z1F5HW37aJ36BkqizoRET%2FZRGoU5e4FAkmqbhC8GY%2BH5dJ1MIqCR7eka3oEZCHe34nI7CJ%2BEgFSFkWxDhGuTR0lSz0aoYLWTYGIPFAsU3KrdjDeCzV7ZVY73c%2FnhcrbwCTya8xWdIOhP9x7thhPCYmlnlq%2FvDM5OfJEVVqPkuUA699Tyaz%2Fj3OgrfUdDlPruC8GLc82WeLXLxV2OoFLAQAA

### SWC Info output

_No response_

### Expected behavior

Output valid JS

### Actual behavior

```js
function p(\xb5, \u03C3) {}
console.log(p);
```

### Version

1.3.94-nightly-20231016.1

### Additional context

https://github.com/parcel-bundler/parcel/issues/9370

Pull request:
fix(es/codegen): Fix `get_ascii_only_ident`
**Description:**

**Related issue:**

 - Closes #8260

Patch:
diff --git a/crates/swc_ecma_codegen/src/lib.rs b/crates/swc_ecma_codegen/src/lib.rs
index 441c3a9c39..7691048a75 100644
--- a/crates/swc_ecma_codegen/src/lib.rs
+++ b/crates/swc_ecma_codegen/src/lib.rs
@@ -1657,20 +1657,6 @@ where
     fn emit_prop_name(&mut self, node: &PropName) -> Result {
         match node {
             PropName::Ident(ident) => {
-                if self.cfg.ascii_only && !ident.sym.is_ascii() {
-                    punct!("\"");
-                    self.wr.write_symbol(
-                        DUMMY_SP,
-                        &get_ascii_only_ident(
-                            &handle_invalid_unicodes(&ident.sym),
-                            self.cfg.target,
-                        ),
-                    )?;
-                    punct!("\"");
-
-                    return Ok(());
-                }
-
                 emit!(ident)
             }
             PropName::Str(ref n) => emit!(n),
@@ -3705,6 +3691,7 @@ fn get_ascii_only_ident(sym: &str, target: EsVersion) -> Cow<str> {
         return Cow::Borrowed(sym);
     }
 
+    let mut first = true;
     let mut buf = String::with_capacity(sym.len() + 8);
     let mut iter = sym.chars().peekable();
 
@@ -3798,16 +3785,16 @@ fn get_ascii_only_ident(sym: &str, target: EsVersion) -> Cow<str> {
             '"' => {
                 buf.push('"');
             }
-            '\x01'..='\x0f' => {
+            '\x01'..='\x0f' if !first => {
                 let _ = write!(buf, "\\x0{:x}", c as u8);
             }
-            '\x10'..='\x1f' => {
+            '\x10'..='\x1f' if !first => {
                 let _ = write!(buf, "\\x{:x}", c as u8);
             }
             '\x20'..='\x7e' => {
                 buf.push(c);
             }
-            '\u{7f}'..='\u{ff}' => {
+            '\u{7f}'..='\u{ff}' if !first => {
                 let _ = write!(buf, "\\x{:x}", c as u8);
             }
             '\u{2028}' => {
@@ -3842,6 +3829,7 @@ fn get_ascii_only_ident(sym: &str, target: EsVersion) -> Cow<str> {
                 }
             }
         }
+        first = false;
     }
 
     Cow::Owned(buf)


Test patch:
diff --git a/crates/swc/tests/fixture/issues-7xxx/7240/output/index.js b/crates/swc/tests/fixture/issues-7xxx/7240/output/index.js
index 708e259f83..240bd27309 100644
--- a/crates/swc/tests/fixture/issues-7xxx/7240/output/index.js
+++ b/crates/swc/tests/fixture/issues-7xxx/7240/output/index.js
@@ -8,6 +8,6 @@ Object.defineProperty(exports, "__esModule", {
     }
 });
 var _obj, _default = ((_obj = {
-    "\u3131": "\u11B0",
-    "\u3141": "\u11B1"
+    \u3131: "\u11B0",
+    \u3141: "\u11B1"
 })["\u3142"] = "\u11B2", _obj);
diff --git a/crates/swc/tests/fixture/issues-7xxx/7805/output/1.js b/crates/swc/tests/fixture/issues-7xxx/7805/output/1.js
index b7618cc853..0ca9c927f0 100644
--- a/crates/swc/tests/fixture/issues-7xxx/7805/output/1.js
+++ b/crates/swc/tests/fixture/issues-7xxx/7805/output/1.js
@@ -2,17 +2,17 @@ var SUPPORTED_LOCALE = {
     tr: {
         regexp: /\u0130|\u0049|\u0049\u0307/g,
         map: {
-            "\u0130": "i",
+            \u0130: "i",
             I: "\u0131",
-            "I\u0307": "i"
+            I\u0307: "i"
         }
     },
     az: {
         regexp: /\u0130/g,
         map: {
-            "\u0130": "i",
+            \u0130: "i",
             I: "\u0131",
-            "I\u0307": "i"
+            I\u0307: "i"
         }
     },
     lt: {
@@ -20,10 +20,10 @@ var SUPPORTED_LOCALE = {
         map: {
             I: "i\u0307",
             J: "j\u0307",
-            "\u012E": "\u012F\u0307",
-            "\xcc": "i\u0307\u0300",
-            "\xcd": "i\u0307\u0301",
-            "\u0128": "i\u0307\u0303"
+            \u012E: "\u012F\u0307",
+            \u00CC: "i\u0307\u0300",
+            \u00CD: "i\u0307\u0301",
+            \u0128: "i\u0307\u0303"
         }
     }
 };
diff --git a/crates/swc/tests/fixture/issues-8xxx/8260/input/.swcrc b/crates/swc/tests/fixture/issues-8xxx/8260/input/.swcrc
new file mode 100644
index 0000000000..773242e031
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8260/input/.swcrc
@@ -0,0 +1,22 @@
+{
+    "jsc": {
+        "parser": {
+            "syntax": "ecmascript",
+            "jsx": false
+        },
+        "target": "es5",
+        "loose": false,
+        "minify": {
+            "compress": false,
+            "mangle": false,
+            "format": {
+                "ascii_only": true
+            }
+        },
+    },
+    "module": {
+        "type": "es6"
+    },
+    "minify": false,
+    "isModule": true
+}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issues-8xxx/8260/input/1.js b/crates/swc/tests/fixture/issues-8xxx/8260/input/1.js
new file mode 100644
index 0000000000..fe8e3a2361
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8260/input/1.js
@@ -0,0 +1,2 @@
+function p(µ, σ) { }
+console.log(p);
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issues-8xxx/8260/output/1.js b/crates/swc/tests/fixture/issues-8xxx/8260/output/1.js
new file mode 100644
index 0000000000..eb9aa7df1d
--- /dev/null
+++ b/crates/swc/tests/fixture/issues-8xxx/8260/output/1.js
@@ -0,0 +1,2 @@
+function p(\u00B5, \u03C3) {}
+console.log(p);