Bug 1889496 - Part 1: Parse @starting-style rule. r=layout-reviewers,firefox-style-system-reviewers,emilio

We introduce this rule and parse it in this patch. Also, fix some wpt
expectations for ERROR.

We will introduce CSSStartingStyleRule in the following patch, and test
it there.

Differential Revision: https://phabricator.services.mozilla.com/D206428
This commit is contained in:
Boris Chiou 2024-04-04 19:39:28 +00:00
Родитель 6cf7b07a43
Коммит e7e11669a6
14 изменённых файлов: 123 добавлений и 15 удалений

Просмотреть файл

@ -106,6 +106,9 @@ css::Rule* ServoCSSRuleList::GetRule(uint32_t aIndex) {
case StyleCssRuleType::Keyframe:
MOZ_ASSERT_UNREACHABLE("keyframe rule cannot be here");
return nullptr;
case StyleCssRuleType::StartingStyle:
// TODO: Implement this in the following patch.
return nullptr;
case StyleCssRuleType::Margin:
// Margin rules not implemented yet, see bug 1864737
return nullptr;
@ -288,6 +291,9 @@ void ServoCSSRuleList::SetRawContents(RefPtr<StyleLockedCssRules> aNewRules,
RULE_CASE_UNLOCKED(LayerStatement, LayerStatement)
RULE_CASE_UNLOCKED(Container, Container)
RULE_CASE_UNLOCKED(Scope, Scope)
case StyleCssRuleType::StartingStyle:
// TODO: Implement this in the following patch.
break;
case StyleCssRuleType::Keyframe:
MOZ_ASSERT_UNREACHABLE("keyframe rule cannot be here");
break;

Просмотреть файл

@ -1004,6 +1004,9 @@ void ServoStyleSet::RuleChangedInternal(StyleSheet& aSheet, css::Rule& aRule,
CASE_FOR(LayerStatement, LayerStatement)
CASE_FOR(Container, Container)
CASE_FOR(Scope, Scope)
case StyleCssRuleType::StartingStyle:
// TODO: Implement this in the following patch.
break;
// @namespace can only be inserted / removed when there are only other
// @namespace and @import rules, and can't be mutated.
case StyleCssRuleType::Namespace:

Просмотреть файл

@ -8356,6 +8356,13 @@
mirror: always
rust: true
# Whether @starting-style is enabled?
- name: layout.css.starting-style-at-rules.enabled
type: RelaxedAtomicBool
value: false
mirror: always
rust: true
# Should we look for counter ancestor scopes first?
- name: layout.css.counter-ancestor-scope.enabled
type: bool

Просмотреть файл

@ -616,7 +616,7 @@ impl StylesheetInvalidationSet {
return self.invalidate_fully();
},
Document(..) | Import(..) | Media(..) | Supports(..) | Container(..) |
LayerBlock(..) => {
LayerBlock(..) | StartingStyle(..) => {
// Do nothing, relevant nested rules are visited as part of rule iteration.
},
FontFace(..) => {

Просмотреть файл

@ -23,6 +23,7 @@ mod property_rule;
mod rule_list;
mod rule_parser;
mod rules_iterator;
mod starting_style_rule;
mod style_rule;
mod stylesheet;
pub mod supports_rule;
@ -70,6 +71,7 @@ pub use self::rules_iterator::{AllRules, EffectiveRules};
pub use self::rules_iterator::{
EffectiveRulesIterator, NestedRuleIterationCondition, RulesIterator,
};
pub use self::starting_style_rule::StartingStyleRule;
pub use self::style_rule::StyleRule;
pub use self::scope_rule::ScopeRule;
pub use self::stylesheet::{AllowImportRules, SanitizationData, SanitizationKind};
@ -272,6 +274,7 @@ pub enum CssRule {
LayerBlock(Arc<LayerBlockRule>),
LayerStatement(Arc<LayerStatementRule>),
Scope(Arc<ScopeRule>),
StartingStyle(Arc<StartingStyleRule>),
}
impl CssRule {
@ -316,6 +319,9 @@ impl CssRule {
CssRule::Document(ref arc) => {
arc.unconditional_shallow_size_of(ops) + arc.size_of(guard, ops)
},
CssRule::StartingStyle(ref arc) => {
arc.unconditional_shallow_size_of(ops) + arc.size_of(guard, ops)
}
// TODO(emilio): Add memory reporting for these rules.
CssRule::LayerBlock(_) | CssRule::LayerStatement(_) => 0,
CssRule::Scope(ref rule) => {
@ -360,6 +366,8 @@ pub enum CssRuleType {
// 20 is an arbitrary number to use for Property.
Property = 20,
Scope = 21,
// https://drafts.csswg.org/css-transitions-2/#the-cssstartingstylerule-interface
StartingStyle = 22,
}
impl CssRuleType {
@ -448,6 +456,7 @@ impl CssRule {
CssRule::LayerStatement(_) => CssRuleType::LayerStatement,
CssRule::Container(_) => CssRuleType::Container,
CssRule::Scope(_) => CssRuleType::Scope,
CssRule::StartingStyle(_) => CssRuleType::StartingStyle,
}
}
@ -585,7 +594,10 @@ impl DeepCloneWithLock for CssRule {
},
CssRule::Scope(ref arc) => {
CssRule::Scope(Arc::new(arc.deep_clone_with_lock(lock, guard, params)))
}
},
CssRule::StartingStyle(ref arc) => {
CssRule::StartingStyle(Arc::new(arc.deep_clone_with_lock(lock, guard, params)))
},
}
}
}
@ -612,6 +624,7 @@ impl ToCssWithGuard for CssRule {
CssRule::LayerStatement(ref rule) => rule.to_css(guard, dest),
CssRule::Container(ref rule) => rule.to_css(guard, dest),
CssRule::Scope(ref rule) => rule.to_css(guard, dest),
CssRule::StartingStyle(ref rule) => rule.to_css(guard, dest),
}
}
}

Просмотреть файл

@ -24,6 +24,7 @@ use crate::stylesheets::import_rule::{ImportLayer, ImportRule, ImportSupportsCon
use crate::stylesheets::keyframes_rule::parse_keyframe_list;
use crate::stylesheets::layer_rule::{LayerBlockRule, LayerName, LayerStatementRule};
use crate::stylesheets::scope_rule::{ScopeBounds, ScopeRule};
use crate::stylesheets::starting_style_rule::StartingStyleRule;
use crate::stylesheets::supports_rule::SupportsCondition;
use crate::stylesheets::{
AllowImportRules, CorsMode, CssRule, CssRuleType, CssRuleTypes, CssRules, DocumentRule,
@ -236,6 +237,8 @@ pub enum AtRulePrelude {
Layer(Vec<LayerName>),
/// A @scope rule prelude.
Scope(ScopeBounds),
/// A @starting-style prelude.
StartingStyle,
}
impl AtRulePrelude {
@ -257,6 +260,7 @@ impl AtRulePrelude {
Self::Namespace(..) => "namespace",
Self::Layer(..) => "layer",
Self::Scope(..) => "scope",
Self::StartingStyle => "starting-style",
}
}
}
@ -525,7 +529,8 @@ impl<'a, 'i> NestedRuleParser<'a, 'i> {
AtRulePrelude::Container(..) |
AtRulePrelude::Document(..) |
AtRulePrelude::Layer(..) |
AtRulePrelude::Scope(..) => true,
AtRulePrelude::Scope(..) |
AtRulePrelude::StartingStyle => true,
AtRulePrelude::Namespace(..) |
AtRulePrelude::FontFace |
@ -722,6 +727,9 @@ impl<'a, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'i> {
let bounds = ScopeBounds::parse(&self.context, input, self.in_style_rule());
AtRulePrelude::Scope(bounds)
},
"starting-style" if static_prefs::pref!("layout.css.starting-style-at-rules.enabled") => {
AtRulePrelude::StartingStyle
},
_ => {
if static_prefs::pref!("layout.css.margin-rules.enabled") {
if let Some(margin_rule_type) = MarginRuleType::match_name(&name) {
@ -898,6 +906,15 @@ impl<'a, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'i> {
source_location,
}))
},
AtRulePrelude::StartingStyle => {
let source_location = start.source_location();
CssRule::StartingStyle(Arc::new(StartingStyleRule {
rules: self
.parse_nested(input, CssRuleType::StartingStyle)
.into_rules(self.shared_lock, source_location),
source_location,
}))
},
};
self.rules.push(rule);
Ok(())

Просмотреть файл

@ -116,7 +116,8 @@ where
Some(supports_rule.rules.read_with(guard).0.iter())
},
CssRule::LayerBlock(ref layer_rule) => Some(layer_rule.rules.read_with(guard).0.iter()),
CssRule::Scope(ref rule) => Some(rule.rules.read_with(guard).0.iter())
CssRule::Scope(ref rule) => Some(rule.rules.read_with(guard).0.iter()),
CssRule::StartingStyle(ref rule) => Some(rule.rules.read_with(guard).0.iter()),
}
}
}

Просмотреть файл

@ -0,0 +1,57 @@
/* 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 https://mozilla.org/MPL/2.0/. */
//! before-change style: the `@starting-style` rules.
//! https://drafts.csswg.org/css-transitions-2/#defining-before-change-style
use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use crate::str::CssStringWriter;
use crate::stylesheets::CssRules;
use cssparser::SourceLocation;
use malloc_size_of::{MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
use servo_arc::Arc;
use std::fmt::{self, Debug, Write};
/// A [`@starting-style`][starting-style] rule.
///
/// [starting-style]: https://drafts.csswg.org/css-transitions-2/#at-ruledef-starting-style
#[derive(Debug, ToShmem)]
pub struct StartingStyleRule {
/// The nested rules to this starting-style rule.
pub rules: Arc<Locked<CssRules>>,
/// The source position where this starting-style rule was found.
pub source_location: SourceLocation,
}
impl StartingStyleRule {
/// Measure heap usage.
#[cfg(feature = "gecko")]
pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
self.rules.unconditional_shallow_size_of(ops) +
self.rules.read_with(guard).size_of(guard, ops)
}
}
impl ToCssWithGuard for StartingStyleRule {
fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
dest.write_str("@starting-style")?;
self.rules.read_with(guard).to_css_block(guard, dest)
}
}
impl DeepCloneWithLock for StartingStyleRule {
fn deep_clone_with_lock(
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard,
params: &DeepCloneParams,
) -> Self {
let rules = self.rules.read_with(guard);
StartingStyleRule {
rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard, params))),
source_location: self.source_location.clone(),
}
}
}

Просмотреть файл

@ -336,7 +336,8 @@ impl SanitizationKind {
CssRule::LayerBlock(..) |
// TODO(dshin): Same comment as Layer applies - shouldn't give away
// something like display size - erring on the side of "safe" for now.
CssRule::Scope(..) => false,
CssRule::Scope(..) |
CssRule::StartingStyle(..) => false,
CssRule::FontFace(..) | CssRule::Namespace(..) | CssRule::Style(..) => true,

Просмотреть файл

@ -3260,7 +3260,8 @@ impl CascadeData {
CssRule::LayerStatement(..) |
CssRule::FontPaletteValues(..) |
CssRule::FontFeatureValues(..) |
CssRule::Scope(..) => {
CssRule::Scope(..) |
CssRule::StartingStyle(..) => {
// Not affected by device changes.
continue;
},

Просмотреть файл

@ -1 +1 @@
prefs: [dom.animations-api.compositing.enabled:true, dom.animations-api.timelines.enabled:true, layout.css.marker.restricted:false]
prefs: [dom.animations-api.compositing.enabled:true, dom.animations-api.timelines.enabled:true, layout.css.marker.restricted:false, layout.css.starting-style-at-rules.enabled:true]

Просмотреть файл

@ -1,2 +1,9 @@
[starting-style-cascade.html]
expected: ERROR
[@starting-style with higher specificity]
expected: FAIL
[Starting style inheriting from parent's after-change style]
expected: FAIL
[Starting style inheriting from parent's after-change style while parent transitioning]
expected: FAIL

Просмотреть файл

@ -1,6 +0,0 @@
[starting-style-name-defining-rules.html]
[@keyframes and @layer in @starting-style apply]
expected: FAIL
[Load @font-face from @starting-style rule]
expected: FAIL

Просмотреть файл

@ -1,2 +1,3 @@
[starting-style-rule-none.html]
expected: ERROR
[@starting-style with display:none]
expected: FAIL