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
This commit is contained in:
Zoltan Herczeg 2018-07-11 02:35:44 +02:00 committed by yichoi
parent 50daa39ee8
commit 04dcefe087
4 changed files with 313 additions and 225 deletions

View File

@ -204,6 +204,22 @@ ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on
return JERRY_CONTEXT (ecma_builtin_objects)[builtin_id]; return JERRY_CONTEXT (ecma_builtin_objects)[builtin_id];
} /* ecma_builtin_get */ } /* 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 * Checks whether the given function is a built-in routine
* *

View File

@ -96,6 +96,8 @@ bool
ecma_builtin_is (ecma_object_t *obj_p, ecma_builtin_id_t builtin_id); ecma_builtin_is (ecma_object_t *obj_p, ecma_builtin_id_t builtin_id);
ecma_object_t * ecma_object_t *
ecma_builtin_get (ecma_builtin_id_t builtin_id); ecma_builtin_get (ecma_builtin_id_t builtin_id);
ecma_object_t *
ecma_builtin_get_global (void);
bool bool
ecma_builtin_function_is_routine (ecma_object_t *func_obj_p); ecma_builtin_function_is_routine (ecma_object_t *func_obj_p);

View File

@ -402,6 +402,47 @@ ecma_op_function_has_instance (ecma_object_t *func_obj_p, /**< Function object *
return ecma_make_boolean_value (result); return ecma_make_boolean_value (result);
} /* ecma_op_function_has_instance */ } /* 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, * [[Call]] implementation for Function objects,
* created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION) * created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION)
@ -422,19 +463,25 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
&& !ecma_is_lexical_environment (func_obj_p)); && !ecma_is_lexical_environment (func_obj_p));
JERRY_ASSERT (ecma_op_is_callable (ecma_make_object_value (func_obj_p))); JERRY_ASSERT (ecma_op_is_callable (ecma_make_object_value (func_obj_p)));
ecma_value_t ret_value = ECMA_VALUE_EMPTY; while (true)
if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION)
{ {
if (JERRY_UNLIKELY (ecma_get_object_is_builtin (func_obj_p))) ecma_object_type_t func_type = ecma_get_object_type (func_obj_p);
{
ret_value = ecma_builtin_dispatch_call (func_obj_p, JERRY_ASSERT (func_type == ECMA_OBJECT_TYPE_FUNCTION
this_arg_value, || !ecma_op_function_has_construct_flag (arguments_list_p));
arguments_list_p,
arguments_list_len); if (func_type == ECMA_OBJECT_TYPE_FUNCTION)
}
else
{ {
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) */ /* Entering Function Code (ECMA-262 v5, 10.4.3) */
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; 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); ext_func_p->u.function.scope_cp);
/* 8. */ /* 8. */
ecma_value_t this_binding; ecma_value_t this_binding = this_arg_value;
bool free_this_binding = false;
bool is_strict; bool is_strict;
bool is_no_lex_env; 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; is_no_lex_env = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED) ? true : false;
/* 1. */ /* 1. */
if (is_strict) if (!is_strict)
{ {
this_binding = ecma_copy_value (this_arg_value); if (ecma_is_value_undefined (this_binding)
} || ecma_is_value_null (this_binding))
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_global ());
/* 2. */ }
this_binding = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL)); else if (!ecma_is_value_object (this_binding))
} {
else /* 3., 4. */
{ this_binding = ecma_op_to_object (this_binding);
/* 3., 4. */ free_this_binding = true;
this_binding = ecma_op_to_object (this_arg_value);
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. */ /* 5. */
ecma_object_t *local_env_p; ecma_object_t *local_env_p;
if (is_no_lex_env) 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, ecma_value_t ret_value = vm_run (bytecode_data_p,
this_binding, this_binding,
local_env_p, local_env_p,
false, false,
arguments_list_p, arguments_list_p,
arguments_list_len); arguments_list_len);
if (!is_no_lex_env) if (!is_no_lex_env)
{ {
ecma_deref_object (local_env_p); 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)
#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;
ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t,
arrow_func_p->scope_cp);
bool is_no_lex_env;
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;
ecma_object_t *local_env_p;
if (is_no_lex_env)
{ {
local_env_p = scope_p; ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p;
}
else
{
local_env_p = ecma_create_decl_lex_env (scope_p);
JERRY_ASSERT (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED)); 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);
ret_value = vm_run (bytecode_data_p, if (JERRY_UNLIKELY (ecma_is_value_error_reference (ret_value)))
arrow_func_p->this_binding, {
local_env_p, JERRY_CONTEXT (error_value) = ecma_clear_error_reference (ret_value, true);
false, return ECMA_VALUE_ERROR;
arguments_list_p, }
arguments_list_len);
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;
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);
ret_value = ECMA_VALUE_ERROR;
}
else
{
#ifdef JERRY_DEBUGGER #ifdef JERRY_DEBUGGER
JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN); JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN);
#endif /* JERRY_DEBUGGER */ #endif /* JERRY_DEBUGGER */
return ret_value;
} }
} #ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION
else 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);
bool is_no_lex_env;
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;
ecma_object_t *local_env_p = scope_p;
if (!is_no_lex_env)
{
local_env_p = ecma_create_decl_lex_env (scope_p);
JERRY_ASSERT (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_ARGUMENTS_NEEDED));
}
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);
if (!is_no_lex_env)
{
ecma_deref_object (local_env_p);
}
return ret_value;
}
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_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; 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. */ /* 4. */
ecma_value_t args_len_or_this = ext_function_p->u.bound_function.args_len_or_this; 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; ecma_length_t args_length;
if (!ecma_is_value_integer_number (args_len_or_this)) 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; args_length = 1;
} }
else 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); args_length = (ecma_length_t) ecma_get_integer_from_value (args_len_or_this);
} }
JERRY_ASSERT (args_length > 0); JERRY_ASSERT (args_length > 0);
if (args_length > 1) if (args_length == 1)
{ {
args_length--; func_obj_p = target_func_obj_p;
ecma_length_t merged_args_list_len = args_length + arguments_list_len; continue;
JMEM_DEFINE_LOCAL_ARRAY (merged_args_list_p, merged_args_list_len, ecma_value_t);
ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
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,
bound_this_value,
merged_args_list_p,
merged_args_list_len);
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);
} }
args_length--;
ecma_length_t merged_args_list_len = args_length + arguments_list_len;
ecma_value_t ret_value;
JMEM_DEFINE_LOCAL_ARRAY (merged_args_list_p, merged_args_list_len, ecma_value_t);
ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
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);
JMEM_FINALIZE_LOCAL_ARRAY (merged_args_list_p);
return ret_value;
} }
JERRY_ASSERT (!ecma_is_value_empty (ret_value));
return ret_value;
} /* ecma_op_function_call */ } /* 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 * Returned value must be freed with ecma_free_value
*/ */
static ecma_value_t static ecma_value_t
ecma_op_function_construct_simple_or_external (ecma_object_t *func_obj_p, /**< Function object */ ecma_op_function_construct_ecma_or_external (ecma_object_t *func_obj_p, /**< Function object */
const ecma_value_t *arguments_list_p, /**< arguments list */ const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len) /**< length of 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 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_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
/* 5. */ /* 5. */
ECMA_TRY_CATCH (func_obj_prototype_prop_value, ecma_value_t prototype_prop_value = ecma_op_object_get_by_magic_id (func_obj_p,
ecma_op_object_get_by_magic_id (func_obj_p, LIT_MAGIC_STRING_PROTOTYPE);
LIT_MAGIC_STRING_PROTOTYPE),
ret_value); if (ECMA_IS_VALUE_ERROR (prototype_prop_value))
{
return prototype_prop_value;
}
/* 1., 2., 4. */ /* 1., 2., 4. */
ecma_object_t *obj_p; ecma_object_t *obj_p;
if (ecma_is_value_object (func_obj_prototype_prop_value)) if (ecma_is_value_object (prototype_prop_value))
{ {
/* 6. */ /* 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, 0,
ECMA_OBJECT_TYPE_GENERAL); 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_deref_object (prototype_p);
} }
ecma_free_value (prototype_prop_value);
/* 3. */ /* 3. */
/* /*
* [[Class]] property of ECMA_OBJECT_TYPE_GENERAL type objects * [[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. */ /* 8. */
ECMA_TRY_CATCH (call_completion, ecma_value_t this_obj = ecma_make_object_value (obj_p);
ecma_op_function_call (func_obj_p, ecma_value_t ret_value;
ecma_make_object_value (obj_p),
arguments_list_p, if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION)
arguments_list_len), {
ret_value); arguments_list_p = ecma_op_function_set_construct_flag (arguments_list_p);
}
ret_value = ecma_op_function_call (func_obj_p,
this_obj,
arguments_list_p,
arguments_list_len);
/* 9. */ /* 9. */
if (ecma_is_value_object (call_completion)) if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value))
{ {
ret_value = ecma_copy_value (call_completion); ecma_deref_object (obj_p);
} return ret_value;
else
{
/* 10. */
ecma_ref_object (obj_p);
ret_value = ecma_make_object_value (obj_p);
} }
ECMA_FINALIZE (call_completion); ecma_fast_free_value (ret_value);
return this_obj;
ecma_deref_object (obj_p); } /* ecma_op_function_construct_ecma_or_external */
ECMA_FINALIZE (func_obj_prototype_prop_value);
return ret_value;
} /* ecma_op_function_construct_simple_or_external */
/** /**
* [[Construct]] implementation: * [[Construct]] implementation:
@ -727,92 +771,92 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
{ {
JERRY_ASSERT (func_obj_p != NULL JERRY_ASSERT (func_obj_p != NULL
&& !ecma_is_lexical_environment (func_obj_p)); && !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; while (true)
{
switch (ecma_get_object_type (func_obj_p))
{
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."));
}
if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) return ecma_builtin_dispatch_construct (func_obj_p,
{ arguments_list_p,
if (JERRY_UNLIKELY (ecma_get_object_is_builtin (func_obj_p) arguments_list_len);
&& !ecma_builtin_function_is_routine (func_obj_p))) }
{ /* FALLTHRU */
ret_value = ecma_builtin_dispatch_construct (func_obj_p, }
arguments_list_p, case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
arguments_list_len); {
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
{
ret_value = ecma_op_function_construct_simple_or_external (func_obj_p,
arguments_list_p,
arguments_list_len);
}
}
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); 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_extended_object_t *ext_function_p = (ecma_extended_object_t *) func_obj_p;
ecma_object_t *target_func_obj_p; ecma_object_t *target_func_obj_p;
target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, target_func_obj_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
ext_function_p->u.bound_function.target_function); ext_function_p->u.bound_function.target_function);
/* 2. */ /* 4. */
if (!ecma_is_constructor (ecma_make_object_value (target_func_obj_p))) 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
JERRY_ASSERT (args_length > 0);
if (args_length == 1)
{ {
/* 4. */ /* 5. */
ecma_value_t args_len_or_this = ext_function_p->u.bound_function.args_len_or_this; func_obj_p = target_func_obj_p;
continue;
ecma_length_t args_length = 1;
if (ecma_is_value_integer_number (args_len_or_this))
{
args_length = (ecma_length_t) ecma_get_integer_from_value (args_len_or_this);
}
JERRY_ASSERT (args_length > 0);
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;
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));
/* 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);
}
else
{
/* 5. */
ret_value = ecma_op_function_construct (target_func_obj_p,
arguments_list_p,
arguments_list_len);
}
} }
ecma_value_t *args_p = (ecma_value_t *) (ext_function_p + 1);
ecma_value_t ret_value;
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);
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);
JMEM_FINALIZE_LOCAL_ARRAY (merged_args_list_p);
return ret_value;
} }
return ret_value;
} /* ecma_op_function_construct */ } /* ecma_op_function_construct */
/** /**

View File

@ -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);
}