mirror of
https://github.com/DoneJS-Runtime/quickjs-done-nextgen.git
synced 2025-01-09 17:43:15 +00:00
Fix next token parsing after a function definition
Ref: c06c399f4f
Fixes: https://github.com/quickjs-ng/quickjs/issues/572
This commit is contained in:
parent
5590756b93
commit
3dcadf1518
2 changed files with 72 additions and 21 deletions
70
quickjs.c
70
quickjs.c
|
@ -19224,6 +19224,48 @@ static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* convert a TOK_IDENT to a keyword when needed */
|
||||
static void update_token_ident(JSParseState *s)
|
||||
{
|
||||
if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||
|
||||
(s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&
|
||||
(s->cur_func->js_mode & JS_MODE_STRICT)) ||
|
||||
(s->token.u.ident.atom == JS_ATOM_yield &&
|
||||
((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||
|
||||
(s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
|
||||
!s->cur_func->in_function_body && s->cur_func->parent &&
|
||||
(s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||
|
||||
(s->token.u.ident.atom == JS_ATOM_await &&
|
||||
(s->is_module ||
|
||||
(s->cur_func->func_kind & JS_FUNC_ASYNC) ||
|
||||
s->cur_func->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT ||
|
||||
(s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
|
||||
!s->cur_func->in_function_body && s->cur_func->parent &&
|
||||
((s->cur_func->parent->func_kind & JS_FUNC_ASYNC) ||
|
||||
s->cur_func->parent->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT))))) {
|
||||
if (s->token.u.ident.has_escape) {
|
||||
s->token.u.ident.is_reserved = TRUE;
|
||||
s->token.val = TOK_IDENT;
|
||||
} else {
|
||||
/* The keywords atoms are pre allocated */
|
||||
s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if the current token is an identifier or keyword, reparse it
|
||||
according to the current function type */
|
||||
static void reparse_ident_token(JSParseState *s)
|
||||
{
|
||||
if (s->token.val == TOK_IDENT ||
|
||||
(s->token.val >= TOK_FIRST_KEYWORD &&
|
||||
s->token.val <= TOK_LAST_KEYWORD)) {
|
||||
s->token.val = TOK_IDENT;
|
||||
s->token.u.ident.is_reserved = FALSE;
|
||||
update_token_ident(s);
|
||||
}
|
||||
}
|
||||
|
||||
/* 'c' is the first character. Return JS_ATOM_NULL in case of error */
|
||||
static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
|
||||
BOOL *pident_has_escape, int c, BOOL is_private)
|
||||
|
@ -19442,29 +19484,9 @@ static __exception int next_token(JSParseState *s)
|
|||
(atom == JS_ATOM_arguments || atom == JS_ATOM_await)) {
|
||||
s->token.u.ident.is_reserved = TRUE;
|
||||
s->token.val = TOK_IDENT;
|
||||
} else if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||
|
||||
(s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&
|
||||
(s->cur_func->js_mode & JS_MODE_STRICT)) ||
|
||||
(s->token.u.ident.atom == JS_ATOM_yield &&
|
||||
((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||
|
||||
(s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
|
||||
!s->cur_func->in_function_body && s->cur_func->parent &&
|
||||
(s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||
|
||||
(s->token.u.ident.atom == JS_ATOM_await &&
|
||||
(s->is_module ||
|
||||
(((s->cur_func->func_kind & JS_FUNC_ASYNC) ||
|
||||
(s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
|
||||
!s->cur_func->in_function_body && s->cur_func->parent &&
|
||||
(s->cur_func->parent->func_kind & JS_FUNC_ASYNC))))))) {
|
||||
if (ident_has_escape) {
|
||||
s->token.u.ident.is_reserved = TRUE;
|
||||
s->token.val = TOK_IDENT;
|
||||
} else {
|
||||
/* The keywords atoms are pre allocated */
|
||||
s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD;
|
||||
}
|
||||
} else {
|
||||
s->token.val = TOK_IDENT;
|
||||
update_token_ident(s);
|
||||
}
|
||||
break;
|
||||
case '#':
|
||||
|
@ -32903,6 +32925,12 @@ static __exception int js_parse_function_decl2(JSParseState *s,
|
|||
done:
|
||||
s->cur_func = fd->parent;
|
||||
|
||||
/* Reparse identifiers after the function is terminated so that
|
||||
the token is parsed in the englobing function. It could be done
|
||||
by just using next_token() here for normal functions, but it is
|
||||
necessary for arrow functions with an expression body. */
|
||||
reparse_ident_token(s);
|
||||
|
||||
/* create the function object */
|
||||
{
|
||||
int idx;
|
||||
|
|
|
@ -691,6 +691,28 @@ function test_optional_chaining()
|
|||
assert((a?.["b"])().c, 42);
|
||||
}
|
||||
|
||||
function test_parse_semicolon()
|
||||
{
|
||||
/* 'yield' or 'await' may not be considered as a token if the
|
||||
previous ';' is missing */
|
||||
function *f()
|
||||
{
|
||||
function func() {
|
||||
}
|
||||
yield 1;
|
||||
var h = x => x + 1
|
||||
yield 2;
|
||||
}
|
||||
async function g()
|
||||
{
|
||||
function func() {
|
||||
}
|
||||
await 1;
|
||||
var h = x => x + 1
|
||||
await 2;
|
||||
}
|
||||
}
|
||||
|
||||
test_op1();
|
||||
test_cvt();
|
||||
test_eq();
|
||||
|
@ -714,3 +736,4 @@ test_reserved_names();
|
|||
test_number_literals();
|
||||
test_syntax();
|
||||
test_optional_chaining();
|
||||
test_parse_semicolon();
|
||||
|
|
Loading…
Reference in a new issue