Bug 589439. De-COMtaminate SVG number lists and support for SMIL animation of SVG number lists. a=roc r=roc,longsonr,dholbert.
authorJonathan Watt <jwatt@jwatt.org>
Fri, 03 Dec 2010 16:40:23 +0000
changeset 58554 4e49d32a52169d2bd98735f7992f7d73f8d7c616
parent 58553 918e77b793124f5927a6a5345094a0fabe68be5f
child 58555 b7e28f4485336c8e3886c300503bd35f690a7b54
push idunknown
push userunknown
push dateunknown
reviewersroc, roc, longsonr, dholbert
bugs589439
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 589439. De-COMtaminate SVG number lists and support for SMIL animation of SVG number lists. a=roc r=roc,longsonr,dholbert.
content/svg/content/src/DOMSVGAnimatedNumberList.cpp
content/svg/content/src/DOMSVGAnimatedNumberList.h
content/svg/content/src/DOMSVGLength.cpp
content/svg/content/src/DOMSVGLength.h
content/svg/content/src/DOMSVGLengthList.h
content/svg/content/src/DOMSVGNumber.cpp
content/svg/content/src/DOMSVGNumber.h
content/svg/content/src/DOMSVGNumberList.cpp
content/svg/content/src/DOMSVGNumberList.h
content/svg/content/src/Makefile.in
content/svg/content/src/SVGAnimatedNumberList.cpp
content/svg/content/src/SVGAnimatedNumberList.h
content/svg/content/src/SVGNumberList.cpp
content/svg/content/src/SVGNumberList.h
content/svg/content/src/SVGNumberListSMILType.cpp
content/svg/content/src/SVGNumberListSMILType.h
content/svg/content/src/nsSVGAnimatedNumberList.cpp
content/svg/content/src/nsSVGAnimatedNumberList.h
content/svg/content/src/nsSVGElement.cpp
content/svg/content/src/nsSVGElement.h
content/svg/content/src/nsSVGFilters.cpp
content/svg/content/src/nsSVGFilters.h
content/svg/content/src/nsSVGNumber.cpp
content/svg/content/src/nsSVGNumber.h
content/svg/content/src/nsSVGNumberList.cpp
content/svg/content/src/nsSVGNumberList.h
content/svg/content/src/nsSVGSVGElement.cpp
content/svg/content/src/nsSVGStopElement.cpp
content/svg/content/src/nsSVGTextElement.cpp
content/svg/content/src/nsSVGTextPositioningElement.cpp
content/svg/content/src/nsSVGTextPositioningElement.h
content/svg/content/test/test_SVGxxxList.xhtml
layout/reftests/svg/smil/anim-feFuncR-tableValues-01-ref.svg
layout/reftests/svg/smil/anim-feFuncR-tableValues-01.svg
layout/reftests/svg/smil/anim-text-rotate-01-ref.svg
layout/reftests/svg/smil/anim-text-rotate-01.svg
layout/reftests/svg/smil/reftest.list
layout/svg/base/src/nsISVGChildFrame.h
layout/svg/base/src/nsSVGAFrame.cpp
layout/svg/base/src/nsSVGGlyphFrame.cpp
layout/svg/base/src/nsSVGGlyphFrame.h
layout/svg/base/src/nsSVGTextContainerFrame.cpp
layout/svg/base/src/nsSVGTextContainerFrame.h
layout/svg/base/src/nsSVGTextPathFrame.cpp
layout/svg/base/src/nsSVGTextPathFrame.h
layout/svg/base/src/nsSVGUtils.cpp
layout/svg/base/src/nsSVGUtils.h
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/DOMSVGAnimatedNumberList.cpp
@@ -0,0 +1,160 @@
+/* -*- 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 Mozilla SVG Project code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 "DOMSVGAnimatedNumberList.h"
+#include "DOMSVGNumberList.h"
+#include "SVGAnimatedNumberList.h"
+#include "nsSVGElement.h"
+#include "nsCOMPtr.h"
+#include "nsSVGAttrTearoffTable.h"
+
+// See the architecture comment in this file's header.
+
+using namespace mozilla;
+
+static nsSVGAttrTearoffTable<SVGAnimatedNumberList, DOMSVGAnimatedNumberList>
+  sSVGAnimatedNumberListTearoffTable;
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(DOMSVGAnimatedNumberList, mElement)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGAnimatedNumberList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGAnimatedNumberList)
+
+DOMCI_DATA(SVGAnimatedNumberList, DOMSVGAnimatedNumberList)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGAnimatedNumberList)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedNumberList)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedNumberList)
+NS_INTERFACE_MAP_END
+
+NS_IMETHODIMP
+DOMSVGAnimatedNumberList::GetBaseVal(nsIDOMSVGNumberList **_retval)
+{
+  if (!mBaseVal) {
+    mBaseVal = new DOMSVGNumberList(this, InternalAList().GetBaseValue());
+  }
+  NS_ADDREF(*_retval = mBaseVal);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGAnimatedNumberList::GetAnimVal(nsIDOMSVGNumberList **_retval)
+{
+  if (!mAnimVal) {
+    mAnimVal = new DOMSVGNumberList(this, InternalAList().GetAnimValue());
+  }
+  NS_ADDREF(*_retval = mAnimVal);
+  return NS_OK;
+}
+
+/* static */ already_AddRefed<DOMSVGAnimatedNumberList>
+DOMSVGAnimatedNumberList::GetDOMWrapper(SVGAnimatedNumberList *aList,
+                                        nsSVGElement *aElement,
+                                        PRUint8 aAttrEnum)
+{
+  DOMSVGAnimatedNumberList *wrapper =
+    sSVGAnimatedNumberListTearoffTable.GetTearoff(aList);
+  if (!wrapper) {
+    wrapper = new DOMSVGAnimatedNumberList(aElement, aAttrEnum);
+    sSVGAnimatedNumberListTearoffTable.AddTearoff(aList, wrapper);
+  }
+  NS_ADDREF(wrapper);
+  return wrapper;
+}
+
+/* static */ DOMSVGAnimatedNumberList*
+DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(SVGAnimatedNumberList *aList)
+{
+  return sSVGAnimatedNumberListTearoffTable.GetTearoff(aList);
+}
+
+DOMSVGAnimatedNumberList::~DOMSVGAnimatedNumberList()
+{
+  // Script no longer has any references to us, to our base/animVal objects, or
+  // to any of their list items.
+  sSVGAnimatedNumberListTearoffTable.RemoveTearoff(&InternalAList());
+}
+
+void
+DOMSVGAnimatedNumberList::InternalBaseValListWillChangeTo(const SVGNumberList& aNewValue)
+{
+  // When the number of items in our internal counterpart's baseVal changes,
+  // we MUST keep our baseVal in sync. If we don't, script will either see a
+  // list that is too short and be unable to access indexes that should be
+  // valid, or else, MUCH WORSE, script will see a list that is too long and be
+  // able to access "items" at indexes that are out of bounds (read/write to
+  // bad memory)!!
+
+  if (mBaseVal) {
+    mBaseVal->InternalListLengthWillChange(aNewValue.Length());
+  }
+
+  // If our attribute is not animating, then our animVal mirrors our baseVal
+  // and we must sync its length too. (If our attribute is animating, then the
+  // SMIL engine takes care of calling InternalAnimValListWillChangeTo() if
+  // necessary.)
+
+  if (!IsAnimating()) {
+    InternalAnimValListWillChangeTo(aNewValue);
+  }
+}
+
+void
+DOMSVGAnimatedNumberList::InternalAnimValListWillChangeTo(const SVGNumberList& aNewValue)
+{
+  if (mAnimVal) {
+    mAnimVal->InternalListLengthWillChange(aNewValue.Length());
+  }
+}
+
+PRBool
+DOMSVGAnimatedNumberList::IsAnimating() const
+{
+  return InternalAList().IsAnimating();
+}
+
+SVGAnimatedNumberList&
+DOMSVGAnimatedNumberList::InternalAList()
+{
+  return *mElement->GetAnimatedNumberList(mAttrEnum);
+}
+
+const SVGAnimatedNumberList&
+DOMSVGAnimatedNumberList::InternalAList() const
+{
+  return *mElement->GetAnimatedNumberList(mAttrEnum);
+}
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/DOMSVGAnimatedNumberList.h
@@ -0,0 +1,156 @@
+/* -*- 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 Mozilla SVG Project code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 MOZILLA_DOMSVGANIMATEDNUMBERLIST_H__
+#define MOZILLA_DOMSVGANIMATEDNUMBERLIST_H__
+
+#include "nsIDOMSVGAnimatedNumberList.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsAutoPtr.h"
+#include "nsTArray.h"
+
+class nsSVGElement;
+
+namespace mozilla {
+
+class SVGAnimatedNumberList;
+class SVGNumberList;
+class DOMSVGNumberList;
+
+/**
+ * Class DOMSVGAnimatedNumberList
+ *
+ * This class is used to create the DOM tearoff objects that wrap internal
+ * SVGAnimatedNumberList objects.
+ *
+ * See the architecture comment in DOMSVGAnimatedLengthList.h (that's
+ * LENGTH list). The comment for that class largly applies to this one too
+ * and will go a long way to helping you understand the architecture here.
+ *
+ * This class is strongly intertwined with DOMSVGNumberList and DOMSVGNumber.
+ * Our DOMSVGNumberList base and anim vals are friends and take care of nulling
+ * out our pointers to them when they die (making our pointers to them true
+ * weak refs).
+ */
+class DOMSVGAnimatedNumberList : public nsIDOMSVGAnimatedNumberList
+{
+  friend class DOMSVGNumberList;
+
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGAnimatedNumberList)
+  NS_DECL_NSIDOMSVGANIMATEDNUMBERLIST
+
+  /**
+   * Factory method to create and return a DOMSVGAnimatedNumberList wrapper
+   * for a given internal SVGAnimatedNumberList object. The factory takes care
+   * of caching the object that it returns so that the same object can be
+   * returned for the given SVGAnimatedNumberList each time it is requested.
+   * The cached object is only removed from the cache when it is destroyed due
+   * to there being no more references to it or to any of its descendant
+   * objects. If that happens, any subsequent call requesting the DOM wrapper
+   * for the SVGAnimatedNumberList will naturally result in a new
+   * DOMSVGAnimatedNumberList being returned.
+   */
+  static already_AddRefed<DOMSVGAnimatedNumberList>
+    GetDOMWrapper(SVGAnimatedNumberList *aList,
+                  nsSVGElement *aElement,
+                  PRUint8 aAttrEnum);
+
+  /**
+   * This method returns the DOMSVGAnimatedNumberList wrapper for an internal
+   * SVGAnimatedNumberList object if it currently has a wrapper. If it does
+   * not, then nsnull is returned.
+   */
+  static DOMSVGAnimatedNumberList*
+    GetDOMWrapperIfExists(SVGAnimatedNumberList *aList);
+
+  /**
+   * Called by internal code to notify us when we need to sync the length of
+   * our baseVal DOM list with its internal list. This is called just prior to
+   * the length of the internal baseVal list being changed so that any DOM list
+   * items that need to be removed from the DOM list can first get their values
+   * from their internal counterpart.
+   *
+   * The only time this method could fail is on OOM when trying to increase the
+   * length of the DOM list. If that happens then this method simply clears the
+   * list and returns. Callers just proceed as normal, and we simply accept
+   * that the DOM list will be empty (until successfully set to a new value).
+   */
+  void InternalBaseValListWillChangeTo(const SVGNumberList& aNewValue);
+  void InternalAnimValListWillChangeTo(const SVGNumberList& aNewValue);
+
+  /**
+   * Returns true if our attribute is animating (in which case our animVal is
+   * not simply a mirror of our baseVal).
+   */
+  PRBool IsAnimating() const;
+
+private:
+
+  /**
+   * Only our static GetDOMWrapper() factory method may create objects of our
+   * type.
+   */
+  DOMSVGAnimatedNumberList(nsSVGElement *aElement, PRUint8 aAttrEnum)
+    : mBaseVal(nsnull)
+    , mAnimVal(nsnull)
+    , mElement(aElement)
+    , mAttrEnum(aAttrEnum)
+  {}
+
+  ~DOMSVGAnimatedNumberList();
+
+  /// Get a reference to this DOM wrapper object's internal counterpart.
+  SVGAnimatedNumberList& InternalAList();
+  const SVGAnimatedNumberList& InternalAList() const;
+
+  // Weak refs to our DOMSVGNumberList baseVal/animVal objects. These objects
+  // are friends and take care of clearing these pointers when they die, making
+  // these true weak references.
+  DOMSVGNumberList *mBaseVal;
+  DOMSVGNumberList *mAnimVal;
+
+  // Strong ref to our element to keep it alive. We hold this not only for
+  // ourself, but also for our base/animVal and all of their items.
+  nsRefPtr<nsSVGElement> mElement;
+
+  PRUint8 mAttrEnum;
+};
+
+} // namespace mozilla
+
+#endif // MOZILLA_DOMSVGANIMATEDNUMBERLIST_H__
--- a/content/svg/content/src/DOMSVGLength.cpp
+++ b/content/svg/content/src/DOMSVGLength.cpp
@@ -83,37 +83,30 @@ DOMSVGLength::DOMSVGLength(DOMSVGLengthL
                            PRUint8 aIsAnimValItem)
   : mList(aList)
   , mListIndex(aListIndex)
   , mAttrEnum(aAttrEnum)
   , mIsAnimValItem(aIsAnimValItem)
   , mUnit(nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER)
   , mValue(0.0f)
 {
-#ifdef DEBUG
-  // These shifts are in sync with the flag member's in the header.
+  // These shifts are in sync with the members in the header.
   NS_ABORT_IF_FALSE(aList &&
                     aAttrEnum < (1 << 22) &&
                     aListIndex < (1 << 4) &&
                     aIsAnimValItem < (1 << 1), "bad arg");
-  if (aIsAnimValItem &&
-      mListIndex >= Element()->GetAnimatedLengthList(mAttrEnum)->GetAnimValue().Length() ||
-      !aIsAnimValItem &&
-      mListIndex >= Element()->GetAnimatedLengthList(mAttrEnum)->GetBaseValue().Length()) {
-    NS_ABORT_IF_FALSE(0, "Bad aListIndex!");
-    mList = nsnull;
-  }
-#endif
+
+  NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGNumber!");
 }
 
 DOMSVGLength::DOMSVGLength()
   : mList(nsnull)
   , mListIndex(0)
   , mAttrEnum(0)
-  , mIsAnimValItem(0)
+  , mIsAnimValItem(PR_FALSE)
   , mUnit(nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER)
   , mValue(0.0f)
 {
 }
 
 NS_IMETHODIMP
 DOMSVGLength::GetUnitType(PRUint16* aUnit)
 {
@@ -316,35 +309,32 @@ DOMSVGLength::ConvertToSpecifiedUnits(PR
 
 void
 DOMSVGLength::InsertingIntoList(DOMSVGLengthList *aList,
                                 PRUint32 aAttrEnum,
                                 PRUint8 aListIndex,
                                 PRUint8 aIsAnimValItem)
 {
   NS_ASSERTION(!HasOwner(), "Inserting item that is already in a list");
-  NS_ASSERTION(mIsAnimValItem &&
-               aListIndex < aList->Element()->GetAnimatedLengthList(aAttrEnum)->GetAnimValue().Length() ||
-               !aIsAnimValItem &&
-               aListIndex < aList->Element()->GetAnimatedLengthList(aAttrEnum)->GetBaseValue().Length(),
-               "mListIndex too big");
 
   mList = aList;
   mAttrEnum = aAttrEnum;
   mListIndex = aListIndex;
   mIsAnimValItem = aIsAnimValItem;
+
+  NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGLength!");
 }
 
 void
 DOMSVGLength::RemovingFromList()
 {
   mValue = InternalItem().GetValueInCurrentUnits();
   mUnit  = InternalItem().GetUnit();
   mList = nsnull;
-  mIsAnimValItem = 0;
+  mIsAnimValItem = PR_FALSE;
 }
 
 SVGLength
 DOMSVGLength::ToSVGLength()
 {
   if (HasOwner()) {
     return SVGLength(InternalItem().GetValueInCurrentUnits(),
                      InternalItem().GetUnit());
@@ -356,9 +346,21 @@ SVGLength&
 DOMSVGLength::InternalItem()
 {
   SVGAnimatedLengthList *alist = Element()->GetAnimatedLengthList(mAttrEnum);
   return mIsAnimValItem && alist->mAnimVal ?
     (*alist->mAnimVal)[mListIndex] :
     alist->mBaseVal[mListIndex];
 }
 
+#ifdef DEBUG
+PRBool
+DOMSVGLength::IndexIsValid()
+{
+  SVGAnimatedLengthList *alist = Element()->GetAnimatedLengthList(mAttrEnum);
+  return (mIsAnimValItem &&
+          mListIndex < alist->GetAnimValue().Length()) ||
+         (!mIsAnimValItem &&
+          mListIndex < alist->GetBaseValue().Length());
+}
+#endif
+
 } // namespace mozilla
--- a/content/svg/content/src/DOMSVGLength.h
+++ b/content/svg/content/src/DOMSVGLength.h
@@ -165,17 +165,17 @@ public:
   void UpdateListIndex(PRUint8 aListIndex) {
     mListIndex = aListIndex;
   }
 
   /**
    * This method is called to notify this DOM object that it is about to be
    * removed from its current DOM list so that it can first make a copy of its
    * internal counterpart's values. (If it didn't do this, then it would
-   * "loose" its value on being removed.)
+   * "lose" its value on being removed.)
    */
   void RemovingFromList();
 
   SVGLength ToSVGLength();
 
 private:
 
   nsSVGElement* Element() {
@@ -193,23 +193,27 @@ private:
   PRUint8 Axis() const {
     return mList->Axis();
   }
 
   /**
    * Get a reference to the internal SVGLength list item that this DOM wrapper
    * object currently wraps.
    *
-   * To simplyfy the code we just have this one method for obtaining both
+   * To simplify the code we just have this one method for obtaining both
    * baseVal and animVal internal items. This means that animVal items don't
    * get const protection, but then our setter methods guard against changing
    * animVal items.
    */
   SVGLength& InternalItem();
 
+#ifdef DEBUG
+  PRBool IndexIsValid();
+#endif
+
   nsRefPtr<DOMSVGLengthList> mList;
 
   // Bounds for the following are checked in the ctor, so be sure to update
   // that if you change the capacity of any of the following.
 
   PRUint32 mListIndex:22; // supports > 4 million list items
   PRUint32 mAttrEnum:4; // supports up to 16 attributes
   PRUint32 mIsAnimValItem:1;
--- a/content/svg/content/src/DOMSVGLengthList.h
+++ b/content/svg/content/src/DOMSVGLengthList.h
@@ -130,17 +130,17 @@ private:
   /// Used to determine if this list is the baseVal or animVal list.
   PRBool IsAnimValList() const {
     return this == mAList->mAnimVal;
   }
 
   /**
    * Get a reference to this object's corresponding internal SVGLengthList.
    *
-   * To simplyfy the code we just have this one method for obtaining both
+   * To simplify the code we just have this one method for obtaining both
    * baseVal and animVal internal lists. This means that animVal lists don't
    * get const protection, but our setter methods guard against changing
    * animVal lists.
    */
   SVGLengthList& InternalList();
 
   /// Creates a DOMSVGLength for aIndex, if it doesn't already exist.
   void EnsureItemAt(PRUint32 aIndex);
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/DOMSVGNumber.cpp
@@ -0,0 +1,190 @@
+/* -*- 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 Mozilla SVG Project code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 "DOMSVGNumber.h"
+#include "DOMSVGNumberList.h"
+#include "DOMSVGAnimatedNumberList.h"
+#include "SVGAnimatedNumberList.h"
+#include "nsSVGElement.h"
+#include "nsIDOMSVGNumber.h"
+#include "nsDOMError.h"
+
+// See the architecture comment in DOMSVGAnimatedNumberList.h.
+
+using namespace mozilla;
+
+// We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
+// clear our list's weak ref to us to be safe. (The other option would be to
+// not unlink and rely on the breaking of the other edges in the cycle, as
+// NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGNumber)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumber)
+  // We may not belong to a list, so we must null check tmp->mList.
+  if (tmp->mList) {
+    tmp->mList->mItems[tmp->mListIndex] = nsnull;
+  }
+NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGNumber)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGNumber)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGNumber)
+
+DOMCI_DATA(SVGNumber, DOMSVGNumber)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGNumber)
+  NS_INTERFACE_MAP_ENTRY(DOMSVGNumber) // pseudo-interface
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGNumber)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGNumber)
+NS_INTERFACE_MAP_END
+
+DOMSVGNumber::DOMSVGNumber(DOMSVGNumberList *aList,
+                           PRUint32 aAttrEnum,
+                           PRUint8 aListIndex,
+                           PRUint8 aIsAnimValItem)
+  : mList(aList)
+  , mListIndex(aListIndex)
+  , mAttrEnum(aAttrEnum)
+  , mIsAnimValItem(aIsAnimValItem)
+  , mValue(0.0f)
+{
+  // These shifts are in sync with the members in the header.
+  NS_ABORT_IF_FALSE(aList &&
+                    aAttrEnum < (1 << 27) &&
+                    aListIndex < (1 << 4) &&
+                    aIsAnimValItem < (1 << 1), "bad arg");
+
+  NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGNumber!");
+}
+
+DOMSVGNumber::DOMSVGNumber()
+  : mList(nsnull)
+  , mListIndex(0)
+  , mAttrEnum(0)
+  , mIsAnimValItem(PR_FALSE)
+  , mValue(0.0f)
+{
+}
+
+NS_IMETHODIMP
+DOMSVGNumber::GetValue(float* aValue)
+{
+#ifdef MOZ_SMIL
+  if (mIsAnimValItem && HasOwner()) {
+    Element()->FlushAnimations(); // May make HasOwner() == PR_FALSE
+  }
+#endif
+  *aValue = HasOwner() ? InternalItem() : mValue;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGNumber::SetValue(float aValue)
+{
+  if (mIsAnimValItem) {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+
+  NS_ENSURE_FINITE(aValue, NS_ERROR_ILLEGAL_VALUE);
+
+  if (HasOwner()) {
+    InternalItem() = aValue;
+    Element()->DidChangeNumberList(mAttrEnum, PR_TRUE);
+#ifdef MOZ_SMIL
+    if (mList->mAList->IsAnimating()) {
+      Element()->AnimationNeedsResample();
+    }
+#endif
+    return NS_OK;
+  }
+  mValue = aValue;
+  return NS_OK;
+}
+
+void
+DOMSVGNumber::InsertingIntoList(DOMSVGNumberList *aList,
+                                PRUint32 aAttrEnum,
+                                PRUint8 aListIndex,
+                                PRUint8 aIsAnimValItem)
+{
+  NS_ASSERTION(!HasOwner(), "Inserting item that is already in a list");
+
+  mList = aList;
+  mAttrEnum = aAttrEnum;
+  mListIndex = aListIndex;
+  mIsAnimValItem = aIsAnimValItem;
+
+  NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGNumber!");
+}
+
+void
+DOMSVGNumber::RemovingFromList()
+{
+  mValue = InternalItem();
+  mList = nsnull;
+  mIsAnimValItem = PR_FALSE;
+}
+
+float
+DOMSVGNumber::ToSVGNumber()
+{
+  return HasOwner() ? InternalItem() : mValue;
+}
+
+float&
+DOMSVGNumber::InternalItem()
+{
+  SVGAnimatedNumberList *alist = Element()->GetAnimatedNumberList(mAttrEnum);
+  return mIsAnimValItem && alist->mAnimVal ?
+    (*alist->mAnimVal)[mListIndex] :
+    alist->mBaseVal[mListIndex];
+}
+
+#ifdef DEBUG
+PRBool
+DOMSVGNumber::IndexIsValid()
+{
+  SVGAnimatedNumberList *alist = Element()->GetAnimatedNumberList(mAttrEnum);
+  return (mIsAnimValItem &&
+          mListIndex < alist->GetAnimValue().Length()) ||
+         (!mIsAnimValItem &&
+          mListIndex < alist->GetBaseValue().Length());
+}
+#endif
+
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/DOMSVGNumber.h
@@ -0,0 +1,194 @@
+/* -*- 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 Mozilla SVG Project code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 MOZILLA_DOMSVGNUMBER_H__
+#define MOZILLA_DOMSVGNUMBER_H__
+
+#include "nsIDOMSVGNumber.h"
+#include "DOMSVGNumberList.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsAutoPtr.h"
+
+class nsSVGElement;
+
+// We make DOMSVGNumber a pseudo-interface to allow us to QI to it in order to
+// check that the objects that scripts pass to DOMSVGNumberList methods are our
+// *native* number objects.
+//
+// {2CA92412-2E1F-4DDB-A16C-52B3B582270D}
+#define MOZILLA_DOMSVGNUMBER_IID \
+  { 0x2CA92412, 0x2E1F, 0x4DDB, \
+    { 0xA1, 0x6C, 0x52, 0xB3, 0xB5, 0x82, 0x27, 0x0D } }
+
+namespace mozilla {
+
+/**
+ * Class DOMSVGNumber
+ *
+ * This class creates the DOM objects that wrap internal SVGNumber objects that
+ * are in an SVGNumberList. It is also used to create the objects returned by
+ * SVGSVGElement.createSVGNumber().
+ *
+ * For the DOM wrapper classes for non-list SVGNumber, see nsSVGNumber2.h.
+ *
+ * See the architecture comment in DOMSVGAnimatedNumberList.h.
+ *
+ * See the comment in DOMSVGLength.h (yes, LENGTH), which applies here too.
+ */
+class DOMSVGNumber : public nsIDOMSVGNumber
+{
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGNUMBER_IID)
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGNumber)
+  NS_DECL_NSIDOMSVGNUMBER
+
+  /**
+   * Generic ctor for DOMSVGNumber objects that are created for an attribute.
+   */
+  DOMSVGNumber(DOMSVGNumberList *aList,
+               PRUint32 aAttrEnum,
+               PRUint8 aListIndex,
+               PRUint8 aIsAnimValItem);
+
+  /**
+   * Ctor for creating the objects returned by SVGSVGElement.createSVGNumber(),
+   * which do not initially belong to an attribute.
+   */
+  DOMSVGNumber();
+
+  ~DOMSVGNumber() {
+    // Our mList's weak ref to us must be nulled out when we die. If GC has
+    // unlinked us using the cycle collector code, then that has already
+    // happened, and mList is null.
+    if (mList) {
+      mList->mItems[mListIndex] = nsnull;
+    }
+  };
+
+  /**
+   * Create an unowned copy. The caller is responsible for the first AddRef().
+   */
+  DOMSVGNumber* Clone() {
+    DOMSVGNumber *clone = new DOMSVGNumber();
+    clone->mValue = ToSVGNumber();
+    return clone;
+  }
+
+  PRBool IsInList() const {
+    return !!mList;
+  }
+
+  /**
+   * In future, if this class is used for non-list numbers, this will be
+   * different to IsInList().
+   */
+  PRBool HasOwner() const {
+    return !!mList;
+  }
+
+  /**
+   * This method is called to notify this DOM object that it is being inserted
+   * into a list, and give it the information it needs as a result.
+   *
+   * This object MUST NOT already belong to a list when this method is called.
+   * That's not to say that script can't move these DOM objects between
+   * lists - it can - it's just that the logic to handle that (and send out
+   * the necessary notifications) is located elsewhere (in DOMSVGNumberList).)
+   */
+  void InsertingIntoList(DOMSVGNumberList *aList,
+                         PRUint32 aAttrEnum,
+                         PRUint8 aListIndex,
+                         PRUint8 aIsAnimValItem);
+
+  /// This method is called to notify this object that its list index changed.
+  void UpdateListIndex(PRUint8 aListIndex) {
+    mListIndex = aListIndex;
+  }
+
+  /**
+   * This method is called to notify this DOM object that it is about to be
+   * removed from its current DOM list so that it can first make a copy of its
+   * internal counterpart's value. (If it didn't do this, then it would
+   * "lose" its value on being removed.)
+   */
+  void RemovingFromList();
+
+  float ToSVGNumber();
+
+private:
+
+  nsSVGElement* Element() {
+    return mList->Element();
+  }
+
+  PRUint8 AttrEnum() const {
+    return mAttrEnum;
+  }
+
+  /**
+   * Get a reference to the internal SVGNumber list item that this DOM wrapper
+   * object currently wraps.
+   *
+   * To simplify the code we just have this one method for obtaining both
+   * baseVal and animVal internal items. This means that animVal items don't
+   * get const protection, but then our setter methods guard against changing
+   * animVal items.
+   */
+  float& InternalItem();
+
+#ifdef DEBUG
+  PRBool IndexIsValid();
+#endif
+
+  nsRefPtr<DOMSVGNumberList> mList;
+
+  // Bounds for the following are checked in the ctor, so be sure to update
+  // that if you change the capacity of any of the following.
+
+  PRUint32 mListIndex:27; // supports > 134 million list items
+  PRUint32 mAttrEnum:4; // supports up to 16 attributes
+  PRUint32 mIsAnimValItem:1;
+
+  // The following member is only used when we're not in a list:
+  float mValue;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(DOMSVGNumber, MOZILLA_DOMSVGNUMBER_IID)
+
+} // namespace mozilla
+
+#endif // MOZILLA_DOMSVGNUMBER_H__
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/DOMSVGNumberList.cpp
@@ -0,0 +1,327 @@
+/* -*- 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 Mozilla SVG Project code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 "nsSVGElement.h"
+#include "DOMSVGNumberList.h"
+#include "DOMSVGNumber.h"
+#include "nsDOMError.h"
+#include "SVGAnimatedNumberList.h"
+#include "nsCOMPtr.h"
+
+// See the comment in this file's header.
+
+using namespace mozilla;
+
+// We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
+// clear our DOMSVGAnimatedNumberList's weak ref to us to be safe. (The other
+// option would be to not unlink and rely on the breaking of the other edges in
+// the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGNumberList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumberList)
+  // No need to null check tmp - script/SMIL can't detach us from mAList
+  ( tmp->IsAnimValList() ? tmp->mAList->mAnimVal : tmp->mAList->mBaseVal ) = nsnull;
+NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAList)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGNumberList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGNumberList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGNumberList)
+
+DOMCI_DATA(SVGNumberList, DOMSVGNumberList)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGNumberList)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGNumberList)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGNumberList)
+NS_INTERFACE_MAP_END
+
+
+void
+DOMSVGNumberList::InternalListLengthWillChange(PRUint32 aNewLength)
+{
+  PRUint32 oldLength = mItems.Length();
+
+  // If our length will decrease, notify the items that will be removed:
+  for (PRUint32 i = aNewLength; i < oldLength; ++i) {
+    if (mItems[i]) {
+      mItems[i]->RemovingFromList();
+    }
+  }
+
+  if (!mItems.SetLength(aNewLength)) {
+    // We silently ignore SetLength OOM failure since being out of sync is safe
+    // so long as we have *fewer* items than our internal list.
+    mItems.Clear();
+    return;
+  }
+
+  // If our length has increased, null out the new pointers:
+  for (PRUint32 i = oldLength; i < aNewLength; ++i) {
+    mItems[i] = nsnull;
+  }
+}
+
+SVGNumberList&
+DOMSVGNumberList::InternalList()
+{
+  SVGAnimatedNumberList *alist = Element()->GetAnimatedNumberList(AttrEnum());
+  return IsAnimValList() && alist->mAnimVal ? *alist->mAnimVal : alist->mBaseVal;
+}
+
+// ----------------------------------------------------------------------------
+// nsIDOMSVGNumberList implementation:
+
+NS_IMETHODIMP
+DOMSVGNumberList::GetNumberOfItems(PRUint32 *aNumberOfItems)
+{
+#ifdef MOZ_SMIL
+  if (IsAnimValList()) {
+    Element()->FlushAnimations();
+  }
+#endif
+  *aNumberOfItems = Length();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGNumberList::Clear()
+{
+  if (IsAnimValList()) {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+
+  if (Length() > 0) {
+    // Notify any existing DOM items of removal *before* truncating the lists
+    // so that they can find their SVGNumber internal counterparts and copy
+    // their values:
+    mAList->InternalBaseValListWillChangeTo(SVGNumberList());
+
+    mItems.Clear();
+    InternalList().Clear();
+    Element()->DidChangeNumberList(AttrEnum(), PR_TRUE);
+#ifdef MOZ_SMIL
+    if (mAList->IsAnimating()) {
+      Element()->AnimationNeedsResample();
+    }
+#endif
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGNumberList::Initialize(nsIDOMSVGNumber *newItem,
+                             nsIDOMSVGNumber **_retval)
+{
+  *_retval = nsnull;
+  if (IsAnimValList()) {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+
+  // If newItem is already in a list we should insert a clone of newItem, and
+  // for consistency, this should happen even if *this* is the list that
+  // newItem is currently in. Note that in the case of newItem being in this
+  // list, the Clear() call before the InsertItemBefore() call would remove it
+  // from this list, and so the InsertItemBefore() call would not insert a
+  // clone of newItem, it would actually insert newItem. To prevent that from
+  // happening we have to do the clone here, if necessary.
+
+  nsCOMPtr<DOMSVGNumber> domItem = do_QueryInterface(newItem);
+  if (!domItem) {
+    return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
+  }
+  if (domItem->HasOwner()) {
+    newItem = domItem->Clone();
+  }
+
+  Clear();
+  return InsertItemBefore(newItem, 0, _retval);
+}
+
+NS_IMETHODIMP
+DOMSVGNumberList::GetItem(PRUint32 index,
+                          nsIDOMSVGNumber **_retval)
+{
+#ifdef MOZ_SMIL
+  if (IsAnimValList()) {
+    Element()->FlushAnimations();
+  }
+#endif
+  if (index < Length()) {
+    EnsureItemAt(index);
+    NS_ADDREF(*_retval = mItems[index]);
+    return NS_OK;
+  }
+  *_retval = nsnull;
+  return NS_ERROR_DOM_INDEX_SIZE_ERR;
+}
+
+NS_IMETHODIMP
+DOMSVGNumberList::InsertItemBefore(nsIDOMSVGNumber *newItem,
+                                   PRUint32 index,
+                                   nsIDOMSVGNumber **_retval)
+{
+  *_retval = nsnull;
+  if (IsAnimValList()) {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+
+  nsCOMPtr<DOMSVGNumber> domItem = do_QueryInterface(newItem);
+  if (!domItem) {
+    return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
+  }
+  index = NS_MIN(index, Length());
+  float value = domItem->ToSVGNumber(); // get before setting domItem
+  if (domItem->HasOwner()) {
+    domItem = new DOMSVGNumber();
+  }
+  PRBool ok = !!InternalList().InsertItem(index, value);
+  if (!ok) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  domItem->InsertingIntoList(this, AttrEnum(), index, IsAnimValList());
+  ok = !!mItems.InsertElementAt(index, domItem.get());
+  if (!ok) {
+    InternalList().RemoveItem(index);
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  for (PRUint32 i = index + 1; i < Length(); ++i) {
+    if (mItems[i]) {
+      mItems[i]->UpdateListIndex(i);
+    }
+  }
+  Element()->DidChangeNumberList(AttrEnum(), PR_TRUE);
+#ifdef MOZ_SMIL
+  if (mAList->IsAnimating()) {
+    Element()->AnimationNeedsResample();
+  }
+#endif
+  *_retval = domItem.forget().get();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGNumberList::ReplaceItem(nsIDOMSVGNumber *newItem,
+                              PRUint32 index,
+                              nsIDOMSVGNumber **_retval)
+{
+  *_retval = nsnull;
+  if (IsAnimValList()) {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+
+  nsCOMPtr<DOMSVGNumber> domItem = do_QueryInterface(newItem);
+  if (!domItem) {
+    return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
+  }
+  if (index >= Length()) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  }
+  float length = domItem->ToSVGNumber(); // get before setting domItem
+  if (domItem->HasOwner()) {
+    domItem = new DOMSVGNumber();
+  }
+  if (mItems[index]) {
+    // Notify any existing DOM item of removal *before* modifying the lists so
+    // that the DOM item can copy the *old* value at its index:
+    mItems[index]->RemovingFromList();
+  }
+  InternalList()[index] = length;
+  domItem->InsertingIntoList(this, AttrEnum(), index, IsAnimValList());
+  mItems[index] = domItem;
+
+  Element()->DidChangeNumberList(AttrEnum(), PR_TRUE);
+#ifdef MOZ_SMIL
+  if (mAList->IsAnimating()) {
+    Element()->AnimationNeedsResample();
+  }
+#endif
+  NS_ADDREF(*_retval = domItem.get());
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGNumberList::RemoveItem(PRUint32 index,
+                             nsIDOMSVGNumber **_retval)
+{
+  *_retval = nsnull;
+  if (IsAnimValList()) {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+
+  if (index >= Length()) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  }
+  // We have to return the removed item, so make sure it exists:
+  EnsureItemAt(index);
+
+  // Notify the DOM item of removal *before* modifying the lists so that the
+  // DOM item can copy its *old* value:
+  mItems[index]->RemovingFromList();
+
+  InternalList().RemoveItem(index);
+
+  NS_ADDREF(*_retval = mItems[index]);
+  mItems.RemoveElementAt(index);
+  for (PRUint32 i = index; i < Length(); ++i) {
+    if (mItems[i]) {
+      mItems[i]->UpdateListIndex(i);
+    }
+  }
+  Element()->DidChangeNumberList(AttrEnum(), PR_TRUE);
+#ifdef MOZ_SMIL
+  if (mAList->IsAnimating()) {
+    Element()->AnimationNeedsResample();
+  }
+#endif
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGNumberList::AppendItem(nsIDOMSVGNumber *newItem,
+                             nsIDOMSVGNumber **_retval)
+{
+  return InsertItemBefore(newItem, Length(), _retval);
+}
+
+void
+DOMSVGNumberList::EnsureItemAt(PRUint32 aIndex)
+{
+  if (!mItems[aIndex]) {
+    mItems[aIndex] = new DOMSVGNumber(this, AttrEnum(), aIndex, IsAnimValList());
+  }
+}
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/DOMSVGNumberList.h
@@ -0,0 +1,153 @@
+/* -*- 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 Mozilla SVG Project code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 MOZILLA_DOMSVGNUMBERLIST_H__
+#define MOZILLA_DOMSVGNUMBERLIST_H__
+
+#include "nsIDOMSVGNumberList.h"
+#include "SVGNumberList.h"
+#include "DOMSVGAnimatedNumberList.h"
+#include "nsCOMArray.h"
+#include "nsAutoPtr.h"
+
+class nsSVGElement;
+
+namespace mozilla {
+
+class DOMSVGNumber;
+
+/**
+ * Class DOMSVGNumberList
+ *
+ * This class is used to create the DOM tearoff objects that wrap internal
+ * SVGNumberList objects.
+ *
+ * See the architecture comment in DOMSVGAnimatedNumberList.h.
+ *
+ * This class is strongly intertwined with DOMSVGAnimatedNumberList and
+ * DOMSVGNumber. We are a friend of DOMSVGAnimatedNumberList, and are
+ * responsible for nulling out our DOMSVGAnimatedNumberList's pointer to us
+ * when we die, essentially making its pointer to us a weak pointer. Similarly,
+ * our DOMSVGNumber items are friends of us and responsible for nulling out our
+ * pointers to them.
+ *
+ * Our DOM items are created lazily on demand as and when script requests them.
+ */
+class DOMSVGNumberList : public nsIDOMSVGNumberList
+{
+  friend class DOMSVGNumber;
+
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGNumberList)
+  NS_DECL_NSIDOMSVGNUMBERLIST
+
+  DOMSVGNumberList(DOMSVGAnimatedNumberList *aAList,
+                   const SVGNumberList &aInternalList)
+    : mAList(aAList)
+  {
+    // We can NOT use InternalList() here - it depends on IsAnimValList, which
+    // in turn depends on this object having been assigned to either aAList's
+    // mBaseVal or mAnimVal. At this point we haven't been assigned to either!
+    // This is why our caller must pass in aInternalList.
+
+    InternalListLengthWillChange(aInternalList.Length()); // Initialize mItems
+  }
+
+  ~DOMSVGNumberList() {
+    // Our mAList's weak ref to us must be nulled out when we die. If GC has
+    // unlinked us using the cycle collector code, then that has already
+    // happened, and mAList is null.
+    if (mAList) {
+      ( IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal ) = nsnull;
+    }
+  }
+
+  /**
+   * This will normally be the same as InternalList().Length(), except if we've
+   * hit OOM in which case our length will be zero.
+   */
+  PRUint32 Length() const {
+    NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
+                      mItems.Length() ==
+                        const_cast<DOMSVGNumberList*>(this)->InternalList().Length(),
+                      "DOM wrapper's list length is out of sync");
+    return mItems.Length();
+  }
+
+  /// Called to notify us to syncronize our length and detach excess items.
+  void InternalListLengthWillChange(PRUint32 aNewLength);
+
+private:
+
+  nsSVGElement* Element() {
+    return mAList->mElement;
+  }
+
+  PRUint8 AttrEnum() const {
+    return mAList->mAttrEnum;
+  }
+
+  /// Used to determine if this list is the baseVal or animVal list.
+  PRBool IsAnimValList() const {
+    NS_ABORT_IF_FALSE(this == mAList->mBaseVal || this == mAList->mAnimVal,
+                      "Calling IsAnimValList() too early?!");
+    return this == mAList->mAnimVal;
+  }
+
+  /**
+   * Get a reference to this object's corresponding internal SVGNumberList.
+   *
+   * To simplify the code we just have this one method for obtaining both
+   * baseVal and animVal internal lists. This means that animVal lists don't
+   * get const protection, but our setter methods guard against changing
+   * animVal lists.
+   */
+  SVGNumberList& InternalList();
+
+  /// Creates a DOMSVGNumber for aIndex, if it doesn't already exist.
+  void EnsureItemAt(PRUint32 aIndex);
+
+  // Weak refs to our DOMSVGNumber items. The items are friends and take care
+  // of clearing our pointer to them when they die.
+  nsTArray<DOMSVGNumber*> mItems;
+
+  nsRefPtr<DOMSVGAnimatedNumberList> mAList;
+};
+
+} // namespace mozilla
+
+#endif // MOZILLA_DOMSVGNUMBERLIST_H__
--- a/content/svg/content/src/Makefile.in
+++ b/content/svg/content/src/Makefile.in
@@ -45,26 +45,28 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkcontentsvg_s
 LIBXUL_LIBRARY	= 1
 
 CPPSRCS		= \
 		DOMSVGAnimatedLengthList.cpp \
+		DOMSVGAnimatedNumberList.cpp \
 		DOMSVGLength.cpp \
 		DOMSVGLengthList.cpp \
+		DOMSVGNumber.cpp \
+		DOMSVGNumberList.cpp \
 		DOMSVGPathSeg.cpp \
 		DOMSVGPathSegList.cpp \
 		nsDOMSVGZoomEvent.cpp \
 		nsDOMSVGEvent.cpp \
 		nsSVGAElement.cpp \
 		nsSVGAltGlyphElement.cpp \
 		nsSVGAngle.cpp \
-		nsSVGAnimatedNumberList.cpp \
 		nsSVGAnimatedTransformList.cpp \
 		nsSVGBoolean.cpp \
 		nsSVGCircleElement.cpp \
 		nsSVGClipPathElement.cpp \
 		nsSVGDataParser.cpp \
 		nsSVGDefsElement.cpp \
 		nsSVGDescElement.cpp \
 		nsSVGElement.cpp \
@@ -81,19 +83,17 @@ CPPSRCS		= \
 		nsSVGImageElement.cpp \
 		nsSVGInteger.cpp \
 		nsSVGLength2.cpp \
 		nsSVGLineElement.cpp \
 		nsSVGMarkerElement.cpp \
 		nsSVGMaskElement.cpp \
 		nsSVGMatrix.cpp \
 		nsSVGMetadataElement.cpp \
-		nsSVGNumber.cpp \
 		nsSVGNumber2.cpp \
-		nsSVGNumberList.cpp \
 		nsSVGPathDataParser.cpp \
 		nsSVGPathElement.cpp \
 		nsSVGPathGeometryElement.cpp \
 		nsSVGPatternElement.cpp \
 		nsSVGPoint.cpp \
 		nsSVGPointList.cpp \
 		nsSVGPolyElement.cpp \
 		nsSVGPolygonElement.cpp \
@@ -118,19 +118,21 @@ CPPSRCS		= \
 		nsSVGTitleElement.cpp \
 		nsSVGTransform.cpp \
 		nsSVGTransformList.cpp \
 		nsSVGTransformListParser.cpp \
 		nsSVGUseElement.cpp \
 		nsSVGValue.cpp \
 		nsSVGViewBox.cpp \
 		SVGAnimatedLengthList.cpp \
+		SVGAnimatedNumberList.cpp \
 		SVGAnimatedPathSegList.cpp \
 		SVGLength.cpp \
 		SVGLengthList.cpp \
+		SVGNumberList.cpp \
 		SVGPathData.cpp \
 		SVGPathSegUtils.cpp \
 		$(NULL)
 
 ifdef MOZ_SMIL
 CPPSRCS += nsSVGAnimateElement.cpp \
            nsSVGAnimateTransformElement.cpp \
            nsSVGAnimateMotionElement.cpp \
@@ -139,33 +141,33 @@ CPPSRCS += nsSVGAnimateElement.cpp \
            nsSVGSetElement.cpp \
            nsSVGTransformSMILType.cpp \
            nsSVGTransformSMILAttr.cpp \
            SVGLengthListSMILType.cpp \
            SVGMotionSMILType.cpp \
            SVGMotionSMILAttr.cpp \
            SVGMotionSMILAnimationFunction.cpp \
            SVGMotionSMILPathUtils.cpp \
+           SVGNumberListSMILType.cpp \
            SVGOrientSMILType.cpp \
            SVGPathSegListSMILType.cpp \
            SVGViewBoxSMILType.cpp \
            $(NULL)
 endif
 
 include $(topsrcdir)/config/config.mk
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 EXPORTS =  			\
 	nsISVGValue.h              \
 	nsISVGValueObserver.h      \
 	nsISVGValueUtils.h         \
 	nsSVGFeatures.h            \
-	nsSVGNumber.h              \
 	nsSVGRect.h                \
 	nsSVGPoint.h               \
 	nsSVGMatrix.h              \
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES += 	\
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/SVGAnimatedNumberList.cpp
@@ -0,0 +1,215 @@
+/* -*- 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 Mozilla SVG Project code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 "SVGAnimatedNumberList.h"
+#include "DOMSVGAnimatedNumberList.h"
+#include "nsSVGElement.h"
+#include "nsSVGAttrTearoffTable.h"
+#ifdef MOZ_SMIL
+#include "nsSMILValue.h"
+#include "SVGNumberListSMILType.h"
+#endif // MOZ_SMIL
+
+using namespace mozilla;
+
+nsresult
+SVGAnimatedNumberList::SetBaseValueString(const nsAString& aValue)
+{
+  SVGNumberList newBaseValue;
+  nsresult rv = newBaseValue.SetValueFromString(aValue);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  DOMSVGAnimatedNumberList *domWrapper =
+    DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(this);
+  if (domWrapper) {
+    // We must send this notification *before* changing mBaseVal! If the length
+    // of our baseVal is being reduced, our baseVal's DOM wrapper list may have
+    // to remove DOM items from itself, and any removed DOM items need to copy
+    // their internal counterpart values *before* we change them.
+    //
+    domWrapper->InternalBaseValListWillChangeTo(newBaseValue);
+  }
+
+  // We don't need to call DidChange* here - we're only called by
+  // nsSVGElement::ParseAttribute under nsGenericElement::SetAttr,
+  // which takes care of notifying.
+
+  rv = mBaseVal.CopyFrom(newBaseValue);
+  if (NS_FAILED(rv)) {
+    // Attempting to increase mBaseVal's length failed - reduce domWrapper
+    // back to the same length:
+    domWrapper->InternalBaseValListWillChangeTo(mBaseVal);
+  }
+  return rv;
+}
+
+void
+SVGAnimatedNumberList::ClearBaseValue(PRUint32 aAttrEnum)
+{
+  DOMSVGAnimatedNumberList *domWrapper =
+    DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(this);
+  if (domWrapper) {
+    // We must send this notification *before* changing mBaseVal! (See above.)
+    domWrapper->InternalAnimValListWillChangeTo(SVGNumberList());
+  }
+  mBaseVal.Clear();
+  // Caller notifies
+}
+
+nsresult
+SVGAnimatedNumberList::SetAnimValue(const SVGNumberList& aNewAnimValue,
+                                    nsSVGElement *aElement,
+                                    PRUint32 aAttrEnum)
+{
+  DOMSVGAnimatedNumberList *domWrapper =
+    DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(this);
+  if (domWrapper) {
+    // A new animation may totally change the number of items in the animVal
+    // list, replacing what was essentially a mirror of the baseVal list, or
+    // else replacing and overriding an existing animation. When this happens
+    // we must try and keep our animVal's DOM wrapper in sync (see the comment
+    // in DOMSVGAnimatedNumberList::InternalBaseValListWillChangeTo).
+    //
+    // It's not possible for us to reliably distinguish between calls to this
+    // method that are setting a new sample for an existing animation, and
+    // calls that are setting the first sample of an animation that will
+    // override an existing animation. Happily it's cheap to just blindly
+    // notify our animVal's DOM wrapper of its internal counterpart's new value
+    // each time this method is called, so that's what we do.
+    //
+    // Note that we must send this notification *before* setting or changing
+    // mAnimVal! (See the comment in SetBaseValueString above.)
+    //
+    domWrapper->InternalAnimValListWillChangeTo(aNewAnimValue);
+  }
+  if (!mAnimVal) {
+    mAnimVal = new SVGNumberList();
+  }
+  nsresult rv = mAnimVal->CopyFrom(aNewAnimValue);
+  if (NS_FAILED(rv)) {
+    // OOM. We clear the animation, and, importantly, ClearAnimValue() ensures
+    // that mAnimVal and its DOM wrapper (if any) will have the same length!
+    ClearAnimValue(aElement, aAttrEnum);
+    return rv;
+  }
+  aElement->DidAnimateNumberList(aAttrEnum);
+  return NS_OK;
+}
+
+void
+SVGAnimatedNumberList::ClearAnimValue(nsSVGElement *aElement,
+                                      PRUint32 aAttrEnum)
+{
+  DOMSVGAnimatedNumberList *domWrapper =
+    DOMSVGAnimatedNumberList::GetDOMWrapperIfExists(this);
+  if (domWrapper) {
+    // When all animation ends, animVal simply mirrors baseVal, which may have
+    // a different number of items to the last active animated value. We must
+    // keep the length of our animVal's DOM wrapper list in sync, and again we
+    // must do that before touching mAnimVal. See comments above.
+    //
+    domWrapper->InternalAnimValListWillChangeTo(mBaseVal);
+  }
+  mAnimVal = nsnull;
+  aElement->DidAnimateNumberList(aAttrEnum);
+}
+
+#ifdef MOZ_SMIL
+nsISMILAttr*
+SVGAnimatedNumberList::ToSMILAttr(nsSVGElement *aSVGElement,
+                                  PRUint8 aAttrEnum)
+{
+  return new SMILAnimatedNumberList(this, aSVGElement, aAttrEnum);
+}
+
+nsresult
+SVGAnimatedNumberList::
+  SMILAnimatedNumberList::ValueFromString(const nsAString& aStr,
+                               const nsISMILAnimationElement* /*aSrcElement*/,
+                               nsSMILValue& aValue,
+                               PRBool& aPreventCachingOfSandwich) const
+{
+  nsSMILValue val(&SVGNumberListSMILType::sSingleton);
+  SVGNumberListAndInfo *nlai = static_cast<SVGNumberListAndInfo*>(val.mU.mPtr);
+  nsresult rv = nlai->SetValueFromString(aStr);
+  if (NS_SUCCEEDED(rv)) {
+    nlai->SetInfo(mElement);
+    aValue.Swap(val);
+  }
+  return rv;
+}
+
+nsSMILValue
+SVGAnimatedNumberList::SMILAnimatedNumberList::GetBaseValue() const
+{
+  // To benefit from Return Value Optimization and avoid copy constructor calls
+  // due to our use of return-by-value, we must return the exact same object
+  // from ALL return points. This function must only return THIS variable:
+  nsSMILValue val;
+
+  nsSMILValue tmp(&SVGNumberListSMILType::sSingleton);
+  SVGNumberListAndInfo *nlai = static_cast<SVGNumberListAndInfo*>(tmp.mU.mPtr);
+  nsresult rv = nlai->CopyFrom(mVal->mBaseVal);
+  if (NS_SUCCEEDED(rv)) {
+    nlai->SetInfo(mElement);
+    val.Swap(tmp);
+  }
+  return val;
+}
+
+nsresult
+SVGAnimatedNumberList::SMILAnimatedNumberList::SetAnimValue(const nsSMILValue& aValue)
+{
+  NS_ASSERTION(aValue.mType == &SVGNumberListSMILType::sSingleton,
+               "Unexpected type to assign animated value");
+  if (aValue.mType == &SVGNumberListSMILType::sSingleton) {
+    mVal->SetAnimValue(*static_cast<SVGNumberListAndInfo*>(aValue.mU.mPtr),
+                       mElement,
+                       mAttrEnum);
+  }
+  return NS_OK;
+}
+
+void
+SVGAnimatedNumberList::SMILAnimatedNumberList::ClearAnimValue()
+{
+  if (mVal->mAnimVal) {
+    mVal->ClearAnimValue(mElement, mAttrEnum);
+  }
+}
+#endif // MOZ_SMIL
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/SVGAnimatedNumberList.h
@@ -0,0 +1,151 @@
+/* -*- 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 Mozilla SVG Project code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 MOZILLA_SVGANIMATEDNUMBERLIST_H__
+#define MOZILLA_SVGANIMATEDNUMBERLIST_H__
+
+#include "SVGNumberList.h"
+
+class nsSVGElement;
+
+#ifdef MOZ_SMIL
+#include "nsISMILAttr.h"
+#endif // MOZ_SMIL
+
+namespace mozilla {
+
+/**
+ * Class SVGAnimatedNumberList
+ *
+ * This class is very different to the SVG DOM interface of the same name found
+ * in the SVG specification. This is a lightweight internal class - see
+ * DOMSVGAnimatedNumberList for the heavier DOM class that wraps instances of
+ * this class and implements the SVG specification's SVGAnimatedNumberList DOM
+ * interface.
+ *
+ * Except where noted otherwise, this class' methods take care of keeping the
+ * appropriate DOM wrappers in sync (see the comment in
+ * DOMSVGAnimatedNumberList::InternalBaseValListWillChangeTo) so that their
+ * consumers don't need to concern themselves with that.
+ */
+class SVGAnimatedNumberList
+{
+  // friends so that they can get write access to mBaseVal
+  friend class DOMSVGNumber;
+  friend class DOMSVGNumberList;
+
+public:
+  SVGAnimatedNumberList() {}
+
+  /**
+   * Because it's so important that mBaseVal and its DOMSVGNumberList wrapper
+   * (if any) be kept in sync (see the comment in
+   * DOMSVGAnimatedNumberList::InternalBaseValListWillChangeTo), this method
+   * returns a const reference. Only our friend classes may get mutable
+   * references to mBaseVal.
+   */
+  const SVGNumberList& GetBaseValue() const {
+    return mBaseVal;
+  }
+
+  nsresult SetBaseValueString(const nsAString& aValue);
+
+  void ClearBaseValue(PRUint32 aAttrEnum);
+
+  const SVGNumberList& GetAnimValue() const {
+    return mAnimVal ? *mAnimVal : mBaseVal;
+  }
+
+  nsresult SetAnimValue(const SVGNumberList& aValue,
+                        nsSVGElement *aElement,
+                        PRUint32 aAttrEnum);
+
+  void ClearAnimValue(nsSVGElement *aElement,
+                      PRUint32 aAttrEnum);
+
+  PRBool IsAnimating() const {
+    return !!mAnimVal;
+  }
+
+#ifdef MOZ_SMIL
+  /// Callers own the returned nsISMILAttr
+  nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement, PRUint8 aAttrEnum);
+#endif // MOZ_SMIL
+
+private:
+
+  // mAnimVal is a pointer to allow us to determine if we're being animated or
+  // not. Making it a non-pointer member and using mAnimVal.IsEmpty() to check
+  // if we're animating is not an option, since that would break animation *to*
+  // the empty string (<set to="">).
+
+  SVGNumberList mBaseVal;
+  nsAutoPtr<SVGNumberList> mAnimVal;
+
+#ifdef MOZ_SMIL
+  struct SMILAnimatedNumberList : public nsISMILAttr
+  {
+  public:
+    SMILAnimatedNumberList(SVGAnimatedNumberList* aVal,
+                           nsSVGElement* aSVGElement,
+                           PRUint8 aAttrEnum)
+      : mVal(aVal)
+      , mElement(aSVGElement)
+      , mAttrEnum(aAttrEnum)
+    {}
+
+    // These will stay alive because a nsISMILAttr only lives as long
+    // as the Compositing step, and DOM elements don't get a chance to
+    // die during that.
+    SVGAnimatedNumberList* mVal;
+    nsSVGElement* mElement;
+    PRUint8 mAttrEnum;
+
+    // nsISMILAttr methods
+    virtual nsresult ValueFromString(const nsAString& aStr,
+                                     const nsISMILAnimationElement* aSrcElement,
+                                     nsSMILValue& aValue,
+                                     PRBool& aPreventCachingOfSandwich) const;
+    virtual nsSMILValue GetBaseValue() const;
+    virtual void ClearAnimValue();
+    virtual nsresult SetAnimValue(const nsSMILValue& aValue);
+  };
+#endif // MOZ_SMIL
+};
+
+} // namespace mozilla
+
+#endif // MOZILLA_SVGANIMATEDNUMBERLIST_H__
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/SVGNumberList.cpp
@@ -0,0 +1,110 @@
+/* -*- 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 Mozilla SVG Project code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 "SVGNumberList.h"
+#include "SVGAnimatedNumberList.h"
+#include "nsSVGElement.h"
+#include "nsISVGValueUtils.h"
+#include "nsDOMError.h"
+#include "nsContentUtils.h"
+#include "nsString.h"
+#include "nsSVGUtils.h"
+#include "string.h"
+#include "prdtoa.h"
+#include "nsTextFormatter.h"
+#include "nsCharSeparatedTokenizer.h"
+
+using namespace mozilla;
+
+nsresult
+SVGNumberList::CopyFrom(const SVGNumberList& rhs)
+{
+  if (!mNumbers.SetCapacity(rhs.Length())) {
+    // Yes, we do want fallible alloc here
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  mNumbers = rhs.mNumbers;
+  return NS_OK;
+}
+
+void
+SVGNumberList::GetValueAsString(nsAString& aValue) const
+{
+  aValue.Truncate();
+  PRUnichar buf[24];
+  PRUint32 last = mNumbers.Length() - 1;
+  for (PRUint32 i = 0; i < mNumbers.Length(); ++i) {
+    // Would like to use aValue.AppendPrintf("%f", mNumbers[i]), but it's not
+    // possible to always avoid trailing zeros.
+    nsTextFormatter::snprintf(buf, NS_ARRAY_LENGTH(buf),
+                              NS_LITERAL_STRING("%g").get(),
+                              double(mNumbers[i]));
+    // We ignore OOM, since it's not useful for us to return an error.
+    aValue.Append(buf);
+    if (i != last) {
+      aValue.Append(' ');
+    }
+  }
+}
+
+nsresult
+SVGNumberList::SetValueFromString(const nsAString& aValue)
+{
+  SVGNumberList temp;
+
+  nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
+    tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
+
+  nsCAutoString str;  // outside loop to minimize memory churn
+
+  while (tokenizer.hasMoreTokens()) {
+    CopyUTF16toUTF8(tokenizer.nextToken(), str); // NS_ConvertUTF16toUTF8
+    const char *token = str.get();
+    if (token == '\0') {
+      return NS_ERROR_DOM_SYNTAX_ERR; // nothing between commas
+    }
+    char *end;
+    float num = float(PR_strtod(token, &end));
+    if (*end != '\0' || !NS_FloatIsFinite(num)) {
+      return NS_ERROR_DOM_SYNTAX_ERR;
+    }
+    temp.AppendItem(num);
+  }
+  if (tokenizer.lastTokenEndedWithSeparator()) {
+    return NS_ERROR_DOM_SYNTAX_ERR; // trailing comma
+  }
+  return CopyFrom(temp);
+}
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/SVGNumberList.h
@@ -0,0 +1,229 @@
+/* -*- 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 Mozilla SVG Project code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either 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 MOZILLA_SVGNUMBERLIST_H__
+#define MOZILLA_SVGNUMBERLIST_H__
+
+#include "nsTArray.h"
+#include "nsSVGElement.h"
+
+namespace mozilla {
+
+/**
+ * ATTENTION! WARNING! WATCH OUT!!
+ *
+ * Consumers that modify objects of this type absolutely MUST keep the DOM
+ * wrappers for those lists (if any) in sync!! That's why this class is so
+ * locked down.
+ *
+ * The DOM wrapper class for this class is DOMSVGNumberList.
+ */
+class SVGNumberList
+{
+  friend class SVGAnimatedNumberList;
+  friend class DOMSVGNumberList;
+  friend class DOMSVGNumber;
+
+public:
+
+  SVGNumberList(){}
+  ~SVGNumberList(){}
+
+  // Only methods that don't make/permit modification to this list are public.
+  // Only our friend classes can access methods that may change us.
+
+  /// This may return an incomplete string on OOM, but that's acceptable.
+  void GetValueAsString(nsAString& aValue) const;
+
+  PRBool IsEmpty() const {
+    return mNumbers.IsEmpty();
+  }
+
+  PRUint32 Length() const {
+    return mNumbers.Length();
+  }
+
+  const float& operator[](PRUint32 aIndex) const {
+    return mNumbers[aIndex];
+  }
+
+  PRBool operator==(const SVGNumberList& rhs) const {
+    return mNumbers == rhs.mNumbers;
+  }
+
+  PRBool SetCapacity(PRUint32 size) {
+    return mNumbers.SetCapacity(size);
+  }
+
+  void Compact() {
+    mNumbers.Compact();
+  }
+
+  // Access to methods that can modify objects of this type is deliberately
+  // limited. This is to reduce the chances of someone modifying objects of
+  // this type without taking the necessary steps to keep DOM wrappers in sync.
+  // If you need wider access to these methods, consider adding a method to
+  // SVGAnimatedNumberList and having that class act as an intermediary so it
+  // can take care of keeping DOM wrappers in sync.
+
+protected:
+
+  /**
+   * This may fail on OOM if the internal capacity needs to be increased, in
+   * which case the list will be left unmodified.
+   */
+  nsresult CopyFrom(const SVGNumberList& rhs);
+
+  float& operator[](PRUint32 aIndex) {
+    return mNumbers[aIndex];
+  }
+
+  /**
+   * This may fail (return PR_FALSE) on OOM if the internal capacity is being
+   * increased, in which case the list will be left unmodified.
+   */
+  PRBool SetLength(PRUint32 aNumberOfItems) {
+    return mNumbers.SetLength(aNumberOfItems);
+  }
+
+private:
+
+  // Marking the following private only serves to show which methods are only
+  // used by our friend classes (as opposed to our subclasses) - it doesn't
+  // really provide additional safety.
+
+  nsresult SetValueFromString(const nsAString& aValue);
+
+  void Clear() {
+    mNumbers.Clear();
+  }
+
+  PRBool InsertItem(PRUint32 aIndex, const float &aNumber) {
+    if (aIndex >= mNumbers.Length()) {
+      aIndex = mNumbers.Length();
+    }
+    return !!mNumbers.InsertElementAt(aIndex, aNumber);
+  }
+
+  void ReplaceItem(PRUint32 aIndex, const float &aNumber) {
+    NS_ASSERTION(aIndex < mNumbers.Length(),
+                 "DOM wrapper caller should have raised INDEX_SIZE_ERR");
+    mNumbers[aIndex] = aNumber;
+  }
+
+  void RemoveItem(PRUint32 aIndex) {
+    NS_ASSERTION(aIndex < mNumbers.Length(),
+                 "DOM wrapper caller should have raised INDEX_SIZE_ERR");
+    mNumbers.RemoveElementAt(aIndex);
+  }
+
+  PRBool AppendItem(float aNumber) {
+    return !!mNumbers.AppendElement(aNumber);
+  }
+
+protected:
+
+  /* See SVGLengthList for the rationale for using nsTArray<float> instead
+   * of nsTArray<float, 1>.
+   */
+  nsTArray<float> mNumbers;
+};
+
+
+/**
+ * This SVGNumberList subclass is used by the SMIL code when a number list
+ * is to be stored in an nsISMILValue instance. Since nsISMILValue objects may
+ * be cached, it is necessary for us to hold a strong reference to our element
+ * so that it doesn't disappear out from under us if, say, the element is
+ * removed from the DOM tree.
+ */
+class SVGNumberListAndInfo : public SVGNumberList
+{
+public:
+
+  SVGNumberListAndInfo()
+    : mElement(nsnull)
+  {}
+
+  SVGNumberListAndInfo(nsSVGElement *aElement)
+    : mElement(aElement)
+  {}
+
+  void SetInfo(nsSVGElement *aElement) {
+    mElement = aElement;
+  }
+
+  nsSVGElement* Element() const {
+    return mElement; // .get();
+  }
+
+  nsresult CopyFrom(const SVGNumberListAndInfo& rhs) {
+    mElement = rhs.mElement;
+    return SVGNumberList::CopyFrom(rhs);
+  }
+
+  // Instances of this special subclass do not have DOM wrappers that we need
+  // to worry about keeping in sync, so it's safe to expose any hidden base
+  // class methods required by the SMIL code, as we do below.
+
+  /**
+   * Exposed so that SVGNumberList baseVals can be copied to
+   * SVGNumberListAndInfo objects. Note that callers should also call
+   * SetInfo() when using this method!
+   */
+  nsresult CopyFrom(const SVGNumberList& rhs) {
+    return SVGNumberList::CopyFrom(rhs);
+  }
+  const float& operator[](PRUint32 aIndex) const {
+    return SVGNumberList::operator[](aIndex);
+  }
+  float& operator[](PRUint32 aIndex) {
+    return SVGNumberList::operator[](aIndex);
+  }
+  PRBool SetLength(PRUint32 aNumberOfItems) {
+    return SVGNumberList::SetLength(aNumberOfItems);
+  }
+
+private:
+  // We must keep a strong reference to our element because we may belong to a
+  // cached baseVal nsSMILValue. See the comments starting at:
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=515116#c15
+  nsRefPtr<nsSVGElement> mElement;
+};
+
+} // namespace mozilla
+
+#endif // MOZILLA_SVGNUMBERLIST_H__
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/SVGNumberListSMILType.cpp
@@ -0,0 +1,243 @@
+/* -*- 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 the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 "SVGNumberListSMILType.h"
+#include "nsSMILValue.h"
+#include "SVGNumberList.h"
+#include <math.h>
+
+/* The "identity" number list for a given number list attribute (the effective
+ * number list that is used if an attribute value is not specified) varies
+ * widely for different number list attributes, and can depend on the value of
+ * other attributes on the same element:
+ *
+ * http://www.w3.org/TR/SVG11/filters.html#feColorMatrixValuesAttribute
+ * http://www.w3.org/TR/SVG11/filters.html#feComponentTransferTableValuesAttribute
+ * http://www.w3.org/TR/SVG11/filters.html#feConvolveMatrixElementKernelMatrixAttribute
+ * http://www.w3.org/TR/SVG11/text.html#TextElementRotateAttribute
+ *
+ * Note that we don't need to worry about that variation here, however. The way
+ * that the SMIL engine creates and composites sandwich layers together allows
+ * us to treat "identity" nsSMILValue objects as a number list of zeros. Such
+ * identity nsSMILValues are identified by the fact that their
+ # SVGNumberListAndInfo has not been given an element yet.
+ */
+
+using namespace mozilla;
+
+/*static*/ SVGNumberListSMILType SVGNumberListSMILType::sSingleton;
+
+//----------------------------------------------------------------------
+// nsISMILType implementation
+
+void
+SVGNumberListSMILType::Init(nsSMILValue &aValue) const
+{
+  NS_ABORT_IF_FALSE(aValue.IsNull(), "Unexpected value type");
+
+  SVGNumberListAndInfo* numberList = new SVGNumberListAndInfo();
+
+  aValue.mU.mPtr = numberList;
+  aValue.mType = this;
+}
+
+void
+SVGNumberListSMILType::Destroy(nsSMILValue& aValue) const
+{
+  NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value type");
+  delete static_cast<SVGNumberListAndInfo*>(aValue.mU.mPtr);
+  aValue.mU.mPtr = nsnull;
+  aValue.mType = &nsSMILNullType::sSingleton;
+}
+
+nsresult
+SVGNumberListSMILType::Assign(nsSMILValue& aDest,
+                              const nsSMILValue& aSrc) const
+{
+  NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
+  NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
+
+  const SVGNumberListAndInfo* src =
+    static_cast<const SVGNumberListAndInfo*>(aSrc.mU.mPtr);
+  SVGNumberListAndInfo* dest =
+    static_cast<SVGNumberListAndInfo*>(aDest.mU.mPtr);
+
+  return dest->CopyFrom(*src);
+}
+
+PRBool
+SVGNumberListSMILType::IsEqual(const nsSMILValue& aLeft,
+                               const nsSMILValue& aRight) const
+{
+  NS_PRECONDITION(aLeft.mType == aRight.mType, "Incompatible SMIL types");
+  NS_PRECONDITION(aLeft.mType == this, "Unexpected type for SMIL value");
+
+  return *static_cast<const SVGNumberListAndInfo*>(aLeft.mU.mPtr) ==
+         *static_cast<const SVGNumberListAndInfo*>(aRight.mU.mPtr);
+}
+
+nsresult
+SVGNumberListSMILType::Add(nsSMILValue& aDest,
+                           const nsSMILValue& aValueToAdd,
+                           PRUint32 aCount) const
+{
+  NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL type");
+  NS_PRECONDITION(aValueToAdd.mType == this, "Incompatible SMIL type");
+
+  SVGNumberListAndInfo& dest =
+    *static_cast<SVGNumberListAndInfo*>(aDest.mU.mPtr);
+  const SVGNumberListAndInfo& valueToAdd =
+    *static_cast<const SVGNumberListAndInfo*>(aValueToAdd.mU.mPtr);
+
+  NS_ABORT_IF_FALSE(dest.Element() || valueToAdd.Element(),
+                    "Target element propagation failure");
+
+  if (!valueToAdd.Element()) {
+    NS_ABORT_IF_FALSE(valueToAdd.Length() == 0,
+                      "Not identity value - target element propagation failure");
+    return NS_OK;
+  }
+  if (!dest.Element()) {
+    NS_ABORT_IF_FALSE(dest.Length() == 0,
+                      "Not identity value - target element propagation failure");
+    if (!dest.SetLength(valueToAdd.Length())) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+    for (PRUint32 i = 0; i < dest.Length(); ++i) {
+      dest[i] = aCount * valueToAdd[i];
+    }
+    dest.SetInfo(valueToAdd.Element()); // propagate target element info!
+    return NS_OK;
+  }
+  NS_ABORT_IF_FALSE(dest.Element() == valueToAdd.Element(),
+                    "adding values from different elements...?");
+  if (dest.Length() != valueToAdd.Length()) {
+    // For now we only support animation between lists with the same number of
+    // items. nsSVGUtils::ReportToConsole
+    return NS_ERROR_FAILURE;
+  }
+  for (PRUint32 i = 0; i < dest.Length(); ++i) {
+    dest[i] += aCount * valueToAdd[i];
+  }
+  dest.SetInfo(valueToAdd.Element()); // propagate target element info!
+  return NS_OK;
+}
+
+nsresult
+SVGNumberListSMILType::ComputeDistance(const nsSMILValue& aFrom,
+                                       const nsSMILValue& aTo,
+                                       double& aDistance) const
+{
+  NS_PRECONDITION(aFrom.mType == this, "Unexpected SMIL type");
+  NS_PRECONDITION(aTo.mType == this, "Incompatible SMIL type");
+
+  const SVGNumberListAndInfo& from =
+    *static_cast<const SVGNumberListAndInfo*>(aFrom.mU.mPtr);
+  const SVGNumberListAndInfo& to =
+    *static_cast<const SVGNumberListAndInfo*>(aTo.mU.mPtr);
+
+  if (from.Length() != to.Length()) {
+    // Lists in the 'values' attribute must have the same length.
+    // nsSVGUtils::ReportToConsole
+    aDistance = 0.0;
+    return NS_ERROR_FAILURE;
+  }
+
+  // We return the root of the sum of the squares of the delta between the
+  // numbers at each correspanding index.
+
+  double total = 0.0;
+
+  for (PRUint32 i = 0; i < to.Length(); ++i) {
+    double delta = to[i] - from[i];
+    total += delta * delta;
+  }
+  double distance = sqrt(total);
+  if (!NS_FloatIsFinite(distance)) {
+    return NS_ERROR_FAILURE;
+  }
+  aDistance = distance;
+
+  return NS_OK;
+}
+
+nsresult
+SVGNumberListSMILType::Interpolate(const nsSMILValue& aStartVal,
+                                   const nsSMILValue& aEndVal,
+                                   double aUnitDistance,
+                                   nsSMILValue& aResult) const
+{
+  NS_PRECONDITION(aStartVal.mType == aEndVal.mType,
+                  "Trying to interpolate different types");
+  NS_PRECONDITION(aStartVal.mType == this,
+                  "Unexpected types for interpolation");
+  NS_PRECONDITION(aResult.mType == this, "Unexpected result type");
+
+  const SVGNumberListAndInfo& start =
+    *static_cast<const SVGNumberListAndInfo*>(aStartVal.mU.mPtr);
+  const SVGNumberListAndInfo& end =
+    *static_cast<const SVGNumberListAndInfo*>(aEndVal.mU.mPtr);
+  SVGNumberListAndInfo& result =
+    *static_cast<SVGNumberListAndInfo*>(aResult.mU.mPtr);
+
+  NS_ABORT_IF_FALSE(end.Element(), "Can't propagate target element");
+  NS_ABORT_IF_FALSE(start.Element() == end.Element() || !start.Element(),
+                    "Different target elements");
+
+  if (start.Element() && // 'start' is not an "identity" value
+      start.Length() != end.Length()) {
+    // For now we only support animation between lists of the same length.
+    // nsSVGUtils::ReportToConsole
+    return NS_ERROR_FAILURE;
+  }
+  if (!result.SetLength(end.Length())) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  result.SetInfo(end.Element()); // propagate target element info!
+
+  if (start.Length() != end.Length()) {
+    NS_ABORT_IF_FALSE(start.Length() == 0, "Not an identity value");
+    for (PRUint32 i = 0; i < end.Length(); ++i) {
+      result[i] = aUnitDistance * end[i];
+    }
+    return NS_OK;
+  }
+  for (PRUint32 i = 0; i < end.Length(); ++i) {
+    result[i] = start[i] + (end[i] - start[i]) * aUnitDistance;
+  }
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/SVGNumberListSMILType.h
@@ -0,0 +1,86 @@
+/* -*- 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 the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 MOZILLA_SVGNUMBERLISTSMILTYPE_H_
+#define MOZILLA_SVGNUMBERLISTSMILTYPE_H_
+
+#include "nsISMILType.h"
+
+class nsSMILValue;
+
+namespace mozilla {
+
+////////////////////////////////////////////////////////////////////////
+// SVGNumberListSMILType
+//
+// Operations for animating an SVGNumberList.
+//
+class SVGNumberListSMILType : public nsISMILType
+{
+public:
+  // Singleton for nsSMILValue objects to hold onto.
+  static SVGNumberListSMILType sSingleton;
+
+protected:
+  // nsISMILType Methods
+  // -------------------
+
+  virtual void     Init(nsSMILValue& aValue) const;
+
+  virtual void     Destroy(nsSMILValue& aValue) const;
+  virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const;
+  virtual PRBool   IsEqual(const nsSMILValue& aLeft,
+                           const nsSMILValue& aRight) const;
+  virtual nsresult Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
+                       PRUint32 aCount) const;
+  virtual nsresult ComputeDistance(const nsSMILValue& aFrom,
+                                   const nsSMILValue& aTo,
+                                   double& aDistance) const;
+  virtual nsresult Interpolate(const nsSMILValue& aStartVal,
+                               const nsSMILValue& aEndVal,
+                               double aUnitDistance,
+                               nsSMILValue& aResult) const;
+
+private:
+  // Private constructor & destructor: prevent instances beyond my singleton,
+  // and prevent others from deleting my singleton.
+  SVGNumberListSMILType() {}
+  ~SVGNumberListSMILType() {}
+};
+
+} // namespace mozilla
+
+#endif // MOZILLA_SVGNUMBERLISTSMILTYPE_H_
deleted file mode 100644
--- a/content/svg/content/src/nsSVGAnimatedNumberList.cpp
+++ /dev/null
@@ -1,212 +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
- * Scooter Morris.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Scooter Morris <scootermorris@comcast.net> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either 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 "nsSVGAnimatedNumberList.h"
-#include "nsSVGNumberList.h"
-#include "nsSVGValue.h"
-#include "nsWeakReference.h"
-#include "nsContentUtils.h"
-
-////////////////////////////////////////////////////////////////////////
-// nsSVGAnimatedNumberList
-
-class nsSVGAnimatedNumberList : public nsIDOMSVGAnimatedNumberList,
-                                public nsSVGValue,
-                                public nsISVGValueObserver
-{  
-protected:
-  friend nsresult
-  NS_NewSVGAnimatedNumberList(nsIDOMSVGAnimatedNumberList** result,
-                              nsIDOMSVGNumberList* aBaseVal);
-
-  nsSVGAnimatedNumberList();
-  ~nsSVGAnimatedNumberList();
-  nsresult Init(nsIDOMSVGNumberList* aBaseVal);
-  
-public:
-  // nsISupports interface:
-  NS_DECL_ISUPPORTS
-
-  // nsIDOMSVGAnimatedNumberList interface:
-  NS_DECL_NSIDOMSVGANIMATEDNUMBERLIST
-
-  // remainder of nsISVGValue interface:
-  NS_IMETHOD SetValueString(const nsAString& aValue);
-  NS_IMETHOD GetValueString(nsAString& aValue);
-
-  // nsISVGValueObserver
-  NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable,
-                                     modificationType aModType);
-  NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
-                                     modificationType aModType);
-  
-  // nsISupportsWeakReference
-  // implementation inherited from nsSupportsWeakReference
-  
-protected:
-  nsCOMPtr<nsIDOMSVGNumberList> mBaseVal;
-};
-
-
-//----------------------------------------------------------------------
-// Implementation
-
-nsSVGAnimatedNumberList::nsSVGAnimatedNumberList()
-{
-}
-
-nsSVGAnimatedNumberList::~nsSVGAnimatedNumberList()
-{
-  nsCOMPtr<nsISVGValue> val = do_QueryInterface(mBaseVal);
-  if (val)
-    val->RemoveObserver(this);
-}
-
-nsresult
-nsSVGAnimatedNumberList::Init(nsIDOMSVGNumberList* aBaseVal)
-{
-  mBaseVal = aBaseVal;
-  if (!mBaseVal) return NS_ERROR_FAILURE;
-  nsCOMPtr<nsISVGValue> val = do_QueryInterface(mBaseVal);
-  if (!val) return NS_ERROR_FAILURE;
-  val->AddObserver(this);
-  return NS_OK;
-}
-
-//----------------------------------------------------------------------
-// nsISupports methods:
-
-NS_IMPL_ADDREF(nsSVGAnimatedNumberList)
-NS_IMPL_RELEASE(nsSVGAnimatedNumberList)
-
-DOMCI_DATA(SVGAnimatedNumberList, nsSVGAnimatedNumberList)
-
-NS_INTERFACE_MAP_BEGIN(nsSVGAnimatedNumberList)
-  NS_INTERFACE_MAP_ENTRY(nsISVGValue)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedNumberList)
-  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-  NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedNumberList)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
-NS_INTERFACE_MAP_END
-
-
-//----------------------------------------------------------------------
-// nsISVGValue methods:
-
-NS_IMETHODIMP
-nsSVGAnimatedNumberList::SetValueString(const nsAString& aValue)
-{
-  nsCOMPtr<nsISVGValue> value = do_QueryInterface(mBaseVal);
-  NS_ASSERTION(value, "value doesn't support SVGValue interfaces");
-  return value->SetValueString(aValue);
-}
-
-NS_IMETHODIMP
-nsSVGAnimatedNumberList::GetValueString(nsAString& aValue)
-{
-  nsCOMPtr<nsISVGValue> value = do_QueryInterface(mBaseVal);
-  NS_ASSERTION(value, "value doesn't support SVGValue interfaces");
-  return value->GetValueString(aValue);
-}
-
-//----------------------------------------------------------------------
-// nsIDOMSVGAnimatedNumberList methods:
-
-/* readonly attribute nsIDOMSVGNumberList aBaseVal; */
-NS_IMETHODIMP
-nsSVGAnimatedNumberList::GetBaseVal(nsIDOMSVGNumberList * *aBaseVal)
-{
-  *aBaseVal = mBaseVal;
-  NS_ADDREF(*aBaseVal);
-  return NS_OK;
-}
-
-/* readonly attribute nsIDOMSVGNumberList animVal; */
-NS_IMETHODIMP
-nsSVGAnimatedNumberList::GetAnimVal(nsIDOMSVGNumberList * *aAnimVal)
-{
-  *aAnimVal = mBaseVal;
-  NS_ADDREF(*aAnimVal);
-  return NS_OK;
-}
-
-//----------------------------------------------------------------------
-// nsISVGValueObserver methods
-
-NS_IMETHODIMP
-nsSVGAnimatedNumberList::WillModifySVGObservable(nsISVGValue* observable,
-                                                 modificationType aModType)
-{
-  WillModify(aModType);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSVGAnimatedNumberList::DidModifySVGObservable (nsISVGValue* observable,
-                                                 modificationType aModType)
-{
-  DidModify(aModType);
-  return NS_OK;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-// Exported creation functions:
-
-nsresult
-NS_NewSVGAnimatedNumberList(nsIDOMSVGAnimatedNumberList** result,
-                            nsIDOMSVGNumberList* aBaseVal)
-{
-  *result = nsnull;
-  
-  nsSVGAnimatedNumberList* animatedNumberList = new nsSVGAnimatedNumberList();
-  if (!animatedNumberList) return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(animatedNumberList);
-
-  if (NS_FAILED(animatedNumberList->Init(aBaseVal))) {
-    NS_RELEASE(animatedNumberList);
-    return NS_ERROR_FAILURE;
-  }
-  
-  *result = (nsIDOMSVGAnimatedNumberList*) animatedNumberList;
-  
-  return NS_OK;
-}
-
-
deleted file mode 100644
--- a/content/svg/content/src/nsSVGAnimatedNumberList.h
+++ /dev/null
@@ -1,51 +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
- * Scooter Morris.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Scooter Morris <scootermorris@comcast.net> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either 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_SVGANIMATEDNUMBERLIST_H__
-#define __NS_SVGANIMATEDNUMBERLIST_H__
-
-#include "nsIDOMSVGAnimatedNumberList.h"
-#include "nsIDOMSVGNumberList.h"
-
-nsresult
-NS_NewSVGAnimatedNumberList(nsIDOMSVGAnimatedNumberList** result,
-                            nsIDOMSVGNumberList* baseVal);
-
-#endif //__NS_SVGANIMATEDNUMBERLIST_H__
-
-
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -69,21 +69,20 @@
 #include "nsSVGLength2.h"
 #include "nsSVGNumber2.h"
 #include "nsSVGInteger.h"
 #include "nsSVGAngle.h"
 #include "nsSVGBoolean.h"
 #include "nsSVGEnum.h"
 #include "nsSVGViewBox.h"
 #include "nsSVGString.h"
+#include "SVGAnimatedNumberList.h"
 #include "SVGAnimatedLengthList.h"
 #include "SVGAnimatedPathSegList.h"
 #include "nsIDOMSVGUnitTypes.h"
-#include "nsIDOMSVGNumberList.h"
-#include "nsIDOMSVGAnimatedNumberList.h"
 #include "nsIDOMSVGPointList.h"
 #include "nsIDOMSVGAnimatedPoints.h"
 #include "nsIDOMSVGTransformList.h"
 #include "nsIDOMSVGAnimTransformList.h"
 #include "nsIDOMSVGAnimatedRect.h"
 #include "nsIDOMSVGGradientElement.h"
 #include "nsIDOMSVGPatternElement.h"
 #include "nsSVGRect.h"
@@ -175,16 +174,22 @@ nsSVGElement::Init()
   }
 
   LengthListAttributesInfo lengthListInfo = GetLengthListInfo();
 
   for (i = 0; i < lengthListInfo.mLengthListCount; i++) {
     lengthListInfo.Reset(i);
   }
 
+  NumberListAttributesInfo numberListInfo = GetNumberListInfo();
+
+  for (i = 0; i < numberListInfo.mNumberListCount; i++) {
+    numberListInfo.Reset(i);
+  }
+
   // No need to reset SVGPathData since the default value in always the same
   // (an empty list).
 
   StringAttributesInfo stringInfo = GetStringInfo();
 
   for (i = 0; i < stringInfo.mStringCount; i++) {
     stringInfo.Reset(i);
   }
@@ -363,26 +368,42 @@ nsSVGElement::ParseAttribute(PRInt32 aNa
 
     if (!foundMatch) {
       // Check for SVGAnimatedLengthList attribute
       LengthListAttributesInfo lengthListInfo = GetLengthListInfo();
       for (i = 0; i < lengthListInfo.mLengthListCount; i++) {
         if (aAttribute == *lengthListInfo.mLengthListInfo[i].mName) {
           rv = lengthListInfo.mLengthLists[i].SetBaseValueString(aValue);
           if (NS_FAILED(rv)) {
-            // ReportToConsole
+            ReportAttributeParseFailure(GetOwnerDoc(), aAttribute, aValue);
             lengthListInfo.Reset(i);
           }
           foundMatch = PR_TRUE;
           break;
         }
       }
     }
 
     if (!foundMatch) {
+      // Check for SVGAnimatedNumberList attribute
+      NumberListAttributesInfo numberListInfo = GetNumberListInfo();
+      for (i = 0; i < numberListInfo.mNumberListCount; i++) {
+        if (aAttribute == *numberListInfo.mNumberListInfo[i].mName) {
+          rv = numberListInfo.mNumberLists[i].SetBaseValueString(aValue);
+          if (NS_FAILED(rv)) {
+            ReportAttributeParseFailure(GetOwnerDoc(), aAttribute, aValue);
+            numberListInfo.Reset(i);
+          }
+          foundMatch = PR_TRUE;
+          break;
+        }
+      }
+    }
+
+    if (!foundMatch) {
       // Check for SVGAnimatedPathSegList attribute
       if (GetPathDataAttrName() == aAttribute) {
         SVGAnimatedPathSegList* segList = GetAnimPathSegList();
         if (segList) {
           rv = segList->SetBaseValueString(aValue);
           if (NS_FAILED(rv)) {
             ReportAttributeParseFailure(GetOwnerDoc(), aAttribute, aValue);
             // The spec says we parse everything up to the failure, so we don't
@@ -584,16 +605,30 @@ nsSVGElement::UnsetAttr(PRInt32 aNamespa
           DidChangeLengthList(i, PR_FALSE);
           foundMatch = PR_TRUE;
           break;
         }
       }
     }
 
     if (!foundMatch) {
+      // Check if this is a number list attribute going away
+      NumberListAttributesInfo numberListInfo = GetNumberListInfo();
+
+      for (PRUint32 i = 0; i < numberListInfo.mNumberListCount; i++) {
+        if (aName == *numberListInfo.mNumberListInfo[i].mName) {
+          numberListInfo.Reset(i);
+          DidChangeNumberList(i, PR_FALSE);
+          foundMatch = PR_TRUE;
+          break;
+        }
+      }
+    }
+
+    if (!foundMatch) {
       // Check if this is a path segment list attribute going away
       if (GetPathDataAttrName() == aName) {
         SVGAnimatedPathSegList *segList = GetAnimPathSegList();
         if (segList) {
           segList->ClearBaseValue();
           DidChangePathSegList(PR_FALSE);
           foundMatch = PR_TRUE;
         }
@@ -731,22 +766,16 @@ nsSVGElement::UnsetAttr(PRInt32 aNamespa
   }
 
   return rv;
 }
 
 void
 nsSVGElement::ResetOldStyleBaseType(nsISVGValue *svg_value)
 {
-  nsCOMPtr<nsIDOMSVGAnimatedNumberList> nl = do_QueryInterface(svg_value);
-  if (nl) {
-    nsCOMPtr<nsIDOMSVGNumberList> numberlist;
-    nl->GetBaseVal(getter_AddRefs(numberlist));
-    numberlist->Clear();
-  }
   nsCOMPtr<nsIDOMSVGAnimatedTransformList> tl = do_QueryInterface(svg_value);
   if (tl) {
     nsCOMPtr<nsIDOMSVGTransformList> transform;
     tl->GetBaseVal(getter_AddRefs(transform));
     transform->Clear();
   }
 }
 
@@ -1574,16 +1603,88 @@ nsSVGElement::GetAnimatedLengthList(PRUi
   if (aAttrEnum < info.mLengthListCount) {
     return &(info.mLengthLists[aAttrEnum]);
   }
   NS_NOTREACHED("Bad attrEnum");
   return nsnull;
 }
 
 
+nsSVGElement::NumberListAttributesInfo
+nsSVGElement::GetNumberListInfo()
+{
+  return NumberListAttributesInfo(nsnull, nsnull, 0);
+}
+
+void
+nsSVGElement::NumberListAttributesInfo::Reset(PRUint8 aAttrEnum)
+{
+  NS_ABORT_IF_FALSE(aAttrEnum < mNumberListCount, "Bad attr enum");
+  mNumberLists[aAttrEnum].ClearBaseValue(aAttrEnum);
+  // caller notifies
+}
+
+void
+nsSVGElement::DidChangeNumberList(PRUint8 aAttrEnum, PRBool aDoSetAttr)
+{
+  if (!aDoSetAttr)
+    return;
+
+  NumberListAttributesInfo info = GetNumberListInfo();
+
+  NS_ABORT_IF_FALSE(info.mNumberListCount > 0,
+                    "DidChangeNumberList on element with no number list attribs");
+  NS_ABORT_IF_FALSE(aAttrEnum < info.mNumberListCount, "aAttrEnum out of range");
+
+  nsAutoString newStr;
+  info.mNumberLists[aAttrEnum].GetBaseValue().GetValueAsString(newStr);
+
+  SetAttr(kNameSpaceID_None, *info.mNumberListInfo[aAttrEnum].mName,
+          newStr, PR_TRUE);
+}
+
+void
+nsSVGElement::DidAnimateNumberList(PRUint8 aAttrEnum)
+{
+  nsIFrame* frame = GetPrimaryFrame();
+
+  if (frame) {
+    NumberListAttributesInfo info = GetNumberListInfo();
+    NS_ABORT_IF_FALSE(aAttrEnum < info.mNumberListCount, "aAttrEnum out of range");
+
+    frame->AttributeChanged(kNameSpaceID_None,
+                            *info.mNumberListInfo[aAttrEnum].mName,
+                            nsIDOMMutationEvent::MODIFICATION);
+  }
+}
+
+SVGAnimatedNumberList*
+nsSVGElement::GetAnimatedNumberList(PRUint8 aAttrEnum)
+{
+  NumberListAttributesInfo info = GetNumberListInfo();
+  if (aAttrEnum < info.mNumberListCount) {
+    return &(info.mNumberLists[aAttrEnum]);
+  }
+  NS_ABORT_IF_FALSE(PR_FALSE, "Bad attrEnum");
+  return nsnull;
+}
+
+SVGAnimatedNumberList*
+nsSVGElement::GetAnimatedNumberList(nsIAtom *aAttrName)
+{
+  NumberListAttributesInfo info = GetNumberListInfo();
+  for (PRUint32 i = 0; i < info.mNumberListCount; i++) {
+    if (aAttrName == *info.mNumberListInfo[i].mName) {
+      return &info.mNumberLists[i];
+    }
+  }
+  NS_ABORT_IF_FALSE(PR_FALSE, "Bad caller");
+  return nsnull;
+}
+
 void
 nsSVGElement::DidChangePathSegList(PRBool aDoSetAttr)
 {
   NS_ABORT_IF_FALSE(GetPathDataAttrName(), "Changing non-existant path data?");
 
   if (!aDoSetAttr)
     return;
 
@@ -2246,16 +2347,27 @@ nsSVGElement::GetAnimatedAttr(PRInt32 aN
     }
 
     // preserveAspectRatio:
     if (aName == nsGkAtoms::preserveAspectRatio) {
       nsSVGPreserveAspectRatio *preserveAspectRatio = GetPreserveAspectRatio();
       return preserveAspectRatio ? preserveAspectRatio->ToSMILAttr(this) : nsnull;
     }
 
+    // NumberLists:
+    {
+      NumberListAttributesInfo info = GetNumberListInfo();
+      for (PRUint32 i = 0; i < info.mNumberListCount; i++) {
+        if (aName == *info.mNumberListInfo[i].mName) {
+          NS_ABORT_IF_FALSE(i <= UCHAR_MAX, "Too many attributes");
+          return info.mNumberLists[i].ToSMILAttr(this, PRUint8(i));
+        }
+      }
+    }
+
     // LengthLists:
     {
       LengthListAttributesInfo info = GetLengthListInfo();
       for (PRUint32 i = 0; i < info.mLengthListCount; i++) {
         if (aName == *info.mLengthListInfo[i].mName) {
           NS_ABORT_IF_FALSE(i <= UCHAR_MAX, "Too many attributes");
           return info.mLengthLists[i].ToSMILAttr(this,
                                                  PRUint8(i),
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -67,32 +67,36 @@ class nsSVGAngle;
 class nsSVGBoolean;
 class nsSVGEnum;
 struct nsSVGEnumMapping;
 class nsSVGViewBox;
 class nsSVGPreserveAspectRatio;
 class nsSVGString;
 struct gfxMatrix;
 namespace mozilla {
+class SVGAnimatedNumberList;
+class SVGNumberList;
 class SVGAnimatedLengthList;
 class SVGUserUnitList;
 class SVGAnimatedPathSegList;
 }
 
 typedef nsStyledElement nsSVGElementBase;
 
 class nsSVGElement : public nsSVGElementBase,    // nsIContent
                      public nsISVGValueObserver  // :nsISupportsWeakReference
 {
 protected:
   nsSVGElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   nsresult Init();
   virtual ~nsSVGElement();
 
 public:
+  typedef mozilla::SVGNumberList SVGNumberList;
+  typedef mozilla::SVGAnimatedNumberList SVGAnimatedNumberList;
   typedef mozilla::SVGUserUnitList SVGUserUnitList;
   typedef mozilla::SVGAnimatedLengthList SVGAnimatedLengthList;
   typedef mozilla::SVGAnimatedPathSegList SVGAnimatedPathSegList;
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIContent interface methods
@@ -166,36 +170,40 @@ public:
   virtual void DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeNumber(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeInteger(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeAngle(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeBoolean(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeEnum(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeViewBox(PRBool aDoSetAttr);
   virtual void DidChangePreserveAspectRatio(PRBool aDoSetAttr);
+  virtual void DidChangeNumberList(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeLengthList(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangePathSegList(PRBool aDoSetAttr);
   virtual void DidChangeString(PRUint8 aAttrEnum) {}
 
   virtual void DidAnimateLength(PRUint8 aAttrEnum);
   virtual void DidAnimateNumber(PRUint8 aAttrEnum);
   virtual void DidAnimateInteger(PRUint8 aAttrEnum);
   virtual void DidAnimateAngle(PRUint8 aAttrEnum);
   virtual void DidAnimateBoolean(PRUint8 aAttrEnum);
   virtual void DidAnimateEnum(PRUint8 aAttrEnum);
   virtual void DidAnimateViewBox();
   virtual void DidAnimatePreserveAspectRatio();
+  virtual void DidAnimateNumberList(PRUint8 aAttrEnum);
   virtual void DidAnimateLengthList(PRUint8 aAttrEnum);
   virtual void DidAnimatePathSegList();
   virtual void DidAnimateTransform();
   virtual void DidAnimateString(PRUint8 aAttrEnum);
 
   void GetAnimatedLengthValues(float *aFirst, ...);
   void GetAnimatedNumberValues(float *aFirst, ...);
   void GetAnimatedIntegerValues(PRInt32 *aFirst, ...);
+  SVGAnimatedNumberList* GetAnimatedNumberList(PRUint8 aAttrEnum);
+  SVGAnimatedNumberList* GetAnimatedNumberList(nsIAtom *aAttrName);
   void GetAnimatedLengthListValues(SVGUserUnitList *aFirst, ...);
   SVGAnimatedLengthList* GetAnimatedLengthList(PRUint8 aAttrEnum);
   virtual SVGAnimatedPathSegList* GetAnimPathSegList() {
     // DOM interface 'SVGAnimatedPathData' (*inherited* by nsSVGPathElement)
     // has a member called 'animatedPathSegList' member, so we have a shorter
     // name so we don't get hidden by the GetAnimatedPathSegList declared by
     // NS_DECL_NSIDOMSVGANIMATEDPATHDATA.
     return nsnull;
@@ -358,16 +366,36 @@ protected:
                        EnumInfo *aEnumInfo,
                        PRUint32 aEnumCount) :
       mEnums(aEnums), mEnumInfo(aEnumInfo), mEnumCount(aEnumCount)
       {}
 
     void Reset(PRUint8 aAttrEnum);
   };
 
+  struct NumberListInfo {
+    nsIAtom** mName;
+  };
+
+  struct NumberListAttributesInfo {
+    SVGAnimatedNumberList* mNumberLists;
+    NumberListInfo*        mNumberListInfo;
+    PRUint32               mNumberListCount;
+
+    NumberListAttributesInfo(SVGAnimatedNumberList *aNumberLists,
+                             NumberListInfo *aNumberListInfo,
+                             PRUint32 aNumberListCount)
+      : mNumberLists(aNumberLists)
+      , mNumberListInfo(aNumberListInfo)
+      , mNumberListCount(aNumberListCount)
+    {}
+
+    void Reset(PRUint8 aAttrEnum);
+  };
+
   struct LengthListInfo {
     nsIAtom** mName;
     PRUint8   mAxis;
     /**
      * Flag to indicate whether appending zeros to the end of the list would
      * change the rendering of the SVG for the attribute in question. For x and
      * y on the <text> element this is true, but for dx and dy on <text> this
      * is false. This flag is fed down to SVGLengthListSMILType so it can
@@ -418,16 +446,17 @@ protected:
   virtual IntegerAttributesInfo GetIntegerInfo();
   virtual AngleAttributesInfo GetAngleInfo();
   virtual BooleanAttributesInfo GetBooleanInfo();
   virtual EnumAttributesInfo GetEnumInfo();
   // We assume all viewboxes and preserveAspectRatios are alike
   // so we don't need to wrap the class
   virtual nsSVGViewBox *GetViewBox();
   virtual nsSVGPreserveAspectRatio *GetPreserveAspectRatio();
+  virtual NumberListAttributesInfo GetNumberListInfo();
   virtual LengthListAttributesInfo GetLengthListInfo();
   virtual StringAttributesInfo GetStringInfo();
 
   static nsSVGEnumMapping sSVGUnitTypesMap[];
 
 private:
   /* read <number-optional-number> */
   nsresult
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -42,18 +42,19 @@
 #include "nsIDOMSVGFilters.h"
 #include "nsCOMPtr.h"
 #include "nsSVGFilterInstance.h"
 #include "nsSVGValue.h"
 #include "nsISVGValueObserver.h"
 #include "nsWeakReference.h"
 #include "nsIDOMSVGFilterElement.h"
 #include "nsSVGEnum.h"
-#include "nsSVGNumberList.h"
-#include "nsSVGAnimatedNumberList.h"
+#include "SVGNumberList.h"
+#include "SVGAnimatedNumberList.h"
+#include "DOMSVGAnimatedNumberList.h"
 #include "nsISVGValueUtils.h"
 #include "nsSVGFilters.h"
 #include "nsLayoutUtils.h"
 #include "nsSVGUtils.h"
 #include "nsStyleContext.h"
 #include "nsIDocument.h"
 #include "nsIFrame.h"
 #include "gfxContext.h"
@@ -70,16 +71,20 @@
 
 #if defined(XP_WIN) 
 // Prevent Windows redefining LoadImage
 #ifndef WINCE
 #undef LoadImage
 #endif
 #endif
 
+#define NUM_ENTRIES_IN_4x5_MATRIX 20
+
+using namespace mozilla;
+
 static void
 CopyDataRect(PRUint8 *aDest, const PRUint8 *aSrc, PRUint32 aStride,
              const nsIntRect& aDataRect)
 {
   for (PRInt32 y = aDataRect.y; y < aDataRect.YMost(); y++) {
     memcpy(aDest + y * aStride + 4 * aDataRect.x,
            aSrc + y * aStride + 4 * aDataRect.x,
            4 * aDataRect.width);
@@ -317,16 +322,22 @@ nsSVGFE::DidAnimateLength(PRUint8 aAttrE
 
 void
 nsSVGFE::DidAnimateNumber(PRUint8 aAttrEnum)
 {
   DidAnimateAttr(this);
 }
 
 void
+nsSVGFE::DidAnimateNumberList(PRUint8 aAttrEnum)
+{
+  DidAnimateAttr(this);
+}
+
+void
 nsSVGFE::DidAnimateInteger(PRUint8 aAttrEnum)
 {
   DidAnimateAttr(this);
 }
 
 void
 nsSVGFE::DidAnimateEnum(PRUint8 aAttrEnum)
 {
@@ -1041,17 +1052,16 @@ typedef nsSVGFE nsSVGFEColorMatrixElemen
 class nsSVGFEColorMatrixElement : public nsSVGFEColorMatrixElementBase,
                                   public nsIDOMSVGFEColorMatrixElement
 {
   friend nsresult NS_NewSVGFEColorMatrixElement(nsIContent **aResult,
                                                 already_AddRefed<nsINodeInfo> aNodeInfo);
 protected:
   nsSVGFEColorMatrixElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsSVGFEColorMatrixElementBase(aNodeInfo) {}
-  nsresult Init();
 
 public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEColorMatrixElementBase::)
 
@@ -1073,27 +1083,30 @@ public:
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
   virtual PRBool OperatesOnPremultipledAlpha(PRInt32) { return PR_FALSE; }
 
   virtual EnumAttributesInfo GetEnumInfo();
   virtual StringAttributesInfo GetStringInfo();
+  virtual NumberListAttributesInfo GetNumberListInfo();
 
   enum { TYPE };
   nsSVGEnum mEnumAttributes[1];
   static nsSVGEnumMapping sTypeMap[];
   static EnumInfo sEnumInfo[1];
 
   enum { RESULT, IN1 };
   nsSVGString mStringAttributes[2];
   static StringInfo sStringInfo[2];
 
-  nsCOMPtr<nsIDOMSVGAnimatedNumberList>  mValues;
+  enum { VALUES };
+  SVGAnimatedNumberList mNumberListAttributes[1];
+  static NumberListInfo sNumberListInfo[1];
 };
 
 nsSVGEnumMapping nsSVGFEColorMatrixElement::sTypeMap[] = {
   {&nsGkAtoms::matrix, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX},
   {&nsGkAtoms::saturate, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_SATURATE},
   {&nsGkAtoms::hueRotate, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_HUE_ROTATE},
   {&nsGkAtoms::luminanceToAlpha, nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_LUMINANCE_TO_ALPHA},
   {nsnull, 0}
@@ -1108,16 +1121,21 @@ nsSVGElement::EnumInfo nsSVGFEColorMatri
 };
 
 nsSVGElement::StringInfo nsSVGFEColorMatrixElement::sStringInfo[2] =
 {
   { &nsGkAtoms::result, kNameSpaceID_None, PR_TRUE },
   { &nsGkAtoms::in, kNameSpaceID_None, PR_TRUE }
 };
 
+nsSVGElement::NumberListInfo nsSVGFEColorMatrixElement::sNumberListInfo[1] =
+{
+  { &nsGkAtoms::values }
+};
+
 NS_IMPL_NS_NEW_SVG_ELEMENT(FEColorMatrix)
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGFEColorMatrixElement,nsSVGFEColorMatrixElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGFEColorMatrixElement,nsSVGFEColorMatrixElementBase)
 
@@ -1126,40 +1144,16 @@ DOMCI_NODE_DATA(SVGFEColorMatrixElement,
 NS_INTERFACE_TABLE_HEAD(nsSVGFEColorMatrixElement)
   NS_NODE_INTERFACE_TABLE5(nsSVGFEColorMatrixElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement,
                            nsIDOMSVGFilterPrimitiveStandardAttributes,
                            nsIDOMSVGFEColorMatrixElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEColorMatrixElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGFEColorMatrixElementBase)
 
-//----------------------------------------------------------------------
-// Implementation
-
-nsresult
-nsSVGFEColorMatrixElement::Init()
-{
-  nsresult rv = nsSVGFEColorMatrixElementBase::Init();
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  // Create mapped properties:
-
-  // DOM property: values, #IMPLIED attrib: values
-  {
-    nsCOMPtr<nsIDOMSVGNumberList> values;
-    rv = NS_NewSVGNumberList(getter_AddRefs(values));
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mValues), values);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::values, mValues);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-
-  return rv;
-}
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEColorMatrixElement)
 
 
@@ -1176,18 +1170,18 @@ NS_IMETHODIMP nsSVGFEColorMatrixElement:
 NS_IMETHODIMP nsSVGFEColorMatrixElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType)
 {
   return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this);
 }
 
 /* readonly attribute nsIDOMSVGAnimatedNumberList values; */
 NS_IMETHODIMP nsSVGFEColorMatrixElement::GetValues(nsIDOMSVGAnimatedNumberList * *aValues)
 {
-  *aValues = mValues;
-  NS_IF_ADDREF(*aValues);
+  *aValues = DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[VALUES],
+                                                     this, VALUES).get();
   return NS_OK;
 }
 
 void
 nsSVGFEColorMatrixElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
 {
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
 }
@@ -1198,23 +1192,17 @@ nsSVGFEColorMatrixElement::Filter(nsSVGF
                                   const Image* aTarget,
                                   const nsIntRect& rect)
 {
   PRUint8* sourceData = aSources[0]->mImage->Data();
   PRUint8* targetData = aTarget->mImage->Data();
   PRUint32 stride = aTarget->mImage->Stride();
 
   PRUint16 type = mEnumAttributes[TYPE].GetAnimValue();
-
-  nsCOMPtr<nsIDOMSVGNumberList> list;
-  mValues->GetAnimVal(getter_AddRefs(list));
-  PRUint32 num = 0;
-  if (list) {
-    list->GetNumberOfItems(&num);
-  }
+  const SVGNumberList &values = GetAnimatedNumberList(VALUES)->GetAnimValue();
 
 #ifdef DEBUG_tor
   fprintf(stderr, "FILTER COLOR MATRIX rect: %d,%d  %dx%d\n",
           rect.x, rect.y, rect.width, rect.height);
 #endif
 
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::values) &&
       (type == nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX ||
@@ -1232,38 +1220,35 @@ nsSVGFEColorMatrixElement::Filter(nsSVGF
       0, 0, 0, 1, 0 };
 
   static const float luminanceToAlphaMatrix[] = 
     { 0,       0,       0,       0, 0,
       0,       0,       0,       0, 0,
       0,       0,       0,       0, 0,
       0.2125f, 0.7154f, 0.0721f, 0, 0 };
 
-  nsCOMPtr<nsIDOMSVGNumber> number;
-  float colorMatrix[20];
+  float colorMatrix[NUM_ENTRIES_IN_4x5_MATRIX];
   float s, c;
 
   switch (type) {
   case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_MATRIX:
 
-    if (num != 20)
+    if (values.Length() != NUM_ENTRIES_IN_4x5_MATRIX)
       return NS_ERROR_FAILURE;
 
-    for(PRUint32 j = 0; j < num; j++) {
-      list->GetItem(j, getter_AddRefs(number));
-      number->GetValue(&colorMatrix[j]);
+    for(PRUint32 j = 0; j < values.Length(); j++) {
+      colorMatrix[j] = values[j];
     }
     break;
   case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_SATURATE:
 
-    if (num != 1)
+    if (values.Length() != 1)
       return NS_ERROR_FAILURE;
 
-    list->GetItem(0, getter_AddRefs(number));
-    number->GetValue(&s);
+    s = values[0];
 
     if (s > 1 || s < 0)
       return NS_ERROR_FAILURE;
 
     memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix));
 
     colorMatrix[0] = 0.213f + 0.787f * s;
     colorMatrix[1] = 0.715f - 0.715f * s;
@@ -1275,25 +1260,23 @@ nsSVGFEColorMatrixElement::Filter(nsSVGF
 
     colorMatrix[10] = 0.213f - 0.213f * s;
     colorMatrix[11] = 0.715f - 0.715f * s;
     colorMatrix[12] = 0.072f + 0.928f * s;
 
     break;
 
   case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_HUE_ROTATE:
-
+  {
     memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix));
 
-    if (num != 1)
+    if (values.Length() != 1)
       return NS_ERROR_FAILURE;
 
-    float hueRotateValue;
-    list->GetItem(0, getter_AddRefs(number));
-    number->GetValue(&hueRotateValue);
+    float hueRotateValue = values[0];
 
     c = static_cast<float>(cos(hueRotateValue * M_PI / 180));
     s = static_cast<float>(sin(hueRotateValue * M_PI / 180));
 
     memcpy(colorMatrix, identityMatrix, sizeof(colorMatrix));
 
     colorMatrix[0] = 0.213f + 0.787f * c - 0.213f * s;
     colorMatrix[1] = 0.715f - 0.715f * c - 0.715f * s;
@@ -1303,16 +1286,17 @@ nsSVGFEColorMatrixElement::Filter(nsSVGF
     colorMatrix[6] = 0.715f + 0.285f * c + 0.140f * s;
     colorMatrix[7] = 0.072f - 0.072f * c - 0.283f * s;
 
     colorMatrix[10] = 0.213f - 0.213f * c - 0.787f * s;
     colorMatrix[11] = 0.715f - 0.715f * c + 0.715f * s;
     colorMatrix[12] = 0.072f + 0.928f * c + 0.072f * s;
 
     break;
+  }
 
   case nsSVGFEColorMatrixElement::SVG_FECOLORMATRIX_TYPE_LUMINANCE_TO_ALPHA:
 
     memcpy(colorMatrix, luminanceToAlphaMatrix, sizeof(colorMatrix));
     break;
 
   default:
     return NS_ERROR_FAILURE;
@@ -1357,16 +1341,23 @@ nsSVGFEColorMatrixElement::GetEnumInfo()
 
 nsSVGElement::StringAttributesInfo
 nsSVGFEColorMatrixElement::GetStringInfo()
 {
   return StringAttributesInfo(mStringAttributes, sStringInfo,
                               NS_ARRAY_LENGTH(sStringInfo));
 }
 
+nsSVGElement::NumberListAttributesInfo
+nsSVGFEColorMatrixElement::GetNumberListInfo()
+{
+  return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
+                                  NS_ARRAY_LENGTH(sNumberListInfo));
+}
+
 //---------------------Composite------------------------
 
 typedef nsSVGFE nsSVGFECompositeElementBase;
 
 class nsSVGFECompositeElement : public nsSVGFECompositeElementBase,
                                 public nsIDOMSVGFECompositeElement
 {
   friend nsresult NS_NewSVGFECompositeElement(nsIContent **aResult,
@@ -1769,34 +1760,38 @@ typedef nsSVGElement nsSVGComponentTrans
 
 class nsSVGComponentTransferFunctionElement : public nsSVGComponentTransferFunctionElementBase
 {
   friend nsresult NS_NewSVGComponentTransferFunctionElement(nsIContent **aResult,
                                                             already_AddRefed<nsINodeInfo> aNodeInfo);
 protected:
   nsSVGComponentTransferFunctionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsSVGComponentTransferFunctionElementBase(aNodeInfo) {}
-  nsresult Init();
 
 public:
   // interfaces:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_SVG_FE_COMPONENT_TRANSFER_FUNCTION_ELEMENT_CID)
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGCOMPONENTTRANSFERFUNCTIONELEMENT
 
   virtual PRInt32 GetChannel() = 0;
   void GenerateLookupTable(PRUint8* aTable);
 
 protected:
   virtual NumberAttributesInfo GetNumberInfo();
   virtual EnumAttributesInfo GetEnumInfo();
+  virtual NumberListAttributesInfo GetNumberListInfo();
+
+  virtual void DidAnimateNumberList(PRUint8 aAttrEnum);
 
   // nsIDOMSVGComponentTransferFunctionElement properties:
-  nsCOMPtr<nsIDOMSVGAnimatedNumberList>  mTableValues;
+  enum { TABLEVALUES };
+  SVGAnimatedNumberList mNumberListAttributes[1];
+  static NumberListInfo sNumberListInfo[1];
 
   enum { SLOPE, INTERCEPT, AMPLITUDE, EXPONENT, OFFSET };
   nsSVGNumber2 mNumberAttributes[5];
   static NumberInfo sNumberInfo[5];
 
   enum { TYPE };
   nsSVGEnum mEnumAttributes[1];
   static nsSVGEnumMapping sTypeMap[];
@@ -1849,16 +1844,21 @@ nsSVGFEComponentTransferElement::Filter(
 }
 
 void
 nsSVGFEComponentTransferElement::GetSourceImageNames(nsTArray<nsSVGStringInfo>& aSources)
 {
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
 }
 
+nsSVGElement::NumberListInfo nsSVGComponentTransferFunctionElement::sNumberListInfo[1] =
+{
+  { &nsGkAtoms::tableValues }
+};
+
 nsSVGElement::NumberInfo nsSVGComponentTransferFunctionElement::sNumberInfo[5] =
 {
   { &nsGkAtoms::slope,     1 },
   { &nsGkAtoms::intercept, 0 },
   { &nsGkAtoms::amplitude, 1 },
   { &nsGkAtoms::exponent,  1 },
   { &nsGkAtoms::offset,    0 }
 };
@@ -1896,55 +1896,31 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsSVGCompo
 NS_INTERFACE_MAP_BEGIN(nsSVGComponentTransferFunctionElement)
    // nsISupports is an ambiguous base of nsSVGFE so we have to work
    // around that
    if ( aIID.Equals(NS_GET_IID(nsSVGComponentTransferFunctionElement)) )
      foundInterface = static_cast<nsISupports*>(static_cast<void*>(this));
    else
 NS_INTERFACE_MAP_END_INHERITING(nsSVGComponentTransferFunctionElementBase)
 
-//----------------------------------------------------------------------
-// Implementation
-
-nsresult
-nsSVGComponentTransferFunctionElement::Init()
-{
-  nsresult rv = nsSVGComponentTransferFunctionElementBase::Init();
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  // Create mapped properties:
-
-  // DOM property: tableValues, #IMPLIED attrib: tableValues
-  {
-    nsCOMPtr<nsIDOMSVGNumberList> values;
-    rv = NS_NewSVGNumberList(getter_AddRefs(values));
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mTableValues), values);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::tableValues, mTableValues);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-
-  return NS_OK;
-}
 
 //----------------------------------------------------------------------
 // nsIDOMSVGComponentTransferFunctionElement methods
 
 /* readonly attribute nsIDOMSVGAnimatedEnumeration type; */
 NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType)
 {
   return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this);
 }
 
 /* readonly attribute nsIDOMSVGAnimatedNumberList tableValues; */
 NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetTableValues(nsIDOMSVGAnimatedNumberList * *aTableValues)
 {
-  *aTableValues = mTableValues;
-  NS_IF_ADDREF(*aTableValues);
+  *aTableValues = DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[TABLEVALUES],
+                                                          this, TABLEVALUES).get();
   return NS_OK;
 }
 
 /* readonly attribute nsIDOMSVGAnimatedNumber slope; */
 NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetSlope(nsIDOMSVGAnimatedNumber * *aSlope)
 {
   return mNumberAttributes[SLOPE].ToDOMAnimatedNumber(aSlope, this);
 }
@@ -1977,63 +1953,50 @@ void
 nsSVGComponentTransferFunctionElement::GenerateLookupTable(PRUint8 *aTable)
 {
   PRUint16 type = mEnumAttributes[TYPE].GetAnimValue();
 
   float slope, intercept, amplitude, exponent, offset;
   GetAnimatedNumberValues(&slope, &intercept, &amplitude, 
                           &exponent, &offset, nsnull);
 
+  const SVGNumberList &tableValues =
+    GetAnimatedNumberList(TABLEVALUES)->GetAnimValue();
+  PRUint32 tvLength = tableValues.Length();
+
   PRUint32 i;
 
   switch (type) {
   case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_TABLE:
   {
-    nsCOMPtr<nsIDOMSVGNumberList> list;
-    nsCOMPtr<nsIDOMSVGNumber> number;
-    mTableValues->GetAnimVal(getter_AddRefs(list));
-    PRUint32 num = 0;
-    if (list)
-      list->GetNumberOfItems(&num);
-    if (num <= 1)
+    if (tableValues.Length() <= 1)
       break;
 
     for (i = 0; i < 256; i++) {
-      PRUint32 k = (i * (num - 1)) / 255;
-      float v1, v2;
-      list->GetItem(k, getter_AddRefs(number));
-      number->GetValue(&v1);
-      list->GetItem(NS_MIN(k + 1, num - 1), getter_AddRefs(number));
-      number->GetValue(&v2);
+      PRUint32 k = (i * (tvLength - 1)) / 255;
+      float v1 = tableValues[k];
+      float v2 = tableValues[NS_MIN(k + 1, tvLength - 1)];
       PRInt32 val =
-        PRInt32(255 * (v1 + (i/255.0f - k/float(num-1))*(num - 1)*(v2 - v1)));
+        PRInt32(255 * (v1 + (i/255.0f - k/float(tvLength-1))*(tvLength - 1)*(v2 - v1)));
       val = NS_MIN(255, val);
       val = NS_MAX(0, val);
       aTable[i] = val;
     }
     break;
   }
 
   case nsIDOMSVGComponentTransferFunctionElement::SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE:
   {
-    nsCOMPtr<nsIDOMSVGNumberList> list;
-    nsCOMPtr<nsIDOMSVGNumber> number;
-    mTableValues->GetAnimVal(getter_AddRefs(list));
-    PRUint32 num = 0;
-    if (list)
-      list->GetNumberOfItems(&num);
-    if (num <= 1)
+    if (tableValues.Length() <= 1)
       break;
 
     for (i = 0; i < 256; i++) {
-      PRUint32 k = (i * num) / 255;
-      k = NS_MIN(k, num - 1);
-      float v;
-      list->GetItem(k, getter_AddRefs(number));
-      number->GetValue(&v);
+      PRUint32 k = (i * tvLength) / 255;
+      k = NS_MIN(k, tvLength - 1);
+      float v = tableValues[k];
       PRInt32 val = PRInt32(255 * v);
       val = NS_MIN(255, val);
       val = NS_MAX(0, val);
       aTable[i] = val;
     }
     break;
   }
 
@@ -2063,30 +2026,53 @@ nsSVGComponentTransferFunctionElement::G
   default:
     break;
   }
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
+nsSVGElement::NumberListAttributesInfo
+nsSVGComponentTransferFunctionElement::GetNumberListInfo()
+{
+  return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
+                                  NS_ARRAY_LENGTH(sNumberListInfo));
+}
+
 nsSVGElement::EnumAttributesInfo
 nsSVGComponentTransferFunctionElement::GetEnumInfo()
 {
   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
                             NS_ARRAY_LENGTH(sEnumInfo));
 }
 
 nsSVGElement::NumberAttributesInfo
 nsSVGComponentTransferFunctionElement::GetNumberInfo()
 {
   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
                               NS_ARRAY_LENGTH(sNumberInfo));
 }
 
+void
+nsSVGComponentTransferFunctionElement::DidAnimateNumberList(PRUint8 aAttrEnum)
+{
+  // We don't have a frame, so use our parent's
+  nsCOMPtr<nsIDOMSVGFEComponentTransferElement> compTrans =
+    do_QueryInterface(GetParent());
+  if (compTrans) {
+    // nsSVGLeafFrame doesn't implement AttributeChanged.
+    nsIFrame* frame = static_cast<nsSVGFE*>(GetParent())->GetPrimaryFrame();
+    if (frame) {
+      nsSVGEffects::InvalidateRenderingObservers(frame);
+    }
+  }
+}
+
+
 class nsSVGFEFuncRElement : public nsSVGComponentTransferFunctionElement,
                             public nsIDOMSVGFEFuncRElement
 {
   friend nsresult NS_NewSVGFEFuncRElement(nsIContent **aResult,
                                           already_AddRefed<nsINodeInfo> aNodeInfo);
 protected:
   nsSVGFEFuncRElement(already_AddRefed<nsINodeInfo> aNodeInfo) 
     : nsSVGComponentTransferFunctionElement(aNodeInfo) {}
@@ -3865,17 +3851,16 @@ typedef nsSVGFE nsSVGFEConvolveMatrixEle
 class nsSVGFEConvolveMatrixElement : public nsSVGFEConvolveMatrixElementBase,
                                      public nsIDOMSVGFEConvolveMatrixElement
 {
   friend nsresult NS_NewSVGFEConvolveMatrixElement(nsIContent **aResult,
                                                    already_AddRefed<nsINodeInfo> aNodeInfo);
 protected:
   nsSVGFEConvolveMatrixElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsSVGFEConvolveMatrixElementBase(aNodeInfo) {}
-  nsresult Init();
 
 public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
 
   // FE Base
   NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEConvolveMatrixElementBase::)
 
@@ -3908,16 +3893,17 @@ protected:
     return !mBooleanAttributes[PRESERVEALPHA].GetAnimValue();
   }
 
   virtual NumberAttributesInfo GetNumberInfo();
   virtual IntegerAttributesInfo GetIntegerInfo();
   virtual BooleanAttributesInfo GetBooleanInfo();
   virtual EnumAttributesInfo GetEnumInfo();
   virtual StringAttributesInfo GetStringInfo();
+  virtual NumberListAttributesInfo GetNumberListInfo();
 
   enum { DIVISOR, BIAS, KERNEL_UNIT_LENGTH_X, KERNEL_UNIT_LENGTH_Y };
   nsSVGNumber2 mNumberAttributes[4];
   static NumberInfo sNumberInfo[4];
 
   enum { ORDER_X, ORDER_Y, TARGET_X, TARGET_Y };
   nsSVGInteger mIntegerAttributes[4];
   static IntegerInfo sIntegerInfo[4];
@@ -3930,17 +3916,19 @@ protected:
   nsSVGEnum mEnumAttributes[1];
   static nsSVGEnumMapping sEdgeModeMap[];
   static EnumInfo sEnumInfo[1];
 
   enum { RESULT, IN1 };
   nsSVGString mStringAttributes[2];
   static StringInfo sStringInfo[2];
 
-  nsCOMPtr<nsIDOMSVGAnimatedNumberList>  mKernelMatrix;
+  enum { KERNELMATRIX };
+  SVGAnimatedNumberList mNumberListAttributes[1];
+  static NumberListInfo sNumberListInfo[1];
 };
 
 nsSVGElement::NumberInfo nsSVGFEConvolveMatrixElement::sNumberInfo[4] =
 {
   { &nsGkAtoms::divisor, 1 },
   { &nsGkAtoms::bias, 0 },
   { &nsGkAtoms::kernelUnitLength, 0 },
   { &nsGkAtoms::kernelUnitLength, 0 }
@@ -3975,16 +3963,21 @@ nsSVGElement::EnumInfo nsSVGFEConvolveMa
 };
 
 nsSVGElement::StringInfo nsSVGFEConvolveMatrixElement::sStringInfo[2] =
 {
   { &nsGkAtoms::result, kNameSpaceID_None, PR_TRUE },
   { &nsGkAtoms::in, kNameSpaceID_None, PR_TRUE }
 };
 
+nsSVGElement::NumberListInfo nsSVGFEConvolveMatrixElement::sNumberListInfo[1] =
+{
+  { &nsGkAtoms::kernelMatrix }
+};
+
 NS_IMPL_NS_NEW_SVG_ELEMENT(FEConvolveMatrix)
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGFEConvolveMatrixElement,nsSVGFEConvolveMatrixElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGFEConvolveMatrixElement,nsSVGFEConvolveMatrixElementBase)
 
@@ -3993,40 +3986,16 @@ DOMCI_NODE_DATA(SVGFEConvolveMatrixEleme
 NS_INTERFACE_TABLE_HEAD(nsSVGFEConvolveMatrixElement)
   NS_NODE_INTERFACE_TABLE5(nsSVGFEConvolveMatrixElement, nsIDOMNode,
                            nsIDOMElement, nsIDOMSVGElement,
                            nsIDOMSVGFilterPrimitiveStandardAttributes,
                            nsIDOMSVGFEConvolveMatrixElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEConvolveMatrixElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGFEConvolveMatrixElementBase)
 
-//----------------------------------------------------------------------
-// Implementation
-
-nsresult
-nsSVGFEConvolveMatrixElement::Init()
-{
-  nsresult rv = nsSVGFEConvolveMatrixElementBase::Init();
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  // Create mapped properties:
-
-  // DOM property: kernelMarix, #IMPLIED attrib: kernelMatrix
-  {
-    nsCOMPtr<nsIDOMSVGNumberList> values;
-    rv = NS_NewSVGNumberList(getter_AddRefs(values));
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mKernelMatrix), values);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::kernelMatrix, mKernelMatrix);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-
-  return rv;
-}
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEConvolveMatrixElement)
 
 //----------------------------------------------------------------------
 // nsSVGFEConvolveMatrixElement methods
@@ -4043,18 +4012,18 @@ NS_IMETHODIMP nsSVGFEConvolveMatrixEleme
 
 NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetOrderY(nsIDOMSVGAnimatedInteger * *aOrderY)
 {
   return mIntegerAttributes[ORDER_Y].ToDOMAnimatedInteger(aOrderY, this);
 }
 
 NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetKernelMatrix(nsIDOMSVGAnimatedNumberList * *aKernelMatrix)
 {
-  *aKernelMatrix = mKernelMatrix;
-  NS_IF_ADDREF(*aKernelMatrix);
+  *aKernelMatrix = DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[KERNELMATRIX],
+                                                           this, KERNELMATRIX).get();
   return NS_OK;
 }
 
 NS_IMETHODIMP nsSVGFEConvolveMatrixElement::GetTargetX(nsIDOMSVGAnimatedInteger * *aTargetX)
 {
   return mIntegerAttributes[TARGET_X].ToDOMAnimatedInteger(aTargetX, this);
 }
 
@@ -4203,29 +4172,26 @@ ConvolvePixel(const PRUint8 *aSourceData
 }
 
 nsresult
 nsSVGFEConvolveMatrixElement::Filter(nsSVGFilterInstance *instance,
                                      const nsTArray<const Image*>& aSources,
                                      const Image* aTarget,
                                      const nsIntRect& rect)
 {
-  nsCOMPtr<nsIDOMSVGNumberList> list;
-  mKernelMatrix->GetAnimVal(getter_AddRefs(list));
-  PRUint32 num = 0;
-  if (list) {
-    list->GetNumberOfItems(&num);
-  }
+  const SVGNumberList &kernelMatrix =
+    GetAnimatedNumberList(KERNELMATRIX)->GetAnimValue();
+  PRUint32 kmLength = kernelMatrix.Length();
 
   PRInt32 orderX, orderY;
   PRInt32 targetX, targetY;
   GetAnimatedIntegerValues(&orderX, &orderY, &targetX, &targetY, nsnull);
 
   if (orderX <= 0 || orderY <= 0 ||
-      static_cast<PRUint32>(orderX * orderY) != num) {
+      static_cast<PRUint32>(orderX * orderY) != kmLength) {
     return NS_ERROR_FAILURE;
   }
 
   if (HasAttr(kNameSpaceID_None, nsGkAtoms::targetX)) {
     if (targetX < 0 || targetX >= orderX)
       return NS_ERROR_FAILURE;
   } else {
     targetX = orderX / 2;
@@ -4238,31 +4204,28 @@ nsSVGFEConvolveMatrixElement::Filter(nsS
   }
 
   if (orderX > NS_SVG_OFFSCREEN_MAX_DIMENSION ||
       orderY > NS_SVG_OFFSCREEN_MAX_DIMENSION)
     return NS_ERROR_FAILURE;
   nsAutoArrayPtr<float> kernel(new float[orderX * orderY]);
   if (!kernel)
     return NS_ERROR_FAILURE;
-  for (PRUint32 i = 0; i < num; i++) {
-    nsCOMPtr<nsIDOMSVGNumber> number;
-    list->GetItem(i, getter_AddRefs(number));
-    // svg specification flips the kernel from what one might expect
-    number->GetValue(&kernel[num - 1 - i]);
+  for (PRUint32 i = 0; i < kmLength; i++) {
+    kernel[kmLength - 1 - i] = kernelMatrix[i];
   }
 
   float divisor;
   if (HasAttr(kNameSpaceID_None, nsGkAtoms::divisor)) {
     divisor = mNumberAttributes[DIVISOR].GetAnimValue();
     if (divisor == 0)
       return NS_ERROR_FAILURE;
   } else {
     divisor = kernel[0];
-    for (PRUint32 i = 1; i < num; i++)
+    for (PRUint32 i = 1; i < kmLength; i++)
       divisor += kernel[i];
     if (divisor == 0)
       divisor = 1;
   }
 
   ScaleInfo info = SetupScalingFilter(instance, aSources[0], aTarget, rect,
                                       &mNumberAttributes[KERNEL_UNIT_LENGTH_X],
                                       &mNumberAttributes[KERNEL_UNIT_LENGTH_Y]);
@@ -4332,16 +4295,23 @@ nsSVGFEConvolveMatrixElement::GetEnumInf
 
 nsSVGElement::StringAttributesInfo
 nsSVGFEConvolveMatrixElement::GetStringInfo()
 {
   return StringAttributesInfo(mStringAttributes, sStringInfo,
                               NS_ARRAY_LENGTH(sStringInfo));
 }
 
+nsSVGElement::NumberListAttributesInfo
+nsSVGFEConvolveMatrixElement::GetNumberListInfo()
+{
+  return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
+                                  NS_ARRAY_LENGTH(sNumberListInfo));
+}
+
 //---------------------DistantLight------------------------
 
 typedef nsSVGElement nsSVGFEDistantLightElementBase;
 
 class nsSVGFEDistantLightElement : public nsSVGFEDistantLightElementBase,
                                    public nsIDOMSVGFEDistantLightElement
 {
   friend nsresult NS_NewSVGFEDistantLightElement(nsIContent **aResult,
--- a/content/svg/content/src/nsSVGFilters.h
+++ b/content/svg/content/src/nsSVGFilters.h
@@ -213,16 +213,17 @@ protected:
     return style->GetStyleSVG()->mColorInterpolationFilters ==
              NS_STYLE_COLOR_INTERPOLATION_SRGB;
   }
 
   // nsSVGElement specializations:
   virtual LengthAttributesInfo GetLengthInfo();
   virtual void DidAnimateLength(PRUint8 aAttrEnum);
   virtual void DidAnimateNumber(PRUint8 aAttrEnum);
+  virtual void DidAnimateNumberList(PRUint8 aAttrEnum);
   virtual void DidAnimateInteger(PRUint8 aAttrEnum);
   virtual void DidAnimateEnum(PRUint8 aAttrEnum);
   virtual void DidAnimateBoolean(PRUint8 aAttrEnum);
   virtual void DidAnimatePreserveAspectRatio();
   virtual void DidAnimateString(PRUint8 aAttrEnum);
 
   // nsIDOMSVGFitlerPrimitiveStandardAttributes values
   enum { X, Y, WIDTH, HEIGHT };
deleted file mode 100644
--- a/content/svg/content/src/nsSVGNumber.cpp
+++ /dev/null
@@ -1,175 +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) 2002
- * 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 "nsSVGNumber.h"
-#include "nsSVGUtils.h"
-#include "nsTextFormatter.h"
-#include "prdtoa.h"
-#include "nsDOMError.h"
-#include "nsSVGValue.h"
-#include "nsISVGValueUtils.h"
-#include "nsContentUtils.h"
-
-////////////////////////////////////////////////////////////////////////
-// nsSVGNumber class
-
-class nsSVGNumber : public nsIDOMSVGNumber,
-                    public nsSVGValue
-{
-protected:
-  friend nsresult NS_NewSVGNumber(nsIDOMSVGNumber** result,
-                                  float val);
-  nsSVGNumber(float val);
-  
-public:
-  // nsISupports interface:
-  NS_DECL_ISUPPORTS
-
-  // nsIDOMSVGNumber interface:
-  NS_DECL_NSIDOMSVGNUMBER
-
-  // nsISVGValue interface:
-  NS_IMETHOD SetValueString(const nsAString& aValue);
-  NS_IMETHOD GetValueString(nsAString& aValue);
-  
-protected:
-  float mValue;
-};
-
-//----------------------------------------------------------------------
-// implementation:
-
-nsresult
-NS_NewSVGNumber(nsIDOMSVGNumber** result, float val)
-{
-  *result = new nsSVGNumber(val);
-  if (!*result) return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(*result);
-  return NS_OK;
-}
-
-nsSVGNumber::nsSVGNumber(float val)
-    : mValue(val)
-{
-}
-
-//----------------------------------------------------------------------
-// nsISupports methods:
-
-NS_IMPL_ADDREF(nsSVGNumber)
-NS_IMPL_RELEASE(nsSVGNumber)
-
-DOMCI_DATA(SVGNumber, nsSVGNumber)
-
-NS_INTERFACE_MAP_BEGIN(nsSVGNumber)
-  NS_INTERFACE_MAP_ENTRY(nsISVGValue)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGNumber)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGNumber)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
-NS_INTERFACE_MAP_END
-
-//----------------------------------------------------------------------
-// nsISVGValue methods:
-
-NS_IMETHODIMP
-nsSVGNumber::GetValueString(nsAString& aValue)
-{
-  PRUnichar buf[24];
-  nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
-                            NS_LITERAL_STRING("%g").get(),
-                            (double)mValue);
-  aValue.Assign(buf);
-  
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSVGNumber::SetValueString(const nsAString& aValue)
-{
-  nsresult rv = NS_OK;
-  WillModify();
-  
-  NS_ConvertUTF16toUTF8 value(aValue);
-  const char *str = value.get();
-
-  if (*str) {
-    char *rest;
-    float val = float(PR_strtod(str, &rest));
-    if (rest && rest!=str && NS_FloatIsFinite(val)) {
-      if (*rest=='%') {
-        rv = SetValue(val / 100.0f);
-        rest++;
-      } else {
-        rv = SetValue(val);
-      }
-      // skip trailing spaces
-      while (*rest && IsSVGWhitespace(*rest))
-        ++rest;
-
-      // check to see if there is trailing stuff...
-      if (*rest != '\0') {
-        rv = NS_ERROR_DOM_SYNTAX_ERR;
-      }
-    } else {
-      rv = NS_ERROR_DOM_SYNTAX_ERR;
-      // no number
-    }
-  }
-  DidModify();
-  return rv;
-}
-
-//----------------------------------------------------------------------
-
-//----------------------------------------------------------------------
-// nsIDOMSVGNumber methods:
-
-/* attribute float value; */
-NS_IMETHODIMP nsSVGNumber::GetValue(float *aValue)
-{
-  *aValue = mValue;
-  return NS_OK;
-}
-NS_IMETHODIMP nsSVGNumber::SetValue(float aValue)
-{
-  NS_ENSURE_FINITE(aValue, NS_ERROR_ILLEGAL_VALUE);
-  WillModify();
-  mValue = aValue;
-  DidModify();
-  return NS_OK;
-}
deleted file mode 100644
--- a/content/svg/content/src/nsSVGNumber.h
+++ /dev/null
@@ -1,48 +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) 2002
- * 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_SVGNUMBER_H__
-#define __NS_SVGNUMBER_H__
-
-#include "nsIDOMSVGNumber.h"
-
-nsresult
-NS_NewSVGNumber(nsIDOMSVGNumber** result,
-                float value=0.0f);
-
-#endif //__NS_SVGNUMBER_H__
deleted file mode 100644
--- a/content/svg/content/src/nsSVGNumberList.cpp
+++ /dev/null
@@ -1,410 +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
- * Scooter Morris.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Scooter Morris <scootermorris@comcast.net>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either 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 "nsSVGNumberList.h"
-#include "nsSVGNumber.h"
-#include "nsSVGValue.h"
-#include "nsWeakReference.h"
-#include "nsDOMError.h"
-#include "nsReadableUtils.h"
-#include "nsCRT.h"
-#include "nsISVGValueUtils.h"
-#include "prdtoa.h"
-#include "nsContentUtils.h"
-
-////////////////////////////////////////////////////////////////////////
-// nsSVGNumberList
-
-class nsSVGNumberList : public nsIDOMSVGNumberList,
-                        public nsSVGValue,
-                        public nsISVGValueObserver
-{  
-protected:
-  friend nsresult NS_NewSVGNumberList(nsIDOMSVGNumberList** result);
-
-  nsSVGNumberList();
-  ~nsSVGNumberList();
-//  void Init();
-  
-public:
-  // nsISupports interface:
-  NS_DECL_ISUPPORTS
-
-  // nsIDOMSVGNumberList interface:
-  NS_DECL_NSIDOMSVGNUMBERLIST
-
-  // remainder of nsISVGValue interface:
-  NS_IMETHOD SetValueString(const nsAString& aValue);
-  NS_IMETHOD GetValueString(nsAString& aValue);
-
-  // nsISVGValueObserver interface:
-  NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable,
-                                     modificationType aModType);
-  NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
-                                     modificationType aModType);
-
-  // nsISupportsWeakReference
-  // implementation inherited from nsSupportsWeakReference
-  
-protected:
-  // implementation helpers:
-  nsIDOMSVGNumber* ElementAt(PRInt32 index);
-  void AppendElement(nsIDOMSVGNumber* aElement);
-  void RemoveElementAt(PRInt32 index);
-  nsresult InsertElementAt(nsIDOMSVGNumber* aElement, PRInt32 index);
-  
-  void ReleaseNumbers();
-  
-  nsAutoTArray<nsIDOMSVGNumber*, 8> mNumbers;
-};
-
-
-#define NS_ENSURE_NATIVE_NUMBER(obj, retval)            \
-  {                                                     \
-    nsCOMPtr<nsISVGValue> val = do_QueryInterface(obj); \
-    if (!val) {                                         \
-      *retval = nsnull;                                 \
-      return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;           \
-    }                                                   \
-  }
-
-//----------------------------------------------------------------------
-// Implementation
-
-nsSVGNumberList::nsSVGNumberList()
-{
-}
-
-nsSVGNumberList::~nsSVGNumberList()
-{
-  ReleaseNumbers();
-}
-
-//----------------------------------------------------------------------
-// nsISupports methods:
-
-NS_IMPL_ADDREF(nsSVGNumberList)
-NS_IMPL_RELEASE(nsSVGNumberList)
-
-DOMCI_DATA(SVGNumberList, nsSVGNumberList)
-
-NS_INTERFACE_MAP_BEGIN(nsSVGNumberList)
-  NS_INTERFACE_MAP_ENTRY(nsISVGValue)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGNumberList)
-  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-  NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGNumberList)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
-NS_INTERFACE_MAP_END
-
-//----------------------------------------------------------------------
-// nsISVGValue methods:
-
-NS_IMETHODIMP
-nsSVGNumberList::SetValueString(const nsAString& aValue)
-{
-  WillModify();
-  ReleaseNumbers();
-
-  nsresult rv = NS_OK;
-
-  char* str = ToNewCString(aValue);
-
-  char* rest = str;
-  char* token;
-  const char* delimiters = ", \t\r\n";
-
-  while ((token = nsCRT::strtok(rest, delimiters, &rest))) {
-    char *left;
-    float val = float(PR_strtod(token, &left));
-    if (token!=left && NS_FloatIsFinite(val)) {
-      nsCOMPtr<nsIDOMSVGNumber> number;
-      NS_NewSVGNumber(getter_AddRefs(number), val);
-      if (!number) {
-        rv = NS_ERROR_DOM_SYNTAX_ERR;
-        break;
-      }
-      AppendElement(number);
-    }
-  }
-  
-  nsMemory::Free(str);
-  
-  DidModify();
-  return rv;
-}
-
-NS_IMETHODIMP
-nsSVGNumberList::GetValueString(nsAString& aValue)
-{
-  aValue.Truncate();
-
-  PRUint32 count = mNumbers.Length();
-
-  if (count == 0) return NS_OK;
-
-  PRUint32 i = 0;
-  
-  while (1) {
-    nsIDOMSVGNumber* number = ElementAt(i);
-    nsCOMPtr<nsISVGValue> val = do_QueryInterface(number);
-    NS_ASSERTION(val, "number doesn't implement required interface");
-    nsAutoString str;
-    val->GetValueString(str);
-    aValue.Append(str);
-
-    if (++i >= count) break;
-
-    aValue.AppendLiteral(" ");
-  }
-  
-  return NS_OK;
-}
-
-//----------------------------------------------------------------------
-// nsIDOMSVGNumberList methods:
-
-/* readonly attribute unsigned long numberOfItems; */
-NS_IMETHODIMP nsSVGNumberList::GetNumberOfItems(PRUint32 *aNumberOfItems)
-{
-  *aNumberOfItems = mNumbers.Length();
-  return NS_OK;
-}
-
-/* void clear (); */
-NS_IMETHODIMP nsSVGNumberList::Clear()
-{
-  WillModify();
-  ReleaseNumbers();
-  DidModify();
-  return NS_OK;
-}
-
-/* nsIDOMSVGNumber initialize (in nsIDOMSVGNumber newItem); */
-NS_IMETHODIMP nsSVGNumberList::Initialize(nsIDOMSVGNumber *newItem,
-                                          nsIDOMSVGNumber **_retval)
-{
-  NS_ENSURE_NATIVE_NUMBER(newItem, _retval);
-  Clear();
-  return AppendItem(newItem, _retval);
-}
-
-/* nsIDOMSVGNumber getItem (in unsigned long index); */
-NS_IMETHODIMP nsSVGNumberList::GetItem(PRUint32 index, nsIDOMSVGNumber **_retval)
-{
-  if (index >= mNumbers.Length()) {
-    *_retval = nsnull;
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
-  }
-
-  *_retval  = ElementAt(index);
-  NS_ADDREF(*_retval);
-  return NS_OK;
-}
-
-/* nsIDOMSVGNumber insertItemBefore (in nsIDOMSVGNumber newItem, in unsigned long index); */
-NS_IMETHODIMP
-nsSVGNumberList::InsertItemBefore(nsIDOMSVGNumber *newItem,
-                                  PRUint32 index,
-                                  nsIDOMSVGNumber **_retval)
-{
-  NS_ENSURE_NATIVE_NUMBER(newItem, _retval);
-  *_retval = newItem;
-
-  nsSVGValueAutoNotifier autonotifier(this);
-
-  PRUint32 count = mNumbers.Length();
-
-  if (!InsertElementAt(newItem, (index < count)? index: count)) {
-    *_retval = nsnull;
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  NS_ADDREF(*_retval);
-  return NS_OK;
-}
-
-/* nsIDOMSVGNumber replaceItem (in nsIDOMSVGNumber newItem, in unsigned long index); */
-NS_IMETHODIMP
-nsSVGNumberList::ReplaceItem(nsIDOMSVGNumber *newItem,
-                             PRUint32 index,
-                             nsIDOMSVGNumber **_retval)
-{
-  NS_ENSURE_NATIVE_NUMBER(newItem, _retval);
-
-  nsresult rv = RemoveItem(index, _retval);
-  if (NS_FAILED(rv))
-    return rv;
-
-  return InsertElementAt(newItem, index);
-}
-
-/* nsIDOMSVGNumberList removeItem (in unsigned long index); */
-NS_IMETHODIMP nsSVGNumberList::RemoveItem(PRUint32 index, nsIDOMSVGNumber **_retval)
-{
-  if (index >= mNumbers.Length()) {
-    *_retval = nsnull;
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
-  }
-
-  *_retval = ElementAt(index);
-  NS_ADDREF(*_retval);
-  WillModify();
-  RemoveElementAt(index);
-  DidModify();
-  return NS_OK;
-}
-
-/* nsIDOMSVGNumberList appendItem (in nsIDOMSVGNumberList newItem); */
-NS_IMETHODIMP
-nsSVGNumberList::AppendItem(nsIDOMSVGNumber *newItem, nsIDOMSVGNumber **_retval)
-{
-  NS_ENSURE_NATIVE_NUMBER(newItem, _retval);
-  *_retval = newItem;
-  AppendElement(newItem);
-  NS_ADDREF(*_retval);
-  return NS_OK;
-}
-
-//----------------------------------------------------------------------
-// nsISVGValueObserver methods
-
-NS_IMETHODIMP
-nsSVGNumberList::WillModifySVGObservable(nsISVGValue* observable,
-                                         modificationType aModType)
-{
-  WillModify(aModType);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsSVGNumberList::DidModifySVGObservable(nsISVGValue* observable,
-                                        modificationType aModType)
-{
-  DidModify(aModType);
-  return NS_OK;
-}
-
-//----------------------------------------------------------------------
-// Implementation helpers
-
-void
-nsSVGNumberList::ReleaseNumbers()
-{
-  WillModify();
-  PRUint32 count = mNumbers.Length();
-  for (PRUint32 i = 0; i < count; ++i) {
-    nsIDOMSVGNumber* number = ElementAt(i);
-    NS_REMOVE_SVGVALUE_OBSERVER(number);
-    NS_RELEASE(number);
-  }
-  mNumbers.Clear();
-  DidModify();
-}
-
-nsIDOMSVGNumber*
-nsSVGNumberList::ElementAt(PRInt32 index)
-{
-  return mNumbers.ElementAt(index);
-}
-
-void
-nsSVGNumberList::AppendElement(nsIDOMSVGNumber* aElement)
-{
-  WillModify();
-  NS_ADDREF(aElement);
-  
-  // The SVG specs state that 'if newItem is already in a list, it
-  // is removed from its previous list before it is inserted into this
-  // list':
-  //  aElement->SetListOwner(this);
-  
-  mNumbers.AppendElement(aElement);
-  NS_ADD_SVGVALUE_OBSERVER(aElement);
-  DidModify();
-}
-
-void
-nsSVGNumberList::RemoveElementAt(PRInt32 index)
-{
-  WillModify();
-  nsIDOMSVGNumber* number = ElementAt(index);
-  NS_ASSERTION(number, "null number");
-  NS_REMOVE_SVGVALUE_OBSERVER(number);
-  mNumbers.RemoveElementAt(index);
-  NS_RELEASE(number);
-  DidModify();
-}
-
-nsresult
-nsSVGNumberList::InsertElementAt(nsIDOMSVGNumber* aElement, PRInt32 index)
-{
-  // The SVG specs state that 'if newItem is already in a list, it
-  // is removed from its previous list before it is inserted into this
-  // list':
-  //  aElement->SetListOwner(this);
-  
-  if (!mNumbers.InsertElementAt(index, aElement)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  WillModify();
-  NS_ADDREF(aElement);
-  NS_ADD_SVGVALUE_OBSERVER(aElement);
-  DidModify();
-  return NS_OK;
-}
-
-
-////////////////////////////////////////////////////////////////////////
-// Exported creation functions:
-
-nsresult
-NS_NewSVGNumberList(nsIDOMSVGNumberList** result)
-{
-  *result = nsnull;
-  
-  nsSVGNumberList* numberList = new nsSVGNumberList();
-  if (!numberList) return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(numberList);
-
-  *result = numberList;
-  
-  return NS_OK;
-}
-
-
deleted file mode 100644
--- a/content/svg/content/src/nsSVGNumberList.h
+++ /dev/null
@@ -1,49 +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
- * Scooter Morris.
- * Portions created by the Initial Developer are Copyright (C) 2004
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Scooter Morris <scootermorris@comcast.net>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either 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_SVGNUMBERLIST_H__
-#define __NS_SVGNUMBERLIST_H__
-
-#include "nsIDOMSVGNumberList.h"
-
-nsresult
-NS_NewSVGNumberList(nsIDOMSVGNumberList** result);
-
-#endif //__NS_SVGNUMBERLIST_H__
-
-
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -34,30 +34,30 @@
  * 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 "nsGkAtoms.h"
+#include "DOMSVGNumber.h"
 #include "DOMSVGLength.h"
 #include "nsSVGAngle.h"
 #include "nsCOMPtr.h"
 #include "nsIPresShell.h"
 #include "nsContentUtils.h"
 #include "nsIDocument.h"
 #include "nsPresContext.h"
 #include "nsSVGMatrix.h"
 #include "nsSVGPoint.h"
 #include "nsSVGTransform.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIFrame.h"
 #include "nsISVGSVGFrame.h" //XXX
-#include "nsSVGNumber.h"
 #include "nsSVGRect.h"
 #include "nsISVGValueUtils.h"
 #include "nsDOMError.h"
 #include "nsISVGChildFrame.h"
 #include "nsGUIEvent.h"
 #include "nsSVGUtils.h"
 #include "nsSVGSVGElement.h"
 #include "nsSVGEffects.h" // For nsSVGEffects::RemoveAllRenderingObservers
@@ -627,17 +627,18 @@ nsSVGSVGElement::DeSelectAll()
   NS_NOTYETIMPLEMENTED("nsSVGSVGElement::DeSelectAll");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /* nsIDOMSVGNumber createSVGNumber (); */
 NS_IMETHODIMP
 nsSVGSVGElement::CreateSVGNumber(nsIDOMSVGNumber **_retval)
 {
-  return NS_NewSVGNumber(_retval);
+  NS_ADDREF(*_retval = new DOMSVGNumber());
+  return NS_OK;
 }
 
 /* nsIDOMSVGLength createSVGLength (); */
 NS_IMETHODIMP
 nsSVGSVGElement::CreateSVGLength(nsIDOMSVGLength **_retval)
 {
   NS_IF_ADDREF(*_retval = new DOMSVGLength());
   return NS_OK;
--- a/content/svg/content/src/nsSVGStopElement.cpp
+++ b/content/svg/content/src/nsSVGStopElement.cpp
@@ -33,17 +33,16 @@
  * 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 "nsIDOMSVGStopElement.h"
-#include "nsSVGAnimatedNumberList.h"
 #include "nsSVGNumber2.h"
 #include "nsSVGUtils.h"
 #include "nsGenericHTMLElement.h"
 
 typedef nsSVGStylableElement nsSVGStopElementBase;
 
 class nsSVGStopElement : public nsSVGStopElementBase,
                          public nsIDOMSVGStopElement
--- a/content/svg/content/src/nsSVGTextElement.cpp
+++ b/content/svg/content/src/nsSVGTextElement.cpp
@@ -42,18 +42,19 @@
 #include "nsCOMPtr.h"
 #include "nsSVGSVGElement.h"
 #include "nsSVGTextPositioningElement.h"
 #include "nsIFrame.h"
 #include "nsDOMError.h"
 #include "SVGAnimatedLengthList.h"
 #include "DOMSVGAnimatedLengthList.h"
 #include "SVGLengthList.h"
-#include "nsSVGNumberList.h"
-#include "nsSVGAnimatedNumberList.h"
+#include "SVGNumberList.h"
+#include "SVGAnimatedNumberList.h"
+#include "DOMSVGAnimatedNumberList.h"
 
 using namespace mozilla;
 
 typedef nsSVGGraphicElement nsSVGTextElementBase;
 
 /**
  * This class does not inherit nsSVGTextPositioningElement - it reimplements it
  * instead.
@@ -68,17 +69,16 @@ typedef nsSVGGraphicElement nsSVGTextEle
  */
 class nsSVGTextElement : public nsSVGTextElementBase,
                          public nsIDOMSVGTextElement // nsIDOMSVGTextPositioningElement
 {
 protected:
   friend nsresult NS_NewSVGTextElement(nsIContent **aResult,
                                        already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGTextElement(already_AddRefed<nsINodeInfo> aNodeInfo);
-  nsresult Init();
   
 public:
   // interfaces:
   
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGTEXTELEMENT
   NS_DECL_NSIDOMSVGTEXTPOSITIONINGELEMENT
   NS_DECL_NSIDOMSVGTEXTCONTENTELEMENT
@@ -96,24 +96,27 @@ public:
 
   virtual nsXPCClassInfo* GetClassInfo();
 protected:
   nsSVGTextContainerFrame* GetTextContainerFrame() {
     return do_QueryFrame(GetPrimaryFrame(Flush_Layout));
   }
 
   virtual LengthListAttributesInfo GetLengthListInfo();
+  virtual NumberListAttributesInfo GetNumberListInfo();
 
   // nsIDOMSVGTextPositioning properties:
 
   enum { X, Y, DX, DY };
   SVGAnimatedLengthList mLengthListAttributes[4];
   static LengthListInfo sLengthListInfo[4];
 
-  nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate;
+  enum { ROTATE };
+  SVGAnimatedNumberList mNumberListAttributes[1];
+  static NumberListInfo sNumberListInfo[1];
 };
 
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Text)
 
 
 //----------------------------------------------------------------------
 // nsISupports methods
@@ -135,37 +138,16 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGTex
 // Implementation
 
 nsSVGTextElement::nsSVGTextElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGTextElementBase(aNodeInfo)
 {
 
 }
   
-nsresult
-nsSVGTextElement::Init()
-{
-  nsresult rv = nsSVGTextElementBase::Init();
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  // DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate
-  {
-    nsCOMPtr<nsIDOMSVGNumberList> numberList;
-    rv = NS_NewSVGNumberList(getter_AddRefs(numberList));
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mRotate),
-                                     numberList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-
-  return rv;
-}
-
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGTextElement)
 
 
 //----------------------------------------------------------------------
@@ -212,18 +194,18 @@ nsSVGTextElement::GetDy(nsIDOMSVGAnimate
                                                  this, DY, nsSVGUtils::Y).get();
   return NS_OK;
 }
 
 /* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */
 NS_IMETHODIMP
 nsSVGTextElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate)
 {
-  *aRotate = mRotate;
-  NS_IF_ADDREF(*aRotate);
+  *aRotate = DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[ROTATE],
+                                                     this, ROTATE).get();
   return NS_OK;
 }
 
 
 //----------------------------------------------------------------------
 // nsIDOMSVGTextContentElement methods
 
 /* readonly attribute nsIDOMSVGAnimatedLength textLength; */
@@ -390,8 +372,20 @@ nsSVGElement::LengthListInfo nsSVGTextEl
 
 nsSVGElement::LengthListAttributesInfo
 nsSVGTextElement::GetLengthListInfo()
 {
   return LengthListAttributesInfo(mLengthListAttributes, sLengthListInfo,
                                   NS_ARRAY_LENGTH(sLengthListInfo));
 }
 
+nsSVGElement::NumberListInfo nsSVGTextElement::sNumberListInfo[1] =
+{
+  { &nsGkAtoms::rotate }
+};
+
+nsSVGElement::NumberListAttributesInfo
+nsSVGTextElement::GetNumberListInfo()
+{
+  return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
+                                  NS_ARRAY_LENGTH(sNumberListInfo));
+}
+
--- a/content/svg/content/src/nsSVGTextPositioningElement.cpp
+++ b/content/svg/content/src/nsSVGTextPositioningElement.cpp
@@ -32,43 +32,20 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGTextPositioningElement.h"
 #include "SVGAnimatedLengthList.h"
 #include "DOMSVGAnimatedLengthList.h"
 #include "SVGLengthList.h"
-#include "nsSVGAnimatedNumberList.h"
-#include "nsSVGNumberList.h"
+#include "DOMSVGAnimatedNumberList.h"
 
 using namespace mozilla;
 
-nsresult
-nsSVGTextPositioningElement::Init()
-{
-  nsresult rv = nsSVGTextPositioningElementBase::Init();
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  // Create mapped properties:
-
-  // DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate
-  {
-    nsCOMPtr<nsIDOMSVGNumberList> numberList;
-    rv = NS_NewSVGNumberList(getter_AddRefs(numberList));
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mRotate),
-                                     numberList);
-    NS_ENSURE_SUCCESS(rv,rv);
-    rv = AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
-    NS_ENSURE_SUCCESS(rv,rv);
-  }
-
-  return rv;
-}
 
 nsSVGElement::LengthListInfo nsSVGTextPositioningElement::sLengthListInfo[4] =
 {
   { &nsGkAtoms::x,  nsSVGUtils::X, PR_FALSE },
   { &nsGkAtoms::y,  nsSVGUtils::Y, PR_FALSE },
   { &nsGkAtoms::dx, nsSVGUtils::X, PR_TRUE },
   { &nsGkAtoms::dy, nsSVGUtils::Y, PR_TRUE }
 };
@@ -76,16 +53,28 @@ nsSVGElement::LengthListInfo nsSVGTextPo
 nsSVGElement::LengthListAttributesInfo
 nsSVGTextPositioningElement::GetLengthListInfo()
 {
   return LengthListAttributesInfo(mLengthListAttributes, sLengthListInfo,
                                   NS_ARRAY_LENGTH(sLengthListInfo));
 }
 
 
+nsSVGElement::NumberListInfo nsSVGTextPositioningElement::sNumberListInfo[1] =
+{
+  { &nsGkAtoms::rotate }
+};
+
+nsSVGElement::NumberListAttributesInfo
+nsSVGTextPositioningElement::GetNumberListInfo()
+{
+  return NumberListAttributesInfo(mNumberListAttributes, sNumberListInfo,
+                                  NS_ARRAY_LENGTH(sNumberListInfo));
+}
+
 //----------------------------------------------------------------------
 // nsIDOMSVGTextPositioningElement methods
 
 /* readonly attribute nsIDOMSVGAnimatedLengthList x; */
 NS_IMETHODIMP nsSVGTextPositioningElement::GetX(nsIDOMSVGAnimatedLengthList * *aX)
 {
   *aX = DOMSVGAnimatedLengthList::GetDOMWrapper(&mLengthListAttributes[X],
                                                 this, X, nsSVGUtils::X).get();
@@ -114,12 +103,12 @@ NS_IMETHODIMP nsSVGTextPositioningElemen
   *aDy = DOMSVGAnimatedLengthList::GetDOMWrapper(&mLengthListAttributes[DY],
                                                  this, DY, nsSVGUtils::Y).get();
   return NS_OK;
 }
 
 /* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */
 NS_IMETHODIMP nsSVGTextPositioningElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate)
 {
-  *aRotate = mRotate;
-  NS_IF_ADDREF(*aRotate);
+  *aRotate = DOMSVGAnimatedNumberList::GetDOMWrapper(&mNumberListAttributes[ROTATE],
+                                                     this, ROTATE).get();
   return NS_OK;
 }
--- a/content/svg/content/src/nsSVGTextPositioningElement.h
+++ b/content/svg/content/src/nsSVGTextPositioningElement.h
@@ -33,18 +33,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGTEXTPOSITIONINGELEMENTBASE_H__
 #define __NS_SVGTEXTPOSITIONINGELEMENTBASE_H__
 
 #include "nsIDOMSVGTextPositionElem.h"
 #include "nsSVGTextContentElement.h"
-#include "nsIDOMSVGAnimatedLengthList.h"
-#include "nsIDOMSVGAnimatedNumberList.h"
+#include "SVGAnimatedNumberList.h"
 #include "SVGAnimatedLengthList.h"
 
 class nsSVGElement;
 
 namespace mozilla {
 class SVGAnimatedLengthList;
 }
 
@@ -61,22 +60,23 @@ public:
   NS_DECL_NSIDOMSVGTEXTPOSITIONINGELEMENT
 
 protected:
 
   nsSVGTextPositioningElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsSVGTextPositioningElementBase(aNodeInfo)
   {}
 
-  nsresult Init();
-
   virtual LengthListAttributesInfo GetLengthListInfo();
+  virtual NumberListAttributesInfo GetNumberListInfo();
 
   // nsIDOMSVGTextPositioning properties:
 
   enum { X, Y, DX, DY };
-  mozilla::SVGAnimatedLengthList mLengthListAttributes[4];
+  SVGAnimatedLengthList mLengthListAttributes[4];
   static LengthListInfo sLengthListInfo[4];
 
-  nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate;
+  enum { ROTATE };
+  SVGAnimatedNumberList mNumberListAttributes[1];
+  static NumberListInfo sNumberListInfo[1];
 };
 
 #endif
--- a/content/svg/content/test/test_SVGxxxList.xhtml
+++ b/content/svg/content/test/test_SVGxxxList.xhtml
@@ -8,16 +8,23 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="text/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=515116">Mozilla Bug 515116</a>
 <p id="display"></p>
 <div id="content" style="display:none;">
 <svg id="svg" xmlns="http://www.w3.org/2000/svg" width="100" height="100">
+  <desc>
+    <filter>
+      <feComponentTransfer>
+        <feFuncR id="feFuncR" type="table"/>
+      </feComponentTransfer>
+    </filter>
+  </desc>
   <text id="text">text</text>
   <path id="path"/>
 </svg>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 <![CDATA[
 
@@ -91,53 +98,61 @@ var tests = [
     attr_val_5a: '10 20ex, 30in ,40cm , 50%',
     attr_val_5b: '50% 10, 20ex ,30in , 40cm',
     item_constructor: function() {
       // We need this function literal to avoid "Illegal operation on
       // WrappedNative prototype object" NS_ERROR_XPC_BAD_OP_ON_WN_PROTO.
       return document.getElementById('svg').createSVGLength();
     }
   },
-  /*
   {
     // SVGNumberList test:
     target_element_id: 'text',
     attr_name: 'rotate',
     prop_name: 'rotate',
     bv_name: 'baseVal',
     av_name: 'animVal',
     el_type: 'SVGTextElement',
     prop_type: 'SVGAnimatedNumberList',
     list_type: 'SVGNumberList',
     item_type: 'SVGNumber',
-    attr_val_3a: '',
-    attr_val_3b: '',
-    attr_val_4 : '',
-    attr_val_5a: '',
-    attr_val_5b: '',
-    item_constructor: document.getElementById('svg').createSVGNumber
+    attr_val_3a: '0 20 40',
+    attr_val_3b: '60 40 20',
+    attr_val_4 : '40 20 10 80',
+    attr_val_5a: '90 30 60 20 70',
+    attr_val_5b: '30 20 70 30 90',
+    item_constructor: function() {
+      // We need this function literal to avoid "Illegal operation on
+      // WrappedNative prototype object" NS_ERROR_XPC_BAD_OP_ON_WN_PROTO.
+      return document.getElementById('svg').createSVGNumber();
+    }
   },
   {
     // SVGNumberList test:
-    target_element_id: 'feComponentTransfer',
+    target_element_id: 'feFuncR',
     attr_name: 'tableValues',
     prop_name: 'tableValues',
     bv_name: 'baseVal',
     av_name: 'animVal',
-    el_type: 'xxx',
+    el_type: 'SVGFEComponentTransferElement',
     prop_type: 'SVGAnimatedNumberList',
     list_type: 'SVGNumberList',
     item_type: 'SVGNumber',
-    attr_val_3a: '',
-    attr_val_3b: '',
-    attr_val_4 : '',
-    attr_val_5a: '',
-    attr_val_5b: '',
-    item_constructor: document.getElementById('svg').createSVGNumber
+    attr_val_3a: '0 .5 .2',
+    attr_val_3b: '1 .7 .1',
+    attr_val_4 : '.5 .3 .8 .2',
+    attr_val_5a: '3 4 5 6 7',
+    attr_val_5b: '7 6 5 4 3',
+    item_constructor: function() {
+      // We need this function literal to avoid "Illegal operation on
+      // WrappedNative prototype object" NS_ERROR_XPC_BAD_OP_ON_WN_PROTO.
+      return document.getElementById('svg').createSVGNumber();
+    }
   },
+/*
   {
     // SVGPointList test:
     target_element_id: 'polyline',
     attr_name: 'points',
     prop_name: null, // SVGAnimatedPoints is an inherited interface!
     bv_name: 'points',
     av_name: 'animatedPoints',
     el_type: 'SVGPolylineElement',
@@ -1091,17 +1106,19 @@ function run_animation_timeline_tests()
        t.list_type+' for '+t.bv_path+', or its list items.');
 
     is(t.animVal.numberOfItems, 5,
        'Even though all SMIL animation have finished, the number '+
        'of items in the '+t.list_type+' for '+t.av_path+
        ' should still be more than the same as the number of items in '+
        t.bv_path+' since one of the animations is still frozen.');
 
-    t.element.querySelector('animate').removeAttribute('fill');
+    var frozen_animate_element =
+      t.element.querySelector('animate[fill][attributeName="'+t.attr_name+'"]');
+    frozen_animate_element.removeAttribute('fill');
 
     ok(t.animVal.numberOfItems == t.baseVal.numberOfItems,
        'Once all SMIL animation have finished and been un-frozen, the number '+
        'of items in the '+t.list_type+' for '+t.av_path+
        ' should be the same as the number of items in '+t.bv_path+'.');
 
     ok(t.animVal.getItem(2) === t.old_animVal_items[2],
        'Even after an animation finishes and is un-frozen, the list items '+
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/smil/anim-feFuncR-tableValues-01-ref.svg
@@ -0,0 +1,52 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <title></title>
+
+  <linearGradient id="gradient">
+    <stop offset="0" stop-color="black" />
+    <stop offset="100%" stop-color="red" />
+  </linearGradient>
+
+  <!-- Comparison for calcMode="linear". -->
+
+  <filter id="f_calcMode_linear_to" x="0%" y="0%" width="100%" height="100%">
+    <feComponentTransfer>
+      <feFuncR type="table" tableValues="0 2 2 0"/>
+    </feComponentTransfer>
+  </filter>
+  <rect x="20" y="20" width="256" height="20" fill="url(#gradient)"
+        filter="url(#f_calcMode_linear_to)"/>
+
+
+  <!-- Comparison for 'by' animation. -->
+
+  <filter id="f_calcMode_linear_by" x="0%" y="0%" width="100%" height="100%">
+    <feComponentTransfer>
+      <feFuncR type="table" tableValues="0 2 2 0"/>
+    </feComponentTransfer>
+  </filter>
+  <rect x="20" y="60" width="256" height="20" fill="url(#gradient)"
+        filter="url(#f_calcMode_linear_by)"/>
+
+
+  <!-- Comparison for calcMode="paced". -->
+
+  <filter id="f_calcMode_paced" x="0%" y="0%" width="100%" height="100%">
+    <feComponentTransfer>
+      <feFuncR type="table" tableValues="0 2 2 0"/>
+    </feComponentTransfer>
+  </filter>
+  <rect x="20" y="100" width="256" height="20" fill="url(#gradient)"
+        filter="url(#f_calcMode_paced)"/>
+
+
+  <!-- Comparison for calcMode="discrete". -->
+
+  <filter id="f_calcMode_discrete" x="0%" y="0%" width="100%" height="100%">
+    <feComponentTransfer>
+      <feFuncR type="table" tableValues="0 2 2 0"/>
+    </feComponentTransfer>
+  </filter>
+  <rect x="20" y="140" width="256" height="20" fill="url(#gradient)"
+        filter="url(#f_calcMode_discrete)"/>
+
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/smil/anim-feFuncR-tableValues-01.svg
@@ -0,0 +1,101 @@
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:xlink="http://www.w3.org/1999/xlink"
+     class="reftest-wait"
+     onload="setTimeAndSnapshot(1, true)">
+  <title>Test animation of the &lt;number-list&gt; attribute on the 'text' element</title>
+  <script xlink:href="smil-util.js" type="text/javascript"/>
+
+  <linearGradient id="gradient">
+    <stop offset="0" stop-color="black" />
+    <stop offset="100%" stop-color="red" />
+  </linearGradient>
+
+  <!-- The difference between respective numbers in the effective 'from' and
+       'to' lists below is carefully designed to be a factor of 3. That way
+       our reference file (which checks against a one third complete animation)
+       can contain whole numbers, which is necessary to avoid failure due to
+       hard coded rounded numbers in the reference not matching platform
+       specific rounding behaviour.
+    -->
+
+
+  <!-- Test calcMode="linear". -->
+
+  <filter id="f_calcMode_linear_to" x="0%" y="0%" width="100%" height="100%">
+    <feComponentTransfer>
+      <feFuncR type="table" tableValues="-1 3 3 -1">
+
+        <!-- At 1s the animVal should be "0 2 2 0". -->
+        <animate attributeName="tableValues"
+                 calcMode="linear"
+                 begin="0s" dur="3s"
+                 to="2 0 0 2"
+                 fill="freeze"/>
+
+      </feFuncR>
+    </feComponentTransfer>
+  </filter>
+  <rect x="20" y="20" width="256" height="20" fill="url(#gradient)"
+        filter="url(#f_calcMode_linear_to)"/>
+
+
+  <!-- Test 'by' animation. -->
+
+  <filter id="f_calcMode_linear_by" x="0%" y="0%" width="100%" height="100%">
+    <feComponentTransfer>
+      <feFuncR type="table" tableValues="-1 3 3 -1">
+
+        <!-- At 1s the animVal should be "0 2 2 0". -->
+        <animate attributeName="tableValues"
+                 calcMode="linear"
+                 begin="0s" dur="3s"
+                 by="3 -3 -3 3"
+                 fill="freeze"/>
+
+      </feFuncR>
+    </feComponentTransfer>
+  </filter>
+  <rect x="20" y="60" width="256" height="20" fill="url(#gradient)"
+        filter="url(#f_calcMode_linear_by)"/>
+
+
+  <!-- Test calcMode="paced". -->
+
+  <filter id="f_calcMode_paced" x="0%" y="0%" width="100%" height="100%">
+    <feComponentTransfer>
+      <feFuncR type="table" tableValues="-1 3 3 -1">
+
+        <!-- At 1s the animVal should be "0 2 2 0". -->
+        <animate attributeName="tableValues"
+                 calcMode="paced"
+                 begin="0s" dur="3s"
+                 values="-1 3 3 -1; 1 1 1 1; 2 0 0 2"
+                 fill="freeze"/>
+
+      </feFuncR>
+    </feComponentTransfer>
+  </filter>
+  <rect x="20" y="100" width="256" height="20" fill="url(#gradient)"
+        filter="url(#f_calcMode_paced)"/>
+
+
+  <!-- Test calcMode="discrete". -->
+
+  <filter id="f_calcMode_discrete" x="0%" y="0%" width="100%" height="100%">
+    <feComponentTransfer>
+      <feFuncR type="table" tableValues="0 0 0 0">
+
+        <!-- The value should be "0 2 2 0" immediately. -->
+        <animate attributeName="tableValues"
+                 calcMode="discrete"
+                 begin="0s" dur="3s"
+                 to="0 2 2 0"
+                 fill="freeze"/>
+
+      </feFuncR>
+    </feComponentTransfer>
+  </filter>
+  <rect x="20" y="140" width="256" height="20" fill="url(#gradient)"
+        filter="url(#f_calcMode_discrete)"/>
+
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/smil/anim-text-rotate-01-ref.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+  <title></title>
+
+  <text transform="translate(20, 20)" rotate="110 120 130">ABC</text>
+  <text transform="translate(120, 20)" rotate="110 120 130">DEF</text>
+  <text transform="translate(220, 20)" rotate="110 120 130">GHI</text>
+  <text transform="translate(320, 20)" rotate="310 320 330">JKL</text>
+
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/smil/anim-text-rotate-01.svg
@@ -0,0 +1,73 @@
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:xlink="http://www.w3.org/1999/xlink"
+     class="reftest-wait"
+     onload="setTimeAndSnapshot(5, true)">
+  <title>Test animation of the &lt;number-list&gt; attribute on the 'text' element</title>
+  <script xlink:href="smil-util.js" type="text/javascript"/>
+
+  <!-- The difference between respective numbers in the effective 'from' and
+       'to' lists below is carefully designed to be a factor of 3. That way
+       our reference file (which checks against a one third complete animation)
+       can contain whole numbers, which is necessary to avoid failure due to
+       hard coded rounded numbers in the reference not matching platform
+       specific rounding behaviour.
+    -->
+
+  <!-- Test calcMode="linear". -->
+
+  <text transform="translate(20, 20)"
+        rotate="10 20 30">ABC
+
+    <!-- At 5s the animVal should be "110 120 130". -->
+    <animate attributeName="rotate"
+             calcMode="linear"
+             begin="0s" dur="15s"
+             to="310 320 330"
+             fill="freeze"/>
+
+  </text>
+
+
+  <!-- Test 'by' animation. -->
+
+  <text transform="translate(120, 20)"
+        rotate="10 20 30">DEF
+
+    <!-- At 5s the animVal should be "110 120 130". -->
+    <animate attributeName="rotate"
+             calcMode="linear"
+             begin="0s" dur="15s"
+             by="300 300 300"
+             fill="freeze"/>
+
+  </text>
+
+
+  <!-- Test calcMode="paced". -->
+
+  <text transform="translate(220, 20)">GHI
+
+    <!-- At 5s the animVal should be "110 120 130". -->
+    <animate attributeName="rotate"
+             calcMode="paced"
+             begin="0s" dur="15s"
+             values="10 20 30; 210 220 230; 310 320 330"
+             fill="freeze"/>
+
+  </text>
+
+
+  <!-- Test calcMode="discrete". -->
+
+  <text transform="translate(320, 20)" rotate="10 20 30">JKL
+
+    <!-- The value should be "310 320 330" immediately. -->
+    <animate attributeName="rotate"
+             calcMode="discrete"
+             begin="0s" dur="30s"
+             to="310 320 330"
+             fill="freeze"/>
+
+  </text>
+
+</svg>
--- a/layout/reftests/svg/smil/reftest.list
+++ b/layout/reftests/svg/smil/reftest.list
@@ -148,16 +148,19 @@ fails == anim-strokecolor-1.svg anim-sta
 == anim-targethref-3.svg anim-standard-ref.svg
 == anim-targethref-4.svg anim-standard-ref.svg
 == anim-targethref-5.svg anim-standard-ref.svg
 == anim-targethref-6.svg anim-standard-ref.svg
 == anim-targethref-7.svg anim-standard-ref.svg
 == anim-targethref-8.svg anim-standard-ref.svg
 == anim-targethref-9.svg anim-standard-ref.svg
 
+== anim-text-rotate-01.svg anim-text-rotate-01-ref.svg
+== anim-feFuncR-tableValues-01.svg anim-feFuncR-tableValues-01-ref.svg
+
 random == anim-text-x-y-dx-dy-01.svg anim-text-x-y-dx-dy-01-ref.svg # bug 579588
 
 == anim-width-done-1a.svg anim-standard-ref.svg
 == anim-width-done-1b.svg anim-standard-ref.svg
 
 == anim-x-done-1a.svg anim-standard-ref.svg
 == anim-x-done-1b.svg anim-standard-ref.svg
 == anim-x-interp-1.svg anim-x-interp-1-ref.svg
--- a/layout/svg/base/src/nsISVGChildFrame.h
+++ b/layout/svg/base/src/nsISVGChildFrame.h
@@ -44,19 +44,33 @@
 #include "nsCOMPtr.h"
 #include "nsRect.h"
 #include "gfxRect.h"
 #include "gfxMatrix.h"
 
 class gfxContext;
 class nsSVGRenderState;
 
+namespace mozilla {
+class SVGAnimatedNumberList;
+class SVGNumberList;
+class SVGAnimatedLengthList;
+class SVGLengthList;
+class SVGUserUnitList;
+}
+
 class nsISVGChildFrame : public nsQueryFrame
 {
 public:
+  typedef mozilla::SVGAnimatedNumberList SVGAnimatedNumberList;
+  typedef mozilla::SVGNumberList SVGNumberList;
+  typedef mozilla::SVGAnimatedLengthList SVGAnimatedLengthList;
+  typedef mozilla::SVGLengthList SVGLengthList;
+  typedef mozilla::SVGUserUnitList SVGUserUnitList;
+
   NS_DECL_QUERYFRAME_TARGET(nsISVGChildFrame)
 
   // Paint this frame - aDirtyRect is the area being redrawn, in frame
   // offset pixel coordinates
   NS_IMETHOD PaintSVG(nsSVGRenderState* aContext,
                       const nsIntRect *aDirtyRect)=0;
 
   // Check if this frame or children contain the given point,
--- a/layout/svg/base/src/nsSVGAFrame.cpp
+++ b/layout/svg/base/src/nsSVGAFrame.cpp
@@ -93,16 +93,19 @@ public:
   virtual void NotifySVGChanged(PRUint32 aFlags);
   
   // nsSVGContainerFrame methods:
   virtual gfxMatrix GetCanvasTM();
 
   // nsSVGTextContainerFrame methods:
   virtual void GetXY(mozilla::SVGUserUnitList *aX, mozilla::SVGUserUnitList *aY);
   virtual void GetDxDy(mozilla::SVGUserUnitList *aDx, mozilla::SVGUserUnitList *aDy);
+  virtual const SVGNumberList* GetRotate() {
+    return nsnull;
+  }
 
 private:
   nsCOMPtr<nsIDOMSVGMatrix> mCanvasTM;
 };
 
 //----------------------------------------------------------------------
 // Implementation
 
--- a/layout/svg/base/src/nsSVGGlyphFrame.cpp
+++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp
@@ -1247,17 +1247,17 @@ nsSVGGlyphFrame::GetEffectiveDxDy(PRInt3
   dxCount = NS_MIN(dxCount, strLength);
   aDx.AppendElements(dx.Elements() + mStartIndex, dxCount);
 
   PRInt32 dyCount = NS_MAX((PRInt32)(dy.Length() - mStartIndex), 0);
   dyCount = NS_MIN(dyCount, strLength);
   aDy.AppendElements(dy.Elements() + mStartIndex, dyCount);
 }
 
-already_AddRefed<nsIDOMSVGNumberList>
+const SVGNumberList*
 nsSVGGlyphFrame::GetRotate()
 {
   nsSVGTextContainerFrame *containerFrame;
   containerFrame = static_cast<nsSVGTextContainerFrame *>(mParent);
   if (containerFrame)
     return containerFrame->GetRotate();
   return nsnull;
 }
--- a/layout/svg/base/src/nsSVGGlyphFrame.h
+++ b/layout/svg/base/src/nsSVGGlyphFrame.h
@@ -211,18 +211,18 @@ protected:
   PRBool GetGlobalTransform(gfxMatrix *aMatrix);
   void SetupGlobalTransform(gfxContext *aContext);
   nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
                         nscolor *foreground, nscolor *background);
   float GetSubStringAdvance(PRUint32 charnum, PRUint32 fragmentChars,
                             float aMetricsScale);
   gfxFloat GetBaselineOffset(float aMetricsScale);
 
-  virtual void GetDxDy(mozilla::SVGUserUnitList *aDx, mozilla::SVGUserUnitList *aDy);
-  already_AddRefed<nsIDOMSVGNumberList> GetRotate();
+  virtual void GetDxDy(SVGUserUnitList *aDx, SVGUserUnitList *aDy);
+  virtual const SVGNumberList *GetRotate();
 
   // Used to support GetBBoxContribution by making GetConvasTM use this as the
   // parent transform instead of the real CanvasTM.
   nsCOMPtr<nsIDOMSVGMatrix> mOverrideCanvasTM;
 
   // Owning pointer, must call gfxTextRunWordCache::RemoveTextRun before deleting
   gfxTextRun *mTextRun;
   gfxPoint mPosition;
--- a/layout/svg/base/src/nsSVGTextContainerFrame.cpp
+++ b/layout/svg/base/src/nsSVGTextContainerFrame.cpp
@@ -35,20 +35,22 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGContainerFrame.h"
 #include "nsSVGTextFrame.h"
 #include "nsSVGUtils.h"
 #include "nsSVGOuterSVGFrame.h"
 #include "nsIDOMSVGTextElement.h"
 #include "nsIDOMSVGAnimatedLengthList.h"
-#include "nsIDOMSVGAnimatedNumberList.h"
+#include "SVGAnimatedNumberList.h"
+#include "SVGNumberList.h"
 #include "nsISVGGlyphFragmentLeaf.h"
 #include "nsDOMError.h"
 #include "SVGLengthList.h"
+#include "nsSVGTextPositioningElement.h"
 
 using namespace mozilla;
 
 //----------------------------------------------------------------------
 // nsQueryFrame methods
 
 NS_QUERYFRAME_HEAD(nsSVGTextContainerFrame)
   NS_QUERYFRAME_ENTRY(nsSVGTextContainerFrame)
@@ -76,30 +78,23 @@ nsSVGTextContainerFrame::GetDxDy(SVGUser
 {
   // SVGUserUnitList is lazy, so there's little overhead it getting the x
   // and y lists even though we ignore them.
   SVGUserUnitList xLengthList, yLengthList;
   static_cast<nsSVGElement*>(mContent)->
     GetAnimatedLengthListValues(&xLengthList, &yLengthList, aDx, aDy, nsnull);
 }
 
-already_AddRefed<nsIDOMSVGNumberList>
+const SVGNumberList*
 nsSVGTextContainerFrame::GetRotate()
 {
-  nsCOMPtr<nsIDOMSVGTextPositioningElement> tpElement =
-    do_QueryInterface(mContent);
-
-  if (!tpElement)
-    return nsnull;
-
-  nsCOMPtr<nsIDOMSVGAnimatedNumberList> animNumberList;
-  tpElement->GetRotate(getter_AddRefs(animNumberList));
-  nsIDOMSVGNumberList *retval;
-  animNumberList->GetAnimVal(&retval);
-  return retval;
+  SVGAnimatedNumberList *animList =
+    static_cast<nsSVGElement*>(mContent)->
+      GetAnimatedNumberList(nsGkAtoms::rotate);
+  return animList ? &animList->GetAnimValue() : nsnull;
 }
 
 //----------------------------------------------------------------------
 // nsIFrame methods
 
 NS_IMETHODIMP
 nsSVGTextContainerFrame::InsertFrames(nsIAtom* aListName,
                                       nsIFrame* aPrevFrame,
@@ -425,40 +420,36 @@ nsSVGTextContainerFrame::CopyPositionLis
   for (PRUint32 i = selfCount; i < parentCount; i++) {
     dstList[i] = (*parentList)[aOffset + i];
   }
 
 }
 
 void
 nsSVGTextContainerFrame::CopyRotateList(nsTArray<float> *parentList,
-                                        nsCOMPtr<nsIDOMSVGNumberList> selfList,
+                                        const SVGNumberList *selfList,
                                         nsTArray<float> &dstList,
                                         PRUint32 aOffset)
 {
   dstList.Clear();
 
   PRUint32 strLength = GetNumberOfChars();
   PRUint32 parentCount = 0;
   if (parentList && parentList->Length() > aOffset) {
     parentCount = NS_MIN(parentList->Length() - aOffset, strLength);
   }
 
-  PRUint32 selfCount = 0;
-  if (selfList) {
-    selfList->GetNumberOfItems(&selfCount);
-  }
-  selfCount = NS_MIN(selfCount, strLength);
+  PRUint32 selfCount = NS_MIN(selfList ? selfList->Length() : 0, strLength);
+  PRUint32 count = NS_MAX(parentCount, selfCount);
 
-  PRUint32 count = NS_MAX(parentCount, selfCount);
   if (count > 0) {
     if (!dstList.SetLength(count))
       return;
     for (PRUint32 i = 0; i < selfCount; i++) {
-      dstList[i] = nsSVGUtils::GetNumberListValue(selfList, i);
+      dstList[i] = (*selfList)[i];
     }
     for (PRUint32 i = selfCount; i < parentCount; i++) {
       dstList[i] = (*parentList)[aOffset + i];
     }
   } else if (parentList && !parentList->IsEmpty()) {
     // rotate is applied to extra characters too
     dstList.AppendElement((*parentList)[parentList->Length() - 1]);
   }
@@ -485,17 +476,17 @@ nsSVGTextContainerFrame::BuildPositionLi
   CopyPositionList(parentX, &x, mX, aOffset);
   CopyPositionList(parentY, &y, mY, aOffset);
 
   SVGUserUnitList dx, dy;
   GetDxDy(&dx, &dy);
   CopyPositionList(parentDx, &dx, mDx, aOffset);
   CopyPositionList(parentDy, &dy, mDy, aOffset);
 
-  nsCOMPtr<nsIDOMSVGNumberList> rotate = GetRotate();
+  const SVGNumberList *rotate = GetRotate();
   CopyRotateList(parentRotate, rotate, mRotate, aOffset);
 
   PRUint32 startIndex = 0;
   nsIFrame* kid = mFrames.FirstChild();
   while (kid) {
     nsSVGTextContainerFrame *text = do_QueryFrame(kid);
     nsISVGGlyphFragmentLeaf *leaf = do_QueryFrame(kid);
     if (text) {
--- a/layout/svg/base/src/nsSVGTextContainerFrame.h
+++ b/layout/svg/base/src/nsSVGTextContainerFrame.h
@@ -33,35 +33,31 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef NS_SVGTEXTCONTAINERFRAME_H
 #define NS_SVGTEXTCONTAINERFRAME_H
 
 #include "nsSVGContainerFrame.h"
-#include "nsIDOMSVGNumberList.h"
 
 class nsISVGGlyphFragmentNode;
 class nsISVGGlyphFragmentLeaf;
 class nsSVGTextFrame;
-namespace mozilla {
-class SVGUserUnitList;
-}
 
 class nsSVGTextContainerFrame : public nsSVGDisplayContainerFrame
 {
 public:
   nsSVGTextContainerFrame(nsStyleContext* aContext) :
     nsSVGDisplayContainerFrame(aContext) {}
 
   void NotifyGlyphMetricsChange();
-  virtual void GetXY(mozilla::SVGUserUnitList *aX, mozilla::SVGUserUnitList *aY);
-  virtual void GetDxDy(mozilla::SVGUserUnitList *aDx, mozilla::SVGUserUnitList *aDy);
-  virtual already_AddRefed<nsIDOMSVGNumberList> GetRotate();
+  virtual void GetXY(SVGUserUnitList *aX, SVGUserUnitList *aY);
+  virtual void GetDxDy(SVGUserUnitList *aDx, SVGUserUnitList *aDy);
+  virtual const SVGNumberList *GetRotate();
   
 public:
   NS_DECL_QUERYFRAME_TARGET(nsSVGTextContainerFrame)
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIFrame
   NS_IMETHOD InsertFrames(nsIAtom*        aListName,
@@ -110,21 +106,21 @@ protected:
   nsISVGGlyphFragmentNode *
   GetNextGlyphFragmentChildNode(nsISVGGlyphFragmentNode *node);
 
   /*
    * Set Whitespace handling
    */
   void SetWhitespaceHandling();
   void CopyPositionList(nsTArray<float> *parentList,
-                        mozilla::SVGUserUnitList *selfList,
+                        SVGUserUnitList *selfList,
                         nsTArray<float> &dstList,
                         PRUint32 aOffset);
   void CopyRotateList(nsTArray<float> *parentList,
-                      nsCOMPtr<nsIDOMSVGNumberList> selfList,
+                      const SVGNumberList *selfList,
                       nsTArray<float> &dstList,
                       PRUint32 aOffset);
   PRUint32 BuildPositionList(PRUint32 aOffset, PRUint32 aDepth);
 
 private:
   /*
    * Returns the glyph fragment containing a particular character
    */
--- a/layout/svg/base/src/nsSVGTextPathFrame.cpp
+++ b/layout/svg/base/src/nsSVGTextPathFrame.cpp
@@ -96,17 +96,17 @@ nsSVGTextPathFrame::GetXY(SVGUserUnitLis
 void
 nsSVGTextPathFrame::GetDxDy(SVGUserUnitList *aDx, SVGUserUnitList *aDy)
 {
   // 'dx' and 'dy' don't apply to 'textPath'
   aDx->Clear();
   aDy->Clear();
 }
 
-already_AddRefed<nsIDOMSVGNumberList>
+const SVGNumberList*
 nsSVGTextPathFrame::GetRotate()
 {
   return nsnull;
 }
 
 //----------------------------------------------------------------------
 // nsSVGTextPathFrame methods:
 
--- a/layout/svg/base/src/nsSVGTextPathFrame.h
+++ b/layout/svg/base/src/nsSVGTextPathFrame.h
@@ -34,17 +34,20 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef NSSVGTEXTPATHFRAME_H
 #define NSSVGTEXTPATHFRAME_H
 
 #include "nsSVGTSpanFrame.h"
 #include "SVGLengthList.h"
-#include "nsSVGNumberList.h"
+
+namespace mozilla {
+class SVGNumberList;
+}
 
 typedef nsSVGTSpanFrame nsSVGTextPathFrameBase;
 
 class nsSVGTextPathFrame : public nsSVGTextPathFrameBase
 {
   friend nsIFrame*
   NS_NewSVGTextPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 protected:
@@ -80,17 +83,17 @@ public:
   // nsSVGTextPathFrame methods:
   already_AddRefed<gfxFlattenedPath> GetFlattenedPath();
   nsIFrame *GetPathFrame();
 
   gfxFloat GetStartOffset();
   gfxFloat GetPathScale();
 protected:
 
-  virtual void GetXY(mozilla::SVGUserUnitList *aX, mozilla::SVGUserUnitList *aY);
-  virtual void GetDxDy(mozilla::SVGUserUnitList *aDx, mozilla::SVGUserUnitList *aDy);
-  virtual already_AddRefed<nsIDOMSVGNumberList> GetRotate();
+  virtual void GetXY(SVGUserUnitList *aX, SVGUserUnitList *aY);
+  virtual void GetDxDy(SVGUserUnitList *aDx, SVGUserUnitList *aDy);
+  virtual const SVGNumberList *GetRotate();
 
 private:
   already_AddRefed<gfxFlattenedPath> GetFlattenedPath(nsIFrame *path);
 };
 
 #endif
--- a/layout/svg/base/src/nsSVGUtils.cpp
+++ b/layout/svg/base/src/nsSVGUtils.cpp
@@ -86,17 +86,16 @@
 #include "nsMathUtils.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsSVGFilterPaintCallback.h"
 #include "nsSVGGeometryFrame.h"
 #include "nsComputedDOMStyle.h"
 #include "nsSVGPathGeometryFrame.h"
 #include "prdtoa.h"
 #include "mozilla/dom/Element.h"
-#include "nsIDOMSVGNumberList.h"
 
 using namespace mozilla::dom;
 
 gfxASurface *nsSVGUtils::gThebesComputationalSurface = nsnull;
 
 // c = n / 255
 // (c <= 0.0031308 ? c * 12.92 : 1.055 * pow(c, 1 / 2.4) - 0.055) * 255 + 0.5
 static const PRUint8 glinearRGBTosRGBMap[256] = {
@@ -1513,31 +1512,16 @@ nsSVGUtils::NumberFromString(const nsASt
     if (*rest == '\0') {
       *aValue = value;
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
-/* static */ float
-nsSVGUtils::GetNumberListValue(nsIDOMSVGNumberList *aList, PRUint32 aIndex)
-{
-  if (!aList) {
-    return 0.0f;
-  }
-  nsCOMPtr<nsIDOMSVGNumber> number;
-  nsresult rv = aList->GetItem(aIndex, getter_AddRefs(number));
-  float value = 0.0f;
-  if (NS_SUCCEEDED(rv)) {
-    number->GetValue(&value);
-  }
-  return value;
-}
-
 // ----------------------------------------------------------------------
 
 nsSVGRenderState::nsSVGRenderState(nsIRenderingContext *aContext) :
   mRenderMode(NORMAL), mRenderingContext(aContext), mPaintingToWindow(PR_FALSE)
 {
   mGfxContext = aContext->ThebesContext();
 }
 
--- a/layout/svg/base/src/nsSVGUtils.h
+++ b/layout/svg/base/src/nsSVGUtils.h
@@ -55,17 +55,16 @@ class nsPresContext;
 class nsIContent;
 class nsStyleContext;
 class nsStyleCoord;
 class nsFrameList;
 class nsIFrame;
 struct nsStyleSVGPaint;
 class nsIDOMSVGElement;
 class nsIDOMSVGLength;
-class nsIDOMSVGNumberList;
 class nsIURI;
 class nsSVGOuterSVGFrame;
 class nsSVGPreserveAspectRatio;
 class nsIAtom;
 class nsSVGLength2;
 class nsSVGElement;
 class nsSVGSVGElement;
 class nsAttrValue;
@@ -127,16 +126,23 @@ class Element;
 
 inline PRBool
 IsSVGWhitespace(char aChar)
 {
   return aChar == '\x20' || aChar == '\x9' ||
          aChar == '\xD'  || aChar == '\xA';
 }
 
+inline PRBool
+IsSVGWhitespace(PRUnichar aChar)
+{
+  return aChar == PRUnichar('\x20') || aChar == PRUnichar('\x9') ||
+         aChar == PRUnichar('\xD')  || aChar == PRUnichar('\xA');
+}
+
 /*
  * Checks the svg enable preference and if a renderer could
  * successfully be created.  Declared as a function instead of a
  * nsSVGUtil method so that files that can't pull in nsSVGUtils.h (due
  * to cairo.h usage) can still query this information.
  */
 PRBool NS_SVGEnabled();
 
@@ -597,21 +603,16 @@ public:
    */
   static PRInt32 ClampToInt(double aVal)
   {
     return NS_lround(NS_MAX(double(PR_INT32_MIN),
                             NS_MIN(double(PR_INT32_MAX), aVal)));
   }
 
   /**
-   * Returns aIndex-th item of nsIDOMSVGNumberList
-   */
-  static float GetNumberListValue(nsIDOMSVGNumberList *aList, PRUint32 aIndex);
-
-  /**
    * Given a nsIContent* that is actually an nsSVGSVGElement*, this method
    * checks whether it currently has a valid viewBox, and returns true if so.
    *
    * No other type of element should be passed to this method.
    * (In debug builds, anything non-<svg> will trigger an abort; in non-debug
    * builds, it will trigger a PR_FALSE return-value as a safe fallback.)
    */
   static PRBool RootSVGElementHasViewbox(const nsIContent *aRootSVGElem);