style: Fix the broken invariants of the rule node cache.

We were spuriously reframing the <shadow> because it initially shared style with
the <br>, which ended up being display: none, while the <shadow> should've been
display: contents from the beginning.

lookup_by_rules seems pretty prone to obscure bugs, and also it's pretty
complex... Probably we should try to get rid of it, I'm unconvinced that it's
worth it.

Even with that, in a normal restyle the <details> wouldn't have ended up with a
style. It of course never had it before the reframe because the <shadow> was
display: none, but that doesn't mean it shouldn't have gotten one, since we
detected we needed to go through kids in:

  https://searchfox.org/mozilla-central/rev/6eea08365e7386a2b81c044e7cc8a3daa51d8754/servo/components/style/matching.rs#500

That code did happen, but since it's an animation-only restyle, we don't look at
unstyled stuff.

That looks somewhat fishy, but I guess for now it's fine as long as display
isn't animatable.

Bug: 1469076
Reviewed-by: heycam
MozReview-Commit-ID: B6NMSTNOKgK
This commit is contained in:
Emilio Cobos Álvarez 2018-06-16 02:50:28 -07:00
parent 8db8f95f1f
commit 3b90ddd5d1
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 23 additions and 2 deletions

View file

@ -815,7 +815,11 @@ impl<E: TElement> StyleSharingCache<E> {
Some(candidate.element.borrow_data().unwrap().share_styles())
}
/// Attempts to find an element in the cache with the given primary rule node and parent.
/// Attempts to find an element in the cache with the given primary rule
/// node and parent.
///
/// FIXME(emilio): re-measure this optimization, and remove if it's not very
/// useful... It's probably not worth the complexity / obscure bugs.
pub fn lookup_by_rules(
&mut self,
shared_context: &SharedStyleContext,
@ -841,7 +845,15 @@ impl<E: TElement> StyleSharingCache<E> {
if style.visited_rules() != visited_rules {
return None;
}
// NOTE(emilio): We only need to check name / namespace because we
// do name-dependent style adjustments, like the display: contents
// to display: none adjustment.
if target.namespace() != candidate.element.namespace() {
return None;
}
if target.local_name() != candidate.element.local_name() {
return None;
}
// Rule nodes and styles are computed independent of the element's
// actual visitedness, but at the end of the cascade (in
// `adjust_for_visited`) we do store the visitedness as a flag in
@ -853,6 +865,7 @@ impl<E: TElement> StyleSharingCache<E> {
// FIXME(jryans): This seems like it breaks the constant time
// requirements of visited, assuming we get a cache hit on only one
// of unvisited vs. visited.
// TODO(emilio): We no longer have such a flag, remove this check.
if target.is_visited_link() != candidate.element.is_visited_link() {
return None;
}