Skip to content

Commit

Permalink
Rule replacement for visited rules
Browse files Browse the repository at this point in the history
Since visited rules are stored separately, we need also run `replace_rules` for
those in addition to regular rules.

MozReview-Commit-ID: 4KYhOBXm88O
  • Loading branch information
jryans committed May 24, 2017
1 parent a7882cf commit 2afaa4f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
5 changes: 5 additions & 0 deletions components/style/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
35 changes: 33 additions & 2 deletions components/style/matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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<Self>,
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<Self>,
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<Locked<PropertyDeclarationBlock>>>,
Expand Down

0 comments on commit 2afaa4f

Please sign in to comment.