Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement valid DatetimeLocal input #19602

Merged
merged 1 commit into from Jan 7, 2018
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

implement valid Date time Local input

  • Loading branch information
tigercosmos committed Jan 7, 2018
commit b43424111e9a901a5837718e2d7e653dbe4a8ed2
@@ -302,6 +302,20 @@ impl DOMString {
pub fn is_valid_week_string(&self) -> bool {
parse_week_string(&*self.0).is_ok()
}

/// A valid normalized local date and time string should be "{date}T{time}"
/// where date and time are both valid, and the time string must be as short as possible
/// https://html.spec.whatwg.org/multipage/#valid-normalised-local-date-and-time-string
pub fn convert_valid_normalized_local_date_and_time_string(&mut self) -> Result<(), ()> {
let ((year, month, day), (hour, minute, second)) = parse_local_date_and_time_string(&*self.0)?;
if second == 0.0 {
self.0 = format!("{:04}-{:02}-{:02}T{:02}:{:02}", year, month, day, hour, minute);
} else {
self.0 = format!("{:04}-{:02}-{:02}T{:02}:{:02}:{}", year, month, day, hour, minute, second);
}
Ok(())
}

}

impl Borrow<str> for DOMString {
@@ -541,6 +555,84 @@ fn parse_date_component(value: &str) -> Result<(u32, u32, u32), ()> {
Ok((year_int, month_int, day_int))
}

/// https://html.spec.whatwg.org/multipage/#parse-a-time-component
fn parse_time_component(value: &str) -> Result<(u32, u32, f32), ()> {
// Step 1
let mut iterator = value.split(':');
let hour = iterator.next().ok_or(())?;
if hour.len() != 2 {
return Err(());
}
let hour_int = hour.parse::<u32>().map_err(|_| ())?;

// Step 2
if hour_int > 23 {
return Err(());
}

// Step 3, 4
let minute = iterator.next().ok_or(())?;
if minute.len() != 2 {
return Err(());
}
let minute_int = minute.parse::<u32>().map_err(|_| ())?;

// Step 5
if minute_int > 59 {
return Err(());
}

// Step 6, 7
let second_float = match iterator.next() {
Some(second) => {
let mut second_iterator = second.split('.');
if second_iterator.next().ok_or(())?.len() != 2 {
return Err(());
}
match second_iterator.next() {
Some(second_last) => {
if second_last.len() > 3 {
return Err(());
}
},
None => {}
}

second.parse::<f32>().map_err(|_| ())?
},
None => 0.0
};

// Step 8
Ok((hour_int, minute_int, second_float))
}

// https://html.spec.whatwg.org/multipage/#parse-a-local-date-and-time-string
fn parse_local_date_and_time_string(value: &str) -> Result<((u32, u32, u32), (u32, u32, f32)), ()> {
// Step 1, 2, 4
let mut iterator = if value.contains('T') {
value.split('T')
} else {
value.split(' ')
};

// Step 3
let date = iterator.next().ok_or(())?;
let date_tuple = parse_date_component(date)?;

// Step 5
let time = iterator.next().ok_or(())?;
let time_tuple = parse_time_component(time)?;

// Step 6
if iterator.next().is_some() {
return Err(());
}

// Step 7, 8, 9
Ok((date_tuple, time_tuple))
}

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),
@@ -996,19 +996,19 @@ impl HTMLInputElement {
InputType::Date => {
let mut textinput = self.textinput.borrow_mut();
if !textinput.single_line_content().is_valid_date_string() {
*textinput.single_line_content_mut() = "".into();
textinput.single_line_content_mut().clear();
}
}
InputType::Month => {
let mut textinput = self.textinput.borrow_mut();
if !textinput.single_line_content().is_valid_month_string() {
*textinput.single_line_content_mut() = "".into();
textinput.single_line_content_mut().clear();
}
}
InputType::Week => {
let mut textinput = self.textinput.borrow_mut();
if !textinput.single_line_content().is_valid_week_string() {
*textinput.single_line_content_mut() = "".into();
textinput.single_line_content_mut().clear();
}
}
InputType::Color => {
@@ -1034,8 +1034,15 @@ impl HTMLInputElement {
InputType::Time => {
let mut textinput = self.textinput.borrow_mut();

if ! textinput.single_line_content().is_valid_time_string() {
*textinput.single_line_content_mut() = "".into();
if !textinput.single_line_content().is_valid_time_string() {
textinput.single_line_content_mut().clear();
}
}
InputType::DatetimeLocal => {
let mut textinput = self.textinput.borrow_mut();
if textinput.single_line_content_mut()
.convert_valid_normalized_local_date_and_time_string().is_err() {
textinput.single_line_content_mut().clear();

This comment has been minimized.

@CYBAI

CYBAI Jan 7, 2018

Collaborator

Nit:

Can it be indented like following?

if textinput.single_line_content_mut()
            .convert_valid_normalized_local_date_and_time_string()
            .is_err() {

Oh, @KiChjang has approved. I think this is not a big issue :P

This comment has been minimized.

@tigercosmos

tigercosmos Jan 7, 2018

Author Collaborator

sure. it's ok. :)

This comment has been minimized.

@KiChjang

KiChjang Jan 7, 2018

Member

@CYBAI I'm actually not sure what the proper rustfmt for this is, I suspect it is this instead?

if textinput.single_line_content_mut()
    .convert_valid_normalized_local_date_and_time_string()
    .is_err()
{
    // body goes here
}

but since we don't run rustfmt yet, I don't really care too much as long as ./mach test-tidy says it's ok.

This comment has been minimized.

}
}
// TODO: Implement more value sanitization algorithms for different types of inputs
"testharness"
],
"html/semantics/forms/the-input-element/datetime-local.html": [
"7fe3ab2bd5a8d60e11d08460286ee8f02943b769",
"382370387908b4625474b410621497a76476a0cf",
"testharness"
],
"html/semantics/forms/the-input-element/datetime.html": [
@@ -1,29 +1,9 @@
[datetime-local.html]
type: testharness
[datetime-local input value set to 2014-01-01 11:11:11.111 without min/max]
expected: FAIL

[datetime-local input value set to 2014-01-01 11:11 without min/max]
expected: FAIL

[datetime-local input value set to 2014-01-01 00:00:00.000 without min/max]
expected: FAIL

[datetime-local input value set to 2014-01-0 11:11 without min/max]
expected: FAIL

[datetime-local input value set to 2014-01-01 11:1 without min/max]
expected: FAIL

[Value >= min attribute]
expected: FAIL

[Value < min attribute]
expected: FAIL

[Value <= max attribute]
expected: FAIL

[Value > max attribute]
expected: FAIL

@@ -225,9 +225,6 @@
[change state from checkbox to email]
expected: FAIL

[change state from checkbox to datetime]
expected: FAIL

[change state from checkbox to number]
expected: FAIL

@@ -294,96 +291,9 @@
[change state from button to range]
expected: FAIL

[change state from hidden to datetime-local]
expected: FAIL

[change state from text to datetime-local]
expected: FAIL

[change state from search to datetime-local]
expected: FAIL

[change state from tel to datetime-local]
expected: FAIL

[change state from url to datetime-local]
expected: FAIL

[change state from email to datetime-local]
expected: FAIL

[change state from password to datetime-local]
expected: FAIL

[change state from datetime-local to hidden]
expected: FAIL

[change state from datetime-local to checkbox]
expected: FAIL

[change state from datetime-local to radio]
expected: FAIL

[change state from datetime-local to submit]
expected: FAIL

[change state from datetime-local to image]
expected: FAIL

[change state from datetime-local to reset]
expected: FAIL

[change state from datetime-local to button]
expected: FAIL

[change state from datetime-local to email]
expected: FAIL

[change state from datetime-local to number]
expected: FAIL

[change state from datetime-local to range]
expected: FAIL

[change state from number to datetime-local]
expected: FAIL

[change state from range to datetime-local]
expected: FAIL

[change state from checkbox to datetime-local]
expected: FAIL

[change state from radio to datetime-local]
expected: FAIL

[change state from submit to datetime-local]
expected: FAIL

[change state from image to datetime-local]
expected: FAIL

[change state from reset to datetime-local]
expected: FAIL

[change state from button to datetime-local]
expected: FAIL

[change state from datetime-local to text]
expected: FAIL

[change state from datetime-local to search]
expected: FAIL

[change state from datetime-local to tel]
expected: FAIL

[change state from datetime-local to url]
expected: FAIL

[change state from datetime-local to password]
expected: FAIL

[change state from number to text]
expected: FAIL

@@ -414,9 +324,6 @@
[change state from range to password]
expected: FAIL

[change state from color to datetime-local]
expected: FAIL

[change state from color to number]
expected: FAIL

@@ -18,12 +18,6 @@
[value IDL attribute of input type range with value attribute]
expected: FAIL

[value IDL attribute of input type datetime-local without value attribute]
expected: FAIL

[value IDL attribute of input type datetime-local with value attribute]
expected: FAIL

[value IDL attribute of input type email without value attribute]
expected: FAIL

@@ -16,6 +16,12 @@
{value: "2014-01-01 00:00:00.000", expected: "2014-01-01T00:00", testname: "datetime-local input value set to 2014-01-01 00:00:00.000 without min/max"},
{value: "2014-01-0 11:11", expected: "", testname: "datetime-local input value set to 2014-01-0 11:11 without min/max"},
{value: "2014-01-01 11:1", expected: "", testname: "datetime-local input value set to 2014-01-01 11:1 without min/max"},
{value: "2014-01-01 11:1d1", expected: "", testname: "invalid datetime-local input value 1"},
{value: "2014-01-01H11:11", expected: "", testname: "invalid datetime-local input value 2"},
{value: "2014-01-01 11:11:", expected: "", testname: "invalid datetime-local input value 3"},
{value: "2014-01-01 11-11", expected: "", testname: "invalid datetime-local input value 4"},
{value: "2014-01-01 11:11:123", expected: "", testname: "invalid datetime-local input value 5"},
{value: "2014-01-01 11:11:12.1234", expected: "", testname: "invalid datetime-local input value 6"},
{value: "2014-01-01 11:12", attributes: { min: "2014-01-01 11:11" }, expected: "2014-01-01T11:12", testname: "Value >= min attribute"},
{value: "2014-01-01 11:10", attributes: { min: "2014-01-01 11:11" }, expected: "2014-01-01T11:11", testname: "Value < min attribute"},
{value: "2014-01-01 11:10", attributes: { max: "2014-01-01 11:11" }, expected: "2014-01-01T11:10", testname: "Value <= max attribute"},
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.