diff --git a/jerry-core/ecma/base/ecma-helpers-number.c b/jerry-core/ecma/base/ecma-helpers-number.c index eb0f224fa..8de473d65 100644 --- a/jerry-core/ecma/base/ecma-helpers-number.c +++ b/jerry-core/ecma/base/ecma-helpers-number.c @@ -13,8 +13,8 @@ * limitations under the License. */ -#include "ecma-globals.h" -#include "ecma-helpers.h" +#include "ecma-conversion.h" +#include "lit-char-helpers.h" /** \addtogroup ecma ECMA * @{ @@ -681,6 +681,372 @@ ecma_integer_multiply (ecma_integer_value_t left_integer, /**< left operand */ return ecma_make_integer_value (left_integer * right_integer); } /* ecma_integer_multiply */ +/** + * The Number object's 'parseInt' routine + * + * See also: + * ECMA-262 v5, 15.1.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_number_parse_int (const lit_utf8_byte_t *string_buff, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t string_buff_size, /**< routine's first argument's + * string buffer's size */ + ecma_value_t radix) /**< routine's second argument */ +{ + if (string_buff_size <= 0) + { + return ecma_make_nan_value (); + } + + const lit_utf8_byte_t *string_curr_p = string_buff; + + /* 2. Remove leading whitespace. */ + ecma_string_trim_helper (&string_curr_p, &string_buff_size); + + const lit_utf8_byte_t *string_end_p = string_curr_p + string_buff_size; + const lit_utf8_byte_t *start_p = string_curr_p; + const lit_utf8_byte_t *end_p = string_end_p; + + if (string_curr_p >= string_end_p) + { + return ecma_make_nan_value (); + } + + /* 3. */ + int sign = 1; + + /* 4. */ + ecma_char_t current = lit_cesu8_read_next (&string_curr_p); + if (current == LIT_CHAR_MINUS) + { + sign = -1; + } + + /* 5. */ + if (current == LIT_CHAR_MINUS || current == LIT_CHAR_PLUS) + { + start_p = string_curr_p; + if (string_curr_p < string_end_p) + { + current = lit_cesu8_read_next (&string_curr_p); + } + } + + /* 6. */ + ecma_number_t radix_num; + radix = ecma_get_number (radix, &radix_num); + + if (!ecma_is_value_empty (radix)) + { + return radix; + } + + int32_t rad = ecma_number_to_int32 (radix_num); + + /* 7.*/ + bool strip_prefix = true; + + /* 8. */ + if (rad != 0) + { + /* 8.a */ + if (rad < 2 || rad > 36) + { + return ecma_make_nan_value (); + } + /* 8.b */ + else if (rad != 16) + { + strip_prefix = false; + } + } + /* 9. */ + else + { + rad = 10; + } + + /* 10. */ + if (strip_prefix + && ((end_p - start_p) >= 2) + && (current == LIT_CHAR_0)) + { + ecma_char_t next = *string_curr_p; + if (next == LIT_CHAR_LOWERCASE_X || next == LIT_CHAR_UPPERCASE_X) + { + /* Skip the 'x' or 'X' characters. */ + start_p = ++string_curr_p; + rad = 16; + } + } + + /* 11. Check if characters are in [0, Radix - 1]. We also convert them to number values in the process. */ + string_curr_p = start_p; + while (string_curr_p < string_end_p) + { + ecma_char_t current_char = *string_curr_p++; + int32_t current_number; + + if ((current_char >= LIT_CHAR_LOWERCASE_A && current_char <= LIT_CHAR_LOWERCASE_Z)) + { + current_number = current_char - LIT_CHAR_LOWERCASE_A + 10; + } + else if ((current_char >= LIT_CHAR_UPPERCASE_A && current_char <= LIT_CHAR_UPPERCASE_Z)) + { + current_number = current_char - LIT_CHAR_UPPERCASE_A + 10; + } + else if (lit_char_is_decimal_digit (current_char)) + { + current_number = current_char - LIT_CHAR_0; + } + else + { + /* Not a valid number char, set value to radix so it fails to pass as a valid character. */ + current_number = rad; + } + + if (!(current_number < rad)) + { + end_p = --string_curr_p; + break; + } + } + + /* 12. */ + if (end_p == start_p) + { + return ecma_make_nan_value (); + } + + ecma_number_t value = ECMA_NUMBER_ZERO; + ecma_number_t multiplier = 1.0f; + + /* 13. and 14. */ + string_curr_p = end_p; + + while (string_curr_p > start_p) + { + ecma_char_t current_char = *(--string_curr_p); + ecma_number_t current_number = ECMA_NUMBER_MINUS_ONE; + + if ((current_char >= LIT_CHAR_LOWERCASE_A && current_char <= LIT_CHAR_LOWERCASE_Z)) + { + current_number = (ecma_number_t) current_char - LIT_CHAR_LOWERCASE_A + 10; + } + else if ((current_char >= LIT_CHAR_UPPERCASE_A && current_char <= LIT_CHAR_UPPERCASE_Z)) + { + current_number = (ecma_number_t) current_char - LIT_CHAR_UPPERCASE_A + 10; + } + else + { + JERRY_ASSERT (lit_char_is_decimal_digit (current_char)); + current_number = (ecma_number_t) current_char - LIT_CHAR_0; + } + + value += current_number * multiplier; + multiplier *= (ecma_number_t) rad; + } + + /* 15. */ + if (sign < 0) + { + value *= (ecma_number_t) sign; + } + return ecma_make_number_value (value); +} /* ecma_number_parse_int */ + +/** + * The Number object's 'parseFloat' routine + * + * See also: + * ECMA-262 v5, 15.1.2.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_number_parse_float (const lit_utf8_byte_t *string_buff, /**< routine's first argument's + * string buffer */ + lit_utf8_size_t string_buff_size) /**< routine's first argument's + * string buffer's size */ +{ + if (string_buff_size <= 0) + { + return ecma_make_nan_value (); + } + + const lit_utf8_byte_t *str_curr_p = string_buff; + + /* 2. Remove leading whitespace. */ + ecma_string_trim_helper (&str_curr_p, &string_buff_size); + + const lit_utf8_byte_t *str_end_p = str_curr_p + string_buff_size; + const lit_utf8_byte_t *start_p = str_curr_p; + const lit_utf8_byte_t *end_p = str_end_p; + + bool sign = false; + ecma_char_t current; + + if (str_curr_p < str_end_p) + { + /* Check if sign is present. */ + current = *str_curr_p; + if (current == LIT_CHAR_MINUS) + { + sign = true; + } + + if (current == LIT_CHAR_MINUS || current == LIT_CHAR_PLUS) + { + /* Set starting position to be after the sign character. */ + start_p = ++str_curr_p; + } + } + + const lit_utf8_byte_t *infinity_str_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING_INFINITY_UL); + lit_utf8_byte_t *infinity_str_curr_p = (lit_utf8_byte_t *) infinity_str_p; + lit_utf8_byte_t *infinity_str_end_p = infinity_str_curr_p + sizeof (*infinity_str_p); + + /* Check if string is equal to "Infinity". */ + while (str_curr_p < str_end_p + && *str_curr_p++ == *infinity_str_curr_p++) + { + if (infinity_str_curr_p == infinity_str_end_p) + { + /* String matched Infinity. */ + return ecma_make_number_value (ecma_number_make_infinity (sign)); + } + } + + /* Reset to starting position. */ + str_curr_p = start_p; + + /* String ended after sign character, or was empty after removing leading whitespace. */ + if (str_curr_p >= str_end_p) + { + return ecma_make_nan_value (); + } + + /* Reset to starting position. */ + str_curr_p = start_p; + + current = *str_curr_p; + + bool has_whole_part = false; + bool has_fraction_part = false; + + /* Check digits of whole part. */ + if (lit_char_is_decimal_digit (current)) + { + has_whole_part = true; + str_curr_p++; + + while (str_curr_p < str_end_p) + { + current = *str_curr_p++; + if (!lit_char_is_decimal_digit (current)) + { + str_curr_p--; + break; + } + } + } + + /* Set end position to the end of whole part. */ + end_p = str_curr_p; + if (str_curr_p < str_end_p) + { + current = *str_curr_p; + + /* Check decimal point. */ + if (current == LIT_CHAR_DOT) + { + str_curr_p++; + + if (str_curr_p < str_end_p) + { + current = *str_curr_p; + + if (lit_char_is_decimal_digit (current)) + { + has_fraction_part = true; + + /* Check digits of fractional part. */ + while (str_curr_p < str_end_p) + { + current = *str_curr_p++; + if (!lit_char_is_decimal_digit (current)) + { + str_curr_p--; + break; + } + } + + /* Set end position to end of fraction part. */ + end_p = str_curr_p; + } + } + } + } + + if (str_curr_p < str_end_p) + { + current = *str_curr_p++; + } + + /* Check exponent. */ + if ((current == LIT_CHAR_LOWERCASE_E || current == LIT_CHAR_UPPERCASE_E) + && (has_whole_part || has_fraction_part) + && str_curr_p < str_end_p) + { + current = *str_curr_p++; + + /* Check sign of exponent. */ + if ((current == LIT_CHAR_PLUS || current == LIT_CHAR_MINUS) + && str_curr_p < str_end_p) + { + current = *str_curr_p++; + } + + if (lit_char_is_decimal_digit (current)) + { + /* Check digits of exponent part. */ + while (str_curr_p < str_end_p) + { + current = *str_curr_p++; + if (!lit_char_is_decimal_digit (current)) + { + str_curr_p--; + break; + } + } + + /* Set end position to end of exponent part. */ + end_p = str_curr_p; + } + } + + /* String did not contain a valid number. */ + if (start_p == end_p) + { + return ecma_make_nan_value (); + } + + /* 5. */ + ecma_number_t ret_num = ecma_utf8_string_to_number (start_p, (lit_utf8_size_t) (end_p - start_p)); + + if (sign) + { + ret_num *= ECMA_NUMBER_MINUS_ONE; + } + + return ecma_make_number_value (ret_num); +} /* ecma_number_parse_float */ + /** * @} * @} diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 1c05d5c6b..cb937be1d 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -400,6 +400,11 @@ ecma_number_t ecma_number_get_prev (ecma_number_t num); ecma_number_t ecma_number_get_next (ecma_number_t num); ecma_number_t ecma_number_trunc (ecma_number_t num); ecma_number_t ecma_number_calc_remainder (ecma_number_t left_num, ecma_number_t right_num); +ecma_value_t ecma_number_parse_int (const lit_utf8_byte_t *string_buff, + lit_utf8_size_t string_buff_size, + ecma_value_t radix); +ecma_value_t ecma_number_parse_float (const lit_utf8_byte_t *string_buff, + lit_utf8_size_t string_buff_size); ecma_value_t ecma_integer_multiply (ecma_integer_value_t left_integer, ecma_integer_value_t right_integer); lit_utf8_size_t ecma_number_to_decimal (ecma_number_t num, lit_utf8_byte_t *out_digits_p, int32_t *out_decimal_exp_p); lit_utf8_size_t ecma_number_to_binary_floating_point_number (ecma_number_t num, diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-global.c b/jerry-core/ecma/builtin-objects/ecma-builtin-global.c index 9f3728994..0c00244a8 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-global.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-global.c @@ -111,373 +111,6 @@ ecma_builtin_global_object_eval (ecma_value_t x) /**< routine's first argument * return ecma_op_eval (ecma_get_string_from_value (x), parse_opts); } /* ecma_builtin_global_object_eval */ -/** - * The Global object's 'parseInt' routine - * - * See also: - * ECMA-262 v5, 15.1.2.2 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_global_object_parse_int (const lit_utf8_byte_t *string_buff, /**< routine's first argument's - * string buffer */ - lit_utf8_size_t string_buff_size, /**< routine's first argument's - * string buffer's size */ - ecma_value_t radix) /**< routine's second argument */ -{ - if (string_buff_size <= 0) - { - return ecma_make_nan_value (); - } - - const lit_utf8_byte_t *string_curr_p = string_buff; - - /* 2. Remove leading whitespace. */ - ecma_string_trim_helper (&string_curr_p, &string_buff_size); - - const lit_utf8_byte_t *string_end_p = string_curr_p + string_buff_size; - const lit_utf8_byte_t *start_p = string_curr_p; - const lit_utf8_byte_t *end_p = string_end_p; - - if (string_curr_p >= string_end_p) - { - return ecma_make_nan_value (); - } - - /* 3. */ - int sign = 1; - - /* 4. */ - ecma_char_t current = lit_cesu8_read_next (&string_curr_p); - if (current == LIT_CHAR_MINUS) - { - sign = -1; - } - - /* 5. */ - if (current == LIT_CHAR_MINUS || current == LIT_CHAR_PLUS) - { - start_p = string_curr_p; - if (string_curr_p < string_end_p) - { - current = lit_cesu8_read_next (&string_curr_p); - } - } - - /* 6. */ - ecma_number_t radix_num; - radix = ecma_get_number (radix, &radix_num); - - if (!ecma_is_value_empty (radix)) - { - return radix; - } - - int32_t rad = ecma_number_to_int32 (radix_num); - - /* 7.*/ - bool strip_prefix = true; - - /* 8. */ - if (rad != 0) - { - /* 8.a */ - if (rad < 2 || rad > 36) - { - return ecma_make_nan_value (); - } - /* 8.b */ - else if (rad != 16) - { - strip_prefix = false; - } - } - /* 9. */ - else - { - rad = 10; - } - - /* 10. */ - if (strip_prefix - && ((end_p - start_p) >= 2) - && (current == LIT_CHAR_0)) - { - ecma_char_t next = *string_curr_p; - if (next == LIT_CHAR_LOWERCASE_X || next == LIT_CHAR_UPPERCASE_X) - { - /* Skip the 'x' or 'X' characters. */ - start_p = ++string_curr_p; - rad = 16; - } - } - - /* 11. Check if characters are in [0, Radix - 1]. We also convert them to number values in the process. */ - string_curr_p = start_p; - while (string_curr_p < string_end_p) - { - ecma_char_t current_char = *string_curr_p++; - int32_t current_number; - - if ((current_char >= LIT_CHAR_LOWERCASE_A && current_char <= LIT_CHAR_LOWERCASE_Z)) - { - current_number = current_char - LIT_CHAR_LOWERCASE_A + 10; - } - else if ((current_char >= LIT_CHAR_UPPERCASE_A && current_char <= LIT_CHAR_UPPERCASE_Z)) - { - current_number = current_char - LIT_CHAR_UPPERCASE_A + 10; - } - else if (lit_char_is_decimal_digit (current_char)) - { - current_number = current_char - LIT_CHAR_0; - } - else - { - /* Not a valid number char, set value to radix so it fails to pass as a valid character. */ - current_number = rad; - } - - if (!(current_number < rad)) - { - end_p = --string_curr_p; - break; - } - } - - /* 12. */ - if (end_p == start_p) - { - return ecma_make_nan_value (); - } - - ecma_number_t value = ECMA_NUMBER_ZERO; - ecma_number_t multiplier = 1.0f; - - /* 13. and 14. */ - string_curr_p = end_p; - - while (string_curr_p > start_p) - { - ecma_char_t current_char = *(--string_curr_p); - ecma_number_t current_number = ECMA_NUMBER_MINUS_ONE; - - if ((current_char >= LIT_CHAR_LOWERCASE_A && current_char <= LIT_CHAR_LOWERCASE_Z)) - { - current_number = (ecma_number_t) current_char - LIT_CHAR_LOWERCASE_A + 10; - } - else if ((current_char >= LIT_CHAR_UPPERCASE_A && current_char <= LIT_CHAR_UPPERCASE_Z)) - { - current_number = (ecma_number_t) current_char - LIT_CHAR_UPPERCASE_A + 10; - } - else - { - JERRY_ASSERT (lit_char_is_decimal_digit (current_char)); - current_number = (ecma_number_t) current_char - LIT_CHAR_0; - } - - value += current_number * multiplier; - multiplier *= (ecma_number_t) rad; - } - - /* 15. */ - if (sign < 0) - { - value *= (ecma_number_t) sign; - } - - return ecma_make_number_value (value); -} /* ecma_builtin_global_object_parse_int */ - -/** - * The Global object's 'parseFloat' routine - * - * See also: - * ECMA-262 v5, 15.1.2.3 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_global_object_parse_float (const lit_utf8_byte_t *string_buff, /**< routine's first argument's - * string buffer */ - lit_utf8_size_t string_buff_size) /**< routine's first argument's - * string buffer's size */ -{ - if (string_buff_size <= 0) - { - return ecma_make_nan_value (); - } - - const lit_utf8_byte_t *str_curr_p = string_buff; - - /* 2. Remove leading whitespace. */ - ecma_string_trim_helper (&str_curr_p, &string_buff_size); - - const lit_utf8_byte_t *str_end_p = str_curr_p + string_buff_size; - const lit_utf8_byte_t *start_p = str_curr_p; - const lit_utf8_byte_t *end_p = str_end_p; - - bool sign = false; - ecma_char_t current; - - if (str_curr_p < str_end_p) - { - /* Check if sign is present. */ - current = *str_curr_p; - if (current == LIT_CHAR_MINUS) - { - sign = true; - } - - if (current == LIT_CHAR_MINUS || current == LIT_CHAR_PLUS) - { - /* Set starting position to be after the sign character. */ - start_p = ++str_curr_p; - } - } - - const lit_utf8_byte_t *infinity_str_p = lit_get_magic_string_utf8 (LIT_MAGIC_STRING_INFINITY_UL); - lit_utf8_byte_t *infinity_str_curr_p = (lit_utf8_byte_t *) infinity_str_p; - lit_utf8_byte_t *infinity_str_end_p = infinity_str_curr_p + sizeof (*infinity_str_p); - - /* Check if string is equal to "Infinity". */ - while (str_curr_p < str_end_p - && *str_curr_p++ == *infinity_str_curr_p++) - { - if (infinity_str_curr_p == infinity_str_end_p) - { - /* String matched Infinity. */ - return ecma_make_number_value (ecma_number_make_infinity (sign)); - } - } - - /* Reset to starting position. */ - str_curr_p = start_p; - - /* String ended after sign character, or was empty after removing leading whitespace. */ - if (str_curr_p >= str_end_p) - { - return ecma_make_nan_value (); - } - - /* Reset to starting position. */ - str_curr_p = start_p; - - current = *str_curr_p; - - bool has_whole_part = false; - bool has_fraction_part = false; - - /* Check digits of whole part. */ - if (lit_char_is_decimal_digit (current)) - { - has_whole_part = true; - str_curr_p++; - - while (str_curr_p < str_end_p) - { - current = *str_curr_p++; - if (!lit_char_is_decimal_digit (current)) - { - str_curr_p--; - break; - } - } - } - - /* Set end position to the end of whole part. */ - end_p = str_curr_p; - if (str_curr_p < str_end_p) - { - current = *str_curr_p; - - /* Check decimal point. */ - if (current == LIT_CHAR_DOT) - { - str_curr_p++; - - if (str_curr_p < str_end_p) - { - current = *str_curr_p; - - if (lit_char_is_decimal_digit (current)) - { - has_fraction_part = true; - - /* Check digits of fractional part. */ - while (str_curr_p < str_end_p) - { - current = *str_curr_p++; - if (!lit_char_is_decimal_digit (current)) - { - str_curr_p--; - break; - } - } - - /* Set end position to end of fraction part. */ - end_p = str_curr_p; - } - } - } - } - - if (str_curr_p < str_end_p) - { - current = *str_curr_p++; - } - - /* Check exponent. */ - if ((current == LIT_CHAR_LOWERCASE_E || current == LIT_CHAR_UPPERCASE_E) - && (has_whole_part || has_fraction_part) - && str_curr_p < str_end_p) - { - current = *str_curr_p++; - - /* Check sign of exponent. */ - if ((current == LIT_CHAR_PLUS || current == LIT_CHAR_MINUS) - && str_curr_p < str_end_p) - { - current = *str_curr_p++; - } - - if (lit_char_is_decimal_digit (current)) - { - /* Check digits of exponent part. */ - while (str_curr_p < str_end_p) - { - current = *str_curr_p++; - if (!lit_char_is_decimal_digit (current)) - { - str_curr_p--; - break; - } - } - - /* Set end position to end of exponent part. */ - end_p = str_curr_p; - } - } - - /* String did not contain a valid number. */ - if (start_p == end_p) - { - return ecma_make_nan_value (); - } - - /* 5. */ - ecma_number_t ret_num = ecma_utf8_string_to_number (start_p, (lit_utf8_size_t) (end_p - start_p)); - - if (sign) - { - ret_num *= ECMA_NUMBER_MINUS_ONE; - } - - return ecma_make_number_value (ret_num); -} /* ecma_builtin_global_object_parse_float */ - /** * The Global object's 'isNaN' routine * @@ -1198,15 +831,15 @@ ecma_builtin_global_dispatch_routine (uint16_t builtin_routine_id, /**< built-in if (builtin_routine_id == ECMA_GLOBAL_PARSE_INT) { - ret_value = ecma_builtin_global_object_parse_int (string_buff, - string_buff_size, - arguments_list_p[1]); + ret_value = ecma_number_parse_int (string_buff, + string_buff_size, + arguments_list_p[1]); } else { JERRY_ASSERT (builtin_routine_id == ECMA_GLOBAL_PARSE_FLOAT); - ret_value = ecma_builtin_global_object_parse_float (string_buff, - string_buff_size); + ret_value = ecma_number_parse_float (string_buff, + string_buff_size); } ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h index ab7a566f4..2d58eb1eb 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h @@ -257,15 +257,20 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROXY_UL, * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ ROUTINE (LIT_MAGIC_STRING_EVAL, ECMA_GLOBAL_EVAL, 1, 1) -ROUTINE (LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_GLOBAL_PARSE_FLOAT, 1, 1) ROUTINE (LIT_MAGIC_STRING_IS_NAN, ECMA_GLOBAL_IS_NAN, 1, 1) ROUTINE (LIT_MAGIC_STRING_IS_FINITE, ECMA_GLOBAL_IS_FINITE, 1, 1) ROUTINE (LIT_MAGIC_STRING_DECODE_URI, ECMA_GLOBAL_DECODE_URI, 1, 1) ROUTINE (LIT_MAGIC_STRING_DECODE_URI_COMPONENT, ECMA_GLOBAL_DECODE_URI_COMPONENT, 1, 1) ROUTINE (LIT_MAGIC_STRING_ENCODE_URI, ECMA_GLOBAL_ENCODE_URI, 1, 1) ROUTINE (LIT_MAGIC_STRING_ENCODE_URI_COMPONENT, ECMA_GLOBAL_ENCODE_URI_COMPONENT, 1, 1) -ROUTINE (LIT_MAGIC_STRING_PARSE_INT, ECMA_GLOBAL_PARSE_INT, 2, 2) +#if ENABLED (JERRY_ES2015) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_FLOAT, LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_INT, LIT_MAGIC_STRING_PARSE_INT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#else /* !ENABLED (JERRY_ES2015) */ +ROUTINE (LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_GLOBAL_PARSE_FLOAT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PARSE_INT, ECMA_GLOBAL_PARSE_INT, 2, 2) +#endif /* ENABLED (JERRY_ES2015) */ #if ENABLED (JERRY_BUILTIN_ANNEXB) ROUTINE (LIT_MAGIC_STRING_ESCAPE, ECMA_GLOBAL_ESCAPE, 1, 1) ROUTINE (LIT_MAGIC_STRING_UNESCAPE, ECMA_GLOBAL_UNESCAPE, 1, 1) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.c b/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.c index 07ea2ac96..bd73ec77d 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.c @@ -16,12 +16,29 @@ #include "ecma-builtins.h" #include "ecma-array-object.h" #include "ecma-gc.h" +#include "lit-char-helpers.h" #if ENABLED (JERRY_ES2015) #define ECMA_BUILTINS_INTERNAL #include "ecma-builtins-internal.h" +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_INTRINSIC_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1, + ECMA_INTRINSIC_PARSE_FLOAT, + ECMA_INTRINSIC_PARSE_INT, + ECMA_INTRINSIC_ARRAY_PROTOTYPE_VALUES +}; + #define BUILTIN_INC_HEADER_NAME "ecma-builtin-intrinsic.inc.h" #define BUILTIN_UNDERSCORED_ID intrinsic #include "ecma-builtin-internal-routines-template.inc.h" @@ -64,6 +81,59 @@ ecma_builtin_intrinsic_array_prototype_values (ecma_value_t this_value) /**< thi return ret_value; } /* ecma_builtin_intrinsic_array_prototype_values */ +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_intrinsic_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + ecma_length_t arguments_number) /**< length of arguments' list */ +{ + JERRY_UNUSED (arguments_number); + + ecma_value_t routine_arg_1 = arguments_list_p[0]; + ecma_value_t routine_arg_2 = arguments_list_p[1]; + + if (builtin_routine_id == ECMA_INTRINSIC_ARRAY_PROTOTYPE_VALUES) + { + return ecma_builtin_intrinsic_array_prototype_values (this_arg); + } + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + if (builtin_routine_id <= ECMA_INTRINSIC_PARSE_INT) + { + ecma_string_t *str_p = ecma_op_to_string (routine_arg_1); + + if (JERRY_UNLIKELY (str_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ECMA_STRING_TO_UTF8_STRING (str_p, string_buff, string_buff_size); + + if (builtin_routine_id == ECMA_INTRINSIC_PARSE_INT) + { + ret_value = ecma_number_parse_int (string_buff, + string_buff_size, + routine_arg_2); + } + else + { + JERRY_ASSERT (builtin_routine_id == ECMA_INTRINSIC_PARSE_FLOAT); + ret_value = ecma_number_parse_float (string_buff, + string_buff_size); + } + ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size); + ecma_deref_ecma_string (str_p); + } + + return ret_value; +} /* ecma_builtin_intrinsic_dispatch_routine */ + /** * @} * @} diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h index 4f7378f33..8fb9152d9 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h @@ -64,8 +64,10 @@ SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, /* ECMA-262 v6, 19.4.2.14 */ SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_UNSCOPABLES, LIT_MAGIC_STRING_UNSCOPABLES) - -ROUTINE (LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, ecma_builtin_intrinsic_array_prototype_values, 0, 0) - +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_INTRINSIC_PARSE_FLOAT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_PARSE_INT, ECMA_INTRINSIC_PARSE_INT, 2, 2) +ROUTINE (LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, ECMA_INTRINSIC_ARRAY_PROTOTYPE_VALUES, 0, 0) #endif /* ENABLED (JERRY_ES2015) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h index 8088655dc..111913559 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h @@ -89,5 +89,7 @@ ROUTINE (LIT_MAGIC_STRING_IS_FINITE, ecma_builtin_number_object_is_finite, 1, 1) ROUTINE (LIT_MAGIC_STRING_IS_NAN, ecma_builtin_number_object_is_nan, 1, 1) ROUTINE (LIT_MAGIC_STRING_IS_INTEGER, ecma_builtin_number_object_is_integer, 1, 1) ROUTINE (LIT_MAGIC_STRING_IS_SAFE_INTEGER, ecma_builtin_number_object_is_safe_integer, 1, 1) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_FLOAT, LIT_MAGIC_STRING_PARSE_FLOAT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +INTRINSIC_PROPERTY (LIT_MAGIC_STRING_PARSE_INT, LIT_MAGIC_STRING_PARSE_INT, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) #endif /* ENABLED (JERRY_ES2015) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index 777207b9d..fb5a527d8 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -542,7 +542,10 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_SEALED_UL, "isSealed") #if ENABLED (JERRY_ES2015) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ITERATOR, "iterator") #endif +#if ENABLED (JERRY_ES2015) \ +|| !( ENABLED (JERRY_ES2015)) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PARSE_INT, "parseInt") +#endif #if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_HOURS_UL, "setHours") #endif @@ -666,7 +669,10 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_DATE_UL, "getUTCDate") || ENABLED (JERRY_BUILTIN_REGEXP) && !( ENABLED (JERRY_ES2015)) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IGNORECASE_UL, "ignoreCase") #endif +#if ENABLED (JERRY_ES2015) \ +|| !( ENABLED (JERRY_ES2015)) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PARSE_FLOAT, "parseFloat") +#endif #if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_FLOAT_32_UL, "setFloat32") #endif diff --git a/tests/jerry/es2015/number-methods.js b/tests/jerry/es2015/number-methods.js new file mode 100644 index 000000000..5dfdd45cc --- /dev/null +++ b/tests/jerry/es2015/number-methods.js @@ -0,0 +1,22 @@ +// Copyright JS Foundation and other contributors, http://js.foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +assert (Number.parseInt ('18528769') === 18528769); +assert (Number.parseFloat ('1.2e3') === 1.2e3); +assert (parseInt ('18528769') === 18528769); +assert (parseFloat ('1.2e3') === 1.2e3); + +assert(Number.parseInt === parseInt); + +assert(Number.parseFloat === parseFloat);