From 2191ec591f2c3cee00bf3c3e71adb17e970a0bc1 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 24 Aug 2020 09:26:28 -0400 Subject: [PATCH] LibJS: Make Date's tuple constructor correctly handle out-of-range arguments Milliseconds need extra handling, but everything else just works now that mktime() handles this case. --- Libraries/LibJS/Runtime/DateConstructor.cpp | 7 ++++++ Libraries/LibJS/Tests/builtins/Date/Date.js | 26 ++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Libraries/LibJS/Runtime/DateConstructor.cpp b/Libraries/LibJS/Runtime/DateConstructor.cpp index 583230c1b1..1f614ef626 100644 --- a/Libraries/LibJS/Runtime/DateConstructor.cpp +++ b/Libraries/LibJS/Runtime/DateConstructor.cpp @@ -195,6 +195,13 @@ Value DateConstructor::construct(Interpreter& interpreter, Function&) int seconds = arg_or(5, 0); int milliseconds = arg_or(6, 0); + seconds += milliseconds / 1000; + milliseconds %= 1000; + if (milliseconds < 0) { + seconds -= 1; + milliseconds += 1000; + } + if (year >= 0 && year <= 99) year += 1900; int month = month_index + 1; diff --git a/Libraries/LibJS/Tests/builtins/Date/Date.js b/Libraries/LibJS/Tests/builtins/Date/Date.js index 80551e638b..e232b79137 100644 --- a/Libraries/LibJS/Tests/builtins/Date/Date.js +++ b/Libraries/LibJS/Tests/builtins/Date/Date.js @@ -30,11 +30,12 @@ test("tuple constructor", () => { // The tuple constructor takes a date in local time. expect(new Date(2019, 11).getFullYear()).toBe(2019); expect(new Date(2019, 11).getMonth()).toBe(11); - expect(new Date(2019, 11).getDate()).toBe(1); // getDay() returns day of week, getDate() returnsn day in month + expect(new Date(2019, 11).getDate()).toBe(1); // getDay() returns day of week, getDate() returns day in month expect(new Date(2019, 11).getHours()).toBe(0); expect(new Date(2019, 11).getMinutes()).toBe(0); expect(new Date(2019, 11).getSeconds()).toBe(0); expect(new Date(2019, 11).getMilliseconds()).toBe(0); + expect(new Date(2019, 11).getDay()).toBe(0); let date = new Date(2019, 11, 15, 9, 16, 14, 123); // Note: Month is 0-based. expect(date.getFullYear()).toBe(2019); @@ -44,6 +45,7 @@ test("tuple constructor", () => { expect(date.getMinutes()).toBe(16); expect(date.getSeconds()).toBe(14); expect(date.getMilliseconds()).toBe(123); + expect(date.getDay()).toBe(0); // getTime() returns a time stamp in UTC, but we can at least check it's in the right interval, which will be true independent of the local timezone if the range is big enough. let timestamp_lower_bound = 1575072000000; // 2019-12-01T00:00:00Z @@ -51,3 +53,25 @@ test("tuple constructor", () => { expect(date.getTime()).toBeGreaterThan(timestamp_lower_bound); expect(date.getTime()).toBeLessThan(timestamp_upper_bound); }); + +test("tuple constructor overflow", () => { + let date = new Date(2019, 13, 33, 30, 70, 80, 2345); + expect(date.getFullYear()).toBe(2020); + expect(date.getMonth()).toBe(2); + expect(date.getDate()).toBe(5); + expect(date.getHours()).toBe(7); + expect(date.getMinutes()).toBe(11); + expect(date.getSeconds()).toBe(22); + expect(date.getMilliseconds()).toBe(345); + expect(date.getDay()).toBe(4); + + let date = new Date(2019, -13, -33, -30, -70, -80, -2345); + expect(date.getFullYear()).toBe(2017); + expect(date.getMonth()).toBe(9); + expect(date.getDate()).toBe(26); + expect(date.getHours()).toBe(16); + expect(date.getMinutes()).toBe(48); + expect(date.getSeconds()).toBe(37); + expect(date.getMilliseconds()).toBe(655); + expect(date.getDay()).toBe(4); +});