/** * Common function to create a non-formatted JSON string. * * See also: * ECMA-262 v5, 15.12.3 * * Used by: * - ecma_builtin_json_object step 10.a * - ecma_builtin_json_array step 10.a * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_json_create_non_formatted_json (ecma_string_t *left_bracket_p, /**< left bracket*/ ecma_string_t *right_bracket_p, /**< right bracket*/ ecma_collection_header_t *partial_p) /**< key-value pairs*/ { /* 10.a */ ecma_string_t *comma_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR); ecma_string_t *properties_str_p; ecma_string_t *tmp_str_p; /* 10.a.i */ properties_str_p = ecma_builtin_helper_json_create_separated_properties (partial_p, comma_str_p); ecma_deref_ecma_string (comma_str_p); /* 10.a.ii */ tmp_str_p = ecma_concat_ecma_strings (left_bracket_p, properties_str_p); ecma_deref_ecma_string (properties_str_p); properties_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (properties_str_p, right_bracket_p); ecma_deref_ecma_string (properties_str_p); properties_str_p = tmp_str_p; return ecma_make_string_value (properties_str_p); } /* ecma_builtin_helper_json_create_non_formatted_json */
/** * Common function to create a formatted JSON string. * * See also: * ECMA-262 v5, 15.12.3 * * Used by: * - ecma_builtin_json_object step 10.b * - ecma_builtin_json_array step 10.b * * @return ecma value * Returned value must be freed with ecma_free_value. */ ecma_value_t ecma_builtin_helper_json_create_formatted_json (ecma_string_t *left_bracket_p, /**< left bracket*/ ecma_string_t *right_bracket_p, /**< right bracket*/ ecma_string_t *stepback_p, /**< stepback*/ ecma_collection_header_t *partial_p, /**< key-value pairs*/ ecma_json_stringify_context_t *context_p) /**< context*/ { /* 10.b */ ecma_string_t *comma_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR); ecma_string_t *line_feed_p = ecma_get_magic_string (LIT_MAGIC_STRING_NEW_LINE_CHAR); ecma_string_t *properties_str_p; ecma_string_t *separator_p; /* 10.b.i */ ecma_string_t *tmp_str_p = ecma_concat_ecma_strings (comma_str_p, line_feed_p); ecma_deref_ecma_string (comma_str_p); separator_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (separator_p, context_p->indent_str_p); ecma_deref_ecma_string (separator_p); separator_p = tmp_str_p; /* 10.b.ii */ properties_str_p = ecma_builtin_helper_json_create_separated_properties (partial_p, separator_p); ecma_deref_ecma_string (separator_p); /* 10.b.iii */ ecma_string_t *final_str_p; tmp_str_p = ecma_concat_ecma_strings (left_bracket_p, line_feed_p); final_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (final_str_p, context_p->indent_str_p); ecma_deref_ecma_string (final_str_p); final_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (final_str_p, properties_str_p); ecma_deref_ecma_string (final_str_p); ecma_deref_ecma_string (properties_str_p); final_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (final_str_p, line_feed_p); ecma_deref_ecma_string (line_feed_p); ecma_deref_ecma_string (final_str_p); final_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (final_str_p, stepback_p); ecma_deref_ecma_string (final_str_p); final_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (final_str_p, right_bracket_p); ecma_deref_ecma_string (final_str_p); final_str_p = tmp_str_p; return ecma_make_string_value (final_str_p); } /* ecma_builtin_helper_json_create_formatted_json */
/** * 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 */
/** * Common function to concatenate key-value pairs into an ecma-string. * * See also: * ECMA-262 v5, 15.12.3 * * Used by: * - ecma_builtin_helper_json_create_formatted_json step 10.b.ii * - ecma_builtin_helper_json_create_non_formatted_json step 10.a.i * * @return pointer to ecma-string * Returned value must be freed with ecma_deref_ecma_string. */ ecma_string_t * ecma_builtin_helper_json_create_separated_properties (ecma_collection_header_t *partial_p, /**< key-value pairs*/ ecma_string_t *separator_p) /**< separator*/ { ecma_string_t *properties_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); ecma_string_t *tmp_str_p; ecma_collection_iterator_t iterator; ecma_collection_iterator_init (&iterator, partial_p); uint32_t index = 0; while (ecma_collection_iterator_next (&iterator)) { ecma_value_t name_value = *iterator.current_value_p; ecma_string_t *current_p = ecma_get_string_from_value (name_value); if (index == 0) { index++; tmp_str_p = ecma_concat_ecma_strings (properties_str_p, current_p); ecma_deref_ecma_string (properties_str_p); properties_str_p = tmp_str_p; continue; } tmp_str_p = ecma_concat_ecma_strings (properties_str_p, separator_p); ecma_deref_ecma_string (properties_str_p); properties_str_p = tmp_str_p; tmp_str_p = ecma_concat_ecma_strings (properties_str_p, current_p); ecma_deref_ecma_string (properties_str_p); properties_str_p = tmp_str_p; } return properties_str_p; } /* ecma_builtin_helper_json_create_separated_properties */
/** * 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 Number.prototype object's 'toPrecision' routine * * See also: * ECMA-262 v5, 15.7.4.7 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_number_prototype_object_to_precision (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); /* 1. */ ECMA_TRY_CATCH (this_value, ecma_builtin_number_prototype_object_value_of (this_arg), ret_value); ecma_number_t this_num = ecma_get_number_from_value (this_value); /* 2. */ if (ecma_is_value_undefined (arg)) { ret_value = ecma_builtin_number_prototype_object_to_string (this_arg, NULL, 0); } else { /* 3. */ ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); /* 4. */ if (ecma_number_is_nan (this_num)) { ecma_string_t *nan_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NAN); ret_value = ecma_make_string_value (nan_str_p); } else { /* 6. */ bool is_negative = false; if (ecma_number_is_negative (this_num) && !ecma_number_is_zero (this_num)) { is_negative = true; this_num *= -1; } /* 7. */ if (ecma_number_is_infinity (this_num)) { ecma_string_t *infinity_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INFINITY_UL); if (is_negative) { ecma_string_t *neg_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_MINUS_CHAR); ecma_string_t *neg_inf_str_p = ecma_concat_ecma_strings (neg_str_p, infinity_str_p); ecma_deref_ecma_string (infinity_str_p); ecma_deref_ecma_string (neg_str_p); ret_value = ecma_make_string_value (neg_inf_str_p); } else { ret_value = ecma_make_string_value (infinity_str_p); } } /* 8. */ else if (arg_num < 1.0 || arg_num >= 22.0) { ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("")); } else { /* Get the parameters of the number if non-zero. */ lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; lit_utf8_size_t num_digits; int32_t exponent; if (!ecma_number_is_zero (this_num)) { num_digits = ecma_number_to_decimal (this_num, digits, &exponent); } else { digits[0] = '0'; num_digits = 1; exponent = 1; } int32_t precision = ecma_number_to_int32 (arg_num); num_digits = ecma_builtin_number_prototype_helper_round (digits, num_digits, precision); int buffer_size; if (exponent < -5 || exponent > precision) { /* Exponential notation, precision + 1 digits for number, 5 for exponent, 1 for \0 */ buffer_size = precision + 1 + 5 + 1; } else if (exponent <= 0) { /* Fixed notation, -exponent + 2 digits for leading zeros, precision digits, 1 for \0 */ buffer_size = -exponent + 2 + precision + 1; } else { /* Fixed notation, precision + 1 digits for number, 1 for \0 */ buffer_size = precision + 1 + 1; } if (is_negative) { buffer_size++; } JMEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *actual_char_p = buff; if (is_negative) { *actual_char_p++ = '-'; } /* 10.c, Exponential notation.*/ if (exponent < -5 || exponent > precision) { actual_char_p += ecma_builtin_number_prototype_helper_to_string (digits, num_digits, 1, actual_char_p, (lit_utf8_size_t) precision); *actual_char_p++ = 'e'; exponent--; if (exponent < 0) { exponent *= -1; *actual_char_p++ = '-'; } else { *actual_char_p++ = '+'; } /* Add exponent digits. */ actual_char_p += ecma_uint32_to_utf8_string ((uint32_t) exponent, actual_char_p, 3); } /* Fixed notation. */ else { lit_utf8_size_t to_num_digits = ((exponent <= 0) ? (lit_utf8_size_t) (1 - exponent + precision) : (lit_utf8_size_t) precision); actual_char_p += ecma_builtin_number_prototype_helper_to_string (digits, num_digits, exponent, actual_char_p, to_num_digits); } JERRY_ASSERT (actual_char_p - buff < buffer_size); *actual_char_p = '\0'; ecma_string_t *str_p = ecma_new_ecma_string_from_utf8 (buff, (lit_utf8_size_t) (actual_char_p - buff)); ret_value = ecma_make_string_value (str_p); JMEM_FINALIZE_LOCAL_ARRAY (buff); } } ECMA_OP_TO_NUMBER_FINALIZE (arg_num); } ECMA_FINALIZE (this_value); return ret_value; } /* ecma_builtin_number_prototype_object_to_precision */
/** * The Number.prototype object's 'toExponential' routine * * See also: * ECMA-262 v5, 15.7.4.6 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_number_prototype_object_to_exponential (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); /* 1. */ ECMA_TRY_CATCH (this_value, ecma_builtin_number_prototype_object_value_of (this_arg), ret_value); ecma_number_t this_num = ecma_get_number_from_value (this_value); ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); /* 7. */ if (arg_num <= -1.0 || arg_num >= 21.0) { ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("")); } else { /* 3. */ if (ecma_number_is_nan (this_num)) { ecma_string_t *nan_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NAN); ret_value = ecma_make_string_value (nan_str_p); } else { /* 5. */ bool is_negative = false; if (ecma_number_is_negative (this_num) && !ecma_number_is_zero (this_num)) { is_negative = true; this_num *= -1; } /* 6. */ if (ecma_number_is_infinity (this_num)) { ecma_string_t *infinity_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INFINITY_UL); if (is_negative) { ecma_string_t *neg_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_MINUS_CHAR); ecma_string_t *neg_inf_str_p = ecma_concat_ecma_strings (neg_str_p, infinity_str_p); ecma_deref_ecma_string (infinity_str_p); ecma_deref_ecma_string (neg_str_p); ret_value = ecma_make_string_value (neg_inf_str_p); } else { ret_value = ecma_make_string_value (infinity_str_p); } } else { /* Get the parameters of the number if non zero. */ lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; lit_utf8_size_t num_digits; int32_t exponent; if (!ecma_number_is_zero (this_num)) { num_digits = ecma_number_to_decimal (this_num, digits, &exponent); } else { digits[0] = '0'; num_digits = 1; exponent = 1; } int32_t frac_digits; if (ecma_is_value_undefined (arg)) { frac_digits = (int32_t) num_digits - 1; } else { frac_digits = ecma_number_to_int32 (arg_num); } num_digits = ecma_builtin_number_prototype_helper_round (digits, num_digits, frac_digits + 1); /* frac_digits + 2 characters for number, 5 characters for exponent, 1 for \0. */ int buffer_size = frac_digits + 2 + 5 + 1; if (is_negative) { /* +1 character for sign. */ buffer_size++; } JMEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *actual_char_p = buff; if (is_negative) { *actual_char_p++ = '-'; } actual_char_p += ecma_builtin_number_prototype_helper_to_string (digits, num_digits, 1, actual_char_p, (lit_utf8_size_t) (frac_digits + 1)); *actual_char_p++ = 'e'; exponent--; if (exponent < 0) { exponent *= -1; *actual_char_p++ = '-'; } else { *actual_char_p++ = '+'; } /* Add exponent digits. */ actual_char_p += ecma_uint32_to_utf8_string ((uint32_t) exponent, actual_char_p, 3); JERRY_ASSERT (actual_char_p - buff < buffer_size); *actual_char_p = '\0'; ecma_string_t *str = ecma_new_ecma_string_from_utf8 (buff, (lit_utf8_size_t) (actual_char_p - buff)); ret_value = ecma_make_string_value (str); JMEM_FINALIZE_LOCAL_ARRAY (buff); } } } ECMA_OP_TO_NUMBER_FINALIZE (arg_num); ECMA_FINALIZE (this_value); return ret_value; } /* ecma_builtin_number_prototype_object_to_exponential */
/** * The Number.prototype object's 'toFixed' routine * * See also: * ECMA-262 v5, 15.7.4.5 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_number_prototype_object_to_fixed (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); ECMA_TRY_CATCH (this_value, ecma_builtin_number_prototype_object_value_of (this_arg), ret_value); ecma_number_t this_num = ecma_get_number_from_value (this_value); ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); /* 2. */ if (arg_num <= -1 || arg_num >= 21) { ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("")); } else { /* 4. */ if (ecma_number_is_nan (this_num)) { ecma_string_t *nan_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NAN); ret_value = ecma_make_string_value (nan_str_p); } else { /* 6. */ bool is_negative = false; if (ecma_number_is_negative (this_num)) { is_negative = true; this_num *= -1; } /* We handle infinities separately. */ if (ecma_number_is_infinity (this_num)) { ecma_string_t *infinity_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INFINITY_UL); if (is_negative) { ecma_string_t *neg_str_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) "-", 1); ecma_string_t *neg_inf_str_p = ecma_concat_ecma_strings (neg_str_p, infinity_str_p); ecma_deref_ecma_string (infinity_str_p); ecma_deref_ecma_string (neg_str_p); ret_value = ecma_make_string_value (neg_inf_str_p); } else { ret_value = ecma_make_string_value (infinity_str_p); } } else { /* Get the parameters of the number if non-zero. */ lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER]; lit_utf8_size_t num_digits; int32_t exponent; if (!ecma_number_is_zero (this_num)) { num_digits = ecma_number_to_decimal (this_num, digits, &exponent); } else { digits[0] = '0'; num_digits = 1; exponent = 1; } /* 7. */ if (exponent > 21) { ret_value = ecma_builtin_number_prototype_object_to_string (this_arg, NULL, 0); } /* 8. */ else { /* 1. */ int32_t frac_digits = ecma_number_to_int32 (arg_num); num_digits = ecma_builtin_number_prototype_helper_round (digits, num_digits, exponent + frac_digits); /* Buffer that is used to construct the string. */ int buffer_size = (exponent > 0) ? exponent + frac_digits + 2 : frac_digits + 3; if (is_negative) { buffer_size++; } JERRY_ASSERT (buffer_size > 0); JMEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *p = buff; if (is_negative) { *p++ = '-'; } lit_utf8_size_t to_num_digits = ((exponent > 0) ? (lit_utf8_size_t) (exponent + frac_digits) : (lit_utf8_size_t) (frac_digits + 1)); p += ecma_builtin_number_prototype_helper_to_string (digits, num_digits, exponent, p, to_num_digits); JERRY_ASSERT (p - buff < buffer_size); /* String terminator. */ *p = 0; ecma_string_t *str = ecma_new_ecma_string_from_utf8 (buff, (lit_utf8_size_t) (p - buff)); ret_value = ecma_make_string_value (str); JMEM_FINALIZE_LOCAL_ARRAY (buff); } } } } ECMA_OP_TO_NUMBER_FINALIZE (arg_num); ECMA_FINALIZE (this_value); return ret_value; } /* ecma_builtin_number_prototype_object_to_fixed */
/** * The Number.prototype object's 'toExponential' routine * * See also: * ECMA-262 v5, 15.7.4.6 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_number_prototype_object_to_exponential (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); /* 1. */ ECMA_TRY_CATCH (this_value, ecma_builtin_number_prototype_object_value_of (this_arg), ret_value); ecma_number_t this_num = *ecma_get_number_from_value (this_value); ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); /* 7. */ if (arg_num <= -1.0 || arg_num >= 21.0) { ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("")); } else { /* 3. */ if (ecma_number_is_nan (this_num)) { ecma_string_t *nan_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NAN); ret_value = ecma_make_string_value (nan_str_p); } else { bool is_negative = false; /* 5. */ if (ecma_number_is_negative (this_num) && !ecma_number_is_zero (this_num)) { is_negative = true; this_num *= -1; } /* 6. */ if (ecma_number_is_infinity (this_num)) { ecma_string_t *infinity_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INFINITY_UL); if (is_negative) { ecma_string_t *neg_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_MINUS_CHAR); ecma_string_t *neg_inf_str_p = ecma_concat_ecma_strings (neg_str_p, infinity_str_p); ecma_deref_ecma_string (infinity_str_p); ecma_deref_ecma_string (neg_str_p); ret_value = ecma_make_string_value (neg_inf_str_p); } else { ret_value = ecma_make_string_value (infinity_str_p); } } else { uint64_t digits = 0; int32_t num_digits = 0; int32_t exponent = 1; if (!ecma_number_is_zero (this_num)) { /* Get the parameters of the number if non zero. */ ecma_number_to_decimal (this_num, &digits, &num_digits, &exponent); } int32_t frac_digits; if (ecma_is_value_undefined (arg)) { frac_digits = num_digits - 1; } else { frac_digits = ecma_number_to_int32 (arg_num); } digits = ecma_builtin_number_prototype_helper_round (digits, num_digits - frac_digits - 1); /* frac_digits + 2 characters for number, 5 characters for exponent, 1 for \0. */ int buffer_size = frac_digits + 2 + 5 + 1; if (is_negative) { /* +1 character for sign. */ buffer_size++; } MEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t); int digit = 0; uint64_t scale = 1; /* Calculate the magnitude of the number. This is used to get the digits from left to right. */ while (scale <= digits) { scale *= 10; } lit_utf8_byte_t *actual_char_p = buff; if (is_negative) { *actual_char_p++ = '-'; } /* Add significant digits. */ for (int i = 0; i <= frac_digits; i++) { digit = 0; scale /= 10; while (digits >= scale && scale > 0) { digits -= scale; digit++; } *actual_char_p = (lit_utf8_byte_t) (digit + '0'); actual_char_p++; if (i == 0 && frac_digits != 0) { *actual_char_p++ = '.'; } } *actual_char_p++ = 'e'; exponent--; if (exponent < 0) { exponent *= -1; *actual_char_p++ = '-'; } else { *actual_char_p++ = '+'; } /* Get magnitude of exponent. */ int32_t scale_expt = 1; while (scale_expt <= exponent) { scale_expt *= 10; } scale_expt /= 10; /* Add exponent digits. */ if (exponent == 0) { *actual_char_p++ = '0'; } else { while (scale_expt > 0) { digit = exponent / scale_expt; exponent %= scale_expt; *actual_char_p++ = (lit_utf8_byte_t) (digit + '0'); scale_expt /= 10; } } JERRY_ASSERT (actual_char_p - buff < buffer_size); *actual_char_p = '\0'; ecma_string_t *str = ecma_new_ecma_string_from_utf8 (buff, (lit_utf8_size_t) (actual_char_p - buff)); ret_value = ecma_make_string_value (str); MEM_FINALIZE_LOCAL_ARRAY (buff); } } } ECMA_OP_TO_NUMBER_FINALIZE (arg_num); ECMA_FINALIZE (this_value); return ret_value; } /* ecma_builtin_number_prototype_object_to_exponential */
/** * Abstract operation 'JA' 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_array (ecma_object_t *obj_p, /**< the array object*/ ecma_json_stringify_context_t *context_p) /**< context*/ { ecma_value_t obj_value = ecma_make_object_value (obj_p); /* 1. */ if (ecma_has_object_value_in_collection (context_p->occurence_stack_p, obj_value)) { return ecma_raise_type_error (""); } ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 2. */ ecma_append_to_values_collection (context_p->occurence_stack_p, obj_value, true); /* 3. */ ecma_string_t *stepback_p = context_p->indent_str_p; /* 4. */ context_p->indent_str_p = ecma_concat_ecma_strings (context_p->indent_str_p, context_p->gap_str_p); /* 5. */ ecma_collection_header_t *partial_p = ecma_new_values_collection (NULL, 0, true); ecma_string_t *length_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); /* 6. */ 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); /* 7. - 8. */ for (uint32_t index = 0; index < array_length && ecma_is_value_empty (ret_value); index++) { /* 8.a */ ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); ECMA_TRY_CATCH (str_val, ecma_builtin_json_str (index_str_p, obj_p, context_p), ret_value); /* 8.b */ if (ecma_is_value_undefined (str_val)) { ecma_string_t *null_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL); ecma_append_to_values_collection (partial_p, ecma_make_string_value (null_str_p), true); ecma_deref_ecma_string (null_str_p); } /* 8.c */ else { ecma_append_to_values_collection (partial_p, str_val, true); } ECMA_FINALIZE (str_val); ecma_deref_ecma_string (index_str_p); } if (ecma_is_value_empty (ret_value)) { /* 9. */ if (partial_p->unit_number == 0) { ecma_string_t *left_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR); ecma_string_t *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR); ecma_string_t *final_str_p = ecma_concat_ecma_strings (left_square_str_p, right_square_str_p); ret_value = ecma_make_string_value (final_str_p); ecma_deref_ecma_string (left_square_str_p); ecma_deref_ecma_string (right_square_str_p); } /* 10. */ else { bool is_gap_empty = (ecma_string_get_length (context_p->gap_str_p) == 0); /* 10.a */ if (is_gap_empty) { ecma_string_t *left_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR); ecma_string_t *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR); ret_value = ecma_builtin_helper_json_create_non_formatted_json (left_square_str_p, right_square_str_p, partial_p); ecma_deref_ecma_string (left_square_str_p); ecma_deref_ecma_string (right_square_str_p); } /* 10.b */ else { ecma_string_t *left_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_SQUARE_CHAR); ecma_string_t *right_square_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR); ret_value = ecma_builtin_helper_json_create_formatted_json (left_square_str_p, right_square_str_p, stepback_p, partial_p, context_p); ecma_deref_ecma_string (left_square_str_p); ecma_deref_ecma_string (right_square_str_p); } } } ECMA_OP_TO_NUMBER_FINALIZE (array_length_num); ECMA_FINALIZE (array_length); ecma_deref_ecma_string (length_str_p); ecma_free_values_collection (partial_p, true); /* 11. */ ecma_remove_last_value_from_values_collection (context_p->occurence_stack_p); /* 12. */ ecma_deref_ecma_string (context_p->indent_str_p); context_p->indent_str_p = stepback_p; /* 13. */ return ret_value; } /* ecma_builtin_json_array */
/** * Abstract operation 'JO' 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_object (ecma_object_t *obj_p, /**< the object*/ ecma_json_stringify_context_t *context_p) /**< context*/ { ecma_value_t obj_value = ecma_make_object_value (obj_p); /* 1. */ if (ecma_has_object_value_in_collection (context_p->occurence_stack_p, obj_value)) { return ecma_raise_type_error (""); } ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); /* 2. */ ecma_append_to_values_collection (context_p->occurence_stack_p, obj_value, true); /* 3. */ ecma_string_t *stepback_p = context_p->indent_str_p; /* 4. */ context_p->indent_str_p = ecma_concat_ecma_strings (context_p->indent_str_p, context_p->gap_str_p); ecma_collection_header_t *property_keys_p; /* 5. */ if (context_p->property_list_p->unit_number > 0) { property_keys_p = context_p->property_list_p; } /* 6. */ else { property_keys_p = ecma_new_values_collection (NULL, 0, true); ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, true, false); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, props_p); while (ecma_collection_iterator_next (&iter)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p); JERRY_ASSERT (ecma_is_property_enumerable (property_p)); if (property_p->type == ECMA_PROPERTY_NAMEDDATA) { ecma_append_to_values_collection (property_keys_p, *iter.current_value_p, true); } } ecma_free_values_collection (props_p, true); } /* 7. */ ecma_collection_header_t *partial_p = ecma_new_values_collection (NULL, 0, true); /* 8. */ ecma_collection_iterator_t iterator; ecma_collection_iterator_init (&iterator, property_keys_p); while (ecma_collection_iterator_next (&iterator) && ecma_is_value_empty (ret_value)) { ecma_value_t value = *iterator.current_value_p; ecma_string_t *key_p = ecma_get_string_from_value (value); /* 8.a */ ECMA_TRY_CATCH (str_val, ecma_builtin_json_str (key_p, obj_p, context_p), ret_value); /* 8.b */ if (!ecma_is_value_undefined (str_val)) { ecma_string_t *colon_p = ecma_get_magic_string (LIT_MAGIC_STRING_COLON_CHAR); ecma_string_t *value_str_p = ecma_get_string_from_value (str_val); ecma_string_t *tmp_str_p; /* 8.b.i */ ecma_value_t str_comp_val = ecma_builtin_json_quote (key_p); JERRY_ASSERT (!ecma_is_value_error (str_comp_val)); ecma_string_t *member_str_p = ecma_get_string_from_value (str_comp_val); /* 8.b.ii */ tmp_str_p = ecma_concat_ecma_strings (member_str_p, colon_p); ecma_free_value (str_comp_val); ecma_deref_ecma_string (colon_p); member_str_p = tmp_str_p; /* 8.b.iii */ bool is_gap_empty = (ecma_string_get_length (context_p->gap_str_p) == 0); if (!is_gap_empty) { ecma_string_t *space_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_SPACE_CHAR); tmp_str_p = ecma_concat_ecma_strings (member_str_p, space_str_p); ecma_deref_ecma_string (member_str_p); ecma_deref_ecma_string (space_str_p); member_str_p = tmp_str_p; } /* 8.b.iv */ tmp_str_p = ecma_concat_ecma_strings (member_str_p, value_str_p); ecma_deref_ecma_string (member_str_p); member_str_p = tmp_str_p; /* 8.b.v */ ecma_value_t member_value = ecma_make_string_value (member_str_p); ecma_append_to_values_collection (partial_p, member_value, true); ecma_deref_ecma_string (member_str_p); } ECMA_FINALIZE (str_val); } if (context_p->property_list_p->unit_number == 0) { ecma_free_values_collection (property_keys_p, true); } if (!ecma_is_value_empty (ret_value)) { ecma_free_values_collection (partial_p, true); ecma_deref_ecma_string (stepback_p); return ret_value; } /* 9. */ if (partial_p->unit_number == 0) { ecma_string_t *left_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_BRACE_CHAR); ecma_string_t *right_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR); ecma_string_t *final_str_p = ecma_concat_ecma_strings (left_brace_str_p, right_brace_str_p); ret_value = ecma_make_string_value (final_str_p); ecma_deref_ecma_string (left_brace_str_p); ecma_deref_ecma_string (right_brace_str_p); } /* 10. */ else { bool is_gap_empty = (ecma_string_get_length (context_p->gap_str_p) == 0); /* 10.a */ if (is_gap_empty) { ecma_string_t *left_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_BRACE_CHAR); ecma_string_t *right_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR); ret_value = ecma_builtin_helper_json_create_non_formatted_json (left_brace_str_p, right_brace_str_p, partial_p); ecma_deref_ecma_string (left_brace_str_p); ecma_deref_ecma_string (right_brace_str_p); } /* 10.b */ else { ecma_string_t *left_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LEFT_BRACE_CHAR); ecma_string_t *right_brace_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR); ret_value = ecma_builtin_helper_json_create_formatted_json (left_brace_str_p, right_brace_str_p, stepback_p, partial_p, context_p); ecma_deref_ecma_string (left_brace_str_p); ecma_deref_ecma_string (right_brace_str_p); } } ecma_free_values_collection (partial_p, true); /* 11. */ ecma_remove_last_value_from_values_collection (context_p->occurence_stack_p); /* 12. */ ecma_deref_ecma_string (context_p->indent_str_p); context_p->indent_str_p = stepback_p; /* 13. */ return ret_value; } /* ecma_builtin_json_object */
/** * Abstract operation 'Quote' 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_quote (ecma_string_t *string_p) /**< string that should be quoted*/ { /* 1. */ ecma_string_t *quote_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_DOUBLE_QUOTE_CHAR); ecma_string_t *product_str_p = ecma_copy_or_ref_ecma_string (quote_str_p); ecma_string_t *tmp_str_p; ecma_length_t string_size = ecma_string_get_size (string_p); MEM_DEFINE_LOCAL_ARRAY (string_buff, string_size, lit_utf8_byte_t); ssize_t bytes_copied = ecma_string_to_utf8_string (string_p, string_buff, (ssize_t) string_size); JERRY_ASSERT (bytes_copied > 0 || !string_size); lit_utf8_byte_t *str_p = string_buff; const lit_utf8_byte_t *str_end_p = str_p + string_size; while (str_p < str_end_p) { ecma_char_t current_char = lit_utf8_read_next (&str_p); /* 2.a */ if (current_char == LIT_CHAR_BACKSLASH || current_char == LIT_CHAR_DOUBLE_QUOTE) { ecma_string_t *backslash_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_BACKSLASH_CHAR); /* 2.a.i */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, backslash_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (backslash_str_p); product_str_p = tmp_str_p; /* 2.a.ii */ ecma_string_t *current_char_str_p = ecma_new_ecma_string_from_code_unit (current_char); tmp_str_p = ecma_concat_ecma_strings (product_str_p, current_char_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (current_char_str_p); product_str_p = tmp_str_p; } /* 2.b */ else if (current_char == LIT_CHAR_BS || current_char == LIT_CHAR_FF || current_char == LIT_CHAR_LF || current_char == LIT_CHAR_CR || current_char == LIT_CHAR_TAB) { ecma_string_t *backslash_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_BACKSLASH_CHAR); /* 2.b.i */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, backslash_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (backslash_str_p); product_str_p = tmp_str_p; /* 2.b.ii */ lit_utf8_byte_t abbrev = LIT_CHAR_SP; switch (current_char) { case LIT_CHAR_BS: { abbrev = LIT_CHAR_LOWERCASE_B; break; } case LIT_CHAR_FF: { abbrev = LIT_CHAR_LOWERCASE_F; break; } case LIT_CHAR_LF: { abbrev = LIT_CHAR_LOWERCASE_N; break; } case LIT_CHAR_CR: { abbrev = LIT_CHAR_LOWERCASE_R; break; } case LIT_CHAR_TAB: { abbrev = LIT_CHAR_LOWERCASE_T; break; } } /* 2.b.iii */ ecma_string_t *abbrev_str_p = ecma_new_ecma_string_from_utf8 (&abbrev, 1); tmp_str_p = ecma_concat_ecma_strings (product_str_p, abbrev_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (abbrev_str_p); product_str_p = tmp_str_p; } /* 2.c */ else if (current_char < LIT_CHAR_SP) { ecma_string_t *backslash_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_BACKSLASH_CHAR); /* 2.c.i */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, backslash_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (backslash_str_p); product_str_p = tmp_str_p; /* 2.c.ii */ lit_utf8_byte_t u_ch = LIT_CHAR_LOWERCASE_U; ecma_string_t *u_ch_str_p = ecma_new_ecma_string_from_utf8 (&u_ch, 1); tmp_str_p = ecma_concat_ecma_strings (product_str_p, u_ch_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (u_ch_str_p); product_str_p = tmp_str_p; /* 2.c.iii */ ecma_string_t *hex_str_p = ecma_builtin_helper_json_create_hex_digit_ecma_string ((uint8_t) current_char); /* 2.c.iv */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, hex_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (hex_str_p); product_str_p = tmp_str_p; } /* 2.d */ else { ecma_string_t *current_char_str_p = ecma_new_ecma_string_from_code_unit (current_char); tmp_str_p = ecma_concat_ecma_strings (product_str_p, current_char_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (current_char_str_p); product_str_p = tmp_str_p; } } MEM_FINALIZE_LOCAL_ARRAY (string_buff); /* 3. */ tmp_str_p = ecma_concat_ecma_strings (product_str_p, quote_str_p); ecma_deref_ecma_string (product_str_p); ecma_deref_ecma_string (quote_str_p); product_str_p = tmp_str_p; /* 4. */ return ecma_make_string_value (product_str_p); } /* ecma_builtin_json_quote */
/** * Get backtrace. The backtrace is an array of strings where * each string contains the position of the corresponding frame. * The array length is zero if the backtrace is not available. * * @return array ecma value */ ecma_value_t vm_get_backtrace (uint32_t max_depth) /**< maximum backtrace depth, 0 = unlimited */ { #ifdef JERRY_ENABLE_LINE_INFO ecma_value_t result_array = ecma_op_create_array_object (NULL, 0, false); if (max_depth == 0) { max_depth = UINT32_MAX; } vm_frame_ctx_t *context_p = JERRY_CONTEXT (vm_top_context_p); ecma_object_t *array_p = ecma_get_object_from_value (result_array); uint32_t index = 0; while (context_p != NULL) { if (context_p->resource_name == ECMA_VALUE_UNDEFINED) { context_p = context_p->prev_context_p; continue; } ecma_string_t *str_p = ecma_get_string_from_value (context_p->resource_name); if (ecma_string_is_empty (str_p)) { const char *unknown_str_p = "<unknown>:"; str_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) unknown_str_p, (lit_utf8_size_t) strlen (unknown_str_p)); } else { ecma_ref_ecma_string (str_p); str_p = ecma_append_magic_string_to_string (str_p, LIT_MAGIC_STRING_COLON_CHAR); } ecma_string_t *line_str_p = ecma_new_ecma_string_from_uint32 (context_p->current_line); str_p = ecma_concat_ecma_strings (str_p, line_str_p); ecma_deref_ecma_string (line_str_p); ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); ecma_property_value_t *prop_value_p; prop_value_p = ecma_create_named_data_property (array_p, index_str_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, NULL); ecma_deref_ecma_string (index_str_p); prop_value_p->value = ecma_make_string_value (str_p); context_p = context_p->prev_context_p; index++; if (index >= max_depth) { break; } } if (index > 0) { JERRY_ASSERT (ecma_get_object_type (array_p) == ECMA_OBJECT_TYPE_ARRAY); ((ecma_extended_object_t *) array_p)->u.array.length = index; } return result_array; #else /* !JERRY_ENABLE_LINE_INFO */ JERRY_UNUSED (max_depth); return ecma_op_create_array_object (NULL, 0, false); #endif /* JERRY_ENABLE_LINE_INFO */ } /* vm_get_backtrace */
/** * The Number.prototype object's 'toPrecision' routine * * See also: * ECMA-262 v5, 15.7.4.7 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_number_prototype_object_to_precision (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); /* 1. */ ECMA_TRY_CATCH (this_value, ecma_builtin_number_prototype_object_value_of (this_arg), ret_value); ecma_number_t this_num = *ecma_get_number_from_value (this_value); /* 2. */ if (ecma_is_value_undefined (arg)) { ret_value = ecma_builtin_number_prototype_object_to_string (this_arg, NULL, 0); } else { /* 3. */ ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); /* 4. */ if (ecma_number_is_nan (this_num)) { ecma_string_t *nan_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NAN); ret_value = ecma_make_string_value (nan_str_p); } else { bool is_negative = false; /* 6. */ if (ecma_number_is_negative (this_num) && !ecma_number_is_zero (this_num)) { is_negative = true; this_num *= -1; } /* 7. */ if (ecma_number_is_infinity (this_num)) { ecma_string_t *infinity_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INFINITY_UL); if (is_negative) { ecma_string_t *neg_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_MINUS_CHAR); ecma_string_t *neg_inf_str_p = ecma_concat_ecma_strings (neg_str_p, infinity_str_p); ecma_deref_ecma_string (infinity_str_p); ecma_deref_ecma_string (neg_str_p); ret_value = ecma_make_string_value (neg_inf_str_p); } else { ret_value = ecma_make_string_value (infinity_str_p); } } /* 8. */ else if (arg_num < 1.0 || arg_num >= 22.0) { ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("")); } else { uint64_t digits = 0; int32_t num_digits = 0; int32_t exponent = 1; int32_t precision = ecma_number_to_int32 (arg_num); /* Get the parameters of the number if non-zero. */ if (!ecma_number_is_zero (this_num)) { ecma_number_to_decimal (this_num, &digits, &num_digits, &exponent); } digits = ecma_builtin_number_prototype_helper_round (digits, num_digits - precision); int buffer_size; if (exponent < -5 || exponent > precision) { /* Exponential notation, precision + 1 digits for number, 5 for exponent, 1 for \0 */ buffer_size = precision + 1 + 5 + 1; } else if (exponent <= 0) { /* Fixed notation, -exponent + 2 digits for leading zeros, precision digits, 1 for \0 */ buffer_size = -exponent + 2 + precision + 1; } else { /* Fixed notation, precision + 1 digits for number, 1 for \0 */ buffer_size = precision + 1 + 1; } if (is_negative) { buffer_size++; } MEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *actual_char_p = buff; uint64_t scale = 1; /* Calculate the magnitude of the number. This is used to get the digits from left to right. */ while (scale <= digits) { scale *= 10; } if (is_negative) { *actual_char_p++ = '-'; } int digit = 0; /* 10.c, Exponential notation.*/ if (exponent < -5 || exponent > precision) { /* Add significant digits. */ for (int i = 1; i <= precision; i++) { digit = 0; scale /= 10; while (digits >= scale && scale > 0) { digits -= scale; digit++; } *actual_char_p++ = (lit_utf8_byte_t) (digit + '0'); if (i == 1 && i != precision) { *actual_char_p++ = '.'; } } *actual_char_p++ = 'e'; exponent--; if (exponent < 0) { exponent *= -1; *actual_char_p++ = '-'; } else { *actual_char_p++ = '+'; } /* Get magnitude of exponent. */ int32_t scale_expt = 1; while (scale_expt <= exponent) { scale_expt *= 10; } scale_expt /= 10; /* Add exponent digits. */ if (exponent == 0) { *actual_char_p++ = '0'; } else { while (scale_expt > 0) { digit = exponent / scale_expt; exponent %= scale_expt; *actual_char_p++ = (lit_utf8_byte_t) (digit + '0'); scale_expt /= 10; } } } /* Fixed notation. */ else { /* Add leading zeros if neccessary. */ if (exponent <= 0) { *actual_char_p++ = '0'; *actual_char_p++ = '.'; for (int i = exponent; i < 0; i++) { *actual_char_p++ = '0'; } } /* Add significant digits. */ for (int i = 1; i <= precision; i++) { digit = 0; scale /= 10; while (digits >= scale && scale > 0) { digits -= scale; digit++; } *actual_char_p++ = (lit_utf8_byte_t) (digit + '0'); if (i == exponent && i != precision) { *actual_char_p++ = '.'; } } } JERRY_ASSERT (actual_char_p - buff < buffer_size); *actual_char_p = '\0'; ecma_string_t *str_p = ecma_new_ecma_string_from_utf8 (buff, (lit_utf8_size_t) (actual_char_p - buff)); ret_value = ecma_make_string_value (str_p); MEM_FINALIZE_LOCAL_ARRAY (buff); } } ECMA_OP_TO_NUMBER_FINALIZE (arg_num); } ECMA_FINALIZE (this_value); return ret_value; } /* ecma_builtin_number_prototype_object_to_precision */
/** * Helper method to count and convert the arguments for the Function constructor call. * * Performs the operation described in ECMA 262 v5.1 15.3.2.1 steps 5.a-d * * * @return completion value - concatenated arguments as a string. * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_function_helper_get_function_expression (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 (); ecma_string_t *left_parenthesis_str_p, *right_parenthesis_str_p; ecma_string_t *left_brace_str_p, *right_brace_str_p; ecma_string_t *comma_str_p; ecma_string_t *function_kw_str_p, *empty_str_p; ecma_string_t *expr_str_p, *concated_str_p; left_parenthesis_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_LEFT_PARENTHESIS_CHAR); right_parenthesis_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_RIGHT_PARENTHESIS_CHAR); left_brace_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_LEFT_BRACE_CHAR); right_brace_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR); comma_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_COMMA_CHAR); function_kw_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING_FUNCTION); empty_str_p = ecma_new_ecma_string_from_magic_string_id (LIT_MAGIC_STRING__EMPTY); /* First, we only process the function arguments skipping the function body */ ecma_length_t number_of_function_args = (arguments_list_len == 0 ? 0 : arguments_list_len - 1); expr_str_p = ecma_concat_ecma_strings (left_parenthesis_str_p, function_kw_str_p); concated_str_p = ecma_concat_ecma_strings (expr_str_p, left_parenthesis_str_p); ecma_deref_ecma_string (expr_str_p); expr_str_p = concated_str_p; for (ecma_length_t idx = 0; idx < number_of_function_args && ecma_is_completion_value_empty (ret_value); idx++) { ECMA_TRY_CATCH (str_arg_value, ecma_op_to_string (arguments_list_p[idx]), ret_value); ecma_string_t *str_p = ecma_get_string_from_value (str_arg_value); concated_str_p = ecma_concat_ecma_strings (expr_str_p, str_p); ecma_deref_ecma_string (expr_str_p); expr_str_p = concated_str_p; if (idx < number_of_function_args - 1) { concated_str_p = ecma_concat_ecma_strings (expr_str_p, comma_str_p); ecma_deref_ecma_string (expr_str_p); expr_str_p = concated_str_p; } ECMA_FINALIZE (str_arg_value); } if (ecma_is_completion_value_empty (ret_value)) { concated_str_p = ecma_concat_ecma_strings (expr_str_p, right_parenthesis_str_p); ecma_deref_ecma_string (expr_str_p); expr_str_p = concated_str_p; concated_str_p = ecma_concat_ecma_strings (expr_str_p, left_brace_str_p); ecma_deref_ecma_string (expr_str_p); expr_str_p = concated_str_p; if (arguments_list_len != 0) { ECMA_TRY_CATCH (str_arg_value, ecma_op_to_string (arguments_list_p[arguments_list_len - 1]), ret_value); ecma_string_t *body_str_p = ecma_get_string_from_value (str_arg_value); concated_str_p = ecma_concat_ecma_strings (expr_str_p, body_str_p); ecma_deref_ecma_string (expr_str_p); expr_str_p = concated_str_p; ECMA_FINALIZE (str_arg_value); } concated_str_p = ecma_concat_ecma_strings (expr_str_p, right_brace_str_p); ecma_deref_ecma_string (expr_str_p); expr_str_p = concated_str_p; concated_str_p = ecma_concat_ecma_strings (expr_str_p, right_parenthesis_str_p); ecma_deref_ecma_string (expr_str_p); expr_str_p = concated_str_p; } ecma_deref_ecma_string (left_parenthesis_str_p); ecma_deref_ecma_string (right_parenthesis_str_p); ecma_deref_ecma_string (left_brace_str_p); ecma_deref_ecma_string (right_brace_str_p); ecma_deref_ecma_string (comma_str_p); ecma_deref_ecma_string (function_kw_str_p); ecma_deref_ecma_string (empty_str_p); if (ecma_is_completion_value_empty (ret_value)) { ret_value = ecma_make_normal_completion_value (ecma_make_string_value (expr_str_p)); } else { ecma_deref_ecma_string (expr_str_p); } return ret_value; } /* ecma_builtin_function_helper_get_function_expression */
/* * Converts an standard error into a string. * * @return standard error string */ static ecma_string_t * jerry_debugger_exception_object_to_string (ecma_value_t exception_obj_value) /**< exception object */ { ecma_object_t *object_p = ecma_get_object_from_value (exception_obj_value); ecma_object_t *prototype_p = ecma_get_object_prototype (object_p); if (prototype_p == NULL || ecma_get_object_type (prototype_p) != ECMA_OBJECT_TYPE_GENERAL || !ecma_get_object_is_builtin (prototype_p)) { return NULL; } lit_magic_string_id_t string_id; switch (((ecma_extended_object_t *) prototype_p)->u.built_in.id) { #ifndef CONFIG_DISABLE_ERROR_BUILTINS case ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE: { string_id = LIT_MAGIC_STRING_EVAL_ERROR_UL; break; } case ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE: { string_id = LIT_MAGIC_STRING_RANGE_ERROR_UL; break; } case ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE: { string_id = LIT_MAGIC_STRING_REFERENCE_ERROR_UL; break; } case ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE: { string_id = LIT_MAGIC_STRING_SYNTAX_ERROR_UL; break; } case ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE: { string_id = LIT_MAGIC_STRING_TYPE_ERROR_UL; break; } case ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE: { string_id = LIT_MAGIC_STRING_URI_ERROR_UL; break; } #endif /* !CONFIG_DISABLE_ERROR_BUILTINS */ case ECMA_BUILTIN_ID_ERROR_PROTOTYPE: { string_id = LIT_MAGIC_STRING_ERROR_UL; break; } default: { return NULL; } } lit_utf8_size_t size = lit_get_magic_string_size (string_id); JERRY_ASSERT (size <= 14); lit_utf8_byte_t data[16]; memcpy (data, lit_get_magic_string_utf8 (string_id), size); ecma_property_t *property_p; property_p = ecma_find_named_property (ecma_get_object_from_value (exception_obj_value), ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE)); if (property_p == NULL || ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDDATA) { return ecma_new_ecma_string_from_utf8 (data, size); } ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); if (!ecma_is_value_string (prop_value_p->value)) { return ecma_new_ecma_string_from_utf8 (data, size); } data[size] = LIT_CHAR_COLON; data[size + 1] = LIT_CHAR_SP; return ecma_concat_ecma_strings (ecma_new_ecma_string_from_utf8 (data, size + 2), ecma_get_string_from_value (prop_value_p->value)); } /* jerry_debugger_exception_object_to_string */
/** * The Number.prototype object's 'toFixed' routine * * See also: * ECMA-262 v5, 15.7.4.5 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_number_prototype_object_to_fixed (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); ECMA_TRY_CATCH (this_value, ecma_builtin_number_prototype_object_value_of (this_arg), ret_value); ecma_number_t this_num = *ecma_get_number_from_value (this_value); ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); /* 2. */ if (arg_num <= -1 || arg_num >= 21) { ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("")); } else { /* 4. */ if (ecma_number_is_nan (this_num)) { ecma_string_t *nan_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NAN); ret_value = ecma_make_string_value (nan_str_p); } else { bool is_negative = false; /* 6. */ if (ecma_number_is_negative (this_num)) { is_negative = true; this_num *= -1; } /* We handle infinities separately. */ if (ecma_number_is_infinity (this_num)) { ecma_string_t *infinity_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INFINITY_UL); if (is_negative) { ecma_string_t *neg_str_p = ecma_new_ecma_string_from_utf8 ((const lit_utf8_byte_t *) "-", 1); ecma_string_t *neg_inf_str_p = ecma_concat_ecma_strings (neg_str_p, infinity_str_p); ecma_deref_ecma_string (infinity_str_p); ecma_deref_ecma_string (neg_str_p); ret_value = ecma_make_string_value (neg_inf_str_p); } else { ret_value = ecma_make_string_value (infinity_str_p); } } else { uint64_t digits = 0; int32_t num_digits = 0; int32_t exponent = 1; /* 1. */ int32_t frac_digits = ecma_number_to_int32 (arg_num); /* Get the parameters of the number if non-zero. */ if (!ecma_number_is_zero (this_num)) { ecma_number_to_decimal (this_num, &digits, &num_digits, &exponent); } digits = ecma_builtin_number_prototype_helper_round (digits, num_digits - exponent - frac_digits); /* 7. */ if (exponent > 21) { ret_value = ecma_builtin_number_prototype_object_to_string (this_arg, NULL, 0); } /* 8. */ else { /* Buffer that is used to construct the string. */ int buffer_size = (exponent > 0) ? exponent + frac_digits + 2 : frac_digits + 3; if (is_negative) { buffer_size++; } JERRY_ASSERT (buffer_size > 0); MEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *p = buff; if (is_negative) { *p++ = '-'; } int8_t digit = 0; uint64_t s = 1; /* Calculate the magnitude of the number. This is used to get the digits from left to right. */ while (s <= digits) { s *= 10; } if (exponent <= 0) { /* Add leading zeros. */ *p++ = '0'; if (frac_digits != 0) { *p++ = '.'; } for (int i = 0; i < -exponent && i < frac_digits; i++) { *p++ = '0'; } /* Add significant digits. */ for (int i = -exponent; i < frac_digits; i++) { digit = 0; s /= 10; while (digits >= s && s > 0) { digits -= s; digit++; } *p = (lit_utf8_byte_t) ((lit_utf8_byte_t) digit + '0'); p++; } } else { /* Add significant digits. */ for (int i = 0; i < exponent; i++) { digit = 0; s /= 10; while (digits >= s && s > 0) { digits -= s; digit++; } *p = (lit_utf8_byte_t) ((lit_utf8_byte_t) digit + '0'); p++; } /* Add the decimal point after whole part. */ if (frac_digits != 0) { *p++ = '.'; } /* Add neccessary fracion digits. */ for (int i = 0; i < frac_digits; i++) { digit = 0; s /= 10; while (digits >= s && s > 0) { digits -= s; digit++; } *p = (lit_utf8_byte_t) ((lit_utf8_byte_t) digit + '0'); p++; } } JERRY_ASSERT (p - buff < buffer_size); /* String terminator. */ *p = 0; ecma_string_t *str = ecma_new_ecma_string_from_utf8 (buff, (lit_utf8_size_t) (p - buff)); ret_value = ecma_make_string_value (str); MEM_FINALIZE_LOCAL_ARRAY (buff); } } } } ECMA_OP_TO_NUMBER_FINALIZE (arg_num); ECMA_FINALIZE (this_value); return ret_value; } /* ecma_builtin_number_prototype_object_to_fixed */