Parse functions directly (#2015)
This patch adds direct function source code parsing, which is useful to avoid source code duplications. The patch also improves the Function constructor. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
committed by
Dániel Bátyai
parent
7713d30702
commit
8d916a44f1
@@ -65,116 +65,53 @@ ecma_builtin_function_dispatch_call (const ecma_value_t *arguments_list_p, /**<
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_function_helper_get_function_expression (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
ecma_length_t arguments_list_len) /**< number of arguments */
|
||||
ecma_builtin_function_helper_get_function_arguments (const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
ecma_length_t arguments_list_len) /**< number of arguments */
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
ecma_string_t *left_parenthesis_str_p, *right_parenthesis_str_p;
|
||||
ecma_string_t *left_brace_str_p, *right_brace_str_p;
|
||||
ecma_string_t *comma_str_p;
|
||||
ecma_string_t *function_kw_str_p, *empty_str_p;
|
||||
ecma_string_t *expr_str_p, *concated_str_p;
|
||||
|
||||
left_parenthesis_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_LEFT_PARENTHESIS_CHAR);
|
||||
right_parenthesis_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_RIGHT_PARENTHESIS_CHAR);
|
||||
|
||||
left_brace_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_LEFT_BRACE_CHAR);
|
||||
right_brace_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR);
|
||||
|
||||
comma_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR);
|
||||
|
||||
function_kw_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_FUNCTION);
|
||||
empty_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING__EMPTY);
|
||||
|
||||
/* First, we only process the function arguments skipping the function body */
|
||||
ecma_length_t number_of_function_args = (arguments_list_len == 0 ? 0 : arguments_list_len - 1);
|
||||
|
||||
expr_str_p = ecma_concat_ecma_strings (left_parenthesis_str_p, function_kw_str_p);
|
||||
|
||||
concated_str_p = ecma_concat_ecma_strings (expr_str_p, left_parenthesis_str_p);
|
||||
ecma_deref_ecma_string (expr_str_p);
|
||||
expr_str_p = concated_str_p;
|
||||
|
||||
for (ecma_length_t idx = 0;
|
||||
idx < number_of_function_args && ecma_is_value_empty (ret_value);
|
||||
idx++)
|
||||
if (arguments_list_len <= 1)
|
||||
{
|
||||
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);
|
||||
|
||||
concated_str_p = ecma_concat_ecma_strings (expr_str_p, str_p);
|
||||
ecma_deref_ecma_string (expr_str_p);
|
||||
expr_str_p = concated_str_p;
|
||||
|
||||
if (idx < number_of_function_args - 1)
|
||||
{
|
||||
concated_str_p = ecma_concat_ecma_strings (expr_str_p, comma_str_p);
|
||||
ecma_deref_ecma_string (expr_str_p);
|
||||
expr_str_p = concated_str_p;
|
||||
}
|
||||
|
||||
ECMA_FINALIZE (str_arg_value);
|
||||
return ecma_make_string_value (ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY));
|
||||
}
|
||||
|
||||
if (ecma_is_value_empty (ret_value))
|
||||
ecma_value_t final_str = ecma_op_to_string (arguments_list_p[0]);
|
||||
|
||||
if (arguments_list_len == 2 || ECMA_IS_VALUE_ERROR (final_str))
|
||||
{
|
||||
concated_str_p = ecma_concat_ecma_strings (expr_str_p, right_parenthesis_str_p);
|
||||
ecma_deref_ecma_string (expr_str_p);
|
||||
expr_str_p = concated_str_p;
|
||||
|
||||
concated_str_p = ecma_concat_ecma_strings (expr_str_p, left_brace_str_p);
|
||||
ecma_deref_ecma_string (expr_str_p);
|
||||
expr_str_p = concated_str_p;
|
||||
|
||||
if (arguments_list_len != 0)
|
||||
{
|
||||
ECMA_TRY_CATCH (str_arg_value,
|
||||
ecma_op_to_string (arguments_list_p[arguments_list_len - 1]),
|
||||
ret_value);
|
||||
|
||||
ecma_string_t *body_str_p = ecma_get_string_from_value (str_arg_value);
|
||||
|
||||
concated_str_p = ecma_concat_ecma_strings (expr_str_p, body_str_p);
|
||||
ecma_deref_ecma_string (expr_str_p);
|
||||
expr_str_p = concated_str_p;
|
||||
|
||||
ECMA_FINALIZE (str_arg_value);
|
||||
}
|
||||
|
||||
concated_str_p = ecma_concat_ecma_strings (expr_str_p, right_brace_str_p);
|
||||
ecma_deref_ecma_string (expr_str_p);
|
||||
expr_str_p = concated_str_p;
|
||||
|
||||
concated_str_p = ecma_concat_ecma_strings (expr_str_p, right_parenthesis_str_p);
|
||||
ecma_deref_ecma_string (expr_str_p);
|
||||
expr_str_p = concated_str_p;
|
||||
return final_str;
|
||||
}
|
||||
|
||||
ecma_string_t *comma_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR);
|
||||
|
||||
for (ecma_length_t idx = 1; idx < arguments_list_len - 1; idx++)
|
||||
{
|
||||
ecma_value_t new_str = ecma_op_to_string (arguments_list_p[idx]);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (new_str))
|
||||
{
|
||||
ecma_free_value (final_str);
|
||||
|
||||
/* Return with the error. */
|
||||
final_str = new_str;
|
||||
break;
|
||||
}
|
||||
|
||||
ecma_string_t *final_str_p = ecma_get_string_from_value (final_str);
|
||||
ecma_string_t *fragment_str_p = ecma_concat_ecma_strings (final_str_p, comma_str_p);
|
||||
ecma_deref_ecma_string (final_str_p);
|
||||
|
||||
ecma_string_t *new_str_p = ecma_get_string_from_value (new_str);
|
||||
final_str_p = ecma_concat_ecma_strings (fragment_str_p, new_str_p);
|
||||
ecma_deref_ecma_string (new_str_p);
|
||||
ecma_deref_ecma_string (fragment_str_p);
|
||||
|
||||
final_str = ecma_make_string_value (final_str_p);
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (left_parenthesis_str_p);
|
||||
ecma_deref_ecma_string (right_parenthesis_str_p);
|
||||
ecma_deref_ecma_string (left_brace_str_p);
|
||||
ecma_deref_ecma_string (right_brace_str_p);
|
||||
ecma_deref_ecma_string (comma_str_p);
|
||||
ecma_deref_ecma_string (function_kw_str_p);
|
||||
ecma_deref_ecma_string (empty_str_p);
|
||||
|
||||
if (ecma_is_value_empty (ret_value))
|
||||
{
|
||||
ret_value = ecma_make_string_value (expr_str_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_deref_ecma_string (expr_str_p);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_builtin_function_helper_get_function_expression */
|
||||
return final_str;
|
||||
} /* ecma_builtin_function_helper_get_function_arguments */
|
||||
|
||||
/**
|
||||
* Handle calling [[Construct]] of built-in Function object
|
||||
@@ -190,18 +127,63 @@ ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p,
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
ecma_value_t arguments_value = ecma_builtin_function_helper_get_function_arguments (arguments_list_p,
|
||||
arguments_list_len);
|
||||
|
||||
ECMA_TRY_CATCH (arguments_value,
|
||||
ecma_builtin_function_helper_get_function_expression (arguments_list_p,
|
||||
arguments_list_len),
|
||||
ret_value);
|
||||
if (ECMA_IS_VALUE_ERROR (arguments_value))
|
||||
{
|
||||
return arguments_value;
|
||||
}
|
||||
|
||||
ecma_string_t *function_expression_p = ecma_get_string_from_value (arguments_value);
|
||||
ecma_value_t function_body_value;
|
||||
|
||||
ret_value = ecma_op_eval (function_expression_p, false, false);
|
||||
if (arguments_list_len > 0)
|
||||
{
|
||||
function_body_value = ecma_op_to_string (arguments_list_p[arguments_list_len - 1]);
|
||||
|
||||
ECMA_FINALIZE (arguments_value);
|
||||
if (ECMA_IS_VALUE_ERROR (function_body_value))
|
||||
{
|
||||
ecma_free_value (arguments_value);
|
||||
return function_body_value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Very unlikely code path, not optimized. */
|
||||
function_body_value = ecma_make_string_value (ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY));
|
||||
}
|
||||
|
||||
ecma_string_t *arguments_str_p = ecma_get_string_from_value (arguments_value);
|
||||
ecma_string_t *function_body_str_p = ecma_get_string_from_value (function_body_value);
|
||||
|
||||
ECMA_STRING_TO_UTF8_STRING (arguments_str_p, arguments_buffer_p, arguments_buffer_size);
|
||||
ECMA_STRING_TO_UTF8_STRING (function_body_str_p, function_body_buffer_p, function_body_buffer_size);
|
||||
|
||||
ecma_compiled_code_t *bytecode_data_p;
|
||||
|
||||
ecma_value_t ret_value = parser_parse_script (arguments_buffer_p,
|
||||
arguments_buffer_size,
|
||||
function_body_buffer_p,
|
||||
function_body_buffer_size,
|
||||
false,
|
||||
&bytecode_data_p);
|
||||
|
||||
if (!ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_true (ret_value));
|
||||
|
||||
ecma_object_t *func_obj_p = ecma_op_create_function_object (ecma_get_global_environment (),
|
||||
bytecode_data_p);
|
||||
|
||||
ecma_bytecode_deref (bytecode_data_p);
|
||||
ret_value = ecma_make_object_value (func_obj_p);
|
||||
}
|
||||
|
||||
ECMA_FINALIZE_UTF8_STRING (function_body_buffer_p, function_body_buffer_size);
|
||||
ECMA_FINALIZE_UTF8_STRING (arguments_buffer_p, arguments_buffer_size);
|
||||
|
||||
ecma_deref_ecma_string (arguments_str_p);
|
||||
ecma_deref_ecma_string (function_body_str_p);
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_builtin_function_dispatch_construct */
|
||||
|
||||
Reference in New Issue
Block a user