From 9364cd21b82b370a6cc3c21e98f5de0b8832449a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 7 Mar 2018 15:01:03 +0100 Subject: [PATCH] style: Don't share style with an element that has a different proto binding than us. See the lengthy comment about why... XBL sucks. MozReview-Commit-ID: 8UgeJAVkj6a --- components/style/dom.rs | 3 +++ components/style/gecko/wrapper.rs | 12 ++++++++++-- components/style/sharing/mod.rs | 22 ++++++++++++++++++---- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/components/style/dom.rs b/components/style/dom.rs index cfd3c80e890..93c587257a6 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -739,6 +739,9 @@ pub trait TElement /// The shadow root which roots the subtree this element is contained in. fn containing_shadow(&self) -> Option<::ConcreteShadowRoot>; + /// XBL hack for style sharing. :( + fn has_same_xbl_proto_binding_as(&self, _other: Self) -> bool { true } + /// Return the element which we can use to look up rules in the selector /// maps. /// diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 321673d7c81..e774b1cfb33 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -1092,8 +1092,16 @@ impl<'le> TElement for GeckoElement<'le> { unsafe { slots._base.mContainingShadow.mRawPtr.as_ref().map(GeckoShadowRoot) } } - /// Execute `f` for each anonymous content child element (apart from - /// ::before and ::after) whose originating element is `self`. + fn has_same_xbl_proto_binding_as(&self, other: Self) -> bool { + match (self.xbl_binding(), other.xbl_binding()) { + (None, None) => true, + (Some(a), Some(b)) => { + a.0.mPrototypeBinding == b.0.mPrototypeBinding + } + _ => false, + } + } + fn each_anonymous_content_child(&self, mut f: F) where F: FnMut(Self), diff --git a/components/style/sharing/mod.rs b/components/style/sharing/mod.rs index 788ad3f5e3d..f0637742173 100644 --- a/components/style/sharing/mod.rs +++ b/components/style/sharing/mod.rs @@ -681,15 +681,29 @@ impl StyleSharingCache { // If two elements belong to different shadow trees, different rules may // apply to them, from the respective trees. - // - // Note that we don't need the same for XBL case, since two elements - // with different XBL bindings need to necessarily have different style - // (and thus children of them would never pass the parent check). if target.element.containing_shadow() != candidate.element.containing_shadow() { trace!("Miss: Different containing shadow roots"); return None; } + // Note that in theory we shouldn't need this XBL check. However, XBL is + // absolutely broken in all sorts of ways. + // + // A style change that changes which XBL binding applies to an element + // arrives there, with the element still having the old prototype + // binding attached. And thus we try to match revalidation selectors + // with the old XBL binding, because we can't look at the new ones of + // course. And that causes us to revalidate with the wrong selectors and + // hit assertions. + // + // Other than this, we don't need anything else like the containing XBL + // binding parent or what not, since two elements with different XBL + // bindings will necessarily end up with different style. + if !target.element.has_same_xbl_proto_binding_as(candidate.element) { + trace!("Miss: Different proto bindings"); + return None; + } + // If the elements are not assigned to the same slot they could match // different ::slotted() rules in the slot scope. //