mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
fix(parser): change unterminated regex error to be non-recoverable (#5285)
closes #5257
This commit is contained in:
parent
cffce11620
commit
e6fd52e2a6
6 changed files with 19 additions and 191 deletions
|
|
@ -223,10 +223,10 @@ impl<'a> ParserImpl<'a> {
|
|||
}
|
||||
|
||||
/// Tell lexer to read a regex
|
||||
pub(crate) fn read_regex(&mut self) -> (u32, RegExpFlags) {
|
||||
let (token, pattern_end, flags) = self.lexer.next_regex(self.cur_kind());
|
||||
pub(crate) fn read_regex(&mut self) -> Result<(u32, RegExpFlags)> {
|
||||
let (token, pattern_end, flags) = self.lexer.next_regex(self.cur_kind())?;
|
||||
self.token = token;
|
||||
(pattern_end, flags)
|
||||
Ok((pattern_end, flags))
|
||||
}
|
||||
|
||||
/// Tell lexer to read a template substitution tail
|
||||
|
|
|
|||
|
|
@ -189,10 +189,9 @@ impl<'a> ParserImpl<'a> {
|
|||
}
|
||||
}
|
||||
Kind::LParen => self.parse_parenthesized_expression(span),
|
||||
Kind::Slash | Kind::SlashEq => {
|
||||
let literal = self.parse_literal_regexp();
|
||||
Ok(self.ast.expression_from_reg_exp_literal(literal))
|
||||
}
|
||||
Kind::Slash | Kind::SlashEq => self
|
||||
.parse_literal_regexp()
|
||||
.map(|literal| self.ast.expression_from_reg_exp_literal(literal)),
|
||||
// JSXElement, JSXFragment
|
||||
Kind::LAngle if self.source_type.is_jsx() => self.parse_jsx_expression(),
|
||||
_ => self.parse_identifier_expression(),
|
||||
|
|
@ -336,11 +335,11 @@ impl<'a> ParserImpl<'a> {
|
|||
Ok(self.ast.big_int_literal(self.end_span(span), raw, base))
|
||||
}
|
||||
|
||||
pub(crate) fn parse_literal_regexp(&mut self) -> RegExpLiteral<'a> {
|
||||
pub(crate) fn parse_literal_regexp(&mut self) -> Result<RegExpLiteral<'a>> {
|
||||
let span = self.start_span();
|
||||
|
||||
// split out pattern
|
||||
let (pattern_end, flags) = self.read_regex();
|
||||
let (pattern_end, flags) = self.read_regex()?;
|
||||
let pattern_start = self.cur_token().start + 1; // +1 to exclude `/`
|
||||
let pattern = &self.source_text[pattern_start as usize..pattern_end as usize];
|
||||
self.bump_any();
|
||||
|
|
@ -350,11 +349,11 @@ impl<'a> ParserImpl<'a> {
|
|||
.parse_regular_expression
|
||||
.then(|| self.parse_regex_pattern(pattern_start, pattern, flags));
|
||||
|
||||
self.ast.reg_exp_literal(
|
||||
Ok(self.ast.reg_exp_literal(
|
||||
self.end_span(span),
|
||||
EmptyObject,
|
||||
RegExp { pattern: self.ast.atom(pattern), flags },
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_regex_pattern(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use oxc_syntax::identifier::is_line_terminator;
|
|||
|
||||
use super::{Kind, Lexer, RegExpFlags, Token};
|
||||
use crate::diagnostics;
|
||||
use oxc_diagnostics::Result;
|
||||
|
||||
impl<'a> Lexer<'a> {
|
||||
/// Re-tokenize the current `/` or `/=` and return `RegExp`
|
||||
|
|
@ -10,34 +11,31 @@ impl<'a> Lexer<'a> {
|
|||
/// where a `RegularExpressionLiteral` is permitted
|
||||
/// Which means the parser needs to re-tokenize on `PrimaryExpression`,
|
||||
/// `RegularExpressionLiteral` only appear on the right hand side of `PrimaryExpression`
|
||||
pub(crate) fn next_regex(&mut self, kind: Kind) -> (Token, u32, RegExpFlags) {
|
||||
pub(crate) fn next_regex(&mut self, kind: Kind) -> Result<(Token, u32, RegExpFlags)> {
|
||||
self.token.start = self.offset()
|
||||
- match kind {
|
||||
Kind::Slash => 1,
|
||||
Kind::SlashEq => 2,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let (pattern_end, flags) = self.read_regex();
|
||||
let (pattern_end, flags) = self.read_regex()?;
|
||||
self.lookahead.clear();
|
||||
let token = self.finish_next(Kind::RegExp);
|
||||
(token, pattern_end, flags)
|
||||
Ok((token, pattern_end, flags))
|
||||
}
|
||||
|
||||
/// 12.9.5 Regular Expression Literals
|
||||
fn read_regex(&mut self) -> (u32, RegExpFlags) {
|
||||
fn read_regex(&mut self) -> Result<(u32, RegExpFlags)> {
|
||||
let mut in_escape = false;
|
||||
let mut in_character_class = false;
|
||||
loop {
|
||||
match self.next_char() {
|
||||
None => {
|
||||
self.error(diagnostics::unterminated_reg_exp(self.unterminated_range()));
|
||||
return (self.offset(), RegExpFlags::empty());
|
||||
return Err(diagnostics::unterminated_reg_exp(self.unterminated_range()));
|
||||
// return (self.offset(), RegExpFlags::empty());
|
||||
}
|
||||
Some(c) if is_line_terminator(c) => {
|
||||
self.error(diagnostics::unterminated_reg_exp(self.unterminated_range()));
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
let pattern_end = self.offset() - c.len_utf8() as u32;
|
||||
return (pattern_end, RegExpFlags::empty());
|
||||
return Err(diagnostics::unterminated_reg_exp(self.unterminated_range()));
|
||||
}
|
||||
Some(c) => {
|
||||
if in_escape {
|
||||
|
|
@ -79,6 +77,6 @@ impl<'a> Lexer<'a> {
|
|||
flags |= flag;
|
||||
}
|
||||
|
||||
(pattern_end, flags)
|
||||
Ok((pattern_end, flags))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1308,12 +1308,6 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
|
|||
╭─[babel/packages/babel-parser/test/fixtures/core/uncategorised/380/input.js:1:9]
|
||||
1 │ var x = /
|
||||
· ──
|
||||
2 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[babel/packages/babel-parser/test/fixtures/core/uncategorised/380/input.js:2:2]
|
||||
1 │ var x = /
|
||||
2 │ /
|
||||
╰────
|
||||
|
||||
|
|
@ -1696,19 +1690,6 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
|
|||
╭─[babel/packages/babel-parser/test/fixtures/core/uncategorised/441/input.js:1:1]
|
||||
1 │ /a\
|
||||
· ────
|
||||
2 │ /
|
||||
╰────
|
||||
|
||||
× Invalid regular expression: Invalid escape
|
||||
╭─[babel/packages/babel-parser/test/fixtures/core/uncategorised/441/input.js:1:3]
|
||||
1 │ /a\
|
||||
· ─
|
||||
2 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[babel/packages/babel-parser/test/fixtures/core/uncategorised/441/input.js:2:2]
|
||||
1 │ /a\
|
||||
2 │ /
|
||||
╰────
|
||||
|
||||
|
|
@ -8218,11 +8199,6 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
|
|||
2 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[babel/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0040/input.js:3:1]
|
||||
2 │ /
|
||||
╰────
|
||||
|
||||
× Invalid Unicode escape sequence
|
||||
╭─[babel/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0041/input.js:1:17]
|
||||
1 │ var x = /[a-z]/\ux
|
||||
|
|
@ -8397,11 +8373,6 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
|
|||
2 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[babel/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0062/input.js:3:1]
|
||||
2 │ /
|
||||
╰────
|
||||
|
||||
× Unterminated string
|
||||
╭─[babel/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0063/input.js:1:9]
|
||||
1 │ var x = "
|
||||
|
|
@ -8942,18 +8913,6 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
|
|||
2 │ /
|
||||
╰────
|
||||
|
||||
× Invalid regular expression: Invalid escape
|
||||
╭─[babel/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0157/input.js:1:3]
|
||||
1 │ /a\
|
||||
· ─
|
||||
2 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[babel/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0157/input.js:3:1]
|
||||
2 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[babel/packages/babel-parser/test/fixtures/esprima/invalid-syntax/migrated_0158/input.js:3:1]
|
||||
2 │
|
||||
|
|
|
|||
|
|
@ -19559,11 +19559,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
· ─
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/line-terminators/invalid-regexp-cr.js:19:1]
|
||||
18 │ /
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/line-terminators/invalid-regexp-lf.js:17:1]
|
||||
16 │
|
||||
|
|
@ -19572,11 +19567,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
18 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/line-terminators/invalid-regexp-lf.js:19:1]
|
||||
18 │ /
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/line-terminators/invalid-regexp-ls.js:17:1]
|
||||
16 │
|
||||
|
|
@ -19584,11 +19574,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
· ──
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/line-terminators/invalid-regexp-ls.js:18:1]
|
||||
17 │ /
/
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/line-terminators/invalid-regexp-ps.js:17:1]
|
||||
16 │
|
||||
|
|
@ -19596,11 +19581,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
· ──
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/line-terminators/invalid-regexp-ps.js:18:1]
|
||||
17 │ /
/
|
||||
╰────
|
||||
|
||||
× Unterminated string
|
||||
╭─[test262/test/language/line-terminators/invalid-string-cr.js:16:1]
|
||||
15 │
|
||||
|
|
@ -20388,11 +20368,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
30 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A1.3_T1.js:31:1]
|
||||
30 │ /
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A1.3_T3.js:29:1]
|
||||
28 │
|
||||
|
|
@ -20401,11 +20376,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
30 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A1.3_T3.js:31:1]
|
||||
30 │ /
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A1.5_T1.js:23:1]
|
||||
22 │
|
||||
|
|
@ -20414,19 +20384,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
24 │ /
|
||||
╰────
|
||||
|
||||
× Invalid regular expression: Invalid escape
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A1.5_T1.js:23:2]
|
||||
22 │
|
||||
23 │ /\
|
||||
· ─
|
||||
24 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A1.5_T1.js:25:1]
|
||||
24 │ /
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A1.5_T3.js:22:1]
|
||||
21 │
|
||||
|
|
@ -20435,19 +20392,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
23 │ /
|
||||
╰────
|
||||
|
||||
× Invalid regular expression: Invalid escape
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A1.5_T3.js:22:2]
|
||||
21 │
|
||||
22 │ /\
|
||||
· ─
|
||||
23 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A1.5_T3.js:24:1]
|
||||
23 │ /
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A2.2_T1.js:23:1]
|
||||
22 │
|
||||
|
|
@ -20470,11 +20414,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
33 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A2.3_T1.js:34:1]
|
||||
33 │ /
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A2.3_T3.js:33:1]
|
||||
32 │
|
||||
|
|
@ -20483,11 +20422,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
34 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A2.3_T3.js:35:1]
|
||||
34 │ /
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A2.5_T1.js:28:1]
|
||||
27 │
|
||||
|
|
@ -20496,19 +20430,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
29 │ /
|
||||
╰────
|
||||
|
||||
× Invalid regular expression: Invalid escape
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A2.5_T1.js:28:3]
|
||||
27 │
|
||||
28 │ /a\
|
||||
· ─
|
||||
29 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A2.5_T1.js:30:1]
|
||||
29 │ /
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A2.5_T3.js:28:1]
|
||||
27 │
|
||||
|
|
@ -20517,19 +20438,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
29 │ /
|
||||
╰────
|
||||
|
||||
× Invalid regular expression: Invalid escape
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A2.5_T3.js:28:3]
|
||||
27 │
|
||||
28 │ /a\
|
||||
· ─
|
||||
29 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/S7.8.5_A2.5_T3.js:30:1]
|
||||
29 │ /
|
||||
╰────
|
||||
|
||||
× Unexpected flag G in regular expression literal
|
||||
╭─[test262/test/language/literals/regexp/early-err-bad-flag.js:18:4]
|
||||
17 │
|
||||
|
|
@ -20994,11 +20902,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
30 │
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/regexp-first-char-no-line-separator.js:34:1]
|
||||
33 │ */
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/literals/regexp/regexp-first-char-no-paragraph-separator.js:29:1]
|
||||
28 │
|
||||
|
|
@ -21007,11 +20910,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
30 │
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/regexp-first-char-no-paragraph-separator.js:34:1]
|
||||
33 │ */
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/literals/regexp/regexp-source-char-no-line-separator.js:28:1]
|
||||
27 │
|
||||
|
|
@ -21020,11 +20918,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
29 │
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/regexp-source-char-no-line-separator.js:33:1]
|
||||
32 │ */
|
||||
╰────
|
||||
|
||||
× Unterminated regular expression
|
||||
╭─[test262/test/language/literals/regexp/regexp-source-char-no-paragraph-separator.js:29:1]
|
||||
28 │
|
||||
|
|
@ -21033,11 +20926,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
30 │
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/literals/regexp/regexp-source-char-no-paragraph-separator.js:34:1]
|
||||
33 │ */
|
||||
╰────
|
||||
|
||||
× Invalid regular expression: Could not parse the entire pattern
|
||||
╭─[test262/test/language/literals/regexp/u-invalid-class-escape.js:23:3]
|
||||
22 │
|
||||
|
|
@ -33624,11 +33512,6 @@ Negative Passed: 4220/4220 (100.00%)
|
|||
· ───────
|
||||
╰────
|
||||
|
||||
× Expected `}` but found `EOF`
|
||||
╭─[test262/test/language/statements/function/invalid-function-body-1.js:18:1]
|
||||
17 │ function __func(){/ ABC}
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
╭─[test262/test/language/statements/function/invalid-function-body-2.js:17:19]
|
||||
16 │
|
||||
|
|
|
|||
|
|
@ -20402,17 +20402,6 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/typeFro
|
|||
· ────────────
|
||||
╰────
|
||||
|
||||
× Invalid regular expression: Could not parse the entire pattern
|
||||
╭─[typescript/tests/cases/conformance/parser/ecmascript5/RegularExpressions/parserRegularExpressionDivideAmbiguity4.ts:1:15]
|
||||
1 │ foo(/notregexp);
|
||||
· ▲
|
||||
╰────
|
||||
|
||||
× Expected `)` but found `EOF`
|
||||
╭─[typescript/tests/cases/conformance/parser/ecmascript5/RegularExpressions/parserRegularExpressionDivideAmbiguity4.ts:1:17]
|
||||
1 │ foo(/notregexp);
|
||||
╰────
|
||||
|
||||
× Expected a semicolon or an implicit semicolon after a statement, but found none
|
||||
╭─[typescript/tests/cases/conformance/parser/ecmascript5/RegularExpressions/parserRegularExpressionDivideAmbiguity7.ts:2:3]
|
||||
1 │ (a/8
|
||||
|
|
|
|||
Loading…
Reference in a new issue