From a9d6978e4b379f21e1f90843b33c00435f144c64 Mon Sep 17 00:00:00 2001 From: Yanhui Shen Date: Tue, 20 Sep 2016 19:13:50 +0800 Subject: [PATCH] Fixing ecma_builtin_number_prototype_helper_round. (#1362) "ecma_builtin_number_prototype_helper_round" is used by following functions: * ecma_builtin_number_prototype_object_to_fixed * ecma_builtin_number_prototype_object_to_exponential * ecma_builtin_number_prototype_object_to_precision The current implementation does not support currying numbers and will produce illegal digit for some test cases. For example, the result of "0.95.toFixed(1)" is "0.:". This patch fixs the issue, however the implementation of "toFixed" is still problematic, at least not meet section 15.7.4.5 8.a of the specification. The related test case is: * assert((0.995).toFixed(2) === "0.99"); * assert((9.995).toFixed(2) === "9.99"); Reference: * http://www.ecma-international.org/ecma-262/5.1/#sec-15.7.4.5 JerryScript-DCO-1.0-Signed-off-by: Yanhui Shen shen.elf@gmail.com --- .../ecma-builtin-number-prototype.c | 35 ++++++++++++++++--- tests/jerry/number-prototype-to-fixed.js | 4 +++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.c index 2c943703c..c90ee65b6 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.c @@ -135,7 +135,8 @@ static inline lit_utf8_size_t __attr_always_inline___ ecma_builtin_number_prototype_helper_round (lit_utf8_byte_t *digits_p, /**< [in,out] number as a string in decimal * form */ lit_utf8_size_t num_digits, /**< length of the string representation */ - int32_t round_num) /**< number of digits to keep */ + int32_t round_num, /**< number of digits to keep */ + int32_t *exponent_p) /**< [in, out] decimal exponent */ { if (round_num < 1) { @@ -149,8 +150,29 @@ ecma_builtin_number_prototype_helper_round (lit_utf8_byte_t *digits_p, /**< [in, if (digits_p[round_num] >= '5') { - digits_p[round_num - 1]++; + digits_p[round_num] = '0'; + + int i = 1; + + /* Handle curry number. */ + for (; i < (int) num_digits; i++) + { + if (++digits_p[round_num - i] <= '9') + { + break; + } + digits_p[round_num - i] = '0'; + } + + /* Prepend highest digit */ + if (i >= (int) num_digits) + { + memmove (digits_p + 1, digits_p, num_digits); + digits_p[0] = '1'; + *exponent_p += 1; + } } + return (lit_utf8_size_t) round_num; } /* ecma_builtin_number_prototype_helper_round */ @@ -535,7 +557,10 @@ ecma_builtin_number_prototype_object_to_fixed (ecma_value_t this_arg, /**< this /* 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); + num_digits = ecma_builtin_number_prototype_helper_round (digits, + num_digits, + exponent + frac_digits, + &exponent); /* Buffer that is used to construct the string. */ int buffer_size = (exponent > 0) ? exponent + frac_digits + 2 : frac_digits + 3; @@ -670,7 +695,7 @@ ecma_builtin_number_prototype_object_to_exponential (ecma_value_t this_arg, /**< frac_digits = ecma_number_to_int32 (arg_num); } - num_digits = ecma_builtin_number_prototype_helper_round (digits, num_digits, frac_digits + 1); + num_digits = ecma_builtin_number_prototype_helper_round (digits, num_digits, frac_digits + 1, &exponent); /* frac_digits + 2 characters for number, 5 characters for exponent, 1 for \0. */ int buffer_size = frac_digits + 2 + 5 + 1; @@ -814,7 +839,7 @@ ecma_builtin_number_prototype_object_to_precision (ecma_value_t this_arg, /**< t int32_t precision = ecma_number_to_int32 (arg_num); - num_digits = ecma_builtin_number_prototype_helper_round (digits, num_digits, precision); + num_digits = ecma_builtin_number_prototype_helper_round (digits, num_digits, precision, &exponent); int buffer_size; if (exponent < -5 || exponent > precision) diff --git a/tests/jerry/number-prototype-to-fixed.js b/tests/jerry/number-prototype-to-fixed.js index a983aa20b..8b6f26a81 100644 --- a/tests/jerry/number-prototype-to-fixed.js +++ b/tests/jerry/number-prototype-to-fixed.js @@ -37,6 +37,10 @@ assert((-0.0).toFixed(1) === "-0.0"); assert((123456789012345678901.0).toFixed(20) === "123456789012345680000.00000000000000000000"); assert((123.56).toFixed(NaN) === "124"); assert((123.56).toFixed(-0.9) === "124"); +assert((0.095).toFixed(2) === "0.10"); +//assert((0.995).toFixed(2) === "0.99"); +//assert((9.995).toFixed(2) === "9.99"); +assert((99.995).toFixed(2) === "100.00"); try { Number.prototype.toExponential.call(new Object());