mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Auto merge of #19602 - tigercosmos:r1, r=KiChjang
implement valid DatetimeLocal input <!-- Please describe your changes on the following line: --> implement valid Date time Local input part of #19172 --- <!-- 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] These changes fix #19587 fix #19603(github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- 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/19602) <!-- Reviewable:end -->
This commit is contained in:
commit
7f36b59762
7 changed files with 111 additions and 125 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
// TODO: Implement more value sanitization algorithms for different types of inputs
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue