diff options
Diffstat (limited to 'components')
58 files changed, 519 insertions, 490 deletions
diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml index 0c376db0d2d..836e959ef8a 100644 --- a/components/canvas/Cargo.toml +++ b/components/canvas/Cargo.toml @@ -12,7 +12,7 @@ path = "lib.rs" [dependencies] azure = {git = "https://github.com/servo/rust-azure"} canvas_traits = {path = "../canvas_traits"} -cssparser = "0.17.0" +cssparser = "0.18" euclid = "0.15" gleam = "0.4" ipc-channel = "0.8" diff --git a/components/canvas_traits/Cargo.toml b/components/canvas_traits/Cargo.toml index e939ca3f50c..6b233c27a9c 100644 --- a/components/canvas_traits/Cargo.toml +++ b/components/canvas_traits/Cargo.toml @@ -10,7 +10,7 @@ name = "canvas_traits" path = "lib.rs" [dependencies] -cssparser = "0.17.0" +cssparser = "0.18" euclid = "0.15" heapsize = "0.4" heapsize_derive = "0.1" diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index b183f804e95..0a6389aebd5 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -34,7 +34,7 @@ byteorder = "1.0" canvas_traits = {path = "../canvas_traits"} caseless = "0.1.0" cookie = "0.6" -cssparser = "0.17.0" +cssparser = "0.18" deny_public_fields = {path = "../deny_public_fields"} devtools_traits = {path = "../devtools_traits"} dom_struct = {path = "../dom_struct"} 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<Cow<'a, str>> for DOMString { } } -impl<'a> Into<CompactCowStr<'a>> for DOMString { - fn into(self) -> CompactCowStr<'a> { +impl<'a> Into<CowRcStr<'a>> for DOMString { + fn into(self) -> CowRcStr<'a> { self.0.into() } } diff --git a/components/script/dom/csskeyframesrule.rs b/components/script/dom/csskeyframesrule.rs index 0e4b2e4eaaa..0a5e0e35a7d 100644 --- a/components/script/dom/csskeyframesrule.rs +++ b/components/script/dom/csskeyframesrule.rs @@ -121,7 +121,7 @@ impl CSSKeyframesRuleMethods for CSSKeyframesRule { // Spec deviation: https://github.com/w3c/csswg-drafts/issues/801 // Setting this property to a CSS-wide keyword or `none` does not throw, // it stores a value that serializes as a quoted string. - let name = KeyframesName::from_ident(value.into()); + let name = KeyframesName::from_ident(&value); let mut guard = self.cssrule.shared_lock().write(); self.keyframesrule.write_with(&mut guard).name = name; Ok(()) diff --git a/components/script_layout_interface/Cargo.toml b/components/script_layout_interface/Cargo.toml index 6e566488f65..1de8502117e 100644 --- a/components/script_layout_interface/Cargo.toml +++ b/components/script_layout_interface/Cargo.toml @@ -13,7 +13,7 @@ path = "lib.rs" app_units = "0.5" atomic_refcell = "0.1" canvas_traits = {path = "../canvas_traits"} -cssparser = "0.17.0" +cssparser = "0.18" euclid = "0.15" gfx_traits = {path = "../gfx_traits"} heapsize = "0.4" diff --git a/components/selectors/Cargo.toml b/components/selectors/Cargo.toml index 8a8ddfda946..c8c3aab5df7 100644 --- a/components/selectors/Cargo.toml +++ b/components/selectors/Cargo.toml @@ -25,7 +25,7 @@ unstable = [] [dependencies] bitflags = "0.7" matches = "0.1" -cssparser = "0.17.0" +cssparser = "0.18" log = "0.3" fnv = "1.0" phf = "0.7.18" diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index 12cefc1939a..490399ce38c 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -7,7 +7,7 @@ use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE, NamespaceConstraint}; use bloom::BLOOM_HASH_MASK; use builder::{SelectorBuilder, SpecificityAndFlags}; use context::QuirksMode; -use cssparser::{ParseError, BasicParseError, CompactCowStr}; +use cssparser::{ParseError, BasicParseError, CowRcStr}; use cssparser::{Token, Parser as CssParser, parse_nth, ToCss, serialize_identifier, CssStringWriter}; use precomputed_hash::PrecomputedHash; use servo_arc::ThinArc; @@ -59,8 +59,8 @@ pub enum SelectorParseError<'i, T> { PseudoElementExpectedColon, PseudoElementExpectedIdent, UnsupportedPseudoClass, - UnexpectedIdent(CompactCowStr<'i>), - ExpectedNamespace(CompactCowStr<'i>), + UnexpectedIdent(CowRcStr<'i>), + ExpectedNamespace(CowRcStr<'i>), Custom(T), } @@ -76,13 +76,6 @@ macro_rules! with_all_bounds { [ $( $CommonBounds: tt )* ] [ $( $FromStr: tt )* ] ) => { - fn from_cow_str<T>(cow: Cow<str>) -> T where T: $($FromStr)* { - match cow { - Cow::Borrowed(s) => T::from(s), - Cow::Owned(s) => T::from(s), - } - } - /// This trait allows to define the parser implementation in regards /// of pseudo-classes/elements /// @@ -125,7 +118,7 @@ macro_rules! with_bounds { with_bounds! { [Clone + Eq] - [From<String> + for<'a> From<&'a str>] + [for<'a> From<&'a str>] } pub trait Parser<'i> { @@ -134,34 +127,34 @@ pub trait Parser<'i> { /// Whether the name is a pseudo-element that can be specified with /// the single colon syntax in addition to the double-colon syntax. - fn is_pseudo_element_allows_single_colon(name: &CompactCowStr<'i>) -> bool { + fn is_pseudo_element_allows_single_colon(name: &CowRcStr<'i>) -> bool { is_css2_pseudo_element(name) } /// This function can return an "Err" pseudo-element in order to support CSS2.1 /// pseudo-elements. - fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>) + fn parse_non_ts_pseudo_class(&self, name: CowRcStr<'i>) -> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ParseError<'i, SelectorParseError<'i, Self::Error>>> { Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name))) } fn parse_non_ts_functional_pseudo_class<'t> - (&self, name: CompactCowStr<'i>, _arguments: &mut CssParser<'i, 't>) + (&self, name: CowRcStr<'i>, _arguments: &mut CssParser<'i, 't>) -> Result<<Self::Impl as SelectorImpl>::NonTSPseudoClass, ParseError<'i, SelectorParseError<'i, Self::Error>>> { Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name))) } - fn parse_pseudo_element(&self, name: CompactCowStr<'i>) + fn parse_pseudo_element(&self, name: CowRcStr<'i>) -> Result<<Self::Impl as SelectorImpl>::PseudoElement, ParseError<'i, SelectorParseError<'i, Self::Error>>> { Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name))) } fn parse_functional_pseudo_element<'t> - (&self, name: CompactCowStr<'i>, _arguments: &mut CssParser<'i, 't>) + (&self, name: CowRcStr<'i>, _arguments: &mut CssParser<'i, 't>) -> Result<<Self::Impl as SelectorImpl>::PseudoElement, ParseError<'i, SelectorParseError<'i, Self::Error>>> { Err(ParseError::Custom(SelectorParseError::UnexpectedIdent(name))) @@ -1060,16 +1053,16 @@ fn parse_selector<'i, 't, P, E, Impl>( let position = input.position(); match input.next_including_whitespace() { Err(_e) => break 'outer_loop, - Ok(Token::WhiteSpace(_)) => any_whitespace = true, - Ok(Token::Delim('>')) => { + Ok(&Token::WhiteSpace(_)) => any_whitespace = true, + Ok(&Token::Delim('>')) => { combinator = Combinator::Child; break } - Ok(Token::Delim('+')) => { + Ok(&Token::Delim('+')) => { combinator = Combinator::NextSibling; break } - Ok(Token::Delim('~')) => { + Ok(&Token::Delim('~')) => { combinator = Combinator::LaterSibling; break } @@ -1154,8 +1147,8 @@ fn parse_type_selector<'i, 't, P, E, Impl, S>(parser: &P, input: &mut CssParser< match local_name { Some(name) => { sink.push(Component::LocalName(LocalName { - lower_name: from_cow_str(to_ascii_lowercase(&name)), - name: from_cow_str(name.into()), + lower_name: to_ascii_lowercase(&name).as_ref().into(), + name: name.as_ref().into(), })) } None => { @@ -1189,7 +1182,7 @@ enum QNamePrefix<Impl: SelectorImpl> { fn parse_qualified_name<'i, 't, P, E, Impl> (parser: &P, input: &mut CssParser<'i, 't>, in_attr_selector: bool) - -> Result<Option<(QNamePrefix<Impl>, Option<CompactCowStr<'i>>)>, + -> Result<Option<(QNamePrefix<Impl>, Option<CowRcStr<'i>>)>, ParseError<'i, SelectorParseError<'i, E>>> where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl { @@ -1203,27 +1196,28 @@ fn parse_qualified_name<'i, 't, P, E, Impl> let explicit_namespace = |input: &mut CssParser<'i, 't>, namespace| { match input.next_including_whitespace() { - Ok(Token::Delim('*')) if !in_attr_selector => { + Ok(&Token::Delim('*')) if !in_attr_selector => { Ok(Some((namespace, None))) }, - Ok(Token::Ident(local_name)) => { - Ok(Some((namespace, Some(local_name)))) + Ok(&Token::Ident(ref local_name)) => { + Ok(Some((namespace, Some(local_name.clone())))) }, - Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))), + Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t.clone()))), Err(e) => Err(ParseError::Basic(e)), } }; let position = input.position(); - match input.next_including_whitespace() { + // FIXME: remove clone() when lifetimes are non-lexical + match input.next_including_whitespace().map(|t| t.clone()) { Ok(Token::Ident(value)) => { let position = input.position(); match input.next_including_whitespace() { - Ok(Token::Delim('|')) => { - let prefix = from_cow_str(value.clone().into()); + Ok(&Token::Delim('|')) => { + let prefix = value.as_ref().into(); let result = parser.namespace_for_prefix(&prefix); let url = result.ok_or(ParseError::Custom( - SelectorParseError::ExpectedNamespace(value.into())))?; + SelectorParseError::ExpectedNamespace(value)))?; explicit_namespace(input, QNamePrefix::ExplicitNamespace(prefix, url)) }, _ => { @@ -1238,7 +1232,8 @@ fn parse_qualified_name<'i, 't, P, E, Impl> }, Ok(Token::Delim('*')) => { let position = input.position(); - match input.next_including_whitespace() { + // FIXME: remove clone() when lifetimes are non-lexical + match input.next_including_whitespace().map(|t| t.clone()) { Ok(Token::Delim('|')) => { explicit_namespace(input, QNamePrefix::ExplicitAnyNamespace) } @@ -1247,7 +1242,7 @@ fn parse_qualified_name<'i, 't, P, E, Impl> if in_attr_selector { match result { Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))), - Err(e) => Err(ParseError::Basic(e)), + Err(e) => Err(ParseError::Basic(e)), } } else { default_namespace(None) @@ -1303,8 +1298,8 @@ fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParse match input.next() { // [foo] Err(_) => { - let local_name_lower = from_cow_str(to_ascii_lowercase(&local_name)); - let local_name = from_cow_str(local_name.into()); + let local_name_lower = to_ascii_lowercase(&local_name).as_ref().into(); + let local_name = local_name.as_ref().into(); if let Some(namespace) = namespace { return Ok(Component::AttributeOther(Box::new(AttrSelectorWithNamespace { namespace: namespace, @@ -1322,38 +1317,38 @@ fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParse } // [foo=bar] - Ok(Token::Delim('=')) => { - value = input.expect_ident_or_string()?; + Ok(&Token::Delim('=')) => { + value = input.expect_ident_or_string()?.clone(); never_matches = false; operator = AttrSelectorOperator::Equal; } // [foo~=bar] - Ok(Token::IncludeMatch) => { - value = input.expect_ident_or_string()?; + Ok(&Token::IncludeMatch) => { + value = input.expect_ident_or_string()?.clone(); never_matches = value.is_empty() || value.contains(SELECTOR_WHITESPACE); operator = AttrSelectorOperator::Includes; } // [foo|=bar] - Ok(Token::DashMatch) => { - value = input.expect_ident_or_string()?; + Ok(&Token::DashMatch) => { + value = input.expect_ident_or_string()?.clone(); never_matches = false; operator = AttrSelectorOperator::DashMatch; } // [foo^=bar] - Ok(Token::PrefixMatch) => { - value = input.expect_ident_or_string()?; + Ok(&Token::PrefixMatch) => { + value = input.expect_ident_or_string()?.clone(); never_matches = value.is_empty(); operator = AttrSelectorOperator::Prefix; } // [foo*=bar] - Ok(Token::SubstringMatch) => { - value = input.expect_ident_or_string()?; + Ok(&Token::SubstringMatch) => { + value = input.expect_ident_or_string()?.clone(); never_matches = value.is_empty(); operator = AttrSelectorOperator::Substring; } // [foo$=bar] - Ok(Token::SuffixMatch) => { - value = input.expect_ident_or_string()?; + Ok(&Token::SuffixMatch) => { + value = input.expect_ident_or_string()?.clone(); never_matches = value.is_empty(); operator = AttrSelectorOperator::Suffix; } @@ -1362,7 +1357,7 @@ fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParse let mut case_sensitivity = parse_attribute_flags(input)?; - let value = from_cow_str(value.into()); + let value = value.as_ref().into(); let local_name_lower; { let local_name_lower_cow = to_ascii_lowercase(&local_name); @@ -1375,9 +1370,9 @@ fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParse ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument } } - local_name_lower = from_cow_str(local_name_lower_cow.into()); + local_name_lower = local_name_lower_cow.as_ref().into(); } - let local_name = from_cow_str(local_name.into()); + let local_name = local_name.as_ref().into(); if let Some(namespace) = namespace { Ok(Component::AttributeOther(Box::new(AttrSelectorWithNamespace { namespace: namespace, @@ -1411,10 +1406,10 @@ fn parse_attribute_flags<'i, 't, E>(input: &mut CssParser<'i, 't>) // Selectors spec says language-defined, but HTML says sensitive. Ok(ParsedCaseSensitivity::CaseSensitive) } - Ok(Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => { + Ok(&Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => { Ok(ParsedCaseSensitivity::AsciiCaseInsensitive) } - Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))) + Ok(t) => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t.clone()))) } } @@ -1433,7 +1428,7 @@ fn parse_negation<'i, 't, P, E, Impl>(parser: &P, // Consume any leading whitespace. loop { let position = input.position(); - if !matches!(input.next_including_whitespace(), Ok(Token::WhiteSpace(_))) { + if !matches!(input.next_including_whitespace(), Ok(&Token::WhiteSpace(_))) { input.reset(position); break } @@ -1476,7 +1471,7 @@ fn parse_compound_selector<'i, 't, P, E, Impl>( // Consume any leading whitespace. loop { let position = input.position(); - if !matches!(input.next_including_whitespace(), Ok(Token::WhiteSpace(_))) { + if !matches!(input.next_including_whitespace(), Ok(&Token::WhiteSpace(_))) { input.reset(position); break } @@ -1508,15 +1503,15 @@ fn parse_compound_selector<'i, 't, P, E, Impl>( loop { match input.next_including_whitespace() { - Ok(Token::Colon) => {}, - Ok(Token::WhiteSpace(_)) | Err(_) => break, + Ok(&Token::Colon) => {}, + Ok(&Token::WhiteSpace(_)) | Err(_) => break, _ => return Err(SelectorParseError::PseudoElementExpectedColon.into()), } // TODO(emilio): Functional pseudo-classes too? // We don't need it for now. let name = match input.next_including_whitespace() { - Ok(Token::Ident(name)) => name, + Ok(&Token::Ident(ref name)) => name.clone(), _ => return Err(SelectorParseError::PseudoElementExpectedIdent.into()), }; @@ -1553,7 +1548,7 @@ fn parse_compound_selector<'i, 't, P, E, Impl>( fn parse_functional_pseudo_class<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParser<'i, 't>, - name: CompactCowStr<'i>, + name: CowRcStr<'i>, inside_negation: bool) -> Result<Component<Impl>, ParseError<'i, SelectorParseError<'i, E>>> @@ -1589,7 +1584,7 @@ where Impl: SelectorImpl, F: FnOnce(i32, i32) -> Component<Impl> { /// Returns whether the name corresponds to a CSS2 pseudo-element that /// can be specified with the single colon syntax (in addition to the /// double-colon syntax, which can be used for all pseudo-elements). -pub fn is_css2_pseudo_element<'i>(name: &CompactCowStr<'i>) -> bool { +pub fn is_css2_pseudo_element<'i>(name: &CowRcStr<'i>) -> bool { // ** Do not add to this list! ** return name.eq_ignore_ascii_case("before") || name.eq_ignore_ascii_case("after") || @@ -1610,18 +1605,19 @@ fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P, where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl { let start_position = input.position(); - match input.next_including_whitespace() { + // FIXME: remove clone() when lifetimes are non-lexical + match input.next_including_whitespace().map(|t| t.clone()) { Ok(Token::IDHash(id)) => { - let id = Component::ID(from_cow_str(id.into())); + let id = Component::ID(id.as_ref().into()); Ok(Some(SimpleSelectorParseResult::SimpleSelector(id))) } Ok(Token::Delim('.')) => { - match input.next_including_whitespace()? { - Token::Ident(class) => { - let class = Component::Class(from_cow_str(class.into())); + match *input.next_including_whitespace()? { + Token::Ident(ref class) => { + let class = Component::Class(class.as_ref().into()); Ok(Some(SimpleSelectorParseResult::SimpleSelector(class))) } - t => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t))), + ref t => Err(ParseError::Basic(BasicParseError::UnexpectedToken(t.clone()))), } } Ok(Token::SquareBracketBlock) => { @@ -1629,8 +1625,8 @@ fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P, Ok(Some(SimpleSelectorParseResult::SimpleSelector(attr))) } Ok(Token::Colon) => { - let (is_single_colon, next_token) = match input.next_including_whitespace()? { - Token::Colon => (false, input.next_including_whitespace()?), + let (is_single_colon, next_token) = match input.next_including_whitespace()?.clone() { + Token::Colon => (false, input.next_including_whitespace()?.clone()), t => (true, t), }; let (name, is_functional) = match next_token { @@ -1667,7 +1663,7 @@ fn parse_one_simple_selector<'i, 't, P, E, Impl>(parser: &P, } } -fn parse_simple_pseudo_class<'i, P, E, Impl>(parser: &P, name: CompactCowStr<'i>) +fn parse_simple_pseudo_class<'i, P, E, Impl>(parser: &P, name: CowRcStr<'i>) -> Result<Component<Impl>, ParseError<'i, SelectorParseError<'i, E>>> where P: Parser<'i, Impl=Impl, Error=E>, Impl: SelectorImpl @@ -1821,7 +1817,7 @@ pub mod tests { type Impl = DummySelectorImpl; type Error = (); - fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>) + fn parse_non_ts_pseudo_class(&self, name: CowRcStr<'i>) -> Result<PseudoClass, ParseError<'i, SelectorParseError<'i, ()>>> { match_ignore_ascii_case! { &name, @@ -1831,17 +1827,17 @@ pub mod tests { } } - fn parse_non_ts_functional_pseudo_class<'t>(&self, name: CompactCowStr<'i>, + fn parse_non_ts_functional_pseudo_class<'t>(&self, name: CowRcStr<'i>, parser: &mut CssParser<'i, 't>) -> Result<PseudoClass, ParseError<'i, SelectorParseError<'i, ()>>> { match_ignore_ascii_case! { &name, - "lang" => Ok(PseudoClass::Lang(parser.expect_ident_or_string()?.into_owned())), + "lang" => Ok(PseudoClass::Lang(parser.expect_ident_or_string()?.as_ref().to_owned())), _ => Err(SelectorParseError::Custom(()).into()) } } - fn parse_pseudo_element(&self, name: CompactCowStr<'i>) + fn parse_pseudo_element(&self, name: CowRcStr<'i>) -> Result<PseudoElement, ParseError<'i, SelectorParseError<'i, ()>>> { match_ignore_ascii_case! { &name, diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 0d349c8f66c..ec98f0a38b8 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -38,7 +38,7 @@ bitflags = "0.7" bit-vec = "0.4.3" byteorder = "1.0" cfg-if = "0.1.0" -cssparser = "0.17.0" +cssparser = "0.18" encoding = {version = "0.2", optional = true} euclid = "0.15" fnv = "1.0" diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index 5ca39da05ca..1eb47fedf51 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -8,7 +8,7 @@ use Atom; use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser}; -use cssparser::{Parser, Token, serialize_identifier, BasicParseError, CompactCowStr}; +use cssparser::{Parser, Token, serialize_identifier, BasicParseError, CowRcStr}; use error_reporting::ContextualParseError; #[cfg(feature = "gecko")] use gecko::rules::CounterStyleDescriptors; #[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSCounterDesc; @@ -184,7 +184,7 @@ macro_rules! counter_style_descriptors { type Declaration = (); type Error = SelectorParseError<'i, StyleParseError<'i>>; - fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>) + fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>) -> Result<(), ParseError<'i>> { match_ignore_ascii_case! { &*name, $( @@ -295,7 +295,7 @@ pub enum System { impl Parse for System { fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { - try_match_ident_ignore_ascii_case! { input.expect_ident()?, + try_match_ident_ignore_ascii_case! { input.expect_ident_cloned()?, "cyclic" => Ok(System::Cyclic), "numeric" => Ok(System::Numeric), "alphabetic" => Ok(System::Alphabetic), @@ -351,9 +351,9 @@ pub enum Symbol { impl Parse for Symbol { fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { match input.next() { - Ok(Token::QuotedString(s)) => Ok(Symbol::String(s.into_owned())), - Ok(Token::Ident(s)) => Ok(Symbol::Ident(s.into_owned())), - Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()), + Ok(&Token::QuotedString(ref s)) => Ok(Symbol::String(s.as_ref().to_owned())), + Ok(&Token::Ident(ref s)) => Ok(Symbol::Ident(s.as_ref().to_owned())), + Ok(t) => Err(BasicParseError::UnexpectedToken(t.clone()).into()), Err(e) => Err(e.into()), } } @@ -419,9 +419,9 @@ impl Parse for Ranges { fn parse_bound<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Option<i32>, ParseError<'i>> { match input.next() { - Ok(Token::Number { int_value: Some(v), .. }) => Ok(Some(v)), - Ok(Token::Ident(ref ident)) if ident.eq_ignore_ascii_case("infinite") => Ok(None), - Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()), + Ok(&Token::Number { int_value: Some(v), .. }) => Ok(Some(v)), + Ok(&Token::Ident(ref ident)) if ident.eq_ignore_ascii_case("infinite") => Ok(None), + Ok(t) => Err(BasicParseError::UnexpectedToken(t.clone()).into()), Err(e) => Err(e.into()), } } diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index 50b49107f25..cb9e3956184 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -252,7 +252,8 @@ fn parse_declaration_value_block<'i, 't> ParseError<'i>> { let mut token_start = input.position(); let mut token = match input.next_including_whitespace_and_comments() { - Ok(token) => token, + // FIXME: remove clone() when borrows are non-lexical + Ok(token) => token.clone(), Err(_) => return Ok((TokenSerializationType::nothing(), TokenSerializationType::nothing())) }; let first_token_type = token.serialization_type(); @@ -351,7 +352,8 @@ fn parse_declaration_value_block<'i, 't> token_start = input.position(); token = match input.next_including_whitespace_and_comments() { - Ok(token) => token, + // FIXME: remove clone() when borrows are non-lexical + Ok(token) => token.clone(), Err(..) => return Ok((first_token_type, last_token_type)), }; } @@ -361,7 +363,7 @@ fn parse_declaration_value_block<'i, 't> fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>, references: &mut Option<HashSet<Name>>) -> Result<(), ParseError<'i>> { - let name = input.expect_ident()?; + let name = input.expect_ident_cloned()?; let name: Result<_, ParseError> = parse_name(&name) .map_err(|()| SelectorParseError::UnexpectedIdent(name.clone()).into()); @@ -597,7 +599,8 @@ fn substitute_block<'i, 't, F>(input: &mut Parser<'i, 't>, let mut set_position_at_next_iteration = false; loop { let before_this_token = input.position(); - let next = input.next_including_whitespace_and_comments(); + // FIXME: remove clone() when borrows are non-lexical + let next = input.next_including_whitespace_and_comments().map(|t| t.clone()); if set_position_at_next_iteration { *position = (before_this_token, match next { Ok(ref token) => token.serialization_type(), @@ -615,7 +618,7 @@ fn substitute_block<'i, 't, F>(input: &mut Parser<'i, 't>, input.slice(position.0..before_this_token), position.1, last_token_type); input.parse_nested_block(|input| { // parse_var_function() ensures neither .unwrap() will fail. - let name = input.expect_ident().unwrap(); + let name = input.expect_ident_cloned().unwrap(); let name = Atom::from(parse_name(&name).unwrap()); if let Ok(last) = substitute_one(&name, partial_computed_value) { diff --git a/components/style/font_face.rs b/components/style/font_face.rs index b180e1e7fe2..3dca241828b 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -12,7 +12,7 @@ use computed_values::{font_feature_settings, font_stretch, font_style, font_weight}; use computed_values::font_family::FamilyName; use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser}; -use cssparser::{SourceLocation, CompactCowStr}; +use cssparser::{SourceLocation, CowRcStr}; use error_reporting::ContextualParseError; #[cfg(feature = "gecko")] use gecko_bindings::structs::CSSFontFaceDescriptors; #[cfg(feature = "gecko")] use cssparser::UnicodeRange; @@ -197,7 +197,7 @@ impl Parse for Source { let format_hints = if input.try(|input| input.expect_function_matching("format")).is_ok() { input.parse_nested_block(|input| { input.parse_comma_separated(|input| { - Ok(input.expect_string()?.into_owned()) + Ok(input.expect_string()?.as_ref().to_owned()) }) })? } else { @@ -275,7 +275,7 @@ macro_rules! font_face_descriptors_common { type Declaration = (); type Error = SelectorParseError<'i, StyleParseError<'i>>; - fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>) + fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>) -> Result<(), ParseError<'i>> { match_ignore_ascii_case! { &*name, $( diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index 8b0e00b91fe..62e891eed90 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -240,11 +240,11 @@ impl Resolution { } fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { - let (value, unit) = match input.next()? { - Token::Dimension { value, unit, .. } => { + let (value, unit) = match *input.next()? { + Token::Dimension { value, ref unit, .. } => { (value, unit) }, - t => return Err(BasicParseError::UnexpectedToken(t).into()), + ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()), }; if value <= 0. { @@ -256,7 +256,7 @@ impl Resolution { "dppx" => Ok(Resolution::Dppx(value)), "dpcm" => Ok(Resolution::Dpcm(value)), _ => Err(()) - }).map_err(|()| StyleParseError::UnexpectedDimension(unit).into()) + }).map_err(|()| StyleParseError::UnexpectedDimension(unit.clone()).into()) } } @@ -474,47 +474,55 @@ impl Expression { -> Result<Self, ParseError<'i>> { input.expect_parenthesis_block()?; input.parse_nested_block(|input| { - let ident = input.expect_ident()?; - - let mut flags = 0; - let result = { - let mut feature_name = &*ident; + // FIXME: remove extra indented block when lifetimes are non-lexical + let feature; + let range; + { + let ident = input.expect_ident()?; + + let mut flags = 0; + let result = { + let mut feature_name = &**ident; + + // TODO(emilio): this is under a pref in Gecko. + if starts_with_ignore_ascii_case(feature_name, "-webkit-") { + feature_name = &feature_name[8..]; + flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8; + } - // TODO(emilio): this is under a pref in Gecko. - if starts_with_ignore_ascii_case(feature_name, "-webkit-") { - feature_name = &feature_name[8..]; - flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8; - } + let range = if starts_with_ignore_ascii_case(feature_name, "min-") { + feature_name = &feature_name[4..]; + nsMediaExpression_Range::eMin + } else if starts_with_ignore_ascii_case(feature_name, "max-") { + feature_name = &feature_name[4..]; + nsMediaExpression_Range::eMax + } else { + nsMediaExpression_Range::eEqual + }; - let range = if starts_with_ignore_ascii_case(feature_name, "min-") { - feature_name = &feature_name[4..]; - nsMediaExpression_Range::eMin - } else if starts_with_ignore_ascii_case(feature_name, "max-") { - feature_name = &feature_name[4..]; - nsMediaExpression_Range::eMax - } else { - nsMediaExpression_Range::eEqual + let atom = Atom::from(feature_name); + match find_feature(|f| atom.as_ptr() == unsafe { *f.mName }) { + Some(f) => Ok((f, range)), + None => Err(()), + } }; - let atom = Atom::from(feature_name); - match find_feature(|f| atom.as_ptr() == unsafe { *f.mName }) { - Some(f) => Ok((f, range)), - None => Err(()), + match result { + Ok((f, r)) => { + feature = f; + range = r; + } + Err(()) => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()), } - }; - - let (feature, range) = match result { - Ok((feature, range)) => (feature, range), - Err(()) => return Err(SelectorParseError::UnexpectedIdent(ident).into()), - }; - if (feature.mReqFlags & !flags) != 0 { - return Err(SelectorParseError::UnexpectedIdent(ident).into()); - } + if (feature.mReqFlags & !flags) != 0 { + return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()); + } - if range != nsMediaExpression_Range::eEqual && - feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed { - return Err(SelectorParseError::UnexpectedIdent(ident).into()); + if range != nsMediaExpression_Range::eEqual && + feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed { + return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()); + } } // If there's no colon, this is a media query of the form @@ -590,7 +598,7 @@ impl Expression { MediaExpressionValue::Enumerated(value) } nsMediaFeature_ValueType::eIdent => { - MediaExpressionValue::Ident(input.expect_ident()?.into_owned()) + MediaExpressionValue::Ident(input.expect_ident()?.as_ref().to_owned()) } }; diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index 0dc03c4e6ed..8fae5d563f2 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -4,7 +4,7 @@ //! Gecko-specific bits for selector-parsing. -use cssparser::{BasicParseError, Parser, ToCss, Token, CompactCowStr}; +use cssparser::{BasicParseError, Parser, ToCss, Token, CowRcStr}; use element_state::ElementState; use gecko_bindings::structs::CSSPseudoClassType; use selector_parser::{SelectorParser, PseudoElementCascadeType}; @@ -267,12 +267,12 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { type Impl = SelectorImpl; type Error = StyleParseError<'i>; - fn is_pseudo_element_allows_single_colon(name: &CompactCowStr<'i>) -> bool { + fn is_pseudo_element_allows_single_colon(name: &CowRcStr<'i>) -> bool { ::selectors::parser::is_css2_pseudo_element(name) || name.starts_with("-moz-tree-") // tree pseudo-elements } - fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>) + fn parse_non_ts_pseudo_class(&self, name: CowRcStr<'i>) -> Result<NonTSPseudoClass, ParseError<'i>> { macro_rules! pseudo_class_parse { (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*], @@ -294,7 +294,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { } fn parse_non_ts_functional_pseudo_class<'t>(&self, - name: CompactCowStr<'i>, + name: CowRcStr<'i>, parser: &mut Parser<'i, 't>) -> Result<NonTSPseudoClass, ParseError<'i>> { macro_rules! pseudo_class_string_parse { @@ -338,12 +338,12 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { } } - fn parse_pseudo_element(&self, name: CompactCowStr<'i>) -> Result<PseudoElement, ParseError<'i>> { + fn parse_pseudo_element(&self, name: CowRcStr<'i>) -> Result<PseudoElement, ParseError<'i>> { PseudoElement::from_slice(&name, self.in_user_agent_stylesheet()) .ok_or(SelectorParseError::UnexpectedIdent(name.clone()).into()) } - fn parse_functional_pseudo_element<'t>(&self, name: CompactCowStr<'i>, + fn parse_functional_pseudo_element<'t>(&self, name: CowRcStr<'i>, parser: &mut Parser<'i, 't>) -> Result<PseudoElement, ParseError<'i>> { if name.starts_with("-moz-tree-") { @@ -352,9 +352,9 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { let mut args = Vec::new(); loop { match parser.next() { - Ok(Token::Ident(ident)) => args.push(ident.into_owned()), - Ok(Token::Comma) => {}, - Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()), + Ok(&Token::Ident(ref ident)) => args.push(ident.as_ref().to_owned()), + Ok(&Token::Comma) => {}, + Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()), Err(BasicParseError::EndOfInput) => break, _ => unreachable!("Parser::next() shouldn't return any other error"), } diff --git a/components/style/gecko_string_cache/namespace.rs b/components/style/gecko_string_cache/namespace.rs index 319f15222a9..090243204c8 100644 --- a/components/style/gecko_string_cache/namespace.rs +++ b/components/style/gecko_string_cache/namespace.rs @@ -6,7 +6,7 @@ use gecko_bindings::structs::nsIAtom; use precomputed_hash::PrecomputedHash; -use std::borrow::{Borrow, Cow}; +use std::borrow::Borrow; use std::fmt; use std::ops::Deref; use string_cache::{Atom, WeakAtom}; @@ -54,8 +54,8 @@ impl Deref for Namespace { } } -impl<'a> From<Cow<'a, str>> for Namespace { - fn from(s: Cow<'a, str>) -> Self { +impl<'a> From<&'a str> for Namespace { + fn from(s: &'a str) -> Self { Namespace(Atom::from(s)) } } diff --git a/components/style/macros.rs b/components/style/macros.rs index af4e0b74684..d72ecc73c06 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -17,7 +17,7 @@ macro_rules! try_match_ident_ignore_ascii_case { _ => Err(()), }) .map_err(|()| { - ::selectors::parser::SelectorParseError::UnexpectedIdent(__ident).into() + ::selectors::parser::SelectorParseError::UnexpectedIdent(__ident.clone()).into() }) } } diff --git a/components/style/media_queries.rs b/components/style/media_queries.rs index a95d9919820..5f71ddf974f 100644 --- a/components/style/media_queries.rs +++ b/components/style/media_queries.rs @@ -211,10 +211,10 @@ impl MediaQuery { None }; - let media_type = match input.try(|input| input.expect_ident()) { + let media_type = match input.try(|i| i.expect_ident_cloned()) { Ok(ident) => { let result: Result<_, ParseError> = MediaQueryType::parse(&*ident) - .map_err(|()| SelectorParseError::UnexpectedIdent(ident).into()); + .map_err(|()| SelectorParseError::UnexpectedIdent(ident.clone()).into()); result? } Err(_) => { @@ -263,7 +263,7 @@ pub fn parse_media_query_list(context: &ParserContext, input: &mut Parser) -> Me } match input.next() { - Ok(Token::Comma) => {}, + Ok(&Token::Comma) => {}, Ok(_) => unreachable!(), Err(_) => break, } diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 3570fc7210b..d192f463d51 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -7,7 +7,7 @@ #![deny(missing_docs)] use context::QuirksMode; -use cssparser::{DeclarationListParser, parse_important, ParserInput, CompactCowStr}; +use cssparser::{DeclarationListParser, parse_important, ParserInput, CowRcStr}; use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter, ParseError as CssParseError}; use error_reporting::{ParseErrorReporter, ContextualParseError}; use parser::{ParserContext, log_css_error}; @@ -945,7 +945,7 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> { type Declaration = Importance; type Error = SelectorParseError<'i, StyleParseError<'i>>; - fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>) + fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>) -> Result<Importance, ParseError<'i>> { let id = match PropertyId::parse(&name) { Ok(id) => id, diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index ede7eac91a7..e6f1c42e31a 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2808,7 +2808,7 @@ fn static_assert() { if atom.is_empty() { AnimationName(None) } else { - AnimationName(Some(KeyframesName::from_ident(atom.to_string()))) + AnimationName(Some(KeyframesName::from_ident(&atom.to_string()))) } } pub fn copy_animation_name_from(&mut self, other: &Self) { diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 5f00342895c..4e3a79f5e77 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -286,7 +286,7 @@ impl TransitionProperty { match supported { Ok(Some(property)) => Ok(property), Ok(None) => CustomIdent::from_ident(ident, &[]).map(TransitionProperty::Unsupported), - Err(()) => Err(SelectorParseError::UnexpectedIdent(ident).into()), + Err(()) => Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()), } } diff --git a/components/style/properties/longhand/background.mako.rs b/components/style/properties/longhand/background.mako.rs index 5c252e15e9b..1fed8b37f40 100644 --- a/components/style/properties/longhand/background.mako.rs +++ b/components/style/properties/longhand/background.mako.rs @@ -122,14 +122,14 @@ ${helpers.predefined_type("background-image", "ImageLayer", pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<SpecifiedValue, ParseError<'i>> { - let ident = input.expect_ident()?; + let ident = input.expect_ident_cloned()?; (match_ignore_ascii_case! { &ident, "repeat-x" => Ok(SpecifiedValue::RepeatX), "repeat-y" => Ok(SpecifiedValue::RepeatY), _ => Err(()), }).or_else(|()| { let horizontal: Result<_, ParseError> = RepeatKeyword::from_ident(&ident) - .map_err(|()| SelectorParseError::UnexpectedIdent(ident).into()); + .map_err(|()| SelectorParseError::UnexpectedIdent(ident.clone()).into()); let horizontal = horizontal?; let vertical = input.try(RepeatKeyword::parse).ok(); Ok(SpecifiedValue::Other(horizontal, vertical)) diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 3738032491c..41e7a3fb4c8 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -1025,7 +1025,7 @@ ${helpers.predefined_type( } Ok(SpecifiedValue(Space::parse(input, |input| { - let function = input.expect_function()?; + let function = input.expect_function()?.clone(); input.parse_nested_block(|input| { let result = match_ignore_ascii_case! { &function, "matrix" => { @@ -1217,7 +1217,7 @@ ${helpers.predefined_type( _ => Err(()), }; result - .map_err(|()| StyleParseError::UnexpectedFunction(function).into()) + .map_err(|()| StyleParseError::UnexpectedFunction(function.clone()).into()) }) })?)) } @@ -1764,7 +1764,7 @@ ${helpers.predefined_type("transform-origin", return Ok(result) } - while let Ok(name) = input.try(|input| input.expect_ident()) { + while let Ok(name) = input.try(|i| i.expect_ident_cloned()) { let flag = match_ignore_ascii_case! { &name, "layout" => Some(LAYOUT), "style" => Some(STYLE), @@ -1773,7 +1773,7 @@ ${helpers.predefined_type("transform-origin", }; let flag = match flag { Some(flag) if !result.contains(flag) => flag, - _ => return Err(SelectorParseError::UnexpectedIdent(name).into()) + _ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into()) }; result.insert(flag); } @@ -1960,7 +1960,8 @@ ${helpers.predefined_type("shape-outside", "basic_shape::FloatAreaShape", pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<SpecifiedValue, ParseError<'i>> { - try_match_ident_ignore_ascii_case! { input.expect_ident()?, + // FIXME: remove clone() when lifetimes are non-lexical + try_match_ident_ignore_ascii_case! { input.expect_ident()?.clone(), "auto" => Ok(TOUCH_ACTION_AUTO), "none" => Ok(TOUCH_ACTION_NONE), "manipulation" => Ok(TOUCH_ACTION_MANIPULATION), diff --git a/components/style/properties/longhand/color.mako.rs b/components/style/properties/longhand/color.mako.rs index 76b5ca18aea..d1fb5429261 100644 --- a/components/style/properties/longhand/color.mako.rs +++ b/components/style/properties/longhand/color.mako.rs @@ -134,7 +134,7 @@ if let Some(color) = color_name(&ident) { Ok(*color) } else { - Err(SelectorParseError::UnexpectedIdent(ident).into()) + Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()) } } } diff --git a/components/style/properties/longhand/counters.mako.rs b/components/style/properties/longhand/counters.mako.rs index 0a079fd277a..85e039b3f68 100644 --- a/components/style/properties/longhand/counters.mako.rs +++ b/components/style/properties/longhand/counters.mako.rs @@ -179,21 +179,22 @@ continue; } % endif - match input.next() { - Ok(Token::QuotedString(value)) => { - content.push(ContentItem::String(value.into_owned())) + // FIXME: remove clone() when lifetimes are non-lexical + match input.next().map(|t| t.clone()) { + Ok(Token::QuotedString(ref value)) => { + content.push(ContentItem::String(value.as_ref().to_owned())) } - Ok(Token::Function(name)) => { + Ok(Token::Function(ref name)) => { let result = match_ignore_ascii_case! { &name, "counter" => Some(input.parse_nested_block(|input| { - let name = input.expect_ident()?.into_owned(); + let name = input.expect_ident()?.as_ref().to_owned(); let style = parse_counter_style(context, input); Ok(ContentItem::Counter(name, style)) })), "counters" => Some(input.parse_nested_block(|input| { - let name = input.expect_ident()?.into_owned(); + let name = input.expect_ident()?.as_ref().to_owned(); input.expect_comma()?; - let separator = input.expect_string()?.into_owned(); + let separator = input.expect_string()?.as_ref().to_owned(); let style = parse_counter_style(context, input); Ok(ContentItem::Counters(name, separator, style)) })), @@ -206,10 +207,10 @@ }; match result { Some(result) => content.push(result?), - None => return Err(StyleParseError::UnexpectedFunction(name).into()) + None => return Err(StyleParseError::UnexpectedFunction(name.clone()).into()) } } - Ok(Token::Ident(ident)) => { + Ok(Token::Ident(ref ident)) => { let valid = match_ignore_ascii_case! { &ident, "open-quote" => { content.push(ContentItem::OpenQuote); true }, "close-quote" => { content.push(ContentItem::CloseQuote); true }, @@ -219,7 +220,7 @@ _ => false, }; if !valid { - return Err(SelectorParseError::UnexpectedIdent(ident).into()) + return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()) } } Err(_) => break, @@ -333,8 +334,8 @@ let mut counters = Vec::new(); loop { let counter_name = match input.next() { - Ok(Token::Ident(ident)) => CustomIdent::from_ident(ident, &["none"])?, - Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()), + Ok(&Token::Ident(ref ident)) => CustomIdent::from_ident(ident, &["none"])?, + Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()), Err(_) => break, }; let counter_delta = input.try(|input| specified::parse_integer(context, input)) diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index c83f60b26e5..8942c73afb9 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -145,13 +145,13 @@ macro_rules! impl_gecko_keyword_conversions { /// Parse a font-family value pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { - if let Ok(value) = input.try(|input| input.expect_string()) { + if let Ok(value) = input.try(|i| i.expect_string_cloned()) { return Ok(FontFamily::FamilyName(FamilyName { name: Atom::from(&*value), quoted: true, })) } - let first_ident = input.expect_ident()?; + let first_ident = input.expect_ident()?.clone(); // FIXME(bholley): The fast thing to do here would be to look up the // string (as lowercase) in the static atoms table. We don't have an @@ -181,7 +181,7 @@ macro_rules! impl_gecko_keyword_conversions { _ => {} } - let mut value = first_ident.into_owned(); + let mut value = first_ident.as_ref().to_owned(); // These keywords are not allowed by themselves. // The only way this value can be valid with with another keyword. if css_wide_keyword { @@ -189,7 +189,7 @@ macro_rules! impl_gecko_keyword_conversions { value.push_str(" "); value.push_str(&ident); } - while let Ok(ident) = input.try(|input| input.expect_ident()) { + while let Ok(ident) = input.try(|i| i.expect_ident_cloned()) { value.push_str(" "); value.push_str(&ident); } @@ -1189,7 +1189,8 @@ ${helpers.single_keyword_system("font-variant-caps", pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<SpecifiedValue, ParseError<'i>> { let mut result = SpecifiedValue { weight: false, style: false }; - try_match_ident_ignore_ascii_case! { input.expect_ident()?, + // FIXME: remove clone() when lifetimes are non-lexical + try_match_ident_ignore_ascii_case! { input.expect_ident()?.clone(), "none" => Ok(result), "weight" => { result.weight = true; @@ -1411,9 +1412,10 @@ ${helpers.single_keyword_system("font-kerning", ) ); while let Ok(_) = input.try(|input| { - match input.next()? { - Token::Ident(ident) => { - if ident == "historical-forms" { + // FIXME: remove clone() when lifetimes are non-lexical + match input.next()?.clone() { + Token::Ident(ref ident) => { + if *ident == "historical-forms" { check_if_parsed!(HISTORICAL_FORMS); alternates.push(VariantAlternates::HistoricalForms); Ok(()) @@ -1421,7 +1423,7 @@ ${helpers.single_keyword_system("font-kerning", return Err(StyleParseError::UnspecifiedError.into()); } }, - Token::Function(name) => { + Token::Function(ref name) => { input.parse_nested_block(|i| { match_ignore_ascii_case! { &name, % for value in "swash stylistic ornaments annotation".split(): @@ -2136,8 +2138,8 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control- if input.try(|input| input.expect_ident_matching("normal")).is_ok() { Ok(SpecifiedValue::Normal) } else { - input.expect_string().map(|cow| { - SpecifiedValue::Override(cow.into_owned()) + input.expect_string().map(|s| { + SpecifiedValue::Override(s.as_ref().to_owned()) }).map_err(|e| e.into()) } } diff --git a/components/style/properties/longhand/inherited_text.mako.rs b/components/style/properties/longhand/inherited_text.mako.rs index 3f2a5ab02a1..80f0624d55f 100644 --- a/components/style/properties/longhand/inherited_text.mako.rs +++ b/components/style/properties/longhand/inherited_text.mako.rs @@ -590,9 +590,9 @@ ${helpers.predefined_type( return Ok(SpecifiedValue::None); } - if let Ok(s) = input.try(|input| input.expect_string()) { + if let Ok(s) = input.try(|i| i.expect_string().map(|s| s.as_ref().to_owned())) { // Handle <string> - return Ok(SpecifiedValue::String(s.into_owned())); + return Ok(SpecifiedValue::String(s)); } // Handle a pair of keywords diff --git a/components/style/properties/longhand/list.mako.rs b/components/style/properties/longhand/list.mako.rs index d675e9b589b..b993824ad4e 100644 --- a/components/style/properties/longhand/list.mako.rs +++ b/components/style/properties/longhand/list.mako.rs @@ -94,7 +94,7 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu Ok(if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) { SpecifiedValue::CounterStyle(style) } else { - SpecifiedValue::String(input.expect_string()?.into_owned()) + SpecifiedValue::String(input.expect_string()?.as_ref().to_owned()) }) } </%helpers:longhand> @@ -197,13 +197,13 @@ ${helpers.single_keyword("list-style-position", "outside inside", animation_valu let mut quotes = Vec::new(); loop { let first = match input.next() { - Ok(Token::QuotedString(value)) => value.into_owned(), - Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()), + Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(), + Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()), Err(_) => break, }; let second = match input.next() { - Ok(Token::QuotedString(value)) => value.into_owned(), - Ok(t) => return Err(BasicParseError::UnexpectedToken(t).into()), + Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(), + Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()), Err(e) => return Err(e.into()), }; quotes.push((first, second)) diff --git a/components/style/properties/longhand/pointing.mako.rs b/components/style/properties/longhand/pointing.mako.rs index 77a7426d6cb..9e7923889b1 100644 --- a/components/style/properties/longhand/pointing.mako.rs +++ b/components/style/properties/longhand/pointing.mako.rs @@ -101,7 +101,7 @@ } else { Cursor::from_css_keyword(&ident) .map(computed_value::Keyword::Cursor) - .map_err(|()| SelectorParseError::UnexpectedIdent(ident).into()) + .map_err(|()| SelectorParseError::UnexpectedIdent(ident.clone()).into()) } } } diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs index 526c62e4ceb..04d0f295eb1 100644 --- a/components/style/properties/longhand/position.mako.rs +++ b/components/style/properties/longhand/position.mako.rs @@ -361,7 +361,7 @@ ${helpers.predefined_type("object-position", _ => false }; if !success { - return Err(SelectorParseError::UnexpectedIdent(ident).into()); + return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()); } } @@ -463,8 +463,8 @@ ${helpers.predefined_type("object-position", fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { let mut strings = vec![]; - while let Ok(string) = input.try(Parser::expect_string) { - strings.push(string.into_owned().into_boxed_str()); + while let Ok(string) = input.try(|i| i.expect_string().map(|s| s.as_ref().into())) { + strings.push(string); } TemplateAreas::from_vec(strings) diff --git a/components/style/properties/longhand/text.mako.rs b/components/style/properties/longhand/text.mako.rs index 7279cc6770b..9c502b5addc 100644 --- a/components/style/properties/longhand/text.mako.rs +++ b/components/style/properties/longhand/text.mako.rs @@ -117,17 +117,17 @@ impl Parse for Side { fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Side, ParseError<'i>> { - match input.next()? { - Token::Ident(ident) => { + match *input.next()? { + Token::Ident(ref ident) => { try_match_ident_ignore_ascii_case! { ident, "clip" => Ok(Side::Clip), "ellipsis" => Ok(Side::Ellipsis), } } - Token::QuotedString(v) => { - Ok(Side::String(v.into_owned().into_boxed_str())) + Token::QuotedString(ref v) => { + Ok(Side::String(v.as_ref().to_owned().into_boxed_str())) } - other => Err(BasicParseError::UnexpectedToken(other).into()), + ref t => Err(BasicParseError::UnexpectedToken(t.clone()).into()), } } } @@ -236,7 +236,7 @@ ${helpers.single_keyword("unicode-bidi", "blink" => if result.contains(BLINK) { Err(()) } else { empty = false; result.insert(BLINK); Ok(()) }, _ => Err(()) - }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into()) + }).map_err(|()| SelectorParseError::UnexpectedIdent(ident.clone()).into()) } Err(e) => return Err(e.into()) } diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index b2445f53dfb..cdf2869f301 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -422,7 +422,7 @@ impl CSSWideKeyword { impl Parse for CSSWideKeyword { fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { - let ident = input.expect_ident()?; + let ident = input.expect_ident()?.clone(); input.expect_exhausted()?; CSSWideKeyword::from_ident(&ident) .ok_or(SelectorParseError::UnexpectedIdent(ident).into()) diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index e49c39bc7b8..c7653a48e15 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -278,12 +278,11 @@ % endfor let first_line_names = input.try(parse_line_names).unwrap_or(vec![].into_boxed_slice()); - if let Ok(s) = input.try(Parser::expect_string) { + if let Ok(mut string) = input.try(|i| i.expect_string().map(|s| s.as_ref().into())) { let mut strings = vec![]; let mut values = vec![]; let mut line_names = vec![]; let mut names = first_line_names.into_vec(); - let mut string = s.into_owned().into_boxed_str(); loop { line_names.push(names.into_boxed_slice()); strings.push(string); @@ -294,8 +293,8 @@ names.extend(v.into_vec()); } - string = match input.try(Parser::expect_string) { - Ok(s) => s.into_owned().into_boxed_str(), + string = match input.try(|i| i.expect_string().map(|s| s.as_ref().into())) { + Ok(s) => s, _ => { // only the named area determines whether we should bail out line_names.push(names.into_boxed_slice()); break diff --git a/components/style/servo/media_queries.rs b/components/style/servo/media_queries.rs index 7583a89f7da..5545ab95051 100644 --- a/components/style/servo/media_queries.rs +++ b/components/style/servo/media_queries.rs @@ -165,7 +165,7 @@ impl Expression { -> Result<Self, ParseError<'i>> { input.expect_parenthesis_block()?; input.parse_nested_block(|input| { - let name = input.expect_ident()?; + let name = input.expect_ident_cloned()?; input.expect_colon()?; // TODO: Handle other media features Ok(Expression(match_ignore_ascii_case! { &name, diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs index b231265775a..ae47b993ebc 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -8,7 +8,7 @@ use {Atom, Prefix, Namespace, LocalName, CaseSensitivityExt}; use attr::{AttrIdentifier, AttrValue}; -use cssparser::{Parser as CssParser, ToCss, serialize_identifier, CompactCowStr}; +use cssparser::{Parser as CssParser, ToCss, serialize_identifier, CowRcStr}; use dom::{OpaqueNode, TElement, TNode}; use element_state::ElementState; use fnv::FnvHashMap; @@ -20,7 +20,6 @@ use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivit use selectors::parser::{SelectorMethods, SelectorParseError}; use selectors::visitor::SelectorVisitor; use std::ascii::AsciiExt; -use std::borrow::Cow; use std::fmt; use std::fmt::Debug; use std::mem; @@ -334,7 +333,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { type Impl = SelectorImpl; type Error = StyleParseError<'i>; - fn parse_non_ts_pseudo_class(&self, name: CompactCowStr<'i>) + fn parse_non_ts_pseudo_class(&self, name: CowRcStr<'i>) -> Result<NonTSPseudoClass, ParseError<'i>> { use self::NonTSPseudoClass::*; let pseudo_class = match_ignore_ascii_case! { &name, @@ -367,19 +366,19 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { } fn parse_non_ts_functional_pseudo_class<'t>(&self, - name: CompactCowStr<'i>, + name: CowRcStr<'i>, parser: &mut CssParser<'i, 't>) -> Result<NonTSPseudoClass, ParseError<'i>> { use self::NonTSPseudoClass::*; let pseudo_class = match_ignore_ascii_case!{ &name, "lang" => { - Lang(parser.expect_ident_or_string()?.into_owned().into_boxed_str()) + Lang(parser.expect_ident_or_string()?.as_ref().into()) } "-servo-case-sensitive-type-attr" => { if !self.in_user_agent_stylesheet() { return Err(SelectorParseError::UnexpectedIdent(name.clone()).into()); } - ServoCaseSensitiveTypeAttr(Atom::from(Cow::from(parser.expect_ident()?))) + ServoCaseSensitiveTypeAttr(Atom::from(parser.expect_ident()?.as_ref())) } _ => return Err(SelectorParseError::UnexpectedIdent(name.clone()).into()) }; @@ -387,7 +386,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { Ok(pseudo_class) } - fn parse_pseudo_element(&self, name: CompactCowStr<'i>) -> Result<PseudoElement, ParseError<'i>> { + fn parse_pseudo_element(&self, name: CowRcStr<'i>) -> Result<PseudoElement, ParseError<'i>> { use self::PseudoElement::*; let pseudo_element = match_ignore_ascii_case! { &name, "before" => Before, diff --git a/components/style/stylesheets/document_rule.rs b/components/style/stylesheets/document_rule.rs index a4390763416..5465a4b9759 100644 --- a/components/style/stylesheets/document_rule.rs +++ b/components/style/stylesheets/document_rule.rs @@ -89,9 +89,9 @@ macro_rules! parse_quoted_or_unquoted_string { let start = input.position(); input.parse_entirely(|input| { match input.next() { - Ok(Token::QuotedString(value)) => - Ok($url_matching_function(value.into_owned())), - Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()), + Ok(&Token::QuotedString(ref value)) => + Ok($url_matching_function(value.as_ref().to_owned())), + Ok(t) => Err(BasicParseError::UnexpectedToken(t.clone()).into()), Err(e) => Err(e.into()), } }).or_else(|_: ParseError| { @@ -112,7 +112,7 @@ impl UrlMatchingFunction { parse_quoted_or_unquoted_string!(input, UrlMatchingFunction::Domain) } else if input.try(|input| input.expect_function_matching("regexp")).is_ok() { input.parse_nested_block(|input| { - Ok(UrlMatchingFunction::RegExp(input.expect_string()?.into_owned())) + Ok(UrlMatchingFunction::RegExp(input.expect_string()?.as_ref().to_owned())) }) } else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) { Ok(UrlMatchingFunction::Url(url)) diff --git a/components/style/stylesheets/keyframes_rule.rs b/components/style/stylesheets/keyframes_rule.rs index 3ae1d8bf9ae..6fe912e517f 100644 --- a/components/style/stylesheets/keyframes_rule.rs +++ b/components/style/stylesheets/keyframes_rule.rs @@ -4,7 +4,7 @@ //! Keyframes: https://drafts.csswg.org/css-animations/#keyframes -use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser, ParserInput, CompactCowStr}; +use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser, ParserInput, CowRcStr}; use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule, SourceLocation}; use error_reporting::{NullReporter, ContextualParseError}; use parser::{ParserContext, log_css_error}; @@ -531,7 +531,7 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeDeclarationParser<'a, 'b> { type Declaration = (); type Error = SelectorParseError<'i, StyleParseError<'i>>; - fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>) + fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>) -> Result<(), ParseError<'i>> { let id = PropertyId::parse(&name) .map_err(|()| PropertyDeclarationParseError::UnknownProperty(name))?; diff --git a/components/style/stylesheets/rule_parser.rs b/components/style/stylesheets/rule_parser.rs index a0923b41232..d4c8b6eec69 100644 --- a/components/style/stylesheets/rule_parser.rs +++ b/components/style/stylesheets/rule_parser.rs @@ -7,7 +7,7 @@ use {Namespace, Prefix}; use counter_style::{parse_counter_style_body, parse_counter_style_name}; use cssparser::{AtRuleParser, AtRuleType, Parser, QualifiedRuleParser, RuleListParser}; -use cssparser::{CompactCowStr, SourceLocation, BasicParseError}; +use cssparser::{CowRcStr, SourceLocation, BasicParseError}; use error_reporting::ContextualParseError; use font_face::parse_font_face_block; use media_queries::{parse_media_query_list, MediaList}; @@ -18,7 +18,6 @@ use selectors::SelectorList; use selectors::parser::SelectorParseError; use servo_arc::Arc; use shared_lock::{Locked, SharedRwLock}; -use std::borrow::Cow; use str::starts_with_ignore_ascii_case; use style_traits::{StyleParseError, ParseError}; use stylesheets::{CssRule, CssRules, CssRuleType, Origin, StylesheetLoader}; @@ -142,7 +141,7 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { fn parse_prelude<'t>( &mut self, - name: CompactCowStr<'i>, + name: CowRcStr<'i>, input: &mut Parser<'i, 't> ) -> Result<AtRuleType<AtRulePrelude, CssRule>, ParseError<'i>> { let location = get_location_with_offset(input.current_source_location(), @@ -156,7 +155,7 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { } self.state = State::Imports; - let url_string = input.expect_url_or_string()?.into_owned(); + let url_string = input.expect_url_or_string()?.as_ref().to_owned(); let specified_url = SpecifiedUrl::parse_from_string(url_string, &self.context)?; let media = parse_media_query_list(&self.context, input); @@ -183,14 +182,14 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { } self.state = State::Namespaces; - let prefix_result = input.try(|input| input.expect_ident()); + let prefix_result = input.try(|i| i.expect_ident_cloned()); let maybe_namespace = match input.expect_url_or_string() { Ok(url_or_string) => url_or_string, Err(BasicParseError::UnexpectedToken(t)) => return Err(StyleParseError::UnexpectedTokenWithinNamespace(t).into()), Err(e) => return Err(e.into()), }; - let url = Namespace::from(Cow::from(maybe_namespace)); + let url = Namespace::from(maybe_namespace.as_ref()); let id = register_namespace(&url) .map_err(|()| StyleParseError::UnspecifiedError)?; @@ -198,7 +197,7 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { let mut namespaces = self.namespaces.as_mut().unwrap(); let opt_prefix = if let Ok(prefix) = prefix_result { - let prefix = Prefix::from(Cow::from(prefix)); + let prefix = Prefix::from(prefix.as_ref()); namespaces .prefixes .insert(prefix.clone(), (url.clone(), id)); @@ -324,7 +323,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { fn parse_prelude<'t>( &mut self, - name: CompactCowStr<'i>, + name: CowRcStr<'i>, input: &mut Parser<'i, 't> ) -> Result<AtRuleType<AtRulePrelude, CssRule>, ParseError<'i>> { let location = diff --git a/components/style/stylesheets/supports_rule.rs b/components/style/stylesheets/supports_rule.rs index 9edc4409fb0..0915b65d36a 100644 --- a/components/style/stylesheets/supports_rule.rs +++ b/components/style/stylesheets/supports_rule.rs @@ -97,14 +97,14 @@ impl SupportsCondition { // End of input return Ok(in_parens) } - Ok(Token::Ident(ident)) => { + Ok(&Token::Ident(ref ident)) => { match_ignore_ascii_case! { &ident, "and" => ("and", SupportsCondition::And as fn(_) -> _), "or" => ("or", SupportsCondition::Or as fn(_) -> _), _ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()) } } - Ok(t) => return Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t))) + Ok(t) => return Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t.clone()))) }; let mut conditions = Vec::with_capacity(2); @@ -126,7 +126,8 @@ impl SupportsCondition { // but we want to not include it in `pos` for the SupportsCondition::FutureSyntax cases. while input.try(Parser::expect_whitespace).is_ok() {} let pos = input.position(); - match input.next()? { + // FIXME: remove clone() when lifetimes are non-lexical + match input.next()?.clone() { Token::ParenthesisBlock => { let nested = input.try(|input| { input.parse_nested_block(|i| parse_condition_or_declaration(i)) @@ -244,7 +245,7 @@ impl Declaration { let mut input = ParserInput::new(&self.0); let mut input = Parser::new(&mut input); input.parse_entirely(|input| { - let prop = input.expect_ident().unwrap(); + let prop = input.expect_ident().unwrap().as_ref().to_owned(); input.expect_colon().unwrap(); let id = PropertyId::parse(&prop) .map_err(|_| StyleParseError::UnspecifiedError)?; diff --git a/components/style/stylesheets/viewport_rule.rs b/components/style/stylesheets/viewport_rule.rs index 015eb33a4f6..3e5a60bd34c 100644 --- a/components/style/stylesheets/viewport_rule.rs +++ b/components/style/stylesheets/viewport_rule.rs @@ -10,7 +10,7 @@ use app_units::Au; use context::QuirksMode; use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, parse_important}; -use cssparser::{CompactCowStr, ToCss as ParserToCss}; +use cssparser::{CowRcStr, ToCss as ParserToCss}; use error_reporting::ContextualParseError; use euclid::TypedSize2D; use font_metrics::get_metrics_provider_for_product; @@ -280,7 +280,7 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for ViewportRuleParser<'a, 'b> { type Declaration = Vec<ViewportDescriptorDeclaration>; type Error = SelectorParseError<'i, StyleParseError<'i>>; - fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>) + fn parse_value<'t>(&mut self, name: CowRcStr<'i>, input: &mut Parser<'i, 't>) -> Result<Vec<ViewportDescriptorDeclaration>, ParseError<'i>> { macro_rules! declaration { ($declaration:ident($parse:expr)) => { diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index b50fb2cf403..f7fb5c8360d 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -100,11 +100,11 @@ impl Parse for GridLine { } grid_line.line_num = Some(i); - } else if let Ok(name) = input.try(|i| i.expect_ident()) { + } else if let Ok(name) = input.try(|i| i.expect_ident_cloned()) { if val_before_span || grid_line.ident.is_some() { return Err(StyleParseError::UnspecifiedError.into()); } - grid_line.ident = Some(CustomIdent::from_ident(name, &[])?); + grid_line.ident = Some(CustomIdent::from_ident(&name, &[])?); } else { break } diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index d93ea570a71..1ad56e08d53 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -151,17 +151,20 @@ impl<T: Parse> Parse for FontSettingTag<T> { use byteorder::{ReadBytesExt, BigEndian}; use std::io::Cursor; - let tag = input.expect_string()?; - - // allowed strings of length 4 containing chars: <U+20, U+7E> - if tag.len() != 4 || - tag.chars().any(|c| c < ' ' || c > '~') + let u_tag; { - return Err(StyleParseError::UnspecifiedError.into()) - } + let tag = input.expect_string()?; - let mut raw = Cursor::new(tag.as_bytes()); - let u_tag = raw.read_u32::<BigEndian>().unwrap(); + // allowed strings of length 4 containing chars: <U+20, U+7E> + if tag.len() != 4 || + tag.chars().any(|c| c < ' ' || c > '~') + { + return Err(StyleParseError::UnspecifiedError.into()) + } + + let mut raw = Cursor::new(tag.as_bytes()); + u_tag = raw.read_u32::<BigEndian>().unwrap(); + } Ok(FontSettingTag { tag: u_tag, value: T::parse(context, input)? }) } diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index caaee1bc36a..616aa5cb485 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -9,11 +9,10 @@ #![deny(missing_docs)] use Atom; -pub use cssparser::{RGBA, Token, Parser, serialize_identifier, BasicParseError, CompactCowStr}; +pub use cssparser::{RGBA, Token, Parser, serialize_identifier, BasicParseError, CowRcStr}; use parser::{Parse, ParserContext}; use selectors::parser::SelectorParseError; use std::ascii::AsciiExt; -use std::borrow::Cow; use std::fmt::{self, Debug}; use std::hash; use style_traits::{ToCss, ParseError, StyleParseError}; @@ -87,18 +86,18 @@ pub struct CustomIdent(pub Atom); impl CustomIdent { /// Parse an already-tokenizer identifier - pub fn from_ident<'i>(ident: CompactCowStr<'i>, excluding: &[&str]) -> Result<Self, ParseError<'i>> { - let valid = match_ignore_ascii_case! { &ident, + pub fn from_ident<'i>(ident: &CowRcStr<'i>, excluding: &[&str]) -> Result<Self, ParseError<'i>> { + let valid = match_ignore_ascii_case! { ident, "initial" | "inherit" | "unset" | "default" => false, _ => true }; if !valid { - return Err(SelectorParseError::UnexpectedIdent(ident).into()); + return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()); } if excluding.iter().any(|s| ident.eq_ignore_ascii_case(s)) { Err(StyleParseError::UnspecifiedError.into()) } else { - Ok(CustomIdent(Atom::from(Cow::from(ident)))) + Ok(CustomIdent(Atom::from(ident.as_ref()))) } } } @@ -121,8 +120,8 @@ pub enum KeyframesName { impl KeyframesName { /// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name - pub fn from_ident(value: String) -> Self { - let custom_ident = CustomIdent::from_ident((&*value).into(), &["none"]).ok(); + pub fn from_ident(value: &str) -> Self { + let custom_ident = CustomIdent::from_ident(&value.into(), &["none"]).ok(); match custom_ident { Some(ident) => KeyframesName::Ident(ident), None => KeyframesName::QuotedString(value.into()), @@ -155,9 +154,9 @@ impl hash::Hash for KeyframesName { impl Parse for KeyframesName { fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { match input.next() { - Ok(Token::Ident(s)) => Ok(KeyframesName::Ident(CustomIdent::from_ident(s, &["none"])?)), - Ok(Token::QuotedString(s)) => Ok(KeyframesName::QuotedString(Atom::from(Cow::from(s)))), - Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()), + Ok(&Token::Ident(ref s)) => Ok(KeyframesName::Ident(CustomIdent::from_ident(s, &["none"])?)), + Ok(&Token::QuotedString(ref s)) => Ok(KeyframesName::QuotedString(Atom::from(s.as_ref()))), + Ok(t) => Err(BasicParseError::UnexpectedToken(t.clone()).into()), Err(e) => Err(e.into()), } } diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index d69c3e88299..d56c42d639c 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -374,7 +374,8 @@ fn parse_normal_or_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignF // <baseline-position> fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> { - try_match_ident_ignore_ascii_case! { input.expect_ident()?, + // FIXME: remove clone() when lifetimes are non-lexical + try_match_ident_ignore_ascii_case! { input.expect_ident()?.clone(), "baseline" => Ok(ALIGN_BASELINE), "first" => { input.expect_ident_matching("baseline")?; @@ -471,7 +472,7 @@ fn parse_self_position<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, // [ legacy && [ left | right | center ] ] fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseError<'i>> { - let a = input.expect_ident()?; + let a = input.expect_ident()?.clone(); let b = input.expect_ident()?; if a.eq_ignore_ascii_case("legacy") { (match_ignore_ascii_case! { &b, @@ -479,7 +480,7 @@ fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseE "right" => Ok(ALIGN_LEGACY | ALIGN_RIGHT), "center" => Ok(ALIGN_LEGACY | ALIGN_CENTER), _ => Err(()) - }).map_err(|()| SelectorParseError::UnexpectedIdent(b).into()) + }).map_err(|()| SelectorParseError::UnexpectedIdent(b.clone()).into()) } else if b.eq_ignore_ascii_case("legacy") { (match_ignore_ascii_case! { &a, "left" => Ok(ALIGN_LEGACY | ALIGN_LEFT), diff --git a/components/style/values/specified/background.rs b/components/style/values/specified/background.rs index db38b873381..88a5f3152c7 100644 --- a/components/style/values/specified/background.rs +++ b/components/style/values/specified/background.rs @@ -27,6 +27,6 @@ impl Parse for BackgroundSize { "cover" => Ok(GenericBackgroundSize::Cover), "contain" => Ok(GenericBackgroundSize::Contain), _ => Err(()), - }).map_err(|()| SelectorParseError::UnexpectedIdent(ident).into()) + }).map_err(|()| SelectorParseError::UnexpectedIdent(ident.clone()).into()) } } diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index fe4b10bb045..4ce3adb2968 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -101,7 +101,7 @@ impl Parse for GeometryBox { impl Parse for BasicShape { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { - let function = input.expect_function()?; + let function = input.expect_function()?.clone(); input.parse_nested_block(move |i| { (match_ignore_ascii_case! { &function, "inset" => return InsetRect::parse_function_arguments(context, i).map(GenericBasicShape::Inset), @@ -109,7 +109,7 @@ impl Parse for BasicShape { "ellipse" => return Ellipse::parse_function_arguments(context, i).map(GenericBasicShape::Ellipse), "polygon" => return Polygon::parse_function_arguments(context, i).map(GenericBasicShape::Polygon), _ => Err(()) - }).map_err(|()| StyleParseError::UnexpectedFunction(function).into()) + }).map_err(|()| StyleParseError::UnexpectedFunction(function.clone()).into()) }) } } diff --git a/components/style/values/specified/calc.rs b/components/style/values/specified/calc.rs index dd29a201e7c..66b94b20ad0 100644 --- a/components/style/values/specified/calc.rs +++ b/components/style/values/specified/calc.rs @@ -150,40 +150,36 @@ impl CalcNode { input: &mut Parser<'i, 't>, expected_unit: CalcUnit ) -> Result<Self, ParseError<'i>> { + // FIXME: remove early returns when lifetimes are non-lexical match (input.next()?, expected_unit) { - (Token::Number { value, .. }, _) => Ok(CalcNode::Number(value)), - (Token::Dimension { value, ref unit, .. }, CalcUnit::Length) | - (Token::Dimension { value, ref unit, .. }, CalcUnit::LengthOrPercentage) => { - NoCalcLength::parse_dimension(context, value, unit) + (&Token::Number { value, .. }, _) => return Ok(CalcNode::Number(value)), + (&Token::Dimension { value, ref unit, .. }, CalcUnit::Length) | + (&Token::Dimension { value, ref unit, .. }, CalcUnit::LengthOrPercentage) => { + return NoCalcLength::parse_dimension(context, value, unit) .map(CalcNode::Length) .map_err(|()| StyleParseError::UnspecifiedError.into()) } - (Token::Dimension { value, ref unit, .. }, CalcUnit::Angle) => { - Angle::parse_dimension(value, unit, /* from_calc = */ true) + (&Token::Dimension { value, ref unit, .. }, CalcUnit::Angle) => { + return Angle::parse_dimension(value, unit, /* from_calc = */ true) .map(CalcNode::Angle) .map_err(|()| StyleParseError::UnspecifiedError.into()) } - (Token::Dimension { value, ref unit, .. }, CalcUnit::Time) => { - Time::parse_dimension(value, unit, /* from_calc = */ true) + (&Token::Dimension { value, ref unit, .. }, CalcUnit::Time) => { + return Time::parse_dimension(value, unit, /* from_calc = */ true) .map(CalcNode::Time) .map_err(|()| StyleParseError::UnspecifiedError.into()) } - (Token::Percentage { unit_value, .. }, CalcUnit::LengthOrPercentage) | - (Token::Percentage { unit_value, .. }, CalcUnit::Percentage) => { - Ok(CalcNode::Percentage(unit_value)) + (&Token::Percentage { unit_value, .. }, CalcUnit::LengthOrPercentage) | + (&Token::Percentage { unit_value, .. }, CalcUnit::Percentage) => { + return Ok(CalcNode::Percentage(unit_value)) } - (Token::ParenthesisBlock, _) => { - input.parse_nested_block(|i| { - CalcNode::parse(context, i, expected_unit) - }) - } - (Token::Function(ref name), _) if name.eq_ignore_ascii_case("calc") => { - input.parse_nested_block(|i| { - CalcNode::parse(context, i, expected_unit) - }) - } - (t, _) => Err(BasicParseError::UnexpectedToken(t).into()) + (&Token::ParenthesisBlock, _) => {} + (&Token::Function(ref name), _) if name.eq_ignore_ascii_case("calc") => {} + (t, _) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()) } + input.parse_nested_block(|i| { + CalcNode::parse(context, i, expected_unit) + }) } /// Parse a top-level `calc` expression, with all nested sub-expressions. @@ -200,11 +196,12 @@ impl CalcNode { loop { let position = input.position(); match input.next_including_whitespace() { - Ok(Token::WhiteSpace(_)) => { + Ok(&Token::WhiteSpace(_)) => { if input.is_exhausted() { break; // allow trailing whitespace } - match input.next()? { + // FIXME: remove clone() when lifetimes are non-lexical + match input.next()?.clone() { Token::Delim('+') => { let rhs = Self::parse_product(context, input, expected_unit)?; @@ -252,13 +249,13 @@ impl CalcNode { loop { let position = input.position(); match input.next() { - Ok(Token::Delim('*')) => { + Ok(&Token::Delim('*')) => { let rhs = Self::parse_one(context, input, expected_unit)?; let new_root = CalcNode::Mul(Box::new(root), Box::new(rhs)); root = new_root; } // TODO(emilio): Figure out why the `Integer` check. - Ok(Token::Delim('/')) if expected_unit != CalcUnit::Integer => { + Ok(&Token::Delim('/')) if expected_unit != CalcUnit::Integer => { let rhs = Self::parse_one(context, input, expected_unit)?; let new_root = CalcNode::Div(Box::new(root), Box::new(rhs)); root = new_root; diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 7120e7a86ee..2f91768cc5c 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -72,7 +72,7 @@ impl Parse for Color { // specified value. let start_position = input.position(); let authored = match input.next() { - Ok(Token::Ident(s)) => Some(s.to_lowercase().into_boxed_str()), + Ok(&Token::Ident(ref s)) => Some(s.to_lowercase().into_boxed_str()), _ => None, }; input.reset(start_position); @@ -173,22 +173,22 @@ impl Color { /// /// https://quirks.spec.whatwg.org/#the-hashless-hex-color-quirk fn parse_quirky_color<'i, 't>(input: &mut Parser<'i, 't>) -> Result<RGBA, ParseError<'i>> { - let (value, unit) = match input.next()? { + let (value, unit) = match *input.next()? { Token::Number { int_value: Some(integer), .. } => { (integer, None) }, - Token::Dimension { int_value: Some(integer), unit, .. } => { + Token::Dimension { int_value: Some(integer), ref unit, .. } => { (integer, Some(unit)) }, - Token::Ident(ident) => { + Token::Ident(ref ident) => { if ident.len() != 3 && ident.len() != 6 { return Err(StyleParseError::UnspecifiedError.into()); } return parse_hash_color(ident.as_bytes()) .map_err(|()| StyleParseError::UnspecifiedError.into()); } - t => { - return Err(BasicParseError::UnexpectedToken(t).into()); + ref t => { + return Err(BasicParseError::UnexpectedToken(t.clone()).into()); }, }; if value < 0 { diff --git a/components/style/values/specified/effects.rs b/components/style/values/specified/effects.rs index c8b21d59d7e..134827e958e 100644 --- a/components/style/values/specified/effects.rs +++ b/components/style/values/specified/effects.rs @@ -159,7 +159,7 @@ impl Parse for Filter { return Ok(GenericFilter::Url(url)); } } - let function = input.expect_function()?; + let function = input.expect_function()?.clone(); input.parse_nested_block(|i| { try_match_ident_ignore_ascii_case! { function, "blur" => Ok(GenericFilter::Blur(Length::parse_non_negative(context, i)?)), diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index 81b60bdad6b..beb1459e76d 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -18,10 +18,10 @@ use values::specified::LengthOrPercentage; /// Parse a single flexible length. pub fn parse_flex<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CSSFloat, ParseError<'i>> { - match input.next()? { + match *input.next()? { Token::Dimension { value, ref unit, .. } if unit.eq_ignore_ascii_case("fr") && value.is_sign_positive() => Ok(value), - t => Err(BasicParseError::UnexpectedToken(t).into()), + ref t => Err(BasicParseError::UnexpectedToken(t.clone()).into()), } } @@ -85,8 +85,8 @@ pub fn parse_line_names<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Box<[Custo input.expect_square_bracket_block()?; input.parse_nested_block(|input| { let mut values = vec![]; - while let Ok(ident) = input.try(|i| i.expect_ident()) { - let ident = CustomIdent::from_ident(ident, &["span"])?; + while let Ok(ident) = input.try(|i| i.expect_ident_cloned()) { + let ident = CustomIdent::from_ident(&ident, &["span"])?; values.push(ident); } diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 6b0794243aa..840f4ed1cf3 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -13,7 +13,6 @@ use parser::{Parse, ParserContext}; use selectors::parser::SelectorParseError; #[cfg(feature = "servo")] use servo_url::ServoUrl; -use std::borrow::Cow; use std::cmp::Ordering; use std::f32::consts::PI; use std::fmt; @@ -169,9 +168,9 @@ impl Image { fn parse_element<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Atom, ParseError<'i>> { input.try(|i| i.expect_function_matching("-moz-element"))?; input.parse_nested_block(|i| { - match i.next()? { - Token::IDHash(id) => Ok(Atom::from(Cow::from(id))), - t => Err(BasicParseError::UnexpectedToken(t).into()), + match *i.next()? { + Token::IDHash(ref id) => Ok(Atom::from(id.as_ref())), + ref t => Err(BasicParseError::UnexpectedToken(t.clone()).into()), } }) } @@ -184,7 +183,8 @@ impl Parse for Gradient { Radial, } - let func = input.expect_function()?; + // FIXME: remove clone() when lifetimes are non-lexical + let func = input.expect_function()?.clone(); let result = match_ignore_ascii_case! { &func, "linear-gradient" => { Some((Shape::Linear, false, CompatMode::Modern)) @@ -234,7 +234,7 @@ impl Parse for Gradient { let (shape, repeating, mut compat_mode) = match result { Some(result) => result, - None => return Err(StyleParseError::UnexpectedFunction(func).into()), + None => return Err(StyleParseError::UnexpectedFunction(func.clone()).into()), }; let (kind, items) = input.parse_nested_block(|i| { @@ -389,7 +389,7 @@ impl Gradient { } } - let ident = input.expect_ident()?; + let ident = input.expect_ident_cloned()?; input.expect_comma()?; let (kind, reverse_stops) = match_ignore_ascii_case! { &ident, @@ -439,7 +439,7 @@ impl Gradient { let mut items = input.try(|i| { i.expect_comma()?; i.parse_comma_separated(|i| { - let function = i.expect_function()?; + let function = i.expect_function()?.clone(); let (color, mut p) = i.parse_nested_block(|i| { let p = match_ignore_ascii_case! { &function, "color-stop" => { @@ -879,7 +879,7 @@ impl Parse for PaintWorklet { input.parse_nested_block(|i| { let name = i.expect_ident()?; Ok(PaintWorklet { - name: Atom::from(Cow::from(name)), + name: Atom::from(name.as_ref()), }) }) } @@ -890,7 +890,7 @@ impl Parse for MozImageRect { input.try(|i| i.expect_function_matching("-moz-image-rect"))?; input.parse_nested_block(|i| { let string = i.expect_url_or_string()?; - let url = SpecifiedUrl::parse_from_string(string.into_owned(), context)?; + let url = SpecifiedUrl::parse_from_string(string.as_ref().to_owned(), context)?; i.expect_comma()?; let top = NumberOrPercentage::parse_non_negative(context, i)?; i.expect_comma()?; diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 3ec01f06545..c3591bdf484 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -619,26 +619,29 @@ impl Length { num_context: AllowedLengthType, allow_quirks: AllowQuirks) -> Result<Length, ParseError<'i>> { - let token = input.next()?; - match token { - Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => { - Length::parse_dimension(context, value, unit) - } - Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { - if value != 0. && - !context.parsing_mode.allows_unitless_lengths() && - !allow_quirks.allowed(context.quirks_mode) { - return Err(StyleParseError::UnspecifiedError.into()) + // FIXME: remove early returns when lifetimes are non-lexical + { + let token = input.next()?; + match *token { + Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => { + return Length::parse_dimension(context, value, unit) + .map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into()) } - Ok(Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(value)))) - }, - Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - return input.parse_nested_block(|input| { - CalcNode::parse_length(context, input, num_context).map(|calc| Length::Calc(Box::new(calc))) - }) + Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { + if value != 0. && + !context.parsing_mode.allows_unitless_lengths() && + !allow_quirks.allowed(context.quirks_mode) { + return Err(StyleParseError::UnspecifiedError.into()) + } + return Ok(Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(value)))) + }, + Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {} + ref token => return Err(BasicParseError::UnexpectedToken(token.clone()).into()) } - _ => Err(()) - }.map_err(|()| BasicParseError::UnexpectedToken(token).into()) + } + input.parse_nested_block(|input| { + CalcNode::parse_length(context, input, num_context).map(|calc| Length::Calc(Box::new(calc))) + }) } /// Parse a non-negative length @@ -761,24 +764,25 @@ impl Percentage { input: &mut Parser<'i, 't>, num_context: AllowedNumericType, ) -> Result<Self, ParseError<'i>> { - match input.next()? { + // FIXME: remove early returns when lifetimes are non-lexical + match *input.next()? { Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => { - Ok(Percentage::new(unit_value)) - } - Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - let result = input.parse_nested_block(|i| { - CalcNode::parse_percentage(context, i) - })?; - - // TODO(emilio): -moz-image-rect is the only thing that uses - // the clamping mode... I guess we could disallow it... - Ok(Percentage { - value: result, - calc_clamping_mode: Some(num_context), - }) + return Ok(Percentage::new(unit_value)) } - t => Err(BasicParseError::UnexpectedToken(t).into()) + Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {} + ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()) } + + let result = input.parse_nested_block(|i| { + CalcNode::parse_percentage(context, i) + })?; + + // TODO(emilio): -moz-image-rect is the only thing that uses + // the clamping mode... I guess we could disallow it... + Ok(Percentage { + value: result, + calc_clamping_mode: Some(num_context), + }) } /// Parses a percentage token, but rejects it if it's negative. @@ -877,31 +881,36 @@ impl LengthOrPercentage { allow_quirks: AllowQuirks) -> Result<LengthOrPercentage, ParseError<'i>> { - let token = input.next()?; - match token { - Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => { - NoCalcLength::parse_dimension(context, value, unit).map(LengthOrPercentage::Length) - } - Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => { - return Ok(LengthOrPercentage::Percentage(computed::Percentage(unit_value))) - } - Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { - if value != 0. && - !context.parsing_mode.allows_unitless_lengths() && - !allow_quirks.allowed(context.quirks_mode) { - Err(()) - } else { - return Ok(LengthOrPercentage::Length(NoCalcLength::from_px(value))) + // FIXME: remove early returns when lifetimes are non-lexical + { + let token = input.next()?; + match *token { + Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => { + return NoCalcLength::parse_dimension(context, value, unit) + .map(LengthOrPercentage::Length) + .map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into()) } + Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => { + return Ok(LengthOrPercentage::Percentage(computed::Percentage(unit_value))) + } + Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { + if value != 0. && + !context.parsing_mode.allows_unitless_lengths() && + !allow_quirks.allowed(context.quirks_mode) { + return Err(BasicParseError::UnexpectedToken(token.clone()).into()) + } else { + return Ok(LengthOrPercentage::Length(NoCalcLength::from_px(value))) + } + } + Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {} + _ => return Err(BasicParseError::UnexpectedToken(token.clone()).into()) } - Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - let calc = input.parse_nested_block(|i| { - CalcNode::parse_length_or_percentage(context, i, num_context) - })?; - return Ok(LengthOrPercentage::Calc(Box::new(calc))) - } - _ => Err(()) - }.map_err(|()| BasicParseError::UnexpectedToken(token).into()) + } + + let calc = input.parse_nested_block(|i| { + CalcNode::parse_length_or_percentage(context, i, num_context) + })?; + Ok(LengthOrPercentage::Calc(Box::new(calc))) } /// Parse a non-negative length. @@ -1013,35 +1022,40 @@ impl LengthOrPercentageOrAuto { num_context: AllowedLengthType, allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> { - let token = input.next()?; - match token { - Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => { - NoCalcLength::parse_dimension(context, value, unit).map(LengthOrPercentageOrAuto::Length) - } - Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => { - Ok(LengthOrPercentageOrAuto::Percentage(computed::Percentage(unit_value))) - } - Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { - if value != 0. && - !context.parsing_mode.allows_unitless_lengths() && - !allow_quirks.allowed(context.quirks_mode) { - return Err(StyleParseError::UnspecifiedError.into()) + // FIXME: remove early returns when lifetimes are non-lexical + { + let token = input.next()?; + match *token { + Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => { + return NoCalcLength::parse_dimension(context, value, unit) + .map(LengthOrPercentageOrAuto::Length) + .map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into()) } - Ok(LengthOrPercentageOrAuto::Length( - NoCalcLength::Absolute(AbsoluteLength::Px(value)) - )) - } - Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => { - Ok(LengthOrPercentageOrAuto::Auto) - } - Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - let calc = input.parse_nested_block(|i| { - CalcNode::parse_length_or_percentage(context, i, num_context) - })?; - Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc))) + Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => { + return Ok(LengthOrPercentageOrAuto::Percentage(computed::Percentage(unit_value))) + } + Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { + if value != 0. && + !context.parsing_mode.allows_unitless_lengths() && + !allow_quirks.allowed(context.quirks_mode) { + return Err(StyleParseError::UnspecifiedError.into()) + } + return Ok(LengthOrPercentageOrAuto::Length( + NoCalcLength::Absolute(AbsoluteLength::Px(value)) + )) + } + Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => { + return Ok(LengthOrPercentageOrAuto::Auto) + } + Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {} + _ => return Err(BasicParseError::UnexpectedToken(token.clone()).into()) } - _ => Err(()) - }.map_err(|()| BasicParseError::UnexpectedToken(token).into()) + } + + let calc = input.parse_nested_block(|i| { + CalcNode::parse_length_or_percentage(context, i, num_context) + })?; + Ok(LengthOrPercentageOrAuto::Calc(Box::new(calc))) } /// Parse a non-negative length, percentage, or auto. @@ -1112,33 +1126,39 @@ impl LengthOrPercentageOrNone { allow_quirks: AllowQuirks) -> Result<LengthOrPercentageOrNone, ParseError<'i>> { - let token = input.next()?; - match token { - Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => { - NoCalcLength::parse_dimension(context, value, unit).map(LengthOrPercentageOrNone::Length) - } - Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => { - Ok(LengthOrPercentageOrNone::Percentage(computed::Percentage(unit_value))) - } - Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { - if value != 0. && !context.parsing_mode.allows_unitless_lengths() && - !allow_quirks.allowed(context.quirks_mode) { - return Err(StyleParseError::UnspecifiedError.into()) + // FIXME: remove early returns when lifetimes are non-lexical + { + let token = input.next()?; + match *token { + Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => { + return NoCalcLength::parse_dimension(context, value, unit) + .map(LengthOrPercentageOrNone::Length) + .map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into()) } - Ok(LengthOrPercentageOrNone::Length( - NoCalcLength::Absolute(AbsoluteLength::Px(value)) - )) - } - Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - let calc = input.parse_nested_block(|i| { - CalcNode::parse_length_or_percentage(context, i, num_context) - })?; - Ok(LengthOrPercentageOrNone::Calc(Box::new(calc))) + Token::Percentage { unit_value, .. } if num_context.is_ok(context.parsing_mode, unit_value) => { + return Ok(LengthOrPercentageOrNone::Percentage(computed::Percentage(unit_value))) + } + Token::Number { value, .. } if num_context.is_ok(context.parsing_mode, value) => { + if value != 0. && !context.parsing_mode.allows_unitless_lengths() && + !allow_quirks.allowed(context.quirks_mode) { + return Err(StyleParseError::UnspecifiedError.into()) + } + return Ok(LengthOrPercentageOrNone::Length( + NoCalcLength::Absolute(AbsoluteLength::Px(value)) + )) + } + Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {} + Token::Ident(ref value) if value.eq_ignore_ascii_case("none") => { + return Ok(LengthOrPercentageOrNone::None) + } + _ => return Err(BasicParseError::UnexpectedToken(token.clone()).into()) } - Token::Ident(ref value) if value.eq_ignore_ascii_case("none") => - Ok(LengthOrPercentageOrNone::None), - _ => Err(()) - }.map_err(|()| BasicParseError::UnexpectedToken(token).into()) + } + + let calc = input.parse_nested_block(|i| { + CalcNode::parse_length_or_percentage(context, i, num_context) + })?; + Ok(LengthOrPercentageOrNone::Calc(Box::new(calc))) } /// Parse a non-negative LengthOrPercentageOrNone. diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index dd34f9bdbeb..a3026907bde 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -12,7 +12,6 @@ use cssparser::{Parser, Token, serialize_identifier, BasicParseError}; use parser::{ParserContext, Parse}; use self::url::SpecifiedUrl; use std::ascii::AsciiExt; -use std::borrow::Cow; use std::f32; use std::fmt; use style_traits::{ToCss, ParseError, StyleParseError}; @@ -83,7 +82,7 @@ pub use ::gecko::url::*; impl Parse for SpecifiedUrl { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { let url = input.expect_url()?; - Self::parse_from_string(url.into_owned(), context) + Self::parse_from_string(url.as_ref().to_owned(), context) } } @@ -98,17 +97,18 @@ no_viewport_percentage!(SpecifiedUrl); /// Parse an `<integer>` value, handling `calc()` correctly. pub fn parse_integer<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Integer, ParseError<'i>> { - match input.next()? { - Token::Number { int_value: Some(v), .. } => Ok(Integer::new(v)), - Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - let result = input.parse_nested_block(|i| { - CalcNode::parse_integer(context, i) - })?; - - Ok(Integer::from_calc(result)) - } - t => Err(BasicParseError::UnexpectedToken(t).into()) + // FIXME: remove early returns when lifetimes are non-lexical + match *input.next()? { + Token::Number { int_value: Some(v), .. } => return Ok(Integer::new(v)), + Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {} + ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()) } + + let result = input.parse_nested_block(|i| { + CalcNode::parse_integer(context, i) + })?; + + Ok(Integer::from_calc(result)) } /// Parse a `<number>` value, handling `calc()` correctly, and without length @@ -123,25 +123,26 @@ pub fn parse_number_with_clamping_mode<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>, clamping_mode: AllowedNumericType) -> Result<Number, ParseError<'i>> { - match input.next()? { + // FIXME: remove early returns when lifetimes are non-lexical + match *input.next()? { Token::Number { value, .. } if clamping_mode.is_ok(context.parsing_mode, value) => { - Ok(Number { + return Ok(Number { value: value.min(f32::MAX).max(f32::MIN), calc_clamping_mode: None, }) - }, - Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - let result = input.parse_nested_block(|i| { - CalcNode::parse_number(context, i) - })?; - - Ok(Number { - value: result.min(f32::MAX).max(f32::MIN), - calc_clamping_mode: Some(clamping_mode), - }) } - t => Err(BasicParseError::UnexpectedToken(t).into()) + Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {} + ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()) } + + let result = input.parse_nested_block(|i| { + CalcNode::parse_number(context, i) + })?; + + Ok(Number { + value: result.min(f32::MAX).max(f32::MIN), + calc_clamping_mode: Some(clamping_mode), + }) } #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] @@ -228,7 +229,8 @@ impl Angle { impl Parse for Angle { /// Parses an angle according to CSS-VALUES § 6.1. fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { - let token = input.next()?; + // FIXME: remove clone() when lifetimes are non-lexical + let token = input.next()?.clone(); match token { Token::Dimension { value, ref unit, .. } => { Angle::parse_dimension(value, unit, /* from_calc = */ false) @@ -237,7 +239,7 @@ impl Parse for Angle { return input.parse_nested_block(|i| CalcNode::parse_angle(context, i)) } _ => Err(()) - }.map_err(|()| BasicParseError::UnexpectedToken(token).into()) + }.map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into()) } } @@ -268,7 +270,8 @@ impl Angle { /// https://github.com/w3c/csswg-drafts/issues/1162 is resolved. pub fn parse_with_unitless<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { - let token = input.next()?; + // FIXME: remove clone() when lifetimes are non-lexical + let token = input.next()?.clone(); match token { Token::Dimension { value, ref unit, .. } => { Angle::parse_dimension(value, unit, /* from_calc = */ false) @@ -278,7 +281,7 @@ impl Angle { return input.parse_nested_block(|i| CalcNode::parse_angle(context, i)) } _ => Err(()) - }.map_err(|()| BasicParseError::UnexpectedToken(token).into()) + }.map_err(|()| BasicParseError::UnexpectedToken(token.clone()).into()) } } @@ -366,24 +369,24 @@ impl Time { -> Result<Self, ParseError<'i>> { use style_traits::PARSING_MODE_DEFAULT; + // FIXME: remove early returns when lifetimes are non-lexical match input.next() { // Note that we generally pass ParserContext to is_ok() to check // that the ParserMode of the ParserContext allows all numeric // values for SMIL regardless of clamping_mode, but in this Time // value case, the value does not animate for SMIL at all, so we use // PARSING_MODE_DEFAULT directly. - Ok(Token::Dimension { value, ref unit, .. }) if clamping_mode.is_ok(PARSING_MODE_DEFAULT, value) => { - Time::parse_dimension(value, unit, /* from_calc = */ false) + Ok(&Token::Dimension { value, ref unit, .. }) if clamping_mode.is_ok(PARSING_MODE_DEFAULT, value) => { + return Time::parse_dimension(value, unit, /* from_calc = */ false) .map_err(|()| StyleParseError::UnspecifiedError.into()) } - Ok(Token::Function(ref name)) if name.eq_ignore_ascii_case("calc") => { - match input.parse_nested_block(|i| CalcNode::parse_time(context, i)) { - Ok(time) if clamping_mode.is_ok(PARSING_MODE_DEFAULT, time.seconds) => Ok(time), - _ => Err(StyleParseError::UnspecifiedError.into()), - } - } - Ok(t) => Err(BasicParseError::UnexpectedToken(t).into()), - Err(e) => Err(e.into()) + Ok(&Token::Function(ref name)) if name.eq_ignore_ascii_case("calc") => {} + Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()), + Err(e) => return Err(e.into()) + } + match input.parse_nested_block(|i| CalcNode::parse_time(context, i)) { + Ok(time) if clamping_mode.is_ok(PARSING_MODE_DEFAULT, time.seconds) => Ok(time), + _ => Err(StyleParseError::UnspecifiedError.into()), } } @@ -814,10 +817,7 @@ impl ClipRect { } } - let func = input.expect_function()?; - if !func.eq_ignore_ascii_case("rect") { - return Err(StyleParseError::UnexpectedFunction(func).into()) - } + input.expect_function_matching("rect")?; input.parse_nested_block(|input| { let top = parse_argument(context, input, allow_quirks)?; @@ -939,20 +939,20 @@ impl Attr { -> Result<Attr, ParseError<'i>> { // Syntax is `[namespace? `|`]? ident` // no spaces allowed - let first = input.try(|i| i.expect_ident()).ok(); - if let Ok(token) = input.try(|i| i.next_including_whitespace()) { + let first = input.try(|i| i.expect_ident_cloned()).ok(); + if let Ok(token) = input.try(|i| i.next_including_whitespace().map(|t| t.clone())) { match token { Token::Delim('|') => {} - t => return Err(BasicParseError::UnexpectedToken(t).into()), + ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()), } // must be followed by an ident - let second_token = match input.next_including_whitespace()? { - Token::Ident(second) => second, - t => return Err(BasicParseError::UnexpectedToken(t).into()), + let second_token = match *input.next_including_whitespace()? { + Token::Ident(ref second) => second, + ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()), }; let ns_with_id = if let Some(ns) = first { - let ns = Namespace::from(Cow::from(ns)); + let ns = Namespace::from(ns.as_ref()); let id: Result<_, ParseError> = get_id_for_namespace(&ns, context) .map_err(|()| StyleParseError::UnspecifiedError.into()); @@ -962,14 +962,14 @@ impl Attr { }; return Ok(Attr { namespace: ns_with_id, - attribute: second_token.into_owned(), + attribute: second_token.as_ref().to_owned(), }) } if let Some(first) = first { Ok(Attr { namespace: None, - attribute: first.into_owned(), + attribute: first.as_ref().to_owned(), }) } else { Err(StyleParseError::UnspecifiedError.into()) diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index 2fc8252f24f..2c0395128c6 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -73,7 +73,7 @@ impl Parse for LineHeight { ref ident if ident.eq_ignore_ascii_case("-moz-block-height") => { Ok(GenericLineHeight::MozBlockHeight) }, - ident => Err(SelectorParseError::UnexpectedIdent(ident).into()), + ident => Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()), } } } diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index e169181f725..ef087e3fcdf 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -147,7 +147,7 @@ impl Parse for TimingFunction { if let Ok(keyword) = input.try(TimingKeyword::parse) { return Ok(GenericTimingFunction::Keyword(keyword)); } - if let Ok(ident) = input.try(|i| i.expect_ident()) { + if let Ok(ident) = input.try(|i| i.expect_ident_cloned()) { let position = match_ignore_ascii_case! { &ident, "step-start" => StepPosition::Start, "step-end" => StepPosition::End, @@ -155,7 +155,7 @@ impl Parse for TimingFunction { }; return Ok(GenericTimingFunction::Steps(Integer::new(1), position)); } - let function = input.expect_function()?; + let function = input.expect_function()?.clone(); input.parse_nested_block(move |i| { (match_ignore_ascii_case! { &function, "cubic-bezier" => { @@ -190,7 +190,7 @@ impl Parse for TimingFunction { } }, _ => Err(()), - }).map_err(|()| StyleParseError::UnexpectedFunction(function).into()) + }).map_err(|()| StyleParseError::UnexpectedFunction(function.clone()).into()) }) } } diff --git a/components/style_traits/Cargo.toml b/components/style_traits/Cargo.toml index 3473d710353..a4dcdc20fc5 100644 --- a/components/style_traits/Cargo.toml +++ b/components/style_traits/Cargo.toml @@ -16,7 +16,7 @@ gecko = [] [dependencies] app_units = "0.5" bitflags = "0.7" -cssparser = "0.17.0" +cssparser = "0.18" euclid = "0.15" heapsize = {version = "0.4", optional = true} heapsize_derive = {version = "0.1", optional = true} diff --git a/components/style_traits/lib.rs b/components/style_traits/lib.rs index 5047388ac37..1747783e2b0 100644 --- a/components/style_traits/lib.rs +++ b/components/style_traits/lib.rs @@ -22,7 +22,7 @@ extern crate euclid; extern crate selectors; #[cfg(feature = "servo")] #[macro_use] extern crate serde; -use cssparser::{CompactCowStr, Token}; +use cssparser::{CowRcStr, Token}; use selectors::parser::SelectorParseError; /// Opaque type stored in type-unsafe work queues for parallel layout. @@ -87,9 +87,9 @@ pub type ParseError<'i> = cssparser::ParseError<'i, SelectorParseError<'i, Style /// Errors that can be encountered while parsing CSS values. pub enum StyleParseError<'i> { /// A bad URL token in a DVB. - BadUrlInDeclarationValueBlock(CompactCowStr<'i>), + BadUrlInDeclarationValueBlock(CowRcStr<'i>), /// A bad string token in a DVB. - BadStringInDeclarationValueBlock(CompactCowStr<'i>), + BadStringInDeclarationValueBlock(CowRcStr<'i>), /// Unexpected closing parenthesis in a DVB. UnbalancedCloseParenthesisInDeclarationValueBlock, /// Unexpected closing bracket in a DVB. @@ -101,11 +101,11 @@ pub enum StyleParseError<'i> { /// A property declaration value had input remaining after successfully parsing. PropertyDeclarationValueNotExhausted, /// An unexpected dimension token was encountered. - UnexpectedDimension(CompactCowStr<'i>), + UnexpectedDimension(CowRcStr<'i>), /// A media query using a ranged expression with no value was encountered. RangedExpressionWithNoValue, /// A function was encountered that was not expected. - UnexpectedFunction(CompactCowStr<'i>), + UnexpectedFunction(CowRcStr<'i>), /// @namespace must be before any rule but @charset and @import UnexpectedNamespaceRule, /// @import must be before any rule but @charset @@ -113,7 +113,7 @@ pub enum StyleParseError<'i> { /// Unexpected @charset rule encountered. UnexpectedCharsetRule, /// Unsupported @ rule - UnsupportedAtRule(CompactCowStr<'i>), + UnsupportedAtRule(CowRcStr<'i>), /// A placeholder for many sources of errors that require more specific variants. UnspecifiedError, /// An unexpected token was found within a namespace rule. @@ -124,13 +124,13 @@ pub enum StyleParseError<'i> { #[derive(Eq, PartialEq, Clone, Debug)] pub enum PropertyDeclarationParseError<'i> { /// The property declaration was for an unknown property. - UnknownProperty(CompactCowStr<'i>), + UnknownProperty(CowRcStr<'i>), /// An unknown vendor-specific identifier was encountered. UnknownVendorProperty, /// The property declaration was for a disabled experimental property. ExperimentalProperty, /// The property declaration contained an invalid value. - InvalidValue(CompactCowStr<'i>), + InvalidValue(CowRcStr<'i>), /// The declaration contained an animation property, and we were parsing /// this as a keyframe block (so that property should be ignored). /// diff --git a/components/style_traits/values.rs b/components/style_traits/values.rs index 6024eae4054..0d0d74b1fa9 100644 --- a/components/style_traits/values.rs +++ b/components/style_traits/values.rs @@ -409,7 +409,7 @@ macro_rules! __define_css_keyword_enum__actual { Self::from_ident(&ident) .map_err(|()| ::cssparser::ParseError::Basic( ::cssparser::BasicParseError::UnexpectedToken( - ::cssparser::Token::Ident(ident)))) + ::cssparser::Token::Ident(ident.clone())))) } /// Parse this property from an already-tokenized identifier. diff --git a/components/style_traits/viewport.rs b/components/style_traits/viewport.rs index 002aa16ab51..01d9b541ac3 100644 --- a/components/style_traits/viewport.rs +++ b/components/style_traits/viewport.rs @@ -154,7 +154,7 @@ impl Zoom { use cssparser::Token; use values::specified::AllowedLengthType::NonNegative; - match input.next()? { + match *input.next()? { // TODO: This parse() method should take ParserContext as an // argument, and pass ParsingMode owned by the ParserContext to // is_ok() instead of using PARSING_MODE_DEFAULT directly. @@ -168,7 +168,7 @@ impl Zoom { Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") => { Ok(Zoom::Auto) } - t => Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t))) + ref t => Err(CssParseError::Basic(BasicParseError::UnexpectedToken(t.clone()))) } } |