Skip to content

Commit c8a16f2

Browse files
galpeteregavrin
authored andcommitted
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
1 parent 292d99b commit c8a16f2

File tree

2 files changed

+143
-12
lines changed

2 files changed

+143
-12
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-function.cpp

Lines changed: 134 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,86 @@ ecma_builtin_function_dispatch_call (const ecma_value_t *arguments_list_p, /**<
5555
return ecma_builtin_function_dispatch_construct (arguments_list_p, arguments_list_len);
5656
} /* ecma_builtin_function_dispatch_call */
5757

58+
/**
59+
* Helper method to count and convert the arguments for the Function constructor call.
60+
*
61+
* Performs the operation described in ECMA 262 v5.1 15.3.2.1 steps 5.a-d
62+
*
63+
*
64+
* @return completion value - concatenated arguments as a string.
65+
* Returned value must be freed with ecma_free_completion_value.
66+
*/
67+
static ecma_completion_value_t
68+
ecma_builtin_function_helper_get_arguments (const ecma_value_t *arguments_list_p, /** < arguments list */
69+
ecma_length_t arguments_list_len, /** < number of arguments */
70+
ecma_length_t *out_total_number_of_args_p) /** < out: number of
71+
* arguments found */
72+
{
73+
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
74+
JERRY_ASSERT (out_total_number_of_args_p != NULL);
75+
76+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
77+
78+
/* We are only processing the function arguments skipping the function body */
79+
ecma_length_t number_of_function_args = (arguments_list_len == 0 ? 0 : arguments_list_len - 1);
80+
ecma_string_t *arguments_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
81+
82+
ecma_string_t *separator_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR);
83+
84+
for (ecma_length_t idx = 0;
85+
idx < number_of_function_args && ecma_is_completion_value_empty (ret_value);
86+
idx++)
87+
{
88+
ECMA_TRY_CATCH (str_arg_value,
89+
ecma_op_to_string (arguments_list_p[idx]),
90+
ret_value);
91+
92+
ecma_string_t *str_p = ecma_get_string_from_value (str_arg_value);
93+
94+
lit_utf8_size_t str_size = ecma_string_get_size (str_p);
95+
MEM_DEFINE_LOCAL_ARRAY (start_p, str_size, lit_utf8_byte_t);
96+
97+
ecma_string_to_utf8_string (str_p, start_p, (ssize_t) str_size);
98+
lit_utf8_iterator_t iter = lit_utf8_iterator_create (start_p, str_size);
99+
100+
while (!lit_utf8_iterator_is_eos (&iter))
101+
{
102+
ecma_char_t current_char = lit_utf8_iterator_read_next (&iter);
103+
104+
if (current_char == ',')
105+
{
106+
(*out_total_number_of_args_p)++;
107+
}
108+
}
109+
110+
MEM_FINALIZE_LOCAL_ARRAY (start_p);
111+
112+
ecma_string_t *concated_str_p = ecma_concat_ecma_strings (arguments_str_p, str_p);
113+
ecma_deref_ecma_string (arguments_str_p);
114+
arguments_str_p = concated_str_p;
115+
116+
if (idx < number_of_function_args - 1)
117+
{
118+
ecma_string_t *concated_str_p = ecma_concat_ecma_strings (arguments_str_p, separator_string_p);
119+
ecma_deref_ecma_string (arguments_str_p);
120+
arguments_str_p = concated_str_p;
121+
}
122+
123+
(*out_total_number_of_args_p)++;
124+
125+
ECMA_FINALIZE (str_arg_value);
126+
}
127+
128+
ecma_deref_ecma_string (separator_string_p);
129+
130+
if (ecma_is_completion_value_empty (ret_value))
131+
{
132+
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (arguments_str_p));
133+
}
134+
135+
return ret_value;
136+
} /* ecma_builtin_function_helper_get_arguments */
137+
58138
/**
59139
* Handle calling [[Construct]] of built-in Function object
60140
*
@@ -71,9 +151,19 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
71151

72152
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
73153

154+
ecma_length_t total_number_of_function_args = 0;
155+
156+
ECMA_TRY_CATCH (arguments_value,
157+
ecma_builtin_function_helper_get_arguments (arguments_list_p,
158+
arguments_list_len,
159+
&total_number_of_function_args),
160+
ret_value);
161+
162+
ecma_string_t *arguments_str_p = ecma_get_string_from_value (arguments_value);
163+
74164
/* Last string, if any, is the function's body, and the rest, if any - are the function's parameter names */
75165
MEM_DEFINE_LOCAL_ARRAY (string_params_p,
76-
arguments_list_len == 0 ? 1 : arguments_list_len,
166+
arguments_list_len == 0 ? 1 : total_number_of_function_args + 1,
77167
ecma_string_t *);
78168
uint32_t params_count;
79169

@@ -89,22 +179,52 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
89179
else
90180
{
91181
/* 4., 5., 6. */
92-
strings_buffer_size = 0;
93-
94182
params_count = 0;
95-
while (params_count < arguments_list_len
96-
&& ecma_is_completion_value_empty (ret_value))
183+
184+
lit_utf8_size_t str_size = ecma_string_get_size (arguments_str_p);
185+
strings_buffer_size = str_size;
186+
187+
MEM_DEFINE_LOCAL_ARRAY (start_p, str_size, lit_utf8_byte_t);
188+
189+
ecma_string_to_utf8_string (arguments_str_p, start_p, (ssize_t) str_size);
190+
lit_utf8_iterator_t iter = lit_utf8_iterator_create (start_p, str_size);
191+
ecma_length_t last_separator = lit_utf8_iterator_get_index (&iter);
192+
ecma_length_t end_position;
193+
194+
while (!lit_utf8_iterator_is_eos (&iter))
97195
{
98-
ECMA_TRY_CATCH (str_arg_value,
99-
ecma_op_to_string (arguments_list_p[params_count]),
100-
ret_value);
196+
ecma_char_t current_char = lit_utf8_iterator_read_next (&iter);
197+
198+
if (current_char == ',')
199+
{
200+
lit_utf8_iterator_decr (&iter);
201+
end_position = lit_utf8_iterator_get_index (&iter);
202+
203+
string_params_p[params_count] = ecma_string_substr (arguments_str_p, last_separator, end_position);
101204

102-
string_params_p[params_count] = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (str_arg_value));
103-
strings_buffer_size += ecma_string_get_size (string_params_p[params_count]);
104-
params_count++;
205+
lit_utf8_iterator_incr (&iter);
206+
last_separator = lit_utf8_iterator_get_index (&iter);
105207

106-
ECMA_FINALIZE (str_arg_value);
208+
params_count++;
209+
}
107210
}
211+
212+
end_position = lit_utf8_string_length (start_p, str_size);
213+
string_params_p[params_count] = ecma_string_substr (arguments_str_p, last_separator, end_position);
214+
params_count++;
215+
216+
MEM_FINALIZE_LOCAL_ARRAY (start_p);
217+
218+
ECMA_TRY_CATCH (str_arg_value,
219+
ecma_op_to_string (arguments_list_p[arguments_list_len - 1]),
220+
ret_value);
221+
222+
ecma_string_t *str_p = ecma_get_string_from_value (str_arg_value);
223+
string_params_p[params_count] = ecma_copy_or_ref_ecma_string (str_p);
224+
strings_buffer_size += ecma_string_get_size (str_p);
225+
params_count++;
226+
227+
ECMA_FINALIZE (str_arg_value);
108228
}
109229

110230
if (ecma_is_completion_value_empty (ret_value))
@@ -197,6 +317,8 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
197317

198318
MEM_FINALIZE_LOCAL_ARRAY (string_params_p);
199319

320+
ECMA_FINALIZE (arguments_value);
321+
200322
return ret_value;
201323
} /* ecma_builtin_function_dispatch_construct */
202324

tests/jerry/function-construct.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ for (i = 1; i < 10; i ++)
6262
}
6363
}
6464

65+
var f = new Function ("a,b", "c", "return a + b + c;");
66+
assert (f (1,2,3) === 6);
67+
68+
f = new Function ("a,b", "c,d", "return a + b + c + d;");
69+
assert (f (1,2,3,4) === 10);
70+
71+
f = new Function ("a" , "b", "c,d", "return a + b + c + d;");
72+
assert (f (1,2,3,4) === 10);
73+
6574
try
6675
{
6776
new Function ({

0 commit comments

Comments
 (0)