Parse rest function arguments in the pre-scanner. (#3099)

Fixes #3097.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2019-09-12 18:04:00 +02:00
committed by Robert Fancsik
parent 57de923770
commit 376cfea47e
3 changed files with 124 additions and 69 deletions
+103 -69
View File
@@ -42,6 +42,9 @@ typedef enum
SCAN_MODE_PRIMARY_EXPRESSION_END, /**< scanning primary expression end */
SCAN_MODE_STATEMENT, /**< scanning statement */
SCAN_MODE_FUNCTION_ARGUMENTS, /**< scanning function arguments */
#if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER)
SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS, /**< continue scanning function arguments */
#endif /* ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) */
SCAN_MODE_PROPERTY_NAME, /**< scanning property name */
#if ENABLED (JERRY_ES2015_CLASS)
SCAN_MODE_CLASS_DECLARATION, /**< scanning class declaration */
@@ -55,6 +58,11 @@ typedef enum
typedef enum
{
SCAN_STACK_HEAD, /**< head */
SCAN_STACK_BLOCK_STATEMENT, /**< block statement group */
SCAN_STACK_FUNCTION_STATEMENT, /**< function statement */
SCAN_STACK_FUNCTION_EXPRESSION, /**< function expression */
SCAN_STACK_FUNCTION_PROPERTY, /**< function expression in an object literal or class */
SCAN_STACK_SWITCH_BLOCK, /**< block part of "switch" statement */
SCAN_STACK_PAREN_EXPRESSION, /**< parent expression group */
SCAN_STACK_PAREN_STATEMENT, /**< parent statement group */
SCAN_STACK_WHILE_START, /**< start of "while" iterator */
@@ -62,14 +70,10 @@ typedef enum
SCAN_STACK_FOR_CONDITION, /**< condition part of "for" iterator */
SCAN_STACK_FOR_EXPRESSION, /**< expression part of "for" iterator */
SCAN_STACK_SWITCH_EXPRESSION, /**< expression part of "switch" statement */
SCAN_STACK_SWITCH_BLOCK, /**< block part of "switch" statement */
SCAN_STACK_COLON_EXPRESSION, /**< colon expression group */
SCAN_STACK_CASE_STATEMENT, /**< colon statement group */
SCAN_STACK_SQUARE_BRACKETED_EXPRESSION, /**< square bracketed expression group */
SCAN_STACK_OBJECT_LITERAL, /**< object literal group */
SCAN_STACK_BLOCK_STATEMENT, /**< block statement group */
SCAN_STACK_BLOCK_EXPRESSION, /**< block expression group */
SCAN_STACK_BLOCK_PROPERTY, /**< block property group */
#if ENABLED (JERRY_ES2015_OBJECT_INITIALIZER)
SCAN_STACK_COMPUTED_PROPERTY, /**< computed property name */
#endif /* ENABLED (JERRY_ES2015_OBJECT_INITIALIZER) */
@@ -80,7 +84,8 @@ typedef enum
SCAN_STACK_ARROW_EXPRESSION, /**< (possible) arrow function */
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
#if ENABLED (JERRY_ES2015_CLASS)
SCAN_STACK_CLASS_FUNCTION, /**< class function expression */
SCAN_STACK_CLASS_STATEMENT, /**< class statement */
SCAN_STACK_CLASS_EXPRESSION, /**< class expression */
SCAN_STACK_CLASS_EXTENDS, /**< class extends expression */
#endif /* ENABLED (JERRY_ES2015_CLASS) */
#if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER)
@@ -187,7 +192,7 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
lexer_next_token (context_p);
}
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION);
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_EXPRESSION);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
return true;
}
@@ -253,7 +258,7 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
#if ENABLED (JERRY_ES2015_CLASS)
case LEXER_KEYW_CLASS:
{
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION);
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_EXPRESSION);
scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
break;
}
@@ -389,10 +394,25 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
}
case LEXER_COMMA:
{
if (stack_top == SCAN_STACK_OBJECT_LITERAL)
switch (stack_top)
{
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
return true;
case SCAN_STACK_OBJECT_LITERAL:
{
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
return true;
}
#if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER)
case SCAN_STACK_FUNCTION_PARAMETERS:
{
scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS;
parser_stack_pop_uint8 (context_p);
return false;
}
#endif /* ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) */
default:
{
break;
}
}
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
return false;
@@ -443,13 +463,11 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
switch (stack_top)
{
case SCAN_STACK_HEAD:
case SCAN_STACK_SWITCH_BLOCK:
case SCAN_STACK_BLOCK_STATEMENT:
case SCAN_STACK_BLOCK_EXPRESSION:
case SCAN_STACK_BLOCK_PROPERTY:
#if ENABLED (JERRY_ES2015_CLASS)
case SCAN_STACK_CLASS_FUNCTION:
#endif /* ENABLED (JERRY_ES2015_CLASS) */
case SCAN_STACK_FUNCTION_STATEMENT:
case SCAN_STACK_FUNCTION_EXPRESSION:
case SCAN_STACK_FUNCTION_PROPERTY:
case SCAN_STACK_SWITCH_BLOCK:
{
scanner_context_p->mode = SCAN_MODE_STATEMENT;
@@ -691,8 +709,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
parser_stack_pop_uint8 (context_p);
stack_top = (scan_stack_modes_t) context_p->stack_top_uint8;
if (stack_top == SCAN_STACK_BLOCK_PROPERTY
|| stack_top == SCAN_STACK_CLASS_FUNCTION)
if (stack_top == SCAN_STACK_FUNCTION_PROPERTY)
{
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
return true;
@@ -702,7 +719,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
if (context_p->token.type == LEXER_LEFT_PAREN)
{
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_PROPERTY);
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
return true;
}
@@ -772,16 +789,9 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
break;
}
lexer_next_token (context_p);
if (context_p->token.type != LEXER_LEFT_BRACE)
{
scanner_raise_error (context_p);
}
scanner_context_p->mode = SCAN_MODE_STATEMENT;
scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS;
parser_stack_pop_uint8 (context_p);
return false;
return true;
}
#endif /* ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) */
default:
@@ -949,6 +959,48 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
{
switch (stack_top)
{
case SCAN_STACK_BLOCK_STATEMENT:
case SCAN_STACK_FUNCTION_STATEMENT:
{
JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_STATEMENT);
break;
}
case SCAN_STACK_FUNCTION_EXPRESSION:
{
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
break;
}
case SCAN_STACK_FUNCTION_PROPERTY:
{
parser_stack_pop_uint8 (context_p);
#if ENABLED (JERRY_ES2015_CLASS)
if (context_p->stack_top_uint8 == SCAN_STACK_CLASS_STATEMENT
|| context_p->stack_top_uint8 == SCAN_STACK_CLASS_EXPRESSION)
{
scanner_context_p->mode = SCAN_MODE_CLASS_METHOD;
return true;
}
#endif /* ENABLED (JERRY_ES2015_CLASS) */
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL);
lexer_next_token (context_p);
if (context_p->token.type == LEXER_RIGHT_BRACE)
{
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
return true;
}
if (context_p->token.type != LEXER_COMMA)
{
scanner_raise_error (context_p);
}
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
return true;
}
case SCAN_STACK_SWITCH_BLOCK:
{
scanner_switch_statement_t switch_statement;
@@ -961,40 +1013,22 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_STATEMENT);
return false;
}
case SCAN_STACK_BLOCK_STATEMENT:
#if ENABLED (JERRY_ES2015_CLASS)
case SCAN_STACK_CLASS_STATEMENT:
{
JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_STATEMENT);
break;
}
case SCAN_STACK_BLOCK_EXPRESSION:
case SCAN_STACK_CLASS_EXPRESSION:
{
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
break;
}
case SCAN_STACK_BLOCK_PROPERTY:
{
lexer_next_token (context_p);
if (context_p->token.type != LEXER_COMMA
&& context_p->token.type != LEXER_RIGHT_BRACE)
{
scanner_raise_error (context_p);
}
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
parser_stack_pop_uint8 (context_p);
return true;
}
#if ENABLED (JERRY_ES2015_CLASS)
case SCAN_STACK_CLASS_FUNCTION:
{
scanner_context_p->mode = SCAN_MODE_CLASS_METHOD;
parser_stack_pop_uint8 (context_p);
return true;
}
#endif /* ENABLED (JERRY_ES2015_CLASS) */
default:
{
scanner_raise_error (context_p);
break;
}
}
@@ -1015,14 +1049,14 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
scanner_raise_error (context_p);
}
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
return false;
}
#if ENABLED (JERRY_ES2015_CLASS)
case LEXER_KEYW_CLASS:
{
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT);
scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
return false;
}
@@ -1163,7 +1197,7 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
lexer_next_token (context_p);
}
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION);
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT);
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
return true;
}
@@ -1368,7 +1402,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
}
case SCAN_MODE_CLASS_METHOD:
{
JERRY_ASSERT (stack_top == SCAN_STACK_BLOCK_STATEMENT || stack_top == SCAN_STACK_BLOCK_EXPRESSION);
JERRY_ASSERT (stack_top == SCAN_STACK_CLASS_STATEMENT || stack_top == SCAN_STACK_CLASS_EXPRESSION);
lexer_scan_identifier (context_p, LEXER_SCAN_CLASS_PROPERTY);
@@ -1379,7 +1413,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
if (context_p->token.type == LEXER_RIGHT_BRACE)
{
scanner_context.mode = (stack_top == SCAN_STACK_BLOCK_EXPRESSION ? SCAN_MODE_PRIMARY_EXPRESSION_END
scanner_context.mode = (stack_top == SCAN_STACK_CLASS_EXPRESSION ? SCAN_MODE_PRIMARY_EXPRESSION_END
: SCAN_MODE_STATEMENT);
parser_stack_pop_uint8 (context_p);
break;
@@ -1390,7 +1424,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
lexer_scan_identifier (context_p, LEXER_SCAN_CLASS_PROPERTY);
}
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_FUNCTION);
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
if (lexer_compare_literal_to_identifier (context_p, "get", 3)
@@ -1426,7 +1460,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
if (context_p->token.type == LEXER_LEFT_BRACE)
{
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION);
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_EXPRESSION);
scanner_context.mode = SCAN_MODE_STATEMENT;
}
else
@@ -1466,16 +1500,9 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
}
case SCAN_MODE_FUNCTION_ARGUMENTS:
{
#if ENABLED (JERRY_ES2015_CLASS)
JERRY_ASSERT (stack_top == SCAN_STACK_BLOCK_STATEMENT
|| stack_top == SCAN_STACK_BLOCK_EXPRESSION
|| 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
|| stack_top == SCAN_STACK_BLOCK_EXPRESSION
|| stack_top == SCAN_STACK_BLOCK_PROPERTY);
#endif /* ENABLED (JERRY_ES2015_CLASS) */
JERRY_ASSERT (stack_top == SCAN_STACK_FUNCTION_STATEMENT
|| stack_top == SCAN_STACK_FUNCTION_EXPRESSION
|| stack_top == SCAN_STACK_FUNCTION_PROPERTY);
if (type != LEXER_LEFT_PAREN)
{
@@ -1483,6 +1510,13 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
}
lexer_next_token (context_p);
#if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER)
/* FALLTHRU */
}
case SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS:
{
#endif /* ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) */
if (context_p->token.type != LEXER_RIGHT_PAREN)
{
while (true)
@@ -1559,7 +1593,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
{
lexer_scan_identifier (context_p, LEXER_SCAN_IDENT_PROPERTY | LEXER_SCAN_IDENT_NO_KEYW);
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_PROPERTY);
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
#if ENABLED (JERRY_ES2015_OBJECT_INITIALIZER)
if (context_p->token.type == LEXER_LEFT_SQUARE)
@@ -1584,7 +1618,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
#if ENABLED (JERRY_ES2015_OBJECT_INITIALIZER)
if (context_p->token.type == LEXER_LEFT_PAREN)
{
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_PROPERTY);
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
continue;
}
@@ -78,3 +78,6 @@ assert (g2 () === 11);
assert (g2 (1) === 3);
assert (g2 (1, 2) === 3);
assert (g2 (1, 2, 3) === 4);
// Pre-scanner regression test
for (var tmp in {}) ;
@@ -0,0 +1,18 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
switch ($) {
case $: function $( $ = $, ... c ) { }
case $ :
}