Skip to content

Commit 376cfea

Browse files
zherczegrerobika
authored andcommitted
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
1 parent 57de923 commit 376cfea

File tree

3 files changed

+124
-69
lines changed

3 files changed

+124
-69
lines changed

jerry-core/parser/js/js-scanner.c

Lines changed: 103 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ typedef enum
4242
SCAN_MODE_PRIMARY_EXPRESSION_END, /**< scanning primary expression end */
4343
SCAN_MODE_STATEMENT, /**< scanning statement */
4444
SCAN_MODE_FUNCTION_ARGUMENTS, /**< scanning function arguments */
45+
#if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER)
46+
SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS, /**< continue scanning function arguments */
47+
#endif /* ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) */
4548
SCAN_MODE_PROPERTY_NAME, /**< scanning property name */
4649
#if ENABLED (JERRY_ES2015_CLASS)
4750
SCAN_MODE_CLASS_DECLARATION, /**< scanning class declaration */
@@ -55,21 +58,22 @@ typedef enum
5558
typedef enum
5659
{
5760
SCAN_STACK_HEAD, /**< head */
61+
SCAN_STACK_BLOCK_STATEMENT, /**< block statement group */
62+
SCAN_STACK_FUNCTION_STATEMENT, /**< function statement */
63+
SCAN_STACK_FUNCTION_EXPRESSION, /**< function expression */
64+
SCAN_STACK_FUNCTION_PROPERTY, /**< function expression in an object literal or class */
65+
SCAN_STACK_SWITCH_BLOCK, /**< block part of "switch" statement */
5866
SCAN_STACK_PAREN_EXPRESSION, /**< parent expression group */
5967
SCAN_STACK_PAREN_STATEMENT, /**< parent statement group */
6068
SCAN_STACK_WHILE_START, /**< start of "while" iterator */
6169
SCAN_STACK_FOR_START, /**< start of "for" iterator */
6270
SCAN_STACK_FOR_CONDITION, /**< condition part of "for" iterator */
6371
SCAN_STACK_FOR_EXPRESSION, /**< expression part of "for" iterator */
6472
SCAN_STACK_SWITCH_EXPRESSION, /**< expression part of "switch" statement */
65-
SCAN_STACK_SWITCH_BLOCK, /**< block part of "switch" statement */
6673
SCAN_STACK_COLON_EXPRESSION, /**< colon expression group */
6774
SCAN_STACK_CASE_STATEMENT, /**< colon statement group */
6875
SCAN_STACK_SQUARE_BRACKETED_EXPRESSION, /**< square bracketed expression group */
6976
SCAN_STACK_OBJECT_LITERAL, /**< object literal group */
70-
SCAN_STACK_BLOCK_STATEMENT, /**< block statement group */
71-
SCAN_STACK_BLOCK_EXPRESSION, /**< block expression group */
72-
SCAN_STACK_BLOCK_PROPERTY, /**< block property group */
7377
#if ENABLED (JERRY_ES2015_OBJECT_INITIALIZER)
7478
SCAN_STACK_COMPUTED_PROPERTY, /**< computed property name */
7579
#endif /* ENABLED (JERRY_ES2015_OBJECT_INITIALIZER) */
@@ -80,7 +84,8 @@ typedef enum
8084
SCAN_STACK_ARROW_EXPRESSION, /**< (possible) arrow function */
8185
#endif /* ENABLED (JERRY_ES2015_ARROW_FUNCTION) */
8286
#if ENABLED (JERRY_ES2015_CLASS)
83-
SCAN_STACK_CLASS_FUNCTION, /**< class function expression */
87+
SCAN_STACK_CLASS_STATEMENT, /**< class statement */
88+
SCAN_STACK_CLASS_EXPRESSION, /**< class expression */
8489
SCAN_STACK_CLASS_EXTENDS, /**< class extends expression */
8590
#endif /* ENABLED (JERRY_ES2015_CLASS) */
8691
#if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER)
@@ -187,7 +192,7 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
187192
lexer_next_token (context_p);
188193
}
189194

190-
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION);
195+
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_EXPRESSION);
191196
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
192197
return true;
193198
}
@@ -253,7 +258,7 @@ scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
253258
#if ENABLED (JERRY_ES2015_CLASS)
254259
case LEXER_KEYW_CLASS:
255260
{
256-
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION);
261+
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_EXPRESSION);
257262
scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
258263
break;
259264
}
@@ -389,10 +394,25 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
389394
}
390395
case LEXER_COMMA:
391396
{
392-
if (stack_top == SCAN_STACK_OBJECT_LITERAL)
397+
switch (stack_top)
393398
{
394-
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
395-
return true;
399+
case SCAN_STACK_OBJECT_LITERAL:
400+
{
401+
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
402+
return true;
403+
}
404+
#if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER)
405+
case SCAN_STACK_FUNCTION_PARAMETERS:
406+
{
407+
scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS;
408+
parser_stack_pop_uint8 (context_p);
409+
return false;
410+
}
411+
#endif /* ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) */
412+
default:
413+
{
414+
break;
415+
}
396416
}
397417
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
398418
return false;
@@ -443,13 +463,11 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
443463
switch (stack_top)
444464
{
445465
case SCAN_STACK_HEAD:
446-
case SCAN_STACK_SWITCH_BLOCK:
447466
case SCAN_STACK_BLOCK_STATEMENT:
448-
case SCAN_STACK_BLOCK_EXPRESSION:
449-
case SCAN_STACK_BLOCK_PROPERTY:
450-
#if ENABLED (JERRY_ES2015_CLASS)
451-
case SCAN_STACK_CLASS_FUNCTION:
452-
#endif /* ENABLED (JERRY_ES2015_CLASS) */
467+
case SCAN_STACK_FUNCTION_STATEMENT:
468+
case SCAN_STACK_FUNCTION_EXPRESSION:
469+
case SCAN_STACK_FUNCTION_PROPERTY:
470+
case SCAN_STACK_SWITCH_BLOCK:
453471
{
454472
scanner_context_p->mode = SCAN_MODE_STATEMENT;
455473

@@ -691,8 +709,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
691709
parser_stack_pop_uint8 (context_p);
692710
stack_top = (scan_stack_modes_t) context_p->stack_top_uint8;
693711

694-
if (stack_top == SCAN_STACK_BLOCK_PROPERTY
695-
|| stack_top == SCAN_STACK_CLASS_FUNCTION)
712+
if (stack_top == SCAN_STACK_FUNCTION_PROPERTY)
696713
{
697714
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
698715
return true;
@@ -702,7 +719,7 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
702719

703720
if (context_p->token.type == LEXER_LEFT_PAREN)
704721
{
705-
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_PROPERTY);
722+
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
706723
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
707724
return true;
708725
}
@@ -772,16 +789,9 @@ scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context *
772789
break;
773790
}
774791

775-
lexer_next_token (context_p);
776-
777-
if (context_p->token.type != LEXER_LEFT_BRACE)
778-
{
779-
scanner_raise_error (context_p);
780-
}
781-
782-
scanner_context_p->mode = SCAN_MODE_STATEMENT;
792+
scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS;
783793
parser_stack_pop_uint8 (context_p);
784-
return false;
794+
return true;
785795
}
786796
#endif /* ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) */
787797
default:
@@ -949,52 +959,76 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
949959
{
950960
switch (stack_top)
951961
{
952-
case SCAN_STACK_SWITCH_BLOCK:
953-
{
954-
scanner_switch_statement_t switch_statement;
955-
956-
parser_stack_pop_uint8 (context_p);
957-
parser_stack_pop (context_p, &switch_statement, sizeof (scanner_switch_statement_t));
958-
959-
scanner_context_p->active_switch_statement = switch_statement;
960-
961-
JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_STATEMENT);
962-
return false;
963-
}
964962
case SCAN_STACK_BLOCK_STATEMENT:
963+
case SCAN_STACK_FUNCTION_STATEMENT:
965964
{
966965
JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_STATEMENT);
967966
break;
968967
}
969-
case SCAN_STACK_BLOCK_EXPRESSION:
968+
case SCAN_STACK_FUNCTION_EXPRESSION:
970969
{
971970
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
972971
break;
973972
}
974-
case SCAN_STACK_BLOCK_PROPERTY:
973+
case SCAN_STACK_FUNCTION_PROPERTY:
975974
{
975+
parser_stack_pop_uint8 (context_p);
976+
977+
#if ENABLED (JERRY_ES2015_CLASS)
978+
if (context_p->stack_top_uint8 == SCAN_STACK_CLASS_STATEMENT
979+
|| context_p->stack_top_uint8 == SCAN_STACK_CLASS_EXPRESSION)
980+
{
981+
scanner_context_p->mode = SCAN_MODE_CLASS_METHOD;
982+
return true;
983+
}
984+
#endif /* ENABLED (JERRY_ES2015_CLASS) */
985+
986+
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL);
987+
976988
lexer_next_token (context_p);
977-
if (context_p->token.type != LEXER_COMMA
978-
&& context_p->token.type != LEXER_RIGHT_BRACE)
989+
990+
if (context_p->token.type == LEXER_RIGHT_BRACE)
991+
{
992+
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
993+
return true;
994+
}
995+
996+
if (context_p->token.type != LEXER_COMMA)
979997
{
980998
scanner_raise_error (context_p);
981999
}
9821000

983-
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
984-
parser_stack_pop_uint8 (context_p);
1001+
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
9851002
return true;
9861003
}
987-
#if ENABLED (JERRY_ES2015_CLASS)
988-
case SCAN_STACK_CLASS_FUNCTION:
1004+
case SCAN_STACK_SWITCH_BLOCK:
9891005
{
990-
scanner_context_p->mode = SCAN_MODE_CLASS_METHOD;
1006+
scanner_switch_statement_t switch_statement;
1007+
9911008
parser_stack_pop_uint8 (context_p);
992-
return true;
1009+
parser_stack_pop (context_p, &switch_statement, sizeof (scanner_switch_statement_t));
1010+
1011+
scanner_context_p->active_switch_statement = switch_statement;
1012+
1013+
JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_STATEMENT);
1014+
return false;
1015+
}
1016+
#if ENABLED (JERRY_ES2015_CLASS)
1017+
case SCAN_STACK_CLASS_STATEMENT:
1018+
{
1019+
JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_STATEMENT);
1020+
break;
1021+
}
1022+
case SCAN_STACK_CLASS_EXPRESSION:
1023+
{
1024+
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
1025+
break;
9931026
}
9941027
#endif /* ENABLED (JERRY_ES2015_CLASS) */
9951028
default:
9961029
{
9971030
scanner_raise_error (context_p);
1031+
break;
9981032
}
9991033
}
10001034

@@ -1015,14 +1049,14 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
10151049
scanner_raise_error (context_p);
10161050
}
10171051

1018-
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
1052+
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT);
10191053
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
10201054
return false;
10211055
}
10221056
#if ENABLED (JERRY_ES2015_CLASS)
10231057
case LEXER_KEYW_CLASS:
10241058
{
1025-
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
1059+
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT);
10261060
scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
10271061
return false;
10281062
}
@@ -1163,7 +1197,7 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */
11631197
lexer_next_token (context_p);
11641198
}
11651199

1166-
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION);
1200+
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT);
11671201
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
11681202
return true;
11691203
}
@@ -1368,7 +1402,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
13681402
}
13691403
case SCAN_MODE_CLASS_METHOD:
13701404
{
1371-
JERRY_ASSERT (stack_top == SCAN_STACK_BLOCK_STATEMENT || stack_top == SCAN_STACK_BLOCK_EXPRESSION);
1405+
JERRY_ASSERT (stack_top == SCAN_STACK_CLASS_STATEMENT || stack_top == SCAN_STACK_CLASS_EXPRESSION);
13721406

13731407
lexer_scan_identifier (context_p, LEXER_SCAN_CLASS_PROPERTY);
13741408

@@ -1379,7 +1413,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
13791413

13801414
if (context_p->token.type == LEXER_RIGHT_BRACE)
13811415
{
1382-
scanner_context.mode = (stack_top == SCAN_STACK_BLOCK_EXPRESSION ? SCAN_MODE_PRIMARY_EXPRESSION_END
1416+
scanner_context.mode = (stack_top == SCAN_STACK_CLASS_EXPRESSION ? SCAN_MODE_PRIMARY_EXPRESSION_END
13831417
: SCAN_MODE_STATEMENT);
13841418
parser_stack_pop_uint8 (context_p);
13851419
break;
@@ -1390,7 +1424,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
13901424
lexer_scan_identifier (context_p, LEXER_SCAN_CLASS_PROPERTY);
13911425
}
13921426

1393-
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_FUNCTION);
1427+
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
13941428
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
13951429

13961430
if (lexer_compare_literal_to_identifier (context_p, "get", 3)
@@ -1426,7 +1460,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
14261460

14271461
if (context_p->token.type == LEXER_LEFT_BRACE)
14281462
{
1429-
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_EXPRESSION);
1463+
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_EXPRESSION);
14301464
scanner_context.mode = SCAN_MODE_STATEMENT;
14311465
}
14321466
else
@@ -1466,23 +1500,23 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
14661500
}
14671501
case SCAN_MODE_FUNCTION_ARGUMENTS:
14681502
{
1469-
#if ENABLED (JERRY_ES2015_CLASS)
1470-
JERRY_ASSERT (stack_top == SCAN_STACK_BLOCK_STATEMENT
1471-
|| stack_top == SCAN_STACK_BLOCK_EXPRESSION
1472-
|| stack_top == SCAN_STACK_CLASS_FUNCTION
1473-
|| stack_top == SCAN_STACK_BLOCK_PROPERTY);
1474-
#else /* !ENABLED (JERRY_ES2015_CLASS) */
1475-
JERRY_ASSERT (stack_top == SCAN_STACK_BLOCK_STATEMENT
1476-
|| stack_top == SCAN_STACK_BLOCK_EXPRESSION
1477-
|| stack_top == SCAN_STACK_BLOCK_PROPERTY);
1478-
#endif /* ENABLED (JERRY_ES2015_CLASS) */
1503+
JERRY_ASSERT (stack_top == SCAN_STACK_FUNCTION_STATEMENT
1504+
|| stack_top == SCAN_STACK_FUNCTION_EXPRESSION
1505+
|| stack_top == SCAN_STACK_FUNCTION_PROPERTY);
14791506

14801507
if (type != LEXER_LEFT_PAREN)
14811508
{
14821509
scanner_raise_error (context_p);
14831510
}
14841511
lexer_next_token (context_p);
14851512

1513+
#if ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER)
1514+
/* FALLTHRU */
1515+
}
1516+
case SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS:
1517+
{
1518+
#endif /* ENABLED (JERRY_ES2015_FUNCTION_PARAMETER_INITIALIZER) */
1519+
14861520
if (context_p->token.type != LEXER_RIGHT_PAREN)
14871521
{
14881522
while (true)
@@ -1559,7 +1593,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
15591593
{
15601594
lexer_scan_identifier (context_p, LEXER_SCAN_IDENT_PROPERTY | LEXER_SCAN_IDENT_NO_KEYW);
15611595

1562-
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_PROPERTY);
1596+
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
15631597

15641598
#if ENABLED (JERRY_ES2015_OBJECT_INITIALIZER)
15651599
if (context_p->token.type == LEXER_LEFT_SQUARE)
@@ -1584,7 +1618,7 @@ scanner_scan_all (parser_context_t *context_p) /**< context */
15841618
#if ENABLED (JERRY_ES2015_OBJECT_INITIALIZER)
15851619
if (context_p->token.type == LEXER_LEFT_PAREN)
15861620
{
1587-
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_PROPERTY);
1621+
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
15881622
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
15891623
continue;
15901624
}

tests/jerry/es2015/function-rest-parameter.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,6 @@ assert (g2 () === 11);
7878
assert (g2 (1) === 3);
7979
assert (g2 (1, 2) === 3);
8080
assert (g2 (1, 2, 3) === 4);
81+
82+
// Pre-scanner regression test
83+
for (var tmp in {}) ;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright JS Foundation and other contributors, http://js.foundation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
switch ($) {
16+
case $: function $( $ = $, ... c ) { }
17+
case $ :
18+
}

0 commit comments

Comments
 (0)