aboutsummaryrefslogtreecommitdiff
path: root/jerry-core/ecma
diff options
context:
space:
mode:
Diffstat (limited to 'jerry-core/ecma')
-rw-r--r--jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.c15
-rw-r--r--jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c36
-rw-r--r--jerry-core/ecma/operations/ecma-async-generator-object.c25
-rw-r--r--jerry-core/ecma/operations/ecma-function-object.c354
-rw-r--r--jerry-core/ecma/operations/ecma-function-object.h7
-rw-r--r--jerry-core/ecma/operations/ecma-iterator-object.c33
-rw-r--r--jerry-core/ecma/operations/ecma-objects.c12
-rw-r--r--jerry-core/ecma/operations/ecma-proxy-object.c6
8 files changed, 256 insertions, 232 deletions
diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.c
index eb26c2ee..1c25e172 100644
--- a/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.c
+++ b/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.c
@@ -241,19 +241,8 @@ ecma_builtin_async_from_sync_iterator_prototype_do (ecma_async_from_sync_iterato
}
/* 8. */
- ecma_value_t call_result;
-
- if (!ecma_op_is_callable (method))
- {
- ecma_free_value (method);
- call_result = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_expected_a_function));
- }
- else
- {
- ecma_object_t *method_func_obj = ecma_get_object_from_value (method);
- call_result = ecma_op_function_call (method_func_obj, sync_iterator, &call_arg, arg_size);
- ecma_deref_object (method_func_obj);
- }
+ ecma_value_t call_result = ecma_op_function_validated_call (method, sync_iterator, &call_arg, arg_size);
+ ecma_free_value (method);
/* 9. */
if (ECMA_IS_VALUE_ERROR (ecma_op_if_abrupt_reject_promise (&call_result, capability_obj_p)))
diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c
index 377bc0fe..c1c09d65 100644
--- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c
+++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c
@@ -584,18 +584,10 @@ ecma_builtin_string_prototype_object_replace_helper (ecma_value_t this_value, /*
if (!ecma_is_value_undefined (replace_symbol) && !ecma_is_value_null (replace_symbol))
{
- if (!ecma_op_is_callable (replace_symbol))
- {
- ecma_free_value (replace_symbol);
- return ecma_raise_type_error (ECMA_ERR_MSG ("@@replace is not callable"));
- }
-
- ecma_object_t *replace_method = ecma_get_object_from_value (replace_symbol);
-
ecma_value_t arguments[] = { this_value, replace_value };
- ecma_value_t replace_result = ecma_op_function_call (replace_method, search_value, arguments, 2);
+ ecma_value_t replace_result = ecma_op_function_validated_call (replace_symbol, search_value, arguments, 2);
+ ecma_free_value (replace_symbol);
- ecma_deref_object (replace_method);
return replace_result;
}
}
@@ -800,16 +792,8 @@ ecma_builtin_string_prototype_object_search (ecma_value_t this_value, /**< this
if (!ecma_is_value_undefined (search_symbol) && !ecma_is_value_null (search_symbol))
{
- if (!ecma_op_is_callable (search_symbol))
- {
- ecma_free_value (search_symbol);
- return ecma_raise_type_error (ECMA_ERR_MSG ("@@search is not callable"));
- }
-
- ecma_object_t *search_method = ecma_get_object_from_value (search_symbol);
- ecma_value_t search_result = ecma_op_function_call (search_method, regexp_value, &this_value, 1);
-
- ecma_deref_object (search_method);
+ ecma_value_t search_result = ecma_op_function_validated_call (search_symbol, regexp_value, &this_value, 1);
+ ecma_free_value (search_symbol);
return search_result;
}
}
@@ -977,18 +961,10 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_value, /**< this a
if (!ecma_is_value_undefined (split_symbol) && !ecma_is_value_null (split_symbol))
{
- if (!ecma_op_is_callable (split_symbol))
- {
- ecma_free_value (split_symbol);
- return ecma_raise_type_error (ECMA_ERR_MSG ("@@split is not callable"));
- }
-
- ecma_object_t *split_method_p = ecma_get_object_from_value (split_symbol);
-
ecma_value_t arguments[] = { this_value, limit_value };
- ecma_value_t split_result = ecma_op_function_call (split_method_p, separator_value, arguments, 2);
+ ecma_value_t split_result = ecma_op_function_validated_call (split_symbol, separator_value, arguments, 2);
+ ecma_free_value (split_symbol);
- ecma_deref_object (split_method_p);
return split_result;
}
}
diff --git a/jerry-core/ecma/operations/ecma-async-generator-object.c b/jerry-core/ecma/operations/ecma-async-generator-object.c
index bec4c9aa..446e9cc9 100644
--- a/jerry-core/ecma/operations/ecma-async-generator-object.c
+++ b/jerry-core/ecma/operations/ecma-async-generator-object.c
@@ -97,29 +97,21 @@ ecma_async_generator_enqueue (vm_executable_object_t *async_generator_object_p,
static ecma_value_t
ecma_async_yield_call (ecma_value_t function, /**< function (takes reference) */
vm_executable_object_t *async_generator_object_p, /**< async generator */
- ecma_value_t argument, /**< argument passed to the function */
- const char *error_msg_p) /**< error message when the function is not callable */
+ ecma_value_t argument) /**< argument passed to the function */
{
- if (!ecma_is_value_object (function) || !ecma_op_is_callable (function))
- {
- ecma_free_value (function);
- return ecma_raise_type_error (error_msg_p);
- }
-
- ecma_object_t *return_obj_p = ecma_get_object_from_value (function);
ecma_value_t iterator = async_generator_object_p->iterator;
ecma_value_t result;
if (argument == ECMA_VALUE_EMPTY)
{
- result = ecma_op_function_call (return_obj_p, iterator, NULL, 0);
+ result = ecma_op_function_validated_call (function, iterator, NULL, 0);
}
else
{
- result = ecma_op_function_call (return_obj_p, iterator, &argument, 1);
+ result = ecma_op_function_validated_call (function, iterator, &argument, 1);
}
- ecma_deref_object (return_obj_p);
+ ecma_free_value (function);
if (ECMA_IS_VALUE_ERROR (result))
{
@@ -155,8 +147,7 @@ ecma_async_yield_throw (vm_executable_object_t *async_generator_object_p, /**< a
result = ecma_async_yield_call (result,
async_generator_object_p,
- ECMA_VALUE_EMPTY,
- ECMA_ERR_MSG ("Iterator 'return' is not callable"));
+ ECMA_VALUE_EMPTY);
if (ECMA_IS_VALUE_ERROR (result))
{
@@ -169,8 +160,7 @@ ecma_async_yield_throw (vm_executable_object_t *async_generator_object_p, /**< a
result = ecma_async_yield_call (result,
async_generator_object_p,
- value,
- ECMA_ERR_MSG ("Iterator 'throw' is not callable"));
+ value);
if (ECMA_IS_VALUE_ERROR (result))
{
@@ -419,8 +409,7 @@ ecma_await_continue (vm_executable_object_t *executable_object_p, /**< executabl
result = ecma_async_yield_call (result,
executable_object_p,
- value,
- ECMA_ERR_MSG ("Iterator 'return' is not callable"));
+ value);
ecma_free_value (value);
if (ECMA_IS_VALUE_ERROR (result))
diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c
index 7c34dc36..0850a417 100644
--- a/jerry-core/ecma/operations/ecma-function-object.c
+++ b/jerry-core/ecma/operations/ecma-function-object.c
@@ -90,6 +90,23 @@ ecma_op_function_form_name (ecma_string_t *prop_name_p, /**< property name */
} /* ecma_op_function_form_name */
#endif /* JERRY_ESNEXT */
+#if JERRY_BUILTIN_PROXY
+/**
+ * IsCallable operation for proxy object.
+ *
+ * @return true - if the given proxy object is callable;
+ * false - otherwise
+ */
+extern inline bool JERRY_ATTR_ALWAYS_INLINE
+ecma_op_proxy_object_is_callable (ecma_object_t *obj_p) /**< ecma object */
+{
+ JERRY_ASSERT (!ecma_is_lexical_environment (obj_p));
+ JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p));
+
+ return (obj_p->u2.prototype_cp & ECMA_PROXY_IS_CALLABLE) != 0;
+} /* ecma_op_proxy_object_is_callable */
+#endif /* JERRY_BUILTIN_PROXY */
+
/**
* IsCallable operation.
*
@@ -108,7 +125,7 @@ ecma_op_object_is_callable (ecma_object_t *obj_p) /**< ecma object */
#if JERRY_BUILTIN_PROXY
if (ECMA_OBJECT_TYPE_IS_PROXY (type))
{
- return (obj_p->u2.prototype_cp & ECMA_PROXY_IS_CALLABLE) != 0;
+ return ecma_op_proxy_object_is_callable (obj_p);
}
#endif /* JERRY_BUILTIN_PROXY */
@@ -1022,6 +1039,76 @@ ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, /**< construc
return proto_obj_p;
} /* ecma_op_get_prototype_from_constructor */
+#if JERRY_ESNEXT
+/**
+ * Perform a JavaScript class function object method call.
+ *
+ * The input function object should be a JavaScript class constructor
+ *
+ * @return the result of the function call.
+ */
+static ecma_value_t JERRY_ATTR_NOINLINE
+ecma_op_function_call_constructor (vm_frame_ctx_shared_args_t *shared_args_p, /**< shared data */
+ ecma_object_t *scope_p, /**< lexical environment to use */
+ ecma_value_t this_binding) /**< value of 'ThisBinding' */
+{
+ shared_args_p->header.status_flags |= VM_FRAME_CTX_SHARED_NON_ARROW_FUNC;
+
+ ecma_value_t ret_value;
+
+ if (JERRY_CONTEXT (current_new_target_p) == NULL)
+ {
+ ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor requires 'new'"));
+ goto exit;
+ }
+
+ ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) shared_args_p->header.function_object_p;
+ if (ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp))
+ {
+ this_binding = ECMA_VALUE_UNINITIALIZED;
+ }
+
+ ecma_op_create_environment_record (scope_p, this_binding, shared_args_p->header.function_object_p);
+
+#if JERRY_BUILTIN_REALMS
+ ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p);
+ JERRY_CONTEXT (global_object_p) = ecma_op_function_get_realm (shared_args_p->header.bytecode_header_p);
+#endif /* JERRY_BUILTIN_REALMS */
+
+ ret_value = vm_run (&shared_args_p->header, this_binding, scope_p);
+
+#if JERRY_BUILTIN_REALMS
+ JERRY_CONTEXT (global_object_p) = saved_global_object_p;
+#endif /* JERRY_BUILTIN_REALMS */
+
+ /* ECMAScript v6, 9.2.2.13 */
+ if (JERRY_UNLIKELY (this_binding == ECMA_VALUE_UNINITIALIZED))
+ {
+ if (!ECMA_IS_VALUE_ERROR (ret_value) && !ecma_is_value_object (ret_value))
+ {
+ if (!ecma_is_value_undefined (ret_value))
+ {
+ ecma_free_value (ret_value);
+ ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Derived constructors may only return object or undefined"));
+ }
+ else
+ {
+ ret_value = ecma_op_get_this_binding (scope_p);
+ }
+ }
+ }
+
+exit:
+ if (JERRY_UNLIKELY (shared_args_p->header.status_flags & VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV))
+ {
+ ecma_deref_object (scope_p);
+ }
+
+ return ret_value;
+} /* ecma_op_function_call_constructor */
+
+#endif /* JERRY_ESNEXT */
+
/**
* Perform a JavaScript function object method call.
*
@@ -1031,7 +1118,7 @@ ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, /**< construc
*/
static ecma_value_t
ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */
- ecma_value_t this_arg_value, /**< 'this' argument's value */
+ ecma_value_t this_binding, /**< 'this' argument's value */
const ecma_value_t *arguments_list_p, /**< arguments list */
uint32_t arguments_list_len) /**< length of arguments list */
{
@@ -1050,8 +1137,6 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */
ext_func_p->u.function.scope_cp);
/* 8. */
- ecma_value_t this_binding = this_arg_value;
-
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
uint16_t status_flags = bytecode_data_p->status_flags;
@@ -1061,29 +1146,50 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */
ecma_global_object_t *realm_p = ecma_op_function_get_realm (bytecode_data_p);
#endif /* JERRY_BUILTIN_REALMS */
- /* 1. */
-#if JERRY_ESNEXT
- if (JERRY_UNLIKELY (CBC_FUNCTION_IS_ARROW (status_flags)))
+ /* 5. */
+ if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED))
{
- ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_obj_p;
+ shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV;
+ scope_p = ecma_create_decl_lex_env (scope_p);
+ }
- if (ecma_is_value_undefined (arrow_func_p->new_target))
+ /* 1. */
+ switch (CBC_FUNCTION_GET_TYPE (status_flags))
+ {
+#if JERRY_ESNEXT
+ case CBC_FUNCTION_CONSTRUCTOR:
{
- JERRY_CONTEXT (current_new_target_p) = NULL;
+ return ecma_op_function_call_constructor (&shared_args, scope_p, this_binding);
}
- else
+ case CBC_FUNCTION_ARROW:
{
- JERRY_CONTEXT (current_new_target_p) = ecma_get_object_from_value (arrow_func_p->new_target);
+ ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_obj_p;
+
+ if (ecma_is_value_undefined (arrow_func_p->new_target))
+ {
+ JERRY_CONTEXT (current_new_target_p) = NULL;
+ }
+ else
+ {
+ JERRY_CONTEXT (current_new_target_p) = ecma_get_object_from_value (arrow_func_p->new_target);
+ }
+
+ this_binding = arrow_func_p->this_binding;
+ break;
}
- this_binding = arrow_func_p->this_binding;
- }
- else
- {
- shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_NON_ARROW_FUNC;
-#endif /* JERRY_ESNEXT */
- if (!(status_flags & CBC_CODE_FLAGS_STRICT_MODE))
+#endif /* JERRY_ESNEXT */
+ default:
{
+#if JERRY_ESNEXT
+ shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_NON_ARROW_FUNC;
+#endif /* JERRY_ESNEXT */
+
+ if (status_flags & CBC_CODE_FLAGS_STRICT_MODE)
+ {
+ break;
+ }
+
if (ecma_is_value_undefined (this_binding)
|| ecma_is_value_null (this_binding))
{
@@ -1102,73 +1208,21 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (this_binding));
}
+ break;
}
-#if JERRY_ESNEXT
- }
-#endif /* JERRY_ESNEXT */
-
- /* 5. */
- if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED))
- {
- shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV;
- scope_p = ecma_create_decl_lex_env (scope_p);
- }
-
- ecma_value_t ret_value;
-
-#if JERRY_ESNEXT
- if (JERRY_UNLIKELY (CBC_FUNCTION_GET_TYPE (status_flags) == CBC_FUNCTION_CONSTRUCTOR))
- {
- if (JERRY_CONTEXT (current_new_target_p) == NULL)
- {
- ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor requires 'new'"));
- goto exit;
- }
-
- ecma_value_t lexical_this = this_binding;
-
- if (ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp))
- {
- shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_HERITAGE_PRESENT;
- lexical_this = ECMA_VALUE_UNINITIALIZED;
- }
-
- ecma_op_create_environment_record (scope_p, lexical_this, func_obj_p);
}
-#endif /* JERRY_ESNEXT */
#if JERRY_BUILTIN_REALMS
ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p);
JERRY_CONTEXT (global_object_p) = realm_p;
#endif /* JERRY_BUILTIN_REALMS */
- ret_value = vm_run (&shared_args.header, this_binding, scope_p);
+ ecma_value_t ret_value = vm_run (&shared_args.header, this_binding, scope_p);
#if JERRY_BUILTIN_REALMS
JERRY_CONTEXT (global_object_p) = saved_global_object_p;
#endif /* JERRY_BUILTIN_REALMS */
-#if JERRY_ESNEXT
- /* ECMAScript v6, 9.2.2.13 */
- if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_HERITAGE_PRESENT))
- {
- if (!ECMA_IS_VALUE_ERROR (ret_value) && !ecma_is_value_object (ret_value))
- {
- if (!ecma_is_value_undefined (ret_value))
- {
- ecma_free_value (ret_value);
- ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Derived constructors may only return object or undefined"));
- }
- else
- {
- ret_value = ecma_op_get_this_binding (scope_p);
- }
- }
- }
-
-exit:
-#endif /* JERRY_ESNEXT */
-
if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV))
{
ecma_deref_object (scope_p);
@@ -1350,11 +1404,30 @@ ecma_op_function_call_bound (ecma_object_t *func_obj_p, /**< Function object */
} /* ecma_op_function_call_bound */
/**
- * [[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).
+ * General [[Call]] implementation
+ *
+ * @return ecma value
+ * Returned value must be freed with ecma_free_value
+ */
+extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
+ecma_op_function_validated_call (ecma_value_t callee, /**< callee */
+ ecma_value_t this_arg_value, /**< 'this' argument's value */
+ const ecma_value_t *arguments_list_p, /**< arguments list */
+ uint32_t arguments_list_len) /**< length of arguments list */
+{
+ if (!ecma_is_value_object (callee))
+ {
+ return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_expected_a_function));
+ }
+
+ return ecma_op_function_call (ecma_get_object_from_value (callee),
+ this_arg_value,
+ arguments_list_p,
+ arguments_list_len);
+} /* ecma_op_function_validated_call */
+
+/**
+ * General [[Call]] implementation
*
* @return ecma value
* Returned value must be freed with ecma_free_value
@@ -1367,21 +1440,12 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
{
JERRY_ASSERT (func_obj_p != NULL
&& !ecma_is_lexical_environment (func_obj_p));
- JERRY_ASSERT (ecma_op_object_is_callable (func_obj_p));
ECMA_CHECK_STACK_USAGE ();
- const ecma_object_type_t type = ecma_get_object_type (func_obj_p);
-
-#if JERRY_BUILTIN_PROXY
- if (ECMA_OBJECT_TYPE_IS_PROXY (type))
- {
- return ecma_proxy_object_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
- }
-#endif /* JERRY_BUILTIN_PROXY */
-
#if JERRY_ESNEXT
ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p);
+
if (JERRY_UNLIKELY (!(JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL)))
{
JERRY_CONTEXT (current_new_target_p) = NULL;
@@ -1390,27 +1454,47 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
ecma_value_t result;
- if (JERRY_LIKELY (type == ECMA_OBJECT_TYPE_FUNCTION))
- {
- result = ecma_op_function_call_simple (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
- }
- else if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)
- {
- result = ecma_op_function_call_native_built_in (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
- }
- else if (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION)
+ switch (ecma_get_object_type (func_obj_p))
{
- result = ecma_op_function_call_native (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
- }
+ case ECMA_OBJECT_TYPE_FUNCTION:
+ {
+ result = ecma_op_function_call_simple (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
+ break;
+ }
+ case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION:
+ {
+ result = ecma_op_function_call_native_built_in (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
+ break;
+ }
+#if JERRY_BUILTIN_PROXY
+ case ECMA_OBJECT_TYPE_PROXY:
+ {
+ result = ecma_proxy_object_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
+ break;
+ }
+#endif /* JERRY_BUILTIN_PROXY */
#if JERRY_ESNEXT
- else if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION))
- {
- result = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_class_constructor_new));
- }
+ case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION:
+ {
+ result = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_class_constructor_new));
+ break;
+ }
#endif /* JERRY_ESNEXT */
- else
- {
- result = ecma_op_function_call_bound (func_obj_p, arguments_list_p, arguments_list_len);
+ case ECMA_OBJECT_TYPE_NATIVE_FUNCTION:
+ {
+ result = ecma_op_function_call_native (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
+ break;
+ }
+ case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
+ {
+ result = ecma_op_function_call_bound (func_obj_p, arguments_list_p, arguments_list_len);
+ break;
+ }
+ default:
+ {
+ result = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_expected_a_function));
+ break;
+ }
}
#if JERRY_ESNEXT
@@ -1704,39 +1788,43 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
JERRY_ASSERT (func_obj_p != NULL
&& !ecma_is_lexical_environment (func_obj_p));
- const ecma_object_type_t type = ecma_get_object_type (func_obj_p);
-
- if (JERRY_LIKELY (type == ECMA_OBJECT_TYPE_FUNCTION))
- {
- return ecma_op_function_construct_simple (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
- }
-
- if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)
+ switch (ecma_get_object_type (func_obj_p))
{
- return ecma_op_function_construct_built_in (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
- }
-
+ case ECMA_OBJECT_TYPE_FUNCTION:
+ {
+ return ecma_op_function_construct_simple (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
+ }
+ case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION:
+ {
+ return ecma_op_function_construct_built_in (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
+ }
#if JERRY_BUILTIN_PROXY
- if (ECMA_OBJECT_TYPE_IS_PROXY (type))
- {
- return ecma_proxy_object_construct (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
- }
+ case ECMA_OBJECT_TYPE_PROXY:
+ {
+ return ecma_proxy_object_construct (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
+ }
#endif /* JERRY_BUILTIN_PROXY */
-
- if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION))
- {
- return ecma_op_function_construct_bound (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
- }
-
#if JERRY_ESNEXT
- if (type == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION)
- {
- return ecma_op_function_construct_constructor (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
- }
+ case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION:
+ {
+ return ecma_op_function_construct_constructor (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
+ }
#endif /* JERRY_ESNEXT */
+ case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
+ {
+ return ecma_op_function_construct_bound (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
+ }
+ case ECMA_OBJECT_TYPE_NATIVE_FUNCTION:
+ {
+ return ecma_op_function_construct_native (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
+ }
+ default:
+ {
+ JERRY_UNREACHABLE ();
+ }
+ }
- JERRY_ASSERT (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION);
- return ecma_op_function_construct_native (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
+ return ECMA_VALUE_UNDEFINED;
} /* ecma_op_function_construct */
/**
diff --git a/jerry-core/ecma/operations/ecma-function-object.h b/jerry-core/ecma/operations/ecma-function-object.h
index b2a710df..76c833a1 100644
--- a/jerry-core/ecma/operations/ecma-function-object.h
+++ b/jerry-core/ecma/operations/ecma-function-object.h
@@ -33,6 +33,9 @@ ecma_value_t ecma_op_function_form_name (ecma_string_t *prop_name_p, char *prefi
#endif /* JERRY_ESNEXT */
bool ecma_op_is_callable (ecma_value_t value);
+#if JERRY_BUILTIN_PROXY
+bool ecma_op_proxy_object_is_callable (ecma_object_t *obj_p);
+#endif /* JERRY_BUILTIN_PROXY */
bool ecma_op_object_is_callable (ecma_object_t *obj_p);
bool ecma_is_constructor (ecma_value_t value);
bool ecma_object_is_constructor (ecma_object_t *obj_p);
@@ -92,6 +95,10 @@ ecma_value_t
ecma_op_function_has_instance (ecma_object_t *func_obj_p, ecma_value_t value);
ecma_value_t
+ecma_op_function_validated_call (ecma_value_t callee, ecma_value_t this_arg_value,
+ const ecma_value_t *arguments_list_p, uint32_t arguments_list_len);
+
+ecma_value_t
ecma_op_function_call (ecma_object_t *func_obj_p, ecma_value_t this_arg_value,
const ecma_value_t *arguments_list_p, uint32_t arguments_list_len);
diff --git a/jerry-core/ecma/operations/ecma-iterator-object.c b/jerry-core/ecma/operations/ecma-iterator-object.c
index cf066d05..badb795e 100644
--- a/jerry-core/ecma/operations/ecma-iterator-object.c
+++ b/jerry-core/ecma/operations/ecma-iterator-object.c
@@ -248,18 +248,11 @@ ecma_op_get_iterator (ecma_value_t value, /**< value to get iterator from */
}
/* 3. */
- if (!ecma_op_is_callable (method))
- {
- ecma_free_value (method);
- return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator is not function"));
- }
-
- ecma_object_t *method_obj_p = ecma_get_object_from_value (method);
- ecma_value_t iterator = ecma_op_function_call (method_obj_p, value, NULL, 0);
+ ecma_value_t iterator = ecma_op_function_validated_call (method, value, NULL, 0);
if (use_default_method)
{
- ecma_deref_object (method_obj_p);
+ ecma_free_value (method);
}
/* 4. */
@@ -284,7 +277,7 @@ ecma_op_get_iterator (ecma_value_t value, /**< value to get iterator from */
return next_method;
}
- if (ecma_is_value_object (next_method) && ecma_op_is_callable (next_method))
+ if (ecma_op_is_callable (next_method))
{
*next_method_p = next_method;
}
@@ -363,15 +356,7 @@ ecma_op_iterator_return (ecma_value_t iterator, /**< iterator value */
return ecma_create_iter_result_object (value, ECMA_VALUE_TRUE);
}
- if (!ecma_op_is_callable (func_return))
- {
- ecma_free_value (func_return);
- return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'return' is not callable"));
- }
-
- ecma_object_t *return_obj_p = ecma_get_object_from_value (func_return);
-
- ecma_value_t result = ecma_op_function_call (return_obj_p, iterator, &value, 1);
+ ecma_value_t result = ecma_op_function_validated_call (func_return, iterator, &value, 1);
ecma_free_value (func_return);
return result;
@@ -415,15 +400,7 @@ ecma_op_iterator_throw (ecma_value_t iterator, /**< iterator value */
return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'throw' is not available"));
}
- if (!ecma_is_value_object (func_throw) || !ecma_op_is_callable (func_throw))
- {
- ecma_free_value (func_throw);
- return ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'throw' is not callable"));
- }
-
- ecma_object_t *return_obj_p = ecma_get_object_from_value (func_throw);
-
- ecma_value_t result = ecma_op_function_call (return_obj_p, iterator, &value, 1);
+ ecma_value_t result = ecma_op_function_validated_call (func_throw, iterator, &value, 1);
ecma_free_value (func_throw);
return result;
diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c
index b9b6f358..c096d1b1 100644
--- a/jerry-core/ecma/operations/ecma-objects.c
+++ b/jerry-core/ecma/operations/ecma-objects.c
@@ -3296,18 +3296,10 @@ ecma_op_invoke (ecma_value_t object, /**< Object value */
}
/* 4. */
- if (!ecma_op_is_callable (func))
- {
- ecma_free_value (func);
- ecma_deref_object (object_p);
- return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not callable"));
- }
-
- ecma_object_t *func_obj_p = ecma_get_object_from_value (func);
- ecma_value_t call_result = ecma_op_function_call (func_obj_p, this_arg, args_p, args_len);
+ ecma_value_t call_result = ecma_op_function_validated_call (func, this_arg, args_p, args_len);
+ ecma_free_value (func);
ecma_deref_object (object_p);
- ecma_deref_object (func_obj_p);
return call_result;
} /* ecma_op_invoke */
diff --git a/jerry-core/ecma/operations/ecma-proxy-object.c b/jerry-core/ecma/operations/ecma-proxy-object.c
index 4c22aae1..744805cb 100644
--- a/jerry-core/ecma/operations/ecma-proxy-object.c
+++ b/jerry-core/ecma/operations/ecma-proxy-object.c
@@ -1771,6 +1771,12 @@ ecma_proxy_object_call (ecma_object_t *obj_p, /**< proxy object */
uint32_t argc) /**< number of arguments */
{
JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p));
+
+ if (!ecma_op_proxy_object_is_callable (obj_p))
+ {
+ return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_expected_a_function));
+ }
+
ECMA_CHECK_STACK_USAGE ();
ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p;