Fix for bug 467671 (Leak 6 nsGlobalWindows due to DOMAnimatedLength not participating in cycle collection).
authorPeter Van der Beken <peterv@propagandism.org>
Tue, 30 Dec 2008 17:32:22 +0100
changeset 23193 9b0d41d19445ee2edba23b7f045d48dd827e3f5d
parent 23192 101fb71a7066705bd9c3217695680742d6949d6a
child 23194 77084056e89a9213a2567c125d94abd06d90638d
push id4383
push userpvanderbeken@mozilla.com
push dateTue, 30 Dec 2008 16:32:36 +0000
treeherdermozilla-central@9b0d41d19445 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs467671
milestone1.9.2a1pre
Fix for bug 467671 (Leak 6 nsGlobalWindows due to DOMAnimatedLength not participating in cycle collection).
content/svg/content/src/nsSVGAngle.cpp
content/svg/content/src/nsSVGAngle.h
content/svg/content/src/nsSVGBoolean.cpp
content/svg/content/src/nsSVGBoolean.h
content/svg/content/src/nsSVGElement.h
content/svg/content/src/nsSVGEnum.cpp
content/svg/content/src/nsSVGEnum.h
content/svg/content/src/nsSVGInteger.cpp
content/svg/content/src/nsSVGInteger.h
content/svg/content/src/nsSVGLength2.cpp
content/svg/content/src/nsSVGLength2.h
content/svg/content/src/nsSVGMarkerElement.cpp
content/svg/content/src/nsSVGMarkerElement.h
content/svg/content/src/nsSVGNumber2.cpp
content/svg/content/src/nsSVGNumber2.h
content/svg/content/src/nsSVGString.cpp
content/svg/content/src/nsSVGString.h
content/svg/content/src/nsSVGSwitchElement.cpp
content/svg/content/src/nsSVGSwitchElement.h
content/svg/content/test/Makefile.in
content/svg/content/test/test_valueLeaks.xhtml
--- a/content/svg/content/src/nsSVGAngle.cpp
+++ b/content/svg/content/src/nsSVGAngle.cpp
@@ -83,41 +83,47 @@ public:
 
   NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
     { mVal.ConvertToSpecifiedUnits(unitType, nsnull); return NS_OK; }
 
 private:
   nsSVGAngle mVal;
 };
 
-NS_IMPL_ADDREF(nsSVGAngle::DOMBaseVal)
-NS_IMPL_RELEASE(nsSVGAngle::DOMBaseVal)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGAngle::DOMBaseVal, mSVGElement)
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGAngle::DOMAnimVal, mSVGElement)
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGAngle::DOMAnimatedAngle, mSVGElement)
 
-NS_IMPL_ADDREF(nsSVGAngle::DOMAnimVal)
-NS_IMPL_RELEASE(nsSVGAngle::DOMAnimVal)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGAngle::DOMBaseVal)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGAngle::DOMBaseVal)
 
-NS_IMPL_ADDREF(nsSVGAngle::DOMAnimatedAngle)
-NS_IMPL_RELEASE(nsSVGAngle::DOMAnimatedAngle)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGAngle::DOMAnimVal)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGAngle::DOMAnimVal)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGAngle::DOMAnimatedAngle)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGAngle::DOMAnimatedAngle)
 
 NS_IMPL_ADDREF(DOMSVGAngle)
 NS_IMPL_RELEASE(DOMSVGAngle)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGAngle::DOMBaseVal)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGAngle::DOMBaseVal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAngle)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAngle)
 NS_INTERFACE_MAP_END
 
-NS_INTERFACE_MAP_BEGIN(nsSVGAngle::DOMAnimVal)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGAngle::DOMAnimVal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAngle)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAngle)
 NS_INTERFACE_MAP_END
 
-NS_INTERFACE_MAP_BEGIN(nsSVGAngle::DOMAnimatedAngle)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGAngle::DOMAnimatedAngle)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedAngle)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedAngle)
 NS_INTERFACE_MAP_END
 
 NS_INTERFACE_MAP_BEGIN(DOMSVGAngle)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAngle)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
--- a/content/svg/content/src/nsSVGAngle.h
+++ b/content/svg/content/src/nsSVGAngle.h
@@ -88,17 +88,18 @@ private:
   void NewValueSpecifiedUnits(PRUint16 aUnitType, float aValue,
                               nsSVGElement *aSVGElement);
   void ConvertToSpecifiedUnits(PRUint16 aUnitType, nsSVGElement *aSVGElement);
   nsresult ToDOMBaseVal(nsIDOMSVGAngle **aResult, nsSVGElement* aSVGElement);
   nsresult ToDOMAnimVal(nsIDOMSVGAngle **aResult, nsSVGElement* aSVGElement);
 
   struct DOMBaseVal : public nsIDOMSVGAngle
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMBaseVal)
 
     DOMBaseVal(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGAngle* mVal; // kept alive because it belongs to mSVGElement
     nsRefPtr<nsSVGElement> mSVGElement;
     
     NS_IMETHOD GetUnitType(PRUint16* aResult)
@@ -127,17 +128,18 @@ private:
         return NS_OK; }
 
     NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
       { mVal->ConvertToSpecifiedUnits(unitType, mSVGElement); return NS_OK; }
   };
 
   struct DOMAnimVal : public nsIDOMSVGAngle
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimVal)
 
     DOMAnimVal(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGAngle* mVal; // kept alive because it belongs to mSVGElement
     nsRefPtr<nsSVGElement> mSVGElement;
     
     NS_IMETHOD GetUnitType(PRUint16* aResult)
@@ -163,17 +165,18 @@ private:
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
 
     NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
   };
 
   struct DOMAnimatedAngle : public nsIDOMSVGAnimatedAngle
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedAngle)
 
     DOMAnimatedAngle(nsSVGAngle* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGAngle* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(nsIDOMSVGAngle **aBaseVal)
--- a/content/svg/content/src/nsSVGBoolean.cpp
+++ b/content/svg/content/src/nsSVGBoolean.cpp
@@ -31,20 +31,22 @@
  * 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 "nsSVGBoolean.h"
 
-NS_IMPL_ADDREF(nsSVGBoolean::DOMAnimatedBoolean)
-NS_IMPL_RELEASE(nsSVGBoolean::DOMAnimatedBoolean)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGBoolean::DOMAnimatedBoolean, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGBoolean::DOMAnimatedBoolean)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGBoolean::DOMAnimatedBoolean)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGBoolean::DOMAnimatedBoolean)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGBoolean::DOMAnimatedBoolean)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedBoolean)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedBoolean)
 NS_INTERFACE_MAP_END
 
 /* Implementation */
 
 nsresult
@@ -89,9 +91,8 @@ nsSVGBoolean::ToDOMAnimatedBoolean(nsIDO
 {
   *aResult = new DOMAnimatedBoolean(this, aSVGElement);
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aResult);
   return NS_OK;
 }
-
--- a/content/svg/content/src/nsSVGBoolean.h
+++ b/content/svg/content/src/nsSVGBoolean.h
@@ -67,17 +67,18 @@ public:
 private:
 
   PRPackedBool mAnimVal;
   PRPackedBool mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   struct DOMAnimatedBoolean : public nsIDOMSVGAnimatedBoolean
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedBoolean)
 
     DOMAnimatedBoolean(nsSVGBoolean* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGBoolean* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(PRBool* aResult)
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -358,9 +358,19 @@ NS_NewSVG##_elementName##Element(nsICont
     return rv;                                                               \
   }                                                                          \
                                                                              \
   *aResult = it;                                                             \
                                                                              \
   return rv;                                                                 \
 }
 
+// No unlinking, we'd need to null out the value pointer (the object it
+// points to is held by the element) and null-check it everywhere.
+#define NS_SVG_VAL_IMPL_CYCLE_COLLECTION(_val, _element)                     \
+NS_IMPL_CYCLE_COLLECTION_CLASS(_val)                                         \
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_val)                                \
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(_element, nsIContent) \
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END                                        \
+NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_val)
+
+
 #endif // __NS_SVGELEMENT_H__
--- a/content/svg/content/src/nsSVGEnum.cpp
+++ b/content/svg/content/src/nsSVGEnum.cpp
@@ -33,20 +33,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGEnum.h"
 #include "nsIAtom.h"
 #include "nsSVGElement.h"
 
-NS_IMPL_ADDREF(nsSVGEnum::DOMAnimatedEnum)
-NS_IMPL_RELEASE(nsSVGEnum::DOMAnimatedEnum)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGEnum::DOMAnimatedEnum, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGEnum::DOMAnimatedEnum)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGEnum::DOMAnimatedEnum)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGEnum::DOMAnimatedEnum)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGEnum::DOMAnimatedEnum)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedEnumeration)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedEnumeration)
 NS_INTERFACE_MAP_END
 
 nsSVGEnumMapping *
 nsSVGEnum::GetMapping(nsSVGElement *aSVGElement)
 {
--- a/content/svg/content/src/nsSVGEnum.h
+++ b/content/svg/content/src/nsSVGEnum.h
@@ -78,17 +78,18 @@ private:
   nsSVGEnumValue mAnimVal;
   nsSVGEnumValue mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   nsSVGEnumMapping *GetMapping(nsSVGElement *aSVGElement);
 
   struct DOMAnimatedEnum : public nsIDOMSVGAnimatedEnumeration
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedEnum)
 
     DOMAnimatedEnum(nsSVGEnum* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGEnum *mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(PRUint16* aResult)
--- a/content/svg/content/src/nsSVGInteger.cpp
+++ b/content/svg/content/src/nsSVGInteger.cpp
@@ -31,20 +31,23 @@
  * 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 "nsSVGInteger.h"
 
-NS_IMPL_ADDREF(nsSVGInteger::DOMAnimatedInteger)
-NS_IMPL_RELEASE(nsSVGInteger::DOMAnimatedInteger)
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGInteger::DOMAnimatedInteger, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGInteger::DOMAnimatedInteger)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGInteger::DOMAnimatedInteger)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGInteger::DOMAnimatedInteger)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGInteger::DOMAnimatedInteger)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedInteger)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedInteger)
 NS_INTERFACE_MAP_END
 
 /* Implementation */
 
 nsresult
@@ -91,9 +94,8 @@ nsSVGInteger::ToDOMAnimatedInteger(nsIDO
 {
   *aResult = new DOMAnimatedInteger(this, aSVGElement);
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aResult);
   return NS_OK;
 }
-
--- a/content/svg/content/src/nsSVGInteger.h
+++ b/content/svg/content/src/nsSVGInteger.h
@@ -67,17 +67,18 @@ public:
 private:
 
   PRInt32 mAnimVal;
   PRInt32 mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   struct DOMAnimatedInteger : public nsIDOMSVGAnimatedInteger
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedInteger)
 
     DOMAnimatedInteger(nsSVGInteger* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGInteger* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(PRInt32* aResult)
--- a/content/svg/content/src/nsSVGLength2.cpp
+++ b/content/svg/content/src/nsSVGLength2.cpp
@@ -38,38 +38,44 @@
 
 #include "nsSVGLength2.h"
 #include "prdtoa.h"
 #include "nsTextFormatter.h"
 #include "nsSVGSVGElement.h"
 #include "nsIFrame.h"
 #include "nsSVGIntegrationUtils.h"
 
-NS_IMPL_ADDREF(nsSVGLength2::DOMBaseVal)
-NS_IMPL_RELEASE(nsSVGLength2::DOMBaseVal)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMBaseVal, mSVGElement)
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMAnimVal, mSVGElement)
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMAnimatedLength, mSVGElement)
 
-NS_IMPL_ADDREF(nsSVGLength2::DOMAnimVal)
-NS_IMPL_RELEASE(nsSVGLength2::DOMAnimVal)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGLength2::DOMBaseVal)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMBaseVal)
 
-NS_IMPL_ADDREF(nsSVGLength2::DOMAnimatedLength)
-NS_IMPL_RELEASE(nsSVGLength2::DOMAnimatedLength)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGLength2::DOMAnimVal)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMAnimVal)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGLength2::DOMBaseVal)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGLength2::DOMAnimatedLength)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMAnimatedLength)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGLength2::DOMBaseVal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLength)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGLength)
 NS_INTERFACE_MAP_END
 
-NS_INTERFACE_MAP_BEGIN(nsSVGLength2::DOMAnimVal)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGLength2::DOMAnimVal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLength)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGLength)
 NS_INTERFACE_MAP_END
 
-NS_INTERFACE_MAP_BEGIN(nsSVGLength2::DOMAnimatedLength)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGLength2::DOMAnimatedLength)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedLength)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedLength)
 NS_INTERFACE_MAP_END
 
 static nsIAtom** const unitMap[] =
 {
   nsnull, /* SVG_LENGTHTYPE_UNKNOWN */
--- a/content/svg/content/src/nsSVGLength2.h
+++ b/content/svg/content/src/nsSVGLength2.h
@@ -118,17 +118,18 @@ private:
   void NewValueSpecifiedUnits(PRUint16 aUnitType, float aValue,
                               nsSVGElement *aSVGElement);
   void ConvertToSpecifiedUnits(PRUint16 aUnitType, nsSVGElement *aSVGElement);
   nsresult ToDOMBaseVal(nsIDOMSVGLength **aResult, nsSVGElement* aSVGElement);
   nsresult ToDOMAnimVal(nsIDOMSVGLength **aResult, nsSVGElement* aSVGElement);
 
   struct DOMBaseVal : public nsIDOMSVGLength
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMBaseVal)
 
     DOMBaseVal(nsSVGLength2* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGLength2* mVal; // kept alive because it belongs to mSVGElement
     nsRefPtr<nsSVGElement> mSVGElement;
     
     NS_IMETHOD GetUnitType(PRUint16* aResult)
@@ -157,17 +158,18 @@ private:
         return NS_OK; }
 
     NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
       { mVal->ConvertToSpecifiedUnits(unitType, mSVGElement); return NS_OK; }
   };
 
   struct DOMAnimVal : public nsIDOMSVGLength
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimVal)
 
     DOMAnimVal(nsSVGLength2* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGLength2* mVal; // kept alive because it belongs to mSVGElement
     nsRefPtr<nsSVGElement> mSVGElement;
     
     NS_IMETHOD GetUnitType(PRUint16* aResult)
@@ -193,17 +195,18 @@ private:
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
 
     NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType)
       { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; }
   };
 
   struct DOMAnimatedLength : public nsIDOMSVGAnimatedLength
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedLength)
 
     DOMAnimatedLength(nsSVGLength2* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
     
     nsSVGLength2* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(nsIDOMSVGLength **aBaseVal)
--- a/content/svg/content/src/nsSVGMarkerElement.cpp
+++ b/content/svg/content/src/nsSVGMarkerElement.cpp
@@ -73,20 +73,22 @@ nsSVGElement::AngleInfo nsSVGMarkerEleme
   { &nsGkAtoms::orient, 0, nsIDOMSVGAngle::SVG_ANGLETYPE_UNSPECIFIED }
 };
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Marker)
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
-NS_IMPL_ADDREF(nsSVGOrientType::DOMAnimatedEnum)
-NS_IMPL_RELEASE(nsSVGOrientType::DOMAnimatedEnum)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGOrientType::DOMAnimatedEnum, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGOrientType::DOMAnimatedEnum)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGOrientType::DOMAnimatedEnum)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGOrientType::DOMAnimatedEnum)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGOrientType::DOMAnimatedEnum)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedEnumeration)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedEnumeration)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGMarkerElement,nsSVGMarkerElementBase)
 
--- a/content/svg/content/src/nsSVGMarkerElement.h
+++ b/content/svg/content/src/nsSVGMarkerElement.h
@@ -66,17 +66,18 @@ public:
                              nsSVGElement* aSVGElement);
 
 private:
   nsSVGEnumValue mAnimVal;
   nsSVGEnumValue mBaseVal;
 
   struct DOMAnimatedEnum : public nsIDOMSVGAnimatedEnumeration
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedEnum)
 
     DOMAnimatedEnum(nsSVGOrientType* aVal,
                     nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGOrientType *mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
--- a/content/svg/content/src/nsSVGNumber2.cpp
+++ b/content/svg/content/src/nsSVGNumber2.cpp
@@ -33,20 +33,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGNumber2.h"
 #include "nsTextFormatter.h"
 #include "prdtoa.h"
 
-NS_IMPL_ADDREF(nsSVGNumber2::DOMAnimatedNumber)
-NS_IMPL_RELEASE(nsSVGNumber2::DOMAnimatedNumber)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGNumber2::DOMAnimatedNumber, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGNumber2::DOMAnimatedNumber)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGNumber2::DOMAnimatedNumber)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGNumber2::DOMAnimatedNumber)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGNumber2::DOMAnimatedNumber)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedNumber)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedNumber)
 NS_INTERFACE_MAP_END
 
 /* Implementation */
 
 nsresult
--- a/content/svg/content/src/nsSVGNumber2.h
+++ b/content/svg/content/src/nsSVGNumber2.h
@@ -68,17 +68,18 @@ public:
 private:
 
   float mAnimVal;
   float mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   struct DOMAnimatedNumber : public nsIDOMSVGAnimatedNumber
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedNumber)
 
     DOMAnimatedNumber(nsSVGNumber2* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGNumber2* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(float* aResult)
--- a/content/svg/content/src/nsSVGString.cpp
+++ b/content/svg/content/src/nsSVGString.cpp
@@ -31,20 +31,22 @@
  * 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 "nsSVGString.h"
 
-NS_IMPL_ADDREF(nsSVGString::DOMAnimatedString)
-NS_IMPL_RELEASE(nsSVGString::DOMAnimatedString)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGString::DOMAnimatedString, mSVGElement)
 
-NS_INTERFACE_MAP_BEGIN(nsSVGString::DOMAnimatedString)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGString::DOMAnimatedString)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGString::DOMAnimatedString)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGString::DOMAnimatedString)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedString)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedString)
 NS_INTERFACE_MAP_END
 
 /* Implementation */
 
 void
--- a/content/svg/content/src/nsSVGString.h
+++ b/content/svg/content/src/nsSVGString.h
@@ -65,17 +65,18 @@ public:
 private:
 
   nsString mAnimVal;
   nsString mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   struct DOMAnimatedString : public nsIDOMSVGAnimatedString
   {
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedString)
 
     DOMAnimatedString(nsSVGString* aVal, nsSVGElement *aSVGElement)
       : mVal(aVal), mSVGElement(aSVGElement) {}
 
     nsSVGString* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(nsAString & aResult)
--- a/content/svg/content/src/nsSVGSwitchElement.cpp
+++ b/content/svg/content/src/nsSVGSwitchElement.cpp
@@ -47,20 +47,30 @@ NS_SVG_PassesConditionalProcessingTests(
 
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Switch)
 
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsSVGSwitchElement)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsSVGSwitchElement,
+                                                  nsSVGSwitchElementBase)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mActiveChild)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsSVGSwitchElement,
+                                                nsSVGSwitchElementBase)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mActiveChild)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
 NS_IMPL_ADDREF_INHERITED(nsSVGSwitchElement,nsSVGSwitchElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGSwitchElement,nsSVGSwitchElementBase)
 
-NS_INTERFACE_TABLE_HEAD(nsSVGSwitchElement)
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsSVGSwitchElement)
   NS_NODE_INTERFACE_TABLE4(nsSVGSwitchElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement, nsIDOMSVGSwitchElement)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGSwitchElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGSwitchElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
--- a/content/svg/content/src/nsSVGSwitchElement.h
+++ b/content/svg/content/src/nsSVGSwitchElement.h
@@ -53,16 +53,18 @@ protected:
 public:
   nsIContent * GetActiveChild()
   { return mActiveChild; }
   void MaybeInvalidate();
     
   // interfaces:
 
   NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsSVGSwitchElement,
+                                           nsSVGSwitchElementBase)
   NS_DECL_NSIDOMSVGSWITCHELEMENT
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE(nsSVGSwitchElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGSwitchElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGSwitchElementBase::)
 
   // nsINode
--- a/content/svg/content/test/Makefile.in
+++ b/content/svg/content/test/Makefile.in
@@ -52,12 +52,13 @@ include $(topsrcdir)/config/rules.mk
 		dataTypes-helper.svg \
 		test_getSubStringLength.xhtml \
 		getSubStringLength-helper.svg \
 		test_pathSeg.xhtml \
 		test_scientific.html \
 		scientific-helper.svg \
 		test_text.html \
 		text-helper.svg \
+		test_valueLeaks.xhtml \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/svg/content/test/test_valueLeaks.xhtml
@@ -0,0 +1,76 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=467671
+-->
+<head>
+  <title>Test for Bug 467671</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=467671">Mozilla Bug 467671</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 467671 **/
+
+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) {
+        Object.prototype.toSource[prop + "_baseVal_expando"] = propVal.baseVal;
+        Object.prototype.toSource[prop + "_animVal_expando"] = propVal.animVal;
+    }
+}
+
+// angle
+storeSVGPropertyAsExpando("marker", "orientAngle");
+
+// boolean
+storeSVGPropertyAsExpando("feConvolveMatrix", "preserveAlpha");
+
+// enum
+storeSVGPropertyAsExpando("feConvolveMatrix", "edgeMode");
+
+// special marker enum
+storeSVGPropertyAsExpando("marker", "orientType");
+
+// integer
+storeSVGPropertyAsExpando("feConvolveMatrix", "orderX");
+
+// length
+storeSVGPropertyAsExpando("feConvolveMatrix", "x");
+
+// number
+storeSVGPropertyAsExpando("feConvolveMatrix", "divisor");
+
+// string
+storeSVGPropertyAsExpando("feConvolveMatrix", "in1");
+
+var elem1 = document.createElementNS("http://www.w3.org/2000/svg", "switch");
+var elem2 = document.createElementNS("http://www.w3.org/2000/svg", "rect");
+elem1.appendChild(elem2);
+document.getElementById("content").appendChild(elem1);
+
+elem2.addEventListener("click", function(){}, false);
+
+Object.prototype.toSource.expando = elem1;
+
+ok(true, "SVG shouldn't leak.");
+
+]]>
+</script>
+</pre>
+</body>
+</html>