fixed next token parsing after a function definition (github issue #77)
This commit is contained in:
parent
5935a26eae
commit
c06c399f4f
2 changed files with 74 additions and 27 deletions
76
quickjs.c
76
quickjs.c
|
@ -20485,6 +20485,48 @@ static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
|
||||||
return 0;
|
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 */
|
/* 'c' is the first character. Return JS_ATOM_NULL in case of error */
|
||||||
static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
|
static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
|
||||||
BOOL *pident_has_escape, int c, BOOL is_private)
|
BOOL *pident_has_escape, int c, BOOL is_private)
|
||||||
|
@ -20691,32 +20733,8 @@ static __exception int next_token(JSParseState *s)
|
||||||
s->token.u.ident.atom = atom;
|
s->token.u.ident.atom = atom;
|
||||||
s->token.u.ident.has_escape = ident_has_escape;
|
s->token.u.ident.has_escape = ident_has_escape;
|
||||||
s->token.u.ident.is_reserved = FALSE;
|
s->token.u.ident.is_reserved = FALSE;
|
||||||
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 (ident_has_escape) {
|
|
||||||
s->token.u.ident.is_reserved = TRUE;
|
|
||||||
s->token.val = TOK_IDENT;
|
s->token.val = TOK_IDENT;
|
||||||
} else {
|
update_token_ident(s);
|
||||||
/* The keywords atoms are pre allocated */
|
|
||||||
s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s->token.val = TOK_IDENT;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case '#':
|
case '#':
|
||||||
/* private name */
|
/* private name */
|
||||||
|
@ -33893,9 +33911,15 @@ static __exception int js_parse_function_decl2(JSParseState *s,
|
||||||
if (js_is_live_code(s)) {
|
if (js_is_live_code(s)) {
|
||||||
emit_return(s, FALSE);
|
emit_return(s, FALSE);
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
s->cur_func = fd->parent;
|
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 */
|
/* create the function object */
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
|
|
|
@ -536,6 +536,28 @@ function test_function_expr_name()
|
||||||
assert_throws(TypeError, f);
|
assert_throws(TypeError, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_op1();
|
||||||
test_cvt();
|
test_cvt();
|
||||||
test_eq();
|
test_eq();
|
||||||
|
@ -555,3 +577,4 @@ test_spread();
|
||||||
test_function_length();
|
test_function_length();
|
||||||
test_argument_scope();
|
test_argument_scope();
|
||||||
test_function_expr_name();
|
test_function_expr_name();
|
||||||
|
test_parse_semicolon();
|
||||||
|
|
Loading…
Reference in a new issue