Skip to content

Commit 5562a2a

Browse files
committed
Add support for function argument initializers.
EcmaScript 2015 14.1. Note: arrow functions with default arguments are not supported yet. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
1 parent e0e6363 commit 5562a2a

File tree

8 files changed

+164
-18
lines changed

8 files changed

+164
-18
lines changed

jerry-core/config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
# define CONFIG_DISABLE_ES2015_ARROW_FUNCTION
4040
# define CONFIG_DISABLE_ES2015_BUILTIN
4141
# define CONFIG_DISABLE_ES2015_CLASS
42+
# define CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER
4243
# define CONFIG_DISABLE_ES2015_MAP_BUILTIN
4344
# define CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER
4445
# define CONFIG_DISABLE_ES2015_PROMISE_BUILTIN

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ typedef enum
7676
#ifndef CONFIG_DISABLE_ES2015_CLASS
7777
SCAN_STACK_CLASS, /**< class language element */
7878
#endif /* !CONFIG_DISABLE_ES2015_CLASS */
79+
#ifndef CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER
80+
SCAN_STACK_FUNCTION_PARAMETERS, /**< function parameter initializer */
81+
#endif /* !CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER */
7982
} scan_stack_modes_t;
8083

8184
/**
@@ -406,6 +409,22 @@ parser_scan_primary_expression_end (parser_context_t *context_p, /**< context */
406409
}
407410
#endif /* !CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER */
408411

412+
#ifndef CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER
413+
if (context_p->token.type == LEXER_RIGHT_PAREN && stack_top == SCAN_STACK_FUNCTION_PARAMETERS)
414+
{
415+
lexer_next_token (context_p);
416+
417+
parser_stack_pop_uint8 (context_p);
418+
419+
if (context_p->token.type != LEXER_LEFT_BRACE)
420+
{
421+
parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED);
422+
}
423+
*mode = SCAN_MODE_STATEMENT;
424+
return false;
425+
}
426+
#endif /* !CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER */
427+
409428
/* Check whether we can enter to statement mode. */
410429
if (stack_top != SCAN_STACK_BLOCK_STATEMENT
411430
&& stack_top != SCAN_STACK_BLOCK_EXPRESSION
@@ -842,6 +861,15 @@ parser_scan_until (parser_context_t *context_p, /**< context */
842861
}
843862
}
844863

864+
#ifndef CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER
865+
if (context_p->token.type == LEXER_ASSIGN)
866+
{
867+
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PARAMETERS);
868+
mode = SCAN_MODE_PRIMARY_EXPRESSION;
869+
break;
870+
}
871+
#endif /* !CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER */
872+
845873
if (context_p->token.type != LEXER_RIGHT_PAREN)
846874
{
847875
parser_raise_error (context_p, PARSER_ERR_RIGHT_PAREN_EXPECTED);

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

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,6 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
326326

327327
context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_VAR;
328328

329-
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
330-
331329
lexer_next_token (context_p);
332330

333331
if (context_p->token.type == LEXER_ASSIGN)
@@ -336,19 +334,11 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
336334
if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
337335
&& ident_line_counter != context_p->last_breakpoint_line)
338336
{
339-
JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL);
340-
341-
cbc_argument_t last_cbc = context_p->last_cbc;
342-
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
343-
344337
parser_emit_cbc (context_p, CBC_BREAKPOINT_DISABLED);
345338
parser_flush_cbc (context_p);
346339

347340
parser_append_breakpoint_info (context_p, JERRY_DEBUGGER_BREAKPOINT_LIST, ident_line_counter);
348341

349-
context_p->last_cbc_opcode = CBC_PUSH_LITERAL;
350-
context_p->last_cbc = last_cbc;
351-
352342
context_p->last_breakpoint_line = ident_line_counter;
353343
}
354344
#endif /* JERRY_DEBUGGER */
@@ -360,16 +350,10 @@ parser_parse_var_statement (parser_context_t *context_p) /**< context */
360350
}
361351
#endif /* JERRY_ENABLE_LINE_INFO */
362352

353+
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
363354
parser_parse_expression (context_p,
364355
PARSE_EXPR_STATEMENT | PARSE_EXPR_NO_COMMA | PARSE_EXPR_HAS_LITERAL);
365356
}
366-
else
367-
{
368-
JERRY_ASSERT (context_p->last_cbc_opcode == CBC_PUSH_LITERAL
369-
&& context_p->last_cbc.literal_type == LEXER_IDENT_LITERAL);
370-
/* We don't need to assign anything to this variable. */
371-
context_p->last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
372-
}
373357

374358
if (context_p->token.type != LEXER_COMMA)
375359
{

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,12 @@ parser_error_to_string (parser_error_t error) /**< error code */
10341034
{
10351035
return "Duplicated label.";
10361036
}
1037+
#ifndef CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER
1038+
case PARSER_ERR_DUPLICATED_ARGUMENT_NAMES:
1039+
{
1040+
return "Duplicated function argument names are not allowed here.";
1041+
}
1042+
#endif /* !CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER */
10371043
case PARSER_ERR_OBJECT_PROPERTY_REDEFINED:
10381044
{
10391045
return "Property of object literal redefined.";

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,6 +2155,11 @@ static void
21552155
parser_parse_function_arguments (parser_context_t *context_p, /**< context */
21562156
lexer_token_type_t end_type) /**< expected end type */
21572157
{
2158+
#ifndef CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER
2159+
bool duplicated_argument_names = false;
2160+
bool initializer_found = false;
2161+
#endif /* !CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER */
2162+
21582163
if (context_p->token.type == end_type)
21592164
{
21602165
return;
@@ -2196,6 +2201,14 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
21962201
{
21972202
lexer_literal_t *literal_p;
21982203

2204+
#ifndef CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER
2205+
if (initializer_found)
2206+
{
2207+
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
2208+
}
2209+
duplicated_argument_names = true;
2210+
#endif /* !CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER */
2211+
21992212
if (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)
22002213
{
22012214
parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
@@ -2232,6 +2245,29 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */
22322245

22332246
lexer_next_token (context_p);
22342247

2248+
#ifndef CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER
2249+
if (context_p->token.type == LEXER_ASSIGN)
2250+
{
2251+
parser_branch_t skip_init;
2252+
2253+
if (duplicated_argument_names)
2254+
{
2255+
parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
2256+
}
2257+
initializer_found = true;
2258+
2259+
/* LEXER_ASSIGN does not overwrite lit_object. */
2260+
parser_emit_cbc (context_p, CBC_PUSH_UNDEFINED);
2261+
parser_emit_cbc_literal (context_p, CBC_STRICT_EQUAL_RIGHT_LITERAL, context_p->lit_object.index);
2262+
parser_emit_cbc_forward_branch (context_p, CBC_BRANCH_IF_FALSE_FORWARD, &skip_init);
2263+
2264+
parser_emit_cbc_literal_from_token (context_p, CBC_PUSH_LITERAL);
2265+
parser_parse_expression (context_p, PARSE_EXPR_STATEMENT | PARSE_EXPR_NO_COMMA | PARSE_EXPR_HAS_LITERAL);
2266+
2267+
parser_set_branch_to_current_position (context_p, &skip_init);
2268+
}
2269+
#endif /* !CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER */
2270+
22352271
if (context_p->token.type != LEXER_COMMA)
22362272
{
22372273
break;

jerry-core/parser/js/js-parser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ typedef enum
118118
PARSER_ERR_INVALID_RETURN, /**< return must be inside a function */
119119
PARSER_ERR_INVALID_RIGHT_SQUARE, /**< right square must terminate a block */
120120
PARSER_ERR_DUPLICATED_LABEL, /**< duplicated label */
121+
#ifndef CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER
122+
PARSER_ERR_DUPLICATED_ARGUMENT_NAMES, /**< duplicated argument names */
123+
#endif /* !CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER */
121124
PARSER_ERR_OBJECT_PROPERTY_REDEFINED, /**< property of object literal redefined */
122125
PARSER_ERR_NON_STRICT_ARG_DEFINITION /**< non-strict argument definition */
123126
} parser_error_t;

jerry-core/profiles/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ Alternatively, if you want to use a custom profile at
3232
# Turn off every ES2015 feature EXCEPT the arrow functions
3333
CONFIG_DISABLE_ES2015_BUILTIN
3434
CONFIG_DISABLE_ES2015_CLASS
35+
CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER
36+
CONFIG_DISABLE_ES2015_MAP_BUILTIN
37+
CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER
3538
CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
3639
CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS
3740
CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
@@ -87,6 +90,8 @@ In JerryScript all of the features are enabled by default, so an empty profile f
8790
Disable the built-in updates of the 5.1 standard. There are some differences in those built-ins which available in both [5.1](http://www.ecma-international.org/ecma-262/5.1/) and [2015](http://www.ecma-international.org/ecma-262/6.0/) versions of the standard. JerryScript uses the latest definition by default.
8891
* `CONFIG_DISABLE_ES2015_CLASS`:
8992
Disable the [class](https://www.ecma-international.org/ecma-262/6.0/#sec-class-definitions) language element.
93+
* `CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER`:
94+
Disable the [default value](http://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions) for formal parameters.
9095
* `CONFIG_DISABLE_ES2015_MAP_BUILTIN`:
9196
Disable the [Map](http://www.ecma-international.org/ecma-262/6.0/#sec-keyed-collection) built-ins.
9297
* `CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER`:
@@ -98,4 +103,6 @@ In JerryScript all of the features are enabled by default, so an empty profile f
98103
* `CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN`:
99104
Disable the [ArrayBuffer](http://www.ecma-international.org/ecma-262/6.0/#sec-arraybuffer-objects) and [TypedArray](http://www.ecma-international.org/ecma-262/6.0/#sec-typedarray-objects) built-ins.
100105
* `CONFIG_DISABLE_ES2015`: Disable all of the implemented [ECMAScript2015 features](http://www.ecma-international.org/ecma-262/6.0/).
101-
(equivalent to `CONFIG_DISABLE_ES2015_ARROW_FUNCTION`, `CONFIG_DISABLE_ES2015_BUILTIN`, `CONFIG_DISABLE_ES2015_CLASS`, `CONFIG_DISABLE_ES2015_PROMISE_BUILTIN`, `CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS`, and `CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN`).
106+
(equivalent to `CONFIG_DISABLE_ES2015_ARROW_FUNCTION`, `CONFIG_DISABLE_ES2015_BUILTIN`, `CONFIG_DISABLE_ES2015_CLASS`,
107+
`CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER`, `CONFIG_DISABLE_ES2015_MAP_BUILTIN`, `CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER`,
108+
`CONFIG_DISABLE_ES2015_PROMISE_BUILTIN`, `CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS`, and `CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN`).
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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+
var local = 0;
16+
17+
switch(0) { /* This switch forces a pre-scanner run. */
18+
default:
19+
20+
function f(a = (5, local = 6),
21+
b = ((5 + function(a = 6) { return a }() * 3)),
22+
c,
23+
d = true ? 1 : 2)
24+
{
25+
return "" + a + ", " + b + ", " + c + ", " + d;
26+
}
27+
28+
assert(f() === "6, 23, undefined, 1");
29+
assert(local === 6);
30+
31+
var obj = {
32+
f: function(a = [10,,20],
33+
b,
34+
c = Math.cos(0),
35+
d)
36+
{
37+
return "" + a + ", " + b + ", " + c + ", " + d;
38+
}
39+
};
40+
41+
assert(obj.f() === "10,,20, undefined, 1, undefined");
42+
43+
function g(a, b = (local = 7)) { }
44+
45+
local = 0;
46+
g();
47+
assert(local === 7);
48+
49+
local = 0;
50+
g(0);
51+
assert(local === 7);
52+
53+
local = 0;
54+
g(0, undefined);
55+
assert(local === 7);
56+
57+
local = 0;
58+
g(0, null);
59+
assert(local === 0);
60+
61+
local = 0;
62+
g(0, false);
63+
assert(local === 0);
64+
break;
65+
}
66+
67+
function CheckSyntaxError(str)
68+
{
69+
try {
70+
eval(str);
71+
assert(false);
72+
} catch (e) {
73+
assert(e instanceof SyntaxError);
74+
}
75+
}
76+
77+
CheckSyntaxError('function x(a += 5) {}');
78+
CheckSyntaxError('function x(a =, b) {}');
79+
CheckSyntaxError('function x(a = (b) {}');
80+
CheckSyntaxError('function x(a, a = 5) {}');
81+
CheckSyntaxError('function x(a = 5, a) {}');

0 commit comments

Comments
 (0)