Skip to content

Commit

Permalink
fix(parser): fix crashing on empty ParenthesizedExpression with comments
Browse files Browse the repository at this point in the history
relates #232
  • Loading branch information
Boshen committed Apr 6, 2023
1 parent 6fca022 commit 9bb2650
Show file tree
Hide file tree
Showing 8 changed files with 25 additions and 33 deletions.
1 change: 1 addition & 0 deletions crates/oxc_ast/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ impl Span {

#[must_use]
pub fn len(&self) -> u32 {
debug_assert!(self.start <= self.end);
self.end - self.start
}

Expand Down
10 changes: 7 additions & 3 deletions crates/oxc_parser/src/js/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,18 +196,22 @@ impl<'a> Parser<'a> {
self.ctx = self.ctx.and_in(has_in);

let mut expressions = list.elements;
let paren_span = self.end_span(span);

// ParenthesizedExpression is from acorn --preserveParens
let expression = if expressions.len() == 1 {
expressions.remove(0)
} else {
if expressions.is_empty() {
self.error(diagnostics::EmptyParenthesizedExpression(list.span));
self.error(diagnostics::EmptyParenthesizedExpression(paren_span));
}
self.ast.sequence_expression(list.span, expressions)
self.ast.sequence_expression(
Span::new(paren_span.start + 1, paren_span.end - 1),
expressions,
)
};

Ok(self.ast.parenthesized_expression(self.end_span(span), expression))
Ok(self.ast.parenthesized_expression(paren_span, expression))
}

/// Section 13.2.2 This Expression
Expand Down
11 changes: 1 addition & 10 deletions crates/oxc_parser/src/js/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,12 @@ impl<'a> SeparatedList<'a> for CallArguments<'a> {
}

pub struct SequenceExpressionList<'a> {
pub span: Span,
pub elements: Vec<'a, Expression<'a>>,
}

impl<'a> SeparatedList<'a> for SequenceExpressionList<'a> {
fn new(p: &Parser<'a>) -> Self {
Self { elements: p.ast.new_vec(), span: Span::default() }
Self { elements: p.ast.new_vec() }
}

fn open(&self) -> Kind {
Expand All @@ -201,14 +200,6 @@ impl<'a> SeparatedList<'a> for SequenceExpressionList<'a> {
Kind::RParen
}

fn start_sequence(&mut self, p: &mut Parser) {
self.span = p.start_span();
}

fn finish_sequence(&mut self, p: &mut Parser) {
self.span = p.end_span(self.span);
}

// read everything as expression and map to it to either
// ParenthesizedExpression or ArrowFormalParameters later
fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()> {
Expand Down
1 change: 1 addition & 0 deletions crates/oxc_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ mod test {

let fail = [
"1<(V=82<<t-j0<(V=$<LBI<(V=ut<I<(V=$<LBI<(V=uIV=82<<t-j0<(V=$<LBI<(V=ut<I<(V=$<LBI<(V<II>",
"x = (/* a */)",
];

for source in fail {
Expand Down
5 changes: 0 additions & 5 deletions crates/oxc_parser/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,11 @@ pub trait SeparatedList<'a>: Sized {
Kind::Comma
}

fn start_sequence(&mut self, _p: &mut Parser<'a>) {}
fn finish_sequence(&mut self, _p: &mut Parser<'a>) {}

fn parse_element(&mut self, p: &mut Parser<'a>) -> Result<()>;

/// Main entry point, parse the list
fn parse_list(&mut self, p: &mut Parser<'a>) -> Result<()> {
p.expect(self.open())?;
self.start_sequence(p);

let mut first = true;

Expand All @@ -67,7 +63,6 @@ pub trait SeparatedList<'a>: Sized {
self.parse_element(p)?;
}

self.finish_sequence(p);
p.expect(self.close())?;
Ok(())
}
Expand Down
10 changes: 5 additions & 5 deletions tasks/coverage/babel.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3790,7 +3790,7 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
× Empty parenthesized expression
╭─[es2015/uncategorised/250/input.js:1:1]
1 │ () <= 42
·
· ──
╰────
× Expected a semicolon or an implicit semicolon after a statement, but found none
Expand Down Expand Up @@ -4242,7 +4242,7 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
× Empty parenthesized expression
╭─[es2015/uncategorised/38/input.js:1:1]
1 │ console.log(typeof () => {});
·
· ──
╰────
× Expected `,` but found `=>`
Expand Down Expand Up @@ -8348,13 +8348,13 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
× Empty parenthesized expression
╭─[esprima/invalid-syntax/migrated_0095/input.js:1:1]
1 │ () <= 42
·
· ──
╰────
× Empty parenthesized expression
╭─[esprima/invalid-syntax/migrated_0096/input.js:1:1]
1 │ () ? 42
·
· ──
╰────
× Expected `:` but found `EOF`
Expand All @@ -8365,7 +8365,7 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts"
× Empty parenthesized expression
╭─[esprima/invalid-syntax/migrated_0097/input.js:1:1]
1 │ () + 42
·
· ──
╰────
× Expected a semicolon or an implicit semicolon after a statement, but found none
Expand Down
12 changes: 6 additions & 6 deletions tasks/coverage/test262.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9678,7 +9678,7 @@ Negative Passed: 3915/3915 (100.00%)
╭─[language/expressions/class/elements/syntax/early-errors/class-heritage-array-literal-arrow-heritage.js:22:1]
22 │
23 │ var C = class extends () => {} {
·
· ──
24 │
╰────

Expand Down Expand Up @@ -14737,7 +14737,7 @@ Negative Passed: 3915/3915 (100.00%)
╭─[language/expressions/in/private-field-invalid-rhs.js:23:1]
23 │ constructor() {
24 │ #field in () => {};
·
· ──
25 │ }
╰────

Expand Down Expand Up @@ -20404,14 +20404,14 @@ Negative Passed: 3915/3915 (100.00%)
╭─[language/module-code/parse-err-invoke-anon-fun-decl.js:25:1]
25 │
26 │ export default function() {}();
·
· ──
╰────

× Empty parenthesized expression
╭─[language/module-code/parse-err-invoke-anon-gen-decl.js:27:1]
27 │
28 │ export default function* () {}();
·
· ──
╰────

× TS1108: A 'return' statement can only be used within a function body
Expand Down Expand Up @@ -25084,7 +25084,7 @@ Negative Passed: 3915/3915 (100.00%)
╭─[language/statements/class/elements/syntax/early-errors/class-heritage-array-literal-arrow-heritage.js:22:1]
22 │
23 │ class C extends () => {} {
·
· ──
24 │
╰────

Expand Down Expand Up @@ -28812,7 +28812,7 @@ Negative Passed: 3915/3915 (100.00%)
╭─[language/statements/expression/S12.4_A1.js:18:1]
18 │ //CHECK#1
19 │ function(){}();
·
· ──
20 │ //
╰────

Expand Down
8 changes: 4 additions & 4 deletions tasks/coverage/typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8436,7 +8436,7 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
× Empty parenthesized expression
╭─[parser/ecmascript5/ErrorRecovery/Expressions/parserErrorRecovery_Expression1.ts:1:1]
1 │ var v = ()({});
·
· ──
╰────

× Expected `{` but found `EOF`
Expand Down Expand Up @@ -8688,7 +8688,7 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
╭─[parser/ecmascript5/ErrorRecovery/parserEmptyParenthesizedExpression1.ts:1:1]
1 │ function getObj() {
2 │ ().toString();
·
· ──
3 │ }
╰────

Expand Down Expand Up @@ -9218,7 +9218,7 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
╭─[parser/ecmascript5/RegressionTests/parser509669.ts:1:1]
1 │ function foo():any {
2 │ return ():void {};
·
· ──
3 │ }
╰────

Expand Down Expand Up @@ -9268,7 +9268,7 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts"
× Empty parenthesized expression
╭─[parser/ecmascript5/RegressionTests/parser566700.ts:1:1]
1 │ var v = ()({});
·
· ──
╰────

× Expected a semicolon or an implicit semicolon after a statement, but found none
Expand Down

0 comments on commit 9bb2650

Please sign in to comment.