diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 5a122075d4..8e528b8db6 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -716,7 +716,8 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ #endif /* !CONFIG_DISABLE_ES2015_CLASS */ } - ecma_value_t ret_value = vm_run (bytecode_data_p, + ecma_value_t ret_value = vm_run (ext_func_p, + bytecode_data_p, this_binding, local_env_p, ECMA_PARSE_NO_OPTS, @@ -779,7 +780,8 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ JERRY_ASSERT (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED)); } - ecma_value_t ret_value = vm_run (bytecode_data_p, + ecma_value_t ret_value = vm_run (NULL, + bytecode_data_p, arrow_func_p->this_binding, local_env_p, ECMA_PARSE_NO_OPTS, diff --git a/jerry-core/vm/vm-defines.h b/jerry-core/vm/vm-defines.h index 06e81528f0..6ac0c1fcc4 100644 --- a/jerry-core/vm/vm-defines.h +++ b/jerry-core/vm/vm-defines.h @@ -45,6 +45,7 @@ typedef const uint8_t *vm_instr_counter_t; */ typedef struct vm_frame_ctx_t { + const ecma_extended_object_t *func_obj_p; /**< currently executed fucntion */ const ecma_compiled_code_t *bytecode_header_p; /**< currently executed byte-code data */ uint8_t *byte_code_p; /**< current byte code pointer */ uint8_t *byte_code_start_p; /**< byte code start pointer */ diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 7c2cc8211d..6ace85aac6 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -224,7 +224,8 @@ vm_run_global (const ecma_compiled_code_t *bytecode_p) /**< pointer to bytecode { ecma_object_t *glob_obj_p = ecma_builtin_get_global (); - return vm_run (bytecode_p, + return vm_run (NULL, + bytecode_p, ecma_make_object_value (glob_obj_p), ecma_get_global_environment (), false, @@ -288,7 +289,8 @@ vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */ lex_env_p = strict_lex_env_p; } - ecma_value_t completion_value = vm_run (bytecode_data_p, + ecma_value_t completion_value = vm_run (NULL, + bytecode_data_p, this_binding, lex_env_p, parse_opts, @@ -733,8 +735,16 @@ vm_init_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ else { is_immutable_binding = (self_reference == literal_start_p[value_index]); - lit_value = vm_construct_literal_object (frame_ctx_p, - literal_start_p[value_index]); + if (is_immutable_binding) + { + lit_value = ecma_make_object_value ((ecma_object_t *) frame_ctx_p->func_obj_p); + ecma_ref_object ((ecma_object_t *) frame_ctx_p->func_obj_p); + } + else + { + lit_value = vm_construct_literal_object (frame_ctx_p, + literal_start_p[value_index]); + } } if (literal_index < register_end) @@ -3471,7 +3481,8 @@ vm_execute (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ * @return ecma value */ ecma_value_t -vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data header */ +vm_run (const ecma_extended_object_t *func_obj_p, /**< function object */ + const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data header */ ecma_value_t this_binding_value, /**< value of 'ThisBinding' */ ecma_object_t *lex_env_p, /**< lexical environment to use */ uint32_t parse_opts, /**< ecma_parse_opts_t option bits */ @@ -3502,7 +3513,7 @@ vm_run (const ecma_compiled_code_t *bytecode_header_p, /**< byte-code data heade frame_ctx.literal_start_p = literal_p; literal_p += args_p->literal_end; } - + frame_ctx.func_obj_p = func_obj_p; frame_ctx.bytecode_header_p = bytecode_header_p; frame_ctx.byte_code_p = (uint8_t *) literal_p; frame_ctx.byte_code_start_p = (uint8_t *) literal_p; diff --git a/jerry-core/vm/vm.h b/jerry-core/vm/vm.h index 92f248c263..3dc02fefa2 100644 --- a/jerry-core/vm/vm.h +++ b/jerry-core/vm/vm.h @@ -353,7 +353,8 @@ typedef enum ecma_value_t vm_run_global (const ecma_compiled_code_t *bytecode_p); ecma_value_t vm_run_eval (ecma_compiled_code_t *bytecode_data_p, uint32_t parse_opts); -ecma_value_t vm_run (const ecma_compiled_code_t *bytecode_header_p, ecma_value_t this_binding_value, +ecma_value_t vm_run (const ecma_extended_object_t *func_obj_p, + const ecma_compiled_code_t *bytecode_header_p, ecma_value_t this_binding_value, ecma_object_t *lex_env_p, uint32_t parse_opts, const ecma_value_t *arg_list_p, ecma_length_t arg_list_len); diff --git a/tests/jerry/function-self-ref.js b/tests/jerry/function-self-ref.js new file mode 100644 index 0000000000..00d8a48c1d --- /dev/null +++ b/tests/jerry/function-self-ref.js @@ -0,0 +1,28 @@ +// 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 foo = function bar() { + assert(foo === bar); +}; +foo(); + +var globalFunc; +function nest(func) { + globalFunc = func; + func(); +} + +nest(function bar() { + assert(globalFunc === bar); +});