зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1886441: Part 1 - Introduce scope proximity in cascade ordering. r=firefox-style-system-reviewers,emilio
Uses the u32 hole left in `ApplicableDeclarationBlock`. Differential Revision: https://phabricator.services.mozilla.com/D207778
This commit is contained in:
Родитель
5acfcd795d
Коммит
4e40923fb6
|
@ -132,6 +132,45 @@ impl CascadePriority {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Proximity to the scope root.
|
||||||
|
///
|
||||||
|
/// https://drafts.csswg.org/css-cascade-6/#cascade-proximity
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
|
||||||
|
pub struct ScopeProximity(u16);
|
||||||
|
|
||||||
|
impl PartialOrd for ScopeProximity {
|
||||||
|
#[inline]
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for ScopeProximity {
|
||||||
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||||
|
// Lower proximity to scope root wins
|
||||||
|
other.0.cmp(&self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sacrifice the largest possible value for infinity. This makes the comparison
|
||||||
|
/// trivial.
|
||||||
|
const PROXIMITY_INFINITY: u16 = u16::MAX;
|
||||||
|
|
||||||
|
impl ScopeProximity {
|
||||||
|
/// Construct a new scope proximity.
|
||||||
|
pub fn new(proximity: usize) -> Self {
|
||||||
|
if cfg!(debug_assertions) && proximity >= PROXIMITY_INFINITY as usize {
|
||||||
|
warn!("Proximity out of bounds");
|
||||||
|
}
|
||||||
|
Self(proximity.clamp(0, (PROXIMITY_INFINITY - 1) as usize) as u16)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a scope proximity for delcarations outside of any scope root.
|
||||||
|
pub fn infinity() -> Self {
|
||||||
|
Self(PROXIMITY_INFINITY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A property declaration together with its precedence among rules of equal
|
/// A property declaration together with its precedence among rules of equal
|
||||||
/// specificity so that we can sort them.
|
/// specificity so that we can sort them.
|
||||||
///
|
///
|
||||||
|
@ -148,6 +187,8 @@ pub struct ApplicableDeclarationBlock {
|
||||||
source_order: u32,
|
source_order: u32,
|
||||||
/// The specificity of the selector.
|
/// The specificity of the selector.
|
||||||
pub specificity: u32,
|
pub specificity: u32,
|
||||||
|
/// The proximity to the scope root.
|
||||||
|
pub scope_proximity: ScopeProximity,
|
||||||
/// The cascade priority of the rule.
|
/// The cascade priority of the rule.
|
||||||
pub cascade_priority: CascadePriority,
|
pub cascade_priority: CascadePriority,
|
||||||
}
|
}
|
||||||
|
@ -165,6 +206,7 @@ impl ApplicableDeclarationBlock {
|
||||||
source: StyleSource::from_declarations(declarations),
|
source: StyleSource::from_declarations(declarations),
|
||||||
source_order: 0,
|
source_order: 0,
|
||||||
specificity: 0,
|
specificity: 0,
|
||||||
|
scope_proximity: ScopeProximity::infinity(),
|
||||||
cascade_priority: CascadePriority::new(level, layer_order),
|
cascade_priority: CascadePriority::new(level, layer_order),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,11 +219,13 @@ impl ApplicableDeclarationBlock {
|
||||||
level: CascadeLevel,
|
level: CascadeLevel,
|
||||||
specificity: u32,
|
specificity: u32,
|
||||||
layer_order: LayerOrder,
|
layer_order: LayerOrder,
|
||||||
|
scope_proximity: ScopeProximity,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ApplicableDeclarationBlock {
|
ApplicableDeclarationBlock {
|
||||||
source,
|
source,
|
||||||
source_order: source_order & SOURCE_ORDER_MASK,
|
source_order: source_order & SOURCE_ORDER_MASK,
|
||||||
specificity,
|
specificity,
|
||||||
|
scope_proximity,
|
||||||
cascade_priority: CascadePriority::new(level, layer_order),
|
cascade_priority: CascadePriority::new(level, layer_order),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,12 +248,29 @@ impl ApplicableDeclarationBlock {
|
||||||
self.cascade_priority.layer_order()
|
self.cascade_priority.layer_order()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the scope proximity of the block.
|
||||||
|
#[inline]
|
||||||
|
pub fn scope_proximity(&self) -> ScopeProximity {
|
||||||
|
self.scope_proximity
|
||||||
|
}
|
||||||
|
|
||||||
/// Convenience method to consume self and return the right thing for the
|
/// Convenience method to consume self and return the right thing for the
|
||||||
/// rule tree to iterate over.
|
/// rule tree to iterate over.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn for_rule_tree(self) -> (StyleSource, CascadePriority) {
|
pub fn for_rule_tree(self) -> (StyleSource, CascadePriority) {
|
||||||
(self.source, self.cascade_priority)
|
(self.source, self.cascade_priority)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the key used to sort applicable declarations.
|
||||||
|
#[inline]
|
||||||
|
pub fn sort_key(&self) -> (LayerOrder, u32, ScopeProximity, u32) {
|
||||||
|
(
|
||||||
|
self.layer_order(),
|
||||||
|
self.specificity,
|
||||||
|
self.scope_proximity(),
|
||||||
|
self.source_order(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size of this struct determines sorting and selector-matching performance.
|
// Size of this struct determines sorting and selector-matching performance.
|
||||||
|
|
|
@ -143,9 +143,7 @@ where
|
||||||
self.context.current_host = host.map(|e| e.opaque());
|
self.context.current_host = host.map(|e| e.opaque());
|
||||||
f(self);
|
f(self);
|
||||||
if start != self.rules.len() {
|
if start != self.rules.len() {
|
||||||
self.rules[start..].sort_unstable_by_key(|block| {
|
self.rules[start..].sort_unstable_by_key(|block| block.sort_key());
|
||||||
(block.layer_order(), block.specificity, block.source_order())
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
self.context.current_host = old_host;
|
self.context.current_host = old_host;
|
||||||
self.in_sort_scope = false;
|
self.in_sort_scope = false;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! A data structure to efficiently index structs containing selectors by local
|
//! A data structure to efficiently index structs containing selectors by local
|
||||||
//! name, ids and hash.
|
//! name, ids and hash.
|
||||||
|
|
||||||
use crate::applicable_declarations::ApplicableDeclarationList;
|
use crate::applicable_declarations::{ApplicableDeclarationList, ScopeProximity};
|
||||||
use crate::context::QuirksMode;
|
use crate::context::QuirksMode;
|
||||||
use crate::dom::TElement;
|
use crate::dom::TElement;
|
||||||
use crate::rule_tree::CascadeLevel;
|
use crate::rule_tree::CascadeLevel;
|
||||||
|
@ -367,7 +367,12 @@ impl SelectorMap<Rule> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
matching_rules.push(rule.to_applicable_declaration_block(cascade_level, cascade_data));
|
// TODO(dshin, bug 1886441): Scope proximity calculation
|
||||||
|
matching_rules.push(rule.to_applicable_declaration_block(
|
||||||
|
cascade_level,
|
||||||
|
cascade_data,
|
||||||
|
ScopeProximity::infinity(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! Selector matching.
|
//! Selector matching.
|
||||||
|
|
||||||
use crate::applicable_declarations::{
|
use crate::applicable_declarations::{
|
||||||
ApplicableDeclarationBlock, ApplicableDeclarationList, CascadePriority,
|
ApplicableDeclarationBlock, ApplicableDeclarationList, CascadePriority, ScopeProximity,
|
||||||
};
|
};
|
||||||
use crate::computed_value_flags::ComputedValueFlags;
|
use crate::computed_value_flags::ComputedValueFlags;
|
||||||
use crate::context::{CascadeInputs, QuirksMode};
|
use crate::context::{CascadeInputs, QuirksMode};
|
||||||
|
@ -1763,8 +1763,7 @@ impl PageRuleMap {
|
||||||
|
|
||||||
// Because page-rules do not have source location information stored,
|
// Because page-rules do not have source location information stored,
|
||||||
// use stable sort to ensure source locations are preserved.
|
// use stable sort to ensure source locations are preserved.
|
||||||
matched_rules[start..]
|
matched_rules[start..].sort_by_key(|block| block.sort_key());
|
||||||
.sort_by_key(|block| (block.layer_order(), block.specificity, block.source_order()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_and_add_rules(
|
fn match_and_add_rules(
|
||||||
|
@ -1793,6 +1792,7 @@ impl PageRuleMap {
|
||||||
level,
|
level,
|
||||||
specificity,
|
specificity,
|
||||||
cascade_data.layer_order_for(data.layer),
|
cascade_data.layer_order_for(data.layer),
|
||||||
|
ScopeProximity::infinity(), // Page rule can't have nested rules anyway.
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2831,7 +2831,7 @@ impl CascadeData {
|
||||||
debug_assert!(!has_nested_rules);
|
debug_assert!(!has_nested_rules);
|
||||||
debug_assert_eq!(stylesheet.contents().origin, Origin::UserAgent);
|
debug_assert_eq!(stylesheet.contents().origin, Origin::UserAgent);
|
||||||
debug_assert_eq!(containing_rule_state.layer_id, LayerId::root());
|
debug_assert_eq!(containing_rule_state.layer_id, LayerId::root());
|
||||||
|
// TODO(dshin, bug 1886441): Because we precompute pseudos, we cannot possibly calculate scope proximity.
|
||||||
precomputed_pseudo_element_decls
|
precomputed_pseudo_element_decls
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.expect("Expected precomputed declarations for the UA level")
|
.expect("Expected precomputed declarations for the UA level")
|
||||||
|
@ -2842,6 +2842,7 @@ impl CascadeData {
|
||||||
CascadeLevel::UANormal,
|
CascadeLevel::UANormal,
|
||||||
selector.specificity(),
|
selector.specificity(),
|
||||||
LayerOrder::root(),
|
LayerOrder::root(),
|
||||||
|
ScopeProximity::infinity(),
|
||||||
));
|
));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -3474,6 +3475,7 @@ impl Rule {
|
||||||
&self,
|
&self,
|
||||||
level: CascadeLevel,
|
level: CascadeLevel,
|
||||||
cascade_data: &CascadeData,
|
cascade_data: &CascadeData,
|
||||||
|
scope_proximity: ScopeProximity,
|
||||||
) -> ApplicableDeclarationBlock {
|
) -> ApplicableDeclarationBlock {
|
||||||
let source = StyleSource::from_rule(self.style_rule.clone());
|
let source = StyleSource::from_rule(self.style_rule.clone());
|
||||||
ApplicableDeclarationBlock::new(
|
ApplicableDeclarationBlock::new(
|
||||||
|
@ -3482,6 +3484,7 @@ impl Rule {
|
||||||
level,
|
level,
|
||||||
self.specificity(),
|
self.specificity(),
|
||||||
cascade_data.layer_order_for(self.layer_id),
|
cascade_data.layer_order_for(self.layer_id),
|
||||||
|
scope_proximity,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче