Skip to content

Commit 36bf1ec

Browse files
authored
Implement argument redefinition with var statement. (#3811)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
1 parent a885664 commit 36bf1ec

File tree

9 files changed

+155
-11
lines changed

9 files changed

+155
-11
lines changed

jerry-core/include/jerryscript-snapshot.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ extern "C"
3030
/**
3131
* Jerry snapshot format version.
3232
*/
33-
#define JERRY_SNAPSHOT_VERSION (47u)
33+
#define JERRY_SNAPSHOT_VERSION (48u)
3434

3535
/**
3636
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ JERRY_STATIC_ASSERT ((sizeof (cbc_uint16_arguments_t) % sizeof (jmem_cpointer_t)
2727
*/
2828
JERRY_STATIC_ASSERT (CBC_END == 238,
2929
number_of_cbc_opcodes_changed);
30-
JERRY_STATIC_ASSERT (CBC_EXT_END == 118,
30+
JERRY_STATIC_ASSERT (CBC_EXT_END == 119,
3131
number_of_cbc_ext_opcodes_changed);
3232

3333
#if ENABLED (JERRY_PARSER)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,8 @@
570570
VM_OC_EXT_VAR_EVAL) \
571571
CBC_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \
572572
VM_OC_EXT_VAR_EVAL) \
573+
CBC_OPCODE (CBC_EXT_COPY_FROM_ARG, CBC_HAS_LITERAL_ARG, 0, \
574+
VM_OC_COPY_FROM_ARG) \
573575
CBC_OPCODE (CBC_EXT_STRING_CONCAT, CBC_NO_FLAG, -1, \
574576
VM_OC_STRING_CONCAT | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \
575577
CBC_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL, CBC_HAS_LITERAL_ARG, 0, \

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

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,9 @@ scanner_get_stream_size (scanner_info_t *info_p, /**< scanner info block */
148148
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
149149
case SCANNER_STREAM_TYPE_ARG:
150150
#if ENABLED (JERRY_ES2015)
151+
case SCANNER_STREAM_TYPE_ARG_VAR:
151152
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
153+
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
152154
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
153155
case SCANNER_STREAM_TYPE_ARG_FUNC:
154156
#if ENABLED (JERRY_ES2015)
@@ -555,7 +557,12 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
555557
continue;
556558
}
557559

558-
type = (uint8_t) ((type & ~SCANNER_LITERAL_IS_FUNC) | SCANNER_LITERAL_IS_VAR);
560+
if (!(type & SCANNER_LITERAL_IS_ARG))
561+
{
562+
type |= SCANNER_LITERAL_IS_VAR;
563+
}
564+
565+
type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC;
559566
literal_p->type = type;
560567
}
561568
#endif /* ENABLED (JERRY_ES2015) */
@@ -802,6 +809,14 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
802809
{
803810
type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG;
804811
}
812+
813+
if (literal_p->type & SCANNER_LITERAL_IS_VAR)
814+
{
815+
type = (uint8_t) (type + 1);
816+
817+
JERRY_ASSERT (type == SCANNER_STREAM_TYPE_ARG_VAR
818+
|| type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR);
819+
}
805820
#endif /* ENABLED (JERRY_ES2015) */
806821
}
807822
#if ENABLED (JERRY_ES2015)
@@ -1731,7 +1746,9 @@ scanner_is_context_needed (parser_context_t *context_p, /**< context */
17311746
|| type == SCANNER_STREAM_TYPE_CONST
17321747
|| type == SCANNER_STREAM_TYPE_LOCAL
17331748
|| type == SCANNER_STREAM_TYPE_ARG
1749+
|| type == SCANNER_STREAM_TYPE_ARG_VAR
17341750
|| type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG
1751+
|| type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR
17351752
|| type == SCANNER_STREAM_TYPE_ARG_FUNC
17361753
|| type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC
17371754
|| type == SCANNER_STREAM_TYPE_FUNC);
@@ -1769,16 +1786,13 @@ scanner_is_context_needed (parser_context_t *context_p, /**< context */
17691786

17701787
if (JERRY_UNLIKELY (check_type == PARSER_CHECK_FUNCTION_CONTEXT))
17711788
{
1772-
if (SCANNER_STREAM_TYPE_IS_ARG (type))
1773-
{
1774-
continue;
1775-
}
1776-
1777-
if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type))
1789+
if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)
1790+
|| type == SCANNER_STREAM_TYPE_ARG_VAR
1791+
|| type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR)
17781792
{
17791793
/* The return value is true, if the variable is stored in the lexical environment
17801794
* or all registers have already been used for function arguments. This can be
1781-
* inprecise in the latter case, but that is a very rare corner case. A more
1795+
* inprecise in the latter case, but this is a very rare corner case. A more
17821796
* sophisticated check would require to decode the literal. */
17831797
if ((data & SCANNER_STREAM_NO_REG)
17841798
|| scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
@@ -1787,6 +1801,11 @@ scanner_is_context_needed (parser_context_t *context_p, /**< context */
17871801
}
17881802
continue;
17891803
}
1804+
1805+
if (SCANNER_STREAM_TYPE_IS_ARG (type))
1806+
{
1807+
continue;
1808+
}
17901809
}
17911810
#endif /* ENABLED (JERRY_ES2015) */
17921811

@@ -2072,6 +2091,24 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
20722091
{
20732092
if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
20742093
{
2094+
#if ENABLED (JERRY_ES2015)
2095+
if ((context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
2096+
&& (type == SCANNER_STREAM_TYPE_ARG_VAR || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR))
2097+
{
2098+
literal.length = data_p[1];
2099+
literal.type = LEXER_IDENT_LITERAL;
2100+
literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
2101+
2102+
/* Literal must be exists. */
2103+
lexer_construct_literal_object (context_p, &literal, LEXER_IDENT_LITERAL);
2104+
2105+
if (context_p->lit_object.index < PARSER_REGISTER_START)
2106+
{
2107+
parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_COPY_FROM_ARG);
2108+
}
2109+
}
2110+
#endif /* ENABLED (JERRY_ES2015) */
2111+
20752112
literal.char_p += data_p[1];
20762113
continue;
20772114
}
@@ -2174,7 +2211,9 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
21742211
}
21752212
case SCANNER_STREAM_TYPE_LET:
21762213
case SCANNER_STREAM_TYPE_ARG:
2214+
case SCANNER_STREAM_TYPE_ARG_VAR:
21772215
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
2216+
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
21782217
case SCANNER_STREAM_TYPE_ARG_FUNC:
21792218
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
21802219
{
@@ -2208,6 +2247,7 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
22082247
case SCANNER_STREAM_TYPE_LET:
22092248
case SCANNER_STREAM_TYPE_CONST:
22102249
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
2250+
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
22112251
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
22122252
{
22132253
scope_stack_map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY;
@@ -2261,6 +2301,7 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
22612301
{
22622302
JERRY_ASSERT (type == SCANNER_STREAM_TYPE_LOCAL
22632303
|| type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG
2304+
|| type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR
22642305
|| type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC);
22652306

22662307
opcode = CBC_CREATE_LOCAL;
@@ -2276,6 +2317,9 @@ scanner_create_variables (parser_context_t *context_p, /**< context */
22762317
break;
22772318
}
22782319
case SCANNER_STREAM_TYPE_ARG:
2320+
#if ENABLED (JERRY_ES2015)
2321+
case SCANNER_STREAM_TYPE_ARG_VAR:
2322+
#endif /* ENABLED (JERRY_ES2015) */
22792323
case SCANNER_STREAM_TYPE_ARG_FUNC:
22802324
{
22812325
#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3301,11 +3301,21 @@ scanner_scan_all (parser_context_t *context_p, /**< context */
33013301
break;
33023302
}
33033303
#if ENABLED (JERRY_ES2015)
3304+
case SCANNER_STREAM_TYPE_ARG_VAR:
3305+
{
3306+
JERRY_DEBUG_MSG (" ARG_VAR ");
3307+
break;
3308+
}
33043309
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
33053310
{
33063311
JERRY_DEBUG_MSG (" DESTRUCTURED_ARG ");
33073312
break;
33083313
}
3314+
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
3315+
{
3316+
JERRY_DEBUG_MSG (" DESTRUCTURED_ARG_VAR ");
3317+
break;
3318+
}
33093319
#endif /* ENABLED (JERRY_ES2015) */
33103320
case SCANNER_STREAM_TYPE_ARG_FUNC:
33113321
{

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,14 @@ typedef enum
154154
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
155155
SCANNER_STREAM_TYPE_IMPORT, /**< module import */
156156
#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
157+
/* The next four types must be in this order (see SCANNER_STREAM_TYPE_IS_ARG). */
157158
SCANNER_STREAM_TYPE_ARG, /**< argument declaration */
158159
#if ENABLED (JERRY_ES2015)
160+
SCANNER_STREAM_TYPE_ARG_VAR, /**< argument declaration which is later copied
161+
* into a variable declared by var statement */
159162
SCANNER_STREAM_TYPE_DESTRUCTURED_ARG, /**< destructuring argument declaration */
163+
SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR, /**< destructuring argument declaration which is later
164+
* copied into a variable declared by var statement */
160165
#endif /* ENABLED (JERRY_ES2015) */
161166
/* Function types should be at the end. See the SCANNER_STREAM_TYPE_IS_FUNCTION macro. */
162167
SCANNER_STREAM_TYPE_ARG_FUNC, /**< argument declaration which
@@ -184,7 +189,7 @@ typedef enum
184189
* Checks whether the decoded type represents a function argument.
185190
*/
186191
#define SCANNER_STREAM_TYPE_IS_ARG(type) \
187-
((type) == SCANNER_STREAM_TYPE_ARG || (type) == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG)
192+
((type) >= SCANNER_STREAM_TYPE_ARG && (type) <= SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR)
188193

189194
/**
190195
* Checks whether the decoded type represents both a function argument and a function declaration.

jerry-core/vm/vm.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,6 +1686,35 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
16861686

16871687
goto free_left_value;
16881688
}
1689+
case VM_OC_COPY_FROM_ARG:
1690+
{
1691+
uint32_t literal_index;
1692+
READ_LITERAL_INDEX (literal_index);
1693+
JERRY_ASSERT (literal_index >= register_end);
1694+
1695+
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
1696+
ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
1697+
ecma_object_t *arg_lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
1698+
1699+
JERRY_ASSERT ((lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK)
1700+
&& ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
1701+
JERRY_ASSERT (arg_lex_env_p != NULL
1702+
&& !(arg_lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK)
1703+
&& ecma_get_lex_env_type (arg_lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
1704+
1705+
ecma_property_value_t *property_value_p;
1706+
property_value_p = ecma_create_named_data_property (lex_env_p,
1707+
name_p,
1708+
ECMA_PROPERTY_FLAG_WRITABLE,
1709+
NULL);
1710+
1711+
ecma_property_t *property_p = ecma_find_named_property (arg_lex_env_p, name_p);
1712+
JERRY_ASSERT (property_p != NULL);
1713+
1714+
ecma_property_value_t *arg_prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
1715+
property_value_p->value = ecma_copy_value_if_not_object (arg_prop_value_p->value);
1716+
continue;
1717+
}
16891718
case VM_OC_CLONE_CONTEXT:
16901719
{
16911720
JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE);

jerry-core/vm/vm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ typedef enum
242242
VM_OC_INIT_BINDING, /**< create and intialize a binding */
243243
VM_OC_THROW_CONST_ERROR, /**< throw invalid assignment to const variable error */
244244
VM_OC_COPY_TO_GLOBAL, /**< copy value to global lex env */
245+
VM_OC_COPY_FROM_ARG, /**< copy value from arg lex env */
245246
VM_OC_CLONE_CONTEXT, /**< clone lexical environment with let/const declarations */
246247
VM_OC_SET_COMPUTED_PROPERTY, /**< set computed property */
247248

@@ -310,6 +311,7 @@ typedef enum
310311
VM_OC_INIT_BINDING = VM_OC_NONE, /**< create and intialize a binding */
311312
VM_OC_THROW_CONST_ERROR = VM_OC_NONE, /**< throw invalid assignment to const variable error */
312313
VM_OC_COPY_TO_GLOBAL = VM_OC_NONE, /**< copy value to global lex env */
314+
VM_OC_COPY_FROM_ARG = VM_OC_NONE, /**< copy value from arg lex env */
313315
VM_OC_CLONE_CONTEXT = VM_OC_NONE, /**< clone lexical environment with let/const declarations */
314316
VM_OC_SET_COMPUTED_PROPERTY = VM_OC_NONE, /**< set computed property is unused */
315317

tests/jerry/es2015/function-scope2.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,55 @@ function f(x = eval("eval('var a = 3; function b() { return 4 } () => a')"), y =
4343
assert(y() === 4);
4444
}
4545
f()
46+
47+
function g() {
48+
'use strict'
49+
50+
function h(x, y = function() { return x }) {
51+
var x = 2;
52+
53+
/* This should not overwrite y. */
54+
eval("var y = 3; assert (y === 3)");
55+
56+
assert(x === 2);
57+
assert(typeof y === "function");
58+
assert(y() === 1);
59+
}
60+
h(1);
61+
}
62+
g();
63+
64+
function h(a, get = () => a, set = (v) => a = v) {
65+
assert(a === 1);
66+
67+
var a = 2;
68+
69+
assert(a === 2);
70+
assert(get() === 1);
71+
72+
set(3)
73+
a = 4;
74+
75+
assert(a === 4);
76+
assert(get() === 3);
77+
}
78+
h(1);
79+
80+
function i([a], get = () => a, set = (v) => a = v) {
81+
assert(a === 1);
82+
83+
var a;
84+
assert(a === 1);
85+
86+
a = 2;
87+
88+
assert(a === 2);
89+
assert(get() === 1);
90+
91+
set(3)
92+
a = 4;
93+
94+
assert(a === 4);
95+
assert(get() === 3);
96+
}
97+
i([1]);

0 commit comments

Comments
 (0)