aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Herczeg <zherczeg.u-szeged@partner.samsung.com>2018-07-11 02:35:44 +0200
committeryichoi <duddlf.choi@samsung.com>2018-07-11 09:35:44 +0900
commit04dcefe0879b51ef9acdef6aeb7b3c0dd2cb3b5b (patch)
treeb2f413431ddc8d443486fda822393aaba1f1ebf2
parent50daa39ee895f231e8e8b62b3fe78332c4603ad2 (diff)
Rework function call. (#2414)
Furthermore add a construct flag, which disallows calling certain functions without new. Constructing bound arrow functions correctly throws error now. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
-rw-r--r--jerry-core/ecma/builtin-objects/ecma-builtins.c16
-rw-r--r--jerry-core/ecma/builtin-objects/ecma-builtins.h2
-rw-r--r--jerry-core/ecma/operations/ecma-function-object.c458
-rw-r--r--tests/jerry/es2015/regression-test-issue-2414.js26
4 files changed, 295 insertions, 207 deletions
diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c
index 665598b7..a79a9f98 100644
--- a/jerry-core/ecma/builtin-objects/ecma-builtins.c
+++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c
@@ -205,6 +205,22 @@ ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on
} /* ecma_builtin_get */
/**
+ * Get reference to the global object
+ *
+ * Note:
+ * Does not increase the reference counter.
+ *
+ * @return pointer to the global object
+ */
+inline ecma_object_t * JERRY_ATTR_ALWAYS_INLINE
+ecma_builtin_get_global (void)
+{
+ JERRY_ASSERT (JERRY_CONTEXT (ecma_builtin_objects)[ECMA_BUILTIN_ID_GLOBAL] != NULL);
+
+ return JERRY_CONTEXT (ecma_builtin_objects)[ECMA_BUILTIN_ID_GLOBAL];
+} /* ecma_builtin_get_global */
+
+/**
* Checks whether the given function is a built-in routine
*
* @return true - if the function object is a built-in routine
diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.h b/jerry-core/ecma/builtin-objects/ecma-builtins.h
index 11ac1dc4..593843b8 100644
--- a/jerry-core/ecma/builtin-objects/ecma-builtins.h
+++ b/jerry-core/ecma/builtin-objects/ecma-builtins.h
@@ -96,6 +96,8 @@ bool
ecma_builtin_is (ecma_object_t *obj_p, ecma_builtin_id_t builtin_id);
ecma_object_t *
ecma_builtin_get (ecma_builtin_id_t builtin_id);
+ecma_object_t *
+ecma_builtin_get_global (void);
bool
ecma_builtin_function_is_routine (ecma_object_t *func_obj_p);
diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c
index 63b6508c..04597662 100644
--- a/jerry-core/ecma/operations/ecma-function-object.c
+++ b/jerry-core/ecma/operations/ecma-function-object.c
@@ -403,6 +403,47 @@ ecma_op_function_has_instance (ecma_object_t *func_obj_p, /**< Function object *
} /* ecma_op_function_has_instance */
/**
+ * Sets the construct flag in the arguments list pointer.
+ *
+ * @return arguments list pointer with the construct flag
+ */
+static inline const ecma_value_t * JERRY_ATTR_ALWAYS_INLINE
+ecma_op_function_set_construct_flag (const ecma_value_t *arguments_list_p) /**< original arguments list pointer */
+{
+ /* Any ecma value list must be aligned to 4 byte. */
+ JERRY_ASSERT ((((uintptr_t) arguments_list_p) & 0x3) == 0);
+
+ /* Currently it returns with the same pointer. When classes
+ * will be enabled, it will set the lowest bit. */
+ return arguments_list_p;
+} /* ecma_op_function_set_construct_flag */
+
+/**
+ * Clears the construct flag in the arguments list pointer.
+ *
+ * @return arguments list pointer without the construct flag
+ */
+static inline const ecma_value_t * JERRY_ATTR_ALWAYS_INLINE
+ecma_op_function_clear_construct_flag (const ecma_value_t *arguments_list_p) /**< modified arguments list pointer */
+{
+ /* Currently it returns with the same pointer. When classes
+ * will be enabled, the lowest bit will be cleared. */
+ return arguments_list_p;
+} /* ecma_op_function_clear_construct_flag */
+
+/**
+ * Returns true if the construct flag is set.
+ *
+ * @return true, if construct flag is set, false otherwise
+ */
+static inline bool JERRY_ATTR_ALWAYS_INLINE
+ecma_op_function_has_construct_flag (const ecma_value_t *arguments_list_p) /**< modified arguments list pointer */
+{
+ JERRY_UNUSED (arguments_list_p);
+ return false;
+} /* ecma_op_function_has_construct_flag */
+
+/**
* [[Call]] implementation for Function objects,
* created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION)
* or 15.3.4.5 (ECMA_OBJECT_TYPE_BOUND_FUNCTION),
@@ -422,19 +463,25 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
&& !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_VALUE_EMPTY;
-
- if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION)
+ while (true)
{
- if (JERRY_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
+ ecma_object_type_t func_type = ecma_get_object_type (func_obj_p);
+
+ JERRY_ASSERT (func_type == ECMA_OBJECT_TYPE_FUNCTION
+ || !ecma_op_function_has_construct_flag (arguments_list_p));
+
+ if (func_type == ECMA_OBJECT_TYPE_FUNCTION)
{
+ if (JERRY_UNLIKELY (ecma_get_object_is_builtin (func_obj_p)))
+ {
+ JERRY_ASSERT (!ecma_op_function_has_construct_flag (arguments_list_p));
+
+ return ecma_builtin_dispatch_call (func_obj_p,
+ this_arg_value,
+ arguments_list_p,
+ arguments_list_len);
+ }
+
/* Entering Function Code (ECMA-262 v5, 10.4.3) */
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p;
@@ -442,7 +489,8 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
ext_func_p->u.function.scope_cp);
/* 8. */
- ecma_value_t this_binding;
+ ecma_value_t this_binding = this_arg_value;
+ bool free_this_binding = false;
bool is_strict;
bool is_no_lex_env;
@@ -452,24 +500,26 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
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))
+ if (!is_strict)
{
- /* 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);
+ if (ecma_is_value_undefined (this_binding)
+ || ecma_is_value_null (this_binding))
+ {
+ /* 2. */
+ this_binding = ecma_make_object_value (ecma_builtin_get_global ());
+ }
+ else if (!ecma_is_value_object (this_binding))
+ {
+ /* 3., 4. */
+ this_binding = ecma_op_to_object (this_binding);
+ free_this_binding = true;
- JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (this_binding));
+ JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (this_binding));
+ }
}
+ arguments_list_p = ecma_op_function_clear_construct_flag (arguments_list_p);
+
/* 5. */
ecma_object_t *local_env_p;
if (is_no_lex_env)
@@ -489,84 +539,85 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
}
}
- ret_value = vm_run (bytecode_data_p,
- this_binding,
- local_env_p,
- false,
- arguments_list_p,
- arguments_list_len);
+ ecma_value_t 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);
+ if (JERRY_UNLIKELY (free_this_binding))
+ {
+ ecma_free_value (this_binding);
+ }
+
+ return ret_value;
+ }
+ else if (func_type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
+ {
+ ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p;
+
+ ecma_value_t ret_value = ext_func_obj_p->u.external_handler_cb (ecma_make_object_value (func_obj_p),
+ this_arg_value,
+ arguments_list_p,
+ arguments_list_len);
+
+ if (JERRY_UNLIKELY (ecma_is_value_error_reference (ret_value)))
+ {
+ JERRY_CONTEXT (error_value) = ecma_clear_error_reference (ret_value, true);
+ return ECMA_VALUE_ERROR;
+ }
+
+#ifdef JERRY_DEBUGGER
+ JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN);
+#endif /* JERRY_DEBUGGER */
+ return ret_value;
}
- }
#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
- else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_ARROW_FUNCTION)
- {
- /* Entering Function Code (ES2015, 9.2.1) */
- ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_obj_p;
+ else if (func_type == ECMA_OBJECT_TYPE_ARROW_FUNCTION)
+ {
+ /* Entering Function Code (ES2015, 9.2.1) */
+ ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_obj_p;
- ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t,
- arrow_func_p->scope_cp);
+ ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t,
+ arrow_func_p->scope_cp);
- bool is_no_lex_env;
+ bool is_no_lex_env;
- const ecma_compiled_code_t *bytecode_data_p = ecma_op_arrow_function_get_compiled_code (arrow_func_p);
+ const ecma_compiled_code_t *bytecode_data_p = ecma_op_arrow_function_get_compiled_code (arrow_func_p);
- is_no_lex_env = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED) ? true : false;
+ is_no_lex_env = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED) ? true : false;
- 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);
+ ecma_object_t *local_env_p = scope_p;
- JERRY_ASSERT (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED));
- }
+ if (!is_no_lex_env)
+ {
+ local_env_p = ecma_create_decl_lex_env (scope_p);
- ret_value = vm_run (bytecode_data_p,
- arrow_func_p->this_binding,
- local_env_p,
- false,
- arguments_list_p,
- arguments_list_len);
+ JERRY_ASSERT (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED));
+ }
- if (!is_no_lex_env)
- {
- ecma_deref_object (local_env_p);
- }
- }
-#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
- else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
- {
- ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p;
+ ecma_value_t ret_value = vm_run (bytecode_data_p,
+ arrow_func_p->this_binding,
+ local_env_p,
+ false,
+ arguments_list_p,
+ arguments_list_len);
- ret_value = ext_func_obj_p->u.external_handler_cb (ecma_make_object_value (func_obj_p),
- this_arg_value,
- arguments_list_p,
- arguments_list_len);
+ if (!is_no_lex_env)
+ {
+ ecma_deref_object (local_env_p);
+ }
- if (JERRY_UNLIKELY (ecma_is_value_error_reference (ret_value)))
- {
- JERRY_CONTEXT (error_value) = ecma_clear_error_reference (ret_value, true);
- ret_value = ECMA_VALUE_ERROR;
+ return ret_value;
}
- else
- {
-#ifdef JERRY_DEBUGGER
- JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN);
-#endif /* JERRY_DEBUGGER */
- }
- }
- else
- {
+#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
+
JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);
JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL;
@@ -579,55 +630,49 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
/* 4. */
ecma_value_t args_len_or_this = ext_function_p->u.bound_function.args_len_or_this;
- ecma_value_t bound_this_value;
ecma_length_t args_length;
if (!ecma_is_value_integer_number (args_len_or_this))
{
- bound_this_value = args_len_or_this;
+ this_arg_value = args_len_or_this;
args_length = 1;
}
else
{
- bound_this_value = *(ecma_value_t *) (ext_function_p + 1);
+ this_arg_value = *(ecma_value_t *) (ext_function_p + 1);
args_length = (ecma_length_t) ecma_get_integer_from_value (args_len_or_this);
}
JERRY_ASSERT (args_length > 0);
- if (args_length > 1)
+ if (args_length == 1)
{
- args_length--;
- ecma_length_t merged_args_list_len = args_length + arguments_list_len;
+ func_obj_p = target_func_obj_p;
+ continue;
+ }
- JMEM_DEFINE_LOCAL_ARRAY (merged_args_list_p, merged_args_list_len, ecma_value_t);
+ args_length--;
- ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
+ ecma_length_t merged_args_list_len = args_length + arguments_list_len;
+ ecma_value_t ret_value;
- memcpy (merged_args_list_p, args_p + 1, args_length * sizeof (ecma_value_t));
- memcpy (merged_args_list_p + args_length, arguments_list_p, arguments_list_len * sizeof (ecma_value_t));
+ JMEM_DEFINE_LOCAL_ARRAY (merged_args_list_p, merged_args_list_len, ecma_value_t);
- /* 5. */
- ret_value = ecma_op_function_call (target_func_obj_p,
- bound_this_value,
- merged_args_list_p,
- merged_args_list_len);
+ ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
- JMEM_FINALIZE_LOCAL_ARRAY (merged_args_list_p);
- }
- else
- {
- /* 5. */
- ret_value = ecma_op_function_call (target_func_obj_p,
- bound_this_value,
- arguments_list_p,
- arguments_list_len);
- }
- }
+ memcpy (merged_args_list_p, args_p + 1, args_length * sizeof (ecma_value_t));
+ memcpy (merged_args_list_p + args_length, arguments_list_p, arguments_list_len * sizeof (ecma_value_t));
+
+ /* 5. */
+ ret_value = ecma_op_function_call (target_func_obj_p,
+ this_arg_value,
+ merged_args_list_p,
+ merged_args_list_len);
- JERRY_ASSERT (!ecma_is_value_empty (ret_value));
+ JMEM_FINALIZE_LOCAL_ARRAY (merged_args_list_p);
- return ret_value;
+ return ret_value;
+ }
} /* ecma_op_function_call */
/**
@@ -639,27 +684,28 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
* Returned value must be freed with ecma_free_value
*/
static ecma_value_t
-ecma_op_function_construct_simple_or_external (ecma_object_t *func_obj_p, /**< Function object */
- const ecma_value_t *arguments_list_p, /**< arguments list */
- ecma_length_t arguments_list_len) /**< length of arguments list */
+ecma_op_function_construct_ecma_or_external (ecma_object_t *func_obj_p, /**< Function object */
+ const ecma_value_t *arguments_list_p, /**< arguments list */
+ ecma_length_t arguments_list_len) /**< length of arguments list */
{
JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION
|| ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
- ecma_value_t ret_value = ECMA_VALUE_EMPTY;
-
/* 5. */
- ECMA_TRY_CATCH (func_obj_prototype_prop_value,
- ecma_op_object_get_by_magic_id (func_obj_p,
- LIT_MAGIC_STRING_PROTOTYPE),
- ret_value);
+ ecma_value_t prototype_prop_value = ecma_op_object_get_by_magic_id (func_obj_p,
+ LIT_MAGIC_STRING_PROTOTYPE);
+
+ if (ECMA_IS_VALUE_ERROR (prototype_prop_value))
+ {
+ return prototype_prop_value;
+ }
/* 1., 2., 4. */
ecma_object_t *obj_p;
- if (ecma_is_value_object (func_obj_prototype_prop_value))
+ if (ecma_is_value_object (prototype_prop_value))
{
/* 6. */
- obj_p = ecma_create_object (ecma_get_object_from_value (func_obj_prototype_prop_value),
+ obj_p = ecma_create_object (ecma_get_object_from_value (prototype_prop_value),
0,
ECMA_OBJECT_TYPE_GENERAL);
}
@@ -673,6 +719,8 @@ ecma_op_function_construct_simple_or_external (ecma_object_t *func_obj_p, /**< F
ecma_deref_object (prototype_p);
}
+ ecma_free_value (prototype_prop_value);
+
/* 3. */
/*
* [[Class]] property of ECMA_OBJECT_TYPE_GENERAL type objects
@@ -683,33 +731,29 @@ ecma_op_function_construct_simple_or_external (ecma_object_t *func_obj_p, /**< F
*/
/* 8. */
- ECMA_TRY_CATCH (call_completion,
- ecma_op_function_call (func_obj_p,
- ecma_make_object_value (obj_p),
- arguments_list_p,
- arguments_list_len),
- ret_value);
+ ecma_value_t this_obj = ecma_make_object_value (obj_p);
+ ecma_value_t ret_value;
- /* 9. */
- if (ecma_is_value_object (call_completion))
- {
- ret_value = ecma_copy_value (call_completion);
- }
- else
+ if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION)
{
- /* 10. */
- ecma_ref_object (obj_p);
- ret_value = ecma_make_object_value (obj_p);
+ arguments_list_p = ecma_op_function_set_construct_flag (arguments_list_p);
}
- ECMA_FINALIZE (call_completion);
+ ret_value = ecma_op_function_call (func_obj_p,
+ this_obj,
+ arguments_list_p,
+ arguments_list_len);
- ecma_deref_object (obj_p);
-
- ECMA_FINALIZE (func_obj_prototype_prop_value);
+ /* 9. */
+ if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value))
+ {
+ ecma_deref_object (obj_p);
+ return ret_value;
+ }
- return ret_value;
-} /* ecma_op_function_construct_simple_or_external */
+ ecma_fast_free_value (ret_value);
+ return this_obj;
+} /* ecma_op_function_construct_ecma_or_external */
/**
* [[Construct]] implementation:
@@ -727,92 +771,92 @@ 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));
- JERRY_ASSERT (ecma_is_constructor (ecma_make_object_value (func_obj_p)));
-
- ecma_value_t ret_value = ECMA_VALUE_EMPTY;
- if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION)
+ while (true)
{
- if (JERRY_UNLIKELY (ecma_get_object_is_builtin (func_obj_p)
- && !ecma_builtin_function_is_routine (func_obj_p)))
+ switch (ecma_get_object_type (func_obj_p))
{
- ret_value = ecma_builtin_dispatch_construct (func_obj_p,
- arguments_list_p,
- arguments_list_len);
- }
- else
- {
- ret_value = ecma_op_function_construct_simple_or_external (func_obj_p,
- arguments_list_p,
- arguments_list_len);
+ case ECMA_OBJECT_TYPE_FUNCTION:
+ {
+ if (JERRY_UNLIKELY (ecma_get_object_is_builtin (func_obj_p)))
+ {
+ if (ecma_builtin_function_is_routine (func_obj_p))
+ {
+ return ecma_raise_type_error (ECMA_ERR_MSG ("Built-in routines have no constructor."));
+ }
+
+ return ecma_builtin_dispatch_construct (func_obj_p,
+ arguments_list_p,
+ arguments_list_len);
+ }
+ /* FALLTHRU */
+ }
+ case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
+ {
+ return ecma_op_function_construct_ecma_or_external (func_obj_p,
+ arguments_list_p,
+ arguments_list_len);
+ }
+#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
+ case ECMA_OBJECT_TYPE_ARROW_FUNCTION:
+ {
+ return ecma_raise_type_error (ECMA_ERR_MSG ("Arrow functions have no constructor."));
+ }
+#endif /* CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
+ default:
+ {
+ break;
+ }
}
- }
- else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
- {
- ret_value = ecma_op_function_construct_simple_or_external (func_obj_p,
- arguments_list_p,
- arguments_list_len);
- }
- else
- {
+
JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION);
- /* 1. */
+ /* 1-3. */
ecma_extended_object_t *ext_function_p = (ecma_extended_object_t *) func_obj_p;
ecma_object_t *target_func_obj_p;
target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
ext_function_p->u.bound_function.target_function);
- /* 2. */
- if (!ecma_is_constructor (ecma_make_object_value (target_func_obj_p)))
+ /* 4. */
+ ecma_value_t args_len_or_this = ext_function_p->u.bound_function.args_len_or_this;
+
+ ecma_length_t args_length = 1;
+
+ if (ecma_is_value_integer_number (args_len_or_this))
{
- ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Expected a constructor."));
+ args_length = (ecma_length_t) ecma_get_integer_from_value (args_len_or_this);
}
- else
- {
- /* 4. */
- ecma_value_t args_len_or_this = ext_function_p->u.bound_function.args_len_or_this;
- ecma_length_t args_length = 1;
+ JERRY_ASSERT (args_length > 0);
- if (ecma_is_value_integer_number (args_len_or_this))
- {
- args_length = (ecma_length_t) ecma_get_integer_from_value (args_len_or_this);
- }
+ if (args_length == 1)
+ {
+ /* 5. */
+ func_obj_p = target_func_obj_p;
+ continue;
+ }
- JERRY_ASSERT (args_length > 0);
+ ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
+ ecma_value_t ret_value;
- if (args_length > 1)
- {
- ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
+ args_length--;
+ ecma_length_t merged_args_list_len = args_length + arguments_list_len;
- args_length--;
- ecma_length_t merged_args_list_len = args_length + arguments_list_len;
+ JMEM_DEFINE_LOCAL_ARRAY (merged_args_list_p, merged_args_list_len, ecma_value_t);
- JMEM_DEFINE_LOCAL_ARRAY (merged_args_list_p, merged_args_list_len, ecma_value_t);
+ memcpy (merged_args_list_p, args_p + 1, args_length * sizeof (ecma_value_t));
+ memcpy (merged_args_list_p + args_length, arguments_list_p, arguments_list_len * sizeof (ecma_value_t));
- memcpy (merged_args_list_p, args_p + 1, args_length * sizeof (ecma_value_t));
- memcpy (merged_args_list_p + args_length, arguments_list_p, arguments_list_len * sizeof (ecma_value_t));
+ /* 5. */
+ ret_value = ecma_op_function_construct (target_func_obj_p,
+ merged_args_list_p,
+ merged_args_list_len);
- /* 5. */
- ret_value = ecma_op_function_construct (target_func_obj_p,
- merged_args_list_p,
- merged_args_list_len);
+ JMEM_FINALIZE_LOCAL_ARRAY (merged_args_list_p);
- JMEM_FINALIZE_LOCAL_ARRAY (merged_args_list_p);
- }
- else
- {
- /* 5. */
- ret_value = ecma_op_function_construct (target_func_obj_p,
- arguments_list_p,
- arguments_list_len);
- }
- }
+ return ret_value;
}
-
- return ret_value;
} /* ecma_op_function_construct */
/**
diff --git a/tests/jerry/es2015/regression-test-issue-2414.js b/tests/jerry/es2015/regression-test-issue-2414.js
new file mode 100644
index 00000000..75be3e6e
--- /dev/null
+++ b/tests/jerry/es2015/regression-test-issue-2414.js
@@ -0,0 +1,26 @@
+// 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.
+
+try {
+ // By default bound functions always support new operator.
+ // However, arrow functions must throw an error even in this case.
+
+ var f = (() => 1).bind();
+
+ new f;
+
+ assert(false);
+} catch (e) {
+ assert(e instanceof TypeError);
+}