diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 6601d8e6856c..596b2db14b2e 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -279,6 +279,20 @@ impl DOMString { _ => false } } + + /// A valid date string should be "YYYY-MM-DD" + /// YYYY must be four or more digits, MM and DD both must be two digits + /// https://html.spec.whatwg.org/multipage/#valid-date-string + pub fn is_valid_date_string(&self) -> bool { + parse_date_string(&*self.0).is_ok() + } + + /// A valid month string should be "YYYY-MM" + /// YYYY must be four or more digits, MM both must be two digits + /// https://html.spec.whatwg.org/multipage/#valid-month-string + pub fn is_valid_month_string(&self) -> bool { + parse_month_string(&*self.0).is_ok() + } } impl Borrow for DOMString { @@ -403,3 +417,90 @@ impl Extend for DOMString { self.0.extend(iterable) } } + +/// https://html.spec.whatwg.org/multipage/#parse-a-month-string +fn parse_month_string(value: &str) -> Result<(u32, u32), ()> { + // Step 1, 2, 3 + let (year_int, month_int) = parse_month_component(value)?; + + // Step 4 + if value.split("-").nth(2).is_some() { + return Err(()); + } + // Step 5 + Ok((year_int, month_int)) +} + +/// https://html.spec.whatwg.org/multipage/#parse-a-date-string +fn parse_date_string(value: &str) -> Result<(u32, u32, u32), ()> { + // Step 1, 2, 3 + let (year_int, month_int, day_int) = parse_date_component(value)?; + + // Step 4 + if value.split('-').nth(3).is_some() { + return Err(()); + } + + // Step 5, 6 + Ok((year_int, month_int, day_int)) +} + +/// https://html.spec.whatwg.org/multipage/#parse-a-month-component +fn parse_month_component(value: &str) -> Result<(u32, u32), ()> { + // Step 3 + let mut iterator = value.split('-'); + let year = iterator.next().ok_or(())?; + let month = iterator.next().ok_or(())?; + + // Step 1, 2 + let year_int = year.parse::().map_err(|_| ())?; + if year.len() < 4 || year_int == 0 { + return Err(()); + } + + // Step 4, 5 + let month_int = month.parse::().map_err(|_| ())?; + if month.len() != 2 || month_int > 12 || month_int < 1 { + return Err(()); + } + + // Step 6 + Ok((year_int, month_int)) +} + +/// https://html.spec.whatwg.org/multipage/#parse-a-date-component +fn parse_date_component(value: &str) -> Result<(u32, u32, u32), ()> { + // Step 1 + let (year_int, month_int) = parse_month_component(value)?; + + // Step 3, 4 + let day = value.split('-').nth(2).ok_or(())?; + let day_int = day.parse::().map_err(|_| ())?; + if day.len() != 2 { + return Err(()); + } + + // Step 2, 5 + let max_day = max_day_in_month(year_int, month_int)?; + if day_int == 0 || day_int > max_day { + return Err(()); + } + + // Step 6 + Ok((year_int, month_int, day_int)) +} + +fn max_day_in_month(year_num: u32, month_num: u32) -> Result { + match month_num { + 1|3|5|7|8|10|12 => Ok(31), + 4|6|9|11 => Ok(30), + 2 => { + if year_num % 400 == 0 || (year_num % 4 == 0 && year_num % 100 != 0) { + Ok(29) + } else { + Ok(28) + } + }, + _ => Err(()) + } +} diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 0725fafcaaca..cbf4f483e0c8 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -875,6 +875,18 @@ impl HTMLInputElement { content.strip_newlines(); content.strip_leading_and_trailing_ascii_whitespace(); } + atom!("date") => { + let mut textinput = self.textinput.borrow_mut(); + if !textinput.single_line_content().is_valid_date_string() { + *textinput.single_line_content_mut() = "".into(); + } + } + atom!("month") => { + let mut textinput = self.textinput.borrow_mut(); + if !textinput.single_line_content().is_valid_month_string() { + *textinput.single_line_content_mut() = "".into(); + } + } atom!("color") => { let mut textinput = self.textinput.borrow_mut(); @@ -1042,6 +1054,7 @@ impl VirtualMethods for HTMLInputElement { let value = mutation.new_value(attr).map(|value| (**value).to_owned()); self.textinput.borrow_mut().set_content( value.map_or(DOMString::new(), DOMString::from)); + self.sanitize_value(); self.update_placeholder_shown_state(); }, &local_name!("name") if self.input_type.get() == InputType::InputRadio => { @@ -1117,7 +1130,6 @@ impl VirtualMethods for HTMLInputElement { if let Some(ref s) = self.super_type() { s.bind_to_tree(tree_in_doc); } - self.upcast::().check_ancestors_disabled_state_for_form_control(); } diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index 18d4d794c2f7..68306f7ae97e 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -542997,7 +542997,7 @@ "testharness" ], "html/semantics/forms/the-input-element/month.html": [ - "1d833657f1db1e58fcc12a01af2ba06a665344aa", + "d0833c2b8ddd97c35200eb95ba0473795abf1f3b", "testharness" ], "html/semantics/forms/the-input-element/number.html": [ diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/date.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/date.html.ini index 241ad23a5e22..99eb0c7bba3b 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/date.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/date.html.ini @@ -5,10 +5,3 @@ [The max attribute, if specified, must have a value that is a valid date string.] expected: FAIL - - [User agents must not allow the user to set the value to a non-empty string that is not a valid date string.] - expected: FAIL - - [Number of days] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/month.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/month.html.ini index 5bf6d6773888..dd41c559298c 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/month.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/month.html.ini @@ -1,32 +1,4 @@ [month.html] type: testharness - [The value attribute, if specified and not empty, must have a value that is a valid month string] - expected: FAIL - - [The min attribute, if specified, must have a value that is a valid month string.] - expected: FAIL - - [The max attribute, if specified, must have a value that is a valid month string] - expected: FAIL - - [User agents must not allow the user to set the value to a non-empty string that is not a valid month string.] - expected: FAIL - - [When value attribute has two digits year value, the value,which is invalid, must return empty string.] - expected: FAIL - - [When value is set with invalid value, the value must return empty string.] - expected: FAIL - - [When value is given invalid value to non-empty valid string, the value must be same as before.] - expected: FAIL - [When step attribute is given invalid value, it must ignore the invalid value and use defaul value instead.] expected: FAIL - - [Month should be <= 13: If the value of the element is not a valid month string, then set it to the empty string instead.] - expected: FAIL - - [Month should be > 0: If the value of the element is not a valid month string, then set it to the empty string instead.>] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/telephone.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/telephone.html.ini deleted file mode 100644 index c76c90b49c41..000000000000 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/telephone.html.ini +++ /dev/null @@ -1,11 +0,0 @@ -[telephone.html] - type: testharness - [The value attribute, if specified, must have a value that contains no "LF" (U+000A)] - expected: FAIL - - [The value attribute, if specified, must have a value that contains no "CR" (U+000D)] - expected: FAIL - - [The value sanitization algorithm is as follows: Strip line breaks from the value] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini index cc3c76ce1ab4..185dd9211147 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini @@ -6,12 +6,6 @@ [change state from hidden to datetime] expected: FAIL - [change state from hidden to date] - expected: FAIL - - [change state from hidden to month] - expected: FAIL - [change state from hidden to week] expected: FAIL @@ -27,12 +21,6 @@ [change state from text to datetime] expected: FAIL - [change state from text to date] - expected: FAIL - - [change state from text to month] - expected: FAIL - [change state from text to week] expected: FAIL @@ -48,12 +36,6 @@ [change state from search to datetime] expected: FAIL - [change state from search to date] - expected: FAIL - - [change state from search to month] - expected: FAIL - [change state from search to week] expected: FAIL @@ -69,12 +51,6 @@ [change state from tel to datetime] expected: FAIL - [change state from tel to date] - expected: FAIL - - [change state from tel to month] - expected: FAIL - [change state from tel to week] expected: FAIL @@ -99,12 +75,6 @@ [change state from url to datetime] expected: FAIL - [change state from url to date] - expected: FAIL - - [change state from url to month] - expected: FAIL - [change state from url to week] expected: FAIL @@ -138,12 +108,6 @@ [change state from email to datetime] expected: FAIL - [change state from email to date] - expected: FAIL - - [change state from email to month] - expected: FAIL - [change state from email to week] expected: FAIL @@ -159,12 +123,6 @@ [change state from password to datetime] expected: FAIL - [change state from password to date] - expected: FAIL - - [change state from password to month] - expected: FAIL - [change state from password to week] expected: FAIL @@ -192,12 +150,6 @@ [change state from datetime to password] expected: FAIL - [change state from datetime to date] - expected: FAIL - - [change state from datetime to month] - expected: FAIL - [change state from datetime to week] expected: FAIL @@ -207,99 +159,18 @@ [change state from datetime to range] expected: FAIL - [change state from date to hidden] - expected: FAIL - - [change state from date to checkbox] - expected: FAIL - - [change state from date to radio] - expected: FAIL - - [change state from date to submit] - expected: FAIL - - [change state from date to image] - expected: FAIL - - [change state from date to reset] - expected: FAIL - - [change state from date to button] - expected: FAIL - - [change state from date to email] - expected: FAIL - [change state from date to datetime] expected: FAIL - [change state from date to month] - expected: FAIL - - [change state from date to week] - expected: FAIL - - [change state from date to number] - expected: FAIL - [change state from date to range] expected: FAIL - [change state from month to hidden] - expected: FAIL - - [change state from month to checkbox] - expected: FAIL - - [change state from month to radio] - expected: FAIL - - [change state from month to submit] - expected: FAIL - - [change state from month to image] - expected: FAIL - - [change state from month to reset] - expected: FAIL - - [change state from month to button] - expected: FAIL - - [change state from month to email] - expected: FAIL - - [change state from month to datetime] - expected: FAIL - - [change state from month to date] - expected: FAIL - - [change state from month to week] - expected: FAIL - - [change state from month to number] + [change state from date to range] expected: FAIL [change state from month to range] expected: FAIL - [change state from week to hidden] - expected: FAIL - - [change state from week to checkbox] - expected: FAIL - - [change state from week to radio] - expected: FAIL - - [change state from week to submit] - expected: FAIL - - [change state from week to image] - expected: FAIL - [change state from week to reset] expected: FAIL @@ -312,10 +183,10 @@ [change state from week to datetime] expected: FAIL - [change state from week to date] + [change state from week to number] expected: FAIL - [change state from week to month] + [change state from week to hidden] expected: FAIL [change state from week to number] @@ -324,6 +195,12 @@ [change state from week to range] expected: FAIL + [change state from time to datetime] + expected: FAIL + + [change state from time to range] + expected: FAIL + [change state from number to hidden] expected: FAIL @@ -351,12 +228,6 @@ [change state from number to datetime] expected: FAIL - [change state from number to date] - expected: FAIL - - [change state from number to month] - expected: FAIL - [change state from number to week] expected: FAIL @@ -390,12 +261,6 @@ [change state from range to datetime] expected: FAIL - [change state from range to date] - expected: FAIL - - [change state from range to month] - expected: FAIL - [change state from range to week] expected: FAIL @@ -408,12 +273,6 @@ [change state from checkbox to datetime] expected: FAIL - [change state from checkbox to date] - expected: FAIL - - [change state from checkbox to month] - expected: FAIL - [change state from checkbox to week] expected: FAIL @@ -429,12 +288,6 @@ [change state from radio to datetime] expected: FAIL - [change state from radio to date] - expected: FAIL - - [change state from radio to month] - expected: FAIL - [change state from radio to week] expected: FAIL @@ -450,12 +303,6 @@ [change state from submit to datetime] expected: FAIL - [change state from submit to date] - expected: FAIL - - [change state from submit to month] - expected: FAIL - [change state from submit to week] expected: FAIL @@ -471,12 +318,6 @@ [change state from image to datetime] expected: FAIL - [change state from image to date] - expected: FAIL - - [change state from image to month] - expected: FAIL - [change state from image to week] expected: FAIL @@ -492,12 +333,6 @@ [change state from reset to datetime] expected: FAIL - [change state from reset to date] - expected: FAIL - - [change state from reset to month] - expected: FAIL - [change state from reset to week] expected: FAIL @@ -513,12 +348,6 @@ [change state from button to datetime] expected: FAIL - [change state from button to date] - expected: FAIL - - [change state from button to month] - expected: FAIL - [change state from button to week] expected: FAIL @@ -573,12 +402,6 @@ [change state from datetime-local to email] expected: FAIL - [change state from datetime-local to date] - expected: FAIL - - [change state from datetime-local to month] - expected: FAIL - [change state from datetime-local to week] expected: FAIL @@ -588,12 +411,6 @@ [change state from datetime-local to range] expected: FAIL - [change state from date to datetime-local] - expected: FAIL - - [change state from month to datetime-local] - expected: FAIL - [change state from week to datetime-local] expected: FAIL @@ -621,7 +438,6 @@ [change state from button to datetime-local] expected: FAIL - [change state from datetime-local to text] expected: FAIL @@ -637,55 +453,33 @@ [change state from datetime-local to password] expected: FAIL - - [change state from date to text] - expected: FAIL - - [change state from date to search] - expected: FAIL - - [change state from date to tel] - expected: FAIL - - [change state from date to url] - expected: FAIL - - [change state from date to password] - expected: FAIL - - - [change state from month to text] - expected: FAIL - - [change state from month to search] + [change state from week to text] expected: FAIL - [change state from month to tel] + [change state from week to search] expected: FAIL - [change state from month to url] + [change state from week to tel] expected: FAIL - [change state from month to password] + [change state from week to url] expected: FAIL - - [change state from week to text] + [change state from week to password] expected: FAIL - [change state from week to search] + [change state from week to checkbox] expected: FAIL - [change state from week to tel] + [change state from week to radio] expected: FAIL - [change state from week to url] + [change state from week to submit] expected: FAIL - [change state from week to password] + [change state from week to image] expected: FAIL - [change state from number to text] expected: FAIL @@ -701,40 +495,29 @@ [change state from number to password] expected: FAIL - - [change state from color to datetime-local] - expected: FAIL - - [change state from color to date] - expected: FAIL - - [change state from color to month] - expected: FAIL - - [change state from color to week] + [change state from range to text] expected: FAIL - [change state from color to number] + [change state from range to search] expected: FAIL - [change state from color to range] + [change state from range to tel] expected: FAIL - - [change state from time to range] + [change state from range to url] expected: FAIL - [change state from range to text] + [change state from range to password] expected: FAIL - [change state from range to search] + [change state from color to datetime-local] expected: FAIL - [change state from range to tel] + [change state from color to week] expected: FAIL - [change state from range to url] + [change state from color to number] expected: FAIL - [change state from range to password] + [change state from color to range] expected: FAIL diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/url.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/url.html.ini deleted file mode 100644 index 2adffb5fdd83..000000000000 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/url.html.ini +++ /dev/null @@ -1,8 +0,0 @@ -[url.html] - type: testharness - [The value sanitization algorithm is as follows: Strip line breaks from the value] - expected: FAIL - - [The value sanitization algorithm is as follows: Strip leading and trailing whitespace from the value.] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini index 8c54f4d21d99..4dd99f109cdc 100644 --- a/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini +++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini @@ -6,18 +6,6 @@ [value IDL attribute of input type datetime with value attribute] expected: FAIL - [value IDL attribute of input type date without value attribute] - expected: FAIL - - [value IDL attribute of input type date with value attribute] - expected: FAIL - - [value IDL attribute of input type month without value attribute] - expected: FAIL - - [value IDL attribute of input type month with value attribute] - expected: FAIL - [value IDL attribute of input type week without value attribute] expected: FAIL diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/month.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/month.html index 15fa76dd4dd0..99be9bca673d 100644 --- a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/month.html +++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/month.html @@ -13,6 +13,9 @@

Inputs Month

+ + + @@ -21,11 +24,27 @@

Inputs Month

+ + + +