aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/invalidation/element/state_and_attributes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/style/invalidation/element/state_and_attributes.rs')
-rw-r--r--components/style/invalidation/element/state_and_attributes.rs112
1 files changed, 33 insertions, 79 deletions
diff --git a/components/style/invalidation/element/state_and_attributes.rs b/components/style/invalidation/element/state_and_attributes.rs
index 88b012a2524..1eb022b298a 100644
--- a/components/style/invalidation/element/state_and_attributes.rs
+++ b/components/style/invalidation/element/state_and_attributes.rs
@@ -24,12 +24,6 @@ use selectors::matching::matches_selector;
use smallvec::SmallVec;
use stylesheets::origin::{Origin, OriginSet};
-#[derive(Debug, PartialEq)]
-enum VisitedDependent {
- Yes,
- No,
-}
-
/// The collector implementation.
struct Collector<'a, 'b: 'a, 'selectors: 'a, E>
where
@@ -167,8 +161,13 @@ where
// do for this case.
if state_changes.intersects(ElementState::IN_VISITED_OR_UNVISITED_STATE) {
trace!(" > visitedness change, force subtree restyle");
+ // If we get here with visited links disabled, we should probably
+ // just avoid the restyle and remove the state change here, not only
+ // as an optimization, but also because it kind of would kill the
+ // point of disabling visited links.
+ debug_assert!(self.shared_context.visited_styles_enabled);
// We can't just return here because there may also be attribute
- // changes as well that imply additional hints.
+ // changes as well that imply additional hints for siblings.
self.data.hint.insert(RestyleHint::restyle_subtree());
}
@@ -347,7 +346,7 @@ where
if let Some(ref id) = removed_id {
if let Some(deps) = map.id_to_selector.get(id, quirks_mode) {
for dep in deps {
- self.scan_dependency(dep, VisitedDependent::No);
+ self.scan_dependency(dep);
}
}
}
@@ -356,7 +355,7 @@ where
if let Some(ref id) = added_id {
if let Some(deps) = map.id_to_selector.get(id, quirks_mode) {
for dep in deps {
- self.scan_dependency(dep, VisitedDependent::No);
+ self.scan_dependency(dep);
}
}
}
@@ -364,7 +363,7 @@ where
for class in self.classes_added.iter().chain(self.classes_removed.iter()) {
if let Some(deps) = map.class_to_selector.get(class, quirks_mode) {
for dep in deps {
- self.scan_dependency(dep, VisitedDependent::No);
+ self.scan_dependency(dep);
}
}
}
@@ -390,7 +389,7 @@ where
self.removed_id,
self.classes_removed,
|dependency| {
- self.scan_dependency(dependency, VisitedDependent::No);
+ self.scan_dependency(dependency);
true
},
);
@@ -410,98 +409,53 @@ where
if !dependency.state.intersects(state_changes) {
return true;
}
- let visited_dependent = if dependency
- .state
- .intersects(ElementState::IN_VISITED_OR_UNVISITED_STATE)
- {
- VisitedDependent::Yes
- } else {
- VisitedDependent::No
- };
- self.scan_dependency(&dependency.dep, visited_dependent);
+ self.scan_dependency(&dependency.dep);
true
},
);
}
- /// Check whether a dependency should be taken into account, using a given
- /// visited handling mode.
+ /// Check whether a dependency should be taken into account.
fn check_dependency(
&mut self,
- visited_handling_mode: VisitedHandlingMode,
dependency: &Dependency,
) -> bool {
let element = &self.element;
let wrapper = &self.wrapper;
- self.matching_context
- .with_visited_handling_mode(visited_handling_mode, |mut context| {
- let matches_now = matches_selector(
- &dependency.selector,
- dependency.selector_offset,
- None,
- element,
- &mut context,
- &mut |_, _| {},
- );
+ let matches_now = matches_selector(
+ &dependency.selector,
+ dependency.selector_offset,
+ None,
+ element,
+ &mut self.matching_context,
+ &mut |_, _| {},
+ );
- let matched_then = matches_selector(
- &dependency.selector,
- dependency.selector_offset,
- None,
- wrapper,
- &mut context,
- &mut |_, _| {},
- );
+ let matched_then = matches_selector(
+ &dependency.selector,
+ dependency.selector_offset,
+ None,
+ wrapper,
+ &mut self.matching_context,
+ &mut |_, _| {},
+ );
- matched_then != matches_now
- })
+ matched_then != matches_now
}
- fn scan_dependency(
- &mut self,
- dependency: &'selectors Dependency,
- is_visited_dependent: VisitedDependent,
- ) {
+ fn scan_dependency(&mut self, dependency: &'selectors Dependency) {
debug!(
- "TreeStyleInvalidator::scan_dependency({:?}, {:?}, {:?})",
- self.element, dependency, is_visited_dependent,
+ "TreeStyleInvalidator::scan_dependency({:?}, {:?})",
+ self.element, dependency
);
if !self.dependency_may_be_relevant(dependency) {
return;
}
- let should_account_for_dependency =
- self.check_dependency(VisitedHandlingMode::AllLinksVisitedAndUnvisited, dependency);
-
- if should_account_for_dependency {
+ if self.check_dependency(dependency) {
return self.note_dependency(dependency);
}
-
- // If there is a relevant link, then we also matched in visited
- // mode.
- //
- // Match again in this mode to ensure this also matches.
- //
- // Note that we never actually match directly against the element's true
- // visited state at all, since that would expose us to timing attacks.
- //
- // The matching process only considers the relevant link state and
- // visited handling mode when deciding if visited matches. Instead, we
- // are rematching here in case there is some :visited selector whose
- // matching result changed for some other state or attribute change of
- // this element (for example, for things like [foo]:visited).
- //
- // NOTE: This thing is actually untested because testing it is flaky,
- // see the tests that were added and then backed out in bug 1328509.
- if is_visited_dependent == VisitedDependent::Yes && self.element.is_link() {
- let should_account_for_dependency =
- self.check_dependency(VisitedHandlingMode::RelevantLinkVisited, dependency);
-
- if should_account_for_dependency {
- return self.note_dependency(dependency);
- }
- }
}
fn note_dependency(&mut self, dependency: &'selectors Dependency) {