From 2afaa4fcba7391eb0a9dbd6127cb8bac3af38ecb Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Fri, 12 May 2017 12:04:15 -0500 Subject: [PATCH] Rule replacement for visited rules Since visited rules are stored separately, we need also run `replace_rules` for those in addition to regular rules. MozReview-Commit-ID: 4KYhOBXm88O --- components/style/data.rs | 5 +++++ components/style/matching.rs | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/components/style/data.rs b/components/style/data.rs index e2cd53abbd9..90ca649e461 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -85,6 +85,11 @@ impl ComputedStyle { self.visited_rules.as_ref() } + /// Gets a mutable reference to the visited rule node, if any. + pub fn get_visited_rules_mut(&mut self) -> Option<&mut StrongRuleNode> { + self.visited_rules.as_mut() + } + /// Gets a reference to the visited rule node. Panic if the element does not /// have visited rule node. pub fn visited_rules(&self) -> &StrongRuleNode { diff --git a/components/style/matching.rs b/components/style/matching.rs index 2baf91cf731..aa992fc3ce3 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -145,6 +145,14 @@ impl CascadeVisitedMode { } } + /// Returns a mutable rules node based on the cascade mode, if any. + fn get_rules_mut<'a>(&self, style: &'a mut ComputedStyle) -> Option<&'a mut StrongRuleNode> { + match *self { + CascadeVisitedMode::Unvisited => Some(&mut style.rules), + CascadeVisitedMode::Visited => style.get_visited_rules_mut(), + } + } + /// Returns the computed values based on the cascade mode. In visited mode, /// visited values are only returned if they already exist. If they don't, /// we fallback to the regular, unvisited styles. @@ -1186,17 +1194,40 @@ pub trait MatchMethods : TElement { } /// Updates the rule nodes without re-running selector matching, using just - /// the rule tree. Returns true if an !important rule was replaced. + /// the rule tree. + /// + /// Returns true if an !important rule was replaced. fn replace_rules(&self, replacements: RestyleReplacements, context: &StyleContext, data: &mut ElementData) -> bool { + let mut result = false; + result |= self.replace_rules_internal(replacements, context, data, + CascadeVisitedMode::Unvisited); + result |= self.replace_rules_internal(replacements, context, data, + CascadeVisitedMode::Visited); + result + } + + /// Updates the rule nodes without re-running selector matching, using just + /// the rule tree, for a specific visited mode. + /// + /// Returns true if an !important rule was replaced. + fn replace_rules_internal(&self, + replacements: RestyleReplacements, + context: &StyleContext, + data: &mut ElementData, + cascade_visited: CascadeVisitedMode) + -> bool { use properties::PropertyDeclarationBlock; use shared_lock::Locked; let element_styles = &mut data.styles_mut(); - let primary_rules = &mut element_styles.primary.rules; + let primary_rules = match cascade_visited.get_rules_mut(&mut element_styles.primary) { + Some(r) => r, + None => return false, + }; let replace_rule_node = |level: CascadeLevel, pdb: Option<&Arc>>,