fix(es/lexer): Fix handling of jsx escapes (#2723)

swc_ecma_parser:
 - Remove logic for unescaping jsx escapes. (Closes #2162)
This commit is contained in:
RiESAEX 2021-11-11 22:37:21 +08:00 committed by GitHub
parent 665c8e05fc
commit 11d1fa56c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 123 additions and 62 deletions

View File

@ -0,0 +1,8 @@
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": true
}
}
}

View File

@ -0,0 +1,7 @@
function test() {
return (
<>
<A b='\' />
</>
);
}

View File

@ -0,0 +1,5 @@
function test() {
return(/*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(A, {
b: "\\"
})));
}

View File

@ -0,0 +1,8 @@
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": true
}
}
}

View File

@ -0,0 +1,7 @@
function test() {
return (
<>
<A b="\" />
</>
);
}

View File

@ -0,0 +1,5 @@
function test() {
return(/*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(A, {
b: "\\"
})));
}

View File

@ -0,0 +1,8 @@
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": true
}
}
}

View File

@ -0,0 +1,7 @@
function test() {
return (
<>
<A b="\x21" />
</>
);
}

View File

@ -0,0 +1,5 @@
function test() {
return(/*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(A, {
b: "\\x21"
})));
}

View File

@ -0,0 +1,8 @@
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": true
}
}
}

View File

@ -0,0 +1,8 @@
function test() {
return (
<>
<A b="\
" />
</>
);
}

View File

@ -0,0 +1,5 @@
function test() {
return(/*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(A, {
b: "\\ "
})));
}

View File

@ -0,0 +1,8 @@
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": true
}
}
}

View File

@ -0,0 +1,7 @@
function test() {
return (
<>
<A b="\u54e6"/>
</>
);
}

View File

@ -0,0 +1,5 @@
function test() {
return(/*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(A, {
b: "\\u54e6"
})));
}

View File

@ -0,0 +1,8 @@
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": true
}
}
}

View File

@ -0,0 +1,7 @@
function test() {
return (
<>
<A b="\'"/>
</>
);
}

View File

@ -0,0 +1,5 @@
function test() {
return(/*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(A, {
b: "\\'"
})));
}

View File

@ -157,9 +157,8 @@ impl<'a, I: Input> Lexer<'a, I> {
if ch == '\\' {
has_escape = true;
out.push_str(self.input.slice(chunk_start, cur_pos));
let chars = self.read_jsx_escaped_char(&mut Raw(None))?;
out.extend(IntoIterator::into_iter(chars).flatten().flatten());
out.push_str("\\");
self.bump();
chunk_start = self.input.cur_pos();
continue;
@ -192,65 +191,6 @@ impl<'a, I: Input> Lexer<'a, I> {
})
}
fn read_jsx_escaped_char(&mut self, raw: &mut Raw) -> LexResult<[Option<Char>; 2]> {
debug_assert_eq!(self.cur(), Some('\\'));
let start = self.cur_pos();
self.bump(); // '\'
let c = match self.cur() {
Some(c) => c,
None => self.error_span(pos_span(start), SyntaxError::InvalidStrEscape)?,
};
macro_rules! push_c_and_ret {
($c:expr) => {{
raw.push(c);
$c
}};
}
let c = match c {
'\\' => push_c_and_ret!('\\'),
'\r' => {
raw.push_str("\r");
self.bump(); // remove '\r'
if self.eat(b'\n') {
raw.push_str("\n");
}
return Ok(Default::default());
}
'\n' | '\u{2028}' | '\u{2029}' => {
match c {
'\n' => raw.push_str("\n"),
'\u{2028}' => raw.push_str("\u{2028}"),
'\u{2029}' => raw.push_str("\u{2029}"),
_ => unreachable!(),
}
self.bump();
return Ok(Default::default());
}
// read hexadecimal escape sequences
'x' => {
raw.push_str("0x");
self.bump(); // 'x'
return self.read_hex_char(start, 2, raw).map(|v| [Some(v), None]);
}
// read unicode escape sequences
'u' => {
return self
.read_unicode_escape(start, raw)
.map(|v| [Some(v), None]);
}
_ => c,
};
self.input.bump();
Ok([Some('\\'.into()), Some(c.into())])
}
/// Read a JSX identifier (valid tag or attribute name).
///
/// Optimized version since JSX identifiers can"t contain