Auto merge of #19385 - tigercosmos:b1, r=KiChjang

implement  "Date type inputs", "Month type inputs"

<!-- Please describe your changes on the following line: -->
implement "Date type inputs", "Month type inputs"

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] `./mach test-unit` does not report any errors

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19385)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-12-04 19:58:08 -06:00 committed by GitHub
commit 68cefb1b00
10 changed files with 182 additions and 317 deletions

View file

@ -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<str> for DOMString {
@ -403,3 +417,90 @@ impl Extend<char> 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::<u32>().map_err(|_| ())?;
if year.len() < 4 || year_int == 0 {
return Err(());
}
// Step 4, 5
let month_int = month.parse::<u32>().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::<u32>().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<u32, ()> {
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(())
}
}

View file

@ -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::<Element>().check_ancestors_disabled_state_for_form_control();
}

View file

@ -542997,7 +542997,7 @@
"testharness"
],
"html/semantics/forms/the-input-element/month.html": [
"1d833657f1db1e58fcc12a01af2ba06a665344aa",
"d0833c2b8ddd97c35200eb95ba0473795abf1f3b",
"testharness"
],
"html/semantics/forms/the-input-element/number.html": [

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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,39 +453,6 @@
[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]
expected: FAIL
[change state from month to tel]
expected: FAIL
[change state from month to url]
expected: FAIL
[change state from month to password]
expected: FAIL
[change state from week to text]
expected: FAIL
@ -685,6 +468,17 @@
[change state from week to password]
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 number to text]
expected: FAIL
@ -701,29 +495,6 @@
[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]
expected: FAIL
[change state from color to number]
expected: FAIL
[change state from color to range]
expected: FAIL
[change state from time to range]
expected: FAIL
[change state from range to text]
expected: FAIL
@ -738,3 +509,15 @@
[change state from range to password]
expected: FAIL
[change state from color to datetime-local]
expected: FAIL
[change state from color to week]
expected: FAIL
[change state from color to number]
expected: FAIL
[change state from color to range]
expected: FAIL

View file

@ -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

View file

@ -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

View file

@ -13,6 +13,9 @@
<body>
<h1>Inputs Month</h1>
<div style="display: none">
<input id="valid_value_1" type="month" value="20133-12" />
<input id="valid_value_2" type="month" value="2013-12" />
<input id="valid_value_3" type="month" value="0003-01" />
<input id="valid" type="month" value="2011-11" min="2011-01" max="2011-12" />
<input id="invalid_value" type="month" value="invalid-month" min="2011-01" max="2011-12"/>
<input id="value_can_be_empty_string" type="month" value="2013-06" />
@ -21,11 +24,27 @@
<input id="step_attribute_is_invalid_value" type="month" value="2013-06" step="invalid_step_value" />
<input id="invalid_month_too_high" type="month" value="2013-13" />
<input id="invalid_month_too_low" type="month" value="2013-00" />
<input id="invalid_year_all_zero" type="month" value="0000-10" />
<input id="invalid_month_with_one_number" type="month" value="2013-1" />
<input id="invalid_month_non_numerical" type="month" value="2013-abc" />
<input id="invalid_date_additional_tuples" type="month" value="2013-11-1-1" />
</div>
<div id="log"></div>
<script>
test(function() {
assert_equals(document.getElementById("valid_value_1").value, "20133-12")
}, "year can be more than four digits");
test(function() {
assert_equals(document.getElementById("valid_value_2").value, "2013-12")
}, "valid value test");
test(function() {
assert_equals(document.getElementById("valid_value_3").value, "0003-01")
}, "year can contain prefixes of zero, as long as there are at least four digits");
test(function() {
assert_equals(document.getElementById("valid").type, "month")
}, "month type support on input element");
@ -60,6 +79,22 @@
test(function() {
assert_equals(document.getElementById("invalid_month_too_low").value, "");
}, "Month should be > 0: If the value of the element is not a valid month string, then set it to the empty string instead.>");
test(function() {
assert_equals(document.getElementById("invalid_year_all_zero").value, "");
}, "Year should be > 0: If the value of the element is not a valid year string, then set it to the empty string instead.>");
test(function() {
assert_equals(document.getElementById("invalid_month_with_one_number").value, "");
}, "Month should be two digits: If the value of the element is not a valid month string, then set it to the empty string instead.>");
test(function() {
assert_equals(document.getElementById("invalid_month_non_numerical").value, "");
}, "Month should be two digits not characters: If the value of the element is not a valid month string, then set it to the empty string instead.>");
test(function() {
assert_equals(document.getElementById("invalid_date_additional_tuples").value, "");
}, "Value should be two parts: If the value of the element is not a valid month string, then set it to the empty string instead.>");
</script>
</body>
</html>