mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
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 <boshenc@gmail.com>
This commit is contained in:
parent
11ca5c2bad
commit
eb2966c512
2 changed files with 19 additions and 0 deletions
|
|
@ -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;
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue