-
Notifications
You must be signed in to change notification settings - Fork 688
Closed
Labels
bugUndesired behaviourUndesired behaviourecma builtinsRelated to ECMA built-in routinesRelated to ECMA built-in routines
Description
The return value of new Date(2016, 9, day) (or any other leap year) is an invalid date object (console.log(…) --> "Invalid Date") since the binary search in ecma_date_make_day() is erroneous.
We do have a working fix, covered by a brute-force unit-test that creates dates in the range from 1950...2050 (that previously failed for every day that follow the aforementioned pattern), but due to time constraints, I won't be able to put up a PR before mid next week.
If for some reason somebody needs a fix before, here's are possible fix:
@@ -781,13 +781,16 @@ ecma_date_make_day (ecma_number_t year, /**< year value */
delta = delta / 2;
}
- if (ecma_date_month_from_time (time + step) < mn)
+ time += step * ECMA_DATE_MS_PER_DAY;
+
+ /* Make sure time represents a day in the previous month */
+ if (ecma_date_month_from_time (time) >= mn)
{
- time += step * ECMA_DATE_MS_PER_DAY;
+ time -= ECMA_DATE_MS_PER_DAY * 31;
}
- /* Get the month's first day */
- while (ecma_date_month_from_time (time) < mn)
+ /* Get the month's first day, don't check for <= as the month wraps */
+ while (ecma_date_month_from_time (time) != mn)
{
time += ECMA_DATE_MS_PER_DAY;
}
Also, these are the tests, we verified this fix against:
+void test_rocky_api_util__ecma_date_make_day(void) {
+ cl_assert_equal_d(16861, ecma_date_make_day(2016, 2, 1)); // JerryScript's unit-test
+ cl_assert_equal_d(-25294, ecma_date_make_day(1900, 9, 1)); // not a leap year!
+ cl_assert_equal_d(17075, ecma_date_make_day(2016, 8, 31)); // Sept-31 == Oct-01
+ cl_assert_equal_d(17075, ecma_date_make_day(2016, 9, 1)); // Oct-01
+ cl_assert_equal_d(17045, ecma_date_make_day(2016, 8, 1)); // Sept-01
+}
+
+void test_rocky_api_util__ecma_date_make_day_list(void) {
+ int fail_count = 0;
+ for(int y = 1950; y < 2050; y++) {
+ for(int m = 0; m < 12; m++) {
+ for (int d = 1; d < 32; d++) {
+ const ecma_number_t result = ecma_date_make_day(y, m, d);
+ if (isnan(result)) {
+ printf("failed for %04d-%02d-%02d\n", y, m, d);
+ fail_count++;
+ } else {
+// printf("passed for %04d-%02d-%02d: %d\n", y, m, d, (int)result);
+ }
+ }
+ }
+ }
+ cl_assert_equal_i(0, fail_count);
+}
Metadata
Metadata
Assignees
Labels
bugUndesired behaviourUndesired behaviourecma builtinsRelated to ECMA built-in routinesRelated to ECMA built-in routines