/** * The String.prototype object's 'concat' routine * * See also: * ECMA-262 v5, 15.5.4.6 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_concat (ecma_value_t this_arg, /**< this argument */ const ecma_value_t* argument_list_p, /**< arguments list */ ecma_length_t arguments_number) /**< number of arguments */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1 */ ECMA_TRY_CATCH (check_coercible_val, ecma_op_check_object_coercible (this_arg), ret_value); /* 2 */ ECMA_TRY_CATCH (to_string_val, ecma_op_to_string (this_arg), ret_value); /* 3 */ // No copy performed /* 4 */ ecma_string_t *string_to_return = ecma_copy_or_ref_ecma_string (ecma_get_string_from_value (to_string_val)); /* 5 */ for (uint32_t arg_index = 0; arg_index < arguments_number && ecma_is_completion_value_empty (ret_value); ++arg_index) { /* 5a */ /* 5b */ ecma_string_t *string_temp = string_to_return; ECMA_TRY_CATCH (get_arg_string, ecma_op_to_string (argument_list_p[arg_index]), ret_value); string_to_return = ecma_concat_ecma_strings (string_to_return, ecma_get_string_from_value (get_arg_string)); ecma_deref_ecma_string (string_temp); ECMA_FINALIZE (get_arg_string); } /* 6 */ if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_make_normal_completion_value (ecma_make_string_value (string_to_return)); } else { ecma_deref_ecma_string (string_to_return); } ECMA_FINALIZE (to_string_val); ECMA_FINALIZE (check_coercible_val); return ret_value; } /* ecma_builtin_string_prototype_object_concat */
/** * Helper function for string indexOf and lastIndexOf functions * * This function implements string indexOf and lastIndexOf with required checks and conversions. * * See also: * ECMA-262 v5, 15.5.4.7 * ECMA-262 v5, 15.5.4.8 * * Used by: * - The String.prototype.indexOf routine. * - The String.prototype.lastIndexOf routine. * * @return uint32_t - (last) index of search string */ ecma_value_t ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2, /**< routine's second argument */ bool first_index) /**< routine's third argument */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1 */ ECMA_TRY_CATCH (check_coercible_val, ecma_op_check_object_coercible (this_arg), ret_value); /* 2 */ ECMA_TRY_CATCH (to_str_val, ecma_op_to_string (this_arg), ret_value); /* 3 */ ECMA_TRY_CATCH (search_str_val, ecma_op_to_string (arg1), ret_value); /* 4 */ ECMA_OP_TO_NUMBER_TRY_CATCH (pos_num, arg2, ret_value); /* 5 (indexOf) -- 6 (lastIndexOf) */ ecma_string_t *original_str_p = ecma_get_string_from_value (to_str_val); const ecma_length_t original_len = ecma_string_get_length (original_str_p); /* 4b, 6 (indexOf) - 4b, 5, 7 (lastIndexOf) */ ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, first_index); /* 7 (indexOf) -- 8 (lastIndexOf) */ ecma_string_t *search_str_p = ecma_get_string_from_value (search_str_val); ecma_number_t ret_num = ECMA_NUMBER_MINUS_ONE; /* 8 (indexOf) -- 9 (lastIndexOf) */ ecma_length_t index_of = 0; if (ecma_builtin_helper_string_find_index (original_str_p, search_str_p, first_index, start, &index_of)) { ret_num = ((ecma_number_t) index_of); } ret_value = ecma_make_number_value (ret_num); ECMA_OP_TO_NUMBER_FINALIZE (pos_num); ECMA_FINALIZE (search_str_val); ECMA_FINALIZE (to_str_val); ECMA_FINALIZE (check_coercible_val); return ret_value; } /* ecma_builtin_helper_string_prototype_object_index_of */
/** * Handle calling [[Call]] of built-in String object * * See also: * ECMA-262 v6, 21.1.1.1 * * @return ecma value */ ecma_value_t ecma_builtin_string_dispatch_call (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_VALUE_EMPTY; /* 1. */ if (arguments_list_len == 0) { ret_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); } #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) /* 2.a */ else if (ecma_is_value_symbol (arguments_list_p[0])) { ret_value = ecma_get_symbol_descriptive_string (arguments_list_p[0]); } #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ /* 2.b */ else { ret_value = ecma_op_to_string (arguments_list_p[0]); } return ret_value; } /* ecma_builtin_string_dispatch_call */
/** * 'in' opcode handler. * * See also: ECMA-262 v5, 11.8.7 * * @return ecma value * returned value must be freed with ecma_free_value. */ ecma_value_t opfunc_in (ecma_value_t left_value, /**< left value */ ecma_value_t right_value) /**< right value */ { if (!ecma_is_value_object (right_value)) { return ecma_raise_type_error (ECMA_ERR_MSG ("Expected an object in 'in' check.")); } bool to_string = !ecma_is_value_string (left_value); if (to_string) { left_value = ecma_op_to_string (left_value); if (ECMA_IS_VALUE_ERROR (left_value)) { return left_value; } } ecma_string_t *left_value_prop_name_p = ecma_get_string_from_value (left_value); ecma_object_t *right_value_obj_p = ecma_get_object_from_value (right_value); ecma_value_t result = ecma_make_boolean_value (ecma_op_object_has_property (right_value_obj_p, left_value_prop_name_p)); if (to_string) { ecma_free_value (left_value); } return result; } /* opfunc_in */
/** * The Array.prototype's 'toLocaleString' single element operation routine * * See also: * ECMA-262 v5, 15.4.4.3 steps 6-8 and 10.b-d * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /**< this object */ uint32_t index) /**< array index */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (index_value, ecma_op_object_get (obj_p, index_string_p), ret_value); if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value)) { ecma_string_t *return_string_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ret_value = ecma_make_string_value (return_string_p); } else { ECMA_TRY_CATCH (index_obj_value, ecma_op_to_object (index_value), ret_value); ecma_object_t *index_obj_p = ecma_get_object_from_value (index_obj_value); ecma_string_t *locale_string_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL); ECMA_TRY_CATCH (to_locale_value, ecma_op_object_get (index_obj_p, locale_string_magic_string_p), ret_value); if (ecma_op_is_callable (to_locale_value)) { ecma_object_t *locale_func_obj_p = ecma_get_object_from_value (to_locale_value); ECMA_TRY_CATCH (call_value, ecma_op_function_call (locale_func_obj_p, ecma_make_object_value (index_obj_p), NULL, 0), ret_value); ret_value = ecma_op_to_string (call_value); ECMA_FINALIZE (call_value); } else { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } ECMA_FINALIZE (to_locale_value); ecma_deref_ecma_string (locale_string_magic_string_p); ECMA_FINALIZE (index_obj_value); } ECMA_FINALIZE (index_value); ecma_deref_ecma_string (index_string_p); return ret_value; } /* ecma_builtin_helper_get_to_locale_string_at_index */
/** * Handle calling [[Call]] of built-in SyntaxError object * * @return ecma value */ ecma_value_t ecma_builtin_syntax_error_dispatch_call (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); if (arguments_list_len != 0 && !ecma_is_value_undefined (arguments_list_p[0])) { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (msg_str_value, ecma_op_to_string (arguments_list_p[0]), ret_value); ecma_string_t *message_string_p = ecma_get_string_from_value (msg_str_value); ecma_object_t *new_error_object_p = ecma_new_standard_error_with_message (ECMA_ERROR_SYNTAX, message_string_p); ret_value = ecma_make_object_value (new_error_object_p); ECMA_FINALIZE (msg_str_value); return ret_value; } else { ecma_object_t *new_error_object_p = ecma_new_standard_error (ECMA_ERROR_SYNTAX); return ecma_make_object_value (new_error_object_p); } } /* ecma_builtin_syntax_error_dispatch_call */
/** * The Object.prototype object's 'hasOwnProperty' routine * * See also: * ECMA-262 v5, 15.2.4.5 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_object_prototype_object_has_own_property (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< first argument */ { ecma_value_t return_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ ECMA_TRY_CATCH (to_string_val, ecma_op_to_string (arg), return_value); /* 2. */ ECMA_TRY_CATCH (obj_val, ecma_op_to_object (this_arg), return_value); ecma_string_t *property_name_string_p = ecma_get_string_from_value (to_string_val); ecma_object_t *obj_p = ecma_get_object_from_value (obj_val); /* 3. */ return_value = ecma_make_boolean_value (ecma_op_object_has_own_property (obj_p, property_name_string_p)); ECMA_FINALIZE (obj_val); ECMA_FINALIZE (to_string_val); return return_value; } /* ecma_builtin_object_prototype_object_has_own_property */
/** * 'in' opcode handler. * * See also: ECMA-262 v5, 11.8.7 * * @return ecma value * returned value must be freed with ecma_free_value. */ ecma_value_t opfunc_in (ecma_value_t left_value, /**< left value */ ecma_value_t right_value) /**< right value */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (!ecma_is_value_object (right_value)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { ECMA_TRY_CATCH (str_left_value, ecma_op_to_string (left_value), ret_value); ecma_string_t *left_value_prop_name_p = ecma_get_string_from_value (str_left_value); ecma_object_t *right_value_obj_p = ecma_get_object_from_value (right_value); if (ecma_op_object_get_property (right_value_obj_p, left_value_prop_name_p) != NULL) { ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } else { ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE); } ECMA_FINALIZE (str_left_value); } return ret_value; } /* opfunc_in */
/** * Handle calling [[Call]] of a built-in error object * * @return ecma value */ ecma_value_t ecma_builtin_helper_error_dispatch_call (ecma_standard_error_t error_type, /**< native error type */ 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); if (arguments_list_len != 0 && !ecma_is_value_undefined (arguments_list_p[0])) { ecma_value_t ret_value = ECMA_VALUE_EMPTY; ECMA_TRY_CATCH (msg_str_value, ecma_op_to_string (arguments_list_p[0]), ret_value); ecma_string_t *message_string_p = ecma_get_string_from_value (msg_str_value); ecma_object_t *new_error_object_p = ecma_new_standard_error_with_message (error_type, message_string_p); ret_value = ecma_make_object_value (new_error_object_p); ECMA_FINALIZE (msg_str_value); return ret_value; } else { ecma_object_t *new_error_object_p = ecma_new_standard_error (error_type); return ecma_make_object_value (new_error_object_p); } } /* ecma_builtin_helper_error_dispatch_call */
/** * The String.prototype object's 'localeCompare' routine * * See also: * ECMA-262 v5, 15.5.4.9 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_locale_compare (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1. */ ECMA_TRY_CATCH (this_check_coercible_val, ecma_op_check_object_coercible (this_arg), ret_value); /* 2. */ ECMA_TRY_CATCH (this_to_string_val, ecma_op_to_string (this_arg), ret_value); /* 3. */ ECMA_TRY_CATCH (arg_to_string_val, ecma_op_to_string (arg), ret_value); ecma_string_t *this_string_p = ecma_get_string_from_value (this_to_string_val); ecma_string_t *arg_string_p = ecma_get_string_from_value (arg_to_string_val); ecma_number_t *result_p = ecma_alloc_number (); if (ecma_compare_ecma_strings_relational (this_string_p, arg_string_p)) { *result_p = ecma_int32_to_number (-1); } else if (!ecma_compare_ecma_strings (this_string_p, arg_string_p)) { *result_p = ecma_int32_to_number (1); } else { *result_p = ecma_int32_to_number (0); } ret_value = ecma_make_normal_completion_value (ecma_make_number_value (result_p)); ECMA_FINALIZE (arg_to_string_val); ECMA_FINALIZE (this_to_string_val); ECMA_FINALIZE (this_check_coercible_val); return ret_value; } /* ecma_builtin_string_prototype_object_locale_compare */
/** * The String.prototype object's 'charCodeAt' routine * * See also: * ECMA-262 v5, 15.5.4.5 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_char_code_at (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1 */ ECMA_TRY_CATCH (check_coercible_val, ecma_op_check_object_coercible (this_arg), ret_value); /* 2 */ ECMA_TRY_CATCH (to_string_val, ecma_op_to_string (this_arg), ret_value); /* 3 */ ECMA_OP_TO_NUMBER_TRY_CATCH (index_num, arg, ret_value); /* 4 */ ecma_string_t *original_string_p = ecma_get_string_from_value (to_string_val); const ecma_length_t len = ecma_string_get_length (original_string_p); ecma_number_t *ret_num_p = ecma_alloc_number (); /* 5 */ // When index_num is NaN, then the first two comparisons are false if (index_num < 0 || index_num >= len || (ecma_number_is_nan (index_num) && !len)) { *ret_num_p = ecma_number_make_nan (); } else { /* 6 */ /* * String length is currently uit32_t, but index_num may be bigger, * ToInteger performs floor, while ToUInt32 performs modulo 2^32, * hence after the check 0 <= index_num < len we assume to_uint32 can be used. * We assume to_uint32 (NaN) is 0. */ JERRY_ASSERT (ecma_number_is_nan (index_num) || ecma_number_to_uint32 (index_num) == ecma_number_trunc (index_num)); ecma_char_t new_ecma_char = ecma_string_get_char_at_pos (original_string_p, ecma_number_to_uint32 (index_num)); *ret_num_p = ecma_uint32_to_number (new_ecma_char); } ecma_value_t new_value = ecma_make_number_value (ret_num_p); ret_value = ecma_make_normal_completion_value (new_value); ECMA_OP_TO_NUMBER_FINALIZE (index_num); ECMA_FINALIZE (to_string_val); ECMA_FINALIZE (check_coercible_val); return ret_value; } /* ecma_builtin_string_prototype_object_char_code_at */
/** * ToString operation. * * See also: * ECMA-262 v5, 9.8 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_to_string (ecma_value_t value) /**< ecma-value */ { ecma_check_value_type_is_spec_defined (value); if (unlikely (ecma_is_value_object (value))) { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ECMA_TRY_CATCH (prim_value, ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING), ret_value); ret_value = ecma_op_to_string (prim_value); ECMA_FINALIZE (prim_value); return ret_value; } else { ecma_string_t *res_p = NULL; if (ecma_is_value_string (value)) { res_p = ecma_get_string_from_value (value); res_p = ecma_copy_or_ref_ecma_string (res_p); } else if (ecma_is_value_number (value)) { ecma_number_t *num_p = ecma_get_number_from_value (value); res_p = ecma_new_ecma_string_from_number (*num_p); } else if (ecma_is_value_undefined (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED); } else if (ecma_is_value_null (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL); } else { JERRY_ASSERT (ecma_is_value_boolean (value)); if (ecma_is_value_true (value)) { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_TRUE); } else { res_p = ecma_get_magic_string (LIT_MAGIC_STRING_FALSE); } } return ecma_make_normal_completion_value (ecma_make_string_value (res_p)); } } /* ecma_op_to_string */
/** * Update getter or setter for object literals. */ void opfunc_set_accessor (bool is_getter, /**< is getter accessor */ ecma_value_t object, /**< object value */ ecma_value_t accessor_name, /**< accessor name value */ ecma_value_t accessor) /**< accessor value */ { ecma_object_t *object_p = ecma_get_object_from_value (object); JERRY_ASSERT (ecma_is_value_string (accessor_name) || ecma_is_value_number (accessor_name)); ecma_string_t *accessor_name_p = ecma_get_string_from_value (ecma_op_to_string (accessor_name)); ecma_property_t *property_p = ecma_find_named_property (object_p, accessor_name_p); if (property_p != NULL && ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDACCESSOR) { ecma_delete_property (object_p, ECMA_PROPERTY_VALUE_PTR (property_p)); property_p = NULL; } if (property_p == NULL) { ecma_object_t *getter_func_p = NULL; ecma_object_t *setter_func_p = NULL; if (is_getter) { getter_func_p = ecma_get_object_from_value (accessor); } else { setter_func_p = ecma_get_object_from_value (accessor); } ecma_create_named_accessor_property (object_p, accessor_name_p, getter_func_p, setter_func_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE, NULL); } else if (is_getter) { ecma_object_t *getter_func_p = ecma_get_object_from_value (accessor); ecma_set_named_accessor_property_getter (object_p, ECMA_PROPERTY_VALUE_PTR (property_p), getter_func_p); } else { ecma_object_t *setter_func_p = ecma_get_object_from_value (accessor); ecma_set_named_accessor_property_setter (object_p, ECMA_PROPERTY_VALUE_PTR (property_p), setter_func_p); } ecma_deref_ecma_string (accessor_name_p); } /* opfunc_set_accessor */
/** * The String.prototype object's 'trim' routine * * See also: * ECMA-262 v5, 15.5.4.20 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_trim (ecma_value_t this_arg) /**< this argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1 */ ECMA_TRY_CATCH (check_coercible_val, ecma_op_check_object_coercible (this_arg), ret_value); /* 2 */ ECMA_TRY_CATCH (to_string_val, ecma_op_to_string (this_arg), ret_value); ecma_string_t *original_string_p = ecma_get_string_from_value (to_string_val); /* 3 */ const lit_utf8_size_t size = ecma_string_get_size (original_string_p); const ecma_length_t length = ecma_string_get_size (original_string_p); /* Workaround: avoid repeated call of ecma_string_get_char_at_pos() because its overhead */ lit_utf8_byte_t *original_utf8_str_p = (lit_utf8_byte_t *) mem_heap_alloc_block (size + 1, MEM_HEAP_ALLOC_SHORT_TERM); ecma_string_to_utf8_string (original_string_p, original_utf8_str_p, (ssize_t) size); uint32_t prefix = 0, postfix = 0; uint32_t new_len = 0; while (prefix < length && isspace (lit_utf8_string_code_unit_at (original_utf8_str_p, size, prefix))) { prefix++; } while (postfix < length - prefix && isspace (lit_utf8_string_code_unit_at (original_utf8_str_p, size, length - postfix - 1))) { postfix++; } new_len = prefix < size ? size - prefix - postfix : 0; ecma_string_t *new_str_p = ecma_string_substr (original_string_p, prefix, prefix + new_len); /* 4 */ ret_value = ecma_make_normal_completion_value (ecma_make_string_value (new_str_p)); mem_heap_free_block (original_utf8_str_p); ECMA_FINALIZE (to_string_val); ECMA_FINALIZE (check_coercible_val); return ret_value; } /* ecma_builtin_string_prototype_object_trim */
/** * The RegExp.prototype object's 'exec' routine * * See also: * ECMA-262 v5, 15.10.6.2 * * @return array object containing the results - if the matched * null - otherwise * * May raise error, so returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_regexp_prototype_exec (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's argument */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (!ecma_is_value_object (this_arg) || ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_REGEXP_UL) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Incomplete RegExp type")); } else { ECMA_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ECMA_TRY_CATCH (input_str_value, ecma_op_to_string (arg), ret_value); ecma_property_t *bytecode_prop_p; ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); bytecode_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); void *bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (void, ecma_get_internal_property_value (bytecode_prop_p)); if (bytecode_p == NULL) { /* Missing bytecode means empty RegExp: '/(?:)/', so always return empty string. */ ecma_string_t *capture_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ecma_value_t arguments_list[1]; arguments_list[0] = ecma_make_string_value (capture_str_p); ret_value = ecma_op_create_array_object (arguments_list, 1, false); ecma_deref_ecma_string (capture_str_p); re_set_result_array_properties (ecma_get_object_from_value (ret_value), ecma_get_string_from_value (input_str_value), 1, 0); } else { ret_value = ecma_regexp_exec_helper (obj_this, input_str_value, false); } ECMA_FINALIZE (input_str_value); ECMA_FINALIZE (obj_this); } return ret_value; } /* ecma_builtin_regexp_prototype_exec */
/** * The String.prototype object's 'charAt' routine * * See also: * ECMA-262 v5, 15.5.4.4 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_char_at (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1 */ ECMA_TRY_CATCH (check_coercible_val, ecma_op_check_object_coercible (this_arg), ret_value); /* 2 */ ECMA_TRY_CATCH (to_string_val, ecma_op_to_string (this_arg), ret_value); /* 3 */ ECMA_OP_TO_NUMBER_TRY_CATCH (index_num, arg, ret_value); /* 4 */ ecma_string_t *original_string_p = ecma_get_string_from_value (to_string_val); const ecma_length_t len = ecma_string_get_length (original_string_p); /* 5 */ if (index_num < 0 || index_num >= len || !len) { ret_value = ecma_make_normal_completion_value (ecma_make_string_value ( ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY))); } else { /* 6 */ ecma_char_t new_ecma_char = ecma_string_get_char_at_pos (original_string_p, ecma_number_to_uint32 (index_num)); ret_value = ecma_make_normal_completion_value (ecma_make_string_value ( ecma_new_ecma_string_from_code_unit (new_ecma_char))); } ECMA_OP_TO_NUMBER_FINALIZE (index_num); ECMA_FINALIZE (to_string_val); ECMA_FINALIZE (check_coercible_val); return ret_value; } /* ecma_builtin_string_prototype_object_char_at */
/** * The Object object's 'getOwnPropertyDescriptor' routine * * See also: * ECMA-262 v5, 15.2.3.3 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_object_object_get_own_property_descriptor (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */ ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2) /**< routine's second argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); // 1. if (!ecma_is_value_object (arg1)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); return ret_value; } ecma_object_t *obj_p = ecma_get_object_from_value (arg1); // 2. ECMA_TRY_CATCH (name_str_value, ecma_op_to_string (arg2), ret_value); ecma_string_t *name_str_p = ecma_get_string_from_value (name_str_value); // 3. ecma_property_t *prop_p = ecma_op_object_get_own_property (obj_p, name_str_p); if (prop_p != NULL) { ecma_property_descriptor_t prop_desc = ecma_get_property_descriptor_from_property (prop_p); // 4. ecma_object_t* desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); ecma_free_property_descriptor (&prop_desc); ret_value = ecma_make_normal_completion_value (ecma_make_object_value (desc_obj_p)); } else { ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED); } ECMA_FINALIZE (name_str_value); return ret_value; } /* ecma_builtin_object_object_get_own_property_descriptor */
/** * The Object object's 'defineProperty' routine * * See also: * ECMA-262 v5, 15.2.3.6 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_object_object_define_property (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */ ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2, /**< routine's second argument */ ecma_value_t arg3) /**< routine's third argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); if (!ecma_is_value_object (arg1)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_object_t *obj_p = ecma_get_object_from_value (arg1); ECMA_TRY_CATCH (name_str_value, ecma_op_to_string (arg2), ret_value); ecma_string_t *name_str_p = ecma_get_string_from_value (name_str_value); ecma_property_descriptor_t prop_desc; ECMA_TRY_CATCH (conv_result, ecma_op_to_property_descriptor (arg3, &prop_desc), ret_value); ECMA_TRY_CATCH (define_own_prop_ret, ecma_op_object_define_own_property (obj_p, name_str_p, &prop_desc, true), ret_value); ret_value = ecma_make_normal_completion_value (ecma_copy_value (arg1, true)); ECMA_FINALIZE (define_own_prop_ret); ecma_free_property_descriptor (&prop_desc); ECMA_FINALIZE (conv_result); ECMA_FINALIZE (name_str_value); } return ret_value; } /* ecma_builtin_object_object_define_property */
/** * Deletes an object property. * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t vm_op_delete_prop (ecma_value_t object, /**< base object */ ecma_value_t property, /**< property name */ bool is_strict) /**< strict mode */ { ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (ecma_is_value_undefined (object)) { completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } else { completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ECMA_TRY_CATCH (check_coercible_ret, ecma_op_check_object_coercible (object), completion_value); ECMA_TRY_CATCH (str_name_value, ecma_op_to_string (property), completion_value); JERRY_ASSERT (ecma_is_value_string (str_name_value)); ecma_string_t *name_string_p = ecma_get_string_from_value (str_name_value); ECMA_TRY_CATCH (obj_value, ecma_op_to_object (object), completion_value); JERRY_ASSERT (ecma_is_value_object (obj_value)); ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); ECMA_TRY_CATCH (delete_op_ret_val, ecma_op_object_delete (obj_p, name_string_p, is_strict), completion_value); completion_value = delete_op_ret_val; ECMA_FINALIZE (delete_op_ret_val); ECMA_FINALIZE (obj_value); ECMA_FINALIZE (str_name_value); ECMA_FINALIZE (check_coercible_ret); } return completion_value; } /* vm_op_delete_prop */
/** * The Object.prototype object's 'propertyIsEnumerable' routine * * See also: * ECMA-262 v5, 15.2.4.7 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_object_prototype_object_property_is_enumerable (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's first argument */ { ecma_value_t return_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ ECMA_TRY_CATCH (to_string_val, ecma_op_to_string (arg), return_value); /* 2. */ ECMA_TRY_CATCH (obj_val, ecma_op_to_object (this_arg), return_value); ecma_string_t *property_name_string_p = ecma_get_string_from_value (to_string_val); ecma_object_t *obj_p = ecma_get_object_from_value (obj_val); /* 3. */ ecma_property_t property = ecma_op_object_get_own_property (obj_p, property_name_string_p, NULL, ECMA_PROPERTY_GET_NO_OPTIONS); /* 4. */ if (property != ECMA_PROPERTY_TYPE_NOT_FOUND) { bool is_enumerable = ecma_is_property_enumerable (property); return_value = ecma_make_boolean_value (is_enumerable); } else { return_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE); } ECMA_FINALIZE (obj_val); ECMA_FINALIZE (to_string_val); return return_value; } /* ecma_builtin_object_prototype_object_property_is_enumerable */
/** * The Object.prototype object's 'propertyIsEnumerable' routine * * See also: * ECMA-262 v5, 15.2.4.7 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_object_prototype_object_property_is_enumerable (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg) /**< routine's first argument */ { ecma_completion_value_t return_value = ecma_make_empty_completion_value (); /* 1. */ ECMA_TRY_CATCH (to_string_val, ecma_op_to_string (arg), return_value); /* 2. */ ECMA_TRY_CATCH (obj_val, ecma_op_to_object (this_arg), return_value); ecma_string_t *property_name_string_p = ecma_get_string_from_value (to_string_val); ecma_object_t *obj_p = ecma_get_object_from_value (obj_val); /* 3. */ ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_string_p); /* 4. */ if (property_p != NULL) { bool is_enumerable = ecma_is_property_enumerable (property_p); return_value = ecma_make_simple_completion_value (is_enumerable ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE); } else { return_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_FALSE); } ECMA_FINALIZE (obj_val); ECMA_FINALIZE (to_string_val); return return_value; } /* ecma_builtin_object_prototype_object_property_is_enumerable */
/** * String object creation operation. * * See also: ECMA-262 v5, 15.5.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of arguments that are passed to String constructor */ ecma_length_t arguments_list_len) /**< length of the arguments' list */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); ecma_value_t prim_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); if (arguments_list_len > 0) { prim_value = ecma_op_to_string (arguments_list_p[0]); if (ECMA_IS_VALUE_ERROR (prim_value)) { return prim_value; } JERRY_ASSERT (ecma_is_value_string (prim_value)); } #ifndef CONFIG_DISABLE_STRING_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_STRING_PROTOTYPE); #else /* CONFIG_DISABLE_STRING_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* !CONFIG_DISABLE_STRING_BUILTIN */ ecma_object_t *object_p = ecma_create_object (prototype_obj_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); ecma_deref_object (prototype_obj_p); ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_STRING_UL; ext_object_p->u.class_prop.u.value = prim_value; return ecma_make_object_value (object_p); } /* ecma_op_create_string_object */
/** * Handle calling [[Call]] of built-in String object * * @return completion-value */ ecma_completion_value_t ecma_builtin_string_dispatch_call (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_completion_value_t ret_value = ecma_make_empty_completion_value (); if (arguments_list_len == 0) { ecma_string_t *str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING__EMPTY); ecma_value_t str_value = ecma_make_string_value (str_p); ret_value = ecma_make_normal_completion_value (str_value); } else { ret_value = ecma_op_to_string (arguments_list_p[0]); } return ret_value; } /* ecma_builtin_string_dispatch_call */
/** * Send string representation of exception to the client. * * @return true - if the data sent successfully to the debugger client, * false - otherwise */ bool jerry_debugger_send_exception_string (void) { ecma_string_t *string_p = NULL; ecma_value_t exception_value = JERRY_CONTEXT (error_value); if (ecma_is_value_object (exception_value)) { string_p = jerry_debugger_exception_object_to_string (exception_value); if (string_p == NULL) { string_p = ecma_get_string_from_value (ecma_builtin_helper_object_to_string (exception_value)); } } else if (ecma_is_value_string (exception_value)) { string_p = ecma_get_string_from_value (exception_value); ecma_ref_ecma_string (string_p); } else { exception_value = ecma_op_to_string (exception_value); string_p = ecma_get_string_from_value (exception_value); } ECMA_STRING_TO_UTF8_STRING (string_p, string_data_p, string_size); bool result = jerry_debugger_send_string (JERRY_DEBUGGER_EXCEPTION_STR, JERRY_DEBUGGER_NO_SUBTYPE, string_data_p, string_size); ECMA_FINALIZE_UTF8_STRING (string_data_p, string_size); ecma_deref_ecma_string (string_p); return result; } /* jerry_debugger_send_exception_string */
/** * 'in' opcode handler. * * See also: ECMA-262 v5, 11.8.7 * * @return ecma value * returned value must be freed with ecma_free_value. */ ecma_value_t opfunc_in (ecma_value_t left_value, /**< left value */ ecma_value_t right_value) /**< right value */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (!ecma_is_value_object (right_value)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Expected an object in 'in' check.")); } else { ECMA_TRY_CATCH (str_left_value, ecma_op_to_string (left_value), ret_value); ecma_string_t *left_value_prop_name_p = ecma_get_string_from_value (str_left_value); ecma_object_t *right_value_obj_p = ecma_get_object_from_value (right_value); ret_value = ecma_make_boolean_value (ecma_op_object_has_property (right_value_obj_p, left_value_prop_name_p)); ECMA_FINALIZE (str_left_value); } return ret_value; } /* opfunc_in */
/* * Helper function for string indexOf and lastIndexOf functions * * This function implements string indexOf and lastIndexOf with required checks and conversions. * * See also: * ECMA-262 v5, 15.5.4.7 * ECMA-262 v5, 15.5.4.8 * * Used by: * - The String.prototype.indexOf routine. * - The String.prototype.lastIndexOf routine. * * @return uint32_t - (last)index of search string */ ecma_completion_value_t ecma_builtin_helper_string_prototype_object_index_of (ecma_value_t this_arg, /**< this argument */ ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2, /**< routine's second argument */ bool firstIndex) /**< routine's third argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 1 */ ECMA_TRY_CATCH (check_coercible_val, ecma_op_check_object_coercible (this_arg), ret_value); /* 2 */ ECMA_TRY_CATCH (to_str_val, ecma_op_to_string (this_arg), ret_value); /* 3 */ ECMA_TRY_CATCH (search_str_val, ecma_op_to_string (arg1), ret_value); /* 4 */ ECMA_OP_TO_NUMBER_TRY_CATCH (pos_num, arg2, ret_value); /* 6 */ ecma_string_t *original_str_p = ecma_get_string_from_value (to_str_val); const ecma_length_t original_len = ecma_string_get_length (original_str_p); const lit_utf8_size_t original_size = ecma_string_get_size (original_str_p); /* 4b, 5, 7 */ ecma_length_t start = ecma_builtin_helper_string_index_normalize (pos_num, original_len, firstIndex); /* 8 */ ecma_string_t *search_str_p = ecma_get_string_from_value (search_str_val); const ecma_length_t search_len = ecma_string_get_length (search_str_p); const lit_utf8_size_t search_size = ecma_string_get_size (search_str_p); ecma_number_t *ret_num_p = ecma_alloc_number (); *ret_num_p = ecma_int32_to_number (-1); /* 9 */ if (search_len <= original_len) { if (!search_len) { *ret_num_p = ecma_uint32_to_number (firstIndex ? 0 : original_len); } else { /* create utf8 string from original string and advance to position */ MEM_DEFINE_LOCAL_ARRAY (original_str_utf8_p, original_size, lit_utf8_byte_t); ecma_string_to_utf8_string (original_str_p, original_str_utf8_p, (ssize_t) (original_size)); lit_utf8_iterator_t original_it = lit_utf8_iterator_create (original_str_utf8_p, original_size); ecma_length_t index = start; lit_utf8_iterator_advance (&original_it, index); /* create utf8 string from search string */ MEM_DEFINE_LOCAL_ARRAY (search_str_utf8_p, search_size, lit_utf8_byte_t); ecma_string_to_utf8_string (search_str_p, search_str_utf8_p, (ssize_t) (search_size)); lit_utf8_iterator_t search_it = lit_utf8_iterator_create (search_str_utf8_p, search_size); /* iterate original string and try to match at each position */ bool searching = true; while (searching) { /* match as long as possible */ ecma_length_t match_len = 0; lit_utf8_iterator_t stored_original_it = original_it; while (match_len < search_len && index + match_len < original_len && lit_utf8_iterator_read_next (&original_it) == lit_utf8_iterator_read_next (&search_it)) { match_len++; } /* check for match */ if (match_len == search_len) { *ret_num_p = ecma_uint32_to_number (index); break; } else { /* inc/dec index and update iterators and search condition */ lit_utf8_iterator_seek_bos (&search_it); original_it = stored_original_it; if (firstIndex) { if ((searching = (index <= original_len - search_len))) { lit_utf8_iterator_incr (&original_it); index++; } } else { if ((searching = (index > 0))) { lit_utf8_iterator_decr (&original_it); index--; } } } } MEM_FINALIZE_LOCAL_ARRAY (search_str_utf8_p); MEM_FINALIZE_LOCAL_ARRAY (original_str_utf8_p); } } ecma_value_t new_value = ecma_make_number_value (ret_num_p); ret_value = ecma_make_normal_completion_value (new_value); ECMA_OP_TO_NUMBER_FINALIZE (pos_num); ECMA_FINALIZE (search_str_val); ECMA_FINALIZE (to_str_val); ECMA_FINALIZE (check_coercible_val); return ret_value; } /* ecma_builtin_helper_string_index_normalize */
/** * String object creation operation. * * See also: ECMA-262 v5, 15.5.2.1 * * @return ecma value * Returned value must be freed with ecma_free_value */ ecma_value_t ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of arguments that are passed to String constructor */ ecma_length_t arguments_list_len) /**< length of the arguments' list */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); ecma_string_t *prim_prop_str_value_p; ecma_number_t length_value; if (arguments_list_len == 0) { prim_prop_str_value_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING__EMPTY); length_value = ECMA_NUMBER_ZERO; } else { ecma_value_t to_str_arg_value = ecma_op_to_string (arguments_list_p[0]); if (ECMA_IS_VALUE_ERROR (to_str_arg_value)) { return to_str_arg_value; } else { JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (to_str_arg_value)); JERRY_ASSERT (ecma_is_value_string (to_str_arg_value)); prim_prop_str_value_p = ecma_get_string_from_value (to_str_arg_value); ecma_length_t string_len = ecma_string_get_length (prim_prop_str_value_p); length_value = ((ecma_number_t) (uint32_t) string_len); } } #ifndef CONFIG_DISABLE_STRING_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_STRING_PROTOTYPE); #else /* CONFIG_DISABLE_STRING_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* !CONFIG_DISABLE_STRING_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, false, true, ECMA_OBJECT_TYPE_STRING); ecma_deref_object (prototype_obj_p); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_STRING type. * * See also: ecma_object_get_class_name */ ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_ECMA_VALUE); ecma_set_internal_property_value (prim_value_prop_p, ecma_make_string_value (prim_prop_str_value_p)); // 15.5.5.1 ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string (); ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p, length_magic_string_p, ECMA_PROPERTY_FIXED); ecma_set_named_data_property_value (length_prop_p, ecma_make_number_value (length_value)); ecma_deref_ecma_string (length_magic_string_p); return ecma_make_object_value (obj_p); } /* ecma_op_create_string_object */
/** * 'Native call' opcode handler. */ ecma_completion_value_t opfunc_native_call (opcode_t opdata, /**< operation data */ int_data_t *int_data) /**< interpreter context */ { const idx_t dst_var_idx = opdata.data.native_call.lhs; const idx_t native_call_id_idx = opdata.data.native_call.name; const idx_t args_number = opdata.data.native_call.arg_list; const opcode_counter_t lit_oc = int_data->pos; JERRY_ASSERT (native_call_id_idx < OPCODE_NATIVE_CALL__COUNT); int_data->pos++; JERRY_STATIC_ASSERT (OPCODE_NATIVE_CALL__COUNT < (1u << (sizeof (native_call_id_idx) * JERRY_BITSINBYTE))); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); MEM_DEFINE_LOCAL_ARRAY (arg_values, args_number, ecma_value_t); ecma_length_t args_read; ecma_completion_value_t get_arg_completion = fill_varg_list (int_data, args_number, arg_values, &args_read); if (ecma_is_completion_value_empty (get_arg_completion)) { JERRY_ASSERT (args_read == args_number); switch ((opcode_native_call_t)native_call_id_idx) { case OPCODE_NATIVE_CALL_LED_TOGGLE: case OPCODE_NATIVE_CALL_LED_ON: case OPCODE_NATIVE_CALL_LED_OFF: case OPCODE_NATIVE_CALL_LED_ONCE: case OPCODE_NATIVE_CALL_WAIT: { JERRY_UNIMPLEMENTED ("Device operations are not implemented."); } case OPCODE_NATIVE_CALL_PRINT: { for (ecma_length_t arg_index = 0; ecma_is_completion_value_empty (ret_value) && arg_index < args_read; arg_index++) { ECMA_TRY_CATCH (str_value, ecma_op_to_string (arg_values[arg_index]), ret_value); ecma_string_t *str_p = ecma_get_string_from_value (str_value); lit_utf8_size_t bytes = ecma_string_get_size (str_p); ssize_t utf8_str_size = (ssize_t) (bytes + 1); lit_utf8_byte_t *utf8_str_p = (lit_utf8_byte_t*) mem_heap_alloc_block ((size_t) utf8_str_size, MEM_HEAP_ALLOC_SHORT_TERM); if (utf8_str_p == NULL) { jerry_fatal (ERR_OUT_OF_MEMORY); } ecma_string_to_utf8_string (str_p, utf8_str_p, utf8_str_size); utf8_str_p[utf8_str_size - 1] = 0; FIXME ("Support unicode in printf."); if (arg_index < args_read - 1) { printf ("%s ", (char*) utf8_str_p); } else { printf ("%s", (char*) utf8_str_p); } mem_heap_free_block (utf8_str_p); ret_value = set_variable_value (int_data, lit_oc, dst_var_idx, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED)); ECMA_FINALIZE (str_value); } printf ("\n"); break; } case OPCODE_NATIVE_CALL__COUNT: { JERRY_UNREACHABLE (); } } } else { JERRY_ASSERT (!ecma_is_completion_value_normal (get_arg_completion)); ret_value = get_arg_completion; } for (ecma_length_t arg_index = 0; arg_index < args_read; arg_index++) { ecma_free_value (arg_values[arg_index], true); } MEM_FINALIZE_LOCAL_ARRAY (arg_values); return ret_value; } /* opfunc_native_call */
/** * Send result of evaluated expression or throw an error. * * @return true - if execution should be resumed * false - otherwise */ static bool jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated string */ size_t eval_string_size) /**< evaluated string size */ { JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED); JERRY_ASSERT (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE)); JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_IGNORE); ecma_value_t result = ecma_op_eval_chars_buffer (eval_string_p + 1, eval_string_size - 1, true, false); JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_IGNORE); if (!ECMA_IS_VALUE_ERROR (result)) { if (eval_string_p[0] != JERRY_DEBUGGER_EVAL_EVAL) { JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN); JERRY_CONTEXT (error_value) = result; /* Stop where the error is caught. */ JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); JERRY_CONTEXT (debugger_stop_context) = NULL; if (eval_string_p[0] == JERRY_DEBUGGER_EVAL_THROW) { JERRY_CONTEXT (status_flags) |= ECMA_STATUS_EXCEPTION; } else { JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_EXCEPTION; } return true; } if (!ecma_is_value_string (result)) { ecma_value_t to_string_value = ecma_op_to_string (result); ecma_free_value (result); result = to_string_value; } } ecma_value_t message = result; uint8_t type = JERRY_DEBUGGER_EVAL_OK; if (ECMA_IS_VALUE_ERROR (result)) { type = JERRY_DEBUGGER_EVAL_ERROR; result = JERRY_CONTEXT (error_value); if (ecma_is_value_object (result)) { message = ecma_op_object_find (ecma_get_object_from_value (result), ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE)); if (!ecma_is_value_string (message) || ecma_string_is_empty (ecma_get_string_from_value (message))) { ecma_free_value (message); lit_magic_string_id_t id = ecma_object_get_class_name (ecma_get_object_from_value (result)); ecma_free_value (result); const lit_utf8_byte_t *string_p = lit_get_magic_string_utf8 (id); jerry_debugger_send_string (JERRY_DEBUGGER_EVAL_RESULT, type, string_p, strlen ((const char *) string_p)); return false; } } else { /* Primitive type. */ message = ecma_op_to_string (result); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (message)); } ecma_free_value (result); } ecma_string_t *string_p = ecma_get_string_from_value (message); ECMA_STRING_TO_UTF8_STRING (string_p, buffer_p, buffer_size); jerry_debugger_send_string (JERRY_DEBUGGER_EVAL_RESULT, type, buffer_p, buffer_size); ECMA_FINALIZE_UTF8_STRING (buffer_p, buffer_size); ecma_free_value (message); return false; } /* jerry_debugger_send_eval */
/** * The RegExp.prototype object's 'compile' routine * * See also: * ECMA-262 v5, B.2.5.1 * * @return undefined - if compiled successfully * error ecma value - otherwise * * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_regexp_prototype_compile (ecma_value_t this_arg, /**< this argument */ ecma_value_t pattern_arg, /**< pattern or RegExp object */ ecma_value_t flags_arg) /**< flags */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); if (!ecma_is_value_object (this_arg) || ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_REGEXP_UL) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Incomplete RegExp type")); } else { ecma_string_t *pattern_string_p = NULL; uint16_t flags = 0; if (ecma_is_value_object (pattern_arg) && ecma_object_get_class_name (ecma_get_object_from_value (pattern_arg)) == LIT_MAGIC_STRING_REGEXP_UL) { if (!ecma_is_value_undefined (flags_arg)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument of RegExp compile.")); } else { /* Compile from existing RegExp pbject. */ ecma_object_t *target_p = ecma_get_object_from_value (pattern_arg); /* Get source. */ ecma_string_t *magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE); ecma_property_t *prop_p = ecma_op_object_get_property (target_p, magic_string_p); pattern_string_p = ecma_get_string_from_value (ecma_get_named_data_property_value (prop_p)); ecma_deref_ecma_string (magic_string_p); /* Get flags. */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); prop_p = ecma_op_object_get_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_GLOBAL; } ecma_deref_ecma_string (magic_string_p); magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL); prop_p = ecma_op_object_get_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_IGNORE_CASE; } ecma_deref_ecma_string (magic_string_p); magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE); prop_p = ecma_op_object_get_property (target_p, magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (prop_p))) { flags |= RE_FLAG_MULTILINE; } ecma_deref_ecma_string (magic_string_p); ECMA_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ecma_object_t *this_obj_p = ecma_get_object_from_value (obj_this); /* Get bytecode property. */ ecma_property_t *bc_prop_p = ecma_get_internal_property (this_obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* TODO: We currently have to re-compile the bytecode, because * we can't copy it without knowing its length. */ const re_compiled_code_t *new_bc_p = NULL; ecma_value_t bc_comp = re_compile_bytecode (&new_bc_p, pattern_string_p, flags); /* Should always succeed, since we're compiling from a source that has been compiled previously. */ JERRY_ASSERT (ecma_is_value_empty (bc_comp)); re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, ecma_get_internal_property_value (bc_prop_p)); if (old_bc_p != NULL) { /* Free the old bytecode */ ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); } ECMA_SET_INTERNAL_VALUE_POINTER (ECMA_PROPERTY_VALUE_PTR (bc_prop_p)->value, new_bc_p); re_initialize_props (this_obj_p, pattern_string_p, flags); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); ECMA_FINALIZE (obj_this); } } else { /* Get source string. */ if (!ecma_is_value_undefined (pattern_arg)) { ECMA_TRY_CATCH (regexp_str_value, ecma_op_to_string (pattern_arg), ret_value); if (ecma_string_is_empty (ecma_get_string_from_value (regexp_str_value))) { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } else { pattern_string_p = ecma_get_string_from_value (regexp_str_value); ecma_ref_ecma_string (pattern_string_p); } ECMA_FINALIZE (regexp_str_value); } else { pattern_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP); } /* Parse flags. */ if (ecma_is_value_empty (ret_value) && !ecma_is_value_undefined (flags_arg)) { ECMA_TRY_CATCH (flags_str_value, ecma_op_to_string (flags_arg), ret_value); ECMA_TRY_CATCH (flags_dummy, re_parse_regexp_flags (ecma_get_string_from_value (flags_str_value), &flags), ret_value); ECMA_FINALIZE (flags_dummy); ECMA_FINALIZE (flags_str_value); } if (ecma_is_value_empty (ret_value)) { ECMA_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ecma_object_t *this_obj_p = ecma_get_object_from_value (obj_this); ecma_property_t *bc_prop_p = ecma_get_internal_property (this_obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); /* Try to compile bytecode from new source. */ const re_compiled_code_t *new_bc_p = NULL; ECMA_TRY_CATCH (bc_dummy, re_compile_bytecode (&new_bc_p, pattern_string_p, flags), ret_value); re_compiled_code_t *old_bc_p = ECMA_GET_INTERNAL_VALUE_POINTER (re_compiled_code_t, ecma_get_internal_property_value (bc_prop_p)); if (old_bc_p != NULL) { /* Free the old bytecode */ ecma_bytecode_deref ((ecma_compiled_code_t *) old_bc_p); } ECMA_SET_INTERNAL_VALUE_POINTER (ECMA_PROPERTY_VALUE_PTR (bc_prop_p)->value, new_bc_p); re_initialize_props (this_obj_p, pattern_string_p, flags); ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); ECMA_FINALIZE (bc_dummy); ECMA_FINALIZE (obj_this); } if (pattern_string_p != NULL) { ecma_deref_ecma_string (pattern_string_p); } } } return ret_value; } /* ecma_builtin_regexp_prototype_compile */