Skip to content

Commit 21e374a

Browse files
committed
Support comma after last argument for function declarations.
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
1 parent 0f0041d commit 21e374a

File tree

5 files changed

+142
-62
lines changed

5 files changed

+142
-62
lines changed

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

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,11 +1793,7 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
17931793
while (true)
17941794
{
17951795
#if ENABLED (JERRY_ESNEXT)
1796-
if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1797-
{
1798-
parser_raise_error (context_p, PARSER_ERR_FORMAL_PARAM_AFTER_REST_PARAMETER);
1799-
}
1800-
else if (context_p->token.type == LEXER_THREE_DOTS)
1796+
if (context_p->token.type == LEXER_THREE_DOTS)
18011797
{
18021798
if (context_p->status_flags & PARSER_IS_PROPERTY_SETTER)
18031799
{
@@ -1965,18 +1961,31 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
19651961

19661962
if (context_p->token.type != LEXER_COMMA)
19671963
{
1964+
if (context_p->token.type != end_type)
1965+
{
1966+
parser_error_t error = ((end_type == LEXER_RIGHT_PAREN) ? PARSER_ERR_RIGHT_PAREN_EXPECTED
1967+
: PARSER_ERR_IDENTIFIER_EXPECTED);
1968+
1969+
parser_raise_error (context_p, error);
1970+
}
19681971
break;
19691972
}
19701973

1971-
lexer_next_token (context_p);
1972-
}
1974+
#if ENABLED (JERRY_ESNEXT)
1975+
if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1976+
{
1977+
parser_raise_error (context_p, PARSER_ERR_FORMAL_PARAM_AFTER_REST_PARAMETER);
1978+
}
1979+
#endif /* ENABLED (JERRY_ESNEXT) */
19731980

1974-
if (context_p->token.type != end_type)
1975-
{
1976-
parser_error_t error = ((end_type == LEXER_RIGHT_PAREN) ? PARSER_ERR_RIGHT_PAREN_EXPECTED
1977-
: PARSER_ERR_IDENTIFIER_EXPECTED);
1981+
lexer_next_token (context_p);
19781982

1979-
parser_raise_error (context_p, error);
1983+
#if ENABLED (JERRY_ESNEXT)
1984+
if (context_p->token.type == end_type)
1985+
{
1986+
break;
1987+
}
1988+
#endif /* ENABLED (JERRY_ESNEXT) */
19801989
}
19811990

19821991
scanner_revert_active (context_p);

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

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -182,65 +182,78 @@ scanner_check_arrow_arg (parser_context_t *context_p, /**< context */
182182
lexer_next_token (context_p);
183183
}
184184

185-
if (context_p->token.type == LEXER_LITERAL
186-
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
185+
switch (context_p->token.type)
187186
{
188-
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
189-
190-
if (lexer_check_arrow (context_p))
187+
case LEXER_RIGHT_PAREN:
191188
{
192-
process_arrow = true;
189+
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
190+
return;
193191
}
194-
else
192+
case LEXER_LITERAL:
195193
{
194+
if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
195+
{
196+
break;
197+
}
198+
199+
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
200+
201+
if (lexer_check_arrow (context_p))
202+
{
203+
process_arrow = true;
204+
break;
205+
}
206+
196207
lexer_lit_location_t *argument_literal_p = scanner_append_argument (context_p, scanner_context_p);
197208

198209
scanner_detect_eval_call (context_p, scanner_context_p);
199210

200211
lexer_next_token (context_p);
201212

202-
if (context_p->token.type == LEXER_ASSIGN)
213+
if (context_p->token.type == LEXER_COMMA || context_p->token.type == LEXER_RIGHT_PAREN)
203214
{
204-
if (argument_literal_p->type & SCANNER_LITERAL_IS_USED)
205-
{
206-
JERRY_ASSERT (argument_literal_p->type & SCANNER_LITERAL_EARLY_CREATE);
207-
return;
208-
}
215+
return;
216+
}
209217

210-
scanner_binding_literal_t binding_literal;
211-
binding_literal.literal_p = argument_literal_p;
218+
if (context_p->token.type != LEXER_ASSIGN)
219+
{
220+
break;
221+
}
212222

213-
parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
214-
parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
223+
if (argument_literal_p->type & SCANNER_LITERAL_IS_USED)
224+
{
225+
JERRY_ASSERT (argument_literal_p->type & SCANNER_LITERAL_EARLY_CREATE);
215226
return;
216227
}
217228

218-
if (context_p->token.type == LEXER_COMMA || context_p->token.type == LEXER_RIGHT_PAREN)
229+
scanner_binding_literal_t binding_literal;
230+
binding_literal.literal_p = argument_literal_p;
231+
232+
parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
233+
parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
234+
return;
235+
}
236+
case LEXER_LEFT_SQUARE:
237+
case LEXER_LEFT_BRACE:
238+
{
239+
scanner_append_hole (context_p, scanner_context_p);
240+
scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_ARROW_ARG, false);
241+
242+
if (context_p->token.type == LEXER_LEFT_BRACE)
219243
{
244+
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
245+
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
220246
return;
221247
}
222-
}
223-
}
224-
else if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
225-
{
226-
scanner_append_hole (context_p, scanner_context_p);
227-
scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_ARROW_ARG, false);
228248

229-
if (context_p->token.type == LEXER_LEFT_BRACE)
230-
{
231-
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
232-
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
249+
parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
250+
scanner_context_p->mode = SCAN_MODE_BINDING;
251+
lexer_next_token (context_p);
233252
return;
234253
}
235-
236-
parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
237-
scanner_context_p->mode = SCAN_MODE_BINDING;
238-
lexer_next_token (context_p);
239-
return;
240254
}
241255

242256
scanner_pop_literal_pool (context_p, scanner_context_p);
243-
244257
parser_stack_pop_uint8 (context_p);
245258

246259
if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC)

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

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,20 +2734,15 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
27342734
}
27352735
case SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS:
27362736
{
2737-
#endif /* ENABLED (JERRY_ESNEXT) */
27382737
if (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS)
27392738
{
2740-
#if ENABLED (JERRY_ESNEXT)
27412739
lexer_lit_location_t *argument_literal_p;
2742-
#endif /* ENABLED (JERRY_ESNEXT) */
27432740

2744-
while (true)
2741+
do
27452742
{
2746-
#if ENABLED (JERRY_ESNEXT)
27472743
if (context_p->token.type == LEXER_THREE_DOTS)
27482744
{
27492745
scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ARGUMENTS_UNMAPPED;
2750-
27512746
lexer_next_token (context_p);
27522747
}
27532748

@@ -2756,30 +2751,25 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
27562751
argument_literal_p = NULL;
27572752
break;
27582753
}
2759-
#endif /* ENABLED (JERRY_ESNEXT) */
27602754

27612755
if (context_p->token.type != LEXER_LITERAL
27622756
|| context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
27632757
{
27642758
scanner_raise_error (context_p);
27652759
}
27662760

2767-
#if ENABLED (JERRY_ESNEXT)
27682761
argument_literal_p = scanner_append_argument (context_p, &scanner_context);
2769-
#else /* !ENABLED (JERRY_ESNEXT) */
2770-
scanner_append_argument (context_p, &scanner_context);
2771-
#endif /* ENABLED (JERRY_ESNEXT) */
2772-
27732762
lexer_next_token (context_p);
27742763

27752764
if (context_p->token.type != LEXER_COMMA)
27762765
{
27772766
break;
27782767
}
2768+
27792769
lexer_next_token (context_p);
27802770
}
2771+
while (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS);
27812772

2782-
#if ENABLED (JERRY_ESNEXT)
27832773
if (argument_literal_p == NULL)
27842774
{
27852775
scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ARGUMENTS_UNMAPPED;
@@ -2820,8 +2810,30 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
28202810
parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
28212811
break;
28222812
}
2823-
#endif /* ENABLED (JERRY_ESNEXT) */
28242813
}
2814+
#else /* !ENABLED (JERRY_ESNEXT) */
2815+
if (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS)
2816+
{
2817+
while (true)
2818+
{
2819+
if (context_p->token.type != LEXER_LITERAL
2820+
|| context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
2821+
{
2822+
scanner_raise_error (context_p);
2823+
}
2824+
2825+
scanner_append_argument (context_p, &scanner_context);
2826+
lexer_next_token (context_p);
2827+
2828+
if (context_p->token.type != LEXER_COMMA)
2829+
{
2830+
break;
2831+
}
2832+
2833+
lexer_next_token (context_p);
2834+
}
2835+
}
2836+
#endif /* ENABLED (JERRY_ESNEXT) */
28252837

28262838
if (context_p->token.type == LEXER_EOS && stack_top == SCAN_STACK_SCRIPT_FUNCTION)
28272839
{

tests/jerry/es.next/arrow-function.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,8 @@ must_throw ("var x => x;");
138138
must_throw ("(()) => 0");
139139
must_throw ("((x)) => 0");
140140
must_throw ("(((x))) => 0");
141-
must_throw ("(x,) => 0");
142141
must_throw ("(x==6) => 0");
143142
must_throw ("(x y) => 0");
144-
must_throw ("(x,y,) => 0");
145143
must_throw ("x\n => 0");
146144
must_throw ("this => 0");
147145
must_throw ("(true) => 0");
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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+
function check_syntax_error (code)
16+
{
17+
try {
18+
eval (code)
19+
assert (false)
20+
} catch (e) {
21+
assert (e instanceof SyntaxError)
22+
}
23+
}
24+
25+
check_syntax_error ("function f(,) {}")
26+
check_syntax_error ("function f(...a,) {}")
27+
check_syntax_error ("function f(a = 1 + 1,,) {}")
28+
check_syntax_error ("function f(a,,b) {}")
29+
check_syntax_error ("function f(,a) {}")
30+
31+
function f1(a,) {}
32+
assert(f1.length === 1)
33+
34+
function f2(a = 1,) {}
35+
assert(f2.length === 1)
36+
37+
function f3(a = 1, b = 1 + 1, c,) {}
38+
assert(f3.length === 3)
39+
40+
var f4 = async(a,) => {}
41+
assert(f4.length === 1)
42+
43+
var f5 = async(a = 1,) => {}
44+
assert(f5.length === 1)
45+
46+
assert(((a = 1, b = 1 + 1, c,) => {}).length === 3)
47+
48+
assert(((a = 1, b, c = 1 + 1,) => {}).length === 3)

0 commit comments

Comments
 (0)