Bug 265894 - Part 2. A cloned symbol element instance should not match rules of svg tag.
Gecko did not implement SymbolFrame for layouting and rendering a cloned symbol
element instance. Instead, we leverage SVGSVGElement and nsSVGInnerFrame to
render a symbol element. As a result, when we match rules for a svg element, we
need to tell whether this svg element is indeed an svg element, or it a bogus
one, used to represent a symbol one.
In this patch, we used SVGSVGElement::mCloneFromSymbol flag to tell whether an
SVG element is truely an SVG element.
MozReview-Commit-ID: Hx2dtWhVEEu
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -1341,16 +1341,20 @@ public:
// Callback for destructor of dataset to ensure to null out our weak pointer
// to it.
void ClearDataset();
void RegisterIntersectionObserver(DOMIntersectionObserver* aObserver);
void UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver);
bool UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t threshold);
+ virtual nsIAtom* GetTagNameAtom() const {
+ return mNodeInfo->NameAtom();
+ }
+
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/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -178,17 +178,18 @@ SVGSVGElement::SVGSVGElement(already_Add
mCurrentTranslate(0.0f, 0.0f),
mCurrentScale(1.0f),
mPreviousTranslate(0.0f, 0.0f),
mPreviousScale(1.0f),
mStartAnimationOnBindToTree(aFromParser == NOT_FROM_PARSER ||
aFromParser == FROM_PARSER_FRAGMENT ||
aFromParser == FROM_PARSER_XSLT),
mImageNeedsTransformInvalidation(false),
- mHasChildrenOnlyTransform(false)
+ mHasChildrenOnlyTransform(false),
+ mCloneFromSymbol(false)
{
}
//----------------------------------------------------------------------
// nsIDOMNode methods
// From NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGSVGElement)
nsresult
@@ -1234,13 +1235,15 @@ SVGSVGElement::CloneFromSymbol(Element*
// move the children over
uint32_t num = aSymbol->GetChildCount();
for (i = 0; i < num; i++) {
nsCOMPtr<nsIContent> child = aSymbol->GetFirstChild();
aSymbol->RemoveChildAt(0, false);
svgNode->InsertChildAt(child, i, true);
}
+ static_cast<SVGSVGElement*>(svgNode.get())->mCloneFromSymbol = true;
+
return svgNode.forget();
}
} // namespace dom
} // namespace mozilla
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -254,16 +254,21 @@ public:
void SetViewportSize(const svgFloatSize& aSize) {
mViewportWidth = aSize.width;
mViewportHeight = aSize.height;
}
static already_AddRefed<nsIContent> CloneFromSymbol(Element* aShadowHost,
nsIContent* aSymbol);
+
+ virtual nsIAtom* GetTagNameAtom() const {
+ return mCloneFromSymbol ? nsGkAtoms::symbol
+ : mNodeInfo->NameAtom();
+ }
// WebIDL
already_AddRefed<SVGAnimatedLength> X();
already_AddRefed<SVGAnimatedLength> Y();
already_AddRefed<SVGAnimatedLength> Width();
already_AddRefed<SVGAnimatedLength> Height();
float PixelUnitToMillimeterX();
float PixelUnitToMillimeterY();
float ScreenPixelToMillimeterX();
@@ -419,16 +424,21 @@ private:
// For outermost <svg> elements created from parsing, animation is started by
// the onload event in accordance with the SVG spec, but for <svg> elements
// created by script or promoted from inner <svg> to outermost <svg> we need
// to manually kick off animation when they are bound to the tree.
bool mStartAnimationOnBindToTree;
bool mImageNeedsTransformInvalidation;
bool mHasChildrenOnlyTransform;
+ // A flag to indicate this svg element is cloned from a symbol element and
+ // is used to represent a symbol element as a element instance inside an
+ // use-element shadow tree. We did this because the behavior of a cloned
+ // symbol is pretty much the same with an svg element.
+ bool mCloneFromSymbol;
};
} // namespace dom
class MOZ_RAII AutoPreserveAspectRatioOverride
{
public:
AutoPreserveAspectRatioOverride(const Maybe<SVGImageContext>& aSVGContext,
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -607,17 +607,17 @@ static inline
void ContentEnumFunc(const RuleValue &value, nsCSSSelector* selector,
ElementDependentRuleProcessorData* data, NodeMatchContext& nodeContext,
AncestorFilter *ancestorFilter);
void RuleHash::EnumerateAllRules(Element* aElement, ElementDependentRuleProcessorData* aData,
NodeMatchContext& aNodeContext)
{
int32_t nameSpace = aElement->GetNameSpaceID();
- nsIAtom* tag = aElement->NodeInfo()->NameAtom();
+ nsIAtom* tag = aElement->GetTagNameAtom();
nsIAtom* id = aElement->GetID();
const nsAttrValue* classList = aElement->GetClasses();
MOZ_ASSERT(tag, "How could we not have a tag?");
int32_t classCount = classList ? classList->GetAtomCount() : 0;
// assume 1 universal, tag, id, and namespace, rather than wasting
@@ -1871,17 +1871,17 @@ static bool SelectorMatches(Element* aEl
if ((kNameSpaceID_Unknown != aSelector->mNameSpace &&
aElement->GetNameSpaceID() != aSelector->mNameSpace))
return false;
if (aSelector->mLowercaseTag) {
nsIAtom* selectorTag =
(aTreeMatchContext.mIsHTMLDocument && aElement->IsHTMLElement()) ?
aSelector->mLowercaseTag : aSelector->mCasedTag;
- if (selectorTag != aElement->NodeInfo()->NameAtom()) {
+ if (selectorTag != aElement->GetTagNameAtom()) {
return false;
}
}
nsAtomList* IDList = aSelector->mIDList;
if (IDList) {
nsIAtom* id = aElement->GetID();
if (id) {