From f3d3c34c30f4760bc29ebf4935dbf191223a8cbd Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Wed, 11 Sep 2019 16:55:58 +0200 Subject: [PATCH] Fix pre-scanner function name parsing. (#3093) The function names of classes were incorrectly parsed. Also made the parsing more strict (more issues were captured by the pre-scanner). Fixes #3088 Fixes #3089 JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- jerry-core/parser/js/js-lexer.c | 16 ++++++ jerry-core/parser/js/js-lexer.h | 5 +- jerry-core/parser/js/js-scanner.c | 92 ++++++++++++++++++++----------- tests/jerry/es2015/class.js | 17 ++++++ 4 files changed, 97 insertions(+), 33 deletions(-) diff --git a/jerry-core/parser/js/js-lexer.c b/jerry-core/parser/js/js-lexer.c index 816d3c1bb..87f2baa8a 100644 --- a/jerry-core/parser/js/js-lexer.c +++ b/jerry-core/parser/js/js-lexer.c @@ -2447,6 +2447,22 @@ lexer_scan_identifier (parser_context_t *context_p, /**< context */ return; } } +#if ENABLED (JERRY_ES2015_CLASS) + if (ident_opts & LEXER_SCAN_CLASS_PROPERTY) + { + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_LITERAL +#if ENABLED (JERRY_ES2015_OBJECT_INITIALIZER) + || context_p->token.type == LEXER_LEFT_SQUARE +#endif /* ENABLED (JERRY_ES2015_OBJECT_INITIALIZER) */ + || context_p->token.type == LEXER_RIGHT_BRACE + || context_p->token.type == LEXER_SEMICOLON) + { + return; + } + } +#endif /* ENABLED (JERRY_ES2015_CLASS) */ parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED); } /* lexer_scan_identifier */ diff --git a/jerry-core/parser/js/js-lexer.h b/jerry-core/parser/js/js-lexer.h index 1dfd0a9f1..6fa5fca8c 100644 --- a/jerry-core/parser/js/js-lexer.h +++ b/jerry-core/parser/js/js-lexer.h @@ -262,7 +262,10 @@ typedef enum { LEXER_SCAN_IDENT_NO_OPTS = (1u << 0), /**< no options */ LEXER_SCAN_IDENT_PROPERTY = (1u << 1), /**< scan valid property names */ - LEXER_SCAN_IDENT_NO_KEYW = (1u << 2), /**< don\t scan keywords (e.g. get/set) */ + LEXER_SCAN_IDENT_NO_KEYW = (1u << 2), /**< don't scan keywords (e.g. get/set) */ +#if ENABLED (JERRY_ES2015_CLASS) + LEXER_SCAN_CLASS_PROPERTY = (1u << 3), /**< scan valid class property names */ +#endif /* ENABLED (JERRY_ES2015_CLASS) */ } lexer_scan_ident_opts_t; /** diff --git a/jerry-core/parser/js/js-scanner.c b/jerry-core/parser/js/js-scanner.c index aaa9e5990..9eb5bfc84 100644 --- a/jerry-core/parser/js/js-scanner.c +++ b/jerry-core/parser/js/js-scanner.c @@ -80,7 +80,7 @@ typedef enum SCAN_STACK_ARROW_EXPRESSION, /**< (possible) arrow function */ #endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */ #if ENABLED (JERRY_ES2015_CLASS) - SCAN_STACK_CLASS, /**< class language element */ + SCAN_STACK_CLASS_FUNCTION, /**< class function expression */ SCAN_STACK_CLASS_EXTENDS, /**< class extends expression */ #endif /* ENABLED (JERRY_ES2015_CLASS) */ #if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) @@ -180,9 +180,16 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */ } case LEXER_KEYW_FUNCTION: { + lexer_next_token (context_p); + if (context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + lexer_next_token (context_p); + } + parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION); scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; - break; + return true; } case LEXER_LEFT_PAREN: { @@ -441,7 +448,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context * case SCAN_STACK_BLOCK_EXPRESSION: case SCAN_STACK_BLOCK_PROPERTY: #if ENABLED (JERRY_ES2015_CLASS) - case SCAN_STACK_CLASS: + case SCAN_STACK_CLASS_FUNCTION: #endif /* ENABLED (JERRY_ES2015_CLASS) */ { scanner_context_p->mode = SCAN_MODE_STATEMENT; @@ -685,13 +692,8 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context * stack_top = (scan_stack_modes_t) context_p->stack_top_uint8; if (stack_top == SCAN_STACK_BLOCK_PROPERTY - || stack_top == SCAN_STACK_CLASS) + || stack_top == SCAN_STACK_CLASS_FUNCTION) { - if (context_p->token.type != LEXER_LEFT_PAREN) - { - scanner_raise_error (context_p); - } - scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; return true; } @@ -759,7 +761,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context * } scanner_context_p->mode = SCAN_MODE_CLASS_METHOD; parser_stack_pop_uint8 (context_p); - return false; + return true; } #endif /* ENABLED (JERRY_ES2015_CLASS) */ #if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) @@ -983,10 +985,11 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */ return true; } #if ENABLED (JERRY_ES2015_CLASS) - case SCAN_STACK_CLASS: + case SCAN_STACK_CLASS_FUNCTION: { scanner_context_p->mode = SCAN_MODE_CLASS_METHOD; - break; + parser_stack_pop_uint8 (context_p); + return true; } #endif /* ENABLED (JERRY_ES2015_CLASS) */ default: @@ -1005,6 +1008,13 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */ } case LEXER_KEYW_FUNCTION: { + lexer_next_token (context_p); + if (context_p->token.type != LEXER_LITERAL + || context_p->token.lit_location.type != LEXER_IDENT_LITERAL) + { + scanner_raise_error (context_p); + } + parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT); scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; return false; @@ -1142,7 +1152,30 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */ if (context_p->token.type == LEXER_KEYW_DEFAULT) { - return false; + lexer_next_token (context_p); + + if (context_p->token.type == LEXER_KEYW_FUNCTION) + { + lexer_next_token (context_p); + if (context_p->token.type == LEXER_LITERAL + && context_p->token.lit_location.type == LEXER_IDENT_LITERAL) + { + lexer_next_token (context_p); + } + + parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION); + scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; + return true; + } +#if ENABLED (JERRY_ES2015_CLASS) + if (context_p->token.type == LEXER_KEYW_CLASS) + { + return true; + } +#endif /* ENABLED (JERRY_ES2015_CLASS) */ + + scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION; + return true; } if (context_p->token.type == LEXER_MULTIPLY) @@ -1331,18 +1364,20 @@ scanner_scan_all (parser_context_t *context_p) /**< context */ } scanner_context.mode = SCAN_MODE_CLASS_METHOD; - break; + /* FALLTHRU */ } case SCAN_MODE_CLASS_METHOD: { - if (type == LEXER_SEMICOLON) + JERRY_ASSERT (stack_top == SCAN_STACK_BLOCK_STATEMENT || stack_top == SCAN_STACK_BLOCK_EXPRESSION); + + lexer_scan_identifier (context_p, LEXER_SCAN_CLASS_PROPERTY); + + if (context_p->token.type == LEXER_SEMICOLON) { break; } - if (type == LEXER_RIGHT_BRACE - && (stack_top == SCAN_STACK_BLOCK_STATEMENT - || stack_top == SCAN_STACK_BLOCK_EXPRESSION)) + if (context_p->token.type == LEXER_RIGHT_BRACE) { scanner_context.mode = (stack_top == SCAN_STACK_BLOCK_EXPRESSION ? SCAN_MODE_PRIMARY_EXPRESSION_END : SCAN_MODE_STATEMENT); @@ -1352,16 +1387,16 @@ scanner_scan_all (parser_context_t *context_p) /**< context */ if (lexer_compare_literal_to_identifier (context_p, "static", 6)) { - lexer_next_token (context_p); + lexer_scan_identifier (context_p, LEXER_SCAN_CLASS_PROPERTY); } if (lexer_compare_literal_to_identifier (context_p, "get", 3) || lexer_compare_literal_to_identifier (context_p, "set", 3)) { - lexer_next_token (context_p); + lexer_scan_identifier (context_p, LEXER_SCAN_CLASS_PROPERTY); } - parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS); + parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_FUNCTION); #if ENABLED (JERRY_ES2015_OBJECT_INITIALIZER) if (context_p->token.type == LEXER_LEFT_SQUARE) @@ -1372,6 +1407,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */ } #endif /* ENABLED (JERRY_ES2015_OBJECT_INITIALIZER) */ + lexer_next_token (context_p); scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS; continue; } @@ -1428,7 +1464,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */ #if ENABLED (JERRY_ES2015_CLASS) JERRY_ASSERT (stack_top == SCAN_STACK_BLOCK_STATEMENT || stack_top == SCAN_STACK_BLOCK_EXPRESSION - || stack_top == SCAN_STACK_CLASS + || stack_top == SCAN_STACK_CLASS_FUNCTION || stack_top == SCAN_STACK_BLOCK_PROPERTY); #else /* !ENABLED (JERRY_ES2015_CLASS) */ JERRY_ASSERT (stack_top == SCAN_STACK_BLOCK_STATEMENT @@ -1436,15 +1472,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */ || stack_top == SCAN_STACK_BLOCK_PROPERTY); #endif /* ENABLED (JERRY_ES2015_CLASS) */ - if (context_p->token.type == LEXER_LITERAL - && (context_p->token.lit_location.type == LEXER_IDENT_LITERAL - || context_p->token.lit_location.type == LEXER_STRING_LITERAL - || context_p->token.lit_location.type == LEXER_NUMBER_LITERAL)) - { - lexer_next_token (context_p); - } - - if (context_p->token.type != LEXER_LEFT_PAREN) + if (type != LEXER_LEFT_PAREN) { scanner_raise_error (context_p); } @@ -1543,7 +1571,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */ } scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS; - continue; + break; } lexer_next_token (context_p); diff --git a/tests/jerry/es2015/class.js b/tests/jerry/es2015/class.js index 75ae43217..f330f0988 100644 --- a/tests/jerry/es2015/class.js +++ b/tests/jerry/es2015/class.js @@ -83,12 +83,21 @@ class C { 3() { return 3; } + + super() { + return 42; + } + return() { + return 43; + } } var c = new C; assert (c.c1() === 5); assert (c.c2() === undefined); assert (c["3"]() === 3); +assert (c.super() === 42); +assert (c.return() === 43); assert (c.constructor === C); class D { @@ -151,6 +160,10 @@ var F = class ClassF { static 2 (a) { return 2 * a; } + + static function(a) { + return 3 * a; + } } var f = new F(5); @@ -163,6 +176,7 @@ assert (F.f3(1, 1) === 2); assert (F.constructor(5) === 5); assert (F.static(5) === 5); assert (F["2"](5) === 10); +assert (F.function(5) === 15); assert (f.constructor === F); var G = class { @@ -202,3 +216,6 @@ G["1"] = 20; assert (G["1"] === 20); G.constructor = 30; assert (G.constructor === 30); + +// Pre-scanner regression test +for (var tmp in {}) ;