diff --git a/Libraries/LibWeb/HTML/Dates.cpp b/Libraries/LibWeb/HTML/Dates.cpp index 0e3870515f0..574c14f9246 100644 --- a/Libraries/LibWeb/HTML/Dates.cpp +++ b/Libraries/LibWeb/HTML/Dates.cpp @@ -414,13 +414,16 @@ static Optional parse_a_time_component(GenericLexer& input) if (!maybe_hour.has_value()) return {}; auto hour = maybe_hour.value(); + // 2. If hour is not a number in the range 0 ≤ hour ≤ 23, then fail. if (hour < 0 || hour > 23) return {}; + // 3. If position is beyond the end of input or if the character at position is not a U+003A COLON character, then // fail. Otherwise, move position forwards one character. if (!input.consume_specific(':')) return {}; + // 4. Collect a sequence of code points that are ASCII digits from input given position. If the collected sequence // is not exactly two characters long, then fail. Otherwise, interpret the resulting sequence as a base-ten integer. // Let that number be the minute. @@ -431,44 +434,50 @@ static Optional parse_a_time_component(GenericLexer& input) if (!maybe_minute.has_value()) return {}; auto minute = maybe_minute.value(); + // 5. If minute is not a number in the range 0 ≤ minute ≤ 59, then fail. if (minute < 0 || hour > 59) return {}; + // 6. Let second be 0. i32 second = 0; + // 7. If position is not beyond the end of input and the character at position is U+003A (:), then: - if (!input.consume_specific(':')) - return {}; - // 7.1. Advance position to the next character in input. - // 7.2. If position is beyond the end of input, or at the last character in input, or if the next two characters in - // input starting at position are not both ASCII digits, then fail. - if (input.is_eof() || input.tell_remaining() == 1 || (!is_ascii_digit(input.peek()) && !is_ascii_digit(input.peek(1)))) - return {}; - // 7.3. Collect a sequence of code points that are either ASCII digits or U+002E FULL STOP characters from input - // given position. - auto second_string = input.consume_while([](auto ch) { return is_ascii_digit(ch) || ch == '.'; }); - // If the collected sequence is three characters long, or if it is longer than three characters long and the third - // character is not a U+002E FULL STOP character, or if it has more than one U+002E FULL STOP character, then fail. - if (second_string.length() == 3) - return {}; - if (second_string.length() > 3 && second_string[2] != '.') - return {}; - if (second_string.find_all("."sv).size() > 1) - return {}; - // Otherwise, interpret the resulting sequence as a base-ten number (possibly with a fractional part). Set second - // to that number. - // NB: The spec doesn't state requirements for what we must do with the fractional part of the second(s) string. - // The spec neither requires that we separately preserve it nor requires that we completely discard it. If we - // did have any reason at all to preserve it, we could parse the string into a float here. But there doesn't - // seem to be any point in doing that, because there’s nothing in the corresponding calling algorithm(s) in the - // spec that takes a milliseconds field and does anything with it anyway. - auto maybe_second = second_string.to_number(); - if (!maybe_second.has_value()) - return {}; - second = maybe_second.value(); - // 7.4. If second is not a number in the range 0 ≤ second < 60, then fail. - if (second < 0 || second > 60) - return {}; + if (input.consume_specific(':')) { + // 1. Advance position to the next character in input. + // 2. If position is beyond the end of input, or at the last character in input, or if the next two characters in + // input starting at position are not both ASCII digits, then fail. + if (input.is_eof() || input.tell_remaining() == 1 || (!is_ascii_digit(input.peek()) && !is_ascii_digit(input.peek(1)))) + return {}; + + // 3. Collect a sequence of code points that are either ASCII digits or U+002E FULL STOP characters from input + // given position. + auto second_string = input.consume_while([](auto ch) { return is_ascii_digit(ch) || ch == '.'; }); + // If the collected sequence is three characters long, or if it is longer than three characters long and the third + // character is not a U+002E FULL STOP character, or if it has more than one U+002E FULL STOP character, then fail. + if (second_string.length() == 3) + return {}; + if (second_string.length() > 3 && second_string[2] != '.') + return {}; + if (second_string.find_all("."sv).size() > 1) + return {}; + // Otherwise, interpret the resulting sequence as a base-ten number (possibly with a fractional part). Set second + // to that number. + // NB: The spec doesn't state requirements for what we must do with the fractional part of the second(s) string. + // The spec neither requires that we separately preserve it nor requires that we completely discard it. If we + // did have any reason at all to preserve it, we could parse the string into a float here. But there doesn't + // seem to be any point in doing that, because there’s nothing in the corresponding calling algorithm(s) in the + // spec that takes a milliseconds field and does anything with it anyway. + auto maybe_second = second_string.to_number(); + if (!maybe_second.has_value()) + return {}; + second = maybe_second.value(); + + // 4. If second is not a number in the range 0 ≤ second < 60, then fail. + if (second < 0 || second > 60) + return {}; + } + // 8. Return hour, minute, and second. return HourMinuteSecond { hour, minute, second }; } diff --git a/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-valueAsNumber.txt b/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-valueAsNumber.txt index ae462d52f55..77921fc7266 100644 --- a/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-valueAsNumber.txt +++ b/Tests/LibWeb/Text/expected/HTML/HTMLInputElement-valueAsNumber.txt @@ -35,7 +35,7 @@ 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: NaN +datetime-local did not throw: 0 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/input-valueasnumber.txt b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasnumber.txt index edde99ed0dc..e85265e8ccd 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasnumber.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/forms/the-input-element/input-valueasnumber.txt @@ -2,8 +2,8 @@ Harness status: OK Found 60 tests -56 Pass -4 Fail +58 Pass +2 Fail Pass valueAsNumber getter on type date (actual value: , expected valueAsNumber: NaN) Pass valueAsNumber getter on type date (actual value: 0000-12-10, expected valueAsNumber: NaN) Pass valueAsNumber getter on type date (actual value: 2019-00-12, expected valueAsNumber: NaN) @@ -41,8 +41,8 @@ Pass valueAsNumber setter on type time (actual valueAsNumber: 0, expected value: Pass valueAsNumber setter on type time (actual valueAsNumber: 43200000, expected value: 12:00) Pass valueAsNumber setter on type time (actual valueAsNumber: 86340000, expected value: 23:59) Pass valueAsNumber getter on type datetime-local (actual value: , expected valueAsNumber: NaN) -Fail valueAsNumber getter on type datetime-local (actual value: 2019-12-10T00:00, expected valueAsNumber: 1575936000000) -Fail valueAsNumber getter on type datetime-local (actual value: 2019-12-10T12:00, expected valueAsNumber: 1575979200000) +Pass valueAsNumber getter on type datetime-local (actual value: 2019-12-10T00:00, expected valueAsNumber: 1575936000000) +Pass valueAsNumber getter on type datetime-local (actual value: 2019-12-10T12:00, expected valueAsNumber: 1575979200000) Pass valueAsNumber setter on type datetime-local (actual valueAsNumber: 1575936000000, expected value: 2019-12-10T00:00) Pass valueAsNumber setter on type datetime-local (actual valueAsNumber: 1575979200000, expected value: 2019-12-10T12:00) Pass valueAsNumber getter on type number (actual value: , expected valueAsNumber: NaN)