Bug 471165. Make SVG animated class storage an nsAutoPtr<nsString> and make the DOM 'className' object a tear-off. r=longsonr,sr=roc
authorCraig Topper <craig.topper@gmail.com>
Mon, 05 Jan 2009 14:13:56 +1300
changeset 23312 e7e8b8ba64984cf329773a856ee305ecb7ab94a9
parent 23311 a5587354082aa8dd09ab5a6fd50a40c1d844ca3a
child 23313 1fb9d185d8f1aa81c566b8c04a937bd458e7b2eb
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslongsonr, roc
bugs471165
milestone1.9.2a1pre
Bug 471165. Make SVG animated class storage an nsAutoPtr<nsString> and make the DOM 'className' object a tear-off. r=longsonr,sr=roc
content/base/src/nsStyledElement.cpp
content/svg/content/src/Makefile.in
content/svg/content/src/nsSVGClassValue.cpp
content/svg/content/src/nsSVGClassValue.h
content/svg/content/src/nsSVGStylableElement.cpp
content/svg/content/src/nsSVGStylableElement.h
content/svg/content/test/test_valueLeaks.xhtml
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -84,20 +84,16 @@ nsStyledElement::ParseAttribute(PRInt32 
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::style) {
       SetFlags(NODE_MAY_HAVE_STYLE);
       ParseStyleAttribute(this, aValue, aResult, PR_FALSE);
       return PR_TRUE;
     }
     if (aAttribute == nsGkAtoms::_class) {
       SetFlags(NODE_MAY_HAVE_CLASS);
-#ifdef MOZ_SVG
-      NS_ASSERTION(!nsCOMPtr<nsIDOMSVGStylable>(do_QueryInterface(this)),
-                   "SVG code should have handled this 'class' attribute!");
-#endif
       aResult.ParseAtomArray(aValue);
       return PR_TRUE;
     }
   }
 
   return nsStyledElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                              aResult);
 }
--- a/content/svg/content/src/Makefile.in
+++ b/content/svg/content/src/Makefile.in
@@ -71,17 +71,16 @@ CPPSRCS		= \
 		nsSVGAngle.cpp \
 		nsSVGAnimatedLengthList.cpp \
 		nsSVGAnimatedNumberList.cpp \
 		nsSVGAnimatedRect.cpp \
 		nsSVGAnimatedPreserveAspectRatio.cpp \
 		nsSVGAnimatedTransformList.cpp \
 		nsSVGBoolean.cpp \
 		nsSVGCircleElement.cpp \
-		nsSVGClassValue.cpp \
 		nsSVGClipPathElement.cpp \
 		nsSVGDataParser.cpp \
 		nsSVGDefsElement.cpp \
 		nsSVGDescElement.cpp \
 		nsSVGElement.cpp \
 		nsSVGElementFactory.cpp \
 		nsSVGEllipseElement.cpp \
 		nsSVGEnum.cpp \
deleted file mode 100644
--- a/content/svg/content/src/nsSVGClassValue.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Mozilla SVG project.
- *
- * The Initial Developer of the Original Code is
- * Crocodile Clips Ltd..
- * Portions created by the Initial Developer are Copyright (C) 2003
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsSVGClassValue.h"
-#include "nsContentUtils.h"
-
-////////////////////////////////////////////////////////////////////////
-// nsSVGClassValue
-
-//----------------------------------------------------------------------
-// nsISupports methods:
-
-NS_IMPL_ADDREF(nsSVGClassValue)
-NS_IMPL_RELEASE(nsSVGClassValue)
-
-NS_INTERFACE_MAP_BEGIN(nsSVGClassValue)
-  NS_INTERFACE_MAP_ENTRY(nsISVGValue)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedString)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedString)
-NS_INTERFACE_MAP_END
-  
-//----------------------------------------------------------------------
-// nsISVGValue methods:
-
-NS_IMETHODIMP
-nsSVGClassValue::SetValueString(const nsAString& aValue)
-{
-  WillModify();
-  mBaseVal.ParseAtomArray(aValue);
-  DidModify();
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSVGClassValue::GetValueString(nsAString& aValue)
-{
-  mBaseVal.ToString(aValue);
-
-  return NS_OK;
-}
-
-//----------------------------------------------------------------------
-// nsIDOMSVGAnimatedString methods:
-
-/* attribute DOMString baseVal; */
-NS_IMETHODIMP
-nsSVGClassValue::GetBaseVal(nsAString & aBaseVal)
-{
-  mBaseVal.ToString(aBaseVal);
-
-  return NS_OK;
-}
-NS_IMETHODIMP
-nsSVGClassValue::SetBaseVal(const nsAString & aBaseVal)
-{
-  SetValueString(aBaseVal);
-
-  return NS_OK;
-}
-
-/* readonly attribute DOMString animVal; */
-NS_IMETHODIMP
-nsSVGClassValue::GetAnimVal(nsAString & aAnimVal)
-{
-  mBaseVal.ToString(aAnimVal);
-
-  return NS_OK;
-}
deleted file mode 100644
--- a/content/svg/content/src/nsSVGClassValue.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Mozilla SVG project.
- *
- * The Initial Developer of the Original Code is
- * Crocodile Clips Ltd..
- * Portions created by the Initial Developer are Copyright (C) 2003
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef __NS_SVGCLASSVALUE_H__
-#define __NS_SVGCLASSVALUE_H__
-
-#include "nsIDOMSVGAnimatedString.h"
-#include "nsSVGValue.h"
-#include "nsAttrValue.h"
-
-class nsSVGClassValue : public nsIDOMSVGAnimatedString,
-                        public nsSVGValue
-{
-public:
-  // nsISupports interface:
-  NS_DECL_ISUPPORTS
-
-  // nsIDOMSVGAnimatedString interface:
-  NS_DECL_NSIDOMSVGANIMATEDSTRING
-
-  // remainder of nsISVGValue interface:
-  NS_IMETHOD SetValueString(const nsAString& aValue);
-  NS_IMETHOD GetValueString(nsAString& aValue);
-
-  const nsAttrValue* GetAttrValue()
-  {
-    return &mBaseVal;
-  }
-
-protected:
-  nsAttrValue mBaseVal;
-};
-
-#endif //__NS_SVGCLASSVALUE_H__
--- a/content/svg/content/src/nsSVGStylableElement.cpp
+++ b/content/svg/content/src/nsSVGStylableElement.cpp
@@ -32,95 +32,149 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGStylableElement.h"
-#include "nsICSSOMFactory.h"
 #include "nsGkAtoms.h"
 #include "nsDOMCSSDeclaration.h"
-#include "nsIDOMClassInfo.h"
-
-static NS_DEFINE_CID(kCSSOMFactoryCID, NS_CSSOMFACTORY_CID);
+#include "nsContentUtils.h"
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGStylableElement::DOMAnimatedClassString, mSVGElement)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGStylableElement::DOMAnimatedClassString)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGStylableElement::DOMAnimatedClassString)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGStylableElement::DOMAnimatedClassString)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedString)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedString)
+NS_INTERFACE_MAP_END
+
 NS_IMPL_ADDREF_INHERITED(nsSVGStylableElement, nsSVGStylableElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGStylableElement, nsSVGStylableElementBase)
 
 NS_INTERFACE_MAP_BEGIN(nsSVGStylableElement)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGStylable)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGStylableElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGStylableElement::nsSVGStylableElement(nsINodeInfo *aNodeInfo)
   : nsSVGStylableElementBase(aNodeInfo)
 {
-  // We never know when we might have a class
-  SetFlags(NODE_MAY_HAVE_CLASS);
-}
-
-nsresult
-nsSVGStylableElement::Init()
-{
-  nsresult rv = nsSVGStylableElementBase::Init();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Create mapped properties:
-
-  // DOM property: className, #IMPLIED attrib: class
-  {
-    mClassName = new nsSVGClassValue;
-    NS_ENSURE_TRUE(mClassName, NS_ERROR_OUT_OF_MEMORY);
-    rv = AddMappedSVGValue(nsGkAtoms::_class,
-			   static_cast<nsIDOMSVGAnimatedString*>(mClassName),
-			   kNameSpaceID_None);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  return rv;
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 const nsAttrValue*
 nsSVGStylableElement::DoGetClasses() const
 {
-  return mClassName->GetAttrValue();
+  return GetClassAnimAttr();
 }
 
 //----------------------------------------------------------------------
 // nsIDOMSVGStylable methods
 
 /* readonly attribute nsIDOMSVGAnimatedString className; */
 NS_IMETHODIMP
 nsSVGStylableElement::GetClassName(nsIDOMSVGAnimatedString** aClassName)
 {
-  NS_ADDREF(*aClassName = mClassName);
+  *aClassName = new DOMAnimatedClassString(this);
+  NS_ENSURE_TRUE(*aClassName, NS_ERROR_OUT_OF_MEMORY);
 
+  NS_ADDREF(*aClassName);
   return NS_OK;
 }
 
 /* readonly attribute nsIDOMCSSStyleDeclaration style; */
 NS_IMETHODIMP
 nsSVGStylableElement::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
 {
   return nsSVGStylableElementBase::GetStyle(aStyle);
 }
 
 /* nsIDOMCSSValue getPresentationAttribute (in DOMString name); */
 NS_IMETHODIMP
 nsSVGStylableElement::GetPresentationAttribute(const nsAString& aName,
-						nsIDOMCSSValue** aReturn)
+                                               nsIDOMCSSValue** aReturn)
 {
   // Let's not implement this just yet. The CSSValue interface has been
   // deprecated by the CSS WG.
   // http://lists.w3.org/Archives/Public/www-style/2003Oct/0347.html
 
   return NS_ERROR_NOT_IMPLEMENTED;
 }
+
+//----------------------------------------------------------------------
+// nsSVGElement methods
+
+PRBool
+nsSVGStylableElement::ParseAttribute(PRInt32 aNamespaceID,
+                                     nsIAtom* aAttribute,
+                                     const nsAString& aValue,
+                                     nsAttrValue& aResult)
+{
+  if (aNamespaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::_class) {
+    mClassAnimAttr = nsnull;
+    // let the rest be handled in nsStyledElement
+  }
+
+  return nsSVGStylableElementBase::ParseAttribute(aNamespaceID, aAttribute,
+                                                   aValue, aResult);
+}
+
+nsresult
+nsSVGStylableElement::UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
+                                PRBool aNotify)
+{
+  if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::_class) {
+    mClassAnimAttr = nsnull;
+  }
+
+  return nsSVGStylableElementBase::UnsetAttr(aNamespaceID, aName, aNotify);
+}
+
+//----------------------------------------------------------------------
+// Methods for managing the class attribute
+
+const nsAttrValue*
+nsSVGStylableElement::GetClassAnimAttr() const
+{
+  if (mClassAnimAttr)
+    return mClassAnimAttr;
+
+  return mAttrsAndChildren.GetAttr(nsGkAtoms::_class, kNameSpaceID_None);
+}
+
+void
+nsSVGStylableElement::GetClassBaseValString(nsAString& aResult) const
+{
+  GetAttr(kNameSpaceID_None, nsGkAtoms::_class, aResult);
+}
+
+void
+nsSVGStylableElement::SetClassBaseValString(const nsAString& aValue)
+{
+  mClassAnimAttr = nsnull;
+  SetAttr(kNameSpaceID_None, nsGkAtoms::_class, aValue, PR_TRUE); 
+}
+
+void
+nsSVGStylableElement::GetClassAnimValString(nsAString& aResult) const
+{
+  const nsAttrValue* attr = GetClassAnimAttr();
+
+  if (!attr) {
+    aResult.Truncate();
+    return;
+  }
+
+  attr->ToString(aResult);
+}
--- a/content/svg/content/src/nsSVGStylableElement.h
+++ b/content/svg/content/src/nsSVGStylableElement.h
@@ -38,33 +38,66 @@
 
 #ifndef __NS_SVGSTYLABLEELEMENT_H__
 #define __NS_SVGSTYLABLEELEMENT_H__
 
 #include "nsSVGElement.h"
 #include "nsIDOMSVGStylable.h"
 #include "nsIDOMSVGAnimatedString.h"
 #include "nsAutoPtr.h"
-#include "nsSVGClassValue.h"
 
 typedef nsSVGElement nsSVGStylableElementBase;
 
 class nsSVGStylableElement : public nsSVGStylableElementBase,
                              public nsIDOMSVGStylable
 {
 protected:
   nsSVGStylableElement(nsINodeInfo *aNodeInfo);
-  nsresult Init();
 
 public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGSTYLABLE
 
   // nsIContent
   virtual const nsAttrValue* DoGetClasses() const;
 
+  // nsSVGElement
+  virtual nsresult UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aAttribute,
+                             PRBool aNotify);
+
 protected:
-  nsRefPtr<nsSVGClassValue> mClassName;
+
+  // nsSVGElement
+  virtual PRBool ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aName,
+                                const nsAString& aValue,
+                                nsAttrValue& aResult);
+
+private:
+  nsAutoPtr<nsAttrValue> mClassAnimAttr;
+
+  const nsAttrValue* GetClassAnimAttr() const;
+ 
+  void GetClassBaseValString(nsAString &aResult) const;
+  void SetClassBaseValString(const nsAString& aValue);
+  void GetClassAnimValString(nsAString& aResult) const;
+
+  struct DOMAnimatedClassString : public nsIDOMSVGAnimatedString
+  {
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedClassString)
+
+    DOMAnimatedClassString(nsSVGStylableElement *aSVGElement)
+      : mSVGElement(aSVGElement) {}
+
+    nsRefPtr<nsSVGStylableElement> mSVGElement;
+
+    NS_IMETHOD GetBaseVal(nsAString& aResult)
+      { mSVGElement->GetClassBaseValString(aResult); return NS_OK; }
+    NS_IMETHOD SetBaseVal(const nsAString& aValue)
+      { mSVGElement->SetClassBaseValString(aValue); return NS_OK; }
+    NS_IMETHOD GetAnimVal(nsAString& aResult)
+      { mSVGElement->GetClassAnimValString(aResult); return NS_OK; }
+  };
 };
 
 
 #endif // __NS_SVGSTYLABLEELEMENT_H__
--- a/content/svg/content/test/test_valueLeaks.xhtml
+++ b/content/svg/content/test/test_valueLeaks.xhtml
@@ -23,25 +23,35 @@ https://bugzilla.mozilla.org/show_bug.cg
 function storeSVGPropertyAsExpando(localName, prop)
 {
     var elem = document.createElementNS("http://www.w3.org/2000/svg", localName);
 
     elem.addEventListener("click", function(){}, false);
 
     var propVal = elem[prop];
     Object.prototype.toSource[prop + "_expando"] = propVal;
-    if (propVal instanceof SVGAnimatedAngle || propVal instanceof SVGAnimatedLength) {
+    if (propVal instanceof SVGAnimatedAngle || propVal instanceof SVGAnimatedLength ||
+        propVal instanceof SVGAnimatedRect || propVal instanceof SVGAnimatedPreserveAspectRatio) {
         Object.prototype.toSource[prop + "_baseVal_expando"] = propVal.baseVal;
         Object.prototype.toSource[prop + "_animVal_expando"] = propVal.animVal;
     }
 }
 
+// class
+storeSVGPropertyAsExpando("marker", "class");
+
 // angle
 storeSVGPropertyAsExpando("marker", "orientAngle");
 
+// viewBox
+storeSVGPropertyAsExpando("marker", "viewBox");
+
+// preserveAspectRatio
+storeSVGPropertyAsExpando("marker", "preserveAspectRatio");
+
 // boolean
 storeSVGPropertyAsExpando("feConvolveMatrix", "preserveAlpha");
 
 // enum
 storeSVGPropertyAsExpando("feConvolveMatrix", "edgeMode");
 
 // special marker enum
 storeSVGPropertyAsExpando("marker", "orientType");