Title: [286869] trunk
Revision
286869
Author
cdu...@apple.com
Date
2021-12-10 12:37:40 -0800 (Fri, 10 Dec 2021)

Log Message

Improve <type="datetime-local"> value parsing and sanitization
https://bugs.webkit.org/show_bug.cgi?id=234039

Reviewed by Darin Adler.

Source/WebCore:

Improve <type="datetime-local"> value parsing and sanitization.

Test: fast/forms/datetimelocal/datetime-local-value-sanitization.html

* html/BaseDateAndTimeInputType.h:
* html/DateTimeLocalInputType.cpp:
(WebCore::DateTimeLocalInputType::sanitizeValue const):
Implement value sanitization for <type="datetime-local"> so that:
- if the input uses a space as date / time separator, the sanitized value will use a 'T' instead.
- The output will use the shortest possible string, omitting seconds or milliseconds when 0, as per
  https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-normalised-local-date-and-time-string

* html/DateTimeLocalInputType.h:
* platform/DateComponents.cpp:
(WebCore::DateComponents::parseTime):
Fix bug where we would allow more than 3 digits for the millisecond part of the time (we
would silently ignore follow-up digits instead of failing parsing). This is as per:
- https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-time-string
This was covered by one of the subtests in imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/datetime-local.html

(WebCore::isDateTimeLocalSeparator):
(WebCore::DateComponents::parseDateTimeLocal):
Allow using a space as date / time separator in <type="datetime-local">, instead of simply allowing a 'T'.
This would align our behavior with Gecko and the specification:
- https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string
Note that Blink still seems to only allow 'T' as separator.

(WebCore::DateComponents::toStringForTime const):
The output will use the shortest possible string, omitting seconds or milliseconds when 0, as per
https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-normalised-local-date-and-time-string

LayoutTests:

* fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal-expected.txt:
* fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal.html:
* fast/forms/datetimelocal/input-valueasnumber-datetimelocal-expected.txt:
* fast/forms/datetimelocal/input-valueasnumber-datetimelocal.html:
Update a couple of existing tests to reflect behavior change.

* fast/forms/datetimelocal/datetime-local-value-sanitization-expected.txt: Added.
* fast/forms/datetimelocal/datetime-local-value-sanitization.html: Added.
Improve test coverage for datetime-local value sanitization.

* platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt:
* platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/datetime-local-expected.txt:
* platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/time-2-expected.txt:
Rebaseline WPT tests now that more checks are passing.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (286868 => 286869)


--- trunk/LayoutTests/ChangeLog	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/ChangeLog	2021-12-10 20:37:40 UTC (rev 286869)
@@ -1,3 +1,25 @@
+2021-12-10  Chris Dumez  <cdu...@apple.com>
+
+        Improve <type="datetime-local"> value parsing and sanitization
+        https://bugs.webkit.org/show_bug.cgi?id=234039
+
+        Reviewed by Darin Adler.
+
+        * fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal-expected.txt:
+        * fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal.html:
+        * fast/forms/datetimelocal/input-valueasnumber-datetimelocal-expected.txt:
+        * fast/forms/datetimelocal/input-valueasnumber-datetimelocal.html:
+        Update a couple of existing tests to reflect behavior change.
+
+        * fast/forms/datetimelocal/datetime-local-value-sanitization-expected.txt: Added.
+        * fast/forms/datetimelocal/datetime-local-value-sanitization.html: Added.
+        Improve test coverage for datetime-local value sanitization.
+
+        * platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt:
+        * platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/datetime-local-expected.txt:
+        * platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/time-2-expected.txt:
+        Rebaseline WPT tests now that more checks are passing.
+
 2021-12-10  Gabriel Nava Marino  <gnavamar...@apple.com>
 
         nullptr deref in ComputeFloatOffsetForLineLayoutAdapter<FloatingObject::FloatLeft>::updateOffsetIfNeeded

Modified: trunk/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal-expected.txt (286868 => 286869)


--- trunk/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal-expected.txt	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -9,17 +9,17 @@
 PASS "2009-09-07T16:49:31.1" is a correct valid datetime-local string.
 PASS "2009-09-07T16:49:31.12" is a correct valid datetime-local string.
 PASS "2009-09-07T16:49:31.123" is a correct valid datetime-local string.
-PASS "2009-09-07T16:49:31.1234567890" is a correct valid datetime-local string.
 PASS "275760-09-13T00:00:00.000" is a correct valid datetime-local string.
 PASS "0001-01-01T00:00:00.000" is a correct valid datetime-local string.
+PASS "2009-09-07 16:49" is a correct valid datetime-local string.
 PASS " 2009-09-07T16:49 " is an invalid datetime-local string and was sanitized.
 PASS "2009-09-07t16:49" is an invalid datetime-local string and was sanitized.
-PASS "2009-09-07 16:49" is an invalid datetime-local string and was sanitized.
 PASS "2009/09/07T16:49" is an invalid datetime-local string and was sanitized.
 PASS "a" is an invalid datetime-local string and was sanitized.
 PASS "-1-09-07T16:49" is an invalid datetime-local string and was sanitized.
 PASS "0000-12-31T23:59:59.999" is an invalid datetime-local string and was sanitized.
 PASS "275760-09-13T00:00:00.001" is an invalid datetime-local string and was sanitized.
+PASS "2009-09-07T16:49:31.1234567890" is an invalid datetime-local string and was sanitized.
 PASS "invalid" is an invalid datetime-local string and was sanitized while disabled.
 PASS successfullyParsed is true
 

Modified: trunk/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal.html (286868 => 286869)


--- trunk/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal.html	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/fast/forms/datetimelocal/ValidityState-typeMismatch-datetimelocal.html	2021-12-10 20:37:40 UTC (rev 286869)
@@ -45,19 +45,19 @@
 shouldBeValid('2009-09-07T16:49:31.1');
 shouldBeValid('2009-09-07T16:49:31.12');
 shouldBeValid('2009-09-07T16:49:31.123');
-shouldBeValid('2009-09-07T16:49:31.1234567890');
 shouldBeValid('275760-09-13T00:00:00.000');
 shouldBeValid('0001-01-01T00:00:00.000');
+shouldBeValid('2009-09-07 16:49');
 
 // Invalid values
 shouldBeInvalid(' 2009-09-07T16:49 ');
 shouldBeInvalid('2009-09-07t16:49');
-shouldBeInvalid('2009-09-07 16:49');
 shouldBeInvalid('2009/09/07T16:49');
 shouldBeInvalid('a');
 shouldBeInvalid('-1-09-07T16:49');
 shouldBeInvalid('0000-12-31T23:59:59.999');
 shouldBeInvalid('275760-09-13T00:00:00.001');
+shouldBeInvalid('2009-09-07T16:49:31.1234567890');
 
 // Disabled
 shouldBeInvalid('invalid', true);

Added: trunk/LayoutTests/fast/forms/datetimelocal/datetime-local-value-sanitization-expected.txt (0 => 286869)


--- trunk/LayoutTests/fast/forms/datetimelocal/datetime-local-value-sanitization-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/datetimelocal/datetime-local-value-sanitization-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -0,0 +1,19 @@
+Tests the sanitization of the value of  elements of type datetime-local.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS input.value is "2000-01-01T12:30:00.5"
+PASS input.value is "2000-01-01T12:30:00.6"
+PASS input.value is "2000-01-01T12:30:00.7"
+PASS input.value is "2000-01-01T12:30:00.04"
+PASS input.value is "2000-01-01T12:30:00.003"
+PASS input.value is ""
+PASS input.value is "2000-01-01T12:30"
+PASS input.value is "2000-01-01T12:30"
+PASS input.value is "2000-01-01T12:30:01"
+PASS input.value is "2000-01-01T12:30:10"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/forms/datetimelocal/datetime-local-value-sanitization.html (0 => 286869)


--- trunk/LayoutTests/fast/forms/datetimelocal/datetime-local-value-sanitization.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/datetimelocal/datetime-local-value-sanitization.html	2021-12-10 20:37:40 UTC (rev 286869)
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description("Tests the sanitization of the value of <input> elements of type datetime-local.");
+
+function testSanitization(inputValue, expectedOutputValue)
+{
+    input = document.createElement("input");
+    input.type = "datetime-local";
+    input.value = inputValue;
+    shouldBeEqualToString("input.value", "" + expectedOutputValue);
+}
+
+let tests = [
+    ["2000-01-01 12:30:00.5", "2000-01-01T12:30:00.5"],
+    ["2000-01-01 12:30:00.60", "2000-01-01T12:30:00.6"],
+    ["2000-01-01 12:30:00.700", "2000-01-01T12:30:00.7"],
+    ["2000-01-01 12:30:00.04", "2000-01-01T12:30:00.04"],
+    ["2000-01-01 12:30:00.003", "2000-01-01T12:30:00.003"],
+    ["2000-01-01 12:30:00.1234", ""],
+    ["2000-01-01 12:30:00", "2000-01-01T12:30"],
+    ["2000-01-01 12:30:00.0", "2000-01-01T12:30"],
+    ["2000-01-01 12:30:01.0", "2000-01-01T12:30:01"],
+    ["2000-01-01 12:30:10.0", "2000-01-01T12:30:10"],
+];
+
+for (let test of tests)
+    testSanitization(test[0], test[1]);
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/fast/forms/datetimelocal/input-valueasnumber-datetimelocal-expected.txt (286868 => 286869)


--- trunk/LayoutTests/fast/forms/datetimelocal/input-valueasnumber-datetimelocal-expected.txt	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/fast/forms/datetimelocal/input-valueasnumber-datetimelocal-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -8,7 +8,7 @@
 PASS valueAsNumberFor("1970-01-01T00:00:00.000") is Date.UTC(1970, 0, 1, 0, 0, 0)
 PASS valueAsNumberFor("2009-12-22T11:32:11") is Date.UTC(2009, 11, 22, 11, 32, 11)
 PASS setValueAsNumberAndGetValue(1969, 11, 1, 0, 0, 0, 0) is "1969-12-01T00:00"
-PASS setValueAsNumberAndGetValue(1970, 0, 1, 10, 1, 0, 100) is "1970-01-01T10:01:00.100"
+PASS setValueAsNumberAndGetValue(1970, 0, 1, 10, 1, 0, 100) is "1970-01-01T10:01:00.1"
 PASS setValueAsNumberAndGetValue(2009, 11, 31, 23, 59, 59, 999) is "2009-12-31T23:59:59.999"
 PASS setValueAsNumberAndGetValue(10000, 0, 1, 12, 0, 1, 0) is "10000-01-01T12:00:01"
 PASS setValueAsNumberAndGetValue(-1, 0, 1, 0, 0, 0, 0) is ""
@@ -26,8 +26,8 @@
 PASS input.valueAsNumber = Number.NEGATIVE_INFINITY threw exception NotSupportedError: The operation is not supported..
 PASS input.valueAsNumber = Date.UTC(275760, 8, 13, 0, 0, 0, 1) threw exception NotSupportedError: The operation is not supported..
 Step attribute value and string representation:
-PASS input.step = "1"; setValueAsNumberAndGetValue(2010, 0, 21, 0, 0, 0, 0) is "2010-01-21T00:00:00"
-PASS input.step = "0.001"; setValueAsNumberAndGetValue(2010, 0, 21, 0, 0, 0, 0) is "2010-01-21T00:00:00.000"
+PASS input.step = "1"; setValueAsNumberAndGetValue(2010, 0, 21, 0, 0, 0, 0) is "2010-01-21T00:00"
+PASS input.step = "0.001"; setValueAsNumberAndGetValue(2010, 0, 21, 0, 0, 0, 0) is "2010-01-21T00:00"
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/forms/datetimelocal/input-valueasnumber-datetimelocal.html (286868 => 286869)


--- trunk/LayoutTests/fast/forms/datetimelocal/input-valueasnumber-datetimelocal.html	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/fast/forms/datetimelocal/input-valueasnumber-datetimelocal.html	2021-12-10 20:37:40 UTC (rev 286869)
@@ -32,7 +32,7 @@
 shouldBe('valueAsNumberFor("2009-12-22T11:32:11")', 'Date.UTC(2009, 11, 22, 11, 32, 11)');
 
 shouldBe('setValueAsNumberAndGetValue(1969, 11, 1, 0, 0, 0, 0)', '"1969-12-01T00:00"');
-shouldBe('setValueAsNumberAndGetValue(1970, 0, 1, 10, 1, 0, 100)', '"1970-01-01T10:01:00.100"');
+shouldBe('setValueAsNumberAndGetValue(1970, 0, 1, 10, 1, 0, 100)', '"1970-01-01T10:01:00.1"');
 shouldBe('setValueAsNumberAndGetValue(2009, 11, 31, 23, 59, 59, 999)', '"2009-12-31T23:59:59.999"');
 shouldBe('setValueAsNumberAndGetValue(10000, 0, 1, 12, 0, 1, 0)', '"10000-01-01T12:00:01"');
 
@@ -54,9 +54,9 @@
 
 debug('Step attribute value and string representation:');
 // If the step attribute value is 1 second and the second part is 0, we should show the second part.
-shouldBe('input.step = "1"; setValueAsNumberAndGetValue(2010, 0, 21, 0, 0, 0, 0)', '"2010-01-21T00:00:00"');
+shouldBe('input.step = "1"; setValueAsNumberAndGetValue(2010, 0, 21, 0, 0, 0, 0)', '"2010-01-21T00:00"');
 // If the step attribute value is 0.001 second and the millisecond part is 0, we should show the millisecond part.
-shouldBe('input.step = "0.001"; setValueAsNumberAndGetValue(2010, 0, 21, 0, 0, 0, 0)', '"2010-01-21T00:00:00.000"');
+shouldBe('input.step = "0.001"; setValueAsNumberAndGetValue(2010, 0, 21, 0, 0, 0, 0)', '"2010-01-21T00:00"');
 </script>
 <script src=""
 </body>

Modified: trunk/LayoutTests/fast/forms/time/time-validity-typemismatch-expected.txt (286868 => 286869)


--- trunk/LayoutTests/fast/forms/time/time-validity-typemismatch-expected.txt	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/fast/forms/time/time-validity-typemismatch-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -10,8 +10,6 @@
 PASS "23:59:59.1" is a correct valid time string.
 PASS "23:59:59.12" is a correct valid time string.
 PASS "23:59:59.123" is a correct valid time string.
-PASS "23:59:59.1234567890" is a correct valid time string.
-PASS "00:00:00.0000000000" is a correct valid time string.
 PASS " 00:00 " is an invalid time string and was sanitized.
 PASS "1:23" is an invalid time string and was sanitized.
 PASS "011:11" is an invalid time string and was sanitized.
@@ -33,6 +31,8 @@
 PASS "23:45:06." is an invalid time string and was sanitized.
 PASS "23:45:06.abc" is an invalid time string and was sanitized.
 PASS "23:45:06.789abc" is an invalid time string and was sanitized.
+PASS "23:59:59.1234567890" is an invalid time string and was sanitized.
+PASS "00:00:00.0000000000" is an invalid time string and was sanitized.
 PASS "invalid" is an invalid time string and was sanitized while disabled.
 PASS successfullyParsed is true
 

Modified: trunk/LayoutTests/fast/forms/time/time-validity-typemismatch.html (286868 => 286869)


--- trunk/LayoutTests/fast/forms/time/time-validity-typemismatch.html	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/fast/forms/time/time-validity-typemismatch.html	2021-12-10 20:37:40 UTC (rev 286869)
@@ -46,8 +46,6 @@
 shouldBeValid('23:59:59.1');
 shouldBeValid('23:59:59.12');
 shouldBeValid('23:59:59.123');
-shouldBeValid('23:59:59.1234567890');
-shouldBeValid('00:00:00.0000000000');
 
 // Invalid values
 shouldBeInvalid(' 00:00 ');
@@ -71,6 +69,8 @@
 shouldBeInvalid('23:45:06.');
 shouldBeInvalid('23:45:06.abc');
 shouldBeInvalid('23:45:06.789abc');
+shouldBeInvalid('23:59:59.1234567890');
+shouldBeInvalid('00:00:00.0000000000');
 
 // Disabled
 shouldBeInvalid('invalid', true);

Modified: trunk/LayoutTests/fast/forms/time/time-valueasdate-expected.txt (286868 => 286869)


--- trunk/LayoutTests/fast/forms/time/time-valueasdate-expected.txt	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/fast/forms/time/time-valueasdate-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -23,7 +23,7 @@
 PASS input.value = "00:00"; input.valueAsDate = null; input.value is ""
 Step attribute value and string representation:
 PASS input.step = "1"; setValueAsDateAndGetValue(0, 0, 0, 0) is "00:00:00"
-PASS input.step = "0.001"; setValueAsDateAndGetValue(0, 0, 0, 0) is "00:00:00.000"
+PASS input.step = "0.001"; setValueAsDateAndGetValue(0, 0, 0, 0) is "00:00:00.0"
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/forms/time/time-valueasdate.html (286868 => 286869)


--- trunk/LayoutTests/fast/forms/time/time-valueasdate.html	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/fast/forms/time/time-valueasdate.html	2021-12-10 20:37:40 UTC (rev 286869)
@@ -50,7 +50,7 @@
 // If the step attribute value is 1 second and the second part is 0, we should show the second part.
 shouldBe('input.step = "1"; setValueAsDateAndGetValue(0, 0, 0, 0)', '"00:00:00"');
 // If the step attribute value is 0.001 second and the millisecond part is 0, we should show the millisecond part.
-shouldBe('input.step = "0.001"; setValueAsDateAndGetValue(0, 0, 0, 0)', '"00:00:00.000"');
+shouldBe('input.step = "0.001"; setValueAsDateAndGetValue(0, 0, 0, 0)', '"00:00:00.0"');
 </script>
 <script src=""
 </body>

Modified: trunk/LayoutTests/fast/forms/time/time-valueasnumber-expected.txt (286868 => 286869)


--- trunk/LayoutTests/fast/forms/time/time-valueasnumber-expected.txt	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/fast/forms/time/time-valueasnumber-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -26,7 +26,7 @@
 PASS input.valueAsNumber = Number.NEGATIVE_INFINITY threw exception NotSupportedError: The operation is not supported..
 Step attribute value and string representation:
 PASS input.step = "1"; setValueAsNumberAndGetValue(0, 0, 0, 0) is "00:00:00"
-PASS input.step = "0.001"; setValueAsNumberAndGetValue(0, 0, 0, 0) is "00:00:00.000"
+PASS input.step = "0.001"; setValueAsNumberAndGetValue(0, 0, 0, 0) is "00:00:00.0"
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/forms/time/time-valueasnumber.html (286868 => 286869)


--- trunk/LayoutTests/fast/forms/time/time-valueasnumber.html	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/fast/forms/time/time-valueasnumber.html	2021-12-10 20:37:40 UTC (rev 286869)
@@ -50,7 +50,7 @@
 // If the step attribute value is 1 second and the second part is 0, we should show the second part.
 shouldBe('input.step = "1"; setValueAsNumberAndGetValue(0, 0, 0, 0)', '"00:00:00"');
 // If the step attribute value is 0.001 second and the millisecond part is 0, we should show the millisecond part.
-shouldBe('input.step = "0.001"; setValueAsNumberAndGetValue(0, 0, 0, 0)', '"00:00:00.000"');
+shouldBe('input.step = "0.001"; setValueAsNumberAndGetValue(0, 0, 0, 0)', '"00:00:00.0"');
 </script>
 <script src=""
 </body>

Modified: trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt (286868 => 286869)


--- trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -19,12 +19,12 @@
 PASS [INPUT in PASSWORD status] The value is empty and required is true
 PASS [INPUT in DATETIME-LOCAL status] The required attribute is not set
 PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(2000-12-10T12:00:00)
-FAIL [INPUT in DATETIME-LOCAL status] Valid local date and time string(2000-12-10 12:00) assert_false: The validity.valueMissing should be false. expected false got true
+PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(2000-12-10 12:00)
 PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(1979-10-14T12:00:00.001)
 PASS [INPUT in DATETIME-LOCAL status] The value attribute is a number(1234567)
 PASS [INPUT in DATETIME-LOCAL status] The value attribute is a Date object
 PASS [INPUT in DATETIME-LOCAL status] Invalid local date and time string(1979-10-99 99:99)
-FAIL [INPUT in DATETIME-LOCAL status] Valid local date and time string(1979-10-14 12:00:00) assert_false: The validity.valueMissing should be false. expected false got true
+PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(1979-10-14 12:00:00)
 PASS [INPUT in DATETIME-LOCAL status] Invalid local date and time string(2001-12-21  12:00)-two white space
 PASS [INPUT in DATETIME-LOCAL status] the value attribute is a string(abc)
 PASS [INPUT in DATETIME-LOCAL status] The value attribute is empty string

Modified: trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/datetime-local-expected.txt (286868 => 286869)


--- trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/datetime-local-expected.txt	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/datetime-local-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -1,9 +1,9 @@
 
 PASS empty value
 PASS datetime-local input value set to 2014-01-01T11:11:11.111 without min/max
-FAIL datetime-local input value set to 2014-01-01 11:11:11.111 without min/max assert_equals: expected "2014-01-01T11:11:11.111" but got ""
-FAIL datetime-local input value set to 2014-01-01 11:11 without min/max assert_equals: expected "2014-01-01T11:11" but got ""
-FAIL datetime-local input value set to 2014-01-01 00:00:00.000 without min/max assert_equals: expected "2014-01-01T00:00" but got ""
+PASS datetime-local input value set to 2014-01-01 11:11:11.111 without min/max
+PASS datetime-local input value set to 2014-01-01 11:11 without min/max
+PASS datetime-local input value set to 2014-01-01 00:00:00.000 without min/max
 PASS datetime-local input value set to 2014-01-0 11:11 without min/max
 PASS datetime-local input value set to 2014-01-01 11:1 without min/max
 PASS invalid datetime-local input value 1
@@ -12,8 +12,8 @@
 PASS invalid datetime-local input value 4
 PASS invalid datetime-local input value 5
 PASS invalid datetime-local input value 6
-FAIL Value >= min attribute assert_equals: expected "2014-01-01T11:12" but got ""
-FAIL Value < min attribute assert_equals: expected "2014-01-01T11:11" but got ""
-FAIL Value <= max attribute assert_equals: expected "2014-01-01T11:10" but got ""
-FAIL Value > max attribute assert_equals: expected "2014-01-01T11:11" but got ""
+PASS Value >= min attribute
+FAIL Value < min attribute assert_equals: expected "2014-01-01T11:11" but got "2014-01-01T11:10"
+PASS Value <= max attribute
+FAIL Value > max attribute assert_equals: expected "2014-01-01T11:11" but got "2014-01-01T11:12"
 

Modified: trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/time-2-expected.txt (286868 => 286869)


--- trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/time-2-expected.txt	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/platform/ios-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/time-2-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -5,7 +5,7 @@
 PASS Valid value: value should be 00:00:00.0
 PASS Valid value: value should be 00:00:00.00
 PASS Valid value: value should be 00:00:00.000
-FAIL Invalid value: fraction should have one, two or three ASCII digits. Value should be empty assert_equals: expected "" but got "00:00:00.0000"
+PASS Invalid value: fraction should have one, two or three ASCII digits. Value should be empty
 PASS Invalid value: hour should have two ASCII digits. Value should be empty
 PASS Invalid value: minutes should have two ASCII digits. Value should be empty
 PASS Invalid value: seconds should have two ASCII digits. Value should be empty

Modified: trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt (286868 => 286869)


--- trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -19,12 +19,12 @@
 PASS [INPUT in PASSWORD status] The value is empty and required is true
 PASS [INPUT in DATETIME-LOCAL status] The required attribute is not set
 PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(2000-12-10T12:00:00)
-FAIL [INPUT in DATETIME-LOCAL status] Valid local date and time string(2000-12-10 12:00) assert_false: The validity.valueMissing should be false. expected false got true
+PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(2000-12-10 12:00)
 PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(1979-10-14T12:00:00.001)
 PASS [INPUT in DATETIME-LOCAL status] The value attribute is a number(1234567)
 PASS [INPUT in DATETIME-LOCAL status] The value attribute is a Date object
 PASS [INPUT in DATETIME-LOCAL status] Invalid local date and time string(1979-10-99 99:99)
-FAIL [INPUT in DATETIME-LOCAL status] Valid local date and time string(1979-10-14 12:00:00) assert_false: The validity.valueMissing should be false. expected false got true
+PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(1979-10-14 12:00:00)
 PASS [INPUT in DATETIME-LOCAL status] Invalid local date and time string(2001-12-21  12:00)-two white space
 PASS [INPUT in DATETIME-LOCAL status] the value attribute is a string(abc)
 PASS [INPUT in DATETIME-LOCAL status] The value attribute is empty string

Modified: trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/datetime-local-expected.txt (286868 => 286869)


--- trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/datetime-local-expected.txt	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/datetime-local-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -1,9 +1,9 @@
 
 PASS empty value
 PASS datetime-local input value set to 2014-01-01T11:11:11.111 without min/max
-FAIL datetime-local input value set to 2014-01-01 11:11:11.111 without min/max assert_equals: expected "2014-01-01T11:11:11.111" but got ""
-FAIL datetime-local input value set to 2014-01-01 11:11 without min/max assert_equals: expected "2014-01-01T11:11" but got ""
-FAIL datetime-local input value set to 2014-01-01 00:00:00.000 without min/max assert_equals: expected "2014-01-01T00:00" but got ""
+PASS datetime-local input value set to 2014-01-01 11:11:11.111 without min/max
+PASS datetime-local input value set to 2014-01-01 11:11 without min/max
+PASS datetime-local input value set to 2014-01-01 00:00:00.000 without min/max
 PASS datetime-local input value set to 2014-01-0 11:11 without min/max
 PASS datetime-local input value set to 2014-01-01 11:1 without min/max
 PASS invalid datetime-local input value 1
@@ -12,8 +12,8 @@
 PASS invalid datetime-local input value 4
 PASS invalid datetime-local input value 5
 PASS invalid datetime-local input value 6
-FAIL Value >= min attribute assert_equals: expected "2014-01-01T11:12" but got ""
-FAIL Value < min attribute assert_equals: expected "2014-01-01T11:11" but got ""
-FAIL Value <= max attribute assert_equals: expected "2014-01-01T11:10" but got ""
-FAIL Value > max attribute assert_equals: expected "2014-01-01T11:11" but got ""
+PASS Value >= min attribute
+FAIL Value < min attribute assert_equals: expected "2014-01-01T11:11" but got "2014-01-01T11:10"
+PASS Value <= max attribute
+FAIL Value > max attribute assert_equals: expected "2014-01-01T11:11" but got "2014-01-01T11:12"
 

Modified: trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/time-2-expected.txt (286868 => 286869)


--- trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/time-2-expected.txt	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/LayoutTests/platform/mac-wk2/imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/time-2-expected.txt	2021-12-10 20:37:40 UTC (rev 286869)
@@ -5,7 +5,7 @@
 PASS Valid value: value should be 00:00:00.0
 PASS Valid value: value should be 00:00:00.00
 PASS Valid value: value should be 00:00:00.000
-FAIL Invalid value: fraction should have one, two or three ASCII digits. Value should be empty assert_equals: expected "" but got "00:00:00.0000"
+PASS Invalid value: fraction should have one, two or three ASCII digits. Value should be empty
 PASS Invalid value: hour should have two ASCII digits. Value should be empty
 PASS Invalid value: minutes should have two ASCII digits. Value should be empty
 PASS Invalid value: seconds should have two ASCII digits. Value should be empty

Modified: trunk/Source/WebCore/ChangeLog (286868 => 286869)


--- trunk/Source/WebCore/ChangeLog	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/Source/WebCore/ChangeLog	2021-12-10 20:37:40 UTC (rev 286869)
@@ -1,3 +1,42 @@
+2021-12-10  Chris Dumez  <cdu...@apple.com>
+
+        Improve <type="datetime-local"> value parsing and sanitization
+        https://bugs.webkit.org/show_bug.cgi?id=234039
+
+        Reviewed by Darin Adler.
+
+        Improve <type="datetime-local"> value parsing and sanitization.
+
+        Test: fast/forms/datetimelocal/datetime-local-value-sanitization.html
+
+        * html/BaseDateAndTimeInputType.h:
+        * html/DateTimeLocalInputType.cpp:
+        (WebCore::DateTimeLocalInputType::sanitizeValue const):
+        Implement value sanitization for <type="datetime-local"> so that:
+        - if the input uses a space as date / time separator, the sanitized value will use a 'T' instead.
+        - The output will use the shortest possible string, omitting seconds or milliseconds when 0, as per
+          https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-normalised-local-date-and-time-string
+
+        * html/DateTimeLocalInputType.h:
+        * platform/DateComponents.cpp:
+        (WebCore::DateComponents::parseTime):
+        Fix bug where we would allow more than 3 digits for the millisecond part of the time (we
+        would silently ignore follow-up digits instead of failing parsing). This is as per:
+        - https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-time-string
+        This was covered by one of the subtests in imported/w3c/web-platform-tests/html/semantics/forms/the-input-element/datetime-local.html
+
+        (WebCore::isDateTimeLocalSeparator):
+        (WebCore::DateComponents::parseDateTimeLocal):
+        Allow using a space as date / time separator in <type="datetime-local">, instead of simply allowing a 'T'.
+        This would align our behavior with Gecko and the specification:
+        - https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string
+        Note that Blink still seems to only allow 'T' as separator.
+
+
+        (WebCore::DateComponents::toStringForTime const):
+        The output will use the shortest possible string, omitting seconds or milliseconds when 0, as per
+        https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-normalised-local-date-and-time-string
+
 2021-12-10  Alex Christensen  <achristen...@webkit.org>
 
         Move if-domain and unless-domain conversion to WKContentRuleList parsing

Modified: trunk/Source/WebCore/html/BaseDateAndTimeInputType.h (286868 => 286869)


--- trunk/Source/WebCore/html/BaseDateAndTimeInputType.h	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/Source/WebCore/html/BaseDateAndTimeInputType.h	2021-12-10 20:37:40 UTC (rev 286869)
@@ -100,7 +100,7 @@
 
     // InputType functions:
     String visibleValue() const final;
-    String sanitizeValue(const String&) const final;
+    String sanitizeValue(const String&) const override;
     void setValue(const String&, bool valueChanged, TextFieldEventBehavior) final;
     WallTime valueAsDate() const override;
     ExceptionOr<void> setValueAsDate(WallTime) const override;

Modified: trunk/Source/WebCore/html/DateTimeLocalInputType.cpp (286868 => 286869)


--- trunk/Source/WebCore/html/DateTimeLocalInputType.cpp	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/Source/WebCore/html/DateTimeLocalInputType.cpp	2021-12-10 20:37:40 UTC (rev 286869)
@@ -99,6 +99,15 @@
     return results.containsAll({ DateTimeFormatValidationResults::HasYear, DateTimeFormatValidationResults::HasMonth, DateTimeFormatValidationResults::HasDay, DateTimeFormatValidationResults::HasHour, DateTimeFormatValidationResults::HasMinute, DateTimeFormatValidationResults::HasMeridiem });
 }
 
+String DateTimeLocalInputType::sanitizeValue(const String& proposedValue) const
+{
+    if (proposedValue.isEmpty())
+        return proposedValue;
+
+    auto components = DateComponents::fromParsingDateTimeLocal(proposedValue);
+    return components ? components->toString() : emptyString();
+}
+
 String DateTimeLocalInputType::formatDateTimeFieldsState(const DateTimeFieldsState& state) const
 {
     if (!state.year || !state.month || !state.dayOfMonth || !state.hour || !state.minute || !state.meridiem)

Modified: trunk/Source/WebCore/html/DateTimeLocalInputType.h (286868 => 286869)


--- trunk/Source/WebCore/html/DateTimeLocalInputType.h	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/Source/WebCore/html/DateTimeLocalInputType.h	2021-12-10 20:37:40 UTC (rev 286869)
@@ -52,6 +52,7 @@
     StepRange createStepRange(AnyStepHandling) const final;
     std::optional<DateComponents> parseToDateComponents(StringView) const final;
     std::optional<DateComponents> setMillisecondToDateComponents(double) const final;
+    String sanitizeValue(const String&) const final;
 
     bool isValidFormat(OptionSet<DateTimeFormatValidationResults>) const final;
     String formatDateTimeFieldsState(const DateTimeFieldsState&) const final;

Modified: trunk/Source/WebCore/platform/DateComponents.cpp (286868 => 286869)


--- trunk/Source/WebCore/platform/DateComponents.cpp	2021-12-10 20:23:01 UTC (rev 286868)
+++ trunk/Source/WebCore/platform/DateComponents.cpp	2021-12-10 20:37:40 UTC (rev 286869)
@@ -477,12 +477,10 @@
                     } else if (digitsLength == 2) {
                         millisecond = parseInt(temporaryBuffer, 2);
                         *millisecond *= 10;
-                    } else {
-                        // Regardless of the number of digits, we only ever parse at most 3. All other
-                        // digits after that are ignored, but the buffer is incremented as if they were
-                        // all parsed.
+                    } else if (digitsLength == 3)
                         millisecond = parseInt(temporaryBuffer, 3);
-                    }
+                    else
+                        return false;
 
                     // Due to the countDigits above, the parseInt calls should all be successful.
                     ASSERT(millisecond);
@@ -502,6 +500,13 @@
     return true;
 }
 
+// Gecko allows both 'T' and a space as datetime-local separator (see https://github.com/whatwg/html/issues/2276).
+// WPT tests also expect this behavior.
+template<typename CharacterType> static bool isDateTimeLocalSeparator(CharacterType c)
+{
+    return c == 'T' || c == ' ';
+}
+
 // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#local-dates-and-times
 template<typename CharacterType> bool DateComponents::parseDateTimeLocal(StringParsingBuffer<CharacterType>& buffer)
 {
@@ -508,7 +513,7 @@
     if (!parseDate(buffer))
         return false;
 
-    if (!skipExactly(buffer, 'T'))
+    if (!skipExactly<isDateTimeLocalSeparator>(buffer))
         return false;
 
     if (!parseTime(buffer))
@@ -760,9 +765,15 @@
         return makeString(pad('0', 2, m_hour), ':', pad('0', 2, m_minute));
     case SecondFormat::Second:
         return makeString(pad('0', 2, m_hour), ':', pad('0', 2, m_minute), ':', pad('0', 2, m_second));
-    case SecondFormat::Millisecond:
-        return makeString(pad('0', 2, m_hour), ':', pad('0', 2, m_minute), ':', pad('0', 2, m_second), '.', pad('0', 3, m_millisecond));
+    case SecondFormat::Millisecond: {
+        auto resultWithoutMilliseconds = makeString(pad('0', 2, m_hour), ':', pad('0', 2, m_minute), ':', pad('0', 2, m_second), '.');
+        if (!(m_millisecond % 100))
+            return makeString(resultWithoutMilliseconds, m_millisecond / 100);
+        if (!(m_millisecond % 10))
+            return makeString(resultWithoutMilliseconds, pad('0', 2, m_millisecond / 10));
+        return makeString(resultWithoutMilliseconds, pad('0', 3, m_millisecond));
     }
+    }
 }
 
 String DateComponents::toString(SecondFormat format) const
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to