/** * [[Call]] implementation for Function objects, * created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION) * or 15.3.4.5 (ECMA_OBJECT_TYPE_BOUND_FUNCTION), * and for built-in Function objects * from section 15 (ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION). * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ ecma_value_t this_arg_value, /**< 'this' argument's value */ const ecma_value_t* arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< length of arguments list */ { JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); JERRY_ASSERT (ecma_op_is_callable (ecma_make_object_value (func_obj_p))); JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) { if (unlikely (ecma_get_object_is_builtin (func_obj_p))) { ret_value = ecma_builtin_dispatch_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); } else { /* Entering Function Code (ECMA-262 v5, 10.4.3) */ ecma_property_t *scope_prop_p = ecma_get_internal_property (func_obj_p, ECMA_INTERNAL_PROPERTY_SCOPE); ecma_property_t *bytecode_prop_p = ecma_get_internal_property (func_obj_p, ECMA_INTERNAL_PROPERTY_CODE_BYTECODE); ecma_property_t *code_prop_p = ecma_get_internal_property (func_obj_p, ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET); ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, scope_prop_p->u.internal_property.value); uint32_t code_prop_value = code_prop_p->u.internal_property.value; // 8. bool is_strict; bool do_instantiate_args_obj; const vm_instr_t *instrs_p = MEM_CP_GET_POINTER (const vm_instr_t, bytecode_prop_p->u.internal_property.value); vm_instr_counter_t code_first_instr_pos = ecma_unpack_code_internal_property_value (code_prop_value, &is_strict, &do_instantiate_args_obj); ecma_value_t this_binding; // 1. if (is_strict) { this_binding = ecma_copy_value (this_arg_value, true); } else if (ecma_is_value_undefined (this_arg_value) || ecma_is_value_null (this_arg_value)) { // 2. this_binding = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL)); } else { // 3., 4. ecma_completion_value_t completion = ecma_op_to_object (this_arg_value); JERRY_ASSERT (ecma_is_completion_value_normal (completion)); this_binding = ecma_get_completion_value_value (completion); } // 5. ecma_object_t *local_env_p = ecma_create_decl_lex_env (scope_p); // 9. ECMA_TRY_CATCH (args_var_declaration_ret, ecma_function_call_setup_args_variables (func_obj_p, local_env_p, arguments_list_p, arguments_list_len, is_strict, do_instantiate_args_obj), ret_value); ecma_completion_value_t completion = vm_run_from_pos (instrs_p, code_first_instr_pos, this_binding, local_env_p, is_strict, false); if (ecma_is_completion_value_return (completion)) { ret_value = ecma_make_normal_completion_value (ecma_get_completion_value_value (completion)); } else { ret_value = completion; } ECMA_FINALIZE (args_var_declaration_ret); ecma_deref_object (local_env_p); ecma_free_value (this_binding, true); } } else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)
/** * [[Call]] implementation for Function objects, * created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION) * or 15.3.4.5 (ECMA_OBJECT_TYPE_BOUND_FUNCTION), * and for built-in Function objects * from section 15 (ECMA_OBJECT_TYPE_FUNCTION). * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ ecma_value_t this_arg_value, /**< 'this' argument's value */ const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< length of arguments list */ { JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); JERRY_ASSERT (ecma_op_is_callable (ecma_make_object_value (func_obj_p))); ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) { if (unlikely (ecma_get_object_is_builtin (func_obj_p))) { ret_value = ecma_builtin_dispatch_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); } else { /* Entering Function Code (ECMA-262 v5, 10.4.3) */ ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; ecma_object_t *scope_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, ext_func_p->u.function.scope_cp); // 8. ecma_value_t this_binding; bool is_strict; bool is_no_lex_env; const ecma_compiled_code_t *bytecode_data_p; bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t, ext_func_p->u.function.bytecode_cp); is_strict = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) ? true : false; is_no_lex_env = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED) ? true : false; // 1. if (is_strict) { this_binding = ecma_copy_value (this_arg_value); } else if (ecma_is_value_undefined (this_arg_value) || ecma_is_value_null (this_arg_value)) { // 2. this_binding = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL)); } else { // 3., 4. this_binding = ecma_op_to_object (this_arg_value); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (this_binding)); } // 5. ecma_object_t *local_env_p; if (is_no_lex_env) { local_env_p = scope_p; } else { local_env_p = ecma_create_decl_lex_env (scope_p); if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED) { ecma_op_create_arguments_object (func_obj_p, local_env_p, arguments_list_p, arguments_list_len, bytecode_data_p); } } ret_value = vm_run (bytecode_data_p, this_binding, local_env_p, false, arguments_list_p, arguments_list_len); if (!is_no_lex_env) { ecma_deref_object (local_env_p); } ecma_free_value (this_binding); } } else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
} else { ret_value = completion; } ECMA_FINALIZE (args_var_declaration_ret); ecma_deref_object (local_env_p); ecma_free_value (this_binding, true); } } else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) { ret_value = ecma_builtin_dispatch_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); } else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION) { ecma_external_pointer_t handler_p; bool is_retrieved = ecma_get_external_pointer_value (func_obj_p, ECMA_INTERNAL_PROPERTY_NATIVE_CODE, &handler_p); JERRY_ASSERT (is_retrieved); ret_value = jerry_dispatch_external_function (func_obj_p, handler_p, this_arg_value, arguments_list_p, arguments_list_len);