From 6c518c89b969d1e9a96c3c5b9fe0da6cfc3637d1 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 2 May 2017 11:10:49 +0200 Subject: Upgrade to html5ever 0.16 --- components/script/dom/bindings/str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index e75958d974a..6cb17fae4e3 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -4,7 +4,7 @@ //! The `ByteString` struct. -use html5ever_atoms::{LocalName, Namespace}; +use html5ever::{LocalName, Namespace}; use servo_atoms::Atom; use std::ascii::AsciiExt; use std::borrow::{Borrow, Cow, ToOwned}; -- cgit v1.2.3 From 524794c09ac3ab4aa4fa80c6b134182bab494bd6 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Tue, 6 Jun 2017 12:44:17 +0800 Subject: script: Move extended_filtering to the style crate. We'll need to call it from the style crate in later patches, when matching :lang() against element snapshots. --- components/script/dom/bindings/str.rs | 57 ----------------------------------- 1 file changed, 57 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 6cb17fae4e3..4e579044491 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -113,63 +113,6 @@ pub fn is_token(s: &[u8]) -> bool { }) } -/// Returns whether the language is matched, as defined by -/// [RFC 4647](https://tools.ietf.org/html/rfc4647#section-3.3.2). -pub fn extended_filtering(tag: &str, range: &str) -> bool { - let lang_ranges: Vec<&str> = range.split(',').collect(); - - lang_ranges.iter().any(|&lang_range| { - // step 1 - let range_subtags: Vec<&str> = lang_range.split('\x2d').collect(); - let tag_subtags: Vec<&str> = tag.split('\x2d').collect(); - - let mut range_iter = range_subtags.iter(); - let mut tag_iter = tag_subtags.iter(); - - // step 2 - // Note: [Level-4 spec](https://drafts.csswg.org/selectors/#lang-pseudo) check for wild card - if let (Some(range_subtag), Some(tag_subtag)) = (range_iter.next(), tag_iter.next()) { - if !(range_subtag.eq_ignore_ascii_case(tag_subtag) || range_subtag.eq_ignore_ascii_case("*")) { - return false; - } - } - - let mut current_tag_subtag = tag_iter.next(); - - // step 3 - for range_subtag in range_iter { - // step 3a - if range_subtag.eq_ignore_ascii_case("*") { - continue; - } - match current_tag_subtag.clone() { - Some(tag_subtag) => { - // step 3c - if range_subtag.eq_ignore_ascii_case(tag_subtag) { - current_tag_subtag = tag_iter.next(); - continue; - } else { - // step 3d - if tag_subtag.len() == 1 { - return false; - } else { - // else step 3e - continue with loop - current_tag_subtag = tag_iter.next(); - if current_tag_subtag.is_none() { - return false; - } - } - } - }, - // step 3b - None => { return false; } - } - } - // step 4 - true - }) -} - /// A DOMString. /// -- cgit v1.2.3 From b83afdedc873903028d94f44632eaa6d3fcaf7f0 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 15 Jun 2017 21:58:40 +0200 Subject: Upgrade cssparser to 0.15 --- components/script/dom/bindings/str.rs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 4e579044491..33f4f1bc57f 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -4,6 +4,7 @@ //! The `ByteString` struct. +use cssparser::CompactCowStr; use html5ever::{LocalName, Namespace}; use servo_atoms::Atom; use std::ascii::AsciiExt; @@ -298,6 +299,12 @@ impl<'a> Into> for DOMString { } } +impl<'a> Into> for DOMString { + fn into(self) -> CompactCowStr<'a> { + self.0.into() + } +} + impl Extend for DOMString { fn extend(&mut self, iterable: I) where I: IntoIterator { self.0.extend(iterable) -- cgit v1.2.3 From f511a77ec573e1fcf25350ceddd86c5ddca6be4b Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Wed, 28 Jun 2017 13:50:51 -0700 Subject: Stop using the unstable optin_builtin_traits feature --- components/script/dom/bindings/str.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 33f4f1bc57f..97b58a290e9 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -11,6 +11,7 @@ use std::ascii::AsciiExt; use std::borrow::{Borrow, Cow, ToOwned}; use std::fmt; use std::hash::{Hash, Hasher}; +use std::marker::PhantomData; use std::ops; use std::ops::{Deref, DerefMut}; use std::str; @@ -152,19 +153,17 @@ pub fn is_token(s: &[u8]) -> bool { /// This type is currently `!Send`, in order to help with an independent /// experiment to store `JSString`s rather than Rust `String`s. #[derive(Clone, Debug, Eq, Hash, HeapSizeOf, Ord, PartialEq, PartialOrd)] -pub struct DOMString(String); - -impl !Send for DOMString {} +pub struct DOMString(String, PhantomData<*const ()>); impl DOMString { /// Creates a new `DOMString`. pub fn new() -> DOMString { - DOMString(String::new()) + DOMString(String::new(), PhantomData) } /// Creates a new `DOMString` from a `String`. pub fn from_string(s: String) -> DOMString { - DOMString(s) + DOMString(s, PhantomData) } /// Appends a given string slice onto the end of this String. @@ -197,7 +196,7 @@ impl Borrow for DOMString { impl Default for DOMString { fn default() -> Self { - DOMString(String::new()) + DOMString(String::new(), PhantomData) } } @@ -244,7 +243,7 @@ impl<'a> PartialEq<&'a str> for DOMString { impl From for DOMString { fn from(contents: String) -> DOMString { - DOMString(contents) + DOMString(contents, PhantomData) } } -- cgit v1.2.3 From eb98ae6e044ff6fb5ce3cfc6b39c70d40e9880a9 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 20 Jul 2017 21:03:53 +0200 Subject: Update cssparser to 0.18 https://github.com/servo/rust-cssparser/pull/171 --- components/script/dom/bindings/str.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 97b58a290e9..761acab3068 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -4,7 +4,7 @@ //! The `ByteString` struct. -use cssparser::CompactCowStr; +use cssparser::CowRcStr; use html5ever::{LocalName, Namespace}; use servo_atoms::Atom; use std::ascii::AsciiExt; @@ -298,8 +298,8 @@ impl<'a> Into> for DOMString { } } -impl<'a> Into> for DOMString { - fn into(self) -> CompactCowStr<'a> { +impl<'a> Into> for DOMString { + fn into(self) -> CowRcStr<'a> { self.0.into() } } -- cgit v1.2.3 From 52348f1fccea3e4abc2ad80d001a43f5f51cbdc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Tue, 1 Aug 2017 14:57:55 +0200 Subject: Performance Timeline API --- components/script/dom/bindings/str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 761acab3068..36b104eb262 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -122,7 +122,7 @@ pub fn is_token(s: &[u8]) -> bool { /// /// [idl]: https://heycam.github.io/webidl/#idl-DOMString /// -/// Cenceptually, a DOMString has the same value space as a JavaScript String, +/// Conceptually, a DOMString has the same value space as a JavaScript String, /// i.e., an array of 16-bit *code units* representing UTF-16, potentially with /// unpaired surrogates present (also sometimes called WTF-16). /// -- cgit v1.2.3 From c5fe2351124c673d1dc4d59355a03654b4fcc541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DAVID?= Date: Wed, 23 Aug 2017 14:10:08 +0200 Subject: order derivable traits lists Ignoring : - **generated**.rs - python/tidy/servo_tidy_tests/rust_tidy.rs --- components/script/dom/bindings/str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 36b104eb262..ea0b4f529b0 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -18,7 +18,7 @@ use std::str; use std::str::{Bytes, FromStr}; /// Encapsulates the IDL `ByteString` type. -#[derive(JSTraceable, Clone, Eq, PartialEq, HeapSizeOf, Debug)] +#[derive(Clone, Debug, Eq, HeapSizeOf, JSTraceable, PartialEq)] pub struct ByteString(Vec); impl ByteString { -- cgit v1.2.3 From 16166d66731d7040a91ddbed6ffd05d4fc64c97b Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Fri, 26 May 2017 13:46:13 -0400 Subject: Derive the Default trait for dictionaries containing GC values. --- components/script/dom/bindings/str.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index ea0b4f529b0..b665b64da8a 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -9,6 +9,7 @@ use html5ever::{LocalName, Namespace}; use servo_atoms::Atom; use std::ascii::AsciiExt; use std::borrow::{Borrow, Cow, ToOwned}; +use std::default::Default; use std::fmt; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; @@ -18,7 +19,7 @@ use std::str; use std::str::{Bytes, FromStr}; /// Encapsulates the IDL `ByteString` type. -#[derive(Clone, Debug, Eq, HeapSizeOf, JSTraceable, PartialEq)] +#[derive(Clone, Debug, Default, Eq, HeapSizeOf, JSTraceable, PartialEq)] pub struct ByteString(Vec); impl ByteString { @@ -77,7 +78,7 @@ impl ops::Deref for ByteString { /// A string that is constructed from a UCS-2 buffer by replacing invalid code /// points with the replacement character. -#[derive(Clone, HeapSizeOf)] +#[derive(Clone, Default, HeapSizeOf)] pub struct USVString(pub String); -- cgit v1.2.3 From 4506f0d30cbbb02df32e9c16135ef288ad6b7e2e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 18 Oct 2017 10:42:01 +1100 Subject: Replace all uses of the `heapsize` crate with `malloc_size_of`. Servo currently uses `heapsize`, but Stylo/Gecko use `malloc_size_of`. `malloc_size_of` is better -- it handles various cases that `heapsize` does not -- so this patch changes Servo to use `malloc_size_of`. This patch makes the following changes to the `malloc_size_of` crate. - Adds `MallocSizeOf` trait implementations for numerous types, some built-in (e.g. `VecDeque`), some external and Servo-only (e.g. `string_cache`). - Makes `enclosing_size_of_op` optional, because vanilla jemalloc doesn't support that operation. - For `HashSet`/`HashMap`, falls back to a computed estimate when `enclosing_size_of_op` isn't available. - Adds an extern "C" `malloc_size_of` function that does the actual heap measurement; this is based on the same functions from the `heapsize` crate. This patch makes the following changes elsewhere. - Converts all the uses of `heapsize` to instead use `malloc_size_of`. - Disables the "heapsize"/"heap_size" feature for the external crates that provide it. - Removes the `HeapSizeOf` implementation from `hashglobe`. - Adds `ignore` annotations to a few `Rc`/`Arc`, because `malloc_size_of` doesn't derive those types, unlike `heapsize`. --- components/script/dom/bindings/str.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index b665b64da8a..af33f662ff7 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -19,7 +19,7 @@ use std::str; use std::str::{Bytes, FromStr}; /// Encapsulates the IDL `ByteString` type. -#[derive(Clone, Debug, Default, Eq, HeapSizeOf, JSTraceable, PartialEq)] +#[derive(Clone, Debug, Default, Eq, JSTraceable, MallocSizeOf, PartialEq)] pub struct ByteString(Vec); impl ByteString { @@ -78,7 +78,7 @@ impl ops::Deref for ByteString { /// A string that is constructed from a UCS-2 buffer by replacing invalid code /// points with the replacement character. -#[derive(Clone, Default, HeapSizeOf)] +#[derive(Clone, Default, MallocSizeOf)] pub struct USVString(pub String); @@ -153,7 +153,7 @@ pub fn is_token(s: &[u8]) -> bool { /// /// This type is currently `!Send`, in order to help with an independent /// experiment to store `JSString`s rather than Rust `String`s. -#[derive(Clone, Debug, Eq, Hash, HeapSizeOf, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)] pub struct DOMString(String, PhantomData<*const ()>); impl DOMString { -- cgit v1.2.3 From 9d60333af95adf64f2489e1e51563f0694abdd2a Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Sat, 21 Oct 2017 05:12:04 -0700 Subject: Implement string stripping utilities from the Infra spec --- components/script/dom/bindings/str.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index af33f662ff7..929ff6e20d4 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -186,6 +186,29 @@ impl DOMString { pub fn bytes(&self) -> Bytes { self.0.bytes() } + + /// Removes newline characters according to . + pub fn strip_newlines(&mut self) { + self.0.retain(|c| c != '\r' && c != '\n'); + } + + /// Removes leading and trailing ASCII whitespaces according to + /// . + pub fn strip_leading_and_trailing_ascii_whitespace(&mut self) { + if self.0.len() == 0 { return; } + + let last_non_whitespace = match self.0.rfind(|ref c| !char::is_ascii_whitespace(c)) { + Some(idx) => idx + 1, + None => { + self.0.clear(); + return; + } + }; + let first_non_whitespace = self.0.find(|ref c| !char::is_ascii_whitespace(c)).unwrap(); + + self.0.truncate(last_non_whitespace); + let _ = self.0.splice(0..first_non_whitespace, ""); + } } impl Borrow for DOMString { -- cgit v1.2.3 From 793bebfc0ef5e3dbfbff094ec459198f2bceeaff Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 6 Nov 2017 14:24:03 +0100 Subject: Upgrade to rustc 1.23.0-nightly (02004ef78 2017-11-08) --- components/script/dom/bindings/str.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index af33f662ff7..60b8d6183be 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -7,7 +7,6 @@ use cssparser::CowRcStr; use html5ever::{LocalName, Namespace}; use servo_atoms::Atom; -use std::ascii::AsciiExt; use std::borrow::{Borrow, Cow, ToOwned}; use std::default::Default; use std::fmt; -- cgit v1.2.3 From a999239f28672aed053c9c3db001a2e6a26efa7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20W=C3=B6rner?= Date: Sun, 26 Nov 2017 15:13:02 +0100 Subject: Added time input sanitization: - Implemented is_valid_time_string for DOMString. - Use is_valid_time_string for sanitize_value with time input. - Improved input type change test --- components/script/dom/bindings/str.rs | 71 +++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 3667dddf92d..6601d8e6856 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -208,6 +208,77 @@ impl DOMString { self.0.truncate(last_non_whitespace); let _ = self.0.splice(0..first_non_whitespace, ""); } + + /// Validates this `DOMString` is a time string according to + /// . + pub fn is_valid_time_string(&self) -> bool { + enum State { + HourHigh, + HourLow09, + HourLow03, + MinuteColon, + MinuteHigh, + MinuteLow, + SecondColon, + SecondHigh, + SecondLow, + MilliStop, + MilliHigh, + MilliMiddle, + MilliLow, + Done, + Error, + } + let next_state = |valid: bool, next: State| -> State { if valid { next } else { State::Error } }; + + let state = self.chars().fold(State::HourHigh, |state, c| { + match state { + // Step 1 "HH" + State::HourHigh => { + match c { + '0' | '1' => State::HourLow09, + '2' => State::HourLow03, + _ => State::Error, + } + }, + State::HourLow09 => next_state(c.is_digit(10), State::MinuteColon), + State::HourLow03 => next_state(c.is_digit(4), State::MinuteColon), + + // Step 2 ":" + State::MinuteColon => next_state(c == ':', State::MinuteHigh), + + // Step 3 "mm" + State::MinuteHigh => next_state(c.is_digit(6), State::MinuteLow), + State::MinuteLow => next_state(c.is_digit(10), State::SecondColon), + + // Step 4.1 ":" + State::SecondColon => next_state(c == ':', State::SecondHigh), + // Step 4.2 "ss" + State::SecondHigh => next_state(c.is_digit(6), State::SecondLow), + State::SecondLow => next_state(c.is_digit(10), State::MilliStop), + + // Step 4.3.1 "." + State::MilliStop => next_state(c == '.', State::MilliHigh), + // Step 4.3.2 "SSS" + State::MilliHigh => next_state(c.is_digit(6), State::MilliMiddle), + State::MilliMiddle => next_state(c.is_digit(10), State::MilliLow), + State::MilliLow => next_state(c.is_digit(10), State::Done), + + _ => State::Error, + } + }); + + match state { + State::Done | + // Step 4 (optional) + State::SecondColon | + // Step 4.3 (optional) + State::MilliStop | + // Step 4.3.2 (only 1 digit required) + State::MilliMiddle | State::MilliLow => true, + _ => false + } + } } impl Borrow for DOMString { -- cgit v1.2.3 From 927fd1d0444d519f514a58407395ea8d5df295a3 Mon Sep 17 00:00:00 2001 From: tigercosmos Date: Sat, 25 Nov 2017 22:57:50 +0800 Subject: implement "Date type inputs", "Month type inputs" --- components/script/dom/bindings/str.rs | 101 ++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 6601d8e6856..596b2db14b2 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(()) + } +} -- cgit v1.2.3 From 54c6028033d07d9104f58beb3d92bcc819600d93 Mon Sep 17 00:00:00 2001 From: tigercosmos Date: Thu, 14 Dec 2017 21:23:06 +0800 Subject: implement valid week string --- components/script/dom/bindings/str.rs | 67 ++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 596b2db14b2..83c438a26e7 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -4,6 +4,8 @@ //! The `ByteString` struct. +use chrono::{Datelike, TimeZone}; +use chrono::prelude::{Weekday, Utc}; use cssparser::CowRcStr; use html5ever::{LocalName, Namespace}; use servo_atoms::Atom; @@ -293,6 +295,13 @@ impl DOMString { pub fn is_valid_month_string(&self) -> bool { parse_month_string(&*self.0).is_ok() } + + /// A valid week string should be like {YYYY}-W{WW}, such as "2017-W52" + /// YYYY must be four or more digits, WW both must be two digits + /// https://html.spec.whatwg.org/multipage/#valid-week-string + pub fn is_valid_week_string(&self) -> bool { + parse_week_string(&*self.0).is_ok() + } } impl Borrow for DOMString { @@ -445,6 +454,48 @@ fn parse_date_string(value: &str) -> Result<(u32, u32, u32), ()> { Ok((year_int, month_int, day_int)) } +/// https://html.spec.whatwg.org/multipage/#parse-a-week-string +fn parse_week_string(value: &str) -> Result<(u32, u32), ()> { + // Step 1, 2, 3 + let mut iterator = value.split('-'); + let year = iterator.next().ok_or(())?; + + // Step 4 + let year_int = year.parse::().map_err(|_| ())?; + if year.len() < 4 || year_int == 0 { + return Err(()); + } + + // Step 5, 6 + let week = iterator.next().ok_or(())?; + let (week_first, week_last) = week.split_at(1); + if week_first != "W" { + return Err(()); + } + + // Step 7 + let week_int = week_last.parse::().map_err(|_| ())?; + if week_last.len() != 2 { + return Err(()); + } + + // Step 8 + let max_week = max_week_in_year(year_int); + + // Step 9 + if week_int < 1 || week_int > max_week { + return Err(()); + } + + // Step 10 + if iterator.next().is_some() { + return Err(()); + } + + // Step 11 + Ok((year_int, week_int)) +} + /// https://html.spec.whatwg.org/multipage/#parse-a-month-component fn parse_month_component(value: &str) -> Result<(u32, u32), ()> { // Step 3 @@ -495,7 +546,7 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result { 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) { + if is_leap_year(year_num) { Ok(29) } else { Ok(28) @@ -504,3 +555,17 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result { _ => Err(()) } } + +// https://html.spec.whatwg.org/multipage/#week-number-of-the-last-day +fn max_week_in_year(year: u32) -> u32 { + match Utc.ymd(year as i32, 1, 1).weekday() { + Weekday::Thu => 53, + Weekday::Wed if is_leap_year(year) => 53, + _ => 52 + } +} + +#[inline] +fn is_leap_year(year: u32) -> bool { + year % 400 == 0 || (year % 4 == 0 && year % 100 != 0) +} -- cgit v1.2.3 From b43424111e9a901a5837718e2d7e653dbe4a8ed2 Mon Sep 17 00:00:00 2001 From: tigercosmos Date: Tue, 19 Dec 2017 08:51:05 +0800 Subject: implement valid Date time Local input --- components/script/dom/bindings/str.rs | 92 +++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 83c438a26e7..9e7c01ed5ca 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -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 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::().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::().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::().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 { match month_num { 1|3|5|7|8|10|12 => Ok(31), -- cgit v1.2.3 From 5b6e8215591c835dfb7092af25676d8ced344ebe Mon Sep 17 00:00:00 2001 From: Nathan Date: Mon, 8 Jan 2018 22:39:39 -0600 Subject: input type=number validations --- components/script/dom/bindings/str.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 9e7c01ed5ca..eaabc29806c 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -303,6 +303,16 @@ impl DOMString { parse_week_string(&*self.0).is_ok() } + /// A valid number is the same as what rust considers to be valid, + /// except for +1., NaN, and Infinity. + /// https://html.spec.whatwg.org/multipage/#valid-floating-point-number + pub fn is_valid_number_string(&self) -> bool { + let input = &self.0; + input.parse::().ok().map_or(false, |val| { + !(val.is_infinite() || val.is_nan() || input.ends_with(".") || input.starts_with("+")) + }) + } + /// 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 -- cgit v1.2.3 From b29230bd76ea30ab42fab724fe72a18c396d5e49 Mon Sep 17 00:00:00 2001 From: tigercosmos Date: Sun, 14 Jan 2018 00:01:47 +0800 Subject: implement range input sanitization --- components/script/dom/bindings/str.rs | 45 +++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index eaabc29806c..4520fd15a6c 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -286,31 +286,37 @@ impl DOMString { /// 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() + 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() + parse_month_string(&self.0).is_ok() } /// A valid week string should be like {YYYY}-W{WW}, such as "2017-W52" /// YYYY must be four or more digits, WW both must be two digits /// https://html.spec.whatwg.org/multipage/#valid-week-string pub fn is_valid_week_string(&self) -> bool { - parse_week_string(&*self.0).is_ok() + parse_week_string(&self.0).is_ok() } - /// A valid number is the same as what rust considers to be valid, - /// except for +1., NaN, and Infinity. /// https://html.spec.whatwg.org/multipage/#valid-floating-point-number - pub fn is_valid_number_string(&self) -> bool { - let input = &self.0; - input.parse::().ok().map_or(false, |val| { - !(val.is_infinite() || val.is_nan() || input.ends_with(".") || input.starts_with("+")) - }) + pub fn is_valid_floating_point_number_string(&self) -> bool { + // for the case that `parse_floating_point_number` cannot handle + if self.0.contains(" ") { + return false; + } + parse_floating_point_number(&self.0).is_ok() + } + + /// https://html.spec.whatwg.org/multipage/#best-representation-of-the-number-as-a-floating-point-number + pub fn set_best_representation_of_the_floating_point_number(&mut self) { + if let Ok(val) = parse_floating_point_number(&self.0) { + self.0 = val.to_string(); + } } /// A valid normalized local date and time string should be "{date}T{time}" @@ -617,7 +623,7 @@ fn parse_time_component(value: &str) -> Result<(u32, u32, f32), ()> { Ok((hour_int, minute_int, second_float)) } -// https://html.spec.whatwg.org/multipage/#parse-a-local-date-and-time-string +/// 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') { @@ -658,7 +664,7 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result { } } -// https://html.spec.whatwg.org/multipage/#week-number-of-the-last-day +/// https://html.spec.whatwg.org/multipage/#week-number-of-the-last-day fn max_week_in_year(year: u32) -> u32 { match Utc.ymd(year as i32, 1, 1).weekday() { Weekday::Thu => 53, @@ -671,3 +677,18 @@ fn max_week_in_year(year: u32) -> u32 { fn is_leap_year(year: u32) -> bool { year % 400 == 0 || (year % 4 == 0 && year % 100 != 0) } + +/// https://html.spec.whatwg.org/multipage/#rules-for-parsing-floating-point-number-values +fn parse_floating_point_number(input: &str) -> Result { + match input.trim().parse::() { + Ok(val) if !( + // A valid number is the same as what rust considers to be valid, + // except for +1., NaN, and Infinity. + val.is_infinite() || val.is_nan() || input.ends_with(".") || input.starts_with("+") + ) => { + // TODO(#19773): need consider `min`, `max`, `step`, when they are implemented + Ok(val.round()) + }, + _ => Err(()) + } +} -- cgit v1.2.3 From 3d6614e3145f0955be55bf5656aa805fedef639c Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 29 Mar 2018 16:25:53 +0200 Subject: Upgrade to rustc 1.27.0-nightly (056f589fb 2018-04-07) --- components/script/dom/bindings/str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 4520fd15a6c..c4cc5f51d21 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -208,7 +208,7 @@ impl DOMString { let first_non_whitespace = self.0.find(|ref c| !char::is_ascii_whitespace(c)).unwrap(); self.0.truncate(last_non_whitespace); - let _ = self.0.splice(0..first_non_whitespace, ""); + let _ = self.0.replace_range(0..first_non_whitespace, ""); } /// Validates this `DOMString` is a time string according to -- cgit v1.2.3 From c37a345dc9f4dda6ea29c42f96f6c7201c42cbac Mon Sep 17 00:00:00 2001 From: chansuke Date: Tue, 18 Sep 2018 23:24:15 +0900 Subject: Format script component --- components/script/dom/bindings/str.rs | 91 +++++++++++++++++------------------ 1 file changed, 45 insertions(+), 46 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index c4cc5f51d21..e52cf7755a3 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -82,7 +82,6 @@ impl ops::Deref for ByteString { #[derive(Clone, Default, MallocSizeOf)] pub struct USVString(pub String); - /// Returns whether `s` is a `token`, as defined by /// [RFC 2616](http://tools.ietf.org/html/rfc2616#page-17). pub fn is_token(s: &[u8]) -> bool { @@ -93,31 +92,14 @@ pub fn is_token(s: &[u8]) -> bool { // http://tools.ietf.org/html/rfc2616#section-2.2 match x { 0...31 | 127 => false, // CTLs - 40 | - 41 | - 60 | - 62 | - 64 | - 44 | - 59 | - 58 | - 92 | - 34 | - 47 | - 91 | - 93 | - 63 | - 61 | - 123 | - 125 | - 32 => false, // separators + 40 | 41 | 60 | 62 | 64 | 44 | 59 | 58 | 92 | 34 | 47 | 91 | 93 | 63 | 61 | 123 | + 125 | 32 => false, // separators x if x > 127 => false, // non-CHARs _ => true, } }) } - /// A DOMString. /// /// This type corresponds to the [`DOMString`](idl) type in WebIDL. @@ -196,14 +178,16 @@ impl DOMString { /// Removes leading and trailing ASCII whitespaces according to /// . pub fn strip_leading_and_trailing_ascii_whitespace(&mut self) { - if self.0.len() == 0 { return; } + if self.0.len() == 0 { + return; + } let last_non_whitespace = match self.0.rfind(|ref c| !char::is_ascii_whitespace(c)) { Some(idx) => idx + 1, None => { self.0.clear(); return; - } + }, }; let first_non_whitespace = self.0.find(|ref c| !char::is_ascii_whitespace(c)).unwrap(); @@ -231,17 +215,21 @@ impl DOMString { Done, Error, } - let next_state = |valid: bool, next: State| -> State { if valid { next } else { State::Error } }; + let next_state = |valid: bool, next: State| -> State { + if valid { + next + } else { + State::Error + } + }; let state = self.chars().fold(State::HourHigh, |state, c| { match state { // Step 1 "HH" - State::HourHigh => { - match c { - '0' | '1' => State::HourLow09, - '2' => State::HourLow03, - _ => State::Error, - } + State::HourHigh => match c { + '0' | '1' => State::HourLow09, + '2' => State::HourLow03, + _ => State::Error, }, State::HourLow09 => next_state(c.is_digit(10), State::MinuteColon), State::HourLow03 => next_state(c.is_digit(4), State::MinuteColon), @@ -323,15 +311,21 @@ impl DOMString { /// 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)?; + 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); + 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); + self.0 = format!( + "{:04}-{:02}-{:02}T{:02}:{:02}:{}", + year, month, day, hour, minute, second + ); } Ok(()) } - } impl Borrow for DOMString { @@ -452,7 +446,10 @@ impl<'a> Into> for DOMString { } impl Extend for DOMString { - fn extend(&mut self, iterable: I) where I: IntoIterator { + fn extend(&mut self, iterable: I) + where + I: IntoIterator, + { self.0.extend(iterable) } } @@ -541,7 +538,7 @@ fn parse_month_component(value: &str) -> Result<(u32, u32), ()> { // Step 4, 5 let month_int = month.parse::().map_err(|_| ())?; - if month.len() != 2 || month_int > 12 || month_int < 1 { + if month.len() != 2 || month_int > 12 || month_int < 1 { return Err(()); } @@ -611,12 +608,12 @@ fn parse_time_component(value: &str) -> Result<(u32, u32, f32), ()> { return Err(()); } }, - None => {} + None => {}, } second.parse::().map_err(|_| ())? }, - None => 0.0 + None => 0.0, }; // Step 8 @@ -624,7 +621,7 @@ fn parse_time_component(value: &str) -> Result<(u32, u32, f32), ()> { } /// 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)), ()> { +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') @@ -651,8 +648,8 @@ fn parse_local_date_and_time_string(value: &str) -> Result<((u32, u32, u32), (u 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), + 1 | 3 | 5 | 7 | 8 | 10 | 12 => Ok(31), + 4 | 6 | 9 | 11 => Ok(30), 2 => { if is_leap_year(year_num) { Ok(29) @@ -660,7 +657,7 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result { Ok(28) } }, - _ => Err(()) + _ => Err(()), } } @@ -669,7 +666,7 @@ fn max_week_in_year(year: u32) -> u32 { match Utc.ymd(year as i32, 1, 1).weekday() { Weekday::Thu => 53, Weekday::Wed if is_leap_year(year) => 53, - _ => 52 + _ => 52, } } @@ -681,14 +678,16 @@ fn is_leap_year(year: u32) -> bool { /// https://html.spec.whatwg.org/multipage/#rules-for-parsing-floating-point-number-values fn parse_floating_point_number(input: &str) -> Result { match input.trim().parse::() { - Ok(val) if !( + Ok(val) + if !( // A valid number is the same as what rust considers to be valid, // except for +1., NaN, and Infinity. val.is_infinite() || val.is_nan() || input.ends_with(".") || input.starts_with("+") - ) => { + ) => + { // TODO(#19773): need consider `min`, `max`, `step`, when they are implemented Ok(val.round()) - }, - _ => Err(()) + } + _ => Err(()), } } -- cgit v1.2.3 From 9e92eb205a2a12fe0be883e42cb7f82deebc9031 Mon Sep 17 00:00:00 2001 From: Pyfisch Date: Tue, 6 Nov 2018 20:38:02 +0100 Subject: Reorder imports --- components/script/dom/bindings/str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index e52cf7755a3..9f038026562 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -4,8 +4,8 @@ //! The `ByteString` struct. +use chrono::prelude::{Utc, Weekday}; use chrono::{Datelike, TimeZone}; -use chrono::prelude::{Weekday, Utc}; use cssparser::CowRcStr; use html5ever::{LocalName, Namespace}; use servo_atoms::Atom; -- cgit v1.2.3 From 1f99bf4631cc0b5bbd2c4407c98bcd547a63905e Mon Sep 17 00:00:00 2001 From: Jim Berlage Date: Wed, 17 Oct 2018 13:54:55 -0500 Subject: Fixes panic on DOMString::strip_leading_and_trailing_ascii_whitespace --- components/script/dom/bindings/str.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 9f038026562..251a03b2d66 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -182,16 +182,16 @@ impl DOMString { return; } - let last_non_whitespace = match self.0.rfind(|ref c| !char::is_ascii_whitespace(c)) { - Some(idx) => idx + 1, - None => { - self.0.clear(); - return; - }, - }; - let first_non_whitespace = self.0.find(|ref c| !char::is_ascii_whitespace(c)).unwrap(); + let trailing_whitespace_len = self + .0 + .trim_end_matches(|ref c| char::is_ascii_whitespace(c)) + .len(); + self.0.truncate(trailing_whitespace_len); + if self.0.is_empty() { + return; + } - self.0.truncate(last_non_whitespace); + let first_non_whitespace = self.0.find(|ref c| !char::is_ascii_whitespace(c)).unwrap(); let _ = self.0.replace_range(0..first_non_whitespace, ""); } -- cgit v1.2.3 From a1a14459c141afc6ac6771b8a6c9ca374537edf2 Mon Sep 17 00:00:00 2001 From: Jan Andre Ikenmeyer Date: Mon, 19 Nov 2018 14:47:12 +0100 Subject: Update MPL license to https (part 3) --- components/script/dom/bindings/str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 251a03b2d66..28a429f846c 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -1,6 +1,6 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ //! The `ByteString` struct. -- cgit v1.2.3 From c46508e497e503c8fd42deb26aa536060334a9c9 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Fri, 14 Dec 2018 03:59:03 +0000 Subject: Update src/href attributes to be a USVString The following IDLs have the src/href attributes typed as a DOMString while in the spec the attribute has been updated to be a USVString: - HTMLIFrameElement - HTMLImageElement - HTMLInputElement - HTMLLinkElement - HTMLMediaElement - HTMLScriptElement --- components/script/dom/bindings/str.rs | 56 ++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 28a429f846c..3142f011c9b 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -79,9 +79,63 @@ impl ops::Deref for ByteString { /// A string that is constructed from a UCS-2 buffer by replacing invalid code /// points with the replacement character. -#[derive(Clone, Default, MallocSizeOf)] +#[derive(Clone, Default, Eq, MallocSizeOf, Ord, PartialEq, PartialOrd)] pub struct USVString(pub String); +impl Borrow for USVString { + #[inline] + fn borrow(&self) -> &str { + &self.0 + } +} + +impl Deref for USVString { + type Target = str; + + #[inline] + fn deref(&self) -> &str { + &self.0 + } +} + +impl DerefMut for USVString { + #[inline] + fn deref_mut(&mut self) -> &mut str { + &mut self.0 + } +} + +impl AsRef for USVString { + fn as_ref(&self) -> &str { + &self.0 + } +} + +impl fmt::Display for USVString { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +impl PartialEq for USVString { + fn eq(&self, other: &str) -> bool { + &**self == other + } +} + +impl<'a> PartialEq<&'a str> for USVString { + fn eq(&self, other: &&'a str) -> bool { + &**self == *other + } +} + +impl From for USVString { + fn from(contents: String) -> USVString { + USVString(contents) + } +} + /// Returns whether `s` is a `token`, as defined by /// [RFC 2616](http://tools.ietf.org/html/rfc2616#page-17). pub fn is_token(s: &[u8]) -> bool { -- cgit v1.2.3 From be69f9c3e6a6f5efb5ba1edd50955cb12c111bf8 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 14 Dec 2018 08:31:30 +0100 Subject: Rustfmt has changed its default style :/ --- components/script/dom/bindings/str.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 3142f011c9b..dfeedc636d6 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -734,10 +734,10 @@ fn parse_floating_point_number(input: &str) -> Result { match input.trim().parse::() { Ok(val) if !( - // A valid number is the same as what rust considers to be valid, - // except for +1., NaN, and Infinity. - val.is_infinite() || val.is_nan() || input.ends_with(".") || input.starts_with("+") - ) => + // A valid number is the same as what rust considers to be valid, + // except for +1., NaN, and Infinity. + val.is_infinite() || val.is_nan() || input.ends_with(".") || input.starts_with("+") + ) => { // TODO(#19773): need consider `min`, `max`, `step`, when they are implemented Ok(val.round()) -- cgit v1.2.3 From 8b6ed3d1823876fa7e3c5ff6b1a9036aa22a72f4 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 2 Jun 2019 07:10:40 +0200 Subject: Remove unused code from script* crates --- components/script/dom/bindings/str.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index dfeedc636d6..e08159bc1e2 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -17,7 +17,7 @@ use std::marker::PhantomData; use std::ops; use std::ops::{Deref, DerefMut}; use std::str; -use std::str::{Bytes, FromStr}; +use std::str::FromStr; /// Encapsulates the IDL `ByteString` type. #[derive(Clone, Debug, Default, Eq, JSTraceable, MallocSizeOf, PartialEq)] @@ -40,11 +40,6 @@ impl ByteString { self.0.len() } - /// Compare `self` to `other`, matching A–Z and a–z as equal. - pub fn eq_ignore_case(&self, other: &ByteString) -> bool { - self.0.eq_ignore_ascii_case(&other.0) - } - /// Returns `self` with A–Z replaced by a–z. pub fn to_lower(&self) -> ByteString { ByteString::new(self.0.to_ascii_lowercase()) @@ -219,11 +214,6 @@ impl DOMString { self.0.truncate(new_len); } - /// An iterator over the bytes of this `DOMString`. - pub fn bytes(&self) -> Bytes { - self.0.bytes() - } - /// Removes newline characters according to . pub fn strip_newlines(&mut self) { self.0.retain(|c| c != '\r' && c != '\n'); -- cgit v1.2.3 From 1d38bc041967b88838ed7b006aab9908e2f24474 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 19 Jun 2019 16:07:13 +0200 Subject: Fix some new warnings --- components/script/dom/bindings/str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index e08159bc1e2..ad4ce8bc621 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -140,7 +140,7 @@ pub fn is_token(s: &[u8]) -> bool { s.iter().all(|&x| { // http://tools.ietf.org/html/rfc2616#section-2.2 match x { - 0...31 | 127 => false, // CTLs + 0..=31 | 127 => false, // CTLs 40 | 41 | 60 | 62 | 64 | 44 | 59 | 58 | 92 | 34 | 47 | 91 | 93 | 63 | 61 | 123 | 125 | 32 => false, // separators x if x > 127 => false, // non-CHARs -- cgit v1.2.3 From b697621b05d5c0b741d377637cb9c16ef31986b9 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Tue, 15 Oct 2019 17:14:00 +0900 Subject: Support WebIDL `record<>` --- components/script/dom/bindings/str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index ad4ce8bc621..38091fcf19e 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -74,7 +74,7 @@ impl ops::Deref for ByteString { /// A string that is constructed from a UCS-2 buffer by replacing invalid code /// points with the replacement character. -#[derive(Clone, Default, Eq, MallocSizeOf, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Default, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)] pub struct USVString(pub String); impl Borrow for USVString { -- cgit v1.2.3 From 576f51f598982a608caf52b9aa74eb397bd762ec Mon Sep 17 00:00:00 2001 From: glowe Date: Sat, 30 Nov 2019 23:29:09 -0500 Subject: Add DOMString floating point string test and fix Fixes an issue where DOMString::is_valid_floating_point_number_string was returning true for strings that began with whitespace characters- TAB, LF, FF, or CR. Also added a unit test to cover this since the corresponding web-platform-tests are incomplete. --- components/script/dom/bindings/str.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 38091fcf19e..2b4830dccfc 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -3,11 +3,11 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ //! The `ByteString` struct. - use chrono::prelude::{Utc, Weekday}; use chrono::{Datelike, TimeZone}; use cssparser::CowRcStr; use html5ever::{LocalName, Namespace}; +use regex::Regex; use servo_atoms::Atom; use std::borrow::{Borrow, Cow, ToOwned}; use std::default::Default; @@ -337,11 +337,11 @@ impl DOMString { /// https://html.spec.whatwg.org/multipage/#valid-floating-point-number pub fn is_valid_floating_point_number_string(&self) -> bool { - // for the case that `parse_floating_point_number` cannot handle - if self.0.contains(" ") { - return false; + lazy_static! { + static ref RE: Regex = + Regex::new(r"^-?(?:\d+\.\d+|\d+|\.\d+)(?:(e|E)(\+|\-)?\d+)?$").unwrap(); } - parse_floating_point_number(&self.0).is_ok() + RE.is_match(&self.0) && parse_floating_point_number(&self.0).is_ok() } /// https://html.spec.whatwg.org/multipage/#best-representation-of-the-number-as-a-floating-point-number -- cgit v1.2.3 From 87e86c81b98f7434711897b94606faba25b1dc5d Mon Sep 17 00:00:00 2001 From: Patrick Shaughnessy Date: Fri, 27 Dec 2019 18:05:48 -0500 Subject: stepUp, stepDown, valueAsNumber, valueAsDate, and list work and have tests --- components/script/dom/bindings/str.rs | 283 +++++++++++++++++++--------------- 1 file changed, 156 insertions(+), 127 deletions(-) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 2b4830dccfc..67ba6f34b3d 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -294,7 +294,7 @@ impl DOMString { // Step 4.3.1 "." State::MilliStop => next_state(c == '.', State::MilliHigh), // Step 4.3.2 "SSS" - State::MilliHigh => next_state(c.is_digit(6), State::MilliMiddle), + State::MilliHigh => next_state(c.is_digit(10), State::MilliMiddle), State::MilliMiddle => next_state(c.is_digit(10), State::MilliLow), State::MilliLow => next_state(c.is_digit(10), State::Done), @@ -318,21 +318,108 @@ impl DOMString { /// 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() + self.parse_date_string().is_ok() + } + + /// https://html.spec.whatwg.org/multipage/#parse-a-date-string + pub fn parse_date_string(&self) -> Result<(i32, u32, u32), ()> { + let value = &self.0; + // 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-time-string + pub fn parse_time_string(&self) -> Result<(u32, u32, f64), ()> { + let value = &self.0; + // Step 1, 2, 3 + let (hour_int, minute_int, second_float) = parse_time_component(value)?; + + // Step 4 + if value.split(':').nth(3).is_some() { + return Err(()); + } + + // Step 5, 6 + Ok((hour_int, minute_int, second_float)) } /// 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() + self.parse_month_string().is_ok() + } + + /// https://html.spec.whatwg.org/multipage/#parse-a-month-string + pub fn parse_month_string(&self) -> Result<(i32, u32), ()> { + let value = &self; + // 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)) } /// A valid week string should be like {YYYY}-W{WW}, such as "2017-W52" /// YYYY must be four or more digits, WW both must be two digits /// https://html.spec.whatwg.org/multipage/#valid-week-string pub fn is_valid_week_string(&self) -> bool { - parse_week_string(&self.0).is_ok() + self.parse_week_string().is_ok() + } + + /// https://html.spec.whatwg.org/multipage/#parse-a-week-string + pub fn parse_week_string(&self) -> Result<(i32, u32), ()> { + let value = &self.0; + // Step 1, 2, 3 + let mut iterator = value.split('-'); + let year = iterator.next().ok_or(())?; + + // Step 4 + let year_int = year.parse::().map_err(|_| ())?; + if year.len() < 4 || year_int == 0 { + return Err(()); + } + + // Step 5, 6 + let week = iterator.next().ok_or(())?; + let (week_first, week_last) = week.split_at(1); + if week_first != "W" { + return Err(()); + } + + // Step 7 + let week_int = week_last.parse::().map_err(|_| ())?; + if week_last.len() != 2 { + return Err(()); + } + + // Step 8 + let max_week = max_week_in_year(year_int); + + // Step 9 + if week_int < 1 || week_int > max_week { + return Err(()); + } + + // Step 10 + if iterator.next().is_some() { + return Err(()); + } + + // Step 11 + Ok((year_int, week_int)) } /// https://html.spec.whatwg.org/multipage/#valid-floating-point-number @@ -341,12 +428,37 @@ impl DOMString { static ref RE: Regex = Regex::new(r"^-?(?:\d+\.\d+|\d+|\.\d+)(?:(e|E)(\+|\-)?\d+)?$").unwrap(); } - RE.is_match(&self.0) && parse_floating_point_number(&self.0).is_ok() + RE.is_match(&self.0) && self.parse_floating_point_number().is_ok() + } + + /// https://html.spec.whatwg.org/multipage/#rules-for-parsing-floating-point-number-values + pub fn parse_floating_point_number(&self) -> Result { + // Steps 15-16 are telling us things about IEEE rounding modes + // for floating-point significands; this code assumes the Rust + // compiler already matches them in any cases where + // that actually matters. They are not + // related to f64::round(), which is for rounding to integers. + let input = &self.0; + match input.trim().parse::() { + Ok(val) + if !( + // A valid number is the same as what rust considers to be valid, + // except for +1., NaN, and Infinity. + val.is_infinite() || + val.is_nan() || + input.ends_with(".") || + input.starts_with("+") + ) => + { + Ok(val) + }, + _ => Err(()), + } } /// https://html.spec.whatwg.org/multipage/#best-representation-of-the-number-as-a-floating-point-number pub fn set_best_representation_of_the_floating_point_number(&mut self) { - if let Ok(val) = parse_floating_point_number(&self.0) { + if let Ok(val) = self.parse_floating_point_number() { self.0 = val.to_string(); } } @@ -356,7 +468,7 @@ impl DOMString { /// 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)?; + self.parse_local_date_and_time_string()?; if second == 0.0 { self.0 = format!( "{:04}-{:02}-{:02}T{:02}:{:02}", @@ -370,6 +482,35 @@ impl DOMString { } Ok(()) } + + /// https://html.spec.whatwg.org/multipage/#parse-a-local-date-and-time-string + pub fn parse_local_date_and_time_string( + &self, + ) -> Result<((i32, u32, u32), (u32, u32, f64)), ()> { + let value = &self; + // 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)) + } } impl Borrow for DOMString { @@ -498,84 +639,15 @@ impl Extend for DOMString { } } -/// 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-week-string -fn parse_week_string(value: &str) -> Result<(u32, u32), ()> { - // Step 1, 2, 3 - let mut iterator = value.split('-'); - let year = iterator.next().ok_or(())?; - - // Step 4 - let year_int = year.parse::().map_err(|_| ())?; - if year.len() < 4 || year_int == 0 { - return Err(()); - } - - // Step 5, 6 - let week = iterator.next().ok_or(())?; - let (week_first, week_last) = week.split_at(1); - if week_first != "W" { - return Err(()); - } - - // Step 7 - let week_int = week_last.parse::().map_err(|_| ())?; - if week_last.len() != 2 { - return Err(()); - } - - // Step 8 - let max_week = max_week_in_year(year_int); - - // Step 9 - if week_int < 1 || week_int > max_week { - return Err(()); - } - - // Step 10 - if iterator.next().is_some() { - return Err(()); - } - - // Step 11 - Ok((year_int, week_int)) -} - /// https://html.spec.whatwg.org/multipage/#parse-a-month-component -fn parse_month_component(value: &str) -> Result<(u32, u32), ()> { +fn parse_month_component(value: &str) -> Result<(i32, 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(|_| ())?; + let year_int = year.parse::().map_err(|_| ())?; if year.len() < 4 || year_int == 0 { return Err(()); } @@ -591,7 +663,7 @@ fn parse_month_component(value: &str) -> Result<(u32, u32), ()> { } /// https://html.spec.whatwg.org/multipage/#parse-a-date-component -fn parse_date_component(value: &str) -> Result<(u32, u32, u32), ()> { +fn parse_date_component(value: &str) -> Result<(i32, u32, u32), ()> { // Step 1 let (year_int, month_int) = parse_month_component(value)?; @@ -613,7 +685,7 @@ fn parse_date_component(value: &str) -> Result<(u32, u32, u32), ()> { } /// https://html.spec.whatwg.org/multipage/#parse-a-time-component -fn parse_time_component(value: &str) -> Result<(u32, u32, f32), ()> { +fn parse_time_component(value: &str) -> Result<(u32, u32, f64), ()> { // Step 1 let mut iterator = value.split(':'); let hour = iterator.next().ok_or(())?; @@ -655,7 +727,7 @@ fn parse_time_component(value: &str) -> Result<(u32, u32, f32), ()> { None => {}, } - second.parse::().map_err(|_| ())? + second.parse::().map_err(|_| ())? }, None => 0.0, }; @@ -664,33 +736,7 @@ fn parse_time_component(value: &str) -> Result<(u32, u32, f32), ()> { 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 { +fn max_day_in_month(year_num: i32, month_num: u32) -> Result { match month_num { 1 | 3 | 5 | 7 | 8 | 10 | 12 => Ok(31), 4 | 6 | 9 | 11 => Ok(30), @@ -706,7 +752,7 @@ fn max_day_in_month(year_num: u32, month_num: u32) -> Result { } /// https://html.spec.whatwg.org/multipage/#week-number-of-the-last-day -fn max_week_in_year(year: u32) -> u32 { +fn max_week_in_year(year: i32) -> u32 { match Utc.ymd(year as i32, 1, 1).weekday() { Weekday::Thu => 53, Weekday::Wed if is_leap_year(year) => 53, @@ -715,23 +761,6 @@ fn max_week_in_year(year: u32) -> u32 { } #[inline] -fn is_leap_year(year: u32) -> bool { +fn is_leap_year(year: i32) -> bool { year % 400 == 0 || (year % 4 == 0 && year % 100 != 0) } - -/// https://html.spec.whatwg.org/multipage/#rules-for-parsing-floating-point-number-values -fn parse_floating_point_number(input: &str) -> Result { - match input.trim().parse::() { - Ok(val) - if !( - // A valid number is the same as what rust considers to be valid, - // except for +1., NaN, and Infinity. - val.is_infinite() || val.is_nan() || input.ends_with(".") || input.starts_with("+") - ) => - { - // TODO(#19773): need consider `min`, `max`, `step`, when they are implemented - Ok(val.round()) - } - _ => Err(()), - } -} -- cgit v1.2.3 From 6dc8f67f8f074bcb93e85df65daf59ebe967b170 Mon Sep 17 00:00:00 2001 From: Patrick Shaughnessy Date: Sat, 11 Jan 2020 14:19:37 -0500 Subject: Make sure input value=12:30:01 doesn't turn into 12:30:1 --- components/script/dom/bindings/str.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 67ba6f34b3d..986554206b6 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -474,7 +474,15 @@ impl DOMString { "{:04}-{:02}-{:02}T{:02}:{:02}", year, month, day, hour, minute ); + } else if second < 10.0 { + // we need exactly one leading zero on the seconds, + // whatever their total string length might be + self.0 = format!( + "{:04}-{:02}-{:02}T{:02}:{:02}:0{}", + year, month, day, hour, minute, second + ); } else { + // we need no leading zeroes on the seconds self.0 = format!( "{:04}-{:02}-{:02}T{:02}:{:02}:{}", year, month, day, hour, minute, second -- cgit v1.2.3 From 779552ee7ddbbde1055c7202e16b9a13c3961988 Mon Sep 17 00:00:00 2001 From: teapotd Date: Wed, 1 Apr 2020 11:08:02 +0200 Subject: Form constraints validation --- components/script/dom/bindings/str.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'components/script/dom/bindings/str.rs') diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 986554206b6..0905c157143 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -519,6 +519,28 @@ impl DOMString { // Step 7, 8, 9 Ok((date_tuple, time_tuple)) } + + /// https://html.spec.whatwg.org/multipage/#valid-e-mail-address + pub fn is_valid_email_address_string(&self) -> bool { + lazy_static! { + static ref RE: Regex = Regex::new(concat!( + r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?", + r"(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$" + )) + .unwrap(); + } + RE.is_match(&self.0) + } + + /// https://html.spec.whatwg.org/multipage/#valid-simple-colour + pub fn is_valid_simple_color_string(&self) -> bool { + let mut chars = self.0.chars(); + if self.0.len() == 7 && chars.next() == Some('#') { + chars.all(|c| c.is_digit(16)) + } else { + false + } + } } impl Borrow for DOMString { -- cgit v1.2.3