mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
Bug 1345950: stylo: Fix slow selector flags. r=bholley
MozReview-Commit-ID: QwuSxulNG0 Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
This commit is contained in:
parent
f90f7d6824
commit
a9b133bcbb
9 changed files with 288 additions and 189 deletions
|
@ -2416,10 +2416,13 @@ impl<'a> ::selectors::Element for Root<Element> {
|
||||||
self.namespace()
|
self.namespace()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_non_ts_pseudo_class(&self,
|
fn match_non_ts_pseudo_class<F>(&self,
|
||||||
pseudo_class: &NonTSPseudoClass,
|
pseudo_class: &NonTSPseudoClass,
|
||||||
_: &mut StyleRelations,
|
_: &mut StyleRelations,
|
||||||
_: &mut ElementSelectorFlags) -> bool {
|
_: &mut F)
|
||||||
|
-> bool
|
||||||
|
where F: FnMut(&Self, ElementSelectorFlags),
|
||||||
|
{
|
||||||
match *pseudo_class {
|
match *pseudo_class {
|
||||||
// https://github.com/servo/servo/issues/8718
|
// https://github.com/servo/servo/issues/8718
|
||||||
NonTSPseudoClass::Link |
|
NonTSPseudoClass::Link |
|
||||||
|
|
|
@ -615,10 +615,13 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
|
||||||
self.element.namespace()
|
self.element.namespace()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_non_ts_pseudo_class(&self,
|
fn match_non_ts_pseudo_class<F>(&self,
|
||||||
pseudo_class: &NonTSPseudoClass,
|
pseudo_class: &NonTSPseudoClass,
|
||||||
_: &mut StyleRelations,
|
_: &mut StyleRelations,
|
||||||
_: &mut ElementSelectorFlags) -> bool {
|
_: &mut F)
|
||||||
|
-> bool
|
||||||
|
where F: FnMut(&Self, ElementSelectorFlags),
|
||||||
|
{
|
||||||
match *pseudo_class {
|
match *pseudo_class {
|
||||||
// https://github.com/servo/servo/issues/8718
|
// https://github.com/servo/servo/issues/8718
|
||||||
NonTSPseudoClass::Link |
|
NonTSPseudoClass::Link |
|
||||||
|
@ -1114,10 +1117,13 @@ impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
|
||||||
self.element.get_namespace()
|
self.element.get_namespace()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_non_ts_pseudo_class(&self,
|
fn match_non_ts_pseudo_class<F>(&self,
|
||||||
_: &NonTSPseudoClass,
|
_: &NonTSPseudoClass,
|
||||||
_: &mut StyleRelations,
|
_: &mut StyleRelations,
|
||||||
_: &mut ElementSelectorFlags) -> bool {
|
_: &mut F)
|
||||||
|
-> bool
|
||||||
|
where F: FnMut(&Self, ElementSelectorFlags),
|
||||||
|
{
|
||||||
// NB: This could maybe be implemented
|
// NB: This could maybe be implemented
|
||||||
warn!("ServoThreadSafeLayoutElement::match_non_ts_pseudo_class called");
|
warn!("ServoThreadSafeLayoutElement::match_non_ts_pseudo_class called");
|
||||||
false
|
false
|
||||||
|
|
|
@ -107,8 +107,11 @@ pub fn matches<E>(selector_list: &[Selector<E::Impl>],
|
||||||
{
|
{
|
||||||
selector_list.iter().any(|selector| {
|
selector_list.iter().any(|selector| {
|
||||||
selector.pseudo_element.is_none() &&
|
selector.pseudo_element.is_none() &&
|
||||||
matches_complex_selector(&*selector.complex_selector, element, parent_bf,
|
matches_complex_selector(&*selector.complex_selector,
|
||||||
&mut StyleRelations::empty(), &mut ElementSelectorFlags::empty())
|
element,
|
||||||
|
parent_bf,
|
||||||
|
&mut StyleRelations::empty(),
|
||||||
|
&mut |_, _| {})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,13 +165,14 @@ fn may_match<E>(mut selector: &ComplexSelector<E::Impl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines whether the given element matches the given complex selector.
|
/// Determines whether the given element matches the given complex selector.
|
||||||
pub fn matches_complex_selector<E>(selector: &ComplexSelector<E::Impl>,
|
pub fn matches_complex_selector<E, F>(selector: &ComplexSelector<E::Impl>,
|
||||||
element: &E,
|
element: &E,
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags)
|
flags_setter: &mut F)
|
||||||
-> bool
|
-> bool
|
||||||
where E: Element
|
where E: Element,
|
||||||
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
if let Some(filter) = parent_bf {
|
if let Some(filter) = parent_bf {
|
||||||
if !may_match::<E>(selector, filter) {
|
if !may_match::<E>(selector, filter) {
|
||||||
|
@ -176,7 +180,10 @@ pub fn matches_complex_selector<E>(selector: &ComplexSelector<E::Impl>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match matches_complex_selector_internal(selector, element, relations, flags) {
|
match matches_complex_selector_internal(selector,
|
||||||
|
element,
|
||||||
|
relations,
|
||||||
|
flags_setter) {
|
||||||
SelectorMatchingResult::Matched => {
|
SelectorMatchingResult::Matched => {
|
||||||
match selector.next {
|
match selector.next {
|
||||||
Some((_, Combinator::NextSibling)) |
|
Some((_, Combinator::NextSibling)) |
|
||||||
|
@ -240,17 +247,26 @@ enum SelectorMatchingResult {
|
||||||
NotMatchedGlobally,
|
NotMatchedGlobally,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn matches_complex_selector_internal<E>(selector: &ComplexSelector<E::Impl>,
|
fn matches_complex_selector_internal<E, F>(selector: &ComplexSelector<E::Impl>,
|
||||||
element: &E,
|
element: &E,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags)
|
flags_setter: &mut F)
|
||||||
-> SelectorMatchingResult
|
-> SelectorMatchingResult
|
||||||
where E: Element
|
where E: Element,
|
||||||
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
let matches_all_simple_selectors = selector.compound_selector.iter().all(|simple| {
|
let matches_all_simple_selectors = selector.compound_selector.iter().all(|simple| {
|
||||||
matches_simple_selector(simple, element, relations, flags)
|
matches_simple_selector(simple, element, relations, flags_setter)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let siblings = selector.next.as_ref().map_or(false, |&(_, combinator)| {
|
||||||
|
matches!(combinator, Combinator::NextSibling | Combinator::LaterSibling)
|
||||||
|
});
|
||||||
|
|
||||||
|
if siblings {
|
||||||
|
flags_setter(element, HAS_SLOW_SELECTOR_LATER_SIBLINGS);
|
||||||
|
}
|
||||||
|
|
||||||
if !matches_all_simple_selectors {
|
if !matches_all_simple_selectors {
|
||||||
return SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling;
|
return SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling;
|
||||||
}
|
}
|
||||||
|
@ -258,17 +274,14 @@ fn matches_complex_selector_internal<E>(selector: &ComplexSelector<E::Impl>,
|
||||||
match selector.next {
|
match selector.next {
|
||||||
None => SelectorMatchingResult::Matched,
|
None => SelectorMatchingResult::Matched,
|
||||||
Some((ref next_selector, combinator)) => {
|
Some((ref next_selector, combinator)) => {
|
||||||
let (siblings, candidate_not_found) = match combinator {
|
let (mut next_element, candidate_not_found) = if siblings {
|
||||||
Combinator::Child => (false, SelectorMatchingResult::NotMatchedGlobally),
|
(element.prev_sibling_element(),
|
||||||
Combinator::Descendant => (false, SelectorMatchingResult::NotMatchedGlobally),
|
SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant)
|
||||||
Combinator::NextSibling => (true, SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant),
|
|
||||||
Combinator::LaterSibling => (true, SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant),
|
|
||||||
};
|
|
||||||
let mut next_element = if siblings {
|
|
||||||
element.prev_sibling_element()
|
|
||||||
} else {
|
} else {
|
||||||
element.parent_element()
|
(element.parent_element(),
|
||||||
|
SelectorMatchingResult::NotMatchedGlobally)
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let element = match next_element {
|
let element = match next_element {
|
||||||
None => return candidate_not_found,
|
None => return candidate_not_found,
|
||||||
|
@ -277,7 +290,7 @@ fn matches_complex_selector_internal<E>(selector: &ComplexSelector<E::Impl>,
|
||||||
let result = matches_complex_selector_internal(&**next_selector,
|
let result = matches_complex_selector_internal(&**next_selector,
|
||||||
&element,
|
&element,
|
||||||
relations,
|
relations,
|
||||||
flags);
|
flags_setter);
|
||||||
match (result, combinator) {
|
match (result, combinator) {
|
||||||
// Return the status immediately.
|
// Return the status immediately.
|
||||||
(SelectorMatchingResult::Matched, _) => return result,
|
(SelectorMatchingResult::Matched, _) => return result,
|
||||||
|
@ -316,13 +329,14 @@ fn matches_complex_selector_internal<E>(selector: &ComplexSelector<E::Impl>,
|
||||||
|
|
||||||
/// Determines whether the given element matches the given single selector.
|
/// Determines whether the given element matches the given single selector.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn matches_simple_selector<E>(
|
fn matches_simple_selector<E, F>(
|
||||||
selector: &SimpleSelector<E::Impl>,
|
selector: &SimpleSelector<E::Impl>,
|
||||||
element: &E,
|
element: &E,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags)
|
flags_setter: &mut F)
|
||||||
-> bool
|
-> bool
|
||||||
where E: Element
|
where E: Element,
|
||||||
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
macro_rules! relation_if {
|
macro_rules! relation_if {
|
||||||
($ex:expr, $flag:ident) => {
|
($ex:expr, $flag:ident) => {
|
||||||
|
@ -399,18 +413,21 @@ fn matches_simple_selector<E>(
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
SimpleSelector::NonTSPseudoClass(ref pc) => {
|
SimpleSelector::NonTSPseudoClass(ref pc) => {
|
||||||
relation_if!(element.match_non_ts_pseudo_class(pc, relations, flags),
|
relation_if!(element.match_non_ts_pseudo_class(pc, relations, flags_setter),
|
||||||
AFFECTED_BY_STATE)
|
AFFECTED_BY_STATE)
|
||||||
}
|
}
|
||||||
SimpleSelector::FirstChild => {
|
SimpleSelector::FirstChild => {
|
||||||
relation_if!(matches_first_child(element, flags), AFFECTED_BY_CHILD_INDEX)
|
relation_if!(matches_first_child(element, flags_setter),
|
||||||
|
AFFECTED_BY_CHILD_INDEX)
|
||||||
}
|
}
|
||||||
SimpleSelector::LastChild => {
|
SimpleSelector::LastChild => {
|
||||||
relation_if!(matches_last_child(element, flags), AFFECTED_BY_CHILD_INDEX)
|
relation_if!(matches_last_child(element, flags_setter),
|
||||||
|
AFFECTED_BY_CHILD_INDEX)
|
||||||
}
|
}
|
||||||
SimpleSelector::OnlyChild => {
|
SimpleSelector::OnlyChild => {
|
||||||
relation_if!(matches_first_child(element, flags) &&
|
relation_if!(matches_first_child(element, flags_setter) &&
|
||||||
matches_last_child(element, flags), AFFECTED_BY_CHILD_INDEX)
|
matches_last_child(element, flags_setter),
|
||||||
|
AFFECTED_BY_CHILD_INDEX)
|
||||||
}
|
}
|
||||||
SimpleSelector::Root => {
|
SimpleSelector::Root => {
|
||||||
// We never share styles with an element with no parent, so no point
|
// We never share styles with an element with no parent, so no point
|
||||||
|
@ -418,41 +435,44 @@ fn matches_simple_selector<E>(
|
||||||
element.is_root()
|
element.is_root()
|
||||||
}
|
}
|
||||||
SimpleSelector::Empty => {
|
SimpleSelector::Empty => {
|
||||||
flags.insert(HAS_EMPTY_SELECTOR);
|
flags_setter(element, HAS_EMPTY_SELECTOR);
|
||||||
relation_if!(element.is_empty(), AFFECTED_BY_EMPTY)
|
relation_if!(element.is_empty(), AFFECTED_BY_EMPTY)
|
||||||
}
|
}
|
||||||
SimpleSelector::NthChild(a, b) => {
|
SimpleSelector::NthChild(a, b) => {
|
||||||
relation_if!(matches_generic_nth_child(element, a, b, false, false, flags),
|
relation_if!(matches_generic_nth_child(element, a, b, false, false, flags_setter),
|
||||||
AFFECTED_BY_CHILD_INDEX)
|
AFFECTED_BY_CHILD_INDEX)
|
||||||
}
|
}
|
||||||
SimpleSelector::NthLastChild(a, b) => {
|
SimpleSelector::NthLastChild(a, b) => {
|
||||||
relation_if!(matches_generic_nth_child(element, a, b, false, true, flags),
|
relation_if!(matches_generic_nth_child(element, a, b, false, true, flags_setter),
|
||||||
AFFECTED_BY_CHILD_INDEX)
|
AFFECTED_BY_CHILD_INDEX)
|
||||||
}
|
}
|
||||||
SimpleSelector::NthOfType(a, b) => {
|
SimpleSelector::NthOfType(a, b) => {
|
||||||
relation_if!(matches_generic_nth_child(element, a, b, true, false, flags),
|
relation_if!(matches_generic_nth_child(element, a, b, true, false, flags_setter),
|
||||||
AFFECTED_BY_CHILD_INDEX)
|
AFFECTED_BY_CHILD_INDEX)
|
||||||
}
|
}
|
||||||
SimpleSelector::NthLastOfType(a, b) => {
|
SimpleSelector::NthLastOfType(a, b) => {
|
||||||
relation_if!(matches_generic_nth_child(element, a, b, true, true, flags),
|
relation_if!(matches_generic_nth_child(element, a, b, true, true, flags_setter),
|
||||||
AFFECTED_BY_CHILD_INDEX)
|
AFFECTED_BY_CHILD_INDEX)
|
||||||
}
|
}
|
||||||
SimpleSelector::FirstOfType => {
|
SimpleSelector::FirstOfType => {
|
||||||
relation_if!(matches_generic_nth_child(element, 0, 1, true, false, flags),
|
relation_if!(matches_generic_nth_child(element, 0, 1, true, false, flags_setter),
|
||||||
AFFECTED_BY_CHILD_INDEX)
|
AFFECTED_BY_CHILD_INDEX)
|
||||||
}
|
}
|
||||||
SimpleSelector::LastOfType => {
|
SimpleSelector::LastOfType => {
|
||||||
relation_if!(matches_generic_nth_child(element, 0, 1, true, true, flags),
|
relation_if!(matches_generic_nth_child(element, 0, 1, true, true, flags_setter),
|
||||||
AFFECTED_BY_CHILD_INDEX)
|
AFFECTED_BY_CHILD_INDEX)
|
||||||
}
|
}
|
||||||
SimpleSelector::OnlyOfType => {
|
SimpleSelector::OnlyOfType => {
|
||||||
relation_if!(matches_generic_nth_child(element, 0, 1, true, false, flags) &&
|
relation_if!(matches_generic_nth_child(element, 0, 1, true, false, flags_setter) &&
|
||||||
matches_generic_nth_child(element, 0, 1, true, true, flags),
|
matches_generic_nth_child(element, 0, 1, true, true, flags_setter),
|
||||||
AFFECTED_BY_CHILD_INDEX)
|
AFFECTED_BY_CHILD_INDEX)
|
||||||
}
|
}
|
||||||
SimpleSelector::Negation(ref negated) => {
|
SimpleSelector::Negation(ref negated) => {
|
||||||
!negated.iter().all(|s| {
|
!negated.iter().all(|s| {
|
||||||
match matches_complex_selector_internal(s, element, relations, flags) {
|
match matches_complex_selector_internal(s,
|
||||||
|
element,
|
||||||
|
relations,
|
||||||
|
flags_setter) {
|
||||||
SelectorMatchingResult::Matched => true,
|
SelectorMatchingResult::Matched => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -462,16 +482,17 @@ fn matches_simple_selector<E>(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn matches_generic_nth_child<E>(element: &E,
|
fn matches_generic_nth_child<E, F>(element: &E,
|
||||||
a: i32,
|
a: i32,
|
||||||
b: i32,
|
b: i32,
|
||||||
is_of_type: bool,
|
is_of_type: bool,
|
||||||
is_from_end: bool,
|
is_from_end: bool,
|
||||||
flags: &mut ElementSelectorFlags)
|
flags_setter: &mut F)
|
||||||
-> bool
|
-> bool
|
||||||
where E: Element
|
where E: Element,
|
||||||
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
flags.insert(if is_from_end {
|
flags_setter(element, if is_from_end {
|
||||||
HAS_SLOW_SELECTOR
|
HAS_SLOW_SELECTOR
|
||||||
} else {
|
} else {
|
||||||
HAS_SLOW_SELECTOR_LATER_SIBLINGS
|
HAS_SLOW_SELECTOR_LATER_SIBLINGS
|
||||||
|
@ -514,15 +535,19 @@ fn matches_generic_nth_child<E>(element: &E,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn matches_first_child<E>(element: &E, flags: &mut ElementSelectorFlags)
|
fn matches_first_child<E, F>(element: &E, flags_setter: &mut F) -> bool
|
||||||
-> bool where E: Element {
|
where E: Element,
|
||||||
flags.insert(HAS_EDGE_CHILD_SELECTOR);
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
|
{
|
||||||
|
flags_setter(element, HAS_EDGE_CHILD_SELECTOR);
|
||||||
element.prev_sibling_element().is_none()
|
element.prev_sibling_element().is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn matches_last_child<E>(element: &E, flags: &mut ElementSelectorFlags)
|
fn matches_last_child<E, F>(element: &E, flags_setter: &mut F) -> bool
|
||||||
-> bool where E: Element {
|
where E: Element,
|
||||||
flags.insert(HAS_EDGE_CHILD_SELECTOR);
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
|
{
|
||||||
|
flags_setter(element, HAS_EDGE_CHILD_SELECTOR);
|
||||||
element.next_sibling_element().is_none()
|
element.next_sibling_element().is_none()
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,10 +139,11 @@ pub trait Element: MatchAttr + Sized {
|
||||||
fn get_local_name(&self) -> &<Self::Impl as SelectorImpl>::BorrowedLocalName;
|
fn get_local_name(&self) -> &<Self::Impl as SelectorImpl>::BorrowedLocalName;
|
||||||
fn get_namespace(&self) -> &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl;
|
fn get_namespace(&self) -> &<Self::Impl as SelectorImpl>::BorrowedNamespaceUrl;
|
||||||
|
|
||||||
fn match_non_ts_pseudo_class(&self,
|
fn match_non_ts_pseudo_class<F>(&self,
|
||||||
pc: &<Self::Impl as SelectorImpl>::NonTSPseudoClass,
|
pc: &<Self::Impl as SelectorImpl>::NonTSPseudoClass,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags) -> bool;
|
flags_setter: &mut F) -> bool
|
||||||
|
where F: FnMut(&Self, ElementSelectorFlags);
|
||||||
|
|
||||||
fn get_id(&self) -> Option<<Self::Impl as SelectorImpl>::Identifier>;
|
fn get_id(&self) -> Option<<Self::Impl as SelectorImpl>::Identifier>;
|
||||||
fn has_class(&self, name: &<Self::Impl as SelectorImpl>::ClassName) -> bool;
|
fn has_class(&self, name: &<Self::Impl as SelectorImpl>::ClassName) -> bool;
|
||||||
|
|
|
@ -663,10 +663,13 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_non_ts_pseudo_class(&self,
|
fn match_non_ts_pseudo_class<F>(&self,
|
||||||
pseudo_class: &NonTSPseudoClass,
|
pseudo_class: &NonTSPseudoClass,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags) -> bool {
|
flags_setter: &mut F)
|
||||||
|
-> bool
|
||||||
|
where F: FnMut(&Self, ElementSelectorFlags),
|
||||||
|
{
|
||||||
match *pseudo_class {
|
match *pseudo_class {
|
||||||
// https://github.com/servo/servo/issues/8718
|
// https://github.com/servo/servo/issues/8718
|
||||||
NonTSPseudoClass::AnyLink => unsafe { Gecko_IsLink(self.0) },
|
NonTSPseudoClass::AnyLink => unsafe { Gecko_IsLink(self.0) },
|
||||||
|
@ -704,7 +707,13 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
Gecko_MatchesElement(pseudo_class.to_gecko_pseudoclasstype().unwrap(), self.0)
|
Gecko_MatchesElement(pseudo_class.to_gecko_pseudoclasstype().unwrap(), self.0)
|
||||||
},
|
},
|
||||||
NonTSPseudoClass::MozAny(ref sels) => {
|
NonTSPseudoClass::MozAny(ref sels) => {
|
||||||
sels.iter().any(|s| matches_complex_selector(s, self, None, relations, flags))
|
sels.iter().any(|s| {
|
||||||
|
matches_complex_selector(s,
|
||||||
|
self,
|
||||||
|
None,
|
||||||
|
relations,
|
||||||
|
flags_setter)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
NonTSPseudoClass::MozSystemMetric(ref s) |
|
NonTSPseudoClass::MozSystemMetric(ref s) |
|
||||||
NonTSPseudoClass::MozLocaleDir(ref s) |
|
NonTSPseudoClass::MozLocaleDir(ref s) |
|
||||||
|
@ -718,7 +727,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
pseudo_class.to_gecko_pseudoclasstype().unwrap(),
|
pseudo_class.to_gecko_pseudoclasstype().unwrap(),
|
||||||
s.as_ptr(), &mut set_slow_selector);
|
s.as_ptr(), &mut set_slow_selector);
|
||||||
if set_slow_selector {
|
if set_slow_selector {
|
||||||
*flags |= HAS_SLOW_SELECTOR;
|
flags_setter(self, HAS_SLOW_SELECTOR);
|
||||||
}
|
}
|
||||||
matches
|
matches
|
||||||
}
|
}
|
||||||
|
@ -862,7 +871,7 @@ impl<'le> ElementExt for GeckoElement<'le> {
|
||||||
fn is_link(&self) -> bool {
|
fn is_link(&self) -> bool {
|
||||||
self.match_non_ts_pseudo_class(&NonTSPseudoClass::AnyLink,
|
self.match_non_ts_pseudo_class(&NonTSPseudoClass::AnyLink,
|
||||||
&mut StyleRelations::empty(),
|
&mut StyleRelations::empty(),
|
||||||
&mut ElementSelectorFlags::empty())
|
&mut |_, _| {})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -18,7 +18,7 @@ use dom::{AnimationRules, SendElement, TElement, TNode};
|
||||||
use properties::{CascadeFlags, ComputedValues, SHAREABLE, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade};
|
use properties::{CascadeFlags, ComputedValues, SHAREABLE, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade};
|
||||||
use properties::longhands::display::computed_value as display;
|
use properties::longhands::display::computed_value as display;
|
||||||
use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RestyleHint};
|
use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RestyleHint};
|
||||||
use rule_tree::{CascadeLevel, StrongRuleNode};
|
use rule_tree::{CascadeLevel, RuleTree, StrongRuleNode};
|
||||||
use selector_parser::{PseudoElement, RestyleDamage, SelectorImpl};
|
use selector_parser::{PseudoElement, RestyleDamage, SelectorImpl};
|
||||||
use selectors::MatchAttr;
|
use selectors::MatchAttr;
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
|
@ -750,12 +750,12 @@ trait PrivateMatchMethods: TElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_rule_node<E: TElement>(context: &StyleContext<E>,
|
fn compute_rule_node<E: TElement>(rule_tree: &RuleTree,
|
||||||
applicable_declarations: &mut Vec<ApplicableDeclarationBlock>)
|
applicable_declarations: &mut Vec<ApplicableDeclarationBlock>)
|
||||||
-> StrongRuleNode
|
-> StrongRuleNode
|
||||||
{
|
{
|
||||||
let rules = applicable_declarations.drain(..).map(|d| (d.source, d.level));
|
let rules = applicable_declarations.drain(..).map(|d| (d.source, d.level));
|
||||||
let rule_node = context.shared.stylist.rule_tree.insert_ordered_rules(rules);
|
let rule_node = rule_tree.insert_ordered_rules(rules);
|
||||||
rule_node
|
rule_node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -775,20 +775,75 @@ pub trait MatchMethods : TElement {
|
||||||
let stylist = &context.shared.stylist;
|
let stylist = &context.shared.stylist;
|
||||||
let style_attribute = self.style_attribute();
|
let style_attribute = self.style_attribute();
|
||||||
let animation_rules = self.get_animation_rules(None);
|
let animation_rules = self.get_animation_rules(None);
|
||||||
let mut flags = ElementSelectorFlags::empty();
|
|
||||||
let mut rule_nodes_changed = false;
|
let mut rule_nodes_changed = false;
|
||||||
|
|
||||||
|
// TODO(emilio): This is somewhat inefficient, because of a variety of
|
||||||
|
// reasons:
|
||||||
|
//
|
||||||
|
// * It doesn't coalesce flags.
|
||||||
|
// * It doesn't look at flags already sent in a task for the main
|
||||||
|
// thread to process.
|
||||||
|
// * It doesn't take advantage of us knowing that the traversal is
|
||||||
|
// sequential.
|
||||||
|
//
|
||||||
|
// I suspect (need to measure!) that we don't use to set flags on
|
||||||
|
// a lot of different elements, but we could end up posting the same
|
||||||
|
// flag over and over with this approach.
|
||||||
|
//
|
||||||
|
// If the number of elements is low, perhaps a small cache with the
|
||||||
|
// flags already sent would be appropriate.
|
||||||
|
//
|
||||||
|
// The sequential task business for this is kind of sad :(.
|
||||||
|
//
|
||||||
|
// Anyway, let's do the obvious thing for now.
|
||||||
|
let tasks = &mut context.thread_local.tasks;
|
||||||
|
let mut set_selector_flags = |element: &Self, flags: ElementSelectorFlags| {
|
||||||
|
// Apply the selector flags.
|
||||||
|
let self_flags = flags.for_self();
|
||||||
|
if !self_flags.is_empty() {
|
||||||
|
if element == self {
|
||||||
|
unsafe { element.set_selector_flags(self_flags); }
|
||||||
|
} else {
|
||||||
|
if !element.has_selector_flags(self_flags) {
|
||||||
|
let task =
|
||||||
|
SequentialTask::set_selector_flags(element.clone(),
|
||||||
|
self_flags);
|
||||||
|
tasks.push(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let parent_flags = flags.for_parent();
|
||||||
|
if !parent_flags.is_empty() {
|
||||||
|
if let Some(p) = element.parent_element() {
|
||||||
|
// Avoid the overhead of the SequentialTask if the flags are
|
||||||
|
// already set.
|
||||||
|
if !p.has_selector_flags(parent_flags) {
|
||||||
|
let task = SequentialTask::set_selector_flags(p, parent_flags);
|
||||||
|
tasks.push(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Borrow the stuff we need here so the borrow checker doesn't get mad
|
||||||
|
// at us later in the closure.
|
||||||
|
let guards = &context.shared.guards;
|
||||||
|
let rule_tree = &context.shared.stylist.rule_tree;
|
||||||
|
let bloom_filter = context.thread_local.bloom_filter.filter();
|
||||||
|
|
||||||
// Compute the primary rule node.
|
// Compute the primary rule node.
|
||||||
let mut primary_relations =
|
let mut primary_relations =
|
||||||
stylist.push_applicable_declarations(self,
|
stylist.push_applicable_declarations(self,
|
||||||
Some(context.thread_local.bloom_filter.filter()),
|
Some(bloom_filter),
|
||||||
style_attribute,
|
style_attribute,
|
||||||
animation_rules,
|
animation_rules,
|
||||||
None,
|
None,
|
||||||
&context.shared.guards,
|
guards,
|
||||||
&mut applicable_declarations,
|
&mut applicable_declarations,
|
||||||
&mut flags);
|
&mut set_selector_flags);
|
||||||
let primary_rule_node = compute_rule_node(context, &mut applicable_declarations);
|
|
||||||
|
let primary_rule_node =
|
||||||
|
compute_rule_node::<Self>(rule_tree, &mut applicable_declarations);
|
||||||
if !data.has_styles() {
|
if !data.has_styles() {
|
||||||
data.set_styles(ElementStyles::new(ComputedStyle::new_partial(primary_rule_node)));
|
data.set_styles(ElementStyles::new(ComputedStyle::new_partial(primary_rule_node)));
|
||||||
rule_nodes_changed = true;
|
rule_nodes_changed = true;
|
||||||
|
@ -808,15 +863,16 @@ pub trait MatchMethods : TElement {
|
||||||
AnimationRules(None, None)
|
AnimationRules(None, None)
|
||||||
};
|
};
|
||||||
stylist.push_applicable_declarations(self,
|
stylist.push_applicable_declarations(self,
|
||||||
Some(context.thread_local.bloom_filter.filter()),
|
Some(bloom_filter),
|
||||||
None, pseudo_animation_rules,
|
None, pseudo_animation_rules,
|
||||||
Some(&pseudo),
|
Some(&pseudo),
|
||||||
&context.shared.guards,
|
&guards,
|
||||||
&mut applicable_declarations,
|
&mut applicable_declarations,
|
||||||
&mut flags);
|
&mut set_selector_flags);
|
||||||
|
|
||||||
if !applicable_declarations.is_empty() {
|
if !applicable_declarations.is_empty() {
|
||||||
let new_rules = compute_rule_node(context, &mut applicable_declarations);
|
let new_rules =
|
||||||
|
compute_rule_node::<Self>(rule_tree, &mut applicable_declarations);
|
||||||
match per_pseudo.entry(pseudo) {
|
match per_pseudo.entry(pseudo) {
|
||||||
Entry::Occupied(mut e) => {
|
Entry::Occupied(mut e) => {
|
||||||
if e.get().rules != new_rules {
|
if e.get().rules != new_rules {
|
||||||
|
@ -848,22 +904,6 @@ pub trait MatchMethods : TElement {
|
||||||
primary_relations |= AFFECTED_BY_PSEUDO_ELEMENTS;
|
primary_relations |= AFFECTED_BY_PSEUDO_ELEMENTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the selector flags.
|
|
||||||
let self_flags = flags.for_self();
|
|
||||||
if !self_flags.is_empty() {
|
|
||||||
unsafe { self.set_selector_flags(self_flags); }
|
|
||||||
}
|
|
||||||
let parent_flags = flags.for_parent();
|
|
||||||
if !parent_flags.is_empty() {
|
|
||||||
if let Some(p) = self.parent_element() {
|
|
||||||
// Avoid the overhead of the SequentialTask if the flags are already set.
|
|
||||||
if !p.has_selector_flags(parent_flags) {
|
|
||||||
let task = SequentialTask::set_selector_flags(p, parent_flags);
|
|
||||||
context.thread_local.tasks.push(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MatchResults {
|
MatchResults {
|
||||||
primary_relations: Some(primary_relations),
|
primary_relations: Some(primary_relations),
|
||||||
rule_nodes_changed: rule_nodes_changed,
|
rule_nodes_changed: rule_nodes_changed,
|
||||||
|
|
|
@ -269,17 +269,25 @@ impl<'a, E> MatchAttr for ElementWrapper<'a, E>
|
||||||
impl<'a, E> Element for ElementWrapper<'a, E>
|
impl<'a, E> Element for ElementWrapper<'a, E>
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
{
|
{
|
||||||
fn match_non_ts_pseudo_class(&self,
|
fn match_non_ts_pseudo_class<F>(&self,
|
||||||
pseudo_class: &NonTSPseudoClass,
|
pseudo_class: &NonTSPseudoClass,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags) -> bool {
|
_: &mut F)
|
||||||
|
-> bool
|
||||||
|
where F: FnMut(&Self, ElementSelectorFlags),
|
||||||
|
{
|
||||||
let flag = SelectorImpl::pseudo_class_state_flag(pseudo_class);
|
let flag = SelectorImpl::pseudo_class_state_flag(pseudo_class);
|
||||||
if flag == ElementState::empty() {
|
if flag.is_empty() {
|
||||||
self.element.match_non_ts_pseudo_class(pseudo_class, relations, flags)
|
return self.element.match_non_ts_pseudo_class(pseudo_class,
|
||||||
} else {
|
relations,
|
||||||
match self.snapshot.and_then(|s| s.state()) {
|
&mut |_, _| {})
|
||||||
Some(snapshot_state) => snapshot_state.contains(flag),
|
}
|
||||||
_ => self.element.match_non_ts_pseudo_class(pseudo_class, relations, flags)
|
match self.snapshot.and_then(|s| s.state()) {
|
||||||
|
Some(snapshot_state) => snapshot_state.contains(flag),
|
||||||
|
None => {
|
||||||
|
self.element.match_non_ts_pseudo_class(pseudo_class,
|
||||||
|
relations,
|
||||||
|
&mut |_, _| {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -581,11 +589,11 @@ impl DependencySet {
|
||||||
let matched_then =
|
let matched_then =
|
||||||
matches_complex_selector(&dep.selector, snapshot, None,
|
matches_complex_selector(&dep.selector, snapshot, None,
|
||||||
&mut StyleRelations::empty(),
|
&mut StyleRelations::empty(),
|
||||||
&mut ElementSelectorFlags::empty());
|
&mut |_, _| {});
|
||||||
let matches_now =
|
let matches_now =
|
||||||
matches_complex_selector(&dep.selector, element, None,
|
matches_complex_selector(&dep.selector, element, None,
|
||||||
&mut StyleRelations::empty(),
|
&mut StyleRelations::empty(),
|
||||||
&mut ElementSelectorFlags::empty());
|
&mut |_, _| {});
|
||||||
if matched_then != matches_now {
|
if matched_then != matches_now {
|
||||||
hint.insert(dep.hint);
|
hint.insert(dep.hint);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use restyle_hints::ElementSnapshot;
|
||||||
use selector_parser::{ElementExt, PseudoElementCascadeType, SelectorParser};
|
use selector_parser::{ElementExt, PseudoElementCascadeType, SelectorParser};
|
||||||
use selector_parser::{attr_equals_selector_is_shareable, attr_exists_selector_is_shareable};
|
use selector_parser::{attr_equals_selector_is_shareable, attr_exists_selector_is_shareable};
|
||||||
use selectors::{Element, MatchAttrGeneric};
|
use selectors::{Element, MatchAttrGeneric};
|
||||||
use selectors::matching::{ElementSelectorFlags, StyleRelations};
|
use selectors::matching::StyleRelations;
|
||||||
use selectors::parser::{AttrSelector, SelectorMethods};
|
use selectors::parser::{AttrSelector, SelectorMethods};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -459,7 +459,7 @@ impl<E: Element<Impl=SelectorImpl> + Debug> ElementExt for E {
|
||||||
fn is_link(&self) -> bool {
|
fn is_link(&self) -> bool {
|
||||||
self.match_non_ts_pseudo_class(&NonTSPseudoClass::AnyLink,
|
self.match_non_ts_pseudo_class(&NonTSPseudoClass::AnyLink,
|
||||||
&mut StyleRelations::empty(),
|
&mut StyleRelations::empty(),
|
||||||
&mut ElementSelectorFlags::empty())
|
&mut |_, _| {})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -398,7 +398,31 @@ impl Stylist {
|
||||||
|
|
||||||
let mut declarations = vec![];
|
let mut declarations = vec![];
|
||||||
|
|
||||||
let mut flags = ElementSelectorFlags::empty();
|
// Apply the selector flags. We should be in sequential mode
|
||||||
|
// already, so we can directly apply the parent flags.
|
||||||
|
let mut set_selector_flags = |element: &E, flags: ElementSelectorFlags| {
|
||||||
|
if cfg!(feature = "servo") {
|
||||||
|
// Servo calls this function from the worker, but only for internal
|
||||||
|
// pseudos, so we should never generate selector flags here.
|
||||||
|
unreachable!("internal pseudo generated slow selector flags?");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gecko calls this from sequential mode, so we can directly apply
|
||||||
|
// the flags.
|
||||||
|
debug_assert!(thread_state::get() == thread_state::LAYOUT);
|
||||||
|
let self_flags = flags.for_self();
|
||||||
|
if !self_flags.is_empty() {
|
||||||
|
unsafe { element.set_selector_flags(self_flags); }
|
||||||
|
}
|
||||||
|
let parent_flags = flags.for_parent();
|
||||||
|
if !parent_flags.is_empty() {
|
||||||
|
if let Some(p) = element.parent_element() {
|
||||||
|
unsafe { p.set_selector_flags(parent_flags); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
self.push_applicable_declarations(element,
|
self.push_applicable_declarations(element,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
|
@ -406,7 +430,7 @@ impl Stylist {
|
||||||
Some(pseudo),
|
Some(pseudo),
|
||||||
guards,
|
guards,
|
||||||
&mut declarations,
|
&mut declarations,
|
||||||
&mut flags);
|
&mut set_selector_flags);
|
||||||
|
|
||||||
let rule_node =
|
let rule_node =
|
||||||
self.rule_tree.insert_ordered_rules(
|
self.rule_tree.insert_ordered_rules(
|
||||||
|
@ -426,28 +450,6 @@ impl Stylist {
|
||||||
&StdoutErrorReporter,
|
&StdoutErrorReporter,
|
||||||
CascadeFlags::empty());
|
CascadeFlags::empty());
|
||||||
|
|
||||||
// Apply the selector flags. We should be in sequential mode already,
|
|
||||||
// so we can directly apply the parent flags.
|
|
||||||
if cfg!(feature = "servo") {
|
|
||||||
// Servo calls this function from the worker, but only for internal
|
|
||||||
// pseudos, so we should never generate selector flags here.
|
|
||||||
debug_assert!(flags.is_empty());
|
|
||||||
} else {
|
|
||||||
// Gecko calls this from sequential mode, so we can directly apply
|
|
||||||
// the flags.
|
|
||||||
debug_assert!(thread_state::get() == thread_state::LAYOUT);
|
|
||||||
let self_flags = flags.for_self();
|
|
||||||
if !self_flags.is_empty() {
|
|
||||||
unsafe { element.set_selector_flags(self_flags); }
|
|
||||||
}
|
|
||||||
let parent_flags = flags.for_parent();
|
|
||||||
if !parent_flags.is_empty() {
|
|
||||||
if let Some(p) = element.parent_element() {
|
|
||||||
unsafe { p.set_selector_flags(parent_flags); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(ComputedStyle::new(rule_node, Arc::new(computed)))
|
Some(ComputedStyle::new(rule_node, Arc::new(computed)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,7 +539,7 @@ impl Stylist {
|
||||||
///
|
///
|
||||||
/// The returned `StyleRelations` indicate hints about which kind of rules
|
/// The returned `StyleRelations` indicate hints about which kind of rules
|
||||||
/// have matched.
|
/// have matched.
|
||||||
pub fn push_applicable_declarations<E, V>(
|
pub fn push_applicable_declarations<E, V, F>(
|
||||||
&self,
|
&self,
|
||||||
element: &E,
|
element: &E,
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
|
@ -546,11 +548,13 @@ impl Stylist {
|
||||||
pseudo_element: Option<&PseudoElement>,
|
pseudo_element: Option<&PseudoElement>,
|
||||||
guards: &StylesheetGuards,
|
guards: &StylesheetGuards,
|
||||||
applicable_declarations: &mut V,
|
applicable_declarations: &mut V,
|
||||||
flags: &mut ElementSelectorFlags) -> StyleRelations
|
flags_setter: &mut F)
|
||||||
|
-> StyleRelations
|
||||||
where E: TElement +
|
where E: TElement +
|
||||||
fmt::Debug +
|
fmt::Debug +
|
||||||
PresentationalHintsSynthetizer,
|
PresentationalHintsSynthetizer,
|
||||||
V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock>
|
V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock>,
|
||||||
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
debug_assert!(!self.is_device_dirty);
|
debug_assert!(!self.is_device_dirty);
|
||||||
debug_assert!(style_attribute.is_none() || pseudo_element.is_none(),
|
debug_assert!(style_attribute.is_none() || pseudo_element.is_none(),
|
||||||
|
@ -573,7 +577,7 @@ impl Stylist {
|
||||||
guards.ua_or_user,
|
guards.ua_or_user,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags_setter,
|
||||||
CascadeLevel::UANormal);
|
CascadeLevel::UANormal);
|
||||||
debug!("UA normal: {:?}", relations);
|
debug!("UA normal: {:?}", relations);
|
||||||
|
|
||||||
|
@ -598,7 +602,7 @@ impl Stylist {
|
||||||
guards.ua_or_user,
|
guards.ua_or_user,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags_setter,
|
||||||
CascadeLevel::UserNormal);
|
CascadeLevel::UserNormal);
|
||||||
debug!("user normal: {:?}", relations);
|
debug!("user normal: {:?}", relations);
|
||||||
map.author.get_all_matching_rules(element,
|
map.author.get_all_matching_rules(element,
|
||||||
|
@ -606,7 +610,7 @@ impl Stylist {
|
||||||
guards.author,
|
guards.author,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags_setter,
|
||||||
CascadeLevel::AuthorNormal);
|
CascadeLevel::AuthorNormal);
|
||||||
debug!("author normal: {:?}", relations);
|
debug!("author normal: {:?}", relations);
|
||||||
|
|
||||||
|
@ -641,7 +645,7 @@ impl Stylist {
|
||||||
guards.author,
|
guards.author,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags_setter,
|
||||||
CascadeLevel::AuthorImportant);
|
CascadeLevel::AuthorImportant);
|
||||||
|
|
||||||
debug!("author important: {:?}", relations);
|
debug!("author important: {:?}", relations);
|
||||||
|
@ -665,7 +669,7 @@ impl Stylist {
|
||||||
guards.ua_or_user,
|
guards.ua_or_user,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags_setter,
|
||||||
CascadeLevel::UserImportant);
|
CascadeLevel::UserImportant);
|
||||||
|
|
||||||
debug!("user important: {:?}", relations);
|
debug!("user important: {:?}", relations);
|
||||||
|
@ -679,7 +683,7 @@ impl Stylist {
|
||||||
guards.ua_or_user,
|
guards.ua_or_user,
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
&mut relations,
|
&mut relations,
|
||||||
flags,
|
flags_setter,
|
||||||
CascadeLevel::UAImportant);
|
CascadeLevel::UAImportant);
|
||||||
|
|
||||||
debug!("UA important: {:?}", relations);
|
debug!("UA important: {:?}", relations);
|
||||||
|
@ -735,11 +739,11 @@ impl Stylist {
|
||||||
let element_matches =
|
let element_matches =
|
||||||
matches_complex_selector(&selector.complex_selector, element,
|
matches_complex_selector(&selector.complex_selector, element,
|
||||||
None, &mut StyleRelations::empty(),
|
None, &mut StyleRelations::empty(),
|
||||||
&mut ElementSelectorFlags::empty());
|
&mut |_, _| {});
|
||||||
let candidate_matches =
|
let candidate_matches =
|
||||||
matches_complex_selector(&selector.complex_selector, candidate,
|
matches_complex_selector(&selector.complex_selector, candidate,
|
||||||
None, &mut StyleRelations::empty(),
|
None, &mut StyleRelations::empty(),
|
||||||
&mut ElementSelectorFlags::empty());
|
&mut |_, _| {});
|
||||||
|
|
||||||
if element_matches != candidate_matches {
|
if element_matches != candidate_matches {
|
||||||
return false;
|
return false;
|
||||||
|
@ -774,12 +778,12 @@ impl Stylist {
|
||||||
let element_matches =
|
let element_matches =
|
||||||
matches_complex_selector(&selector.complex_selector, element,
|
matches_complex_selector(&selector.complex_selector, element,
|
||||||
None, &mut StyleRelations::empty(),
|
None, &mut StyleRelations::empty(),
|
||||||
&mut ElementSelectorFlags::empty());
|
&mut |_, _| {});
|
||||||
|
|
||||||
let candidate_matches =
|
let candidate_matches =
|
||||||
matches_complex_selector(&selector.complex_selector, candidate,
|
matches_complex_selector(&selector.complex_selector, candidate,
|
||||||
None, &mut StyleRelations::empty(),
|
None, &mut StyleRelations::empty(),
|
||||||
&mut ElementSelectorFlags::empty());
|
&mut |_, _| {});
|
||||||
|
|
||||||
if element_matches != candidate_matches {
|
if element_matches != candidate_matches {
|
||||||
debug!("match_same_sibling_affecting_rules: Failure due to {:?}",
|
debug!("match_same_sibling_affecting_rules: Failure due to {:?}",
|
||||||
|
@ -912,16 +916,17 @@ impl SelectorMap {
|
||||||
///
|
///
|
||||||
/// Extract matching rules as per element's ID, classes, tag name, etc..
|
/// Extract matching rules as per element's ID, classes, tag name, etc..
|
||||||
/// Sort the Rules at the end to maintain cascading order.
|
/// Sort the Rules at the end to maintain cascading order.
|
||||||
pub fn get_all_matching_rules<E, V>(&self,
|
pub fn get_all_matching_rules<E, V, F>(&self,
|
||||||
element: &E,
|
element: &E,
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
guard: &SharedRwLockReadGuard,
|
guard: &SharedRwLockReadGuard,
|
||||||
matching_rules_list: &mut V,
|
matching_rules_list: &mut V,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags,
|
flags_setter: &mut F,
|
||||||
cascade_level: CascadeLevel)
|
cascade_level: CascadeLevel)
|
||||||
where E: Element<Impl=SelectorImpl>,
|
where E: Element<Impl=SelectorImpl>,
|
||||||
V: VecLike<ApplicableDeclarationBlock>
|
V: VecLike<ApplicableDeclarationBlock>,
|
||||||
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
if self.empty {
|
if self.empty {
|
||||||
return
|
return
|
||||||
|
@ -937,7 +942,7 @@ impl SelectorMap {
|
||||||
guard,
|
guard,
|
||||||
matching_rules_list,
|
matching_rules_list,
|
||||||
relations,
|
relations,
|
||||||
flags,
|
flags_setter,
|
||||||
cascade_level)
|
cascade_level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,7 +954,7 @@ impl SelectorMap {
|
||||||
guard,
|
guard,
|
||||||
matching_rules_list,
|
matching_rules_list,
|
||||||
relations,
|
relations,
|
||||||
flags,
|
flags_setter,
|
||||||
cascade_level);
|
cascade_level);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -965,7 +970,7 @@ impl SelectorMap {
|
||||||
guard,
|
guard,
|
||||||
matching_rules_list,
|
matching_rules_list,
|
||||||
relations,
|
relations,
|
||||||
flags,
|
flags_setter,
|
||||||
cascade_level);
|
cascade_level);
|
||||||
|
|
||||||
SelectorMap::get_matching_rules(element,
|
SelectorMap::get_matching_rules(element,
|
||||||
|
@ -974,7 +979,7 @@ impl SelectorMap {
|
||||||
guard,
|
guard,
|
||||||
matching_rules_list,
|
matching_rules_list,
|
||||||
relations,
|
relations,
|
||||||
flags,
|
flags_setter,
|
||||||
cascade_level);
|
cascade_level);
|
||||||
|
|
||||||
// Sort only the rules we just added.
|
// Sort only the rules we just added.
|
||||||
|
@ -1027,7 +1032,7 @@ impl SelectorMap {
|
||||||
matching_rules_list
|
matching_rules_list
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_matching_rules_from_hash<E, Str, BorrowedStr: ?Sized, Vector>(
|
fn get_matching_rules_from_hash<E, Str, BorrowedStr: ?Sized, Vector, F>(
|
||||||
element: &E,
|
element: &E,
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
hash: &FnvHashMap<Str, Vec<Rule>>,
|
hash: &FnvHashMap<Str, Vec<Rule>>,
|
||||||
|
@ -1035,12 +1040,13 @@ impl SelectorMap {
|
||||||
guard: &SharedRwLockReadGuard,
|
guard: &SharedRwLockReadGuard,
|
||||||
matching_rules: &mut Vector,
|
matching_rules: &mut Vector,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags,
|
flags_setter: &mut F,
|
||||||
cascade_level: CascadeLevel)
|
cascade_level: CascadeLevel)
|
||||||
where E: Element<Impl=SelectorImpl>,
|
where E: Element<Impl=SelectorImpl>,
|
||||||
Str: Borrow<BorrowedStr> + Eq + Hash,
|
Str: Borrow<BorrowedStr> + Eq + Hash,
|
||||||
BorrowedStr: Eq + Hash,
|
BorrowedStr: Eq + Hash,
|
||||||
Vector: VecLike<ApplicableDeclarationBlock>
|
Vector: VecLike<ApplicableDeclarationBlock>,
|
||||||
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
if let Some(rules) = hash.get(key) {
|
if let Some(rules) = hash.get(key) {
|
||||||
SelectorMap::get_matching_rules(element,
|
SelectorMap::get_matching_rules(element,
|
||||||
|
@ -1049,22 +1055,23 @@ impl SelectorMap {
|
||||||
guard,
|
guard,
|
||||||
matching_rules,
|
matching_rules,
|
||||||
relations,
|
relations,
|
||||||
flags,
|
flags_setter,
|
||||||
cascade_level)
|
cascade_level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds rules in `rules` that match `element` to the `matching_rules` list.
|
/// Adds rules in `rules` that match `element` to the `matching_rules` list.
|
||||||
fn get_matching_rules<E, V>(element: &E,
|
fn get_matching_rules<E, V, F>(element: &E,
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
rules: &[Rule],
|
rules: &[Rule],
|
||||||
guard: &SharedRwLockReadGuard,
|
guard: &SharedRwLockReadGuard,
|
||||||
matching_rules: &mut V,
|
matching_rules: &mut V,
|
||||||
relations: &mut StyleRelations,
|
relations: &mut StyleRelations,
|
||||||
flags: &mut ElementSelectorFlags,
|
flags_setter: &mut F,
|
||||||
cascade_level: CascadeLevel)
|
cascade_level: CascadeLevel)
|
||||||
where E: Element<Impl=SelectorImpl>,
|
where E: Element<Impl=SelectorImpl>,
|
||||||
V: VecLike<ApplicableDeclarationBlock>
|
V: VecLike<ApplicableDeclarationBlock>,
|
||||||
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
for rule in rules.iter() {
|
for rule in rules.iter() {
|
||||||
let style_rule = rule.style_rule.read_with(guard);
|
let style_rule = rule.style_rule.read_with(guard);
|
||||||
|
@ -1076,7 +1083,7 @@ impl SelectorMap {
|
||||||
};
|
};
|
||||||
if any_declaration_for_importance &&
|
if any_declaration_for_importance &&
|
||||||
matches_complex_selector(&*rule.selector, element, parent_bf,
|
matches_complex_selector(&*rule.selector, element, parent_bf,
|
||||||
relations, flags) {
|
relations, flags_setter) {
|
||||||
matching_rules.push(
|
matching_rules.push(
|
||||||
rule.to_applicable_declaration_block(cascade_level));
|
rule.to_applicable_declaration_block(cascade_level));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue