diff --git a/components/style/invalidation/stylesheets.rs b/components/style/invalidation/stylesheets.rs index f4dc0c5a443..fc39b8cca76 100644 --- a/components/style/invalidation/stylesheets.rs +++ b/components/style/invalidation/stylesheets.rs @@ -543,6 +543,7 @@ impl StylesheetInvalidationSet { FontFeatureValues(..) | FontFace(..) | Keyframes(..) | + ScrollTimeline(..) | Style(..) => { if is_generic_change { // TODO(emilio): We need to do this for selector / keyframe @@ -618,6 +619,10 @@ impl StylesheetInvalidationSet { // existing elements. } }, + ScrollTimeline(..) => { + // TODO: Bug 1676784: check if animation-timeline name is referenced. + // Now we do nothing. + }, CounterStyle(..) | Page(..) | Viewport(..) | FontFeatureValues(..) => { debug!( " > Found unsupported rule, marking the whole subtree \ diff --git a/components/style/stylesheets/mod.rs b/components/style/stylesheets/mod.rs index d17bc3ffd05..762bca6033f 100644 --- a/components/style/stylesheets/mod.rs +++ b/components/style/stylesheets/mod.rs @@ -63,6 +63,7 @@ pub use self::rules_iterator::{AllRules, EffectiveRules}; pub use self::rules_iterator::{ EffectiveRulesIterator, NestedRuleIterationCondition, RulesIterator, }; +pub use self::scroll_timeline_rule::ScrollTimelineRule; pub use self::style_rule::StyleRule; pub use self::stylesheet::{AllowImportRules, SanitizationData, SanitizationKind}; pub use self::stylesheet::{DocumentStyleSheet, Namespaces, Stylesheet}; @@ -261,6 +262,7 @@ pub enum CssRule { Page(Arc>), Document(Arc>), Layer(Arc>), + ScrollTimeline(Arc>), } impl CssRule { @@ -304,6 +306,7 @@ impl CssRule { // TODO(emilio): Add memory reporting for @layer rules. CssRule::Layer(_) => 0, + CssRule::ScrollTimeline(_) => 0, } } } @@ -339,6 +342,7 @@ pub enum CssRuleType { // After viewport, all rules should return 0 from the API, but we still need // a constant somewhere. Layer = 16, + ScrollTimeline = 17, } #[allow(missing_docs)] @@ -366,6 +370,7 @@ impl CssRule { CssRule::Page(_) => CssRuleType::Page, CssRule::Document(_) => CssRuleType::Document, CssRule::Layer(_) => CssRuleType::Layer, + CssRule::ScrollTimeline(_) => CssRuleType::ScrollTimeline, } } @@ -505,6 +510,10 @@ impl DeepCloneWithLock for CssRule { lock.wrap(rule.deep_clone_with_lock(lock, guard, params)), )) } + CssRule::ScrollTimeline(ref arc) => { + let rule = arc.read_with(guard); + CssRule::ScrollTimeline(Arc::new(lock.wrap(rule.clone()))) + } } } } @@ -526,6 +535,7 @@ impl ToCssWithGuard for CssRule { CssRule::Page(ref lock) => lock.read_with(guard).to_css(guard, dest), CssRule::Document(ref lock) => lock.read_with(guard).to_css(guard, dest), CssRule::Layer(ref lock) => lock.read_with(guard).to_css(guard, dest), + CssRule::ScrollTimeline(ref lock) => lock.read_with(guard).to_css(guard, dest), } } } diff --git a/components/style/stylesheets/rule_parser.rs b/components/style/stylesheets/rule_parser.rs index dd85144a45f..fe4988044d3 100644 --- a/components/style/stylesheets/rule_parser.rs +++ b/components/style/stylesheets/rule_parser.rs @@ -15,21 +15,24 @@ use crate::shared_lock::{Locked, SharedRwLock}; use crate::str::starts_with_ignore_ascii_case; use crate::stylesheets::document_rule::DocumentCondition; use crate::stylesheets::font_feature_values_rule::parse_family_name_list; +use crate::stylesheets::import_rule::ImportLayer; use crate::stylesheets::keyframes_rule::parse_keyframe_list; +use crate::stylesheets::layer_rule::{LayerName, LayerRuleKind}; +use crate::stylesheets::scroll_timeline_rule::ScrollTimelineDescriptors; use crate::stylesheets::stylesheet::Namespaces; use crate::stylesheets::supports_rule::SupportsCondition; -use crate::stylesheets::import_rule::ImportLayer; -use crate::stylesheets::layer_rule::{LayerName, LayerRuleKind}; -use crate::stylesheets::viewport_rule; -use crate::stylesheets::AllowImportRules; -use crate::stylesheets::{CorsMode, DocumentRule, FontFeatureValuesRule, KeyframesRule, MediaRule}; -use crate::stylesheets::{CssRule, CssRuleType, CssRules, RulesMutateError, StylesheetLoader}; -use crate::stylesheets::{LayerRule, NamespaceRule, PageRule, StyleRule, SupportsRule, ViewportRule}; +use crate::stylesheets::{ + viewport_rule, AllowImportRules, CorsMode, CssRule, CssRuleType, CssRules, DocumentRule, + FontFeatureValuesRule, KeyframesRule, LayerRule, MediaRule, NamespaceRule, PageRule, + RulesMutateError, ScrollTimelineRule, StyleRule, StylesheetLoader, SupportsRule, ViewportRule, +}; use crate::values::computed::font::FamilyName; -use crate::values::{CssUrl, CustomIdent, KeyframesName}; +use crate::values::{CssUrl, CustomIdent, KeyframesName, TimelineName}; use crate::{Namespace, Prefix}; -use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser}; -use cssparser::{BasicParseError, BasicParseErrorKind, CowRcStr, ParserState, SourcePosition}; +use cssparser::{ + AtRuleParser, BasicParseError, BasicParseErrorKind, CowRcStr, Parser, ParserState, + QualifiedRuleParser, RuleListParser, SourcePosition, +}; use selectors::SelectorList; use servo_arc::Arc; use style_traits::{ParseError, StyleParseErrorKind}; @@ -175,6 +178,8 @@ pub enum AtRulePrelude { Namespace(Option, Namespace), /// A @layer rule prelude. Layer(Vec), + /// A @scroll-timeline rule prelude. + ScrollTimeline(TimelineName), } impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> { @@ -472,6 +477,10 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { let cond = DocumentCondition::parse(self.context, input)?; AtRulePrelude::Document(cond) }, + "scroll-timeline" if static_prefs::pref!("layout.css.scroll-linked-animations.enabled") => { + let name = TimelineName::parse(self.context, input)?; + AtRulePrelude::ScrollTimeline(name) + }, _ => return Err(input.new_custom_error(StyleParseErrorKind::UnsupportedAtRule(name.clone()))) }) } @@ -619,6 +628,21 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { // These rules don't have blocks. Err(input.new_unexpected_token_error(cssparser::Token::CurlyBracketBlock)) }, + AtRulePrelude::ScrollTimeline(name) => { + let context = ParserContext::new_with_rule_type( + self.context, + CssRuleType::ScrollTimeline, + self.namespaces, + ); + + Ok(CssRule::ScrollTimeline(Arc::new(self.shared_lock.wrap( + ScrollTimelineRule { + name, + descriptors: ScrollTimelineDescriptors::parse(&context, input)?, + source_location: start.source_location(), + }, + )))) + }, } } } diff --git a/components/style/stylesheets/rules_iterator.rs b/components/style/stylesheets/rules_iterator.rs index d98d70981df..32851dd2cca 100644 --- a/components/style/stylesheets/rules_iterator.rs +++ b/components/style/stylesheets/rules_iterator.rs @@ -68,6 +68,7 @@ where CssRule::CounterStyle(_) | CssRule::Viewport(_) | CssRule::Keyframes(_) | + CssRule::ScrollTimeline(_) | CssRule::Page(_) | CssRule::FontFeatureValues(_) => None, CssRule::Import(ref import_rule) => { diff --git a/components/style/stylesheets/stylesheet.rs b/components/style/stylesheets/stylesheet.rs index 91a407f5c32..7cdea20e8bf 100644 --- a/components/style/stylesheets/stylesheet.rs +++ b/components/style/stylesheets/stylesheet.rs @@ -378,7 +378,8 @@ impl SanitizationKind { CssRule::Page(..) | CssRule::FontFeatureValues(..) | CssRule::Viewport(..) | - CssRule::CounterStyle(..) => !is_standard, + CssRule::CounterStyle(..) | + CssRule::ScrollTimeline(..) => !is_standard, } } } diff --git a/components/style/stylist.rs b/components/style/stylist.rs index d3d1a24a9d9..6dc80e03ff5 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -2285,6 +2285,10 @@ impl CascadeData { } }, #[cfg(feature = "gecko")] + CssRule::ScrollTimeline(..) => { + // TODO: Bug 1676784: set the timeline into animation. + } + #[cfg(feature = "gecko")] CssRule::FontFace(ref rule) => { self.extra_data.add_font_face(rule); }, @@ -2553,6 +2557,7 @@ impl CascadeData { CssRule::CounterStyle(..) | CssRule::Supports(..) | CssRule::Keyframes(..) | + CssRule::ScrollTimeline(..) | CssRule::Page(..) | CssRule::Viewport(..) | CssRule::Document(..) |