From 0b188ccdff487bc5c344b0e70b102ce1d9ba308d Mon Sep 17 00:00:00 2001 From: Ian Tan Date: Fri, 29 Dec 2023 16:48:24 +0800 Subject: [PATCH] fix(es/parser): Disallowing await as an identifier in class static block (#8450) --- crates/swc_ecma_parser/src/lib.rs | 3 ++ .../src/parser/class_and_fn.rs | 2 + crates/swc_ecma_parser/src/parser/ident.rs | 4 ++ crates/swc_ecma_parser/src/parser/pat.rs | 2 +- crates/swc_ecma_parser/src/parser/stmt.rs | 40 +++++++++++++++++++ crates/swc_ecma_parser/src/parser/util.rs | 4 +- 6 files changed, 52 insertions(+), 3 deletions(-) diff --git a/crates/swc_ecma_parser/src/lib.rs b/crates/swc_ecma_parser/src/lib.rs index 9b5844a09c99..6c8e0bb51ebd 100644 --- a/crates/swc_ecma_parser/src/lib.rs +++ b/crates/swc_ecma_parser/src/lib.rs @@ -394,6 +394,9 @@ pub struct Context { /// keyword. in_generator: bool, + /// If true, await is treated as a keyword. + in_static_block: bool, + is_continue_allowed: bool, is_break_allowed: bool, diff --git a/crates/swc_ecma_parser/src/parser/class_and_fn.rs b/crates/swc_ecma_parser/src/parser/class_and_fn.rs index 8b3a7324b526..c08715d694c0 100644 --- a/crates/swc_ecma_parser/src/parser/class_and_fn.rs +++ b/crates/swc_ecma_parser/src/parser/class_and_fn.rs @@ -579,6 +579,7 @@ impl Parser { fn parse_static_block(&mut self, start: BytePos) -> PResult { let body = self .with_ctx(Context { + in_static_block: true, in_class_field: true, allow_using_decl: true, ..self.ctx() @@ -1386,6 +1387,7 @@ impl Parser { true }, in_function: true, + in_static_block: false, is_break_allowed: false, is_continue_allowed: false, ..self.ctx() diff --git a/crates/swc_ecma_parser/src/parser/ident.rs b/crates/swc_ecma_parser/src/parser/ident.rs index 2ee2a630eef3..7533046e613e 100644 --- a/crates/swc_ecma_parser/src/parser/ident.rs +++ b/crates/swc_ecma_parser/src/parser/ident.rs @@ -147,6 +147,10 @@ impl Parser { match w { Word::Keyword(Keyword::Await) if p.ctx().in_declare => Ok(atom!("await")), + Word::Keyword(Keyword::Await) if p.ctx().in_static_block => { + syntax_error!(p, p.input.prev_span(), SyntaxError::ExpectedIdent) + } + // It is a Syntax Error if the goal symbol of the syntactic grammar is Module // and the StringValue of IdentifierName is "await". Word::Keyword(Keyword::Await) if p.ctx().module | p.ctx().in_async => { diff --git a/crates/swc_ecma_parser/src/parser/pat.rs b/crates/swc_ecma_parser/src/parser/pat.rs index c765055a52d2..438469d8a0c8 100644 --- a/crates/swc_ecma_parser/src/parser/pat.rs +++ b/crates/swc_ecma_parser/src/parser/pat.rs @@ -35,7 +35,7 @@ impl Parser { if ident.is_reserved_in_strict_bind() { self.emit_strict_mode_err(ident.span, SyntaxError::EvalAndArgumentsInStrict); } - if self.ctx().in_async && ident.sym == "await" { + if (self.ctx().in_async || self.ctx().in_static_block) && ident.sym == "await" { self.emit_err(ident.span, SyntaxError::ExpectedIdent); } if self.ctx().in_generator && ident.sym == "yield" { diff --git a/crates/swc_ecma_parser/src/parser/stmt.rs b/crates/swc_ecma_parser/src/parser/stmt.rs index ddfb6bf78564..8adec1910767 100644 --- a/crates/swc_ecma_parser/src/parser/stmt.rs +++ b/crates/swc_ecma_parser/src/parser/stmt.rs @@ -2396,6 +2396,46 @@ export default function waitUntil(callback, options = {}) { }); } + #[test] + #[should_panic(expected = "Expected ident")] + fn class_static_blocks_with_await() { + let src = "class Foo{ + static { + var await = 'bar'; + } + }"; + test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr()); + } + + #[test] + #[should_panic(expected = "Expected ident")] + fn class_static_blocks_with_await_in_nested_class() { + let src = "class Foo{ + static { + function foo() { + class Foo { + static { + var await = 'bar'; + } + } + } + } + }"; + test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr()); + } + + #[test] + fn class_static_blocks_with_await_in_fn() { + let src = "class Foo{ + static { + function foo() { + var await = 'bar'; + } + } + }"; + test_parser(src, Syntax::Es(Default::default()), |p| p.parse_expr()); + } + #[test] #[should_panic(expected = "Modifiers cannot appear here")] fn class_static_blocks_in_ts_with_invalid_modifier_01() { diff --git a/crates/swc_ecma_parser/src/parser/util.rs b/crates/swc_ecma_parser/src/parser/util.rs index fb94bb48fd76..b4a21da35f65 100644 --- a/crates/swc_ecma_parser/src/parser/util.rs +++ b/crates/swc_ecma_parser/src/parser/util.rs @@ -5,7 +5,7 @@ impl Context { pub(crate) fn is_reserved(self, word: &Word) -> bool { match *word { Word::Keyword(Keyword::Let) => self.strict, - Word::Keyword(Keyword::Await) => self.in_async || self.strict, + Word::Keyword(Keyword::Await) => self.in_async || self.in_static_block || self.strict, Word::Keyword(Keyword::Yield) => self.in_generator || self.strict, Word::Null @@ -70,7 +70,7 @@ impl Context { // let await = 1; // } // ``` - "await" => self.in_async || self.module, + "await" => self.in_async || self.in_static_block || self.module, "yield" => self.in_generator || self.strict, "null" | "true" | "false" | "break" | "case" | "catch" | "continue" | "debugger"