return 0;
}
+/* Walk up through arrow parameter contexts to find an ancestor with
+ the given func_kind flags (JS_FUNC_ASYNC or JS_FUNC_GENERATOR) */
+static BOOL func_has_ancestor_kind(JSFunctionDef *fd, int forced_func_kind, int kind_flags)
+{
+ if (forced_func_kind >= 0)
+ return (forced_func_kind & kind_flags) != 0;
+ for(;;) {
+ if (fd->func_kind & kind_flags)
+ return TRUE;
+ if (fd->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT && kind_flags == JS_FUNC_ASYNC)
+ return TRUE;
+ /* Arrow function parameters inherit binding from parent context */
+ if (fd->func_type == JS_PARSE_FUNC_ARROW && !fd->in_function_body && fd->parent)
+ fd = fd->parent;
+ else
+ break;
+ }
+ return FALSE;
+}
+
/* convert a TOK_IDENT to a keyword when needed */
-static void update_token_ident(JSParseState *s)
+static void update_token_ident(JSParseState *s, int forced_func_kind)
{
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)))) ||
+ (func_has_ancestor_kind(s->cur_func, forced_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))))) {
+ func_has_ancestor_kind(s->cur_func, forced_func_kind, JS_FUNC_ASYNC)))) {
if (s->token.u.ident.has_escape) {
s->token.u.ident.is_reserved = TRUE;
s->token.val = TOK_IDENT;
/* if the current token is an identifier or keyword, reparse it
according to the current function type */
-static void reparse_ident_token(JSParseState *s)
+static void reparse_ident_token(JSParseState *s, int forced_func_kind)
{
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);
+ update_token_ident(s, forced_func_kind);
}
}
s->token.u.ident.has_escape = ident_has_escape;
s->token.u.ident.is_reserved = FALSE;
s->token.val = TOK_IDENT;
- update_token_ident(s);
+ update_token_ident(s, -1);
break;
case '#':
/* private name */
func_kind |= JS_FUNC_GENERATOR;
}
+ if (func_type == JS_PARSE_FUNC_EXPR) {
+ /* in function expressions, the function name must be
+ parsed in the function context */
+ reparse_ident_token(s, func_kind);
+ }
+
if (s->token.val == TOK_IDENT) {
- if (s->token.u.ident.is_reserved ||
- (s->token.u.ident.atom == JS_ATOM_yield &&
- func_type == JS_PARSE_FUNC_EXPR &&
- (func_kind & JS_FUNC_GENERATOR)) ||
- (s->token.u.ident.atom == JS_ATOM_await &&
- ((func_type == JS_PARSE_FUNC_EXPR &&
- (func_kind & JS_FUNC_ASYNC)) ||
- func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT))) {
+ if (s->token.u.ident.is_reserved)
return js_parse_error_reserved_identifier(s);
- }
- }
- if (s->token.val == TOK_IDENT ||
- (((s->token.val == TOK_YIELD && !(fd->js_mode & JS_MODE_STRICT)) ||
- (s->token.val == TOK_AWAIT && !s->is_module)) &&
- func_type == JS_PARSE_FUNC_EXPR)) {
func_name = JS_DupAtom(ctx, s->token.u.ident.atom);
if (next_token(s)) {
JS_FreeAtom(ctx, func_name);
fd->has_simple_parameter_list = TRUE;
fd->has_parameter_expressions = FALSE;
has_opt_arg = FALSE;
+
+ if (func_type == JS_PARSE_FUNC_ARROW) {
+ /* reparse the potential arrow first parameter in the function context */
+ reparse_ident_token(s, -1);
+ }
+
if (func_type == JS_PARSE_FUNC_ARROW && s->token.val == TOK_IDENT) {
JSAtom name;
if (s->token.u.ident.is_reserved) {
goto fail;
}
name = s->token.u.ident.atom;
- if (name == JS_ATOM_yield && fd->func_kind == JS_FUNC_GENERATOR) {
- js_parse_error_reserved_identifier(s);
- goto fail;
- }
if (fd->has_parameter_expressions) {
if (js_parse_check_duplicate_parameter(s, name))
goto fail;
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);
+ reparse_ident_token(s, -1);
/* create the function object */
{
test262/test/staging/sm/Function/function-name-for.js:13: Test262Error: Expected SameValue(«""», «"forInHead"») to be true
test262/test/staging/sm/Function/implicit-this-in-parameter-expression.js:12: Test262Error: Expected SameValue(«[object Object]», «undefined») to be true
test262/test/staging/sm/Function/invalid-parameter-list.js:13: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/staging/sm/async-functions/async-contains-unicode-escape.js:11: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/staging/sm/async-functions/await-in-arrow-parameters.js:10: Test262Error: AsyncFunction:(a = (b = await/r/g) => {}) => {} Expected a SyntaxError to be thrown but no exception was thrown at all
test262/test/staging/sm/class/boundFunctionSubclassing.js:9: Test262Error: Expected SameValue(«false», «true») to be true
test262/test/staging/sm/class/strictExecution.js:13: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
test262/test/staging/sm/class/superPropOrdering.js:17: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
-test262/test/staging/sm/generators/syntax.js:50: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-arguments.js:13: Test262Error: Expected SameValue(«"object"», «"function"») to be true
test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-eval.js:11: Test262Error: Expected SameValue(«"outer-gouter-geval-gtruefalseq"», «"outer-geval-gwith-gtruefalseq"») to be true
test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-if.js:19: TypeError: not a function