瀏覽代碼

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.
Nico Weber 5 年之前
父節點
當前提交
2191ec591f
共有 2 個文件被更改,包括 32 次插入1 次删除
  1. 7 0
      Libraries/LibJS/Runtime/DateConstructor.cpp
  2. 25 1
      Libraries/LibJS/Tests/builtins/Date/Date.js

+ 7 - 0
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;

+ 25 - 1
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);
+});