From 74a5a149e4fcd554bfe9829c0e332cf72b8ae08b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20Lang=C3=B3?= Date: Mon, 13 Jul 2015 11:03:54 +0200 Subject: [PATCH 1/2] Follow up fix for Date.prototype.toString MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JerryScript-DCO-1.0-Signed-off-by: László Langó llango.u-szeged@partner.samsung.com --- .../ecma/builtin-objects/ecma-builtin-date-prototype.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp index 5cdafb4c22..9fa7644007 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp @@ -53,7 +53,9 @@ ecma_date_insert_leading_zeros (ecma_string_t **str_p, /**< input/output string JERRY_ASSERT (length >= 1); /* If the length is bigger than the number of digits in num, then insert leding zeros. */ - for (uint32_t i = length - 1; i > 0 && num < pow (10,i); i--) + uint32_t first_index = length - 1u; + ecma_number_t power_i = (ecma_number_t) pow (10, first_index); + for (uint32_t i = first_index; i > 0 && num < power_i; i--, power_i /= 10) { ecma_string_t *zero_str_p = ecma_new_ecma_string_from_uint32 (0); ecma_string_t *concat_p = ecma_concat_ecma_strings (zero_str_p, *str_p); From e1b9fb69eab164217004a2ac65150892503bbf8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3=20Lang=C3=B3?= Date: Fri, 10 Jul 2015 10:39:49 +0200 Subject: [PATCH 2/2] Implement Date.prototype.toDateString and Date.prototype.toTimeString MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JerryScript-DCO-1.0-Signed-off-by: László Langó llango.u-szeged@partner.samsung.com --- .../ecma-builtin-date-prototype.cpp | 101 +++++++++++++++++- tests/jerry/date-tostring.js | 47 +++++++- 2 files changed, 141 insertions(+), 7 deletions(-) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp index 9fa7644007..d8dae6569b 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp @@ -105,9 +105,10 @@ ecma_builtin_date_prototype_to_string (ecma_value_t this_arg) /**< this argument { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); - if (ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_DATE_UL) + 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 ("Incomplete Date type"); + ret_value = ecma_raise_type_error ("Incompatible type"); } else { @@ -176,7 +177,54 @@ ecma_builtin_date_prototype_to_string (ecma_value_t this_arg) /**< this argument static ecma_completion_value_t ecma_builtin_date_prototype_to_date_string (ecma_value_t this_arg) /**< this argument */ { - ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg); + 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_DATE_UL) + { + ret_value = ecma_raise_type_error ("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_value_prop_p; + 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); + + 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_normal_completion_value (ecma_make_string_value (magic_str_p)); + } + else + { + ecma_number_t day = ecma_date_date_from_time (*prim_value_num_p); + ecma_string_t *output_str_p = ecma_new_ecma_string_from_number (day); + ecma_date_insert_leading_zeros (&output_str_p, day, 2); + + /* + * Note: + * 'ecma_date_month_from_time' (ECMA 262 v5, 15.9.1.4) returns a number from 0 to 11, + * but we have to print the month from 1 to 12 for ISO 8601 standard (ECMA 262 v5, 15.9.1.15). + */ + ecma_number_t month = ecma_date_month_from_time (*prim_value_num_p) + 1; + ecma_date_insert_num_with_sep (&output_str_p, month, LIT_MAGIC_STRING_MINUS_CHAR, 2); + + ecma_number_t year = ecma_date_year_from_time (*prim_value_num_p); + ecma_date_insert_num_with_sep (&output_str_p, year, LIT_MAGIC_STRING_MINUS_CHAR, 4); + + ret_value = ecma_make_normal_completion_value (ecma_make_string_value (output_str_p)); + } + + ECMA_FINALIZE (obj_this); + } + + return ret_value; } /* ecma_builtin_date_prototype_to_date_string */ /** @@ -191,7 +239,52 @@ ecma_builtin_date_prototype_to_date_string (ecma_value_t this_arg) /**< this arg static ecma_completion_value_t ecma_builtin_date_prototype_to_time_string (ecma_value_t this_arg) /**< this argument */ { - ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg); + 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_DATE_UL) + { + ret_value = ecma_raise_type_error ("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_value_prop_p; + 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); + + 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_normal_completion_value (ecma_make_string_value (magic_str_p)); + } + else + { + ecma_number_t milliseconds = ecma_date_ms_from_time (*prim_value_num_p); + ecma_string_t *output_str_p = ecma_new_ecma_string_from_number (milliseconds); + ecma_date_insert_leading_zeros (&output_str_p, milliseconds, 3); + + ecma_number_t seconds = ecma_date_sec_from_time (*prim_value_num_p); + ecma_date_insert_num_with_sep (&output_str_p, seconds, LIT_MAGIC_STRING_DOT_CHAR, 2); + + ecma_number_t minutes = ecma_date_min_from_time (*prim_value_num_p); + ecma_date_insert_num_with_sep (&output_str_p, minutes, LIT_MAGIC_STRING_COLON_CHAR, 2); + + ecma_number_t hours = ecma_date_hour_from_time (*prim_value_num_p); + ecma_date_insert_num_with_sep (&output_str_p, hours, LIT_MAGIC_STRING_COLON_CHAR, 2); + + ret_value = ecma_make_normal_completion_value (ecma_make_string_value (output_str_p)); + } + + ECMA_FINALIZE (obj_this); + } + + return ret_value; } /* ecma_builtin_date_prototype_to_time_string */ /** diff --git a/tests/jerry/date-tostring.js b/tests/jerry/date-tostring.js index 8085d32c3f..ce280842eb 100644 --- a/tests/jerry/date-tostring.js +++ b/tests/jerry/date-tostring.js @@ -13,6 +13,47 @@ // See the License for the specific language governing permissions and // limitations under the License. -assert (new Date(NaN) == "Invalid Date"); -assert (new Date("2015-02-13") == "2015-02-13T00:00:00.000"); -assert (new Date("2015-07-08T11:29:05.023") == "2015-07-08T11:29:05.023"); +assert (new Date (NaN) == "Invalid Date"); +assert (new Date ("2015-02-13") == "2015-02-13T00:00:00.000"); +assert (new Date ("2015-07-08T11:29:05.023") == "2015-07-08T11:29:05.023"); + +try +{ + Date.prototype.toString.call(-1); + assert (false); +} +catch (e) +{ + assert (e instanceof TypeError); + assert (e.message === "Incompatible type"); +} + +assert (new Date (NaN).toDateString () == "Invalid Date"); +assert (new Date ("2015-02-13").toDateString () == "2015-02-13"); +assert (new Date ("2015-07-08T11:29:05.023").toDateString () == "2015-07-08"); + +try +{ + Date.prototype.toDateString.call(-1); + assert (false); +} +catch (e) +{ + assert (e instanceof TypeError); + assert (e.message === "Incompatible type"); +} + +assert (new Date (NaN).toTimeString () == "Invalid Date"); +assert (new Date ("2015-02-13").toTimeString () == "00:00:00.000"); +assert (new Date ("2015-07-08T11:29:05.023").toTimeString () == "11:29:05.023"); + +try +{ + Date.prototype.toTimeString.call(-1); + assert (false); +} +catch (e) +{ + assert (e instanceof TypeError); + assert (e.message === "Incompatible type"); +}