From eb2966c512632189231900acfe4b0fc59a029382 Mon Sep 17 00:00:00 2001 From: overlookmotel Date: Thu, 4 Jan 2024 13:39:15 +0000 Subject: [PATCH] fix(parser): fix incorrectly identified directives (#1885) Parser incorrectly identifies string literals as directives if they follow after `import`s, `export`s, or decorators. In all of these cases, `'use strict'` produces a directive in the AST, where it should be parsed as an `ExpressionStatement` containing a `StringLiteral`: ```js import x from 'foo'; 'use strict'; ``` ```js export {x}; 'use strict'; ``` ```js @foo 'use strict'; ``` [Playground](https://oxc-project.github.io/oxc/playground/?code=3YCAAIC0gICAgICAgIC0G8rnONK89ITJ3zrK%2FUP7OmSZPgHQzStr3yMtwFTU%2BD1WPt09JgqZJLoYooydbGsM5vGcf34BnIA%3D) This PR should fix that. I'm not sure about the decorator case, though. I assume it's not a directive. But is prefixing a string literal with a decorator even legal syntax anyway? And a side nit: If I'm reading it right, I don't think the `continue` statement in the decorator arm of the match does anything. Do I have that right? Last question: Where does one go about putting a test? I guess these silly cases aren't covered by Babel etc's tests. --------- Co-authored-by: Boshen --- crates/oxc_parser/src/js/statement.rs | 3 +++ crates/oxc_parser/src/lib.rs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/crates/oxc_parser/src/js/statement.rs b/crates/oxc_parser/src/js/statement.rs index 54505ae97..54297b88b 100644 --- a/crates/oxc_parser/src/js/statement.rs +++ b/crates/oxc_parser/src/js/statement.rs @@ -44,13 +44,16 @@ impl<'a> Parser<'a> { Kind::Import if !matches!(self.peek_kind(), Kind::Dot | Kind::LParen) => { let stmt = self.parse_import_declaration()?; statements.push(stmt); + expecting_directives = false; } Kind::Export => { let stmt = self.parse_export_declaration()?; statements.push(stmt); + expecting_directives = false; } Kind::At => { self.eat_decorators()?; + expecting_directives = false; continue; } _ => { diff --git a/crates/oxc_parser/src/lib.rs b/crates/oxc_parser/src/lib.rs index 73f902c03..45dd4d3b5 100644 --- a/crates/oxc_parser/src/lib.rs +++ b/crates/oxc_parser/src/lib.rs @@ -300,6 +300,22 @@ mod test { assert_eq!(ret.errors.first().unwrap().to_string(), "Flow is not supported"); } + #[test] + fn directives() { + let allocator = Allocator::default(); + let source_type = SourceType::default(); + let sources = [ + ("import x from 'foo'; 'use strict';", 2), + ("export {x} from 'foo'; 'use strict';", 2), + ("@decorator 'use strict';", 1), + ]; + for (source, body_length) in sources { + let ret = Parser::new(&allocator, source, source_type).parse(); + assert!(ret.program.directives.is_empty(), "{source}"); + assert_eq!(ret.program.body.len(), body_length, "{source}"); + } + } + // Source with length u32::MAX + 1 fails to parse #[test] fn overlong_source() {