Repository: swc-project/swc
File: crates/swc_ecma_parser/src/lexer/state.rs (Rust)

Code before:
            None => Ok(Token::Eof),
        }
    }

    #[cold]
    /// Slow path: we encountered `&` in the jsx child, so we need to scan and
    /// resolve the jsx entity, which requires a dedicate string allocation.
    fn scan_jsx_token_with_jsx_entity(&mut self) -> LexResult<Token> {
        let mut value = String::new();
        let mut chunk_start = self.input.cur_pos();

        while let Some(byte) = self.input.cur_as_char() {
            match byte {
                '>' => {
                    self.bump(1);
                    self.emit_error(
                        self.input().cur_pos(),
                        SyntaxError::UnexpectedTokenWithSuggestions {
                            candidate_list: vec!["`{'>'}`", "`&gt;`"],
                        },
                    );
                }
                '}' => {
                    self.bump(1);
                    self.emit_error(
                        self.input().cur_pos(),
                        SyntaxError::UnexpectedTokenWithSuggestions {
                            candidate_list: vec!["`{'}'}`", "`&rbrace;`"],
                        },
                    );
                }
                '&' => {
                    // Push the string before the `&` to the result
                    let s = unsafe {
                        // Safety: We already checked for the range
                        self.input_slice_str(chunk_start, self.cur_pos())
                    };
                    value.push_str(s);

                    // Read the jsx entity and update the start of chunk
                    if let Ok(jsx_entity) = self.read_jsx_entity() {
                        value.push(jsx_entity.0);
                        chunk_start = self.input.cur_pos();
                    }
                }
                '<' | '{' => break,
                c => {
                    self.bump(c.len_utf8());
                }
            }
        }

Review comment (bug):
The error position is incorrect. The code bumps past the '>' character before reporting the error, which means the error will be reported at the position AFTER the '>' instead of AT the '>'. This is inconsistent with the fast path implementation (lines 428-436) where the error is correctly reported at the position of the matched byte. The error reporting should happen before bumping, or the error position should be calculated as the position before the bump.
```suggestion
                    let pos = self.input().cur_pos();
                    self.bump(1);
                    self.emit_error(
                        pos,
                        SyntaxError::UnexpectedTokenWithSuggestions {
                            candidate_list: vec!["`{'>'}`", "`&gt;`"],
                        },
                    );
                }
                '}' => {
                    let pos = self.input().cur_pos();
                    self.bump(1);
                    self.emit_error(
                        pos,
```

Code after:
            None => Ok(Token::Eof),
        }
    }

    #[cold]
    /// Slow path: we encountered `&` in the jsx child, so we need to scan and
    /// resolve the jsx entity, which requires a dedicated string allocation.
    fn scan_jsx_token_with_jsx_entity(&mut self) -> LexResult<Token> {
        let mut value = String::new();
        let mut chunk_start = self.input.cur_pos();

        while let Some(ch) = self.input.cur_as_char() {
            match ch {
                '>' => {
                    let error_pos = self.input().cur_pos();
                    self.bump(1);
                    self.emit_error(
                        error_pos,
                        SyntaxError::UnexpectedTokenWithSuggestions {
                            candidate_list: vec!["`{'>'}`", "`&gt;`"],
                        },
                    );
                }
                '}' => {
                    let error_pos = self.input().cur_pos();
                    self.bump(1);
                    self.emit_error(
                        error_pos,
                        SyntaxError::UnexpectedTokenWithSuggestions {
                            candidate_list: vec!["`{'}'}`", "`&rbrace;`"],
                        },
                    );
                }
                '&' => {
                    // Push the string before the `&` to the result
                    let s = unsafe {
                        // Safety: We already checked for the range
                        self.input_slice_str(chunk_start, self.cur_pos())
                    };
                    value.push_str(s);

                    // Read the jsx entity and update the start of chunk
                    if let Ok(jsx_entity) = self.read_jsx_entity() {
                        value.push(jsx_entity.0);
                        chunk_start = self.input.cur_pos();
                    }
                }
                '<' | '{' => break,
                c => {
                    self.bump(c.len_utf8());
                }