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
This commit is contained in:
Zoltan Herczeg
2019-09-11 16:55:58 +02:00
committed by Dániel Bátyai
parent fbde788d1f
commit f3d3c34c30
4 changed files with 97 additions and 33 deletions
+16
View File
@@ -2447,6 +2447,22 @@ lexer_scan_identifier (parser_context_t *context_p, /**< context */
return; 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); parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
} /* lexer_scan_identifier */ } /* lexer_scan_identifier */
+4 -1
View File
@@ -262,7 +262,10 @@ typedef enum
{ {
LEXER_SCAN_IDENT_NO_OPTS = (1u << 0), /**< no options */ LEXER_SCAN_IDENT_NO_OPTS = (1u << 0), /**< no options */
LEXER_SCAN_IDENT_PROPERTY = (1u << 1), /**< scan valid property names */ 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; } lexer_scan_ident_opts_t;
/** /**
+60 -32
View File
@@ -80,7 +80,7 @@ typedef enum
SCAN_STACK_ARROW_EXPRESSION, /**< (possible) arrow function */ SCAN_STACK_ARROW_EXPRESSION, /**< (possible) arrow function */
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */ #endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
#if ENABLED (JERRY_ES2015_CLASS) #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 */ SCAN_STACK_CLASS_EXTENDS, /**< class extends expression */
#endif /* ENABLED (JERRY_ES2015_CLASS) */ #endif /* ENABLED (JERRY_ES2015_CLASS) */
#if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) #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: 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); parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
break; return true;
} }
case LEXER_LEFT_PAREN: 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_EXPRESSION:
case SCAN_STACK_BLOCK_PROPERTY: case SCAN_STACK_BLOCK_PROPERTY:
#if ENABLED (JERRY_ES2015_CLASS) #if ENABLED (JERRY_ES2015_CLASS)
case SCAN_STACK_CLASS: case SCAN_STACK_CLASS_FUNCTION:
#endif /* ENABLED (JERRY_ES2015_CLASS) */ #endif /* ENABLED (JERRY_ES2015_CLASS) */
{ {
scanner_context_p->mode = SCAN_MODE_STATEMENT; 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; stack_top = (scan_stack_modes_t) context_p->stack_top_uint8;
if (stack_top == SCAN_STACK_BLOCK_PROPERTY 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; scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
return true; 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; scanner_context_p->mode = SCAN_MODE_CLASS_METHOD;
parser_stack_pop_uint8 (context_p); parser_stack_pop_uint8 (context_p);
return false; return true;
} }
#endif /* ENABLED (JERRY_ES2015_CLASS) */ #endif /* ENABLED (JERRY_ES2015_CLASS) */
#if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) #if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER)
@@ -983,10 +985,11 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
return true; return true;
} }
#if ENABLED (JERRY_ES2015_CLASS) #if ENABLED (JERRY_ES2015_CLASS)
case SCAN_STACK_CLASS: case SCAN_STACK_CLASS_FUNCTION:
{ {
scanner_context_p->mode = SCAN_MODE_CLASS_METHOD; scanner_context_p->mode = SCAN_MODE_CLASS_METHOD;
break; parser_stack_pop_uint8 (context_p);
return true;
} }
#endif /* ENABLED (JERRY_ES2015_CLASS) */ #endif /* ENABLED (JERRY_ES2015_CLASS) */
default: default:
@@ -1005,6 +1008,13 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
} }
case LEXER_KEYW_FUNCTION: 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); parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS; scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
return false; return false;
@@ -1142,7 +1152,30 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
if (context_p->token.type == LEXER_KEYW_DEFAULT) 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) 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; scanner_context.mode = SCAN_MODE_CLASS_METHOD;
break; /* FALLTHRU */
} }
case SCAN_MODE_CLASS_METHOD: 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; break;
} }
if (type == LEXER_RIGHT_BRACE if (context_p->token.type == LEXER_RIGHT_BRACE)
&& (stack_top == SCAN_STACK_BLOCK_STATEMENT
|| stack_top == SCAN_STACK_BLOCK_EXPRESSION))
{ {
scanner_context.mode = (stack_top == SCAN_STACK_BLOCK_EXPRESSION ? SCAN_MODE_PRIMARY_EXPRESSION_END scanner_context.mode = (stack_top == SCAN_STACK_BLOCK_EXPRESSION ? SCAN_MODE_PRIMARY_EXPRESSION_END
: SCAN_MODE_STATEMENT); : 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)) 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) if (lexer_compare_literal_to_identifier (context_p, "get", 3)
|| lexer_compare_literal_to_identifier (context_p, "set", 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 ENABLED (JERRY_ES2015_OBJECT_INITIALIZER)
if (context_p->token.type == LEXER_LEFT_SQUARE) 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) */ #endif /* ENABLED (JERRY_ES2015_OBJECT_INITIALIZER) */
lexer_next_token (context_p);
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS; scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
continue; continue;
} }
@@ -1428,7 +1464,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
#if ENABLED (JERRY_ES2015_CLASS) #if ENABLED (JERRY_ES2015_CLASS)
JERRY_ASSERT (stack_top == SCAN_STACK_BLOCK_STATEMENT JERRY_ASSERT (stack_top == SCAN_STACK_BLOCK_STATEMENT
|| stack_top == SCAN_STACK_BLOCK_EXPRESSION || stack_top == SCAN_STACK_BLOCK_EXPRESSION
|| stack_top == SCAN_STACK_CLASS || stack_top == SCAN_STACK_CLASS_FUNCTION
|| stack_top == SCAN_STACK_BLOCK_PROPERTY); || stack_top == SCAN_STACK_BLOCK_PROPERTY);
#else /* !ENABLED (JERRY_ES2015_CLASS) */ #else /* !ENABLED (JERRY_ES2015_CLASS) */
JERRY_ASSERT (stack_top == SCAN_STACK_BLOCK_STATEMENT 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); || stack_top == SCAN_STACK_BLOCK_PROPERTY);
#endif /* ENABLED (JERRY_ES2015_CLASS) */ #endif /* ENABLED (JERRY_ES2015_CLASS) */
if (context_p->token.type == LEXER_LITERAL if (type != LEXER_LEFT_PAREN)
&& (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)
{ {
scanner_raise_error (context_p); 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; scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
continue; break;
} }
lexer_next_token (context_p); lexer_next_token (context_p);
+17
View File
@@ -83,12 +83,21 @@ class C {
3() { 3() {
return 3; return 3;
} }
super() {
return 42;
}
return() {
return 43;
}
} }
var c = new C; var c = new C;
assert (c.c1() === 5); assert (c.c1() === 5);
assert (c.c2() === undefined); assert (c.c2() === undefined);
assert (c["3"]() === 3); assert (c["3"]() === 3);
assert (c.super() === 42);
assert (c.return() === 43);
assert (c.constructor === C); assert (c.constructor === C);
class D { class D {
@@ -151,6 +160,10 @@ var F = class ClassF {
static 2 (a) { static 2 (a) {
return 2 * a; return 2 * a;
} }
static function(a) {
return 3 * a;
}
} }
var f = new F(5); var f = new F(5);
@@ -163,6 +176,7 @@ assert (F.f3(1, 1) === 2);
assert (F.constructor(5) === 5); assert (F.constructor(5) === 5);
assert (F.static(5) === 5); assert (F.static(5) === 5);
assert (F["2"](5) === 10); assert (F["2"](5) === 10);
assert (F.function(5) === 15);
assert (f.constructor === F); assert (f.constructor === F);
var G = class { var G = class {
@@ -202,3 +216,6 @@ G["1"] = 20;
assert (G["1"] === 20); assert (G["1"] === 20);
G.constructor = 30; G.constructor = 30;
assert (G.constructor === 30); assert (G.constructor === 30);
// Pre-scanner regression test
for (var tmp in {}) ;