mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Improve Function constructor argument handling.
For the Function constructor it is possible to pass the name of the function arguments in one or more strings, and each argument name should be separated with a comma. JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com
This commit is contained in:
parent
292d99ba4e
commit
c8a16f2107
@ -55,6 +55,86 @@ ecma_builtin_function_dispatch_call (const ecma_value_t *arguments_list_p, /**<
|
||||
return ecma_builtin_function_dispatch_construct (arguments_list_p, arguments_list_len);
|
||||
} /* ecma_builtin_function_dispatch_call */
|
||||
|
||||
/**
|
||||
* Helper method to count and convert the arguments for the Function constructor call.
|
||||
*
|
||||
* Performs the operation described in ECMA 262 v5.1 15.3.2.1 steps 5.a-d
|
||||
*
|
||||
*
|
||||
* @return completion value - concatenated arguments as a string.
|
||||
* Returned value must be freed with ecma_free_completion_value.
|
||||
*/
|
||||
static ecma_completion_value_t
|
||||
ecma_builtin_function_helper_get_arguments (const ecma_value_t *arguments_list_p, /** < arguments list */
|
||||
ecma_length_t arguments_list_len, /** < number of arguments */
|
||||
ecma_length_t *out_total_number_of_args_p) /** < out: number of
|
||||
* arguments found */
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
JERRY_ASSERT (out_total_number_of_args_p != NULL);
|
||||
|
||||
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
|
||||
|
||||
/* We are only processing the function arguments skipping the function body */
|
||||
ecma_length_t number_of_function_args = (arguments_list_len == 0 ? 0 : arguments_list_len - 1);
|
||||
ecma_string_t *arguments_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
|
||||
|
||||
ecma_string_t *separator_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR);
|
||||
|
||||
for (ecma_length_t idx = 0;
|
||||
idx < number_of_function_args && ecma_is_completion_value_empty (ret_value);
|
||||
idx++)
|
||||
{
|
||||
ECMA_TRY_CATCH (str_arg_value,
|
||||
ecma_op_to_string (arguments_list_p[idx]),
|
||||
ret_value);
|
||||
|
||||
ecma_string_t *str_p = ecma_get_string_from_value (str_arg_value);
|
||||
|
||||
lit_utf8_size_t str_size = ecma_string_get_size (str_p);
|
||||
MEM_DEFINE_LOCAL_ARRAY (start_p, str_size, lit_utf8_byte_t);
|
||||
|
||||
ecma_string_to_utf8_string (str_p, start_p, (ssize_t) str_size);
|
||||
lit_utf8_iterator_t iter = lit_utf8_iterator_create (start_p, str_size);
|
||||
|
||||
while (!lit_utf8_iterator_is_eos (&iter))
|
||||
{
|
||||
ecma_char_t current_char = lit_utf8_iterator_read_next (&iter);
|
||||
|
||||
if (current_char == ',')
|
||||
{
|
||||
(*out_total_number_of_args_p)++;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_FINALIZE_LOCAL_ARRAY (start_p);
|
||||
|
||||
ecma_string_t *concated_str_p = ecma_concat_ecma_strings (arguments_str_p, str_p);
|
||||
ecma_deref_ecma_string (arguments_str_p);
|
||||
arguments_str_p = concated_str_p;
|
||||
|
||||
if (idx < number_of_function_args - 1)
|
||||
{
|
||||
ecma_string_t *concated_str_p = ecma_concat_ecma_strings (arguments_str_p, separator_string_p);
|
||||
ecma_deref_ecma_string (arguments_str_p);
|
||||
arguments_str_p = concated_str_p;
|
||||
}
|
||||
|
||||
(*out_total_number_of_args_p)++;
|
||||
|
||||
ECMA_FINALIZE (str_arg_value);
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (separator_string_p);
|
||||
|
||||
if (ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (arguments_str_p));
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_builtin_function_helper_get_arguments */
|
||||
|
||||
/**
|
||||
* Handle calling [[Construct]] of built-in Function object
|
||||
*
|
||||
@ -71,9 +151,19 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
|
||||
|
||||
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
|
||||
|
||||
ecma_length_t total_number_of_function_args = 0;
|
||||
|
||||
ECMA_TRY_CATCH (arguments_value,
|
||||
ecma_builtin_function_helper_get_arguments (arguments_list_p,
|
||||
arguments_list_len,
|
||||
&total_number_of_function_args),
|
||||
ret_value);
|
||||
|
||||
ecma_string_t *arguments_str_p = ecma_get_string_from_value (arguments_value);
|
||||
|
||||
/* Last string, if any, is the function's body, and the rest, if any - are the function's parameter names */
|
||||
MEM_DEFINE_LOCAL_ARRAY (string_params_p,
|
||||
arguments_list_len == 0 ? 1 : arguments_list_len,
|
||||
arguments_list_len == 0 ? 1 : total_number_of_function_args + 1,
|
||||
ecma_string_t *);
|
||||
uint32_t params_count;
|
||||
|
||||
@ -89,22 +179,52 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
|
||||
else
|
||||
{
|
||||
/* 4., 5., 6. */
|
||||
strings_buffer_size = 0;
|
||||
|
||||
params_count = 0;
|
||||
while (params_count < arguments_list_len
|
||||
&& ecma_is_completion_value_empty (ret_value))
|
||||
|
||||
lit_utf8_size_t str_size = ecma_string_get_size (arguments_str_p);
|
||||
strings_buffer_size = str_size;
|
||||
|
||||
MEM_DEFINE_LOCAL_ARRAY (start_p, str_size, lit_utf8_byte_t);
|
||||
|
||||
ecma_string_to_utf8_string (arguments_str_p, start_p, (ssize_t) str_size);
|
||||
lit_utf8_iterator_t iter = lit_utf8_iterator_create (start_p, str_size);
|
||||
ecma_length_t last_separator = lit_utf8_iterator_get_index (&iter);
|
||||
ecma_length_t end_position;
|
||||
|
||||
while (!lit_utf8_iterator_is_eos (&iter))
|
||||
{
|
||||
ECMA_TRY_CATCH (str_arg_value,
|
||||
ecma_op_to_string (arguments_list_p[params_count]),
|
||||
ret_value);
|
||||
ecma_char_t current_char = lit_utf8_iterator_read_next (&iter);
|
||||
|
||||
string_params_p[params_count] = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (str_arg_value));
|
||||
strings_buffer_size += ecma_string_get_size (string_params_p[params_count]);
|
||||
params_count++;
|
||||
if (current_char == ',')
|
||||
{
|
||||
lit_utf8_iterator_decr (&iter);
|
||||
end_position = lit_utf8_iterator_get_index (&iter);
|
||||
|
||||
ECMA_FINALIZE (str_arg_value);
|
||||
string_params_p[params_count] = ecma_string_substr (arguments_str_p, last_separator, end_position);
|
||||
|
||||
lit_utf8_iterator_incr (&iter);
|
||||
last_separator = lit_utf8_iterator_get_index (&iter);
|
||||
|
||||
params_count++;
|
||||
}
|
||||
}
|
||||
|
||||
end_position = lit_utf8_string_length (start_p, str_size);
|
||||
string_params_p[params_count] = ecma_string_substr (arguments_str_p, last_separator, end_position);
|
||||
params_count++;
|
||||
|
||||
MEM_FINALIZE_LOCAL_ARRAY (start_p);
|
||||
|
||||
ECMA_TRY_CATCH (str_arg_value,
|
||||
ecma_op_to_string (arguments_list_p[arguments_list_len - 1]),
|
||||
ret_value);
|
||||
|
||||
ecma_string_t *str_p = ecma_get_string_from_value (str_arg_value);
|
||||
string_params_p[params_count] = ecma_copy_or_ref_ecma_string (str_p);
|
||||
strings_buffer_size += ecma_string_get_size (str_p);
|
||||
params_count++;
|
||||
|
||||
ECMA_FINALIZE (str_arg_value);
|
||||
}
|
||||
|
||||
if (ecma_is_completion_value_empty (ret_value))
|
||||
@ -197,6 +317,8 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
|
||||
|
||||
MEM_FINALIZE_LOCAL_ARRAY (string_params_p);
|
||||
|
||||
ECMA_FINALIZE (arguments_value);
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_builtin_function_dispatch_construct */
|
||||
|
||||
|
||||
@ -62,6 +62,15 @@ for (i = 1; i < 10; i ++)
|
||||
}
|
||||
}
|
||||
|
||||
var f = new Function ("a,b", "c", "return a + b + c;");
|
||||
assert (f (1,2,3) === 6);
|
||||
|
||||
f = new Function ("a,b", "c,d", "return a + b + c + d;");
|
||||
assert (f (1,2,3,4) === 10);
|
||||
|
||||
f = new Function ("a" , "b", "c,d", "return a + b + c + d;");
|
||||
assert (f (1,2,3,4) === 10);
|
||||
|
||||
try
|
||||
{
|
||||
new Function ({
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user