Repository: swc-project/swc (rust)

Issue:
TaggedTemplateLiteral Parser Error
### Describe the bug

When dealing the template object, there may be an error in swc,
the result of input code run by node is true, but after transforming by swc, the result is false.


### Input code

```typescript
let filter = void 0;
function test(quasis, ...expressionValues){
	const {raw} = quasis;
	const rawLen = raw.length;
	expressionValues = expressionValues.map( filter || ((x) => `(${x})`) )

	let s = '', i = 0;
	while (true) {
		s += raw[i];
		if (i + 1 === rawLen) {
			return s;
		}
		s += expressionValues[i++];
	}
}
{// raw unicode, hex
	let hex = test`\x22\x21\x224`;
	console.log(hex === "\\x22\\x21\\x224");
}
```


### Config

```json
{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": false,
      "dynamicImport": false,
      "privateMethod": false,
      "functionBind": false,
      "exportDefaultFrom": false,
      "exportNamespaceFrom": false,
      "decorators": false,
      "decoratorsBeforeExport": false,
      "topLevelAwait": false,
      "importMeta": false
    },
    "transform": null,
    "target": "es5",
    "loose": false,
    "externalHelpers": false
  }
}
```


### Playground link

https://play.swc.rs/?version=1.2.111&code=H4sIAAAAAAAAA12QTWrDMBCF19IphlCIhI3ThOyMe4Kuu0kKNs4kFqhSqp%2FG4PjuHdnxxgsxw3tvRh%2BjMcBV6YAOKviz6gLvJb9G0wZlDQT0QfzGxiufQ1EU2N8dek%2FWV6Mjejlw1lrjAwyueYy0Yg6Xi0zqJxrSqSk0mlvoyFuvIX8tFT%2FNXSxkzycI0UuoPqAWb0M%2FylqC5Jxpok%2FT220Oiiqxs0enNIIILqIE4mMesun%2Fk%2Fomm6krCAUZ7KGqqhfgHGQOQ3QGEj4bl8k12UllWVo08pEPu13aANGo1l4whw77mYoa4kn3q8%2F94UBvn%2Bqxfp3Gaiy0vYkpRxyb8xSbclNwI0s%2B%2FgNMedErngEAAA%3D%3D&config=H4sIAAAAAAAAA0VOOw6DMAy9i2fWLtygA4ewgkFBSRzZRmqKuHsTNcBkv4%2Ff8wGbOhgPyChK0jYtyfADI5CLqE58NhiqrVILBqVzAENZyZpFX1ULzEpdHSD65JfSkhzHLKT6SJjWcDnPGhR53htxgJVcZzuJnDatqWrind23fzjx%2FDQF%2FJYbJH4nI%2BH8vHl90h1ep15nstP5A1SlDpf7AAAA

### Expected behavior

The ori code run by node is true, but after transforming, the result is false.

### Version

1.2.111

### Additional context

I run swc use cmd as follows
```bash
npx swc --config-file=.swcrc poc.js -o poc.js
```
The environment is ubuntu 20.04 amd64.

Pull request:
fix(ecma/lexer): hexadecimal escape sequences
fix #2822


Patch:
diff --git a/crates/swc_ecma_minifier/src/compress/pure/strings.rs b/crates/swc_ecma_minifier/src/compress/pure/strings.rs
index 229ca9e701..230d4f79d5 100644
--- a/crates/swc_ecma_minifier/src/compress/pure/strings.rs
+++ b/crates/swc_ecma_minifier/src/compress/pure/strings.rs
@@ -23,6 +23,7 @@ where
                 }) && (M::force_str_for_tpl()
                     || (!c.value.contains("\\n") && !c.value.contains("\\r")))
                     && !c.value.contains("\\0")
+                    && !c.value.contains("\\x")
                 {
                     *e = Expr::Lit(Lit::Str(Str {
                         value: c
diff --git a/crates/swc_ecma_parser/src/lexer/mod.rs b/crates/swc_ecma_parser/src/lexer/mod.rs
index 5055a3bb70..6b9cea705b 100644
--- a/crates/swc_ecma_parser/src/lexer/mod.rs
+++ b/crates/swc_ecma_parser/src/lexer/mod.rs
@@ -530,7 +530,7 @@ impl<'a, I: Input> Lexer<'a, I> {
 
             // read hexadecimal escape sequences
             'x' => {
-                raw.push_str("0x");
+                raw.push_str("x");
                 self.bump(); // 'x'
                 return self.read_hex_char(start, 2, raw).map(Some);
             }


Test patch:
diff --git a/crates/swc/tests/fixture/issue-2822/1/input/.swcrc b/crates/swc/tests/fixture/issue-2822/1/input/.swcrc
new file mode 100644
index 0000000000..2fdb3e32f3
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2822/1/input/.swcrc
@@ -0,0 +1,5 @@
+{
+  "jsc": {
+    "target": "es5"
+  }
+}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issue-2822/1/input/index.js b/crates/swc/tests/fixture/issue-2822/1/input/index.js
new file mode 100644
index 0000000000..3ad69b66f5
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2822/1/input/index.js
@@ -0,0 +1,1 @@
+console.log`\x22\x21\x224`
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issue-2822/1/output/index.js b/crates/swc/tests/fixture/issue-2822/1/output/index.js
new file mode 100644
index 0000000000..ccb5b36c71
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2822/1/output/index.js
@@ -0,0 +1,22 @@
+function _taggedTemplateLiteral(strings, raw) {
+    if (!raw) {
+        raw = strings.slice(0);
+    }
+    return Object.freeze(Object.defineProperties(strings, {
+        raw: {
+            value: Object.freeze(raw)
+        }
+    }));
+}
+function _templateObject() {
+    var data = _taggedTemplateLiteral([
+        "\"!\"4"
+    ], [
+        "\\x22\\x21\\x224"
+    ]);
+    _templateObject = function _templateObject() {
+        return data;
+    };
+    return data;
+}
+console.log(_templateObject());
diff --git a/crates/swc/tests/fixture/issue-2822/2/input/.swcrc b/crates/swc/tests/fixture/issue-2822/2/input/.swcrc
new file mode 100644
index 0000000000..cedb940d7b
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2822/2/input/.swcrc
@@ -0,0 +1,5 @@
+{
+  "jsc": {
+    "target": "es2015"
+  }
+}
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issue-2822/2/input/index.js b/crates/swc/tests/fixture/issue-2822/2/input/index.js
new file mode 100644
index 0000000000..ef5c859686
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2822/2/input/index.js
@@ -0,0 +1,1 @@
+`\x22\x21\x224`
\ No newline at end of file
diff --git a/crates/swc/tests/fixture/issue-2822/2/output/index.js b/crates/swc/tests/fixture/issue-2822/2/output/index.js
new file mode 100644
index 0000000000..be8d3419b3
--- /dev/null
+++ b/crates/swc/tests/fixture/issue-2822/2/output/index.js
@@ -0,0 +1,1 @@
+`\x22\x21\x224`;
diff --git a/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes01/input.ts/es2015.1.normal/output.js b/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes01/input.ts/es2015.1.normal/output.js
index 4eaec0d510..ee39cd6f05 100644
--- a/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes01/input.ts/es2015.1.normal/output.js
+++ b/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes01/input.ts/es2015.1.normal/output.js
@@ -1,1 +1,1 @@
-var x = `\0\0x00\u0000 0 00 0000`;
+var x = `\0\x00\u0000 0 00 0000`;
diff --git a/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes01_ES6/input.ts/es2015.1.normal/output.js b/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes01_ES6/input.ts/es2015.1.normal/output.js
index 9e752a2a2e..8b29233d47 100644
--- a/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes01_ES6/input.ts/es2015.1.normal/output.js
+++ b/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes01_ES6/input.ts/es2015.1.normal/output.js
@@ -1,2 +1,2 @@
 // @target: es6
-var x = `\0\0x00\u0000 0 00 0000`;
+var x = `\0\x00\u0000 0 00 0000`;
diff --git a/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes03/input.ts/es2015.1.normal/output.js b/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes03/input.ts/es2015.1.normal/output.js
index c383f62398..142dd43671 100644
--- a/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes03/input.ts/es2015.1.normal/output.js
+++ b/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes03/input.ts/es2015.1.normal/output.js
@@ -1,1 +1,1 @@
-var x = `\x1f\u001f 1F 1f`;
+var x = `\x1F\u001f 1F 1f`;
diff --git a/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes03_ES6/input.ts/es2015.1.normal/output.js b/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes03_ES6/input.ts/es2015.1.normal/output.js
index eca2694ce4..768cd233de 100644
--- a/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes03_ES6/input.ts/es2015.1.normal/output.js
+++ b/crates/swc/tests/tsc-references/es6/templates/templateStringControlCharacterEscapes03_ES6/input.ts/es2015.1.normal/output.js
@@ -1,2 +1,2 @@
 // @target: es6
-var x = `\x1f\u001f 1F 1f`;
+var x = `\x1F\u001f 1F 1f`;
diff --git a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes01/input.ts.json b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes01/input.ts.json
index 173d7cee22..1e4454700f 100644
--- a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes01/input.ts.json
+++ b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes01/input.ts.json
@@ -72,7 +72,7 @@
                     "end": 33,
                     "ctxt": 0
                   },
-                  "value": "\\0\\0x00\\u0000 0 00 0000",
+                  "value": "\\0\\x00\\u0000 0 00 0000",
                   "hasEscape": true,
                   "kind": {
                     "type": "normal",
diff --git a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes01_ES6/input.ts.json b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes01_ES6/input.ts.json
index 5ab5559f8a..8f84ed848c 100644
--- a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes01_ES6/input.ts.json
+++ b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes01_ES6/input.ts.json
@@ -72,7 +72,7 @@
                     "end": 48,
                     "ctxt": 0
                   },
-                  "value": "\\0\\0x00\\u0000 0 00 0000",
+                  "value": "\\0\\x00\\u0000 0 00 0000",
                   "hasEscape": true,
                   "kind": {
                     "type": "normal",
diff --git a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes02/input.ts.json b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes02/input.ts.json
index 55a6fc20ba..97716c639c 100644
--- a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes02/input.ts.json
+++ b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes02/input.ts.json
@@ -72,7 +72,7 @@
                     "end": 24,
                     "ctxt": 0
                   },
-                  "value": "\\0x19\\u0019 19",
+                  "value": "\\x19\\u0019 19",
                   "hasEscape": true,
                   "kind": {
                     "type": "normal",
diff --git a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes02_ES6/input.ts.json b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes02_ES6/input.ts.json
index afa0549a11..3026aacd2d 100644
--- a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes02_ES6/input.ts.json
+++ b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes02_ES6/input.ts.json
@@ -72,7 +72,7 @@
                     "end": 39,
                     "ctxt": 0
                   },
-                  "value": "\\0x19\\u0019 19",
+                  "value": "\\x19\\u0019 19",
                   "hasEscape": true,
                   "kind": {
                     "type": "normal",
diff --git a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes03/input.ts.json b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes03/input.ts.json
index ed7daf8a2a..cc305ba2f6 100644
--- a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes03/input.ts.json
+++ b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes03/input.ts.json
@@ -72,7 +72,7 @@
                     "end": 27,
                     "ctxt": 0
                   },
-                  "value": "\\0x1F\\u001f 1F 1f",
+                  "value": "\\x1F\\u001f 1F 1f",
                   "hasEscape": true,
                   "kind": {
                     "type": "normal",
diff --git a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes03_ES6/input.ts.json b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes03_ES6/input.ts.json
index 7368619862..f9daa5b478 100644
--- a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes03_ES6/input.ts.json
+++ b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes03_ES6/input.ts.json
@@ -72,7 +72,7 @@
                     "end": 42,
                     "ctxt": 0
                   },
-                  "value": "\\0x1F\\u001f 1F 1f",
+                  "value": "\\x1F\\u001f 1F 1f",
                   "hasEscape": true,
                   "kind": {
                     "type": "normal",
diff --git a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes04/input.ts.json b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes04/input.ts.json
index 83362184f9..8909e8d701 100644
--- a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes04/input.ts.json
+++ b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes04/input.ts.json
@@ -72,7 +72,7 @@
                     "end": 24,
                     "ctxt": 0
                   },
-                  "value": "\\0x20\\u0020 20",
+                  "value": "\\x20\\u0020 20",
                   "hasEscape": true,
                   "kind": {
                     "type": "normal",
diff --git a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes04_ES6/input.ts.json b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes04_ES6/input.ts.json
index 565f58c2c2..7b1eaf4593 100644
--- a/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes04_ES6/input.ts.json
+++ b/crates/swc_ecma_parser/tests/typescript/tsc/es6/templates/templateStringControlCharacterEscapes04_ES6/input.ts.json
@@ -72,7 +72,7 @@
                     "end": 39,
                     "ctxt": 0
                   },
-                  "value": "\\0x20\\u0020 20",
+                  "value": "\\x20\\u0020 20",
                   "hasEscape": true,
                   "kind": {
                     "type": "normal",