/** * The String.prototype object's 'toString' routine * * See also: * ECMA-262 v5, 15.5.4.2 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ { if (ecma_is_value_string (this_arg)) { return ecma_make_normal_completion_value (ecma_copy_value (this_arg, true)); } else if (ecma_is_value_object (this_arg)) { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_STRING_UL) { ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_STRING_VALUE); ecma_string_t *prim_value_str_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prim_value_prop_p->u.internal_property.value); prim_value_str_p = ecma_copy_or_ref_ecma_string (prim_value_str_p); return ecma_make_normal_completion_value (ecma_make_string_value (prim_value_str_p)); } } return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } /* ecma_builtin_string_prototype_object_to_string */
/** * The Number.prototype object's 'valueOf' routine * * See also: * ECMA-262 v5, 15.7.4.4 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_number_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */ { if (ecma_is_value_number (this_arg)) { return ecma_copy_value (this_arg); } else if (ecma_is_value_object (this_arg)) { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_NUMBER_UL) { ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); ecma_number_t *prim_value_num_p; prim_value_num_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_number_t, ecma_get_internal_property_value (prim_value_prop_p)); ecma_number_t *ret_num_p = ecma_alloc_number (); *ret_num_p = *prim_value_num_p; return ecma_make_number_value (ret_num_p); } } return ecma_raise_type_error (ECMA_ERR_MSG ("")); } /* ecma_builtin_number_prototype_object_value_of */
/** * The Date.prototype object's 'setTime' routine * * See also: * ECMA-262 v5, 15.9.5.27 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_date_prototype_set_time (ecma_value_t this_arg, /**< this argument */ ecma_value_t time) /**< time */ { 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_DATE_UL) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Incompatible type")); } else { /* 1. */ ECMA_OP_TO_NUMBER_TRY_CATCH (t, time, ret_value); ecma_number_t *value_p = ecma_alloc_number (); *value_p = ecma_date_time_clip (t); /* 2. */ ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); ecma_property_t *prim_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); ecma_number_t *prim_value_num_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_number_t, ecma_get_internal_property_value (prim_prop_p)); *prim_value_num_p = *value_p; /* 3. */ ret_value = ecma_make_number_value (value_p); ECMA_OP_TO_NUMBER_FINALIZE (t); } return ret_value; } /* ecma_builtin_date_prototype_set_time */
/** * 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 Date.prototype object's 'getTime' routine * * See also: * ECMA-262 v5, 15.9.5.9 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_date_prototype_get_time (ecma_value_t this_arg) /**< this argument */ { if (ecma_is_value_object (this_arg)) { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_DATE_UL) { ecma_value_t *date_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_DATE_FLOAT); ecma_number_t *date_num_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_number_t, *date_prop_p); return ecma_make_number_value (*date_num_p); } } return ecma_raise_type_error (ECMA_ERR_MSG ("")); } /* ecma_builtin_date_prototype_get_time */
/** * The Array object's 'isArray' routine * * See also: * ECMA-262 v5, 15.4.3.2 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_array_object_is_array (ecma_value_t this_arg, /**< 'this' argument */ ecma_value_t arg) /**< first argument */ { JERRY_UNUSED (this_arg); ecma_simple_value_t is_array = ECMA_SIMPLE_VALUE_FALSE; if (ecma_is_value_object (arg)) { ecma_object_t *obj_p = ecma_get_object_from_value (arg); if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_ARRAY_UL) { is_array = ECMA_SIMPLE_VALUE_TRUE; } } return ecma_make_simple_value (is_array); } /* ecma_builtin_array_object_is_array */
/** * The Date.prototype object's 'getTime' routine * * See also: * ECMA-262 v5, 15.9.5.9 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_date_prototype_get_time (ecma_value_t this_arg) /**< this argument */ { if (ecma_is_value_object (this_arg)) { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_DATE_UL) { ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); ecma_number_t *prim_value_num_p = ECMA_GET_NON_NULL_POINTER (ecma_number_t, prim_value_prop_p->u.internal_property.value); ecma_number_t *ret_num_p = ecma_alloc_number (); *ret_num_p = *prim_value_num_p; return ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p)); } } return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } /* ecma_builtin_date_prototype_get_time */
/** * The Date.prototype object's 'toDateString' routine * * See also: * ECMA-262 v5, 15.9.5.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_date_prototype_to_date_string (ecma_value_t this_arg) /**< this 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_DATE_UL) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Incompatible type")); } else { ECMA_TRY_CATCH (obj_this, ecma_op_to_object (this_arg), ret_value); ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); ecma_property_t *prim_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); ecma_number_t *prim_value_num_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_number_t, ecma_get_internal_property_value (prim_prop_p)); if (ecma_number_is_nan (*prim_value_num_p)) { ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INVALID_DATE_UL); ret_value = ecma_make_string_value (magic_str_p); } else { ret_value = ecma_date_value_to_date_string (*prim_value_num_p); } ECMA_FINALIZE (obj_this); } return ret_value; } /* ecma_builtin_date_prototype_to_date_string */
/** * The Number.prototype object's 'valueOf' routine * * See also: * ECMA-262 v5, 15.7.4.4 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_number_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */ { if (ecma_is_value_number (this_arg)) { return ecma_copy_value (this_arg); } else if (ecma_is_value_object (this_arg)) { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_NUMBER_UL) { ecma_property_t *prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_ECMA_VALUE); JERRY_ASSERT (ecma_is_value_number (ecma_get_internal_property_value (prim_value_prop_p))); return ecma_copy_value (ecma_get_internal_property_value (prim_value_prop_p)); } } return ecma_raise_type_error (ECMA_ERR_MSG ("")); } /* ecma_builtin_number_prototype_object_value_of */
/** * The Function.prototype object's 'bind' routine * * See also: * ECMA-262 v5, 15.3.4.5 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_function_prototype_object_bind (ecma_value_t this_arg, /**< this argument */ const ecma_value_t *arguments_list_p, /**< list of arguments */ ecma_length_t arguments_number) /**< number of arguments */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 2. */ if (!ecma_op_is_callable (this_arg)) { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("")); } else { /* 4. 11. 18. */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_object_t *function_p = ecma_create_object (prototype_obj_p, false, true, ECMA_OBJECT_TYPE_BOUND_FUNCTION); ecma_deref_object (prototype_obj_p); /* 7. */ ecma_value_t *target_function_prop_p; target_function_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION); ecma_object_t *this_arg_obj_p = ecma_get_object_from_value (this_arg); ECMA_SET_INTERNAL_VALUE_POINTER (*target_function_prop_p, this_arg_obj_p); /* 8. */ ecma_value_t *bound_this_prop_p; bound_this_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS); const ecma_length_t arg_count = arguments_number; if (arg_count > 0) { *bound_this_prop_p = ecma_copy_value_if_not_object (arguments_list_p[0]); } else { *bound_this_prop_p = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } if (arg_count > 1) { ecma_collection_header_t *bound_args_collection_p; bound_args_collection_p = ecma_new_values_collection (&arguments_list_p[1], arg_count - 1, false); ecma_value_t *bound_args_prop_p; bound_args_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS); ECMA_SET_INTERNAL_VALUE_POINTER (*bound_args_prop_p, bound_args_collection_p); } /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. * * See also: ecma_object_get_class_name */ /* 16. */ ecma_number_t length = ECMA_NUMBER_ZERO; ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string (); /* 15. */ if (ecma_object_get_class_name (this_arg_obj_p) == LIT_MAGIC_STRING_FUNCTION_UL) { ecma_value_t get_len_value = ecma_op_object_get (this_arg_obj_p, magic_string_length_p); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (get_len_value)); JERRY_ASSERT (ecma_is_value_number (get_len_value)); const ecma_length_t bound_arg_count = arg_count > 1 ? arg_count - 1 : 0; /* 15.a */ length = ecma_get_number_from_value (get_len_value) - ((ecma_number_t) bound_arg_count); ecma_free_value (get_len_value); /* 15.b */ if (ecma_number_is_negative (length)) { length = ECMA_NUMBER_ZERO; } } /* 17. */ ecma_value_t completion = ecma_builtin_helper_def_prop (function_p, magic_string_length_p, ecma_make_number_value (length), false, /* Writable */ false, /* Enumerable */ false, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_boolean (completion)); ecma_deref_ecma_string (magic_string_length_p); /* 19-21. */ ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = false; prop_desc.is_get_defined = true; prop_desc.get_p = thrower_p; prop_desc.is_set_defined = true; prop_desc.set_p = thrower_p; } ecma_string_t *magic_string_caller_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER); completion = ecma_op_object_define_own_property (function_p, magic_string_caller_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_boolean (completion)); ecma_deref_ecma_string (magic_string_caller_p); ecma_string_t *magic_string_arguments_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS); completion = ecma_op_object_define_own_property (function_p, magic_string_arguments_p, &prop_desc, false); JERRY_ASSERT (ecma_is_value_boolean (completion)); ecma_deref_ecma_string (magic_string_arguments_p); ecma_deref_object (thrower_p); /* 22. */ ret_value = ecma_make_object_value (function_p); } return ret_value; } /* ecma_builtin_function_prototype_object_bind */
/** * RegExp helper function to start the recursive matching algorithm * and create the result Array object * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_regexp_exec_helper (ecma_value_t regexp_value, /**< RegExp object */ ecma_value_t input_string, /**< input string */ bool ignore_global) /**< ignore global flag */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); JERRY_ASSERT (ecma_is_value_object (regexp_value)); JERRY_ASSERT (ecma_is_value_string (input_string)); ecma_object_t *regexp_object_p = ecma_get_object_from_value (regexp_value); JERRY_ASSERT (ecma_object_get_class_name (regexp_object_p) == LIT_MAGIC_STRING_REGEXP_UL); ecma_property_t *bytecode_prop_p = ecma_get_internal_property (regexp_object_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); re_bytecode_t *bc_p = ECMA_GET_POINTER (re_bytecode_t, bytecode_prop_p->u.internal_property.value); ecma_string_t *input_string_p = ecma_get_string_from_value (input_string); lit_utf8_size_t input_string_size = ecma_string_get_size (input_string_p); MEM_DEFINE_LOCAL_ARRAY (input_utf8_buffer_p, input_string_size, lit_utf8_byte_t); ecma_string_to_utf8_string (input_string_p, input_utf8_buffer_p, (ssize_t) input_string_size); lit_utf8_iterator_t iterator = lit_utf8_iterator_create (input_utf8_buffer_p, input_string_size); re_matcher_ctx_t re_ctx; re_ctx.input_start_p = iterator.buf_p; re_ctx.input_end_p = iterator.buf_p + iterator.buf_size; /* 1. Read bytecode header and init regexp matcher context. */ re_ctx.flags = (uint8_t) re_get_value (&bc_p); if (ignore_global) { re_ctx.flags &= (uint8_t) ~RE_FLAG_GLOBAL; } JERRY_DDLOG ("Exec with flags [global: %d, ignoreCase: %d, multiline: %d]\n", re_ctx.flags & RE_FLAG_GLOBAL, re_ctx.flags & RE_FLAG_IGNORE_CASE, re_ctx.flags & RE_FLAG_MULTILINE); re_ctx.num_of_captures = re_get_value (&bc_p); JERRY_ASSERT (re_ctx.num_of_captures % 2 == 0); re_ctx.num_of_non_captures = re_get_value (&bc_p); /* We create an invalid iterator, that will be used to identify unused result values. */ lit_utf8_iterator_t unused_iter = lit_utf8_iterator_create (NULL, 0); unused_iter.buf_p = (lit_utf8_byte_t *) 1; MEM_DEFINE_LOCAL_ARRAY (saved_p, re_ctx.num_of_captures + re_ctx.num_of_non_captures, lit_utf8_iterator_t); for (uint32_t i = 0; i < re_ctx.num_of_captures + re_ctx.num_of_non_captures; i++) { saved_p[i] = unused_iter; } re_ctx.saved_p = saved_p; uint32_t num_of_iter_length = (re_ctx.num_of_captures / 2) + (re_ctx.num_of_non_captures - 1); MEM_DEFINE_LOCAL_ARRAY (num_of_iter_p, num_of_iter_length, uint32_t); for (uint32_t i = 0; i < num_of_iter_length; i++) { num_of_iter_p[i] = 0u; } bool is_match = false; re_ctx.num_of_iterations_p = num_of_iter_p; int32_t index = 0; ecma_length_t input_str_len = lit_utf8_string_length (iterator.buf_p, iterator.buf_size); if (iterator.buf_p && (re_ctx.flags & RE_FLAG_GLOBAL)) { ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); ecma_property_t *lastindex_prop_p = ecma_op_object_get_property (regexp_object_p, magic_str_p); ECMA_OP_TO_NUMBER_TRY_CATCH (lastindex_num, lastindex_prop_p->u.named_data_property.value, ret_value) index = ecma_number_to_int32 (lastindex_num); JERRY_ASSERT (iterator.buf_pos.offset == 0 && !iterator.buf_pos.is_non_bmp_middle); if (!lit_utf8_iterator_is_eos (&iterator) && index <= (int32_t) input_str_len && index > 0) { lit_utf8_iterator_advance (&iterator, (ecma_length_t) index); } ECMA_OP_TO_NUMBER_FINALIZE (lastindex_num); ecma_deref_ecma_string (magic_str_p); } /* 2. Try to match */ lit_utf8_iterator_t sub_iter = lit_utf8_iterator_create (NULL, 0); while (ecma_is_completion_value_empty (ret_value)) { if (index < 0 || index > (int32_t) input_str_len) { if (re_ctx.flags & RE_FLAG_GLOBAL) { ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); ecma_number_t *lastindex_num_p = ecma_alloc_number (); *lastindex_num_p = ECMA_NUMBER_ZERO; ecma_op_object_put (regexp_object_p, magic_str_p, ecma_make_number_value (lastindex_num_p), true); ecma_dealloc_number (lastindex_num_p); ecma_deref_ecma_string (magic_str_p); } is_match = false; break; } else { ECMA_TRY_CATCH (match_value, re_match_regexp (&re_ctx, bc_p, iterator, &sub_iter), ret_value); if (ecma_is_value_true (match_value)) { is_match = true; break; } if (!lit_utf8_iterator_is_eos (&iterator)) { lit_utf8_iterator_advance (&iterator, 1); } index++; ECMA_FINALIZE (match_value); } } if (iterator.buf_p && (re_ctx.flags & RE_FLAG_GLOBAL)) { ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); ecma_number_t *lastindex_num_p = ecma_alloc_number (); *lastindex_num_p = sub_iter.buf_pos.offset; ecma_op_object_put (regexp_object_p, magic_str_p, ecma_make_number_value (lastindex_num_p), true); ecma_dealloc_number (lastindex_num_p); ecma_deref_ecma_string (magic_str_p); } /* 3. Fill the result array or return with 'undefiend' */ if (ecma_is_completion_value_empty (ret_value)) { if (is_match) { ecma_completion_value_t result_array = ecma_op_create_array_object (0, 0, false); ecma_object_t *result_array_obj_p = ecma_get_object_from_completion_value (result_array); ecma_string_t *input_str_p = ecma_new_ecma_string_from_utf8 (iterator.buf_p, iterator.buf_size); re_set_result_array_properties (result_array_obj_p, input_str_p, re_ctx.num_of_captures / 2, index); ecma_deref_ecma_string (input_str_p); for (uint32_t i = 0; i < re_ctx.num_of_captures; i += 2) { ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (i / 2); /* Note: 'iter_p->buf_p == NULL' means the input is empty string */ if ((re_ctx.saved_p[i].buf_p != unused_iter.buf_p && re_ctx.saved_p[i + 1].buf_p != unused_iter.buf_p) && re_ctx.saved_p[i + 1].buf_pos.offset >= re_ctx.saved_p[i].buf_pos.offset) { ecma_length_t capture_str_len; capture_str_len = (ecma_length_t) re_ctx.saved_p[i + 1].buf_pos.offset - re_ctx.saved_p[i].buf_pos.offset; ecma_string_t *capture_str_p; if (capture_str_len > 0) { const lit_utf8_byte_t *utf8_str_p = re_ctx.saved_p[i].buf_p + re_ctx.saved_p[i].buf_pos.offset; capture_str_p = ecma_new_ecma_string_from_utf8 (utf8_str_p, capture_str_len); } else { capture_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } ecma_op_object_put (result_array_obj_p, index_str_p, ecma_make_string_value (capture_str_p), true); ecma_deref_ecma_string (capture_str_p); } else { ecma_op_object_put (result_array_obj_p, index_str_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), true); } ecma_deref_ecma_string (index_str_p); } ret_value = result_array; } else { ret_value = ecma_make_normal_completion_value (ecma_make_simple_value (ECMA_SIMPLE_VALUE_NULL)); } } MEM_FINALIZE_LOCAL_ARRAY (num_of_iter_p); MEM_FINALIZE_LOCAL_ARRAY (saved_p); MEM_FINALIZE_LOCAL_ARRAY (input_utf8_buffer_p); return ret_value; } /* ecma_regexp_exec_helper */
/** * 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 */
/** * The RegExp.prototype object's 'toString' routine * * See also: * ECMA-262 v5, 15.10.6.4 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_regexp_prototype_to_string (ecma_value_t this_arg) /**< this 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_object_t *obj_p = ecma_get_object_from_value (obj_this); /* Get RegExp source from the source property */ ecma_string_t *magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE); ecma_property_t *source_prop_p = ecma_op_object_get_property (obj_p, magic_string_p); ecma_deref_ecma_string (magic_string_p); ecma_string_t *src_sep_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_SLASH_CHAR); ecma_string_t *source_str_p = ecma_get_string_from_value (ecma_get_named_data_property_value (source_prop_p)); ecma_string_t *output_str_p = ecma_concat_ecma_strings (src_sep_str_p, source_str_p); ecma_string_t *concat_p = ecma_concat_ecma_strings (output_str_p, src_sep_str_p); ecma_deref_ecma_string (src_sep_str_p); ecma_deref_ecma_string (output_str_p); output_str_p = concat_p; /* Check the global flag */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); ecma_property_t *global_prop_p = ecma_op_object_get_property (obj_p, magic_string_p); ecma_deref_ecma_string (magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (global_prop_p))) { ecma_string_t *g_flag_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_G_CHAR); concat_p = ecma_concat_ecma_strings (output_str_p, g_flag_str_p); ecma_deref_ecma_string (output_str_p); ecma_deref_ecma_string (g_flag_str_p); output_str_p = concat_p; } /* Check the ignoreCase flag */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL); ecma_property_t *ignorecase_prop_p = ecma_op_object_get_property (obj_p, magic_string_p); ecma_deref_ecma_string (magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (ignorecase_prop_p))) { ecma_string_t *ic_flag_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_I_CHAR); concat_p = ecma_concat_ecma_strings (output_str_p, ic_flag_str_p); ecma_deref_ecma_string (output_str_p); ecma_deref_ecma_string (ic_flag_str_p); output_str_p = concat_p; } /* Check the global flag */ magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE); ecma_property_t *multiline_prop_p = ecma_op_object_get_property (obj_p, magic_string_p); ecma_deref_ecma_string (magic_string_p); if (ecma_is_value_true (ecma_get_named_data_property_value (multiline_prop_p))) { ecma_string_t *m_flag_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_M_CHAR); concat_p = ecma_concat_ecma_strings (output_str_p, m_flag_str_p); ecma_deref_ecma_string (output_str_p); ecma_deref_ecma_string (m_flag_str_p); output_str_p = concat_p; } ret_value = ecma_make_string_value (output_str_p); ECMA_FINALIZE (obj_this); } return ret_value; } /* ecma_builtin_regexp_prototype_to_string */
/** * The RegExp.prototype object's 'exec' routine * * See also: * ECMA-262 v5, 15.10.6.2 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_regexp_prototype_exec (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 (); 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 ("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_completion_value (obj_this); bytecode_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE); void *bytecode_p = ECMA_GET_POINTER (void, bytecode_prop_p->u.internal_property.value); if (bytecode_p == NULL) { /* Missing bytecode means empty RegExp: '/(?:)/', so always return empty string. */ ecma_completion_value_t result_array = ecma_op_create_array_object (0, 0, false); ecma_object_t *result_array_obj_p = ecma_get_object_from_completion_value (result_array); ecma_string_t *input_str_p = ecma_get_string_from_value (input_str_value); re_set_result_array_properties (result_array_obj_p, input_str_p, 1, 0); ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (0); ecma_string_t *capture_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ECMA_TRY_CATCH (put_res_value, ecma_op_object_put (result_array_obj_p, index_str_p, ecma_make_string_value (capture_str_p), true), ret_value); ret_value = result_array; ECMA_FINALIZE (put_res_value) ecma_deref_ecma_string (capture_str_p); ecma_deref_ecma_string (index_str_p); } 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 */
/** * Handle calling [[Construct]] of built-in RegExp object * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_regexp_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< number of arguments */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_value_t pattern_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); ecma_value_t flags_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); if (arguments_list_len > 0) { /* pattern string or RegExp object */ pattern_value = arguments_list_p[0]; if (arguments_list_len > 1) { flags_value = arguments_list_p[1]; } } if (ecma_is_value_object (pattern_value) && ecma_object_get_class_name (ecma_get_object_from_value (pattern_value)) == LIT_MAGIC_STRING_REGEXP_UL) { if (ecma_is_value_undefined (flags_value)) { ret_value = ecma_copy_value (pattern_value); } else { ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument of RegExp call.")); } } else { ecma_string_t *pattern_string_p = NULL; ecma_string_t *flags_string_p = NULL; if (!ecma_is_value_undefined (pattern_value)) { ECMA_TRY_CATCH (regexp_str_value, ecma_op_to_string (pattern_value), 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); } if (ecma_is_value_empty (ret_value) && !ecma_is_value_undefined (flags_value)) { ECMA_TRY_CATCH (flags_str_value, ecma_op_to_string (flags_value), ret_value); flags_string_p = ecma_get_string_from_value (flags_str_value); ecma_ref_ecma_string (flags_string_p); ECMA_FINALIZE (flags_str_value); } if (ecma_is_value_empty (ret_value)) { ret_value = ecma_op_create_regexp_object (pattern_string_p, flags_string_p); } if (pattern_string_p != NULL) { ecma_deref_ecma_string (pattern_string_p); } if (flags_string_p != NULL) { ecma_deref_ecma_string (flags_string_p); } } return ret_value; } /* ecma_builtin_regexp_dispatch_construct */
/** * Abstract operation 'Str' defined in 15.12.3 * * See also: * ECMA-262 v5, 15.12.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_str (ecma_string_t *key_p, /**< property key*/ ecma_object_t *holder_p, /**< the object*/ ecma_json_stringify_context_t *context_p) /**< context*/ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 1. */ ECMA_TRY_CATCH (value, ecma_op_object_get (holder_p, key_p), ret_value); ecma_value_t my_val = ecma_copy_value (value, true); /* 2. */ if (ecma_is_value_object (my_val)) { ecma_object_t *value_obj_p = ecma_get_object_from_value (my_val); ecma_string_t *to_json_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_TO_JSON_UL); /* 2.a */ ECMA_TRY_CATCH (toJSON, ecma_op_object_get (value_obj_p, to_json_str_p), ret_value); /* 2.b */ if (ecma_op_is_callable (toJSON)) { ecma_value_t key_value = ecma_make_string_value (key_p); ecma_value_t call_args[] = { key_value }; ecma_object_t *toJSON_obj_p = ecma_get_object_from_value (toJSON); ECMA_TRY_CATCH (func_ret_val, ecma_op_function_call (toJSON_obj_p, my_val, call_args, 1), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (func_ret_val, true); ECMA_FINALIZE (func_ret_val); } ECMA_FINALIZE (toJSON); ecma_deref_ecma_string (to_json_str_p); } /* 3. */ if (context_p->replacer_function_p && ecma_is_value_empty (ret_value)) { ecma_value_t holder_value = ecma_make_object_value (holder_p); ecma_value_t key_value = ecma_make_string_value (key_p); ecma_value_t call_args[] = { key_value, my_val }; ECMA_TRY_CATCH (func_ret_val, ecma_op_function_call (context_p->replacer_function_p, holder_value, call_args, 2), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (func_ret_val, true); ECMA_FINALIZE (func_ret_val); } /* 4. */ if (ecma_is_value_object (my_val) && ecma_is_value_empty (ret_value)) { ecma_object_t *obj_p = ecma_get_object_from_value (my_val); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); /* 4.a */ if (class_name == LIT_MAGIC_STRING_NUMBER_UL) { ECMA_TRY_CATCH (val, ecma_op_to_number (my_val), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 4.b */ else if (class_name == LIT_MAGIC_STRING_STRING_UL) { ECMA_TRY_CATCH (val, ecma_op_to_string (my_val), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 4.c */ else if (class_name == LIT_MAGIC_STRING_BOOLEAN_UL) { ECMA_TRY_CATCH (val, ecma_op_to_primitive (my_val, ECMA_PREFERRED_TYPE_NO), ret_value); ecma_free_value (my_val); my_val = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } if (ecma_is_value_empty (ret_value)) { /* 5. - 7. */ if (ecma_is_value_null (my_val) || ecma_is_value_boolean (my_val)) { ret_value = ecma_op_to_string (my_val); JERRY_ASSERT (!ecma_is_value_error (ret_value)); } /* 8. */ else if (ecma_is_value_string (my_val)) { ecma_string_t *value_str_p = ecma_get_string_from_value (my_val); ret_value = ecma_builtin_json_quote (value_str_p); } /* 9. */ else if (ecma_is_value_number (my_val)) { ecma_number_t num_value_p = *ecma_get_number_from_value (my_val); /* 9.a */ if (!ecma_number_is_nan (num_value_p) && !ecma_number_is_infinity (num_value_p)) { ret_value = ecma_op_to_string (my_val); JERRY_ASSERT (!ecma_is_value_error (ret_value)); } else { /* 9.b */ ecma_string_t *null_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL); ret_value = ecma_make_string_value (null_str_p); } } /* 10. */ else if (ecma_is_value_object (my_val) && !ecma_op_is_callable (my_val)) { ecma_object_t *obj_p = ecma_get_object_from_value (my_val); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); /* 10.a */ if (class_name == LIT_MAGIC_STRING_ARRAY_UL) { ECMA_TRY_CATCH (val, ecma_builtin_json_array (obj_p, context_p), ret_value); ret_value = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 10.b */ else { ECMA_TRY_CATCH (val, ecma_builtin_json_object (obj_p, context_p), ret_value); ret_value = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } else { /* 11. */ ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } } ecma_free_value (my_val); ECMA_FINALIZE (value); return ret_value; } /* ecma_builtin_json_str */
/** * Helper function for concatenating an ecma_value_t to an Array. * * See also: * ECMA-262 v5, 15.4.4.4 steps 5.b - 5.c * * Used by: * - The Array.prototype.concat routine. * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ ecma_completion_value_t ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, /**< array */ uint32_t *length_p, /**< in-out: array's length */ ecma_value_t value) /**< value to concat */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 5.b */ if (ecma_is_value_object (value) && (ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_ARRAY_UL)) { ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); /* 5.b.ii */ ECMA_TRY_CATCH (arg_len_value, ecma_op_object_get (ecma_get_object_from_value (value), magic_string_length_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (arg_len_number, arg_len_value, ret_value); uint32_t arg_len = ecma_number_to_uint32 (arg_len_number); /* 5.b.iii */ for (uint32_t array_index = 0; array_index < arg_len && ecma_is_completion_value_empty (ret_value); array_index++) { ecma_string_t *array_index_string_p = ecma_new_ecma_string_from_uint32 (array_index); /* 5.b.iii.2 */ if (ecma_op_object_get_property (ecma_get_object_from_value (value), array_index_string_p) != NULL) { ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 (*length_p + array_index); /* 5.b.iii.3.a */ ECMA_TRY_CATCH (get_value, ecma_op_object_get (ecma_get_object_from_value (value), array_index_string_p), ret_value); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = get_value; prop_desc.is_writable_defined = true; prop_desc.is_writable = true; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = true; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = true; } /* 5.b.iii.3.b */ /* This will always be a simple value since 'is_throw' is false, so no need to free. */ ecma_completion_value_t put_comp = ecma_op_object_define_own_property (obj_p, new_array_index_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp)); ECMA_FINALIZE (get_value); ecma_deref_ecma_string (new_array_index_string_p); } ecma_deref_ecma_string (array_index_string_p); } *length_p += arg_len; ECMA_OP_TO_NUMBER_FINALIZE (arg_len_number); ECMA_FINALIZE (arg_len_value); ecma_deref_ecma_string (magic_string_length_p); } else { ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 ((*length_p)++); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = value; prop_desc.is_writable_defined = true; prop_desc.is_writable = true; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = true; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = true; } /* 5.c.i */ /* This will always be a simple value since 'is_throw' is false, so no need to free. */ ecma_completion_value_t put_comp = ecma_op_object_define_own_property (obj_p, new_array_index_string_p, &prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (put_comp)); ecma_deref_ecma_string (new_array_index_string_p); } if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } return ret_value; } /* ecma_builtin_helper_array_concat_value */
/** * Helper function for concatenating an ecma_value_t to an Array. * * See also: * ECMA-262 v5, 15.4.4.4 steps 5.b - 5.c * * Used by: * - The Array.prototype.concat routine. * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, /**< array */ uint32_t *length_p, /**< [in,out] array's length */ ecma_value_t value) /**< value to concat */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 5.b */ if (ecma_is_value_object (value) && (ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_ARRAY_UL)) { ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string (); /* 5.b.ii */ ECMA_TRY_CATCH (arg_len_value, ecma_op_object_get (ecma_get_object_from_value (value), magic_string_length_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (arg_len_number, arg_len_value, ret_value); uint32_t arg_len = ecma_number_to_uint32 (arg_len_number); /* 5.b.iii */ for (uint32_t array_index = 0; array_index < arg_len && ecma_is_value_empty (ret_value); array_index++) { ecma_string_t *array_index_string_p = ecma_new_ecma_string_from_uint32 (array_index); /* 5.b.iii.2 */ if (ecma_op_object_get_property (ecma_get_object_from_value (value), array_index_string_p) != NULL) { ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 (*length_p + array_index); /* 5.b.iii.3.a */ ECMA_TRY_CATCH (get_value, ecma_op_object_get (ecma_get_object_from_value (value), array_index_string_p), ret_value); /* 5.b.iii.3.b */ /* This will always be a simple value since 'is_throw' is false, so no need to free. */ ecma_value_t put_comp = ecma_builtin_helper_def_prop (obj_p, new_array_index_string_p, get_value, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (put_comp)); ECMA_FINALIZE (get_value); ecma_deref_ecma_string (new_array_index_string_p); } ecma_deref_ecma_string (array_index_string_p); } *length_p += arg_len; ECMA_OP_TO_NUMBER_FINALIZE (arg_len_number); ECMA_FINALIZE (arg_len_value); ecma_deref_ecma_string (magic_string_length_p); } else { ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 ((*length_p)++); /* 5.c.i */ /* This will always be a simple value since 'is_throw' is false, so no need to free. */ ecma_value_t put_comp = ecma_builtin_helper_def_prop (obj_p, new_array_index_string_p, value, true, /* Writable */ true, /* Enumerable */ true, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_value_true (put_comp)); ecma_deref_ecma_string (new_array_index_string_p); } if (ecma_is_value_empty (ret_value)) { ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE); } return ret_value; } /* ecma_builtin_helper_array_concat_value */
/** * The JSON object's 'stringify' routine * * See also: * ECMA-262 v5, 15.12.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_json_stringify (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */ ecma_value_t arg1, /**< value */ ecma_value_t arg2, /**< replacer */ ecma_value_t arg3) /**< space */ { ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); ecma_json_stringify_context_t context; /* 1. */ context.occurence_stack_p = ecma_new_values_collection (NULL, 0, false); /* 2. */ context.indent_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); /* 3. */ context.property_list_p = ecma_new_values_collection (NULL, 0, false); context.replacer_function_p = NULL; /* 4. */ if (ecma_is_value_object (arg2)) { ecma_object_t *obj_p = ecma_get_object_from_value (arg2); /* 4.a */ if (ecma_op_is_callable (arg2)) { context.replacer_function_p = obj_p; } /* 4.b */ else if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_ARRAY_UL) { ecma_string_t *length_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ECMA_TRY_CATCH (array_length, ecma_op_object_get (obj_p, length_str_p), ret_value); ECMA_OP_TO_NUMBER_TRY_CATCH (array_length_num, array_length, ret_value); uint32_t array_length = ecma_number_to_uint32 (array_length_num); uint32_t index = 0; /* 4.b.ii */ while ((index < array_length) && ecma_is_value_empty (ret_value)) { ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (value, ecma_op_object_get (obj_p, index_str_p), ret_value); /* 4.b.ii.1 */ ecma_value_t item = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); /* 4.b.ii.2 */ if (ecma_is_value_string (value)) { item = ecma_copy_value (value, true); } /* 4.b.ii.3 */ else if (ecma_is_value_number (value)) { ECMA_TRY_CATCH (str_val, ecma_op_to_string (value), ret_value); item = ecma_copy_value (str_val, true); ECMA_FINALIZE (str_val); } /* 4.b.ii.4 */ else if (ecma_is_value_object (value)) { ecma_object_t *obj_val_p = ecma_get_object_from_value (value); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_val_p); /* 4.b.ii.4.a */ if (class_name == LIT_MAGIC_STRING_NUMBER_UL || class_name == LIT_MAGIC_STRING_STRING_UL) { ECMA_TRY_CATCH (val, ecma_op_to_string (value), ret_value); item = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } /* 4.b.ii.5 */ if (!ecma_is_value_undefined (item)) { if (!ecma_has_string_value_in_collection (context.property_list_p, item)) { ecma_append_to_values_collection (context.property_list_p, item, true); ecma_deref_ecma_string (ecma_get_string_from_value (item)); } else { ecma_free_value (item); } } ECMA_FINALIZE (value); ecma_deref_ecma_string (index_str_p); index++; } ECMA_OP_TO_NUMBER_FINALIZE (array_length_num); ECMA_FINALIZE (array_length); ecma_deref_ecma_string (length_str_p); } } if (ecma_is_value_empty (ret_value)) { ecma_value_t space = ecma_copy_value (arg3, true); /* 5. */ if (ecma_is_value_object (arg3)) { ecma_object_t *obj_p = ecma_get_object_from_value (arg3); lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); /* 5.a */ if (class_name == LIT_MAGIC_STRING_NUMBER_UL) { ECMA_TRY_CATCH (val, ecma_op_to_number (arg3), ret_value); ecma_free_value (space); space = ecma_copy_value (val, true); ECMA_FINALIZE (val); } /* 5.b */ else if (class_name == LIT_MAGIC_STRING_STRING_UL) { ECMA_TRY_CATCH (val, ecma_op_to_string (arg3), ret_value); ecma_free_value (space); space = ecma_copy_value (val, true); ECMA_FINALIZE (val); } } if (ecma_is_value_empty (ret_value)) { /* 6. */ if (ecma_is_value_number (space)) { ECMA_OP_TO_NUMBER_TRY_CATCH (array_length_num, arg3, ret_value); /* 6.a */ int32_t num_of_spaces = ecma_number_to_int32 (array_length_num); int32_t space = (num_of_spaces > 10) ? 10 : num_of_spaces; /* 6.b */ if (space < 1) { context.gap_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } else { MEM_DEFINE_LOCAL_ARRAY (space_buff, space, char); for (int32_t i = 0; i < space; i++) { space_buff[i] = LIT_CHAR_SP; } context.gap_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) space_buff, (lit_utf8_size_t) space); MEM_FINALIZE_LOCAL_ARRAY (space_buff); } ECMA_OP_TO_NUMBER_FINALIZE (array_length_num); } /* 7. */ else if (ecma_is_value_string (space)) { ecma_string_t *space_str_p = ecma_get_string_from_value (space); ecma_length_t num_of_chars = ecma_string_get_length (space_str_p); if (num_of_chars < 10) { context.gap_str_p = ecma_copy_or_ref_ecma_string (space_str_p); } else { context.gap_str_p = ecma_string_substr (space_str_p, 0, 10); } } /* 8. */ else { context.gap_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } } ecma_free_value (space); if (ecma_is_value_empty (ret_value)) { /* 9. */ ecma_object_t *obj_wrapper_p = ecma_op_create_object_object_noarg (); ecma_string_t *empty_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); /* 10. */ ecma_value_t put_comp_val = ecma_op_object_put (obj_wrapper_p, empty_str_p, arg1, false); JERRY_ASSERT (ecma_is_value_true (put_comp_val)); ecma_free_value (put_comp_val); /* 11. */ ECMA_TRY_CATCH (str_val, ecma_builtin_json_str (empty_str_p, obj_wrapper_p, &context), ret_value); ret_value = ecma_copy_value (str_val, true); ECMA_FINALIZE (str_val); ecma_deref_object (obj_wrapper_p); ecma_deref_ecma_string (empty_str_p); } ecma_deref_ecma_string (context.gap_str_p); } ecma_deref_ecma_string (context.indent_str_p); ecma_free_values_collection (context.property_list_p, true); ecma_free_values_collection (context.occurence_stack_p, true); return ret_value; } /* ecma_builtin_json_stringify */
/** * The String.prototype object's 'match' routine * * See also: * ECMA-262 v5, 15.5.4.10 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_string_prototype_object_match (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_value, ecma_op_check_object_coercible (this_arg), ret_value); /* 2. */ ECMA_TRY_CATCH (this_to_string_value, ecma_op_to_string (this_arg), ret_value); ecma_value_t regexp_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 3. */ if (ecma_is_value_object (arg) && ecma_object_get_class_name (ecma_get_object_from_value (arg)) == LIT_MAGIC_STRING_REGEXP_UL) { regexp_value = ecma_copy_value (arg, true); } else { /* 4. */ ecma_value_t regexp_arguments[1] = { arg }; ECMA_TRY_CATCH (new_regexp_value, ecma_builtin_regexp_dispatch_construct (regexp_arguments, 1), ret_value); regexp_value = ecma_copy_value (new_regexp_value, true); ECMA_FINALIZE (new_regexp_value); } if (ecma_is_completion_value_empty (ret_value)) { JERRY_ASSERT (!ecma_is_value_empty (regexp_value)); ecma_object_t *regexp_obj_p = ecma_get_object_from_value (regexp_value); ecma_string_t *global_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL); /* 5. */ ECMA_TRY_CATCH (global_value, ecma_op_object_get (regexp_obj_p, global_string_p), ret_value); JERRY_ASSERT (ecma_is_value_boolean (global_value)); ecma_value_t exec_arguments[1] = { this_to_string_value }; if (!ecma_is_value_true (global_value)) { /* 7. */ ret_value = ecma_builtin_regexp_prototype_dispatch_routine (LIT_MAGIC_STRING_EXEC, regexp_value, exec_arguments, 1); } else { /* 8.a. */ ecma_number_t *zero_number_p = ecma_alloc_number (); *zero_number_p = 0; ecma_string_t *index_zero_string_p = ecma_new_ecma_string_from_uint32 (0); ecma_string_t *last_index_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); ECMA_TRY_CATCH (put_value, ecma_op_object_put (regexp_obj_p, last_index_string_p, ecma_make_number_value (zero_number_p), true), ret_value); /* 8.b. */ ECMA_TRY_CATCH (new_array_value, ecma_op_create_array_object (NULL, 0, false), ret_value); ecma_object_t *new_array_obj_p = ecma_get_object_from_value (new_array_value); /* 8.c. */ ecma_number_t previous_last_index = 0; /* 8.d. */ uint32_t n = 0; /* 8.e. */ bool last_match = true; //ecma_completion_value_t exec_result = ecma_make_empty_completion_value (); /* 8.f. */ while (last_match && ecma_is_completion_value_empty (ret_value)) { /* 8.f.i. */ ECMA_TRY_CATCH (exec_value, ecma_builtin_regexp_prototype_dispatch_routine (LIT_MAGIC_STRING_EXEC, regexp_value, exec_arguments, 1), ret_value); if (ecma_is_value_null (exec_value)) { /* 8.f.ii. */ last_match = false; } else { /* 8.f.iii. */ ECMA_TRY_CATCH (this_index_value, ecma_op_object_get (regexp_obj_p, last_index_string_p), ret_value); ECMA_TRY_CATCH (this_index_number, ecma_op_to_number (this_index_value), ret_value); ecma_number_t this_index = *ecma_get_number_from_value (this_index_number); /* 8.f.iii.2. */ if (this_index == previous_last_index) { ecma_number_t *new_last_index_p = ecma_alloc_number (); *new_last_index_p = this_index + 1; /* 8.f.iii.2.a. */ ECMA_TRY_CATCH (index_put_value, ecma_op_object_put (regexp_obj_p, last_index_string_p, ecma_make_number_value (new_last_index_p), true), ret_value); /* 8.f.iii.2.b. */ previous_last_index = this_index + 1; ECMA_FINALIZE (index_put_value); ecma_dealloc_number (new_last_index_p); } else { /* 8.f.iii.3. */ previous_last_index = this_index; } if (ecma_is_completion_value_empty (ret_value)) { /* 8.f.iii.4. */ JERRY_ASSERT (ecma_is_value_object (exec_value)); ecma_object_t *exec_obj_p = ecma_get_object_from_value (exec_value); ECMA_TRY_CATCH (match_string_value, ecma_op_object_get (exec_obj_p, index_zero_string_p), ret_value); /* 8.f.iii.5. */ ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_value_defined = true; prop_desc.value = match_string_value; prop_desc.is_writable_defined = true; prop_desc.is_writable = true; prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = true; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = true; } ecma_string_t *current_index_str_p = ecma_new_ecma_string_from_uint32 (n); ecma_completion_value_t completion = ecma_op_object_define_own_property (new_array_obj_p, current_index_str_p, &prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)); ecma_deref_ecma_string (current_index_str_p); /* 8.f.iii.6. */ n++; ECMA_FINALIZE (match_string_value); } ECMA_FINALIZE (this_index_number); ECMA_FINALIZE (this_index_value); } ECMA_FINALIZE (exec_value); } if (ecma_is_completion_value_empty (ret_value)) { if (n == 0) { /* 8.g. */ ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_NULL); } else { /* 8.h. */ ret_value = ecma_make_normal_completion_value (ecma_copy_value (new_array_value, true)); } } ECMA_FINALIZE (new_array_value); ECMA_FINALIZE (put_value); ecma_deref_ecma_string (last_index_string_p); ecma_deref_ecma_string (index_zero_string_p); ecma_dealloc_number (zero_number_p); } ECMA_FINALIZE (global_value); ecma_deref_ecma_string (global_string_p); ecma_free_value (regexp_value, true); } ECMA_FINALIZE (this_to_string_value); ECMA_FINALIZE (this_check_coercible_value); return ret_value; } /* ecma_builtin_string_prototype_object_match */
ecma_completion_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this argument */ { lit_magic_string_id_t type_string; if (ecma_is_value_undefined (this_arg)) { type_string = LIT_MAGIC_STRING_UNDEFINED_UL; } else if (ecma_is_value_null (this_arg)) { type_string = LIT_MAGIC_STRING_NULL_UL; } else { ecma_completion_value_t obj_this = ecma_op_to_object (this_arg); if (!ecma_is_completion_value_normal (obj_this)) { return obj_this; } JERRY_ASSERT (ecma_is_value_object (ecma_get_completion_value_value (obj_this))); ecma_object_t *obj_p = ecma_get_object_from_completion_value (obj_this); type_string = ecma_object_get_class_name (obj_p); ecma_free_completion_value (obj_this); } ecma_string_t *ret_string_p; /* Building string "[object #type#]" where type is 'Undefined', 'Null' or one of possible object's classes. The string with null character is maximum 19 characters long. */ const ssize_t buffer_size = 19; MEM_DEFINE_LOCAL_ARRAY (str_buffer, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *buffer_ptr = str_buffer; ssize_t buffer_size_left = buffer_size; const lit_magic_string_id_t magic_string_ids[] = { LIT_MAGIC_STRING_LEFT_SQUARE_CHAR, LIT_MAGIC_STRING_OBJECT, LIT_MAGIC_STRING_SPACE_CHAR, type_string, LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR }; for (uint32_t i = 0; i < sizeof (magic_string_ids) / sizeof (lit_magic_string_id_t); ++i) { buffer_ptr = lit_copy_magic_string_to_buffer (magic_string_ids[i], buffer_ptr, buffer_size_left); buffer_size_left = buffer_size - (buffer_ptr - str_buffer); } JERRY_ASSERT (buffer_size_left >= 0); ret_string_p = ecma_new_ecma_string_from_utf8 (str_buffer, (lit_utf8_size_t) (buffer_size - buffer_size_left)); MEM_FINALIZE_LOCAL_ARRAY (str_buffer); return ecma_make_normal_completion_value (ecma_make_string_value (ret_string_p)); } /* ecma_builtin_helper_object_to_string */
/** * [[DefaultValue]] ecma general object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 8.12.8 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_general_object_default_value (ecma_object_t *obj_p, /**< the object */ ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ { JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); if (hint == ECMA_PREFERRED_TYPE_NO) { if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_DATE_UL) { hint = ECMA_PREFERRED_TYPE_STRING; } else { hint = ECMA_PREFERRED_TYPE_NUMBER; } } for (uint32_t i = 1; i <= 2; i++) { lit_magic_string_id_t function_name_magic_string_id; if ((i == 1 && hint == ECMA_PREFERRED_TYPE_STRING) || (i == 2 && hint == ECMA_PREFERRED_TYPE_NUMBER)) { function_name_magic_string_id = LIT_MAGIC_STRING_TO_STRING_UL; } else { function_name_magic_string_id = LIT_MAGIC_STRING_VALUE_OF_UL; } ecma_string_t *function_name_p = ecma_get_magic_string (function_name_magic_string_id); ecma_completion_value_t function_value_get_completion = ecma_op_object_get (obj_p, function_name_p); ecma_deref_ecma_string (function_name_p); if (!ecma_is_completion_value_normal (function_value_get_completion)) { return function_value_get_completion; } ecma_completion_value_t call_completion = ecma_make_empty_completion_value (); if (ecma_op_is_callable (ecma_get_completion_value_value (function_value_get_completion))) { ecma_object_t *func_obj_p = ecma_get_object_from_completion_value (function_value_get_completion); call_completion = ecma_op_function_call (func_obj_p, ecma_make_object_value (obj_p), NULL); } ecma_free_completion_value (function_value_get_completion); if (!ecma_is_completion_value_normal (call_completion)) { return call_completion; } if (!ecma_is_completion_value_empty (call_completion) && !ecma_is_value_object (ecma_get_completion_value_value (call_completion))) { return call_completion; } ecma_free_completion_value (call_completion); } return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } /* ecma_op_general_object_default_value */