diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 476eaabd4..c6569d52d 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -110,15 +110,16 @@ typedef enum ECMA_PARSE_MODULE = (1u << 1), /**< module is parsed */ ECMA_PARSE_EVAL = (1u << 2), /**< eval is called */ ECMA_PARSE_DIRECT_EVAL = (1u << 3), /**< eval is called directly (ECMA-262 v5, 15.1.2.1.1) */ + ECMA_PARSE_CLASS_CONSTRUCTOR = (1u << 4), /**< a class constructor is being parsed */ - /* These 4 status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */ - ECMA_PARSE_CLASS_CONSTRUCTOR = (1u << 4), /**< a class constructor is being parsed (this value must be kept in - * in sync with PARSER_CLASS_CONSTRUCTOR) */ + /* These four status flags must be in this order. The first three are also parser status flags. + * See PARSER_SAVE_STATUS_FLAGS / PARSER_RESTORE_STATUS_FLAGS. */ ECMA_PARSE_ALLOW_SUPER = (1u << 5), /**< allow super property access */ ECMA_PARSE_ALLOW_SUPER_CALL = (1u << 6), /**< allow super constructor call */ ECMA_PARSE_ALLOW_NEW_TARGET = (1u << 7), /**< allow new.target access */ + ECMA_PARSE_FUNCTION_CONTEXT = (1u << 8), /**< function context is present (ECMA_PARSE_DIRECT_EVAL must be set) */ - ECMA_PARSE_GENERATOR_FUNCTION = (1u << 8), /**< generator function is parsed */ + ECMA_PARSE_GENERATOR_FUNCTION = (1u << 9), /**< generator function is parsed */ /* These flags are internally used by the parser. */ #ifndef JERRY_NDEBUG @@ -126,7 +127,7 @@ typedef enum * This flag represents an error in for in/of statements, which cannot be set * if the parsing is completed successfully. */ - ECMA_PARSE_INTERNAL_FOR_IN_OFF_CONTEXT_ERROR = (1u << 9), + ECMA_PARSE_INTERNAL_FOR_IN_OFF_CONTEXT_ERROR = (1u << 30), #endif /* !JERRY_NDEBUG */ } ecma_parse_opts_t; @@ -707,7 +708,8 @@ typedef enum /** * Get JERRY_CONTEXT (status_flags) top 8 bits. */ -#define ECMA_GET_LOCAL_PARSE_OPTS() (JERRY_CONTEXT (status_flags) >> ECMA_LOCAL_PARSE_OPTS_OFFSET) +#define ECMA_GET_LOCAL_PARSE_OPTS() \ + (JERRY_CONTEXT (status_flags) >> (ECMA_LOCAL_PARSE_OPTS_OFFSET - JERRY_LOG2 (ECMA_PARSE_ALLOW_SUPER))) /** * Clear JERRY_CONTEXT (status_flags) top 8 bits. diff --git a/jerry-core/include/jerryscript-snapshot.h b/jerry-core/include/jerryscript-snapshot.h index e43f6df54..15871f5be 100644 --- a/jerry-core/include/jerryscript-snapshot.h +++ b/jerry-core/include/jerryscript-snapshot.h @@ -30,7 +30,7 @@ extern "C" /** * Jerry snapshot format version. */ -#define JERRY_SNAPSHOT_VERSION (46u) +#define JERRY_SNAPSHOT_VERSION (47u) /** * Flags for jerry_generate_snapshot and jerry_generate_function_snapshot. diff --git a/jerry-core/parser/js/byte-code.c b/jerry-core/parser/js/byte-code.c index edf9e5521..1acadd6ea 100644 --- a/jerry-core/parser/js/byte-code.c +++ b/jerry-core/parser/js/byte-code.c @@ -27,7 +27,7 @@ JERRY_STATIC_ASSERT ((sizeof (cbc_uint16_arguments_t) % sizeof (jmem_cpointer_t) */ JERRY_STATIC_ASSERT (CBC_END == 238, number_of_cbc_opcodes_changed); -JERRY_STATIC_ASSERT (CBC_EXT_END == 116, +JERRY_STATIC_ASSERT (CBC_EXT_END == 118, number_of_cbc_ext_opcodes_changed); #if ENABLED (JERRY_PARSER) diff --git a/jerry-core/parser/js/byte-code.h b/jerry-core/parser/js/byte-code.h index d58c53ea3..c5e4510d6 100644 --- a/jerry-core/parser/js/byte-code.h +++ b/jerry-core/parser/js/byte-code.h @@ -566,6 +566,10 @@ VM_OC_PUSH_LIT_POS_BYTE | VM_OC_GET_LITERAL) \ CBC_OPCODE (CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE, CBC_HAS_LITERAL_ARG | CBC_HAS_BYTE_ARG, 2, \ VM_OC_PUSH_LIT_NEG_BYTE | VM_OC_GET_LITERAL) \ + CBC_OPCODE (CBC_EXT_CREATE_VAR_EVAL, CBC_HAS_LITERAL_ARG, 0, \ + VM_OC_EXT_VAR_EVAL) \ + CBC_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL, CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2, 0, \ + VM_OC_EXT_VAR_EVAL) \ CBC_OPCODE (CBC_EXT_STRING_CONCAT, CBC_NO_FLAG, -1, \ VM_OC_STRING_CONCAT | VM_OC_GET_STACK_STACK | VM_OC_PUT_STACK) \ CBC_OPCODE (CBC_EXT_STRING_CONCAT_RIGHT_LITERAL, CBC_HAS_LITERAL_ARG, 0, \ diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c index 69e42338e..c2c3389c1 100644 --- a/jerry-core/parser/js/js-parser-expr.c +++ b/jerry-core/parser/js/js-parser-expr.c @@ -2224,16 +2224,23 @@ parser_process_unary_expression (parser_context_t *context_p, /**< context */ context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED; #if ENABLED (JERRY_ES2015) + uint16_t eval_flags = PARSER_SAVE_STATUS_FLAGS (context_p->status_flags); + const uint32_t required_flags = PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED; + if (context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS) { context_p->status_flags |= PARSER_LEXICAL_BLOCK_NEEDED; } - - if (context_p->status_flags & (PARSER_ALLOW_SUPER_CALL | PARSER_ALLOW_SUPER | PARSER_ALLOW_NEW_TARGET)) + else if (((context_p->status_flags & (required_flags | PARSER_IS_STRICT)) == required_flags) + || ((context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT) + && !(context_p->status_flags & PARSER_IS_FUNCTION))) { - parser_emit_cbc_ext_call (context_p, - CBC_EXT_LOCAL_EVAL, - PARSER_SAVE_STATUS_FLAGS (context_p->status_flags)); + eval_flags |= PARSER_GET_EVAL_FLAG (ECMA_PARSE_FUNCTION_CONTEXT); + } + + if (eval_flags != 0) + { + parser_emit_cbc_ext_call (context_p, CBC_EXT_LOCAL_EVAL, eval_flags); } else { diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index b7dccb435..539615de3 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -67,9 +67,9 @@ typedef enum PARSER_FUNCTION_IS_PARSING_ARGS = (1u << 17), /**< set when parsing function arguments */ PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM = (1u << 18), /**< function has a non simple parameter */ PARSER_FUNCTION_HAS_REST_PARAM = (1u << 19), /**< function has rest parameter */ - /* These 4 status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */ PARSER_CLASS_CONSTRUCTOR = (1u << 20), /**< a class constructor is parsed * Note: PARSER_ALLOW_SUPER must be present */ + /* These three status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */ PARSER_ALLOW_SUPER = (1u << 21), /**< allow super property access */ PARSER_ALLOW_SUPER_CALL = (1u << 22), /**< allow super constructor call * Note: PARSER_CLASS_CONSTRUCTOR must be present */ @@ -154,34 +154,40 @@ typedef enum #if ENABLED (JERRY_ES2015) /** - * Offset between PARSER_CLASS_CONSTRUCTOR and ECMA_PARSE_CLASS_CONSTRUCTOR + * Offset of PARSER_ALLOW_SUPER */ #define PARSER_SAVED_FLAGS_OFFSET \ - (JERRY_LOG2 (PARSER_CLASS_CONSTRUCTOR) - JERRY_LOG2 (ECMA_PARSE_CLASS_CONSTRUCTOR)) + JERRY_LOG2 (PARSER_ALLOW_SUPER) /** - * Count of ecma_parse_opts_t class parsing options related bits + * Mask of saved flags */ -#define PARSER_SAVED_FLAGS_COUNT \ - (JERRY_LOG2 (ECMA_PARSE_ALLOW_NEW_TARGET) - JERRY_LOG2 (ECMA_PARSE_CLASS_CONSTRUCTOR) + 1) - -/** - * Mask for get class option bits from ecma_parse_opts_t - */ -#define PARSER_CLASS_ECMA_PARSE_OPTS_TO_PARSER_OPTS_MASK \ - (((1 << PARSER_SAVED_FLAGS_COUNT) - 1) << JERRY_LOG2 (ECMA_PARSE_CLASS_CONSTRUCTOR)) - -/** - * Get class option bits from ecma_parse_opts_t - */ -#define PARSER_GET_SAVED_FLAGS(opts) \ - (((opts) & PARSER_CLASS_ECMA_PARSE_OPTS_TO_PARSER_OPTS_MASK) << PARSER_SAVED_FLAGS_OFFSET) +#define PARSER_SAVED_FLAGS_MASK \ + ((1 << (JERRY_LOG2 (PARSER_ALLOW_NEW_TARGET) - JERRY_LOG2 (PARSER_ALLOW_SUPER) + 1)) - 1) /** * Get class option bits from parser_general_flags_t */ #define PARSER_SAVE_STATUS_FLAGS(opts) \ - ((uint16_t) (((opts) >> PARSER_SAVED_FLAGS_OFFSET) & PARSER_CLASS_ECMA_PARSE_OPTS_TO_PARSER_OPTS_MASK)) + ((uint16_t) (((opts) >> PARSER_SAVED_FLAGS_OFFSET) & PARSER_SAVED_FLAGS_MASK)) + +/** + * Mask for get class option bits from ecma_parse_opts_t + */ +#define PARSER_RESTORE_STATUS_FLAGS_MASK \ + (((ECMA_PARSE_ALLOW_NEW_TARGET << 1) - 1) - (ECMA_PARSE_ALLOW_SUPER - 1)) + +/** + * Shift for get class option bits from ecma_parse_opts_t + */ +#define PARSER_RESTORE_STATUS_FLAGS_SHIFT \ + (JERRY_LOG2 (PARSER_ALLOW_SUPER) - JERRY_LOG2 (ECMA_PARSE_ALLOW_SUPER)) + +/** + * Get class option bits from ecma_parse_opts_t + */ +#define PARSER_RESTORE_STATUS_FLAGS(opts) \ + (((opts) & PARSER_RESTORE_STATUS_FLAGS_MASK) << PARSER_RESTORE_STATUS_FLAGS_SHIFT) /** * All flags that affect exotic arguments object creation. @@ -189,6 +195,12 @@ typedef enum #define PARSER_ARGUMENTS_RELATED_FLAGS \ (PARSER_ARGUMENTS_NEEDED | PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM | PARSER_IS_STRICT) +/** + * Get the corresponding eval flag for a ecma_parse_opts_t flag + */ +#define PARSER_GET_EVAL_FLAG(type) \ + ((type) >> JERRY_LOG2 (ECMA_PARSE_ALLOW_SUPER)) + #else /* !ENABLED (JERRY_ES2015) */ /** diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index 5e6dfabb6..bdfc75eec 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -27,8 +27,13 @@ JERRY_STATIC_ASSERT ((int) ECMA_PARSE_STRICT_MODE == (int) PARSER_IS_STRICT, ecma_parse_strict_mode_must_be_equal_to_parser_is_strict); #if ENABLED (JERRY_ES2015) -JERRY_STATIC_ASSERT ((ECMA_PARSE_CLASS_CONSTRUCTOR << PARSER_SAVED_FLAGS_OFFSET) == PARSER_CLASS_CONSTRUCTOR, - ecma_saved_parse_options_must_be_transformed_to_ecma_general_flags); +JERRY_STATIC_ASSERT (PARSER_SAVE_STATUS_FLAGS (PARSER_ALLOW_SUPER) == 0x1, + incorrect_saving_of_ecma_parse_allow_super); +JERRY_STATIC_ASSERT (PARSER_RESTORE_STATUS_FLAGS (ECMA_PARSE_ALLOW_SUPER) == PARSER_ALLOW_SUPER, + incorrect_restoring_of_ecma_parse_allow_super); + +JERRY_STATIC_ASSERT (PARSER_RESTORE_STATUS_FLAGS (ECMA_PARSE_FUNCTION_CONTEXT) == 0, + ecma_parse_function_context_must_not_be_transformed); #endif /* ENABLED (JERRY_ES2015) */ /** \addtogroup parser Parser @@ -2016,7 +2021,7 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */ } #if ENABLED (JERRY_ES2015) - context.status_flags |= PARSER_GET_SAVED_FLAGS (parse_opts); + context.status_flags |= PARSER_RESTORE_STATUS_FLAGS (parse_opts); context.tagged_template_literal_cp = JMEM_CP_NULL; #endif /* ENABLED (JERRY_ES2015) */ diff --git a/jerry-core/parser/js/js-scanner-util.c b/jerry-core/parser/js/js-scanner-util.c index bc2ccde2a..be6766bdf 100644 --- a/jerry-core/parser/js/js-scanner-util.c +++ b/jerry-core/parser/js/js-scanner-util.c @@ -2227,9 +2227,9 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p); #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */ - uint16_t opcode = ((option_flags & SCANNER_CREATE_VARS_IS_SCRIPT) ? CBC_CREATE_VAR_EVAL - : CBC_CREATE_VAR); #if ENABLED (JERRY_ES2015) + uint16_t opcode; + switch (type) { case SCANNER_STREAM_TYPE_LET: @@ -2242,14 +2242,34 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ opcode = CBC_CREATE_CONST; break; } - case SCANNER_STREAM_TYPE_LOCAL: - case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG: - case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC: + case SCANNER_STREAM_TYPE_VAR: { + opcode = CBC_CREATE_VAR; + + if (option_flags & SCANNER_CREATE_VARS_IS_SCRIPT) + { + opcode = CBC_CREATE_VAR_EVAL; + + if (context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT) + { + opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_EVAL); + } + } + break; + } + default: + { + JERRY_ASSERT (type == SCANNER_STREAM_TYPE_LOCAL + || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG + || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC); + opcode = CBC_CREATE_LOCAL; break; } } +#else /* !ENABLED (JERRY_ES2015) */ + uint16_t opcode = ((option_flags & SCANNER_CREATE_VARS_IS_SCRIPT) ? CBC_CREATE_VAR_EVAL + : CBC_CREATE_VAR); #endif /* ENABLED (JERRY_ES2015) */ parser_emit_cbc_literal (context_p, opcode, map_to); @@ -2323,6 +2343,11 @@ scanner_create_variables (parser_context_t *context_p, /**< context */ || !scanner_scope_find_let_declaration (context_p, &literal)) { func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL; + + if (context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT) + { + func_init_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL); + } } literal.char_p += data_p[1]; #else /* !ENABLED (JERRY_ES2015) */ diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 3ccec4d92..3079852f2 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -1322,39 +1322,41 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { uint32_t value_index; READ_LITERAL_INDEX (value_index); + JERRY_ASSERT (value_index >= const_literal_end); lit_value = vm_construct_literal_object (frame_ctx_p, literal_start_p[value_index]); } READ_LITERAL_INDEX (literal_index); + JERRY_ASSERT (literal_index >= register_end); ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) { - #if ENABLED (JERRY_ES2015) && !(defined JERRY_NDEBUG) +#if ENABLED (JERRY_ES2015) && !(defined JERRY_NDEBUG) if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); } - #endif /* ENABLED (JERRY_ES2015) && !JERRY_NDEBUG */ +#endif /* ENABLED (JERRY_ES2015) && !JERRY_NDEBUG */ JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); } - #if ENABLED (JERRY_ES2015) && !(defined JERRY_NDEBUG) +#if ENABLED (JERRY_ES2015) && !(defined JERRY_NDEBUG) if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) { ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); } - #endif /* ENABLED (JERRY_ES2015) && !JERRY_NDEBUG */ +#endif /* ENABLED (JERRY_ES2015) && !JERRY_NDEBUG */ result = vm_var_decl (lex_env_p, name_p, frame_ctx_p->is_eval_code); @@ -1375,6 +1377,68 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ continue; } +#if ENABLED (JERRY_ES2015) + case VM_OC_EXT_VAR_EVAL: + { + uint32_t literal_index; + ecma_value_t lit_value = ECMA_VALUE_UNDEFINED; + + JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE); + + if (opcode == CBC_EXT_CREATE_VAR_FUNC_EVAL) + { + uint32_t value_index; + READ_LITERAL_INDEX (value_index); + JERRY_ASSERT (value_index >= const_literal_end); + + lit_value = vm_construct_literal_object (frame_ctx_p, + literal_start_p[value_index]); + } + + READ_LITERAL_INDEX (literal_index); + JERRY_ASSERT (literal_index >= register_end); + + ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]); + ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p; + ecma_object_t *prev_lex_env_p = NULL; + + while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) + { +#if !(defined JERRY_NDEBUG) + if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE) + { + ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p); + + JERRY_ASSERT (property_p == NULL || !(*property_p & ECMA_PROPERTY_FLAG_ENUMERABLE)); + } +#endif /* !JERRY_NDEBUG */ + + JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL); + prev_lex_env_p = lex_env_p; + lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp); + } + + JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (prev_lex_env_p != NULL + && ecma_get_lex_env_type (prev_lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE); + JERRY_ASSERT (ecma_find_named_property (prev_lex_env_p, name_p) == NULL); + + ecma_property_value_t *property_value_p; + property_value_p = ecma_create_named_data_property (prev_lex_env_p, + name_p, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + + if (lit_value == ECMA_VALUE_UNDEFINED) + { + continue; + } + + property_value_p->value = lit_value; + ecma_deref_object (ecma_get_object_from_value (lit_value)); + continue; + } +#endif /* ENABLED (JERRY_ES2015) */ #if ENABLED (JERRY_SNAPSHOT_EXEC) case VM_OC_SET_BYTECODE_PTR: { diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index 627ec8bdb..1b3f64dc8 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -219,6 +219,10 @@ typedef enum VM_OC_CREATE_BINDING, /**< create variables */ VM_OC_SET_BYTECODE_PTR, /**< setting bytecode pointer */ VM_OC_VAR_EVAL, /**< variable and function evaluation */ +#if ENABLED (JERRY_ES2015) + VM_OC_EXT_VAR_EVAL, /**< variable and function evaluation for + * functions with separate argument context */ +#endif /* ENABLED (JERRY_ES2015) */ VM_OC_INIT_ARG_OR_FUNC, /**< create and init a function or argument binding */ #if ENABLED (JERRY_DEBUGGER) @@ -298,6 +302,8 @@ typedef enum VM_OC_LINE = VM_OC_NONE, /**< line number of the next statement is unused */ #endif /* !ENABLED (JERRY_LINE_INFO) */ #if !ENABLED (JERRY_ES2015) + VM_OC_EXT_VAR_EVAL = VM_OC_NONE, /**< variable and function evaluation for + * functions with separate argument context */ VM_OC_CHECK_VAR = VM_OC_NONE, /**< check redeclared vars in the global scope */ VM_OC_CHECK_LET = VM_OC_NONE, /**< check redeclared lets in the global scope */ VM_OC_ASSIGN_LET_CONST = VM_OC_NONE, /**< assign values to let/const declarations */ diff --git a/tests/jerry/es2015/function-scope2.js b/tests/jerry/es2015/function-scope2.js new file mode 100644 index 000000000..a35ca1f12 --- /dev/null +++ b/tests/jerry/es2015/function-scope2.js @@ -0,0 +1,45 @@ +// 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. + +var a = 1; +var b = 2; + +function f(x = eval("eval('var a = 3; function b() { return 4 } () => a')"), y = b) { + eval("eval('var a = 5; function b() { return 6 }')"); + + assert(a === 5); + assert(b() === 6); + + assert(x() === 3); + assert(y() === 4); + + delete a; + delete b; + + assert(a === 3); + assert(b() === 4); + + assert(x() === 3); + assert(y() === 4); + + delete a; + delete b; + + assert(a === 1); + assert(b === 2); + + assert(x() === 1); + assert(y() === 4); +} +f()