Fix next token parsing after a function definition

Ref: c06c399f4f
Fixes: https://github.com/quickjs-ng/quickjs/issues/572
This commit is contained in:
Saúl Ibarra Corretgé 2024-10-04 11:55:14 +02:00
parent 5590756b93
commit 3dcadf1518
2 changed files with 72 additions and 21 deletions

View file

@ -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;

View file

@ -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();