mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 13:51:19 +03:00
Top level await (#627)
Implements a top level await for es2017+, and allow it for typescript and ecmascript (ecmascript requires topLevelAwait: true). Closes #626.
This commit is contained in:
parent
42373f975b
commit
94eac1de89
@ -46,6 +46,8 @@ pub struct Error {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum SyntaxError {
|
||||
TopLevelAwait,
|
||||
|
||||
LegacyDecimal,
|
||||
LegacyOctal,
|
||||
InvalidIdentChar,
|
||||
@ -226,6 +228,9 @@ impl<'a> From<ErrorToDiag<'a>> for DiagnosticBuilder<'a> {
|
||||
#[cold]
|
||||
fn from(e: ErrorToDiag<'a>) -> Self {
|
||||
let msg: Cow<'static, _> = match e.error {
|
||||
TopLevelAwait => "top level await requires target to es2017 or higher and \
|
||||
topLevelAwait:true for ecmascript"
|
||||
.into(),
|
||||
LegacyDecimal => "Legacy decimal escape is not permitted in strict mode".into(),
|
||||
LegacyOctal => "Legacy octal escape is not permitted in strict mode".into(),
|
||||
InvalidIdentChar => "Invalid character in identifier".into(),
|
||||
|
@ -281,6 +281,18 @@ impl Syntax {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn top_level_await(self) -> bool {
|
||||
match self {
|
||||
Syntax::Es(EsConfig {
|
||||
top_level_await: true,
|
||||
..
|
||||
})
|
||||
| Syntax::Typescript(..) => true,
|
||||
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
|
||||
@ -378,6 +390,10 @@ pub struct EsConfig {
|
||||
/// Stage 3.
|
||||
#[serde(default)]
|
||||
pub import_meta: bool,
|
||||
|
||||
/// Stage 3.
|
||||
#[serde(default)]
|
||||
pub top_level_await: bool,
|
||||
}
|
||||
|
||||
/// Syntactic context.
|
||||
|
@ -338,11 +338,10 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn parse_await_expr(&mut self) -> PResult<'a, Box<Expr>> {
|
||||
pub(crate) fn parse_await_expr(&mut self) -> PResult<'a, Box<Expr>> {
|
||||
let start = cur_pos!();
|
||||
|
||||
assert_and_bump!("await");
|
||||
debug_assert!(self.ctx().in_async);
|
||||
|
||||
if is!('*') {
|
||||
syntax_error!(SyntaxError::AwaitStar);
|
||||
|
@ -175,7 +175,7 @@ where
|
||||
F: for<'a> FnOnce(&'a mut Parser<'a, Lexer<'a, crate::SourceFileInput<'_>>>) -> Result<Ret, ()>,
|
||||
{
|
||||
crate::with_test_sess(s, |sess, input| {
|
||||
let lexer = Lexer::new(sess, syntax, Default::default(), input, None);
|
||||
let lexer = Lexer::new(sess, syntax, JscTarget::Es2019, input, None);
|
||||
f(&mut Parser::new_from(sess, lexer))
|
||||
})
|
||||
.unwrap_or_else(|output| panic!("test_parser(): failed to parse \n{}\n{}", s, output))
|
||||
|
@ -92,6 +92,20 @@ impl<'a, I: Tokens> Parser<'a, I> {
|
||||
top_level: bool,
|
||||
decorators: Vec<Decorator>,
|
||||
) -> PResult<'a, Stmt> {
|
||||
let start = cur_pos!();
|
||||
if top_level && is!("await") {
|
||||
let valid = self.target() >= JscTarget::Es2017 && self.syntax().top_level_await();
|
||||
|
||||
if !valid {
|
||||
self.emit_err(self.input.cur_span(), SyntaxError::TopLevelAwait);
|
||||
}
|
||||
|
||||
let expr = self.parse_await_expr()?;
|
||||
|
||||
let span = span!(start);
|
||||
return Ok(Stmt::Expr(ExprStmt { span, expr }));
|
||||
}
|
||||
|
||||
if self.input.syntax().typescript() && is!("const") && peeked_is!("enum") {
|
||||
assert_and_bump!("const");
|
||||
assert_and_bump!("enum");
|
||||
@ -1634,4 +1648,20 @@ export default function waitUntil(callback, options = {}) {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn top_level_await() {
|
||||
test_parser(
|
||||
"await foo",
|
||||
Syntax::Es(EsConfig {
|
||||
top_level_await: true,
|
||||
..Default::default()
|
||||
}),
|
||||
|p| {
|
||||
p.parse_module().map_err(|mut e| {
|
||||
e.emit();
|
||||
})
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,10 @@
|
||||
error: Unexpected token Some(Word(await))
|
||||
error: top level await requires target to es2017 or higher and topLevelAwait:true for ecmascript
|
||||
--> $DIR/tests/test262-parser/fail/1aefe47e20eb91fa.module.js:1:1
|
||||
|
|
||||
1 | await
|
||||
| ^^^^^
|
||||
|
||||
error: Unexpected token None
|
||||
--> $DIR/tests/test262-parser/fail/1aefe47e20eb91fa.module.js:1:1
|
||||
|
|
||||
1 | await
|
||||
|
@ -0,0 +1 @@
|
||||
await foo
|
@ -0,0 +1,6 @@
|
||||
error: top level await requires target to es2017 or higher and topLevelAwait:true for ecmascript
|
||||
--> $DIR/tests/typescript-errors/custom/top-level-await-jsc-target/input.ts:1:1
|
||||
|
|
||||
1 | await foo
|
||||
| ^^^^^
|
||||
|
@ -21,7 +21,7 @@
|
||||
},
|
||||
"declare": false,
|
||||
"span": {
|
||||
"start": 0,
|
||||
"start": 5,
|
||||
"end": 196,
|
||||
"ctxt": 0
|
||||
},
|
||||
|
@ -21,7 +21,7 @@
|
||||
},
|
||||
"declare": false,
|
||||
"span": {
|
||||
"start": 0,
|
||||
"start": 21,
|
||||
"end": 34,
|
||||
"ctxt": 0
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user