From ec807d40dd1981343ee23a714b3e3ab70706ca11 Mon Sep 17 00:00:00 2001 From: Glenn Skrzypczak Date: Mon, 11 Aug 2025 08:03:32 +0200 Subject: [PATCH] LibWeb/HTML: Correctly convert number to time/local datetime string This fixes a bug where non-zero milliseconds were previously not included if the second component was zero. --- Libraries/LibWeb/HTML/HTMLInputElement.cpp | 15 ++++++--------- .../HTML/HTMLInputElement-valueAsNumber.txt | 4 ++-- .../semantics/forms/the-input-element/time.txt | 5 ++--- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 7d48c5f0878..11fbd84ca48 100644 --- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -2422,11 +2422,10 @@ static Utf16String convert_number_to_time_string(double input) // string that represents the time that is input milliseconds after midnight on a day with no time changes. auto seconds = JS::sec_from_time(input); auto milliseconds = JS::ms_from_time(input); - if (seconds > 0) { - if (milliseconds > 0) - return Utf16String::formatted("{:02d}:{:02d}:{:02d}.{:3d}", JS::hour_from_time(input), JS::min_from_time(input), seconds, milliseconds); + if (milliseconds > 0) + return Utf16String::formatted("{:02d}:{:02d}:{:02d}.{:03d}", JS::hour_from_time(input), JS::min_from_time(input), seconds, milliseconds); + if (seconds > 0) return Utf16String::formatted("{:02d}:{:02d}:{:02d}", JS::hour_from_time(input), JS::min_from_time(input), seconds); - } return Utf16String::formatted("{:02d}:{:02d}", JS::hour_from_time(input), JS::min_from_time(input)); } @@ -2444,12 +2443,10 @@ static Utf16String convert_number_to_local_date_and_time_string(double input) auto seconds = JS::sec_from_time(input); auto milliseconds = JS::ms_from_time(input); - if (seconds > 0) { - if (milliseconds > 0) - return Utf16String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}.{:03d}", year, month, day, hour, minutes, seconds, milliseconds); + if (milliseconds > 0) + return Utf16String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}.{:03d}", year, month, day, hour, minutes, seconds, milliseconds).trim("0"sv, TrimMode::Right); + if (seconds > 0) return Utf16String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}", year, month, day, hour, minutes, seconds); - } - return Utf16String::formatted("{:04d}-{:02d}-{:02d}T{:02d}:{:02d}", year, month, day, hour, minutes); } diff --git a/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-valueAsNumber.txt b/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-valueAsNumber.txt index 77921fc7266..df12e4dbdf7 100644 --- a/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-valueAsNumber.txt +++ b/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-valueAsNumber.txt @@ -34,8 +34,8 @@ password threw exception: InvalidStateError: valueAsNumber: Invalid input type u date did not throw: 0 month did not throw: 100 week did not throw: 345600000 -time did not throw: 0 -datetime-local did not throw: 0 +time did not throw: 100 +datetime-local did not throw: 100 color threw exception: InvalidStateError: valueAsNumber: Invalid input type used checkbox threw exception: InvalidStateError: valueAsNumber: Invalid input type used radio threw exception: InvalidStateError: valueAsNumber: Invalid input type used diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/time.txt b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/time.txt index 61bc6ad8281..8065a7f4ada 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/time.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/time.txt @@ -2,8 +2,7 @@ Harness status: OK Found 32 tests -31 Pass -1 Fail +32 Pass Pass time element of default time value Pass step attribute on default value check Pass max attribute on default value check @@ -26,7 +25,7 @@ Pass stepUp on step value hour Pass stepDown on step value hour Pass stepUp on step value second Pass stepDown on step value second -Fail stepUp on step value with fractional seconds +Pass stepUp on step value with fractional seconds Pass stepDown on step value with fractional seconds Pass stepUp argument 2 times Pass stepDown argument 2 times