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

Code before:
            kind,
            Span::new_with_checked(start, self.input.cur_pos()),
            had_line_break_before,
        )
    }

    fn read_number(&mut self, had_line_break_before: bool) -> Token {
        let start = self.input.cur_pos();

        while matches!(self.input.cur_as_ascii(), Some(b'0'..=b'9')) {
            self.bump_ascii();
        }

        if self.input.cur_as_ascii() == Some(b'.') {
            self.bump_ascii();
            while matches!(self.input.cur_as_ascii(), Some(b'0'..=b'9')) {
                self.bump_ascii();
            }
        }

        if matches!(self.input.cur_as_ascii(), Some(b'e' | b'E')) {
            self.bump_ascii();
            if matches!(self.input.cur_as_ascii(), Some(b'+' | b'-')) {
                self.bump_ascii();
            }
            if !matches!(self.input.cur_as_ascii(), Some(b'0'..=b'9')) {
                let span = Span::new_with_checked(start, self.input.cur_pos());
                self.errors.push(Error::new(
                    span,
                    Severity::Error,
                    ErrorCode::InvalidNumber,
                    "numeric literal exponent should contain digits",
                ));
            }
            while matches!(self.input.cur_as_ascii(), Some(b'0'..=b'9')) {
                self.bump_ascii();
            }
        }

        let end = self.input.cur_pos();
        let raw = unsafe { self.input.slice_str(start, end) };
        let value = raw.parse::<f64>().unwrap_or_else(|_| {
            self.errors.push(Error::new(
                Span::new_with_checked(start, end),
                Severity::Error,
                ErrorCode::InvalidNumber,
                "failed to parse number literal",
            ));
            0.0
        });


Review comment (bug):
The lexer now produces `TokenKind::StarStar` / `StarStarEq`, but the parser currently doesn’t handle these tokens (e.g. `parse_multiplicative_expr` only matches `Star | Slash | Percent`, and assignment ops don’t include `StarStarEq`). This will cause exponentiation (`**`, `**=`) inputs to fail parsing. Either keep lexing `**` as two `Star` tokens until parser support is added, or update the parser precedence + assignment-op handling to consume these new token kinds.

Code after:
        let kind = if self.input.eat_byte(b'=') {
            assign
        } else {
            plain
        };
        Token::simple(
            kind,
            Span::new_with_checked(start, self.input.cur_pos()),
            had_line_break_before,
        )
    }

    fn star_like(&mut self, had_line_break_before: bool) -> Token {
        let start = self.input.cur_pos();
        self.bump_ascii();
        let kind = if self.input.eat_byte(b'*') {
            if self.input.eat_byte(b'=') {
                TokenKind::StarStarEq
            } else {
                TokenKind::StarStar
            }
        } else if self.input.eat_byte(b'=') {
            TokenKind::StarEq
        } else {
            TokenKind::Star
        };

        Token::simple(
            kind,
            Span::new_with_checked(start, self.input.cur_pos()),
            had_line_break_before,
        )
    }

    fn one(&mut self, kind: TokenKind, had_line_break_before: bool) -> Token {
        let start = self.input.cur_pos();
        self.bump_ascii();
        Token::simple(
            kind,
            Span::new_with_checked(start, self.input.cur_pos()),
            had_line_break_before,
        )
    }

    fn read_number(&mut self, had_line_break_before: bool) -> Token {
        let start = self.input.cur_pos();

        while matches!(self.input.cur_as_ascii(), Some(b'0'..=b'9')) {
            self.bump_ascii();
        }