diff --git a/components/style/gecko_bindings/sugar/ns_style_auto_array.rs b/components/style/gecko_bindings/sugar/ns_style_auto_array.rs index 9d8c37fe743..b5772a6c77a 100644 --- a/components/style/gecko_bindings/sugar/ns_style_auto_array.rs +++ b/components/style/gecko_bindings/sugar/ns_style_auto_array.rs @@ -5,10 +5,12 @@ //! Rust helpers for Gecko's `nsStyleAutoArray`. use crate::gecko_bindings::bindings::Gecko_EnsureStyleAnimationArrayLength; +use crate::gecko_bindings::bindings::Gecko_EnsureStyleScrollTimelineArrayLength; use crate::gecko_bindings::bindings::Gecko_EnsureStyleTransitionArrayLength; use crate::gecko_bindings::bindings::Gecko_EnsureStyleViewTimelineArrayLength; use crate::gecko_bindings::structs::nsStyleAutoArray; -use crate::gecko_bindings::structs::{StyleAnimation, StyleTransition, StyleViewTimeline}; +use crate::gecko_bindings::structs::{StyleAnimation, StyleTransition}; +use crate::gecko_bindings::structs::{StyleScrollTimeline, StyleViewTimeline}; use std::iter::{once, Chain, IntoIterator, Once}; use std::ops::{Index, IndexMut}; use std::slice::{Iter, IterMut}; @@ -88,6 +90,18 @@ impl nsStyleAutoArray { } } +impl nsStyleAutoArray { + /// Ensures that the array has length at least the given length. + pub fn ensure_len(&mut self, len: usize) { + unsafe { + Gecko_EnsureStyleScrollTimelineArrayLength( + self as *mut nsStyleAutoArray as *mut _, + len, + ); + } + } +} + impl<'a, T> IntoIterator for &'a mut nsStyleAutoArray { type Item = &'a mut T; type IntoIter = Chain, IterMut<'a, T>>; diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index a40375abaa1..1f4fb6fd82d 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1721,6 +1721,7 @@ mask-mode mask-repeat mask-clip mask-origin mask-composite mask-position-x mask- animation-timing-function animation-composition animation-timeline transition-duration transition-delay transition-timing-function transition-property + scroll-timeline-name scroll-timeline-axis view-timeline-name view-timeline-axis view-timeline-inset""" %> <%self:impl_trait style_struct_name="UI" skip_longhands="${skip_ui_longhands}"> @@ -1905,6 +1906,9 @@ mask-mode mask-repeat mask-clip mask-origin mask-composite mask-position-x mask- ${impl_coordinated_property('animation', 'timeline', 'Timeline')} ${impl_coordinated_property('animation', 'timing_function', 'TimingFunction')} + ${impl_coordinated_property('scroll_timeline', 'name', 'Name')} + ${impl_coordinated_property('scroll_timeline', 'axis', 'Axis')} + ${impl_coordinated_property('view_timeline', 'name', 'Name')} ${impl_coordinated_property('view_timeline', 'axis', 'Axis')} ${impl_coordinated_property('view_timeline', 'inset', 'Inset')} diff --git a/components/style/properties/longhands/ui.mako.rs b/components/style/properties/longhands/ui.mako.rs index 2fb14b1a953..6dc87ce60fe 100644 --- a/components/style/properties/longhands/ui.mako.rs +++ b/components/style/properties/longhands/ui.mako.rs @@ -335,6 +335,8 @@ ${helpers.predefined_type( "scroll-timeline-name", "ScrollTimelineName", "computed::ScrollTimelineName::none()", + vector=True, + need_index=True, engines="gecko", animation_value_type="none", gecko_pref="layout.css.scroll-driven-animations.enabled", @@ -346,6 +348,8 @@ ${helpers.predefined_type( "scroll-timeline-axis", "ScrollAxis", "computed::ScrollAxis::default()", + vector=True, + need_index=True, engines="gecko", animation_value_type="none", gecko_pref="layout.css.scroll-driven-animations.enabled", diff --git a/components/style/properties/shorthands/ui.mako.rs b/components/style/properties/shorthands/ui.mako.rs index 0090ba9c31c..4b99243b59c 100644 --- a/components/style/properties/shorthands/ui.mako.rs +++ b/components/style/properties/shorthands/ui.mako.rs @@ -327,63 +327,48 @@ macro_rules! try_parse_one { context: &ParserContext, input: &mut Parser<'i, '_>, ) -> Result> { - use crate::parser::Parse; - use crate::values::specified::box_::{ScrollAxis, ScrollTimelineName}; + use crate::properties::longhands::{scroll_timeline_axis, scroll_timeline_name}; - let mut name = None; - let mut axis = None; - // FIXME: Bug 1809005: The order of |name| and |axis| should be fixed. - loop { - // Note: When parsing positionally-ambiguous keywords in a property value, a - // production can only claim the keyword if no other unfulfilled - // production can claim it. So we try to parse `scroll-timeline-axis` first. - // - // https://drafts.csswg.org/css-values-4/#custom-idents + let mut names = Vec::with_capacity(1); + let mut axes = Vec::with_capacity(1); + input.parse_comma_separated(|input| { + let name = scroll_timeline_name::single_value::parse(context, input)?; + let axis = input.try_parse(|i| scroll_timeline_axis::single_value::parse(context, i)); - if axis.is_none() { - axis = input.try_parse(ScrollAxis::parse).ok(); - } + names.push(name); + axes.push(axis.unwrap_or_default()); - if name.is_none() { - if let Ok(value) = input.try_parse(|i| ScrollTimelineName::parse(context, i)) { - name = Some(value); - continue; - } - } - break; - } - - // Must occur one or more. - if name.is_none() && axis.is_none() { - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); - } + Ok(()) + })?; Ok(expanded! { - scroll_timeline_name: name.unwrap_or(ScrollTimelineName::none()), - scroll_timeline_axis: axis.unwrap_or_default(), + scroll_timeline_name: scroll_timeline_name::SpecifiedValue(names.into()), + scroll_timeline_axis: scroll_timeline_axis::SpecifiedValue(axes.into()), }) } impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: fmt::Write { - use crate::values::specified::box_::ScrollAxis; - - let is_default_axis = self.scroll_timeline_axis == &ScrollAxis::default(); - let is_default_name = self.scroll_timeline_name.0.is_none(); - - // Note: if both are default values, we serialize the default axis (because it is the - // first value per spec). - if !is_default_axis || (is_default_axis && is_default_name) { - self.scroll_timeline_axis.to_css(dest)?; + // If any value list length is differs then we don't do a shorthand serialization + // either. + let len = self.scroll_timeline_name.0.len(); + if len != self.scroll_timeline_axis.0.len() { + return Ok(()); } - if !is_default_name { - if !is_default_axis { - dest.write_char(' ')?; + for i in 0..len { + if i != 0 { + dest.write_str(", ")?; } - self.scroll_timeline_name.to_css(dest)?; - } + self.scroll_timeline_name.0[i].to_css(dest)?; + + if self.scroll_timeline_axis.0[i] != Default::default() { + dest.write_char(' ')?; + self.scroll_timeline_axis.0[i].to_css(dest)?; + } + + } Ok(()) } } @@ -423,14 +408,9 @@ macro_rules! try_parse_one { impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: fmt::Write { - let len = self.view_timeline_name.0.len(); - // There should be at least one declared value - if len == 0 { - return Ok(()); - } - // If any value list length is differs then we don't do a shorthand serialization // either. + let len = self.view_timeline_name.0.len(); if len != self.view_timeline_axis.0.len() { return Ok(()); }