Don't match native anonymous content to user/author rules.

This commit is contained in:
Cameron McCormack 2016-11-24 10:18:20 +08:00
parent 210b1be1d0
commit 22b62e0913
5 changed files with 83 additions and 60 deletions

View file

@ -28,6 +28,7 @@ use gecko_bindings::bindings::Gecko_StoreStyleDifference;
use gecko_bindings::structs; use gecko_bindings::structs;
use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO}; use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO};
use gecko_bindings::structs::{nsIAtom, nsIContent, nsStyleContext}; use gecko_bindings::structs::{nsIAtom, nsIContent, nsStyleContext};
use gecko_bindings::structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
use parking_lot::RwLock; use parking_lot::RwLock;
use parser::ParserContextExtraData; use parser::ParserContextExtraData;
use properties::{ComputedValues, parse_style_attribute}; use properties::{ComputedValues, parse_style_attribute};
@ -624,4 +625,9 @@ 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)
} }
#[inline]
fn matches_user_and_author_rules(&self) -> bool {
self.flags() & (NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE as u32) == 0
}
} }

View file

@ -106,6 +106,7 @@ pub enum CacheMiss {
LocalName, LocalName,
Namespace, Namespace,
Link, Link,
UserAndAuthorRules,
State, State,
IdAttr, IdAttr,
StyleAttr, StyleAttr,
@ -143,6 +144,10 @@ fn element_matches_candidate<E: TElement>(element: &E,
miss!(Link) miss!(Link)
} }
if element.matches_user_and_author_rules() != candidate_element.matches_user_and_author_rules() {
miss!(UserAndAuthorRules)
}
if element.get_state() != candidate_element.get_state() { if element.get_state() != candidate_element.get_state() {
miss!(State) miss!(State)
} }

View file

@ -101,6 +101,8 @@ impl PseudoElementCascadeType {
pub trait ElementExt: Element<Impl=SelectorImpl> { pub trait ElementExt: Element<Impl=SelectorImpl> {
fn is_link(&self) -> bool; fn is_link(&self) -> bool;
fn matches_user_and_author_rules(&self) -> bool;
} }
impl SelectorImpl { impl SelectorImpl {

View file

@ -398,4 +398,9 @@ impl<E: Element<Impl=SelectorImpl>> 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)
} }
#[inline]
fn matches_user_and_author_rules(&self) -> bool {
true
}
} }

View file

@ -330,9 +330,9 @@ impl Stylist {
pseudo: &PseudoElement, pseudo: &PseudoElement,
parent: &Arc<ComputedValues>) parent: &Arc<ComputedValues>)
-> Option<(Arc<ComputedValues>, StrongRuleNode)> -> Option<(Arc<ComputedValues>, StrongRuleNode)>
where E: Element<Impl=SelectorImpl> + where E: ElementExt +
fmt::Debug + fmt::Debug +
PresentationalHintsSynthetizer PresentationalHintsSynthetizer
{ {
debug_assert!(SelectorImpl::pseudo_element_cascade_type(pseudo).is_lazy()); debug_assert!(SelectorImpl::pseudo_element_cascade_type(pseudo).is_lazy());
if self.pseudos_map.get(pseudo).is_none() { if self.pseudos_map.get(pseudo).is_none() {
@ -418,7 +418,7 @@ impl Stylist {
pseudo_element: Option<&PseudoElement>, pseudo_element: Option<&PseudoElement>,
applicable_declarations: &mut V, applicable_declarations: &mut V,
reason: MatchingReason) -> StyleRelations reason: MatchingReason) -> StyleRelations
where E: Element<Impl=SelectorImpl> + where E: ElementExt +
fmt::Debug + fmt::Debug +
PresentationalHintsSynthetizer, PresentationalHintsSynthetizer,
V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock> V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock>
@ -456,66 +456,71 @@ impl Stylist {
} }
debug!("preshints: {:?}", relations); debug!("preshints: {:?}", relations);
// Step 3: User and author normal rules. if element.matches_user_and_author_rules() {
map.user.get_all_matching_rules(element, // Step 3: User and author normal rules.
parent_bf, map.user.get_all_matching_rules(element,
applicable_declarations, parent_bf,
&mut relations, applicable_declarations,
reason, &mut relations,
Importance::Normal); reason,
debug!("user normal: {:?}", relations); Importance::Normal);
map.author.get_all_matching_rules(element, debug!("user normal: {:?}", relations);
parent_bf, map.author.get_all_matching_rules(element,
applicable_declarations, parent_bf,
&mut relations, applicable_declarations,
reason, &mut relations,
Importance::Normal); reason,
debug!("author normal: {:?}", relations); Importance::Normal);
debug!("author normal: {:?}", relations);
// Step 4: Normal style attributes. // Step 4: Normal style attributes.
if let Some(sa) = style_attribute { if let Some(sa) = style_attribute {
if sa.read().any_normal() { if sa.read().any_normal() {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE; relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push( Push::push(
applicable_declarations, applicable_declarations,
ApplicableDeclarationBlock::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.get_all_matching_rules(element,
parent_bf,
applicable_declarations,
&mut relations,
reason,
Importance::Important);
debug!("author important: {:?}", relations);
// Step 6: `!important` style attributes.
if let Some(sa) = style_attribute {
if sa.read().any_important() {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push(
applicable_declarations,
ApplicableDeclarationBlock::from_declarations(sa.clone(), Importance::Important));
}
}
debug!("style attr important: {:?}", relations);
// Step 7: User `!important` rules.
map.user.get_all_matching_rules(element,
parent_bf,
applicable_declarations,
&mut relations,
reason,
Importance::Important);
debug!("user important: {:?}", relations);
} else {
debug!("skipping non-agent rules");
} }
debug!("style attr: {:?}", relations); // Step 8: UA `!important` rules.
// Step 5: Author-supplied `!important` rules.
map.author.get_all_matching_rules(element,
parent_bf,
applicable_declarations,
&mut relations,
reason,
Importance::Important);
debug!("author important: {:?}", relations);
// Step 6: `!important` style attributes.
if let Some(sa) = style_attribute {
if sa.read().any_important() {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push(
applicable_declarations,
ApplicableDeclarationBlock::from_declarations(sa.clone(), Importance::Important));
}
}
debug!("style attr important: {:?}", relations);
// Step 7: User and UA `!important` rules.
map.user.get_all_matching_rules(element,
parent_bf,
applicable_declarations,
&mut relations,
reason,
Importance::Important);
debug!("user important: {:?}", relations);
map.user_agent.get_all_matching_rules(element, map.user_agent.get_all_matching_rules(element,
parent_bf, parent_bf,
applicable_declarations, applicable_declarations,