From 32c74fff22b3d82f2cfaa3193f3aff19e8842d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Csaba=20Osztrogon=C3=A1c?= Date: Wed, 2 Oct 2019 10:26:20 +0200 Subject: [PATCH] Fix Date.prototype.toString() and toISOString() (#3175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The implementation was incorrect for negative years and years bigger than 9999. -1 was 000/ because the negative (year%10) was added to '0' character, years bigger than 9999 was truncated to 4 digits. ES5.1 15.9.1.15.1 defines extended years format with 6 digits, but toString() and toISOString() sections don't mention anything about extended years. ES6 20.3.4.3 already clarifies that Date.prototype.toISOString() should use this extended year format if it is necessary. Changes: - Date.prototype.toString() uses 4 digits for years by default, 5 or 6 if it is necessary and put '-' sign for negative years, no sign for positive years. Date.prototype.toString() was implementation dependent until ES9, but ES9 already specify exactly this format. - Date.prototype.toISOString() uses fixed 4 digits for years 0 - 9999, otherwise sign + 6 digits (extended years). - Tests added for corner cases. JerryScript-DCO-1.0-Signed-off-by: Csaba Osztrogonác oszi@inf.u-szeged.hu --- .../ecma-builtin-helpers-date.c | 42 +++++++++++++-- tests/jerry/date-toisostring.js | 54 +++++++++++++++++++ tests/jerry/date-tostring.js | 26 +++++++++ 3 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 tests/jerry/date-toisostring.js diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c index 105b1556c..366180832 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c @@ -587,7 +587,7 @@ ecma_date_to_string_format (ecma_number_t datetime_number, /**< datetime */ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - const uint32_t date_buffer_length = 34; + const uint32_t date_buffer_length = 37; JERRY_VLA (lit_utf8_byte_t, date_buffer, date_buffer_length); lit_utf8_byte_t *dest_p = date_buffer; @@ -611,7 +611,32 @@ ecma_date_to_string_format (ecma_number_t datetime_number, /**< datetime */ case LIT_CHAR_UPPERCASE_Y: /* Year. */ { number = (int32_t) ecma_date_year_from_time (datetime_number); - number_length = 4; + + if (number >= 100000 || number <= -100000) + { + number_length = 6; + } + else if (number >= 10000 || number <= -10000) + { + number_length = 5; + } + else + { + number_length = 4; + } + break; + } + case LIT_CHAR_LOWERCASE_Y: /* ISO Year: -000001, 0000, 0001, 9999, +012345 */ + { + number = (int32_t) ecma_date_year_from_time (datetime_number); + if (0 <= number && number <= 9999) + { + number_length = 4; + } + else + { + number_length = 6; + } break; } case LIT_CHAR_UPPERCASE_M: /* Month. */ @@ -723,6 +748,17 @@ ecma_date_to_string_format (ecma_number_t datetime_number, /**< datetime */ /* Print right aligned number values. */ JERRY_ASSERT (number_length > 0); + if (number < 0) + { + number = -number; + *dest_p++ = '-'; + } + else if (*(format_p - 1) == LIT_CHAR_LOWERCASE_Y && number_length == 6) + { + /* positive sign is compulsory for extended years */ + *dest_p++ = '+'; + } + dest_p += number_length; lit_utf8_byte_t *buffer_p = dest_p; @@ -785,7 +821,7 @@ ecma_date_value_to_utc_string (ecma_number_t datetime_number) /**< datetime */ ecma_value_t ecma_date_value_to_iso_string (ecma_number_t datetime_number) /**