servo: Merge #19556 - Move list quotes out of mako (from emilio:quotes-mako); r=emilio
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 14 Dec 2017 01:39:38 -0600
changeset 396406 1e60dbbef9973cccdaabfec0b40ee27be873a9da
parent 396405 f8d18d87288cbc3657b6a38d7449d4d36365e048
child 396407 97043a5a2d5e47c600408cefb258de9d6f5e1d5e
push id56987
push userservo-vcs-sync@mozilla.com
push dateThu, 14 Dec 2017 16:00:28 +0000
treeherderautoland@1e60dbbef997 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
servo: Merge #19556 - Move list quotes out of mako (from emilio:quotes-mako); r=emilio Rebase of https://github.com/servo/servo/pull/19154. Source-Repo: https://github.com/servo/servo Source-Revision: 26feea3be5bc70fed7a642ca768187d29469fee0
servo/components/layout/generated_content.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/list.mako.rs
servo/components/style/values/computed/list.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/specified/list.rs
servo/components/style/values/specified/mod.rs
--- a/servo/components/layout/generated_content.rs
+++ b/servo/components/layout/generated_content.rs
@@ -306,19 +306,19 @@ impl<'a, 'b> ResolveGeneratedContentFrag
         }
         let &(ref open_quote, ref close_quote) =
             if self.traversal.quote as usize >= quotes.0.len() {
                 quotes.0.last().unwrap()
             } else {
                 &quotes.0[self.traversal.quote as usize]
             };
         if close {
-            close_quote.clone()
+            close_quote.to_string()
         } else {
-            open_quote.clone()
+            open_quote.to_string()
         }
     }
 }
 
 /// A counter per CSS 2.1 ยง 12.4.
 struct Counter {
     /// The values at each level.
     values: Vec<CounterValue>,
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -4224,18 +4224,21 @@ fn static_assert() {
         self.copy_quotes_from(other)
     }
 
     pub fn clone_quotes(&self) -> longhands::quotes::computed_value::T {
         unsafe {
             let ref gecko_quote_values = *self.gecko.mQuotes.mRawPtr;
             longhands::quotes::computed_value::T(
                 gecko_quote_values.mQuotePairs.iter().map(|gecko_pair| {
-                    (gecko_pair.first.to_string(), gecko_pair.second.to_string())
-                }).collect()
+                    (
+                        gecko_pair.first.to_string().into_boxed_str(),
+                        gecko_pair.second.to_string().into_boxed_str(),
+                    )
+                }).collect::<Vec<_>>().into_boxed_slice()
             )
         }
     }
 
     #[allow(non_snake_case)]
     pub fn set__moz_image_region(&mut self, v: longhands::_moz_image_region::computed_value::T) {
         use values::Either;
 
--- a/servo/components/style/properties/longhand/list.mako.rs
+++ b/servo/components/style/properties/longhand/list.mako.rs
@@ -130,86 +130,21 @@
         % else :
         let value = input.try(|input| UrlOrNone::parse(context, input))?;
         % endif
 
         return Ok(SpecifiedValue(value));
     }
 </%helpers:longhand>
 
-<%helpers:longhand name="quotes" animation_value_type="discrete"
-                   spec="https://drafts.csswg.org/css-content/#propdef-quotes">
-    use cssparser::serialize_string;
-    use std::fmt;
-    use style_traits::ToCss;
-
-    pub use self::computed_value::T as SpecifiedValue;
-
-    pub mod computed_value {
-        #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
-        pub struct T(pub Vec<(String, String)>);
-    }
-
-    impl ToCss for SpecifiedValue {
-        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            if self.0.is_empty() {
-                return dest.write_str("none")
-            }
-
-            let mut first = true;
-            for pair in &self.0 {
-                if !first {
-                    dest.write_str(" ")?;
-                }
-                first = false;
-                serialize_string(&*pair.0, dest)?;
-                dest.write_str(" ")?;
-                serialize_string(&*pair.1, dest)?;
-            }
-            Ok(())
-        }
-    }
-
-    #[inline]
-    pub fn get_initial_value() -> computed_value::T {
-        computed_value::T(vec![
-            ("\u{201c}".to_owned(), "\u{201d}".to_owned()),
-            ("\u{2018}".to_owned(), "\u{2019}".to_owned()),
-        ])
-    }
-
-    pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
-                         -> Result<SpecifiedValue,ParseError<'i>> {
-        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
-            return Ok(SpecifiedValue(Vec::new()))
-        }
-
-        let mut quotes = Vec::new();
-        loop {
-            let location = input.current_source_location();
-            let first = match input.next() {
-                Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
-                Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
-                Err(_) => break,
-            };
-            let location = input.current_source_location();
-            let second = match input.next() {
-                Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
-                Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
-                Err(e) => return Err(e.into()),
-            };
-            quotes.push((first, second))
-        }
-        if !quotes.is_empty() {
-            Ok(SpecifiedValue(quotes))
-        } else {
-            Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
-        }
-    }
-</%helpers:longhand>
+${helpers.predefined_type("quotes",
+                          "Quotes",
+                          "computed::Quotes::get_initial_value()",
+                          animation_value_type="discrete",
+                          spec="https://drafts.csswg.org/css-content/#propdef-quotes")}
 
 ${helpers.predefined_type("-moz-image-region",
                           "ClipRectOrAuto",
                           "computed::ClipRectOrAuto::auto()",
                           animation_value_type="ComputedValue",
                           products="gecko",
                           boxed="True",
                           spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-image-region)")}
new file mode 100644
--- /dev/null
+++ b/servo/components/style/values/computed/list.rs
@@ -0,0 +1,26 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! `list` computed values.
+
+pub use values::specified::list::Quotes;
+
+impl Quotes {
+    /// Initial value for `quotes`.
+    ///
+    /// FIXME(emilio): This should ideally not allocate.
+    #[inline]
+    pub fn get_initial_value() -> Quotes {
+        Quotes(vec![
+            (
+                "\u{201c}".to_owned().into_boxed_str(),
+                "\u{201d}".to_owned().into_boxed_str(),
+            ),
+            (
+                "\u{2018}".to_owned().into_boxed_str(),
+                "\u{2019}".to_owned().into_boxed_str(),
+            ),
+        ].into_boxed_slice())
+    }
+}
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -49,16 +49,17 @@ pub use self::image::{Gradient, Gradient
 #[cfg(feature = "gecko")]
 pub use self::gecko::ScrollSnapPoint;
 pub use self::rect::LengthOrNumberRect;
 pub use super::{Auto, Either, None_};
 pub use super::specified::{BorderStyle, TextDecorationLine};
 pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage};
 pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength};
 pub use self::length::{CSSPixelLength, NonNegativeLength, NonNegativeLengthOrPercentage};
+pub use self::list::Quotes;
 pub use self::outline::OutlineStyle;
 pub use self::percentage::Percentage;
 pub use self::position::{Position, GridAutoFlow, GridTemplateAreas};
 pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth};
 pub use self::table::XSpan;
 pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextOverflow, WordSpacing};
 pub use self::time::Time;
 pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin};
@@ -75,16 +76,17 @@ pub mod box_;
 pub mod color;
 pub mod effects;
 pub mod flex;
 pub mod font;
 pub mod image;
 #[cfg(feature = "gecko")]
 pub mod gecko;
 pub mod length;
+pub mod list;
 pub mod outline;
 pub mod percentage;
 pub mod position;
 pub mod rect;
 pub mod svg;
 pub mod table;
 pub mod text;
 pub mod time;
@@ -394,16 +396,17 @@ trivial_to_computed_value!(i32);
 trivial_to_computed_value!(u8);
 trivial_to_computed_value!(u16);
 trivial_to_computed_value!(u32);
 trivial_to_computed_value!(Atom);
 trivial_to_computed_value!(BorderStyle);
 trivial_to_computed_value!(Cursor);
 trivial_to_computed_value!(Namespace);
 trivial_to_computed_value!(String);
+trivial_to_computed_value!(Box<str>);
 
 /// A `<number>` value.
 pub type Number = CSSFloat;
 
 /// A wrapper of Number, but the value >= 0.
 pub type NonNegativeNumber = NonNegative<CSSFloat>;
 
 impl From<CSSFloat> for NonNegativeNumber {
new file mode 100644
--- /dev/null
+++ b/servo/components/style/values/specified/list.rs
@@ -0,0 +1,71 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! `list` specified values.
+
+use cssparser::{Parser, Token};
+use parser::{Parse, ParserContext};
+use std::fmt;
+use style_traits::{ParseError, StyleParseErrorKind, ToCss};
+
+/// Specified and computed `quote` property.
+///
+/// FIXME(emilio): It's a shame that this allocates all the time it's computed,
+/// probably should just be refcounted.
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
+pub struct Quotes(pub Box<[(Box<str>, Box<str>)]>);
+
+impl ToCss for Quotes {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        let mut iter = self.0.iter();
+
+        match iter.next() {
+            Some(&(ref l, ref r)) => {
+                l.to_css(dest)?;
+                dest.write_char(' ')?;
+                r.to_css(dest)?;
+            }
+            None => return dest.write_str("none"),
+        }
+
+        for &(ref l, ref r) in iter {
+            dest.write_char(' ')?;
+            l.to_css(dest)?;
+            dest.write_char(' ')?;
+            r.to_css(dest)?;
+        }
+
+        Ok(())
+    }
+}
+
+impl Parse for Quotes {
+    fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Quotes, ParseError<'i>> {
+        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
+            return Ok(Quotes(Vec::new().into_boxed_slice()))
+        }
+
+        let mut quotes = Vec::new();
+        loop {
+            let location = input.current_source_location();
+            let first = match input.next() {
+                Ok(&Token::QuotedString(ref value)) => {
+                    value.as_ref().to_owned().into_boxed_str()
+                },
+                Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
+                Err(_) => break,
+            };
+
+            let second =
+                input.expect_string()?.as_ref().to_owned().into_boxed_str();
+            quotes.push((first, second))
+        }
+
+        if !quotes.is_empty() {
+            Ok(Quotes(quotes.into_boxed_slice()))
+        } else {
+            Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
+        }
+    }
+}
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -44,16 +44,17 @@ pub use self::gecko::ScrollSnapPoint;
 pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRect};
 pub use self::length::{AbsoluteLength, CalcLengthOrPercentage, CharacterWidth};
 pub use self::length::{FontRelativeLength, Length, LengthOrNone, LengthOrNumber};
 pub use self::length::{LengthOrPercentage, LengthOrPercentageOrAuto};
 pub use self::length::{LengthOrPercentageOrNone, MaxLength, MozLength};
 pub use self::length::{NoCalcLength, ViewportPercentageLength};
 pub use self::length::NonNegativeLengthOrPercentage;
+pub use self::list::Quotes;
 pub use self::outline::OutlineStyle;
 pub use self::rect::LengthOrNumberRect;
 pub use self::percentage::Percentage;
 pub use self::position::{Position, PositionComponent, GridAutoFlow, GridTemplateAreas};
 pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth};
 pub use self::table::XSpan;
 pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextDecorationLine, TextOverflow, WordSpacing};
 pub use self::time::Time;
@@ -74,16 +75,17 @@ pub mod color;
 pub mod effects;
 pub mod flex;
 pub mod font;
 #[cfg(feature = "gecko")]
 pub mod gecko;
 pub mod grid;
 pub mod image;
 pub mod length;
+pub mod list;
 pub mod outline;
 pub mod percentage;
 pub mod position;
 pub mod rect;
 pub mod source_size_list;
 pub mod svg;
 pub mod table;
 pub mod text;