Bug 1245751 - Part 2: Allow href without xlink on SVG <use> elements. draft
authorBoris Chiou <boris.chiou@gmail.com>
Tue, 05 Jul 2016 16:37:17 +0800
changeset 400486 05b039842cad92acb7574f7187e1b0644bb7cde0
parent 400485 0f6e76e7b56ac30d30202f4d2ae518e26101a65b
child 400487 60bf9527bd22febe52cf8dbfca591a3eec417c67
push id26164
push userbmo:boris.chiou@gmail.com
push dateSun, 14 Aug 2016 10:23:43 +0000
bugs1245751
milestone51.0a1
Bug 1245751 - Part 2: Allow href without xlink on SVG <use> elements. MozReview-Commit-ID: 28op2ZoRm6X
dom/svg/SVGUseElement.cpp
dom/svg/SVGUseElement.h
layout/svg/nsSVGUseFrame.cpp
--- a/dom/svg/SVGUseElement.cpp
+++ b/dom/svg/SVGUseElement.cpp
@@ -33,18 +33,19 @@ SVGUseElement::WrapNode(JSContext *aCx, 
 nsSVGElement::LengthInfo SVGUseElement::sLengthInfo[4] =
 {
   { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
   { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
   { &nsGkAtoms::width, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
   { &nsGkAtoms::height, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
 };
 
-nsSVGElement::StringInfo SVGUseElement::sStringInfo[1] =
+nsSVGElement::StringInfo SVGUseElement::sStringInfo[2] =
 {
+  { &nsGkAtoms::href, kNameSpaceID_None, true },
   { &nsGkAtoms::href, kNameSpaceID_XLink, true }
 };
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(SVGUseElement)
 
@@ -104,17 +105,19 @@ SVGUseElement::Clone(mozilla::dom::NodeI
   }
 
   return NS_FAILED(rv1) ? rv1 : rv2;
 }
 
 already_AddRefed<SVGAnimatedString>
 SVGUseElement::Href()
 {
-  return mStringAttributes[HREF].ToDOMAnimatedString(this);
+  return mStringAttributes[HREF].IsExplicitlySet()
+         ? mStringAttributes[HREF].ToDOMAnimatedString(this)
+         : mStringAttributes[XLINK_HREF].ToDOMAnimatedString(this);
 }
 
 //----------------------------------------------------------------------
 
 already_AddRefed<SVGAnimatedLength>
 SVGUseElement::X()
 {
   return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this);
@@ -390,19 +393,25 @@ SVGUseElement::SyncWidthOrHeight(nsIAtom
     return;
   }
 }
 
 void
 SVGUseElement::LookupHref()
 {
   nsAutoString href;
-  mStringAttributes[HREF].GetAnimValue(href, this);
-  if (href.IsEmpty())
+  if (mStringAttributes[HREF].IsExplicitlySet()) {
+    mStringAttributes[HREF].GetAnimValue(href, this);
+  } else {
+    mStringAttributes[XLINK_HREF].GetAnimValue(href, this);
+  }
+
+  if (href.IsEmpty()) {
     return;
+  }
 
   nsCOMPtr<nsIURI> targetURI;
   nsCOMPtr<nsIURI> baseURI = mOriginal ? mOriginal->GetBaseURI() : GetBaseURI();
   nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
                                             GetComposedDoc(), baseURI);
 
   mSource.Reset(this, targetURI);
 }
--- a/dom/svg/SVGUseElement.h
+++ b/dom/svg/SVGUseElement.h
@@ -105,19 +105,19 @@ protected:
   void LookupHref();
   void TriggerReclone();
   void UnlinkSource();
 
   enum { ATTR_X, ATTR_Y, ATTR_WIDTH, ATTR_HEIGHT };
   nsSVGLength2 mLengthAttributes[4];
   static LengthInfo sLengthInfo[4];
 
-  enum { HREF };
-  nsSVGString mStringAttributes[1];
-  static StringInfo sStringInfo[1];
+  enum { HREF, XLINK_HREF };
+  nsSVGString mStringAttributes[2];
+  static StringInfo sStringInfo[2];
 
   nsCOMPtr<nsIContent> mOriginal; // if we've been cloned, our "real" copy
   nsCOMPtr<nsIContent> mClone;    // cloned tree
   SourceReference      mSource;   // observed element
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/layout/svg/nsSVGUseFrame.cpp
+++ b/layout/svg/nsSVGUseFrame.cpp
@@ -112,18 +112,17 @@ nsSVGUseFrame::Init(nsIContent*       aC
 nsresult
 nsSVGUseFrame::AttributeChanged(int32_t         aNameSpaceID,
                                 nsIAtom*        aAttribute,
                                 int32_t         aModType)
 {
   SVGUseElement *useElement = static_cast<SVGUseElement*>(mContent);
 
   if (aNameSpaceID == kNameSpaceID_None) {
-    if (aAttribute == nsGkAtoms::x ||
-        aAttribute == nsGkAtoms::y) {
+    if (aAttribute == nsGkAtoms::x || aAttribute == nsGkAtoms::y) {
       // make sure our cached transform matrix gets (lazily) updated
       mCanvasTM = nullptr;
       nsLayoutUtils::PostRestyleEvent(
         useElement, nsRestyleHint(0),
         nsChangeHint_InvalidateRenderingObservers);
       nsSVGUtils::ScheduleReflowSVG(this);
       nsSVGUtils::NotifyChildrenOfSVGChange(this, TRANSFORM_CHANGED);
     } else if (aAttribute == nsGkAtoms::width ||
@@ -139,18 +138,21 @@ nsSVGUseFrame::AttributeChanged(int32_t 
       }
       if (invalidate) {
         nsLayoutUtils::PostRestyleEvent(
           useElement, nsRestyleHint(0),
           nsChangeHint_InvalidateRenderingObservers);
         nsSVGUtils::ScheduleReflowSVG(this);
       }
     }
-  } else if (aNameSpaceID == kNameSpaceID_XLink &&
-             aAttribute == nsGkAtoms::href) {
+  }
+
+  if ((aNameSpaceID == kNameSpaceID_XLink ||
+       aNameSpaceID == kNameSpaceID_None) &&
+      aAttribute == nsGkAtoms::href) {
     // we're changing our nature, clear out the clone information
     nsLayoutUtils::PostRestyleEvent(
       useElement, nsRestyleHint(0),
       nsChangeHint_InvalidateRenderingObservers);
     nsSVGUtils::ScheduleReflowSVG(this);
     useElement->mOriginal = nullptr;
     useElement->UnlinkSource();
     useElement->TriggerReclone();