From e1fc90db0e526175be575a59826d0a271ea2827d Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Fri, 8 Nov 2019 12:18:23 +0100 Subject: [PATCH] Delay the variable construction in the function body. (#3289) Local variables inside the function body should be constructed after the parameters are initialized. Furthermore arguments should be available during parameter initialization. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- jerry-core/parser/js/js-parser-internal.h | 9 + jerry-core/parser/js/js-parser.c | 8 +- jerry-core/parser/js/js-scanner-util.c | 212 +++++++++++++-------- jerry-core/parser/js/js-scanner.c | 7 +- jerry-core/parser/js/js-scanner.h | 10 +- jerry-core/vm/vm.c | 4 - tests/jerry/es2015/function-param-init2.js | 65 +++++++ 7 files changed, 223 insertions(+), 92 deletions(-) create mode 100644 tests/jerry/es2015/function-param-init2.js diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index 2a2400ff0..a471733ac 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -320,6 +320,14 @@ typedef struct /** * This item represents a function literal in the scope stack. + * + * When map_from == PARSER_SCOPE_STACK_FUNC: + * map_to represents the literal reserved for a function literal + * Note: the name of the function is the previous value in the scope stack + * + * When map_to == PARSER_SCOPE_STACK_FUNC: + * map_from represents the name of the function literal following this literal + * Note: only the name, the real mapping is somewhere else in the scope stack */ #define PARSER_SCOPE_STACK_FUNC 0xffff @@ -626,6 +634,7 @@ void parser_parse_super_class_context_end (parser_context_t *context_p); void scanner_release_next (parser_context_t *context_p, size_t size); void scanner_set_active (parser_context_t *context_p); +void scanner_revert_active (parser_context_t *context_p); void scanner_release_active (parser_context_t *context_p, size_t size); void scanner_release_switch_cases (scanner_case_info_t *case_p); void scanner_seek (parser_context_t *context_p); diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index 2e4d58c23..98a4319c8 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -1617,13 +1617,16 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */ #endif /* ENABLED (JERRY_ES2015) */ JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION); - scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); if (context_p->token.type == end_type) { + scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS); return; } + scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_ARGS); + scanner_set_active (context_p); + while (true) { #if ENABLED (JERRY_ES2015) @@ -1730,6 +1733,9 @@ parser_parse_function_arguments (parser_context_t *context_p, /**< context */ parser_raise_error (context_p, error); } + + scanner_revert_active (context_p); + scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_BODY); } /* parser_parse_function_arguments */ /** diff --git a/jerry-core/parser/js/js-scanner-util.c b/jerry-core/parser/js/js-scanner-util.c index 61c3d1002..1a5a1a70f 100644 --- a/jerry-core/parser/js/js-scanner-util.c +++ b/jerry-core/parser/js/js-scanner-util.c @@ -258,6 +258,19 @@ scanner_set_active (parser_context_t *context_p) /**< context */ context_p->active_scanner_info_p = scanner_info_p; } /* scanner_set_active */ +/** + * Set the next scanner info to the active scanner info. + */ +inline void JERRY_ATTR_ALWAYS_INLINE +scanner_revert_active (parser_context_t *context_p) /**< context */ +{ + scanner_info_t *scanner_info_p = context_p->active_scanner_info_p; + + context_p->active_scanner_info_p = scanner_info_p->next_p; + scanner_info_p->next_p = context_p->next_scanner_info_p; + context_p->next_scanner_info_p = scanner_info_p; +} /* scanner_revert_active */ + /** * Release the active scanner info. */ @@ -394,7 +407,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */ lexer_lit_location_t *literal_p; bool is_function = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION) != 0; bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0; - bool search_arguments = is_function && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0; + bool search_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0; bool arguments_required = (no_reg && search_arguments); #if ENABLED (JERRY_ES2015) bool no_var_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_VAR_REG) != 0; @@ -545,7 +558,7 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */ if (is_function || (compressed_size > 1)) { - compressed_size += is_function ? sizeof (scanner_function_info_t) : sizeof (scanner_info_t); + compressed_size += sizeof (scanner_info_t); scanner_info_t *info_p; @@ -564,14 +577,12 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */ no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK; } - uint8_t *data_p = (uint8_t *) info_p; + uint8_t *data_p = (uint8_t *) (info_p + 1); if (is_function) { info_p->type = SCANNER_TYPE_FUNCTION; - data_p += sizeof (scanner_function_info_t); - scanner_function_info_t *function_info_p = (scanner_function_info_t *) info_p; uint8_t status_flags = 0; if (arguments_required) @@ -584,13 +595,12 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */ } } - function_info_p->info.u8_arg = status_flags; - function_info_p->info.u16_arg = (uint16_t) no_declarations; + info_p->u8_arg = status_flags; + info_p->u16_arg = (uint16_t) no_declarations; } else { info_p->type = SCANNER_TYPE_BLOCK; - data_p += sizeof (scanner_info_t); JERRY_ASSERT (prev_literal_pool_p != NULL); } @@ -730,6 +740,7 @@ scanner_filter_arguments (parser_context_t *context_p, /**< context */ parser_list_iterator_t literal_iterator; lexer_lit_location_t *literal_p; bool no_reg = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_REG) != 0; + bool has_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0; if (no_reg && prev_literal_pool_p != NULL) { @@ -774,7 +785,10 @@ scanner_filter_arguments (parser_context_t *context_p, /**< context */ while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL) { - if (literal_p->type & SCANNER_LITERAL_IS_ARG) + if ((literal_p->type & SCANNER_LITERAL_IS_ARG) + || (has_arguments + && literal_p->length == 9 + && lexer_compare_identifiers (literal_p->char_p, (const uint8_t *) "arguments", 9))) { lexer_lit_location_t *new_literal_p; new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool); @@ -1189,10 +1203,6 @@ scanner_cleanup (parser_context_t *context_p) /**< context */ continue; } case SCANNER_TYPE_FUNCTION: - { - size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_function_info_t)); - break; - } case SCANNER_TYPE_BLOCK: { size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_info_t)); @@ -1396,7 +1406,7 @@ bool scanner_is_global_context_needed (parser_context_t *context_p) /**< context */ { scanner_info_t *info_p = context_p->next_scanner_info_p; - const uint8_t *data_p = ((const uint8_t *) info_p) + sizeof (scanner_function_info_t); + const uint8_t *data_p = (const uint8_t *) (info_p + 1); uint32_t scope_stack_reg_top = 0; JERRY_ASSERT (info_p->type == SCANNER_TYPE_FUNCTION); @@ -1467,6 +1477,26 @@ const lexer_lit_location_t lexer_arguments_literal = (const uint8_t *) "arguments", 9, LEXER_IDENT_LITERAL, false }; +/** + * Create an unused literal. + */ +static void +scanner_create_unused_literal (parser_context_t *context_p, /**< context */ + uint8_t status_flags) /**< initial status flags */ +{ + if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)) + { + parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); + } + + lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); + + literal_p->type = LEXER_UNUSED_LITERAL; + literal_p->status_flags = status_flags; + + context_p->literal_count++; +} /* scanner_create_unused_literal */ + /** * Create and/or initialize var/let/const/function/etc. variables. */ @@ -1475,15 +1505,19 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ uint32_t option_flags) /**< combination of scanner_create_variables_flags_t bits */ { scanner_info_t *info_p = context_p->next_scanner_info_p; - const uint8_t *data_p; + const uint8_t *next_data_p = (const uint8_t *) (info_p + 1); uint8_t info_type = info_p->type; lexer_lit_location_t literal; parser_scope_stack *scope_stack_p; parser_scope_stack *scope_stack_end_p; JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION || info_type == SCANNER_TYPE_BLOCK); + JERRY_ASSERT (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS) + || !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)); + JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION + || !(option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_ARGS | SCANNER_CREATE_VARS_IS_FUNCTION_BODY))); - if (info_type == SCANNER_TYPE_FUNCTION) + if (info_type == SCANNER_TYPE_FUNCTION && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)) { JERRY_ASSERT (context_p->scope_stack_p == NULL); @@ -1492,59 +1526,55 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ if (stack_size == 0) { - scanner_release_next (context_p, sizeof (scanner_function_info_t) + 1); + if (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)) + { + scanner_release_next (context_p, sizeof (scanner_info_t) + 1); + } return; } scope_stack_p = (parser_scope_stack *) parser_malloc (context_p, stack_size); context_p->scope_stack_p = scope_stack_p; scope_stack_end_p = scope_stack_p + context_p->scope_stack_size; - - data_p = ((const uint8_t *) info_p) + sizeof (scanner_function_info_t); } else { JERRY_ASSERT (context_p->scope_stack_p != NULL); + scope_stack_p = context_p->scope_stack_p; scope_stack_end_p = scope_stack_p + context_p->scope_stack_size; scope_stack_p += context_p->scope_stack_top; - - data_p = ((const uint8_t *) info_p) + sizeof (scanner_info_t); } uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top; literal.char_p = info_p->source_p - 1; - while (data_p[0] != SCANNER_STREAM_TYPE_END) + while (next_data_p[0] != SCANNER_STREAM_TYPE_END) { - uint32_t type = data_p[0] & SCANNER_STREAM_TYPE_MASK; + uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK; + const uint8_t *data_p = next_data_p; - if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) - { - JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); - parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); - } + JERRY_ASSERT ((option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_BODY | SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)) + || (type != SCANNER_STREAM_TYPE_HOLE + && type != SCANNER_STREAM_TYPE_ARG + && type != SCANNER_STREAM_TYPE_ARG_FUNC)); +#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) + JERRY_ASSERT (type != SCANNER_STREAM_TYPE_IMPORT || (data_p[0] & SCANNER_STREAM_NO_REG)); +#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ if (type == SCANNER_STREAM_TYPE_HOLE) { - data_p++; + next_data_p++; - JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION); + if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY) + { + continue; + } if (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED) { - if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)) - { - parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); - } - - lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); - - literal_p->type = LEXER_UNUSED_LITERAL; - literal_p->status_flags = LEXER_FLAG_FUNCTION_ARGUMENT; - - context_p->literal_count++; + scanner_create_unused_literal (context_p, LEXER_FLAG_FUNCTION_ARGUMENT); } if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) @@ -1554,19 +1584,17 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ continue; } - size_t length; - if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF)) { if (data_p[2] != 0) { literal.char_p += data_p[2]; - length = 2 + 1; + next_data_p += 2 + 1; } else { memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *)); - length = 2 + 1 + sizeof (const uint8_t *); + next_data_p += 2 + 1 + sizeof (const uint8_t *); } } else @@ -1579,7 +1607,22 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ } literal.char_p += diff; - length = 2 + 2; + next_data_p += 2 + 2; + } + + if (type == SCANNER_STREAM_TYPE_ARG) + { + if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY) + { + literal.char_p += data_p[1]; + continue; + } + } + else if ((option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS) + && type != SCANNER_STREAM_TYPE_ARG_FUNC) + { + /* Function arguments must come first. */ + break; } literal.length = data_p[1]; @@ -1587,16 +1630,39 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0; lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL); + literal.char_p += data_p[1]; + + if (type == SCANNER_STREAM_TYPE_ARG_FUNC && (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)) + { + JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p + 2); + + parser_scope_stack *function_map_p = scope_stack_p - 2; + uint16_t literal_index = context_p->lit_object.index; + + while (literal_index != function_map_p->map_from) + { + function_map_p--; + + JERRY_ASSERT (function_map_p >= context_p->scope_stack_p); + } + + JERRY_ASSERT (function_map_p[1].map_from == PARSER_SCOPE_STACK_FUNC); + + parser_emit_cbc_literal_value (context_p, CBC_SET_VAR_FUNC, function_map_p[1].map_to, function_map_p[0].map_to); + continue; + } + + if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) + { + JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); + parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); + } scope_stack_p->map_from = context_p->lit_object.index; uint16_t map_to; uint16_t func_init_opcode = CBC_INIT_LOCAL; -#if ENABLED (JERRY_ES2015_MODULE_SYSTEM) - JERRY_ASSERT (type != SCANNER_STREAM_TYPE_IMPORT || (data_p[0] & SCANNER_STREAM_NO_REG)); -#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ - #if ENABLED (JERRY_ES2015) if (info_type == SCANNER_TYPE_FUNCTION) { @@ -1682,6 +1748,7 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ break; } case SCANNER_STREAM_TYPE_ARG: + case SCANNER_STREAM_TYPE_ARG_FUNC: { #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); @@ -1691,14 +1758,12 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ CBC_INIT_LOCAL, (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top), map_to); - /* FALLTHRU */ - } - case SCANNER_STREAM_TYPE_ARG_FUNC: - { + if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS) { scope_stack_reg_top++; } + break; } } } @@ -1706,9 +1771,6 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ scope_stack_p++; - literal.char_p += data_p[1]; - data_p += length; - if (!SCANNER_STREAM_TYPE_IS_FUNCTION (type)) { continue; @@ -1720,37 +1782,34 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED); } - if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS)) - { - parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED); - } - #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */ - if (func_init_opcode == CBC_INIT_LOCAL - && (option_flags & SCANNER_CREATE_VARS_IS_EVAL)) + if (type != SCANNER_STREAM_TYPE_ARG_FUNC) { - func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL; - } + if (func_init_opcode == CBC_INIT_LOCAL + && (option_flags & SCANNER_CREATE_VARS_IS_EVAL)) + { + func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL; + } - parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to); + parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to); + } scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC; scope_stack_p->map_to = context_p->literal_count; scope_stack_p++; - lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool); - - literal_p->type = LEXER_UNUSED_LITERAL; - literal_p->status_flags = 0; - - context_p->literal_count++; + scanner_create_unused_literal (context_p, 0); } - if (info_type == SCANNER_TYPE_FUNCTION && (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED)) + if (info_type == SCANNER_TYPE_FUNCTION + && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY) + && (info_p->u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED)) { + JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION); + if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p)) { JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK); @@ -1781,7 +1840,10 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ context_p->register_count = (uint16_t) scope_stack_reg_top; } - scanner_release_next (context_p, (size_t) (data_p + 1 - ((const uint8_t *) info_p))); + if (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)) + { + scanner_release_next (context_p, (size_t) (next_data_p + 1 - ((const uint8_t *) info_p))); + } parser_flush_cbc (context_p); } /* scanner_create_variables */ diff --git a/jerry-core/parser/js/js-scanner.c b/jerry-core/parser/js/js-scanner.c index 5ba2d961c..789beb50d 100644 --- a/jerry-core/parser/js/js-scanner.c +++ b/jerry-core/parser/js/js-scanner.c @@ -2632,12 +2632,11 @@ scan_completed: if (info_p->type == SCANNER_TYPE_FUNCTION) { - scanner_function_info_t *function_info_p = (scanner_function_info_t *) info_p; - data_p = (const uint8_t *) (function_info_p + 1); + data_p = (const uint8_t *) (info_p + 1); JERRY_DEBUG_MSG (" FUNCTION: flags: 0x%x declarations: %d", - (int) function_info_p->info.u8_arg, - (int) function_info_p->info.u16_arg); + (int) info_p->u8_arg, + (int) info_p->u16_arg); } else { diff --git a/jerry-core/parser/js/js-scanner.h b/jerry-core/parser/js/js-scanner.h index 5cb7368d4..2058e6df1 100644 --- a/jerry-core/parser/js/js-scanner.h +++ b/jerry-core/parser/js/js-scanner.h @@ -175,14 +175,6 @@ typedef enum SCANNER_FUNCTION_ARGUMENTS_NEEDED = (1 << 0), /**< arguments object needs to be created */ } scanner_function_flags_t; -/** - * Scanner info for function statements. - */ -typedef struct -{ - scanner_info_t info; /**< header */ -} scanner_function_info_t; - /** * Option bits for scanner_create_variables function. */ @@ -190,6 +182,8 @@ typedef enum { SCANNER_CREATE_VARS_NO_OPTS = 0, /**< no options */ SCANNER_CREATE_VARS_IS_EVAL = (1 << 0), /**< create variables for script / direct eval */ + SCANNER_CREATE_VARS_IS_FUNCTION_ARGS = (1 << 1), /**< create variables for function arguments */ + SCANNER_CREATE_VARS_IS_FUNCTION_BODY = (1 << 2), /**< create variables for function body */ } scanner_create_variables_flags_t; /** diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index ff05d2e09..3a8556f72 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -949,7 +949,6 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ break; } -#if ENABLED (JERRY_ES2015) case CBC_SET_VAR_FUNC: { uint32_t literal_index, value_index; @@ -966,8 +965,6 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (literal_index < register_end) { - JERRY_ASSERT (type == CBC_SET_VAR_FUNC); - ecma_fast_free_value (frame_ctx_p->registers_p[literal_index]); frame_ctx_p->registers_p[literal_index] = lit_value; break; @@ -978,7 +975,6 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ vm_set_var (frame_ctx_p->lex_env_p, name_p, is_strict, lit_value); break; } -#endif /* ENABLED (JERRY_ES2015) */ #if ENABLED (JERRY_SNAPSHOT_EXEC) case CBC_SET_BYTECODE_PTR: diff --git a/tests/jerry/es2015/function-param-init2.js b/tests/jerry/es2015/function-param-init2.js new file mode 100644 index 000000000..237a5b704 --- /dev/null +++ b/tests/jerry/es2015/function-param-init2.js @@ -0,0 +1,65 @@ +// 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. + +function f(a, b = a) +{ + function a() { return 2; } + + assert(a() === 2); + assert(b === 1) +} +f(1); + +function g(a, b = a) +{ + function a() { return 2; } + + eval("assert(a() === 2)"); + eval("assert(b === 1)"); +} +g(1); + +var x = 1; +function h(a = x) { + assert(x === undefined); + var x = 2; + assert(a === 1); + assert(x === 2); +} +h(); + +x = function() { return 4; } +let y = 6; + +function i(a = x() / 2, b = (y) + 2, c = typeof z) { + let y = 10; + let z = 11; + + function x() { return 5; } + + assert(a === 2); + assert(x() === 5); + assert(b === 8); + assert(c === "undefined"); + assert(y === 10); + assert(z === 11); +} +i(); + +var arguments = 10; +function j(a = arguments[1]) +{ + assert(a === 2); +} +j(undefined,2);