fix(parser): reject trailing tokens in Parser::parse_expression (#25371)

## Summary

`ReplaceGlobalDefinesConfig` validates replacement values with `Parser::parse_expression`, which previously accepted a valid prefix and ignored the remaining tokens. Require the parser to consume the whole input so invalid values such as `console.log foo` are rejected instead of being truncated.

Fixes #25369
This commit is contained in:
camc314 committed 2026-08-07 21:04:52 +00:00
1 parent 9c13f5e181
commit cc2e28d3e3
2 files changed
+20 -1

No files matched your search

+13 -1
View File
@@ -407,7 +407,7 @@ mod parser_parse {
/// use oxc_parser::Parser;
/// use oxc_span::SourceType;
///
/// let src = "let x = 1 + 2;";
/// let src = "1 + 2";
/// let allocator = Allocator::new();
/// let source_type = SourceType::default();
///
@@ -774,6 +774,9 @@ impl<'a, C: ParserConfig> ParserImpl<'a, C> {
// initialize cur_token and prev_token by moving onto the first token
self.bump_any();
let expr = self.parse_expr();
if !self.at(Kind::Eof) {
self.set_unexpected();
}
if let Some(FatalError { error, .. }) = self.fatal_error.take() {
return Err(error.into_diagnostic().into());
}
@@ -963,6 +966,15 @@ mod test {
assert!(matches!(expr, Expression::Identifier(_)));
}
#[test]
fn parse_expression_rejects_trailing_tokens() {
let allocator = Allocator::default();
let source_type = SourceType::default();
for source in ["a b", "a;", "let x = 1"] {
assert!(Parser::new(&allocator, source, source_type).parse_expression().is_err());
}
}
#[test]
fn flow_error() {
let allocator = Allocator::default();
@@ -199,6 +199,13 @@ fn invalid_typeof_define_key() {
}
}
#[test]
fn invalid_define_value() {
for value in ["console.log foo", "1 2", "foo;"] {
assert!(ReplaceGlobalDefinesConfig::new(&[("foo", value)]).is_err(), "{value}");
}
}
#[test]
fn dot() {
let config = config(&[("process.env.NODE_ENV", "production")]);