зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #13179 - Remove one level of nesting in `Stylist` (from servo:flatter-stylist); r=emilio
<!-- Please describe your changes on the following line: --> Since #13134, the "normal" and "important" parts of `Stylist` are identical, so we don’t need to store them twice. r? @emilio --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 89126b44d74ac49e7e05d8a127020aa39de0d30e
This commit is contained in:
Родитель
8689191075
Коммит
7042e55074
|
@ -91,7 +91,7 @@ use style::properties::{DeclaredValue, Importance};
|
|||
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
|
||||
use style::refcell::Ref;
|
||||
use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
|
||||
use style::selector_matching::DeclarationBlock;
|
||||
use style::selector_matching::ApplicableDeclarationBlock;
|
||||
use style::sink::Push;
|
||||
use style::values::CSSFloat;
|
||||
use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage};
|
||||
|
@ -291,7 +291,7 @@ pub trait LayoutElementHelpers {
|
|||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, &mut V)
|
||||
where V: Push<DeclarationBlock>;
|
||||
where V: Push<ApplicableDeclarationBlock>;
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn get_colspan(self) -> u32;
|
||||
#[allow(unsafe_code)]
|
||||
|
@ -324,11 +324,11 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
|||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
|
||||
where V: Push<DeclarationBlock>
|
||||
where V: Push<ApplicableDeclarationBlock>
|
||||
{
|
||||
#[inline]
|
||||
fn from_declaration(rule: PropertyDeclaration) -> DeclarationBlock {
|
||||
DeclarationBlock::from_declarations(
|
||||
fn from_declaration(rule: PropertyDeclaration) -> ApplicableDeclarationBlock {
|
||||
ApplicableDeclarationBlock::from_declarations(
|
||||
Arc::new(PropertyDeclarationBlock {
|
||||
declarations: vec![(rule, Importance::Normal)],
|
||||
important_count: 0,
|
||||
|
|
|
@ -63,7 +63,7 @@ use style::element_state::*;
|
|||
use style::properties::{ComputedValues, PropertyDeclarationBlock};
|
||||
use style::refcell::{Ref, RefCell, RefMut};
|
||||
use style::selector_impl::{ElementSnapshot, NonTSPseudoClass, PseudoElement, ServoSelectorImpl};
|
||||
use style::selector_matching::DeclarationBlock;
|
||||
use style::selector_matching::ApplicableDeclarationBlock;
|
||||
use style::sink::Push;
|
||||
use style::str::is_whitespace;
|
||||
use url::Url;
|
||||
|
@ -442,7 +442,7 @@ impl<'le> fmt::Debug for ServoLayoutElement<'le> {
|
|||
|
||||
impl<'le> PresentationalHintsSynthetizer for ServoLayoutElement<'le> {
|
||||
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
|
||||
where V: Push<DeclarationBlock>
|
||||
where V: Push<ApplicableDeclarationBlock>
|
||||
{
|
||||
unsafe {
|
||||
self.element.synthesize_presentational_hints_for_legacy_attributes(hints);
|
||||
|
@ -1094,5 +1094,5 @@ impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
|
|||
|
||||
impl<'le> PresentationalHintsSynthetizer for ServoThreadSafeLayoutElement<'le> {
|
||||
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
|
||||
where V: Push<DeclarationBlock> {}
|
||||
where V: Push<ApplicableDeclarationBlock> {}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use properties::longhands::animation_play_state::computed_value::AnimationPlaySt
|
|||
use properties::longhands::transition_timing_function::computed_value::StartEnd;
|
||||
use properties::longhands::transition_timing_function::computed_value::TransitionTimingFunction;
|
||||
use properties::{self, ComputedValues, Importance};
|
||||
use selector_matching::DeclarationBlock;
|
||||
use selector_matching::ApplicableDeclarationBlock;
|
||||
use std::sync::Arc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use string_cache::Atom;
|
||||
|
@ -384,7 +384,7 @@ fn compute_style_for_animation_step(context: &SharedStyleContext,
|
|||
// an Arc in the below (more common case).
|
||||
KeyframesStepValue::ComputedValues => style_from_cascade.clone(),
|
||||
KeyframesStepValue::Declarations(ref declarations) => {
|
||||
let declaration_block = DeclarationBlock {
|
||||
let declaration_block = ApplicableDeclarationBlock {
|
||||
mixed_declarations: declarations.clone(),
|
||||
importance: Importance::Normal,
|
||||
source_order: 0,
|
||||
|
|
|
@ -13,7 +13,7 @@ use properties::{ComputedValues, PropertyDeclarationBlock};
|
|||
use refcell::{Ref, RefMut};
|
||||
use restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
|
||||
use selector_impl::{ElementExt, PseudoElement};
|
||||
use selector_matching::DeclarationBlock;
|
||||
use selector_matching::ApplicableDeclarationBlock;
|
||||
use sink::Push;
|
||||
use std::fmt::Debug;
|
||||
use std::ops::BitOr;
|
||||
|
@ -186,7 +186,7 @@ pub trait TDocument : Sized + Copy + Clone {
|
|||
|
||||
pub trait PresentationalHintsSynthetizer {
|
||||
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
|
||||
where V: Push<DeclarationBlock>;
|
||||
where V: Push<ApplicableDeclarationBlock>;
|
||||
}
|
||||
|
||||
pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + PresentationalHintsSynthetizer {
|
||||
|
|
|
@ -75,7 +75,7 @@ pub struct Keyframe {
|
|||
|
||||
/// `!important` is not allowed in keyframe declarations,
|
||||
/// so the second value of these tuples is always `Importance::Normal`.
|
||||
/// But including them enables `compute_style_for_animation_step` to create a `DeclarationBlock`
|
||||
/// But including them enables `compute_style_for_animation_step` to create a `ApplicableDeclarationBlock`
|
||||
/// by cloning an `Arc<_>` (incrementing a reference count) rather than re-creating a `Vec<_>`.
|
||||
pub block: Arc<PropertyDeclarationBlock>,
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ use dom::{TElement, TNode, TRestyleDamage, UnsafeNode};
|
|||
use properties::longhands::display::computed_value as display;
|
||||
use properties::{ComputedValues, cascade, PropertyDeclarationBlock};
|
||||
use selector_impl::{TheSelectorImpl, PseudoElement};
|
||||
use selector_matching::{DeclarationBlock, Stylist};
|
||||
use selector_matching::{ApplicableDeclarationBlock, Stylist};
|
||||
use selectors::bloom::BloomFilter;
|
||||
use selectors::matching::{MatchingReason, StyleRelations, AFFECTED_BY_PSEUDO_ELEMENTS};
|
||||
use selectors::{Element, MatchAttr};
|
||||
|
@ -51,9 +51,9 @@ fn create_common_style_affecting_attributes_from_element<E: TElement>(element: &
|
|||
}
|
||||
|
||||
pub struct ApplicableDeclarations {
|
||||
pub normal: SmallVec<[DeclarationBlock; 16]>,
|
||||
pub normal: SmallVec<[ApplicableDeclarationBlock; 16]>,
|
||||
pub per_pseudo: HashMap<PseudoElement,
|
||||
Vec<DeclarationBlock>,
|
||||
Vec<ApplicableDeclarationBlock>,
|
||||
BuildHasherDefault<::fnv::FnvHasher>>,
|
||||
|
||||
/// Whether the `normal` declarations are shareable with other nodes.
|
||||
|
@ -78,11 +78,11 @@ impl ApplicableDeclarations {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct ApplicableDeclarationsCacheEntry {
|
||||
pub declarations: Vec<DeclarationBlock>,
|
||||
pub declarations: Vec<ApplicableDeclarationBlock>,
|
||||
}
|
||||
|
||||
impl ApplicableDeclarationsCacheEntry {
|
||||
fn new(declarations: Vec<DeclarationBlock>) -> ApplicableDeclarationsCacheEntry {
|
||||
fn new(declarations: Vec<ApplicableDeclarationBlock>) -> ApplicableDeclarationsCacheEntry {
|
||||
ApplicableDeclarationsCacheEntry {
|
||||
declarations: declarations,
|
||||
}
|
||||
|
@ -105,11 +105,11 @@ impl Hash for ApplicableDeclarationsCacheEntry {
|
|||
}
|
||||
|
||||
struct ApplicableDeclarationsCacheQuery<'a> {
|
||||
declarations: &'a [DeclarationBlock],
|
||||
declarations: &'a [ApplicableDeclarationBlock],
|
||||
}
|
||||
|
||||
impl<'a> ApplicableDeclarationsCacheQuery<'a> {
|
||||
fn new(declarations: &'a [DeclarationBlock]) -> ApplicableDeclarationsCacheQuery<'a> {
|
||||
fn new(declarations: &'a [ApplicableDeclarationBlock]) -> ApplicableDeclarationsCacheQuery<'a> {
|
||||
ApplicableDeclarationsCacheQuery {
|
||||
declarations: declarations,
|
||||
}
|
||||
|
@ -159,14 +159,14 @@ impl ApplicableDeclarationsCache {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find(&self, declarations: &[DeclarationBlock]) -> Option<Arc<ComputedValues>> {
|
||||
pub fn find(&self, declarations: &[ApplicableDeclarationBlock]) -> Option<Arc<ComputedValues>> {
|
||||
match self.cache.find(&ApplicableDeclarationsCacheQuery::new(declarations)) {
|
||||
None => None,
|
||||
Some(ref values) => Some((*values).clone()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, declarations: Vec<DeclarationBlock>, style: Arc<ComputedValues>) {
|
||||
pub fn insert(&mut self, declarations: Vec<ApplicableDeclarationBlock>, style: Arc<ComputedValues>) {
|
||||
self.cache.insert(ApplicableDeclarationsCacheEntry::new(declarations), style)
|
||||
}
|
||||
|
||||
|
@ -493,7 +493,7 @@ trait PrivateMatchMethods: TNode {
|
|||
fn cascade_node_pseudo_element<'a, Ctx>(&self,
|
||||
context: &Ctx,
|
||||
parent_style: Option<&Arc<ComputedValues>>,
|
||||
applicable_declarations: &[DeclarationBlock],
|
||||
applicable_declarations: &[ApplicableDeclarationBlock],
|
||||
mut old_style: Option<&mut Arc<ComputedValues>>,
|
||||
applicable_declarations_cache:
|
||||
&mut ApplicableDeclarationsCache,
|
||||
|
|
|
@ -29,7 +29,7 @@ use computed_values;
|
|||
#[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide};
|
||||
use logical_geometry::WritingMode;
|
||||
use parser::{ParserContext, ParserContextExtraData, log_css_error};
|
||||
use selector_matching::DeclarationBlock;
|
||||
use selector_matching::ApplicableDeclarationBlock;
|
||||
use stylesheets::Origin;
|
||||
use values::LocalToCss;
|
||||
use values::HasViewportPercentage;
|
||||
|
@ -1718,7 +1718,7 @@ mod lazy_static_module {
|
|||
#[allow(unused_mut, unused_imports)]
|
||||
fn cascade_with_cached_declarations(
|
||||
viewport_size: Size2D<Au>,
|
||||
applicable_declarations: &[DeclarationBlock],
|
||||
applicable_declarations: &[ApplicableDeclarationBlock],
|
||||
shareable: bool,
|
||||
parent_style: &ComputedValues,
|
||||
cached_style: &ComputedValues,
|
||||
|
@ -1863,7 +1863,7 @@ static CASCADE_PROPERTY: [CascadePropertyFn; ${len(data.longhands)}] = [
|
|||
///
|
||||
/// Returns the computed values and a boolean indicating whether the result is cacheable.
|
||||
pub fn cascade(viewport_size: Size2D<Au>,
|
||||
applicable_declarations: &[DeclarationBlock],
|
||||
applicable_declarations: &[ApplicableDeclarationBlock],
|
||||
shareable: bool,
|
||||
parent_style: Option<<&ComputedValues>,
|
||||
cached_style: Option<<&ComputedValues>,
|
||||
|
|
|
@ -38,8 +38,7 @@ pub type FnvHashMap<K, V> = HashMap<K, V, BuildHasherDefault<::fnv::FnvHasher>>;
|
|||
/// for a given document. The selectors are converted into `Rule`s
|
||||
/// (defined in rust-selectors), and introduced in a `SelectorMap`
|
||||
/// depending on the pseudo-element (see `PerPseudoElementSelectorMap`),
|
||||
/// stylesheet origin (see `PerOriginSelectorMap`), and priority
|
||||
/// (see the `normal` and `important` fields in `PerOriginSelectorMap`).
|
||||
/// and stylesheet origin (see the fields of `PerPseudoElementSelectorMap`).
|
||||
///
|
||||
/// This structure is effectively created once per pipeline, in the
|
||||
/// LayoutThread corresponding to that pipeline.
|
||||
|
@ -71,7 +70,7 @@ pub struct Stylist {
|
|||
/// Applicable declarations for a given non-eagerly cascaded pseudo-element.
|
||||
/// These are eagerly computed once, and then used to resolve the new
|
||||
/// computed values on the fly on layout.
|
||||
precomputed_pseudo_element_decls: FnvHashMap<PseudoElement, Vec<DeclarationBlock>>,
|
||||
precomputed_pseudo_element_decls: FnvHashMap<PseudoElement, Vec<ApplicableDeclarationBlock>>,
|
||||
|
||||
rules_source_order: usize,
|
||||
|
||||
|
@ -162,38 +161,26 @@ impl Stylist {
|
|||
}
|
||||
let mut rules_source_order = self.rules_source_order;
|
||||
|
||||
// Take apart the StyleRule into individual Rules and insert
|
||||
// them into the SelectorMap of that priority.
|
||||
macro_rules! append(
|
||||
($style_rule: ident, $priority: ident, $importance: expr) => {
|
||||
for selector in &$style_rule.selectors {
|
||||
let map = if let Some(ref pseudo) = selector.pseudo_element {
|
||||
self.pseudos_map
|
||||
.entry(pseudo.clone())
|
||||
.or_insert_with(PerPseudoElementSelectorMap::new)
|
||||
.borrow_for_origin(&stylesheet.origin)
|
||||
} else {
|
||||
self.element_map.borrow_for_origin(&stylesheet.origin)
|
||||
};
|
||||
|
||||
map.$priority.insert(Rule {
|
||||
selector: selector.complex_selector.clone(),
|
||||
declarations: DeclarationBlock {
|
||||
specificity: selector.specificity,
|
||||
mixed_declarations: $style_rule.declarations.clone(),
|
||||
importance: $importance,
|
||||
source_order: rules_source_order,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
for rule in stylesheet.effective_rules(&self.device) {
|
||||
match *rule {
|
||||
CSSRule::Style(ref style_rule) => {
|
||||
append!(style_rule, normal, Importance::Normal);
|
||||
append!(style_rule, important, Importance::Important);
|
||||
for selector in &style_rule.selectors {
|
||||
let map = if let Some(ref pseudo) = selector.pseudo_element {
|
||||
self.pseudos_map
|
||||
.entry(pseudo.clone())
|
||||
.or_insert_with(PerPseudoElementSelectorMap::new)
|
||||
.borrow_for_origin(&stylesheet.origin)
|
||||
} else {
|
||||
self.element_map.borrow_for_origin(&stylesheet.origin)
|
||||
};
|
||||
|
||||
map.insert(Rule {
|
||||
selector: selector.complex_selector.clone(),
|
||||
declarations: style_rule.declarations.clone(),
|
||||
specificity: selector.specificity,
|
||||
source_order: rules_source_order,
|
||||
});
|
||||
}
|
||||
rules_source_order += 1;
|
||||
|
||||
for selector in &style_rule.selectors {
|
||||
|
@ -242,8 +229,7 @@ impl Stylist {
|
|||
if let Some(map) = self.pseudos_map.remove(&pseudo) {
|
||||
let mut declarations = vec![];
|
||||
|
||||
map.user_agent.normal.get_universal_rules(&mut declarations);
|
||||
map.user_agent.important.get_universal_rules(&mut declarations);
|
||||
map.user_agent.get_universal_rules(&mut declarations);
|
||||
|
||||
self.precomputed_pseudo_element_decls.insert(pseudo, declarations);
|
||||
}
|
||||
|
@ -350,7 +336,7 @@ impl Stylist {
|
|||
where E: Element<Impl=TheSelectorImpl> +
|
||||
fmt::Debug +
|
||||
PresentationalHintsSynthetizer,
|
||||
V: Push<DeclarationBlock> + VecLike<DeclarationBlock>
|
||||
V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock>
|
||||
{
|
||||
assert!(!self.is_device_dirty);
|
||||
assert!(style_attribute.is_none() || pseudo_element.is_none(),
|
||||
|
@ -368,12 +354,12 @@ impl Stylist {
|
|||
|
||||
debug!("Determining if style is shareable: pseudo: {}", pseudo_element.is_some());
|
||||
// Step 1: Normal user-agent rules.
|
||||
map.user_agent.normal.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Normal);
|
||||
map.user_agent.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Normal);
|
||||
debug!("UA normal: {:?}", relations);
|
||||
|
||||
// Step 2: Presentational hints.
|
||||
|
@ -386,19 +372,19 @@ impl Stylist {
|
|||
debug!("preshints: {:?}", relations);
|
||||
|
||||
// Step 3: User and author normal rules.
|
||||
map.user.normal.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Normal);
|
||||
map.user.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Normal);
|
||||
debug!("user normal: {:?}", relations);
|
||||
map.author.normal.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Normal);
|
||||
map.author.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Normal);
|
||||
debug!("author normal: {:?}", relations);
|
||||
|
||||
// Step 4: Normal style attributes.
|
||||
|
@ -407,19 +393,19 @@ impl Stylist {
|
|||
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
|
||||
Push::push(
|
||||
applicable_declarations,
|
||||
DeclarationBlock::from_declarations(sa.clone(), Importance::Normal));
|
||||
ApplicableDeclarationBlock::from_declarations(sa.clone(), Importance::Normal));
|
||||
}
|
||||
}
|
||||
|
||||
debug!("style attr: {:?}", relations);
|
||||
|
||||
// Step 5: Author-supplied `!important` rules.
|
||||
map.author.important.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Important);
|
||||
map.author.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Important);
|
||||
|
||||
debug!("author important: {:?}", relations);
|
||||
|
||||
|
@ -429,28 +415,28 @@ impl Stylist {
|
|||
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
|
||||
Push::push(
|
||||
applicable_declarations,
|
||||
DeclarationBlock::from_declarations(sa.clone(), Importance::Important));
|
||||
ApplicableDeclarationBlock::from_declarations(sa.clone(), Importance::Important));
|
||||
}
|
||||
}
|
||||
|
||||
debug!("style attr important: {:?}", relations);
|
||||
|
||||
// Step 7: User and UA `!important` rules.
|
||||
map.user.important.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Important);
|
||||
map.user.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Important);
|
||||
|
||||
debug!("user important: {:?}", relations);
|
||||
|
||||
map.user_agent.important.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Important);
|
||||
map.user_agent.get_all_matching_rules(element,
|
||||
parent_bf,
|
||||
applicable_declarations,
|
||||
&mut relations,
|
||||
reason,
|
||||
Importance::Important);
|
||||
|
||||
debug!("UA important: {:?}", relations);
|
||||
|
||||
|
@ -549,51 +535,30 @@ impl Stylist {
|
|||
}
|
||||
|
||||
|
||||
/// Map that contains the CSS rules for a given origin.
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
struct PerOriginSelectorMap {
|
||||
/// Rules that contains at least one property declaration with
|
||||
/// normal importance.
|
||||
normal: SelectorMap,
|
||||
/// Rules that contains at least one property declaration with
|
||||
/// !important.
|
||||
important: SelectorMap,
|
||||
}
|
||||
|
||||
impl PerOriginSelectorMap {
|
||||
#[inline]
|
||||
fn new() -> Self {
|
||||
PerOriginSelectorMap {
|
||||
normal: SelectorMap::new(),
|
||||
important: SelectorMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Map that contains the CSS rules for a specific PseudoElement
|
||||
/// (or lack of PseudoElement).
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
struct PerPseudoElementSelectorMap {
|
||||
/// Rules from user agent stylesheets
|
||||
user_agent: PerOriginSelectorMap,
|
||||
user_agent: SelectorMap,
|
||||
/// Rules from author stylesheets
|
||||
author: PerOriginSelectorMap,
|
||||
author: SelectorMap,
|
||||
/// Rules from user stylesheets
|
||||
user: PerOriginSelectorMap,
|
||||
user: SelectorMap,
|
||||
}
|
||||
|
||||
impl PerPseudoElementSelectorMap {
|
||||
#[inline]
|
||||
fn new() -> Self {
|
||||
PerPseudoElementSelectorMap {
|
||||
user_agent: PerOriginSelectorMap::new(),
|
||||
author: PerOriginSelectorMap::new(),
|
||||
user: PerOriginSelectorMap::new(),
|
||||
user_agent: SelectorMap::new(),
|
||||
author: SelectorMap::new(),
|
||||
user: SelectorMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn borrow_for_origin(&mut self, origin: &Origin) -> &mut PerOriginSelectorMap {
|
||||
fn borrow_for_origin(&mut self, origin: &Origin) -> &mut SelectorMap {
|
||||
match *origin {
|
||||
Origin::UserAgent => &mut self.user_agent,
|
||||
Origin::Author => &mut self.author,
|
||||
|
@ -665,7 +630,7 @@ impl SelectorMap {
|
|||
reason: MatchingReason,
|
||||
importance: Importance)
|
||||
where E: Element<Impl=TheSelectorImpl>,
|
||||
V: VecLike<DeclarationBlock>
|
||||
V: VecLike<ApplicableDeclarationBlock>
|
||||
{
|
||||
if self.empty {
|
||||
return
|
||||
|
@ -726,7 +691,7 @@ impl SelectorMap {
|
|||
/// `self` sorted by specifity and source order.
|
||||
pub fn get_universal_rules<V>(&self,
|
||||
matching_rules_list: &mut V)
|
||||
where V: VecLike<DeclarationBlock>
|
||||
where V: VecLike<ApplicableDeclarationBlock>
|
||||
{
|
||||
if self.empty {
|
||||
return
|
||||
|
@ -737,7 +702,14 @@ impl SelectorMap {
|
|||
for rule in self.other_rules.iter() {
|
||||
if rule.selector.compound_selector.is_empty() &&
|
||||
rule.selector.next.is_none() {
|
||||
matching_rules_list.push(rule.declarations.clone());
|
||||
if rule.declarations.any_normal() {
|
||||
matching_rules_list.push(
|
||||
rule.to_applicable_declaration_block(Importance::Normal));
|
||||
}
|
||||
if rule.declarations.any_important() {
|
||||
matching_rules_list.push(
|
||||
rule.to_applicable_declaration_block(Importance::Important));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -757,7 +729,7 @@ impl SelectorMap {
|
|||
where E: Element<Impl=TheSelectorImpl>,
|
||||
Str: Borrow<BorrowedStr> + Eq + Hash,
|
||||
BorrowedStr: Eq + Hash,
|
||||
Vector: VecLike<DeclarationBlock>
|
||||
Vector: VecLike<ApplicableDeclarationBlock>
|
||||
{
|
||||
if let Some(rules) = hash.get(key) {
|
||||
SelectorMap::get_matching_rules(element,
|
||||
|
@ -779,10 +751,10 @@ impl SelectorMap {
|
|||
reason: MatchingReason,
|
||||
importance: Importance)
|
||||
where E: Element<Impl=TheSelectorImpl>,
|
||||
V: VecLike<DeclarationBlock>
|
||||
V: VecLike<ApplicableDeclarationBlock>
|
||||
{
|
||||
for rule in rules.iter() {
|
||||
let block = &rule.declarations.mixed_declarations;
|
||||
let block = &rule.declarations;
|
||||
let any_declaration_for_importance = if importance.important() {
|
||||
block.any_important()
|
||||
} else {
|
||||
|
@ -791,7 +763,7 @@ impl SelectorMap {
|
|||
if any_declaration_for_importance &&
|
||||
matches_complex_selector(&*rule.selector, element, parent_bf,
|
||||
relations, reason) {
|
||||
matching_rules.push(rule.declarations.clone());
|
||||
matching_rules.push(rule.to_applicable_declaration_block(importance));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -868,28 +840,42 @@ pub struct Rule {
|
|||
// that it matches. Selector contains an owned vector (through
|
||||
// ComplexSelector) and we want to avoid the allocation.
|
||||
pub selector: Arc<ComplexSelector<TheSelectorImpl>>,
|
||||
pub declarations: DeclarationBlock,
|
||||
pub declarations: Arc<PropertyDeclarationBlock>,
|
||||
pub source_order: usize,
|
||||
pub specificity: u32,
|
||||
}
|
||||
|
||||
impl Rule {
|
||||
fn to_applicable_declaration_block(&self, importance: Importance)
|
||||
-> ApplicableDeclarationBlock {
|
||||
ApplicableDeclarationBlock {
|
||||
mixed_declarations: self.declarations.clone(),
|
||||
importance: importance,
|
||||
source_order: self.source_order,
|
||||
specificity: self.specificity,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A property declaration together with its precedence among rules of equal specificity so that
|
||||
/// we can sort them.
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DeclarationBlock {
|
||||
pub struct ApplicableDeclarationBlock {
|
||||
/// Contains declarations of either importance, but only those of self.importance are relevant.
|
||||
/// Use DeclarationBlock::iter
|
||||
/// Use ApplicableDeclarationBlock::iter
|
||||
pub mixed_declarations: Arc<PropertyDeclarationBlock>,
|
||||
pub importance: Importance,
|
||||
pub source_order: usize,
|
||||
pub specificity: u32,
|
||||
}
|
||||
|
||||
impl DeclarationBlock {
|
||||
impl ApplicableDeclarationBlock {
|
||||
#[inline]
|
||||
pub fn from_declarations(declarations: Arc<PropertyDeclarationBlock>,
|
||||
importance: Importance)
|
||||
-> Self {
|
||||
DeclarationBlock {
|
||||
ApplicableDeclarationBlock {
|
||||
mixed_declarations: declarations,
|
||||
importance: importance,
|
||||
source_order: 0,
|
||||
|
@ -897,20 +883,20 @@ impl DeclarationBlock {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> DeclarationBlockIter {
|
||||
DeclarationBlockIter {
|
||||
pub fn iter(&self) -> ApplicableDeclarationBlockIter {
|
||||
ApplicableDeclarationBlockIter {
|
||||
iter: self.mixed_declarations.declarations.iter(),
|
||||
importance: self.importance,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DeclarationBlockIter<'a> {
|
||||
pub struct ApplicableDeclarationBlockIter<'a> {
|
||||
iter: slice::Iter<'a, (PropertyDeclaration, Importance)>,
|
||||
importance: Importance,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for DeclarationBlockIter<'a> {
|
||||
impl<'a> Iterator for ApplicableDeclarationBlockIter<'a> {
|
||||
type Item = &'a PropertyDeclaration;
|
||||
|
||||
#[inline]
|
||||
|
@ -924,7 +910,7 @@ impl<'a> Iterator for DeclarationBlockIter<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> DoubleEndedIterator for DeclarationBlockIter<'a> {
|
||||
impl<'a> DoubleEndedIterator for ApplicableDeclarationBlockIter<'a> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
while let Some(&(ref declaration, importance)) = self.iter.next_back() {
|
||||
|
|
|
@ -51,7 +51,7 @@ use style::properties::PropertyDeclarationBlock;
|
|||
use style::properties::{ComputedValues, parse_style_attribute};
|
||||
use style::refcell::{Ref, RefCell, RefMut};
|
||||
use style::selector_impl::ElementExt;
|
||||
use style::selector_matching::DeclarationBlock;
|
||||
use style::selector_matching::ApplicableDeclarationBlock;
|
||||
use style::sink::Push;
|
||||
use url::Url;
|
||||
|
||||
|
@ -484,7 +484,7 @@ impl<'le> PartialEq for GeckoElement<'le> {
|
|||
|
||||
impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> {
|
||||
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
|
||||
where V: Push<DeclarationBlock>
|
||||
where V: Push<ApplicableDeclarationBlock>
|
||||
{
|
||||
// FIXME(bholley) - Need to implement this.
|
||||
}
|
||||
|
|
|
@ -6,8 +6,9 @@ use cssparser::Parser;
|
|||
use selectors::parser::{LocalName, ParserContext, parse_selector_list};
|
||||
use std::sync::Arc;
|
||||
use string_cache::Atom;
|
||||
use style::properties::{Importance, PropertyDeclarationBlock};
|
||||
use style::selector_matching::{DeclarationBlock, Rule, SelectorMap};
|
||||
use style::properties::{PropertyDeclarationBlock, PropertyDeclaration, DeclaredValue};
|
||||
use style::properties::{longhands, Importance};
|
||||
use style::selector_matching::{Rule, SelectorMap};
|
||||
|
||||
/// Helper method to get some Rules from selector strings.
|
||||
/// Each sublist of the result contains the Rules for one StyleRule.
|
||||
|
@ -18,15 +19,16 @@ fn get_mock_rules(css_selectors: &[&str]) -> Vec<Vec<Rule>> {
|
|||
.unwrap().into_iter().map(|s| {
|
||||
Rule {
|
||||
selector: s.complex_selector.clone(),
|
||||
declarations: DeclarationBlock {
|
||||
mixed_declarations: Arc::new(PropertyDeclarationBlock {
|
||||
declarations: Vec::new(),
|
||||
important_count: 0,
|
||||
}),
|
||||
importance: Importance::Normal,
|
||||
specificity: s.specificity,
|
||||
source_order: i,
|
||||
}
|
||||
declarations: Arc::new(PropertyDeclarationBlock {
|
||||
declarations: vec![
|
||||
(PropertyDeclaration::Display(DeclaredValue::Value(
|
||||
longhands::display::SpecifiedValue::block)),
|
||||
Importance::Normal),
|
||||
],
|
||||
important_count: 0,
|
||||
}),
|
||||
specificity: s.specificity,
|
||||
source_order: i,
|
||||
}
|
||||
}).collect()
|
||||
}).collect()
|
||||
|
@ -48,8 +50,8 @@ fn get_mock_map(selectors: &[&str]) -> SelectorMap {
|
|||
#[test]
|
||||
fn test_rule_ordering_same_specificity() {
|
||||
let rules_list = get_mock_rules(&["a.intro", "img.sidebar"]);
|
||||
let a = &rules_list[0][0].declarations;
|
||||
let b = &rules_list[1][0].declarations;
|
||||
let a = &rules_list[0][0];
|
||||
let b = &rules_list[1][0];
|
||||
assert!((a.specificity, a.source_order) < ((b.specificity, b.source_order)),
|
||||
"The rule that comes later should win.");
|
||||
}
|
||||
|
@ -89,9 +91,9 @@ fn test_insert() {
|
|||
let rules_list = get_mock_rules(&[".intro.foo", "#top"]);
|
||||
let mut selector_map = SelectorMap::new();
|
||||
selector_map.insert(rules_list[1][0].clone());
|
||||
assert_eq!(1, selector_map.id_hash.get(&atom!("top")).unwrap()[0].declarations.source_order);
|
||||
assert_eq!(1, selector_map.id_hash.get(&atom!("top")).unwrap()[0].source_order);
|
||||
selector_map.insert(rules_list[0][0].clone());
|
||||
assert_eq!(0, selector_map.class_hash.get(&Atom::from("intro")).unwrap()[0].declarations.source_order);
|
||||
assert_eq!(0, selector_map.class_hash.get(&Atom::from("intro")).unwrap()[0].source_order);
|
||||
assert!(selector_map.class_hash.get(&Atom::from("foo")).is_none());
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче