From c145dd7b0ceb77537887660b6ae6cac12838162d Mon Sep 17 00:00:00 2001 From: Ravi Shankar Date: Sun, 11 Jun 2017 23:12:48 +0530 Subject: [PATCH 01/11] Cleanup some old code --- components/style/properties/gecko.mako.rs | 20 +++++++------------- components/style/values/generics/grid.rs | 12 ++++++------ components/style/values/specified/grid.rs | 9 +++------ 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index b0953f9a1d9..1a6e0995fe0 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1240,26 +1240,20 @@ fn static_assert() { <% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %> use gecko::values::GeckoStyleCoordConvertible; use gecko_bindings::structs::{nsTArray, nsStyleGridLine_kMaxLine}; - use nsstring::{nsCString, nsStringRepr}; + use nsstring::nsStringRepr; use std::usize; + use values::CustomIdent; use values::generics::grid::TrackListType::Auto; use values::generics::grid::{RepeatCount, TrackSize}; #[inline] - fn set_bitfield(bitfield: &mut u8, pos: u8, val: bool) { - let mask = 1 << (pos - 1); - *bitfield &= !mask; - *bitfield |= (val as u8) << (pos - 1); - } - - #[inline] - fn set_line_names(servo_names: &[String], gecko_names: &mut nsTArray) { + fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray) { unsafe { bindings::Gecko_ResizeTArrayForStrings(gecko_names, servo_names.len() as u32); } for (servo_name, gecko_name) in servo_names.iter().zip(gecko_names.iter_mut()) { - gecko_name.assign_utf8(&nsCString::from(&*servo_name)); + gecko_name.assign(servo_name.0.as_slice()); } } @@ -1284,8 +1278,8 @@ fn static_assert() { // Set defaults ${self_grid}.mRepeatAutoIndex = -1; - set_bitfield(&mut ${self_grid}._bitfield_1, 1, false); // mIsAutoFill - set_bitfield(&mut ${self_grid}._bitfield_1, 2, false); // mIsSubgrid + ${self_grid}.set_mIsAutoFill(false); + ${self_grid}.set_mIsSubgrid(false); // FIXME: mIsSubgrid is false only for , but we don't support subgrid name lists at the moment. match v { @@ -1297,7 +1291,7 @@ fn static_assert() { let auto_repeat = track.auto_repeat.as_ref().expect("expected value"); if auto_repeat.count == RepeatCount::AutoFill { - set_bitfield(&mut ${self_grid}._bitfield_1, 1, true); + ${self_grid}.set_mIsAutoFill(true); } ${self_grid}.mRepeatAutoIndex = idx as i16; diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index 3cb10439598..3693c670718 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -5,7 +5,7 @@ //! Generic types for the handling of //! [grids](https://drafts.csswg.org/css-grid/). -use cssparser::{Parser, serialize_identifier}; +use cssparser::Parser; use parser::{Parse, ParserContext}; use std::{fmt, mem, usize}; use style_traits::{ToCss, ParseError, StyleParseError}; @@ -307,15 +307,15 @@ impl ToComputedValue for TrackSize { /// Helper function for serializing identifiers with a prefix and suffix, used /// for serializing (in grid). pub fn concat_serialize_idents(prefix: &str, suffix: &str, - slice: &[String], sep: &str, dest: &mut W) -> fmt::Result + slice: &[CustomIdent], sep: &str, dest: &mut W) -> fmt::Result where W: fmt::Write { if let Some((ref first, rest)) = slice.split_first() { dest.write_str(prefix)?; - serialize_identifier(first, dest)?; + first.to_css(dest)?; for thing in rest { dest.write_str(sep)?; - serialize_identifier(thing, dest)?; + thing.to_css(dest)?; } dest.write_str(suffix)?; @@ -372,7 +372,7 @@ pub struct TrackRepeat { /// If there's no ``, then it's represented by an empty vector. /// For N `` values, there will be N+1 ``, and so this vector's /// length is always one value more than that of the ``. - pub line_names: Vec>, + pub line_names: Vec>, /// `` values. pub track_sizes: Vec>, } @@ -502,7 +502,7 @@ pub struct TrackList { /// If there's no ``, then it's represented by an empty vector. /// For N values, there will be N+1 ``, and so this vector's /// length is always one value more than that of the ``. - pub line_names: Vec>, + pub line_names: Vec>, /// `` value after computation. This field is necessary, because /// the `values` field (after computation) will only contain `` values, and /// we need something to represent this function. diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index d19ab3703c3..9f68196d1b1 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -81,16 +81,13 @@ impl Parse for TrackSize { /// Parse the grid line names into a vector of owned strings. /// /// https://drafts.csswg.org/css-grid/#typedef-line-names -pub fn parse_line_names<'i, 't>(input: &mut Parser<'i, 't>) -> Result, ParseError<'i>> { +pub fn parse_line_names<'i, 't>(input: &mut Parser<'i, 't>) -> Result, ParseError<'i>> { input.expect_square_bracket_block()?; input.parse_nested_block(|input| { let mut values = vec![]; while let Ok(ident) = input.try(|i| i.expect_ident()) { - if CustomIdent::from_ident((&*ident).into(), &["span"]).is_err() { - return Err(StyleParseError::UnspecifiedError.into()) - } - - values.push(ident.into_owned()); + let ident = CustomIdent::from_ident(ident, &["span"])?; + values.push(ident); } Ok(values) From 8af912200cd5b62c604a4e098abe955bcf5c5d3f Mon Sep 17 00:00:00 2001 From: Ravi Shankar Date: Fri, 9 Jun 2017 23:35:44 +0530 Subject: [PATCH 02/11] Add support for subgrid line name lists --- components/style/values/generics/grid.rs | 99 +++++++++++++++++++++++ components/style/values/specified/grid.rs | 3 +- 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index 3693c670718..42516cda6b1 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -12,6 +12,7 @@ use style_traits::{ToCss, ParseError, StyleParseError}; use values::{CSSFloat, CustomIdent}; use values::computed::{self, ComputedValueAsSpecified, Context, ToComputedValue}; use values::specified::Integer; +use values::specified::grid::parse_line_names; #[derive(PartialEq, Clone, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] @@ -551,3 +552,101 @@ impl ToCss for TrackList { Ok(()) } } + +/// The `` for subgrids. +/// +/// `subgrid [ | repeat( | auto-fill, +) ]+` +/// Old spec: https://www.w3.org/TR/2015/WD-css-grid-1-20150917/#typedef-line-name-list +#[derive(Clone, PartialEq, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub struct LineNameList { + /// The optional `` + pub names: Vec>, + /// Indicates the line name that requires `auto-fill` + pub fill_idx: Option, +} + +impl Parse for LineNameList { + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + input.expect_ident_matching("subgrid")?; + let mut line_names = vec![]; + let mut fill_idx = None; + + loop { + let repeat_parse_result = input.try(|input| { + input.expect_function_matching("repeat")?; + input.parse_nested_block(|input| { + let count = RepeatCount::parse(context, input)?; + input.expect_comma()?; + let mut names_list = vec![]; + names_list.push(parse_line_names(input)?); // there should be at least one + while let Ok(names) = input.try(parse_line_names) { + names_list.push(names); + } + + Ok((names_list, count)) + }) + }); + + if let Ok((mut names_list, count)) = repeat_parse_result { + match count { + RepeatCount::Number(num) => + line_names.extend(names_list.iter().cloned().cycle() + .take(num.value() as usize * names_list.len())), + RepeatCount::AutoFill if fill_idx.is_none() => { + // `repeat(autof-fill, ..)` should have just one line name. + if names_list.len() > 1 { + return Err(StyleParseError::UnspecifiedError.into()); + } + let names = names_list.pop().expect("expected one name list for auto-fill"); + + line_names.push(names); + fill_idx = Some(line_names.len() as u32 - 1); + }, + _ => return Err(StyleParseError::UnspecifiedError.into()), + } + } else if let Ok(names) = input.try(parse_line_names) { + line_names.push(names); + } else { + break + } + } + + Ok(LineNameList { + names: line_names, + fill_idx: fill_idx, + }) + } +} + +impl ToCss for LineNameList { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + dest.write_str("subgrid")?; + let fill_idx = self.fill_idx.map(|v| v as usize).unwrap_or(usize::MAX); + for (i, names) in self.names.iter().enumerate() { + if i == fill_idx { + dest.write_str(" repeat(auto-fill,")?; + } + + dest.write_str(" [")?; + + if let Some((ref first, rest)) = names.split_first() { + first.to_css(dest)?; + for name in rest { + dest.write_str(" ")?; + name.to_css(dest)?; + } + } + + dest.write_str("]")?; + if i == fill_idx { + dest.write_str(")")?; + } + } + + Ok(()) + } +} + +impl ComputedValueAsSpecified for LineNameList {} +no_viewport_percentage!(LineNameList); diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index 9f68196d1b1..436b2d5f1b4 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -110,8 +110,7 @@ enum RepeatType { impl TrackRepeat { fn parse_with_repeat_type<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result<(TrackRepeat, RepeatType), - ParseError<'i>> { + -> Result<(TrackRepeat, RepeatType), ParseError<'i>> { input.try(|i| i.expect_function_matching("repeat").map_err(|e| e.into())).and_then(|_| { input.parse_nested_block(|input| { let count = RepeatCount::parse(context, input)?; From 9d9d99ec2501aa2d5df4eb84af3dd65b2288f468 Mon Sep 17 00:00:00 2001 From: Ravi Shankar Date: Sun, 11 Jun 2017 11:31:30 +0530 Subject: [PATCH 03/11] Switch to GridTemplateComponent for subgrid line names --- components/style/gecko/generated/bindings.rs | 5 ++ components/style/properties/gecko.mako.rs | 31 +++++++++-- .../properties/longhand/position.mako.rs | 6 +-- .../properties/shorthand/position.mako.rs | 45 +++++++++------- components/style/values/computed/mod.rs | 5 +- components/style/values/generics/grid.rs | 14 +++++ components/style/values/specified/grid.rs | 52 ++++++++++++++++++- components/style/values/specified/mod.rs | 5 +- tests/unit/style/parsing/position.rs | 19 +++++-- 9 files changed, 144 insertions(+), 38 deletions(-) diff --git a/components/style/gecko/generated/bindings.rs b/components/style/gecko/generated/bindings.rs index 8ccd98dd2cc..92ddd525c9f 100644 --- a/components/style/gecko/generated/bindings.rs +++ b/components/style/gecko/generated/bindings.rs @@ -1041,6 +1041,11 @@ extern "C" { *mut nsStyleGridTemplate, track_sizes: u32); } +extern "C" { + pub fn Gecko_SetGridTemplateLineNamesLength(grid_template: + *mut nsStyleGridTemplate, + track_sizes: u32); +} extern "C" { pub fn Gecko_CopyStyleGridTemplateValues(grid_template: *mut nsStyleGridTemplate, diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 1a6e0995fe0..f3085cec790 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1244,7 +1244,7 @@ fn static_assert() { use std::usize; use values::CustomIdent; use values::generics::grid::TrackListType::Auto; - use values::generics::grid::{RepeatCount, TrackSize}; + use values::generics::grid::{GridTemplateComponent, RepeatCount, TrackSize}; #[inline] fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray) { @@ -1280,10 +1280,11 @@ fn static_assert() { ${self_grid}.mRepeatAutoIndex = -1; ${self_grid}.set_mIsAutoFill(false); ${self_grid}.set_mIsSubgrid(false); - // FIXME: mIsSubgrid is false only for , but we don't support subgrid name lists at the moment. + + let max_lines = nsStyleGridLine_kMaxLine as usize - 1; // for accounting the final match v { - Either::First(track) => { + GridTemplateComponent::TrackList(track) => { let mut auto_idx = usize::MAX; let mut auto_track_size = None; if let Auto(idx) = track.list_type { @@ -1314,7 +1315,6 @@ fn static_assert() { num_values += 1; } - let max_lines = nsStyleGridLine_kMaxLine as usize - 1; // for accounting the final num_values = cmp::min(num_values, max_lines); unsafe { bindings::Gecko_SetStyleGridTemplateArrayLengths(&mut ${self_grid}, num_values as u32); @@ -1341,7 +1341,7 @@ fn static_assert() { let final_names = line_names.next().unwrap(); set_line_names(&final_names, ${self_grid}.mLineNameLists.last_mut().unwrap()); }, - Either::Second(_none) => { + GridTemplateComponent::None => { unsafe { bindings::Gecko_SetStyleGridTemplateArrayLengths(&mut ${self_grid}, 0); bindings::Gecko_ResizeTArrayForStrings( @@ -1350,6 +1350,27 @@ fn static_assert() { &mut ${self_grid}.mRepeatAutoLineNameListAfter, 0); } }, + GridTemplateComponent::Subgrid(list) => { + ${self_grid}.set_mIsSubgrid(true); + let num_values = cmp::min(list.names.len(), max_lines + 1); + unsafe { + bindings::Gecko_SetStyleGridTemplateArrayLengths(&mut ${self_grid}, 0); + bindings::Gecko_SetGridTemplateLineNamesLength(&mut ${self_grid}, num_values as u32); + bindings::Gecko_ResizeTArrayForStrings( + &mut ${self_grid}.mRepeatAutoLineNameListBefore, 0); + bindings::Gecko_ResizeTArrayForStrings( + &mut ${self_grid}.mRepeatAutoLineNameListAfter, 0); + } + + if let Some(idx) = list.fill_idx { + ${self_grid}.set_mIsAutoFill(true); + ${self_grid}.mRepeatAutoIndex = idx as i16; + } + + for (servo_names, gecko_names) in list.names.iter().zip(${self_grid}.mLineNameLists.iter_mut()) { + set_line_names(servo_names, gecko_names); + } + }, } } diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs index 609573b44af..c39a7585215 100644 --- a/components/style/properties/longhand/position.mako.rs +++ b/components/style/properties/longhand/position.mako.rs @@ -276,11 +276,9 @@ ${helpers.predefined_type("object-position", products="gecko", boxed=True)} - // NOTE: The spec lists only `none | | `, but gecko seems to support - // `subgrid ?` in addition to this (probably old spec). We should support it soon. ${helpers.predefined_type("grid-template-%ss" % kind, - "TrackListOrNone", - "Either::Second(None_)", + "GridTemplateComponent", + "specified::GenericGridTemplateComponent::None", products="gecko", spec="https://drafts.csswg.org/css-grid/#propdef-grid-template-%ss" % kind, boxed=True, diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index c13a53eb885..4207a07ca03 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -245,15 +245,16 @@ use properties::longhands::grid_template_areas::TemplateAreas; use values::{Either, None_}; use values::generics::grid::{TrackSize, TrackList, TrackListType, concat_serialize_idents}; - use values::specified::TrackListOrNone; + use values::specified::{GridTemplateComponent, GenericGridTemplateComponent}; use values::specified::grid::parse_line_names; /// Parsing for `` shorthand (also used by `grid` shorthand). pub fn parse_grid_template<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result<(TrackListOrNone, TrackListOrNone, Either), - ParseError<'i>> { + -> Result<(GridTemplateComponent, + GridTemplateComponent, + Either), ParseError<'i>> { if input.try(|i| i.expect_ident_matching("none")).is_ok() { - return Ok((Either::Second(None_), Either::Second(None_), Either::Second(None_))) + return Ok((GenericGridTemplateComponent::None, GenericGridTemplateComponent::None, Either::Second(None_))) } let first_line_names = input.try(parse_line_names).unwrap_or(vec![]); @@ -296,20 +297,23 @@ }; let template_cols = if input.try(|i| i.expect_delim('/')).is_ok() { - let track_list = TrackList::parse(context, input)?; - if track_list.list_type != TrackListType::Explicit { - return Err(StyleParseError::UnspecifiedError.into()) + let value = GridTemplateComponent::parse(context, input)?; + if let GenericGridTemplateComponent::TrackList(ref list) = value { + if list.list_type != TrackListType::Explicit { + return Err(StyleParseError::UnspecifiedError.into()) + } } - Either::First(track_list) + value } else { - Either::Second(None_) + GenericGridTemplateComponent::None }; - Ok((Either::First(template_rows), template_cols, Either::First(template_areas))) + Ok((GenericGridTemplateComponent::TrackList(template_rows), + template_cols, Either::First(template_areas))) } else { let mut template_rows = grid_template_rows::parse(context, input)?; - if let Either::First(ref mut list) = template_rows { + if let GenericGridTemplateComponent::TrackList(ref mut list) = template_rows { list.line_names[0] = first_line_names; // won't panic } @@ -329,14 +333,14 @@ } /// Serialization for `` shorthand (also used by `grid` shorthand). - pub fn serialize_grid_template(template_rows: &TrackListOrNone, - template_columns: &TrackListOrNone, + pub fn serialize_grid_template(template_rows: &GridTemplateComponent, + template_columns: &GridTemplateComponent, template_areas: &Either, dest: &mut W) -> fmt::Result where W: fmt::Write { match *template_areas { Either::Second(_none) => { - if template_rows == &Either::Second(None_) && - template_columns == &Either::Second(None_) { + if template_rows == &GenericGridTemplateComponent::None && + template_columns == &GenericGridTemplateComponent::None { dest.write_str("none") } else { template_rows.to_css(dest)?; @@ -346,8 +350,8 @@ }, Either::First(ref areas) => { let track_list = match *template_rows { - Either::First(ref list) => list, - Either::Second(_none) => unreachable!(), // should exist! + GenericGridTemplateComponent::TrackList(ref list) => list, + _ => unreachable!(), // should exist! }; let mut names_iter = track_list.line_names.iter(); @@ -371,7 +375,7 @@ concat_serialize_idents(" [", "]", names, " ", dest)?; } - if let Either::First(ref list) = *template_columns { + if let GenericGridTemplateComponent::TrackList(ref list) = *template_columns { dest.write_str(" / ")?; list.to_css(dest)?; } @@ -401,12 +405,13 @@ use properties::longhands::{grid_template_columns, grid_template_rows}; use properties::longhands::grid_auto_flow::computed_value::{AutoFlow, T as SpecifiedAutoFlow}; use values::{Either, None_}; + use values::generics::grid::GridTemplateComponent; use values::specified::{LengthOrPercentage, TrackSize}; pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - let mut temp_rows = Either::Second(None_); - let mut temp_cols = Either::Second(None_); + let mut temp_rows = GridTemplateComponent::None; + let mut temp_cols = GridTemplateComponent::None; let mut temp_areas = Either::Second(None_); let mut auto_rows = TrackSize::default(); let mut auto_cols = TrackSize::default(); diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 4930e25a050..7a115179e88 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -19,6 +19,7 @@ use std::fmt; use style_traits::ToCss; use super::{CSSFloat, CSSInteger, RGBA}; use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; +use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; use super::generics::grid::TrackList as GenericTrackList; use super::specified; @@ -565,8 +566,8 @@ pub type TrackSize = GenericTrackSize; /// (could also be `` or ``) pub type TrackList = GenericTrackList; -/// ` | none` -pub type TrackListOrNone = Either; +/// ` | ` +pub type GridTemplateComponent = GenericGridTemplateComponent; impl ClipRectOrAuto { /// Return an auto (default for clip-rect and image-region) value diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index 42516cda6b1..a7b0de061a7 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -650,3 +650,17 @@ impl ToCss for LineNameList { impl ComputedValueAsSpecified for LineNameList {} no_viewport_percentage!(LineNameList); + +/// Variants for ` | ` +/// Subgrid deferred to Level 2 spec due to lack of implementation. +/// But it's implemented in gecko, so we have to as well. +#[derive(Clone, PartialEq, Debug, ToCss)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub enum GridTemplateComponent { + /// `none` value. + None, + /// The grid `` + TrackList(TrackList), + /// A `subgrid ?` + Subgrid(LineNameList), +} diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index 436b2d5f1b4..af2f4a70c22 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -12,8 +12,8 @@ use std::ascii::AsciiExt; use style_traits::{HasViewportPercentage, ParseError, StyleParseError}; use values::{CSSFloat, CustomIdent, Either}; use values::computed::{self, Context, ToComputedValue}; -use values::generics::grid::{RepeatCount, TrackBreadth, TrackKeyword, TrackRepeat}; -use values::generics::grid::{TrackSize, TrackList, TrackListType}; +use values::generics::grid::{GridTemplateComponent, RepeatCount, TrackBreadth, TrackKeyword, TrackRepeat}; +use values::generics::grid::{LineNameList, TrackSize, TrackList, TrackListType}; use values::specified::LengthOrPercentage; /// Parse a single flexible length. @@ -349,3 +349,51 @@ impl ToComputedValue for TrackList { } } } + +impl Parse for GridTemplateComponent { // FIXME: Derive Parse (probably with None_) + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { + return Ok(GridTemplateComponent::None) + } + + if let Ok(t) = input.try(|i| TrackList::parse(context, i)) { + return Ok(GridTemplateComponent::TrackList(t)) + } + + LineNameList::parse(context, input).map(GridTemplateComponent::Subgrid) + } +} + +impl HasViewportPercentage for GridTemplateComponent { + #[inline] + fn has_viewport_percentage(&self) -> bool { + match *self { + GridTemplateComponent::TrackList(ref l) => l.has_viewport_percentage(), + _ => false, + } + } +} + +impl ToComputedValue for GridTemplateComponent { + type ComputedValue = GridTemplateComponent>; + + #[inline] + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { + match *self { + GridTemplateComponent::None => GridTemplateComponent::None, + GridTemplateComponent::TrackList(ref l) => GridTemplateComponent::TrackList(l.to_computed_value(context)), + GridTemplateComponent::Subgrid(ref n) => GridTemplateComponent::Subgrid(n.to_computed_value(context)), + } + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + match *computed { + GridTemplateComponent::None => GridTemplateComponent::None, + GridTemplateComponent::TrackList(ref l) => + GridTemplateComponent::TrackList(ToComputedValue::from_computed_value(l)), + GridTemplateComponent::Subgrid(ref n) => + GridTemplateComponent::Subgrid(ToComputedValue::from_computed_value(n)), + } + } +} diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index d429376c1f6..c05085d7137 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -48,6 +48,7 @@ pub use self::position::{Position, PositionComponent}; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing}; pub use self::transform::{TimingFunction, TransformOrigin}; pub use super::generics::grid::GridLine; +pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; #[cfg(feature = "gecko")] pub mod align; @@ -685,8 +686,8 @@ pub type TrackSize = GenericTrackSize; /// (could also be `` or ``) pub type TrackList = GenericTrackList; -/// ` | none` -pub type TrackListOrNone = Either; +/// ` | ` +pub type GridTemplateComponent = GenericGridTemplateComponent; #[derive(Clone, Debug, HasViewportPercentage, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] diff --git a/tests/unit/style/parsing/position.rs b/tests/unit/style/parsing/position.rs index c1527c2f233..9029e401355 100644 --- a/tests/unit/style/parsing/position.rs +++ b/tests/unit/style/parsing/position.rs @@ -191,12 +191,18 @@ fn test_grid_template_rows_columns() { // with as assert_roundtrip_with_context!(grid_template_rows::parse, "calc(4em + 5px)"); // with followed by with `{3}` (, auto, minmax) - assert_roundtrip_with_context!(grid_template_rows::parse, "10px repeat(2, 1fr auto minmax(200px, 1fr))"); + assert_roundtrip_with_context!(grid_template_rows::parse, + "10px repeat(2, 1fr auto minmax(200px, 1fr))", + "10px 1fr auto minmax(200px, 1fr) 1fr auto minmax(200px, 1fr)"); // with ` ` followed by - assert_roundtrip_with_context!(grid_template_rows::parse, "repeat(4, 10px [col-start] 250px [col-end]) 10px"); + assert_roundtrip_with_context!(grid_template_rows::parse, + "repeat(2, 10px [col-start] 250px [col-end]) 10px", + "10px [col-start] 250px [col-end] 10px [col-start] 250px [col-end] 10px"); // mixture of , and assert_roundtrip_with_context!(grid_template_rows::parse, - "[a] auto [b] minmax(min-content, 1fr) [b c d] repeat(2, [e] 40px) repeat(5, [f g] auto [h]) [i]"); + "[a] auto [b] minmax(min-content, 1fr) [b c d] repeat(2, 40px [e] 30px) [i]", + "[a] auto [b] minmax(min-content, 1fr) [b c d] 40px [e] 30px 40px [e] 30px [i]"); + assert!(parse(grid_template_rows::parse, "subgrid").is_ok()); // no span allowed in assert!(parse(grid_template_rows::parse, "[a span] 10px").is_err()); @@ -232,4 +238,11 @@ fn test_computed_grid_template_rows_colums() { assert_computed_serialization(grid_template_rows::parse, "10px repeat(2, 1fr auto minmax(200px, 1fr))", "10px minmax(auto, 1fr) auto minmax(200px, 1fr) minmax(auto, 1fr) auto minmax(200px, 1fr)"); + + assert_computed_serialization(grid_template_rows::parse, + "subgrid [a] [] repeat(auto-fill, [])", "subgrid [a] [] repeat(auto-fill, [])"); + + assert_computed_serialization(grid_template_rows::parse, + "subgrid [a] [b] repeat(2, [c d] [] [e]) [] repeat(auto-fill, [])", + "subgrid [a] [b] [c d] [] [e] [c d] [] [e] [] repeat(auto-fill, [])"); } From 5eb33bac8f6e8d777bd35efe306d2371b23cb040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Thu, 29 Jun 2017 16:36:48 -0700 Subject: [PATCH 04/11] Fix the serialization of TrackRepeat It was printing `repeat(n, )` for number TrackRepeat. But it should just print n times instead. MozReview-Commit-ID: FEmL8O2osVb --- components/style/values/generics/grid.rs | 45 +++++++++++++++++------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index a7b0de061a7..0bed2512dd7 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -380,26 +380,45 @@ pub struct TrackRepeat { impl ToCss for TrackRepeat { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - dest.write_str("repeat(")?; - self.count.to_css(dest)?; - dest.write_str(", ")?; + // If repeat count is an integer instead of a keyword, it should'n serialized + // with `repeat` function. It should serialized with `N` repeated form. + let repeat_count = match self.count { + RepeatCount::Number(integer) => integer.value(), + _ => { + dest.write_str("repeat(")?; + self.count.to_css(dest)?; + dest.write_str(", ")?; + 1 + }, + }; - let mut line_names_iter = self.line_names.iter(); - for (i, (ref size, ref names)) in self.track_sizes.iter() - .zip(&mut line_names_iter).enumerate() { - if i > 0 { + for i in 0..repeat_count { + if i != 0 { dest.write_str(" ")?; } - concat_serialize_idents("[", "] ", names, " ", dest)?; - size.to_css(dest)?; + let mut line_names_iter = self.line_names.iter(); + for (i, (ref size, ref names)) in self.track_sizes.iter() + .zip(&mut line_names_iter).enumerate() { + if i > 0 { + dest.write_str(" ")?; + } + + concat_serialize_idents("[", "] ", names, " ", dest)?; + size.to_css(dest)?; + } + + if let Some(line_names_last) = line_names_iter.next() { + concat_serialize_idents(" [", "]", line_names_last, " ", dest)?; + } } - if let Some(line_names_last) = line_names_iter.next() { - concat_serialize_idents(" [", "]", line_names_last, " ", dest)?; + match self.count { + RepeatCount::AutoFill | RepeatCount::AutoFit => { + dest.write_str(")")?; + }, + _ => {}, } - - dest.write_str(")")?; Ok(()) } } From f4eccdae3fa2ae27d20bc7ffb8250781182774f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Mon, 3 Jul 2017 11:35:19 -0700 Subject: [PATCH 05/11] Fall back to an older version of the spec in TrackRepeat for the parity with gecko --- components/style/values/specified/grid.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index af2f4a70c22..1be04015792 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -143,6 +143,16 @@ impl TrackRepeat { values.push(track_size); names.push(current_names); + if is_auto { + // FIXME: In the older version of the spec + // (https://www.w3.org/TR/2015/WD-css-grid-1-20150917/#typedef-auto-repeat), + // if the repeat type is `` we shouldn't try to parse more than + // one `TrackSize`. But in current version of the spec, this is deprecated + // but we are adding this for gecko parity. We should remove this when + // gecko implements new spec. + names.push(input.try(parse_line_names).unwrap_or(vec![])); + break + } } else { if values.is_empty() { // expecting at least one From fd3b99027a16b00d93ebea90103ba5e6ff024870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Mon, 3 Jul 2017 11:41:03 -0700 Subject: [PATCH 06/11] Prevent parsing 'none' keyword in grid-template's columns part --- .../style/properties/shorthand/position.mako.rs | 13 ++++++------- components/style/values/specified/grid.rs | 8 ++++++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 4207a07ca03..248127a7aa4 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -241,7 +241,6 @@ disable_when_testing="True" products="gecko"> use parser::Parse; - use properties::longhands::grid_template_rows; use properties::longhands::grid_template_areas::TemplateAreas; use values::{Either, None_}; use values::generics::grid::{TrackSize, TrackList, TrackListType, concat_serialize_idents}; @@ -297,7 +296,7 @@ }; let template_cols = if input.try(|i| i.expect_delim('/')).is_ok() { - let value = GridTemplateComponent::parse(context, input)?; + let value = GridTemplateComponent::parse_without_none(context, input)?; if let GenericGridTemplateComponent::TrackList(ref list) = value { if list.list_type != TrackListType::Explicit { return Err(StyleParseError::UnspecifiedError.into()) @@ -312,12 +311,12 @@ Ok((GenericGridTemplateComponent::TrackList(template_rows), template_cols, Either::First(template_areas))) } else { - let mut template_rows = grid_template_rows::parse(context, input)?; + let mut template_rows = GridTemplateComponent::parse(context, input)?; if let GenericGridTemplateComponent::TrackList(ref mut list) = template_rows { list.line_names[0] = first_line_names; // won't panic } - Ok((template_rows, grid_template_rows::parse(context, input)?, Either::Second(None_))) + Ok((template_rows, GridTemplateComponent::parse(context, input)?, Either::Second(None_))) } } @@ -401,8 +400,8 @@ spec="https://drafts.csswg.org/css-grid/#propdef-grid" disable_when_testing="True" products="gecko"> + use parser::Parse; use properties::longhands::{grid_auto_columns, grid_auto_rows, grid_auto_flow}; - use properties::longhands::{grid_template_columns, grid_template_rows}; use properties::longhands::grid_auto_flow::computed_value::{AutoFlow, T as SpecifiedAutoFlow}; use values::{Either, None_}; use values::generics::grid::GridTemplateComponent; @@ -447,7 +446,7 @@ temp_rows = rows; temp_cols = cols; temp_areas = areas; - } else if let Ok(rows) = input.try(|i| grid_template_rows::parse(context, i)) { + } else if let Ok(rows) = input.try(|i| GridTemplateComponent::parse(context, i)) { temp_rows = rows; input.expect_delim('/')?; flow = parse_auto_flow(input, false)?; @@ -456,7 +455,7 @@ flow = parse_auto_flow(input, true)?; auto_rows = input.try(|i| grid_auto_rows::parse(context, i)).unwrap_or_default(); input.expect_delim('/')?; - temp_cols = grid_template_columns::parse(context, input)?; + temp_cols = GridTemplateComponent::parse(context, input)?; } Ok(expanded! { diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index 1be04015792..50d88fee175 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -366,6 +366,14 @@ impl Parse for GridTemplateComponent { // FIXME: Derive Par return Ok(GridTemplateComponent::None) } + Self::parse_without_none(context, input) + } +} + +impl GridTemplateComponent { + /// Parses a `GridTemplateComponent` except `none` keyword. + pub fn parse_without_none<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) + -> Result> { if let Ok(t) = input.try(|i| TrackList::parse(context, i)) { return Ok(GridTemplateComponent::TrackList(t)) } From af96e09c7f52e02bd59647d21521685850176f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Mon, 3 Jul 2017 11:43:17 -0700 Subject: [PATCH 07/11] Fix parsing of grid-template shorthand It should accept 'grid-template-rows / grid-template-columns values' values not 'grid-template-rows grid-template-columns values'. --- components/style/properties/shorthand/position.mako.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 248127a7aa4..d304f2bab6e 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -316,6 +316,7 @@ list.line_names[0] = first_line_names; // won't panic } + input.expect_delim('/')?; Ok((template_rows, GridTemplateComponent::parse(context, input)?, Either::Second(None_))) } } From 8827cb1440b6fa2426d8edd975184f2a6296a929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Mon, 3 Jul 2017 11:44:11 -0700 Subject: [PATCH 08/11] Fix 'grid' shorthand serialization --- .../properties/longhand/position.mako.rs | 17 +++++---- .../properties/shorthand/position.mako.rs | 37 ++++++++++++------- components/style/values/generics/grid.rs | 7 ++++ 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs index c39a7585215..1cf56b645ce 100644 --- a/components/style/properties/longhand/position.mako.rs +++ b/components/style/properties/longhand/position.mako.rs @@ -307,7 +307,9 @@ ${helpers.predefined_type("object-position", #[derive(PartialEq, Clone, Eq, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct T { - pub autoflow: AutoFlow, + // This needs to be an Option because we need an indicator to determine whether this property is + // parsed or not in `grid` shorthand. Otherwise we can't properly serialize it. + pub autoflow: Option, pub dense: bool, } } @@ -317,7 +319,7 @@ ${helpers.predefined_type("object-position", impl ToCss for computed_value::T { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - dest.write_str(match self.autoflow { + dest.write_str(match self.autoflow.unwrap_or(computed_value::AutoFlow::Row) { computed_value::AutoFlow::Column => "column", computed_value::AutoFlow::Row => "row" })?; @@ -330,7 +332,8 @@ ${helpers.predefined_type("object-position", #[inline] pub fn get_initial_value() -> computed_value::T { computed_value::T { - autoflow: computed_value::AutoFlow::Row, + // None should resolve to `computed_value::AutoFlow::Row` in layout. + autoflow: None, dense: false } } @@ -367,7 +370,7 @@ ${helpers.predefined_type("object-position", if value.is_some() || dense { Ok(computed_value::T { - autoflow: value.unwrap_or(AutoFlow::Row), + autoflow: value, dense: dense, }) } else { @@ -382,12 +385,12 @@ ${helpers.predefined_type("object-position", use self::computed_value::AutoFlow; SpecifiedValue { - autoflow: + autoflow: Some( if bits & structs::NS_STYLE_GRID_AUTO_FLOW_ROW as u8 != 0 { AutoFlow::Row } else { AutoFlow::Column - }, + }), dense: bits & structs::NS_STYLE_GRID_AUTO_FLOW_DENSE as u8 != 0, } @@ -400,7 +403,7 @@ ${helpers.predefined_type("object-position", use gecko_bindings::structs; use self::computed_value::AutoFlow; - let mut result: u8 = match v.autoflow { + let mut result: u8 = match v.autoflow.unwrap_or(AutoFlow::Row) { AutoFlow::Row => structs::NS_STYLE_GRID_AUTO_FLOW_ROW as u8, AutoFlow::Column => structs::NS_STYLE_GRID_AUTO_FLOW_COLUMN as u8, }; diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index d304f2bab6e..8b9b816bc68 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -437,7 +437,7 @@ auto_flow.map(|flow| { SpecifiedAutoFlow { - autoflow: flow, + autoflow: Some(flow), dense: dense, } }).ok_or(StyleParseError::UnspecifiedError.into()) @@ -450,10 +450,10 @@ } else if let Ok(rows) = input.try(|i| GridTemplateComponent::parse(context, i)) { temp_rows = rows; input.expect_delim('/')?; - flow = parse_auto_flow(input, false)?; + flow = parse_auto_flow(input, true)?; auto_cols = grid_auto_columns::parse(context, input).unwrap_or_default(); } else { - flow = parse_auto_flow(input, true)?; + flow = parse_auto_flow(input, false)?; auto_rows = input.try(|i| grid_auto_rows::parse(context, i)).unwrap_or_default(); input.expect_delim('/')?; temp_cols = GridTemplateComponent::parse(context, input)?; @@ -474,28 +474,39 @@ impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - if let Either::First(_) = *self.grid_template_areas { - super::grid_template::serialize_grid_template(self.grid_template_rows, - self.grid_template_columns, - self.grid_template_areas, dest) - } else if self.grid_auto_flow.autoflow == AutoFlow::Row { + if self.grid_auto_flow.autoflow.is_none() { + return super::grid_template::serialize_grid_template(self.grid_template_rows, + self.grid_template_columns, + self.grid_template_areas, dest); + } + + // This unwrap is safe because we checked the None part in previous if condition. + if self.grid_auto_flow.autoflow.unwrap() == AutoFlow::Row { self.grid_template_rows.to_css(dest)?; dest.write_str(" / auto-flow")?; if self.grid_auto_flow.dense { dest.write_str(" dense")?; } - self.grid_auto_columns.to_css(dest) + if !self.grid_auto_columns.is_default() { + dest.write_str(" ")?; + self.grid_auto_columns.to_css(dest)?; + } } else { - dest.write_str("auto-flow ")?; + dest.write_str("auto-flow")?; if self.grid_auto_flow.dense { - dest.write_str("dense ")?; + dest.write_str(" dense")?; + } + + if !self.grid_auto_rows.is_default() { + dest.write_str(" ")?; + self.grid_auto_rows.to_css(dest)?; } - self.grid_auto_rows.to_css(dest)?; dest.write_str(" / ")?; - self.grid_template_columns.to_css(dest) + self.grid_template_columns.to_css(dest)?; } + Ok(()) } } diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index 0bed2512dd7..c64a7929107 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -252,6 +252,13 @@ impl Default for TrackSize { } } +impl TrackSize { + /// Returns true if current TrackSize is same as default. + pub fn is_default(&self) -> bool { + *self == TrackSize::default() + } +} + impl ToCss for TrackSize { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { From f7aac8d22502a176fba0280999c02fe89e223643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Mon, 3 Jul 2017 11:45:04 -0700 Subject: [PATCH 09/11] Fix parsing logic of grid-template property Fist line names are parsed on the top of the function already and it shouldn't be parsed again. --- components/style/properties/shorthand/position.mako.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 8b9b816bc68..3077e4e1d38 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -313,7 +313,13 @@ } else { let mut template_rows = GridTemplateComponent::parse(context, input)?; if let GenericGridTemplateComponent::TrackList(ref mut list) = template_rows { - list.line_names[0] = first_line_names; // won't panic + // Fist line names are parsed already and it shouldn't be parsed again. + // If line names are not empty, that means given property value is not acceptable + if list.line_names[0].is_empty() { + list.line_names[0] = first_line_names; // won't panic + } else { + return Err(StyleParseError::UnspecifiedError.into()); + } } input.expect_delim('/')?; From ba6641de588fe330fc3516e07239d696aa9de0bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Mon, 3 Jul 2017 11:45:51 -0700 Subject: [PATCH 10/11] Fix parsing of 'subgrid' and 'none' keywords in grid-template --- .../properties/shorthand/position.mako.rs | 28 +++++++++++++++++-- components/style/values/generics/grid.rs | 2 +- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 3077e4e1d38..88d51a1a179 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -243,7 +243,7 @@ use parser::Parse; use properties::longhands::grid_template_areas::TemplateAreas; use values::{Either, None_}; - use values::generics::grid::{TrackSize, TrackList, TrackListType, concat_serialize_idents}; + use values::generics::grid::{LineNameList, TrackSize, TrackList, TrackListType, concat_serialize_idents}; use values::specified::{GridTemplateComponent, GenericGridTemplateComponent}; use values::specified::grid::parse_line_names; @@ -252,9 +252,31 @@ -> Result<(GridTemplateComponent, GridTemplateComponent, Either), ParseError<'i>> { - if input.try(|i| i.expect_ident_matching("none")).is_ok() { - return Ok((GenericGridTemplateComponent::None, GenericGridTemplateComponent::None, Either::Second(None_))) + + // Other shorthand sub properties also parse `none` and `subgrid` keywords and this + // shorthand should know after these keywords there is nothing to parse. Otherwise it + // gets confused and rejects the sub properties that contains `none` or `subgrid`. + <% keywords = { + "none": "GenericGridTemplateComponent::None", + "subgrid": "GenericGridTemplateComponent::Subgrid(LineNameList::default())" } + %> + % for keyword, rust_type in keywords.items(): + if let Ok(x) = input.try(|i| { + if i.try(|i| i.expect_ident_matching("${keyword}")).is_ok() { + if i.is_exhausted() { + return Ok((${rust_type}, + ${rust_type}, + Either::Second(None_))) + } else { + return Err(()); + } + } + Err(()) + }) { + return Ok(x); + } + % endfor let first_line_names = input.try(parse_line_names).unwrap_or(vec![]); if let Ok(s) = input.try(Parser::expect_string) { diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index c64a7929107..f266307d7a7 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -583,7 +583,7 @@ impl ToCss for TrackList { /// /// `subgrid [ | repeat( | auto-fill, +) ]+` /// Old spec: https://www.w3.org/TR/2015/WD-css-grid-1-20150917/#typedef-line-name-list -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, PartialEq, Debug, Default)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct LineNameList { /// The optional `` From 3e49a8c80ab639cefd1ae3947deb16bbfdf60ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Mon, 3 Jul 2017 11:46:40 -0700 Subject: [PATCH 11/11] Fix serialization of grid-template If both columns and rows are 'none', shorthand should serialize it as 'none / none' instead of just 'none'. --- .../style/properties/shorthand/position.mako.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 88d51a1a179..a862cc20e04 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -367,14 +367,9 @@ dest: &mut W) -> fmt::Result where W: fmt::Write { match *template_areas { Either::Second(_none) => { - if template_rows == &GenericGridTemplateComponent::None && - template_columns == &GenericGridTemplateComponent::None { - dest.write_str("none") - } else { - template_rows.to_css(dest)?; - dest.write_str(" / ")?; - template_columns.to_css(dest) - } + template_rows.to_css(dest)?; + dest.write_str(" / ")?; + template_columns.to_css(dest) }, Either::First(ref areas) => { let track_list = match *template_rows {