Bug 265894 - Part 4. Selectors should not cross use-element shadow tree boundary.
MozReview-Commit-ID: DVYGUba6FD9
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -1345,16 +1345,26 @@ public:
void RegisterIntersectionObserver(DOMIntersectionObserver* aObserver);
void UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver);
bool UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t threshold);
virtual nsIAtom* GetTagNameAtom() const {
return mNodeInfo->NameAtom();
}
+ /*
+ * Mostly, this function is equal to GetParent, except for the root element
+ * of a use-element shadow tree.
+ *
+ * (Referes to nsSVGElement::GetParentInShadowTree)
+ */
+ virtual nsIContent* GetParentInsideUseElementShadowTree() const {
+ return GetParent();
+ }
+
protected:
/*
* Named-bools for use with SetAttrAndNotify to make call sites easier to
* read.
*/
static const bool kFireMutationEvent = true;
static const bool kDontFireMutationEvent = false;
static const bool kNotifyDocumentObservers = true;
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -1352,16 +1352,34 @@ nsSVGElement::UpdateContentDeclarationBl
}
const DeclarationBlock*
nsSVGElement::GetContentDeclarationBlock() const
{
return mContentDeclarationBlock;
}
+nsIContent* nsSVGElement::GetParentInsideUseElementShadowTree() const
+{
+ MOZ_ASSERT(IsAnonymousContentInSVGUseSubtree(),
+ "Used only if this element is inside of an use element tree.");
+
+ nsIContent* parent = GetParent();
+ if (!parent) {
+ return nullptr;
+ }
+
+ // Do not get parent cross the boundary of an use-element shadow tree .
+ Element* parentElement = parent->AsElement();
+ if (parentElement && parentElement->IsSVGElement(nsGkAtoms::use)) {
+ return nullptr;
+ }
+
+ return parent;
+}
/**
* Helper methods for the type-specific WillChangeXXX methods.
*
* This method sends out appropriate pre-change notifications so that selector
* restyles (e.g. due to changes that cause |elem[attr="val"]| to start/stop
* matching) work, and it returns an nsAttrValue that _may_ contain the
* attribute's pre-change value.
*
--- a/dom/svg/nsSVGElement.h
+++ b/dom/svg/nsSVGElement.h
@@ -330,16 +330,18 @@ public:
already_AddRefed<mozilla::dom::SVGAnimatedString> ClassName();
virtual bool IsSVGFocusable(bool* aIsFocusable, int32_t* aTabIndex);
virtual bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse) override;
void UpdateContentDeclarationBlock(mozilla::StyleBackendType aBackend);
const mozilla::DeclarationBlock* GetContentDeclarationBlock() const;
+ virtual nsIContent* GetParentInsideUseElementShadowTree() const override;
+
protected:
virtual JSObject* WrapNode(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
#ifdef DEBUG
// We define BeforeSetAttr here and mark it final to ensure it is NOT used
// by SVG elements.
// This is because we're not currently passing the correct value for aValue to
// BeforeSetAttr since it would involve allocating extra SVG value types.
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -2411,17 +2411,20 @@ SelectorMatchesTree(Element* aPrevElemen
parent->SetFlags(NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS);
element = prevElement->GetPreviousElementSibling();
}
}
// for descendant combinators and child combinators, the element
// to test against is the parent
else {
- nsIContent *content = prevElement->GetParent();
+ nsIContent *content =
+ prevElement->IsInAnonymousSubtree() && prevElement->IsAnonymousContentInSVGUseSubtree()
+ ? prevElement->GetParentInsideUseElementShadowTree()
+ : prevElement->GetParent();
// GetParent could return a document fragment; we only want
// element parents.
if (content && content->IsElement()) {
element = content->AsElement();
if (aTreeMatchContext.mForScopedStyle) {
// We are moving up to the parent element; tell the
// TreeMatchContext, so that in case this element is the
// style scope element, selector matching stops before we