Bug 607854 - implement SVGTests interface. r=jwatt
authorRobert Longson <longsonr@gmail.com>
Sat, 31 Dec 2011 09:44:03 +0000
changeset 84835 883815d2edb2e7104f7c0c7cf1164db083b2b4b8
parent 84834 a895e9432ea4eebaf577c2e6937c7de15385bebc
child 84836 0341759ffb4cd88254b45b09bf3ecaf35a34acf1
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwatt
bugs607854
milestone12.0a1
Bug 607854 - implement SVGTests interface. r=jwatt
content/base/src/nsGenericElement.cpp
content/svg/content/src/DOMSVGStringList.cpp
content/svg/content/src/DOMSVGStringList.h
content/svg/content/src/DOMSVGTests.cpp
content/svg/content/src/DOMSVGTests.h
content/svg/content/src/Makefile.in
content/svg/content/src/SVGStringList.cpp
content/svg/content/src/SVGStringList.h
content/svg/content/src/nsSVGAElement.cpp
content/svg/content/src/nsSVGAElement.h
content/svg/content/src/nsSVGAltGlyphElement.cpp
content/svg/content/src/nsSVGAnimateElement.cpp
content/svg/content/src/nsSVGAnimateMotionElement.cpp
content/svg/content/src/nsSVGAnimateTransformElement.cpp
content/svg/content/src/nsSVGAnimationElement.cpp
content/svg/content/src/nsSVGAnimationElement.h
content/svg/content/src/nsSVGCircleElement.cpp
content/svg/content/src/nsSVGClipPathElement.cpp
content/svg/content/src/nsSVGClipPathElement.h
content/svg/content/src/nsSVGDefsElement.cpp
content/svg/content/src/nsSVGElement.cpp
content/svg/content/src/nsSVGElement.h
content/svg/content/src/nsSVGElementList.h
content/svg/content/src/nsSVGEllipseElement.cpp
content/svg/content/src/nsSVGFeatures.cpp
content/svg/content/src/nsSVGFeatures.h
content/svg/content/src/nsSVGFilterElement.cpp
content/svg/content/src/nsSVGFilterElement.h
content/svg/content/src/nsSVGForeignObjectElement.cpp
content/svg/content/src/nsSVGForeignObjectElement.h
content/svg/content/src/nsSVGGElement.cpp
content/svg/content/src/nsSVGGradientElement.cpp
content/svg/content/src/nsSVGGradientElement.h
content/svg/content/src/nsSVGImageElement.cpp
content/svg/content/src/nsSVGLineElement.cpp
content/svg/content/src/nsSVGMaskElement.cpp
content/svg/content/src/nsSVGMaskElement.h
content/svg/content/src/nsSVGPathElement.cpp
content/svg/content/src/nsSVGPathGeometryElement.cpp
content/svg/content/src/nsSVGPathGeometryElement.h
content/svg/content/src/nsSVGPatternElement.cpp
content/svg/content/src/nsSVGPatternElement.h
content/svg/content/src/nsSVGPolygonElement.cpp
content/svg/content/src/nsSVGPolylineElement.cpp
content/svg/content/src/nsSVGRectElement.cpp
content/svg/content/src/nsSVGSVGElement.cpp
content/svg/content/src/nsSVGSVGElement.h
content/svg/content/src/nsSVGSetElement.cpp
content/svg/content/src/nsSVGSwitchElement.cpp
content/svg/content/src/nsSVGSwitchElement.h
content/svg/content/src/nsSVGSymbolElement.cpp
content/svg/content/src/nsSVGTSpanElement.cpp
content/svg/content/src/nsSVGTextContentElement.cpp
content/svg/content/src/nsSVGTextContentElement.h
content/svg/content/src/nsSVGTextElement.cpp
content/svg/content/src/nsSVGTextPathElement.cpp
content/svg/content/src/nsSVGUseElement.cpp
content/svg/content/src/nsSVGUseElement.h
content/svg/content/test/test_SVGxxxList.xhtml
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsDOMClassInfoClasses.h
dom/interfaces/svg/Makefile.in
dom/interfaces/svg/nsIDOMSVGStringList.idl
dom/interfaces/svg/nsIDOMSVGTests.idl
layout/base/nsCSSFrameConstructor.cpp
layout/reftests/svg/conditions-06.svg
layout/reftests/svg/reftest.list
layout/svg/base/src/nsSVGOuterSVGFrame.cpp
layout/svg/base/src/nsSVGOuterSVGFrame.h
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -2437,17 +2437,17 @@ nsGenericElement::InternalIsSupported(ns
     }
   } else if (PL_strcasecmp(f, "XPath") == 0) {
     if (aVersion.IsEmpty() ||
         PL_strcmp(v, "3.0") == 0) {
       *aReturn = true;
     }
   } else if (PL_strcasecmp(f, "SVGEvents") == 0 ||
              PL_strcasecmp(f, "SVGZoomEvents") == 0 ||
-             nsSVGFeatures::HaveFeature(aObject, aFeature)) {
+             nsSVGFeatures::HasFeature(aObject, aFeature)) {
     if (aVersion.IsEmpty() ||
         PL_strcmp(v, "1.0") == 0 ||
         PL_strcmp(v, "1.1") == 0) {
       *aReturn = true;
     }
   }
   else if (NS_SMILEnabled() && PL_strcasecmp(f, "TimeControl") == 0) {
     if (aVersion.IsEmpty() || PL_strcmp(v, "1.0") == 0) {
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/DOMSVGStringList.cpp
@@ -0,0 +1,199 @@
+/* -*- 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
+ * Robert Longson <longsonr@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * 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 "DOMSVGStringList.h"
+#include "DOMSVGTests.h"
+#include "nsDOMError.h"
+#include "nsCOMPtr.h"
+#include "nsSVGAttrTearoffTable.h"
+
+// See the architecture comment in this file's header.
+
+namespace mozilla {
+
+static nsSVGAttrTearoffTable<SVGStringList, DOMSVGStringList>
+  sSVGStringListTearoffTable;
+
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION(DOMSVGStringList, mElement)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGStringList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGStringList)
+
+} // namespace mozilla
+
+DOMCI_DATA(SVGStringList, mozilla::DOMSVGStringList)
+namespace mozilla {
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGStringList)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGStringList)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGStringList)
+NS_INTERFACE_MAP_END
+
+
+/* static */ already_AddRefed<DOMSVGStringList>
+DOMSVGStringList::GetDOMWrapper(SVGStringList *aList,
+                                nsSVGElement *aElement,
+                                bool aIsConditionalProcessingAttribute,
+                                PRUint8 aAttrEnum)
+{
+  DOMSVGStringList *wrapper =
+    sSVGStringListTearoffTable.GetTearoff(aList);
+  if (!wrapper) {
+    wrapper = new DOMSVGStringList(aElement, 
+                                   aIsConditionalProcessingAttribute,
+                                   aAttrEnum);
+    sSVGStringListTearoffTable.AddTearoff(aList, wrapper);
+  }
+  NS_ADDREF(wrapper);
+  return wrapper;
+}
+
+DOMSVGStringList::~DOMSVGStringList()
+{
+  // Script no longer has any references to us.
+  sSVGStringListTearoffTable.RemoveTearoff(&InternalList());
+}
+
+// ----------------------------------------------------------------------------
+// nsIDOMSVGStringList implementation:
+
+NS_IMETHODIMP
+DOMSVGStringList::GetNumberOfItems(PRUint32 *aNumberOfItems)
+{
+  *aNumberOfItems = InternalList().Length();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGStringList::Clear()
+{
+  if (InternalList().IsExplicitlySet()) {
+    InternalList().Clear();
+    mElement->DidChangeStringList(mIsConditionalProcessingAttribute,
+                                  mAttrEnum);
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGStringList::Initialize(const nsAString & newItem, nsAString & _retval)
+{
+  if (InternalList().IsExplicitlySet()) {
+    InternalList().Clear();
+  }
+  return InsertItemBefore(newItem, 0, _retval);
+}
+
+NS_IMETHODIMP
+DOMSVGStringList::GetItem(PRUint32 index,
+                          nsAString & _retval)
+{
+  if (index >= InternalList().Length()) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  }
+  _retval = InternalList()[index];
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGStringList::InsertItemBefore(const nsAString & newItem,
+                                   PRUint32 index,
+                                   nsAString & _retval)
+{
+  index = NS_MIN(index, InternalList().Length());
+
+  // Ensure we have enough memory so we can avoid complex error handling below:
+  if (!InternalList().SetCapacity(InternalList().Length() + 1)) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  InternalList().InsertItem(index, newItem);
+
+  mElement->DidChangeStringList(mIsConditionalProcessingAttribute, mAttrEnum);
+  _retval = newItem;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGStringList::ReplaceItem(const nsAString & newItem,
+                              PRUint32 index,
+                              nsAString & _retval)
+{
+  if (index >= InternalList().Length()) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  }
+
+  _retval = InternalList()[index];
+  InternalList().ReplaceItem(index, newItem);
+
+  mElement->DidChangeStringList(mIsConditionalProcessingAttribute, mAttrEnum);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGStringList::RemoveItem(PRUint32 index,
+                             nsAString & _retval)
+{
+  if (index >= InternalList().Length()) {
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+  }
+
+  InternalList().RemoveItem(index);
+
+  mElement->DidChangeStringList(mIsConditionalProcessingAttribute, mAttrEnum);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMSVGStringList::AppendItem(const nsAString & newItem,
+                             nsAString & _retval)
+{
+  return InsertItemBefore(newItem, InternalList().Length(), _retval);
+}
+
+SVGStringList &
+DOMSVGStringList::InternalList()
+{
+  if (mIsConditionalProcessingAttribute) {
+    nsCOMPtr<DOMSVGTests> tests = do_QueryInterface(mElement);
+    return tests->mStringListAttributes[mAttrEnum];
+  }
+  return mElement->GetStringListInfo().mStringLists[mAttrEnum];
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/DOMSVGStringList.h
@@ -0,0 +1,129 @@
+/* -*- 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
+ * Robert Longson <longsonr@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * 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_DOMSVGSTRINGLIST_H__
+#define MOZILLA_DOMSVGSTRINGLIST_H__
+
+#include "nsIDOMSVGStringList.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsCOMArray.h"
+#include "nsAutoPtr.h"
+
+class nsSVGElement;
+
+namespace mozilla {
+
+class SVGStringList;
+
+/**
+ * Class DOMSVGStringList
+ *
+ * This class is used to create the DOM tearoff objects that wrap internal
+ * SVGPathData objects.
+ *
+ * See the architecture comment in DOMSVGAnimatedLengthList.h first (that's
+ * LENGTH list), then continue reading the remainder of this comment.
+ *
+ * The architecture of this class is similar to that of DOMSVGLengthList
+ * except for two important aspects:
+ *
+ * First, since there is no nsIDOMSVGAnimatedStringList interface in SVG, we
+ * have no parent DOMSVGAnimatedStringList (unlike DOMSVGLengthList which has
+ * a parent DOMSVGAnimatedLengthList class). As a consequence, much of the
+ * logic that would otherwise be in DOMSVGAnimatedStringList (and is in
+ * DOMSVGAnimatedLengthList) is contained in this class.
+ *
+ * Second, since there is no nsIDOMSVGString interface in SVG, we have no
+ * DOMSVGString items to maintain. As far as script is concerned, objects
+ * of this class contain a list of strings, not a list of mutable objects
+ * like the other SVG list types. As a result, unlike the other SVG list
+ * types, this class does not create its items lazily on demand and store
+ * them so it can return the same objects each time. It simply returns a new
+ * string each time any given item is requested.
+ */
+class DOMSVGStringList : public nsIDOMSVGStringList
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGStringList)
+  NS_DECL_NSIDOMSVGSTRINGLIST
+
+  /**
+   * Factory method to create and return a DOMSVGStringList wrapper
+   * for a given internal SVGStringList object. The factory takes care
+   * of caching the object that it returns so that the same object can be
+   * returned for the given SVGStringList 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. If that happens, any subsequent
+   * call requesting the DOM wrapper for the SVGStringList will naturally
+   * result in a new DOMSVGStringList being returned.
+   */
+  static already_AddRefed<DOMSVGStringList>
+    GetDOMWrapper(SVGStringList *aList,
+                  nsSVGElement *aElement,
+                  bool aIsConditionalProcessingAttribute,
+                  PRUint8 aAttrEnum);
+
+private:
+  /**
+   * Only our static GetDOMWrapper() factory method may create objects of our
+   * type.
+   */
+  DOMSVGStringList(nsSVGElement *aElement,
+                   bool aIsConditionalProcessingAttribute, PRUint8 aAttrEnum)
+    : mElement(aElement)
+    , mAttrEnum(aAttrEnum)
+    , mIsConditionalProcessingAttribute(aIsConditionalProcessingAttribute)
+  {}
+
+  ~DOMSVGStringList();
+
+  void DidChangeStringList(PRUint8 aAttrEnum, bool aDoSetAttr);
+
+  SVGStringList &InternalList();
+
+  // Strong ref to our element to keep it alive.
+  nsRefPtr<nsSVGElement> mElement;
+
+  PRUint8 mAttrEnum;
+
+  bool    mIsConditionalProcessingAttribute;
+};
+
+} // namespace mozilla
+
+#endif // MOZILLA_DOMSVGSTRINGLIST_H__
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/DOMSVGTests.cpp
@@ -0,0 +1,289 @@
+/* -*- 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
+ * Robert Longson <longsonr@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * 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 "DOMSVGTests.h"
+#include "DOMSVGStringList.h"
+#include "nsSVGFeatures.h"
+#include "nsSVGSwitchElement.h"
+#include "nsCharSeparatedTokenizer.h"
+#include "nsStyleUtil.h"
+#include "nsSVGUtils.h"
+#include "mozilla/Preferences.h"
+
+using namespace mozilla;
+
+NS_IMPL_ISUPPORTS1(DOMSVGTests, nsIDOMSVGTests)
+
+DOMSVGTests::StringListInfo DOMSVGTests::sStringListInfo[3] =
+{
+  { &nsGkAtoms::requiredFeatures, false },
+  { &nsGkAtoms::requiredExtensions, false },
+  { &nsGkAtoms::systemLanguage, true }
+};
+
+/* readonly attribute nsIDOMSVGStringList requiredFeatures; */
+NS_IMETHODIMP
+DOMSVGTests::GetRequiredFeatures(nsIDOMSVGStringList * *aRequiredFeatures)
+{
+  nsCOMPtr<nsSVGElement> element = do_QueryInterface(this);
+  *aRequiredFeatures = DOMSVGStringList::GetDOMWrapper(
+                         &mStringListAttributes[FEATURES], element, true, FEATURES).get();
+  return NS_OK;
+}
+
+/* readonly attribute nsIDOMSVGStringList requiredExtensions; */
+NS_IMETHODIMP
+DOMSVGTests::GetRequiredExtensions(nsIDOMSVGStringList * *aRequiredExtensions)
+{
+  nsCOMPtr<nsSVGElement> element = do_QueryInterface(this);
+  *aRequiredExtensions = DOMSVGStringList::GetDOMWrapper(
+                           &mStringListAttributes[EXTENSIONS], element, true, EXTENSIONS).get();
+  return NS_OK;
+}
+
+/* readonly attribute nsIDOMSVGStringList systemLanguage; */
+NS_IMETHODIMP
+DOMSVGTests::GetSystemLanguage(nsIDOMSVGStringList * *aSystemLanguage)
+{
+  nsCOMPtr<nsSVGElement> element = do_QueryInterface(this);
+  *aSystemLanguage = DOMSVGStringList::GetDOMWrapper(
+                       &mStringListAttributes[LANGUAGE], element, true, LANGUAGE).get();
+  return NS_OK;
+}
+
+/* boolean hasExtension (in DOMString extension); */
+NS_IMETHODIMP
+DOMSVGTests::HasExtension(const nsAString & extension, bool *_retval)
+{
+  *_retval = nsSVGFeatures::HasExtension(extension);
+  return NS_OK;
+}
+
+bool
+DOMSVGTests::IsConditionalProcessingAttribute(const nsIAtom* aAttribute) const
+{
+  for (PRUint32 i = 0; i < ArrayLength(sStringListInfo); i++) {
+    if (aAttribute == *sStringListInfo[i].mName) {
+      return true;
+    }
+  }
+  return false;
+}
+
+PRInt32
+DOMSVGTests::GetBestLanguagePreferenceRank(const nsSubstring& aAcceptLangs) const
+{
+  const nsDefaultStringComparator defaultComparator;
+
+  PRInt32 lowestRank = -1;
+
+  for (PRUint32 i = 0; i < mStringListAttributes[LANGUAGE].Length(); i++) {
+    nsCharSeparatedTokenizer languageTokenizer(aAcceptLangs, ',');
+    PRInt32 index = 0;
+    while (languageTokenizer.hasMoreTokens()) {
+      const nsSubstring &languageToken = languageTokenizer.nextToken();
+      bool exactMatch = (languageToken == mStringListAttributes[LANGUAGE][i]);
+      bool prefixOnlyMatch =
+        !exactMatch &&
+        nsStyleUtil::DashMatchCompare(mStringListAttributes[LANGUAGE][i],
+                                      languageTokenizer.nextToken(),
+                                      defaultComparator);
+      if (index == 0 && exactMatch) {
+        // best possible match
+        return 0;
+      }
+      if ((exactMatch || prefixOnlyMatch) &&
+          (lowestRank == -1 || 2 * index + prefixOnlyMatch < lowestRank)) {
+        lowestRank = 2 * index + prefixOnlyMatch;
+      }
+      ++index;
+    }
+  }
+  return lowestRank;
+}
+
+const nsString * const DOMSVGTests::kIgnoreSystemLanguage = (nsString *) 0x01;
+
+bool
+DOMSVGTests::PassesConditionalProcessingTests(const nsString *aAcceptLangs) const
+{
+  // Required Features
+  if (mStringListAttributes[FEATURES].IsExplicitlySet()) {
+    if (mStringListAttributes[FEATURES].IsEmpty()) {
+      return false;
+    }
+    nsCOMPtr<nsIContent> content(
+      do_QueryInterface(const_cast<DOMSVGTests*>(this)));
+
+    for (PRUint32 i = 0; i < mStringListAttributes[FEATURES].Length(); i++) {
+      if (!nsSVGFeatures::HasFeature(content, mStringListAttributes[FEATURES][i])) {
+        return false;
+      }
+    }
+  }
+
+  // Required Extensions
+  //
+  // The requiredExtensions  attribute defines a list of required language
+  // extensions. Language extensions are capabilities within a user agent that
+  // go beyond the feature set defined in the SVG specification.
+  // Each extension is identified by a URI reference.
+  // For now, claim that mozilla's SVG implementation supports XHTML and MathML.
+  if (mStringListAttributes[EXTENSIONS].IsExplicitlySet()) {
+    if (mStringListAttributes[EXTENSIONS].IsEmpty()) {
+      return false;
+    }
+    for (PRUint32 i = 0; i < mStringListAttributes[EXTENSIONS].Length(); i++) {
+      if (!nsSVGFeatures::HasExtension(mStringListAttributes[EXTENSIONS][i])) {
+        return false;
+      }
+    }
+  }
+
+  if (aAcceptLangs == kIgnoreSystemLanguage) {
+    return true;
+  }
+
+  // systemLanguage
+  //
+  // Evaluates to "true" if one of the languages indicated by user preferences
+  // exactly equals one of the languages given in the value of this parameter,
+  // or if one of the languages indicated by user preferences exactly equals a
+  // prefix of one of the languages given in the value of this parameter such
+  // that the first tag character following the prefix is "-".
+  if (mStringListAttributes[LANGUAGE].IsExplicitlySet()) {
+    if (mStringListAttributes[LANGUAGE].IsEmpty()) {
+      return false;
+    }
+
+    // Get our language preferences
+    const nsAutoString acceptLangs(aAcceptLangs ? *aAcceptLangs :
+      Preferences::GetLocalizedString("intl.accept_languages"));
+
+    if (acceptLangs.IsEmpty()) {
+      NS_WARNING("no default language specified for systemLanguage conditional test");
+      return false;
+    }
+
+    const nsDefaultStringComparator defaultComparator;
+
+    for (PRUint32 i = 0; i < mStringListAttributes[LANGUAGE].Length(); i++) {
+      nsCharSeparatedTokenizer languageTokenizer(acceptLangs, ',');
+      while (languageTokenizer.hasMoreTokens()) {
+        if (nsStyleUtil::DashMatchCompare(mStringListAttributes[LANGUAGE][i],
+                                          languageTokenizer.nextToken(),
+                                          defaultComparator)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  return true;
+}
+
+bool
+DOMSVGTests::ParseConditionalProcessingAttribute(nsIAtom* aAttribute,
+                                                 const nsAString& aValue,
+                                                 nsAttrValue& aResult)
+{
+  for (PRUint32 i = 0; i < ArrayLength(sStringListInfo); i++) {
+    if (aAttribute == *sStringListInfo[i].mName) {
+      nsresult rv = mStringListAttributes[i].SetValue(
+                      aValue, sStringListInfo[i].mIsCommaSeparated);
+      if (NS_FAILED(rv)) {
+        mStringListAttributes[i].Clear();
+      }
+      MaybeInvalidate();
+      return true;
+    }
+  }
+  return false;
+}
+
+void
+DOMSVGTests::GetValue(PRUint8 aAttrEnum, nsAString& aValue) const
+{
+  NS_ABORT_IF_FALSE(aAttrEnum >= 0 && aAttrEnum < ArrayLength(sStringListInfo),
+                    "aAttrEnum out of range");
+  mStringListAttributes[aAttrEnum].GetValue(
+    aValue, sStringListInfo[aAttrEnum].mIsCommaSeparated);
+}
+
+void
+DOMSVGTests::UnsetAttr(const nsIAtom* aAttribute)
+{
+  for (PRUint32 i = 0; i < ArrayLength(sStringListInfo); i++) {
+    if (aAttribute == *sStringListInfo[i].mName) {
+      mStringListAttributes[i].Clear();
+      MaybeInvalidate();
+      return;
+    }
+  }
+}
+
+void
+DOMSVGTests::DidChangeStringList(PRUint8 aAttrEnum)
+{
+  NS_ASSERTION(aAttrEnum < ArrayLength(sStringListInfo), "aAttrEnum out of range");
+
+  nsCOMPtr<nsSVGElement> element = do_QueryInterface(this);
+
+  nsAutoString serializedValue;
+  GetValue(aAttrEnum, serializedValue);
+
+  nsAttrValue attrValue(serializedValue);
+  element->SetParsedAttr(kNameSpaceID_None,
+                         *sStringListInfo[aAttrEnum].mName,
+                         nsnull, attrValue, true);
+
+  MaybeInvalidate();
+}
+
+void
+DOMSVGTests::MaybeInvalidate()
+{
+  nsCOMPtr<nsSVGElement> element = do_QueryInterface(this);
+
+  nsIContent* parent = element->GetFlattenedTreeParent();
+  
+  if (parent &&
+      parent->NodeInfo()->Equals(nsGkAtoms::svgSwitch, kNameSpaceID_SVG)) {
+    static_cast<nsSVGSwitchElement*>(parent)->MaybeInvalidate();
+  }
+}
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/DOMSVGTests.h
@@ -0,0 +1,123 @@
+/* -*- 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
+ * Robert Longson <longsonr@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * 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_DOMSVGTESTS_H__
+#define MOZILLA_DOMSVGTESTS_H__
+
+#include "nsIDOMSVGTests.h"
+#include "SVGStringList.h"
+
+class DOMSVGTests : public nsIDOMSVGTests
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOMSVGTESTS
+
+  friend class mozilla::DOMSVGStringList;
+  typedef mozilla::SVGStringList SVGStringList;
+
+  /**
+   * Compare the language name(s) in a systemLanguage attribute to the
+   * user's language preferences, as defined in
+   * http://www.w3.org/TR/SVG11/struct.html#SystemLanguageAttribute
+   * We have a match if a language name in the users language preferences
+   * exactly equals one of the language names or exactly equals a prefix of
+   * one of the language names in the systemLanguage attribute.
+   * @returns 2 * the lowest index in the aAcceptLangs that matches + 1
+   * if only the prefix matches, or -1 if no indices match.
+   * XXX This algorithm is O(M*N).
+   */
+  PRInt32 GetBestLanguagePreferenceRank(const nsSubstring& aAcceptLangs) const;
+
+  /**
+   * Special value to pass to PassesConditionalProcessingTests to ignore systemLanguage
+   * attributes
+   */
+  static const nsString * const kIgnoreSystemLanguage;
+
+  /**
+   * Check whether the conditional processing attributes requiredFeatures,
+   * requiredExtensions and systemLanguage all "return true" if they apply to
+   * and are specified on the given element. Returns true if this element
+   * should be rendered, false if it should not.
+   *
+   * @param aAcceptLangs Optional parameter to pass in the value of the
+   *   intl.accept_languages preference if the caller has it cached.
+   *   Alternatively, pass in kIgnoreSystemLanguage to skip the systemLanguage
+   *   check if the caller is giving that special treatment.
+   */
+  bool PassesConditionalProcessingTests(
+         const nsString *aAcceptLangs = nsnull) const;
+
+  /**
+   * Returns true if the attribute is one of the conditional processing
+   * attributes.
+   */
+  bool IsConditionalProcessingAttribute(const nsIAtom* aAttribute) const;
+
+  bool ParseConditionalProcessingAttribute(
+         nsIAtom* aAttribute,
+         const nsAString& aValue,
+         nsAttrValue& aResult);
+
+  /**
+   * Serialises the conditional processing attribute.
+   */
+  void GetValue(PRUint8 aAttrEnum, nsAString& aValue) const;
+
+  /**
+   * Unsets a conditional processing attribute.
+   */
+  void UnsetAttr(const nsIAtom* aAttribute);
+
+  void DidChangeStringList(PRUint8 aAttrEnum);
+
+  void MaybeInvalidate();
+
+private:
+
+  struct StringListInfo {
+    nsIAtom** mName;
+    bool      mIsCommaSeparated;
+  };
+
+  enum { FEATURES, EXTENSIONS, LANGUAGE };
+  SVGStringList mStringListAttributes[3];
+  static StringListInfo sStringListInfo[3];
+};
+
+#endif // MOZILLA_DOMSVGTESTS_H__
--- a/content/svg/content/src/Makefile.in
+++ b/content/svg/content/src/Makefile.in
@@ -56,16 +56,18 @@ CPPSRCS		= \
 		DOMSVGLengthList.cpp \
 		DOMSVGMatrix.cpp \
 		DOMSVGNumber.cpp \
 		DOMSVGNumberList.cpp \
 		DOMSVGPathSeg.cpp \
 		DOMSVGPathSegList.cpp \
 		DOMSVGPoint.cpp \
 		DOMSVGPointList.cpp \
+		DOMSVGStringList.cpp \
+		DOMSVGTests.cpp \
 		DOMSVGTransform.cpp \
 		DOMSVGTransformList.cpp \
 		nsDOMSVGZoomEvent.cpp \
 		nsDOMSVGEvent.cpp \
 		nsSVGAElement.cpp \
 		nsSVGAltGlyphElement.cpp \
 		nsSVGAngle.cpp \
 		nsSVGBoolean.cpp \
@@ -129,16 +131,17 @@ CPPSRCS		= \
 		SVGAnimatedPreserveAspectRatio.cpp \
 		SVGAnimatedTransformList.cpp \
 		SVGLength.cpp \
 		SVGLengthList.cpp \
 		SVGNumberList.cpp \
 		SVGPathData.cpp \
 		SVGPathSegUtils.cpp \
 		SVGPointList.cpp \
+		SVGStringList.cpp \
 		SVGTransform.cpp \
 		SVGTransformList.cpp \
 		SVGTransformListParser.cpp \
 		nsSVGAnimateElement.cpp \
 		nsSVGAnimateTransformElement.cpp \
 		nsSVGAnimateMotionElement.cpp \
 		nsSVGAnimationElement.cpp \
 		nsSVGMpathElement.cpp \
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/SVGStringList.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
+ * Robert Longson <longsonr@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * 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 "mozilla/Util.h"
+
+#include "SVGStringList.h"
+#include "nsSVGElement.h"
+#include "nsDOMError.h"
+#include "nsString.h"
+#include "nsSVGUtils.h"
+#include "nsTextFormatter.h"
+#include "nsWhitespaceTokenizer.h"
+#include "nsCharSeparatedTokenizer.h"
+#include "nsMathUtils.h"
+
+namespace mozilla {
+
+nsresult
+SVGStringList::CopyFrom(const SVGStringList& rhs)
+{
+  if (!mStrings.SetCapacity(rhs.Length())) {
+    // Yes, we do want fallible alloc here
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  mStrings = rhs.mStrings;
+  mIsSet = true;
+  return NS_OK;
+}
+
+void
+SVGStringList::GetValue(nsAString& aValue, bool aIsCommaSeparated) const
+{
+  aValue.Truncate();
+  PRUint32 last = mStrings.Length() - 1;
+  for (PRUint32 i = 0; i < mStrings.Length(); ++i) {
+    aValue.Append(mStrings[i]);
+    if (i != last) {
+      if (aIsCommaSeparated) {
+        aValue.Append(',');
+      }
+      aValue.Append(' ');
+    }
+  }
+}
+
+nsresult
+SVGStringList::SetValue(const nsAString& aValue, bool aIsCommaSeparated)
+{
+  SVGStringList temp;
+
+  if (aIsCommaSeparated) {
+    nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
+      tokenizer(aValue, ',');
+
+    while (tokenizer.hasMoreTokens()) {
+      if (!temp.AppendItem(tokenizer.nextToken())) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+    }
+    if (tokenizer.lastTokenEndedWithSeparator()) {
+      return NS_ERROR_DOM_SYNTAX_ERR; // trailing comma
+    }
+  } else {
+    nsWhitespaceTokenizer tokenizer(aValue);
+
+    while (tokenizer.hasMoreTokens()) {
+      if (!temp.AppendItem(tokenizer.nextToken())) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+    }
+  }
+
+  return CopyFrom(temp);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/svg/content/src/SVGStringList.h
@@ -0,0 +1,174 @@
+/* -*- 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
+ * Robert Longson <longsonr@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * 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_SVGSTRINGLIST_H__
+#define MOZILLA_SVGSTRINGLIST_H__
+
+#include "nsTArray.h"
+#include "nsSVGElement.h"
+
+namespace mozilla {
+
+/**
+ *
+ * The DOM wrapper class for this class is DOMSVGStringList.
+ */
+class SVGStringList
+{
+  friend class DOMSVGStringList;
+
+public:
+
+  SVGStringList() : mIsSet(false) {}
+  ~SVGStringList(){}
+
+  nsresult SetValue(const nsAString& aValue, bool aIsCommaSeparated);
+
+  void Clear() {
+    mStrings.Clear();
+    mIsSet = false;
+  }
+
+  /// This may return an incomplete string on OOM, but that's acceptable.
+  void GetValue(nsAString& aValue, bool aIsCommaSeparated) const;
+
+  bool IsEmpty() const {
+    return mStrings.IsEmpty();
+  }
+
+  PRUint32 Length() const {
+    return mStrings.Length();
+  }
+
+  const nsAString& operator[](PRUint32 aIndex) const {
+    return mStrings[aIndex];
+  }
+
+  bool operator==(const SVGStringList& rhs) const {
+    return mStrings == rhs.mStrings;
+  }
+
+  bool SetCapacity(PRUint32 size) {
+    return mStrings.SetCapacity(size);
+  }
+
+  void Compact() {
+    mStrings.Compact();
+  }
+
+  // Returns true if the animated value of this stringlist has been explicitly
+  // set by taking on the base value which has been explicitly set by markup
+  // or a DOM call, false otherwise.
+  bool IsExplicitlySet() const
+    { return mIsSet; }
+
+  // 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
+  // SVGAnimatedStringList 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 SVGStringList& rhs);
+
+  nsAString& operator[](PRUint32 aIndex) {
+    return mStrings[aIndex];
+  }
+
+  /**
+   * This may fail (return false) on OOM if the internal capacity is being
+   * increased, in which case the list will be left unmodified.
+   */
+  bool SetLength(PRUint32 aStringOfItems) {
+    return mStrings.SetLength(aStringOfItems);
+  }
+
+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.
+
+  bool InsertItem(PRUint32 aIndex, const nsAString &aString) {
+    if (aIndex >= mStrings.Length()) {
+      aIndex = mStrings.Length();
+    }
+    if (mStrings.InsertElementAt(aIndex, aString)) {
+      mIsSet = true;
+      return true;
+    }
+    return false;
+  }
+
+  void ReplaceItem(PRUint32 aIndex, const nsAString &aString) {
+    NS_ABORT_IF_FALSE(aIndex < mStrings.Length(),
+                      "DOM wrapper caller should have raised INDEX_SIZE_ERR");
+    mStrings[aIndex] = aString;
+  }
+
+  void RemoveItem(PRUint32 aIndex) {
+    NS_ABORT_IF_FALSE(aIndex < mStrings.Length(),
+                      "DOM wrapper caller should have raised INDEX_SIZE_ERR");
+    mStrings.RemoveElementAt(aIndex);
+  }
+
+  bool AppendItem(const nsAString &aString) {
+    if (mStrings.AppendElement(aString)) {
+      mIsSet = true;
+      return true;
+    }
+    return false;
+  }
+
+protected:
+
+  /* See SVGLengthList for the rationale for using nsTArray<float> instead
+   * of nsTArray<float, 1>.
+   */
+  nsTArray<nsString> mStrings;
+  bool mIsSet;
+};
+
+} // namespace mozilla
+
+#endif // MOZILLA_SVGSTRINGLIST_H__
--- a/content/svg/content/src/nsSVGAElement.cpp
+++ b/content/svg/content/src/nsSVGAElement.cpp
@@ -62,21 +62,22 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(A)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGAElement, nsSVGAElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGAElement, nsSVGAElementBase)
 
 DOMCI_NODE_DATA(SVGAElement, nsSVGAElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGAElement)
-  NS_NODE_INTERFACE_TABLE7(nsSVGAElement,
+  NS_NODE_INTERFACE_TABLE8(nsSVGAElement,
                            nsIDOMNode,
                            nsIDOMElement,
                            nsIDOMSVGElement,
                            nsIDOMSVGAElement,
+                           nsIDOMSVGTests,
                            nsIDOMSVGURIReference,
                            nsILink,
                            Link)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGAElementBase)
 
 
 //----------------------------------------------------------------------
--- a/content/svg/content/src/nsSVGAElement.h
+++ b/content/svg/content/src/nsSVGAElement.h
@@ -38,23 +38,25 @@
 #ifndef NS_SVGAELEMENT_H_
 #define NS_SVGAELEMENT_H_
 
 #include "nsSVGGraphicElement.h"
 #include "nsIDOMSVGAElement.h"
 #include "nsIDOMSVGURIReference.h"
 #include "nsILink.h"
 #include "nsSVGString.h"
+#include "DOMSVGTests.h"
 
 #include "Link.h"
 
 typedef nsSVGGraphicElement nsSVGAElementBase;
 
 class nsSVGAElement : public nsSVGAElementBase,
                       public nsIDOMSVGAElement,
+                      public DOMSVGTests,
                       public nsIDOMSVGURIReference,
                       public nsILink,
                       public mozilla::dom::Link
 {
 protected:
   friend nsresult NS_NewSVGAElement(nsIContent **aResult,
                                     already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGAElement(already_AddRefed<nsINodeInfo> aNodeInfo);
--- a/content/svg/content/src/nsSVGAltGlyphElement.cpp
+++ b/content/svg/content/src/nsSVGAltGlyphElement.cpp
@@ -99,19 +99,20 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(AltGlyph)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGAltGlyphElement,nsSVGAltGlyphElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGAltGlyphElement,nsSVGAltGlyphElementBase)
 
 DOMCI_NODE_DATA(SVGAltGlyphElement, nsSVGAltGlyphElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGAltGlyphElement)
-  NS_NODE_INTERFACE_TABLE7(nsSVGAltGlyphElement, nsIDOMNode, nsIDOMElement,
+  NS_NODE_INTERFACE_TABLE8(nsSVGAltGlyphElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement, nsIDOMSVGAltGlyphElement,
                            nsIDOMSVGTextPositioningElement, nsIDOMSVGTextContentElement,
+                           nsIDOMSVGTests,
                            nsIDOMSVGURIReference)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAltGlyphElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGAltGlyphElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGAltGlyphElement::nsSVGAltGlyphElement(already_AddRefed<nsINodeInfo> aNodeInfo)
--- a/content/svg/content/src/nsSVGAnimateElement.cpp
+++ b/content/svg/content/src/nsSVGAnimateElement.cpp
@@ -76,19 +76,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Animate)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGAnimateElement,nsSVGAnimateElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGAnimateElement,nsSVGAnimateElementBase)
 
 DOMCI_NODE_DATA(SVGAnimateElement, nsSVGAnimateElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGAnimateElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGAnimateElement, nsIDOMNode, nsIDOMElement,
+  NS_NODE_INTERFACE_TABLE6(nsSVGAnimateElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement, nsIDOMSVGAnimationElement,
-                           nsIDOMSVGAnimateElement)
+                           nsIDOMSVGTests, nsIDOMSVGAnimateElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimateElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGAnimateElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGAnimateElement::nsSVGAnimateElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGAnimateElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGAnimateMotionElement.cpp
+++ b/content/svg/content/src/nsSVGAnimateMotionElement.cpp
@@ -46,19 +46,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(AnimateMotion
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGAnimateMotionElement,nsSVGAnimateMotionElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGAnimateMotionElement,nsSVGAnimateMotionElementBase)
 
 DOMCI_NODE_DATA(SVGAnimateMotionElement, nsSVGAnimateMotionElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGAnimateMotionElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGAnimateMotionElement, nsIDOMNode,
+  NS_NODE_INTERFACE_TABLE6(nsSVGAnimateMotionElement, nsIDOMNode,
                            nsIDOMElement, nsIDOMSVGElement,
-                           nsIDOMSVGAnimationElement,
+                           nsIDOMSVGAnimationElement, nsIDOMSVGTests,
                            nsIDOMSVGAnimateMotionElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimateMotionElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGAnimateMotionElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGAnimateMotionElement::nsSVGAnimateMotionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
--- a/content/svg/content/src/nsSVGAnimateTransformElement.cpp
+++ b/content/svg/content/src/nsSVGAnimateTransformElement.cpp
@@ -87,19 +87,20 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(AnimateTransf
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGAnimateTransformElement,nsSVGAnimateTransformElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGAnimateTransformElement,nsSVGAnimateTransformElementBase)
 
 DOMCI_NODE_DATA(SVGAnimateTransformElement, nsSVGAnimateTransformElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGAnimateTransformElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGAnimateTransformElement, nsIDOMNode,
+  NS_NODE_INTERFACE_TABLE6(nsSVGAnimateTransformElement, nsIDOMNode,
                            nsIDOMElement, nsIDOMSVGElement,
                            nsIDOMSVGAnimationElement,
+                           nsIDOMSVGTests,
                            nsIDOMSVGAnimateTransformElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimateTransformElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGAnimateTransformElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGAnimateTransformElement::nsSVGAnimateTransformElement(already_AddRefed<nsINodeInfo> aNodeInfo)
--- a/content/svg/content/src/nsSVGAnimationElement.cpp
+++ b/content/svg/content/src/nsSVGAnimationElement.cpp
@@ -50,16 +50,17 @@ using namespace mozilla::dom;
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGAnimationElement, nsSVGAnimationElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGAnimationElement, nsSVGAnimationElementBase)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGAnimationElement)
   NS_INTERFACE_MAP_ENTRY(nsISMILAnimationElement)
   NS_INTERFACE_MAP_ENTRY(nsIDOMElementTimeControl)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTests)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGAnimationElementBase)
 
 // Cycle collection magic -- based on nsSVGUseElement
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsSVGAnimationElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsSVGAnimationElement,
                                                 nsSVGAnimationElementBase)
   tmp->mHrefTarget.Unlink();
   tmp->mTimedElement.Unlink();
--- a/content/svg/content/src/nsSVGAnimationElement.h
+++ b/content/svg/content/src/nsSVGAnimationElement.h
@@ -38,23 +38,25 @@
 
 #ifndef NS_SVGANIMATIONELEMENT_H_
 #define NS_SVGANIMATIONELEMENT_H_
 
 #include "nsSVGElement.h"
 #include "nsAutoPtr.h"
 #include "nsReferencedElement.h"
 #include "nsIDOMSVGAnimationElement.h"
+#include "DOMSVGTests.h"
 #include "nsIDOMElementTimeControl.h"
 #include "nsISMILAnimationElement.h"
 #include "nsSMILTimedElement.h"
 
 typedef nsSVGElement nsSVGAnimationElementBase;
 
 class nsSVGAnimationElement : public nsSVGAnimationElementBase,
+                              public DOMSVGTests,
                               public nsISMILAnimationElement,
                               public nsIDOMElementTimeControl
 {
 protected:
   nsSVGAnimationElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   nsresult Init();
 
 public:
--- a/content/svg/content/src/nsSVGCircleElement.cpp
+++ b/content/svg/content/src/nsSVGCircleElement.cpp
@@ -95,18 +95,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Circle)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGCircleElement,nsSVGCircleElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGCircleElement,nsSVGCircleElementBase)
 
 DOMCI_NODE_DATA(SVGCircleElement, nsSVGCircleElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGCircleElement)
-  NS_NODE_INTERFACE_TABLE4(nsSVGCircleElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGCircleElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGCircleElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGCircleElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGCircleElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGCircleElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGCircleElement::nsSVGCircleElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGCircleElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGClipPathElement.cpp
+++ b/content/svg/content/src/nsSVGClipPathElement.cpp
@@ -55,18 +55,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(ClipPath)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGClipPathElement,nsSVGClipPathElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGClipPathElement,nsSVGClipPathElementBase)
 
 DOMCI_NODE_DATA(SVGClipPathElement, nsSVGClipPathElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGClipPathElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGClipPathElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGClipPathElement,
+  NS_NODE_INTERFACE_TABLE6(nsSVGClipPathElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGClipPathElement,
                            nsIDOMSVGUnitTypes)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGClipPathElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGClipPathElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGClipPathElement::nsSVGClipPathElement(already_AddRefed<nsINodeInfo> aNodeInfo)
--- a/content/svg/content/src/nsSVGClipPathElement.h
+++ b/content/svg/content/src/nsSVGClipPathElement.h
@@ -35,22 +35,24 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGCLIPPATHELEMENT_H__
 #define __NS_SVGCLIPPATHELEMENT_H__
 
 #include "nsSVGGraphicElement.h"
 #include "nsIDOMSVGClipPathElement.h"
 #include "nsIDOMSVGUnitTypes.h"
+#include "DOMSVGTests.h"
 #include "nsSVGEnum.h"
 
 typedef nsSVGGraphicElement nsSVGClipPathElementBase;
 
 class nsSVGClipPathElement : public nsSVGClipPathElementBase,
                              public nsIDOMSVGClipPathElement,
+                             public DOMSVGTests,
                              public nsIDOMSVGUnitTypes
 {
   friend class nsSVGClipPathFrame;
 
 protected:
   friend nsresult NS_NewSVGClipPathElement(nsIContent **aResult,
                                            already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGClipPathElement(already_AddRefed<nsINodeInfo> aNodeInfo);
--- a/content/svg/content/src/nsSVGDefsElement.cpp
+++ b/content/svg/content/src/nsSVGDefsElement.cpp
@@ -35,23 +35,25 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/Util.h"
 
 #include "nsSVGGraphicElement.h"
 #include "nsIDOMSVGDefsElement.h"
+#include "DOMSVGTests.h"
 
 using namespace mozilla;
 
 typedef nsSVGGraphicElement nsSVGDefsElementBase;
 
 class nsSVGDefsElement : public nsSVGDefsElementBase,
-                         public nsIDOMSVGDefsElement
+                         public nsIDOMSVGDefsElement,
+                         public DOMSVGTests
 {
 protected:
   friend nsresult NS_NewSVGDefsElement(nsIContent **aResult,
                                        already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGDefsElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   
 public:
   // interfaces:
@@ -83,18 +85,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Defs)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGDefsElement,nsSVGDefsElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGDefsElement,nsSVGDefsElementBase)
 
 DOMCI_NODE_DATA(SVGDefsElement, nsSVGDefsElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGDefsElement)
-  NS_NODE_INTERFACE_TABLE4(nsSVGDefsElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGDefsElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGDefsElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGDefsElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGDefsElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGDefsElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGDefsElement::nsSVGDefsElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGDefsElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -35,17 +35,16 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/Util.h"
 
 #include "nsSVGElement.h"
 #include "nsSVGSVGElement.h"
-#include "nsSVGSwitchElement.h"
 #include "nsIDocument.h"
 #include "nsRange.h"
 #include "nsIDOMAttr.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsMutationEvent.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsBindingManager.h"
@@ -76,16 +75,17 @@
 #include "nsSVGEnum.h"
 #include "nsSVGViewBox.h"
 #include "nsSVGString.h"
 #include "SVGAnimatedNumberList.h"
 #include "SVGAnimatedLengthList.h"
 #include "SVGAnimatedPointList.h"
 #include "SVGAnimatedPathSegList.h"
 #include "SVGAnimatedTransformList.h"
+#include "DOMSVGTests.h"
 #include "nsIDOMSVGUnitTypes.h"
 #include "nsSVGRect.h"
 #include "nsIFrame.h"
 #include "prdtoa.h"
 #include <stdarg.h>
 #include "nsSMILMappedAttribute.h"
 #include "SVGMotionSMILAttr.h"
 
@@ -270,29 +270,16 @@ nsSVGElement::AfterSetAttr(PRInt32 aName
     mContentStyleRule = nsnull;
   }
 
   if (IsEventName(aName) && aValue) {
     nsresult rv = AddScriptEventListener(GetEventNameForAttr(aName), *aValue);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  if (aNamespaceID == kNameSpaceID_None &&
-      (aName == nsGkAtoms::requiredFeatures ||
-       aName == nsGkAtoms::requiredExtensions ||
-       aName == nsGkAtoms::systemLanguage)) {
-
-    nsIContent* parent = GetFlattenedTreeParent();
-  
-    if (parent &&
-        parent->NodeInfo()->Equals(nsGkAtoms::svgSwitch, kNameSpaceID_SVG)) {
-      static_cast<nsSVGSwitchElement*>(parent)->MaybeInvalidate();
-    }
-  }
-
   return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aNotify);
 }
 
 bool
 nsSVGElement::ParseAttribute(PRInt32 aNamespaceID,
                              nsIAtom* aAttribute,
                              const nsAString& aValue,
                              nsAttrValue& aResult)
@@ -477,16 +464,40 @@ nsSVGElement::ParseAttribute(PRInt32 aNa
           }
           foundMatch = true;
           break;
         }
       }
     }
 
     if (!foundMatch) {
+      // Check for conditional processing attributes
+      nsCOMPtr<DOMSVGTests> tests(do_QueryInterface(this));
+      if (tests && tests->ParseConditionalProcessingAttribute(
+                            aAttribute, aValue, aResult)) {
+        foundMatch = true;
+      }
+    }
+
+    if (!foundMatch) {
+      // Check for StringList attribute
+      StringListAttributesInfo stringListInfo = GetStringListInfo();
+      for (i = 0; i < stringListInfo.mStringListCount; i++) {
+        if (aAttribute == *stringListInfo.mStringListInfo[i].mName) {
+          rv = stringListInfo.mStringLists[i].SetValue(aValue, false);
+          if (NS_FAILED(rv)) {
+            stringListInfo.Reset(i);
+          }
+          foundMatch = true;
+          break;
+        }
+      }
+    }
+
+    if (!foundMatch) {
       // Check for nsSVGViewBox attribute
       if (aAttribute == nsGkAtoms::viewBox) {
         nsSVGViewBox* viewBox = GetViewBox();
         if (viewBox) {
           rv = viewBox->SetBaseValueString(aValue, this);
           if (NS_FAILED(rv)) {
             viewBox->Init();
           }
@@ -719,16 +730,33 @@ nsSVGElement::UnsetAttrInternal(PRInt32 
     if (GetTransformListAttrName() == aName) {
       SVGAnimatedTransformList *transformList = GetAnimatedTransformList();
       if (transformList) {
         transformList->ClearBaseValue();
         DidChangeTransformList(false);
         return;
       }
     }
+
+    // Check for conditional processing attributes
+    nsCOMPtr<DOMSVGTests> tests(do_QueryInterface(this));
+    if (tests && tests->IsConditionalProcessingAttribute(aName)) {
+      tests->UnsetAttr(aName);
+      return;
+    }
+
+    // Check if this is a string list attribute going away
+    StringListAttributesInfo stringListInfo = GetStringListInfo();
+
+    for (PRUint32 i = 0; i < stringListInfo.mStringListCount; i++) {
+      if (aName == *stringListInfo.mStringListInfo[i].mName) {
+        stringListInfo.Reset(i);
+        return;
+      }
+    }
   }
 
   // Check if this is a string attribute going away
   StringAttributesInfo stringInfo = GetStringInfo();
 
   for (PRUint32 i = 0; i < stringInfo.mStringCount; i++) {
     if (aNamespaceID == stringInfo.mStringInfo[i].mNamespaceID &&
         aName == *stringInfo.mStringInfo[i].mName) {
@@ -749,22 +777,21 @@ nsSVGElement::UnsetAttr(PRInt32 aNamespa
 
 nsChangeHint
 nsSVGElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                      PRInt32 aModType) const
 {
   nsChangeHint retval =
     nsSVGElementBase::GetAttributeChangeHint(aAttribute, aModType);
 
-  if (aAttribute == nsGkAtoms::requiredFeatures ||
-      aAttribute == nsGkAtoms::requiredExtensions ||
-      aAttribute == nsGkAtoms::systemLanguage) {
+  nsCOMPtr<DOMSVGTests> tests(do_QueryInterface(const_cast<nsSVGElement*>(this)));
+  if (tests && tests->IsConditionalProcessingAttribute(aAttribute)) {
     // It would be nice to only reconstruct the frame if the value returned by
-    // NS_SVG_PassesConditionalProcessingTests has changed, but we don't know
-    // that
+    // DOMSVGTests::PassesConditionalProcessingTests has changed, but we don't
+    // know that
     NS_UpdateHint(retval, nsChangeHint_ReconstructFrame);
   }
   return retval;
 }
 
 bool
 nsSVGElement::IsNodeOfType(PRUint32 aFlags) const
 {
@@ -2113,16 +2140,54 @@ nsSVGElement::DidAnimateString(PRUint8 a
   if (frame) {
     StringAttributesInfo info = GetStringInfo();
     frame->AttributeChanged(info.mStringInfo[aAttrEnum].mNamespaceID,
                             *info.mStringInfo[aAttrEnum].mName,
                             nsIDOMMutationEvent::MODIFICATION);
   }
 }
 
+nsSVGElement::StringListAttributesInfo
+nsSVGElement::GetStringListInfo()
+{
+  return StringListAttributesInfo(nsnull, nsnull, 0);
+}
+
+void
+nsSVGElement::DidChangeStringList(bool aIsConditionalProcessingAttribute,
+                                  PRUint8 aAttrEnum)
+{
+  if (aIsConditionalProcessingAttribute) {
+    nsCOMPtr<DOMSVGTests> tests(do_QueryInterface(this));
+    tests->DidChangeStringList(aAttrEnum);
+    return;
+  }
+
+  StringListAttributesInfo info = GetStringListInfo();
+
+  NS_ASSERTION(info.mStringListCount > 0,
+               "DidChangeStringList on element with no string list attribs");
+
+  NS_ASSERTION(aAttrEnum < info.mStringListCount, "aAttrEnum out of range");
+
+  nsAutoString serializedValue;
+  info.mStringLists[aAttrEnum].GetValue(serializedValue, this);
+
+  nsAttrValue attrValue(serializedValue);
+  SetParsedAttr(kNameSpaceID_None, *info.mStringListInfo[aAttrEnum].mName,
+                nsnull, attrValue, true);
+}
+
+void
+nsSVGElement::StringListAttributesInfo::Reset(PRUint8 aAttrEnum)
+{
+  mStringLists[aAttrEnum].Clear();
+  // caller notifies
+}
+
 nsresult
 nsSVGElement::ReportAttributeParseFailure(nsIDocument* aDocument,
                                           nsIAtom* aAttribute,
                                           const nsAString& aValue)
 {
   const nsAFlatString& attributeValue = PromiseFlatString(aValue);
   const PRUnichar *strings[] = { aAttribute->GetUTF16String(),
                                  attributeValue.get() };
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -71,16 +71,18 @@ namespace mozilla {
 class SVGAnimatedNumberList;
 class SVGNumberList;
 class SVGAnimatedLengthList;
 class SVGUserUnitList;
 class SVGAnimatedPointList;
 class SVGAnimatedPathSegList;
 class SVGAnimatedPreserveAspectRatio;
 class SVGAnimatedTransformList;
+class SVGStringList;
+class DOMSVGStringList;
 }
 
 typedef nsStyledElementNotElementCSSInlineStyle nsSVGElementBase;
 
 class nsSVGElement : public nsSVGElementBase    // nsIContent
 {
 protected:
   nsSVGElement(already_AddRefed<nsINodeInfo> aNodeInfo);
@@ -91,16 +93,17 @@ public:
   typedef mozilla::SVGNumberList SVGNumberList;
   typedef mozilla::SVGAnimatedNumberList SVGAnimatedNumberList;
   typedef mozilla::SVGUserUnitList SVGUserUnitList;
   typedef mozilla::SVGAnimatedLengthList SVGAnimatedLengthList;
   typedef mozilla::SVGAnimatedPointList SVGAnimatedPointList;
   typedef mozilla::SVGAnimatedPathSegList SVGAnimatedPathSegList;
   typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
   typedef mozilla::SVGAnimatedTransformList SVGAnimatedTransformList;
+  typedef mozilla::SVGStringList SVGStringList;
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIContent interface methods
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
@@ -172,16 +175,18 @@ public:
   virtual void DidChangeViewBox(bool aDoSetAttr);
   virtual void DidChangePreserveAspectRatio(bool aDoSetAttr);
   virtual void DidChangeNumberList(PRUint8 aAttrEnum, bool aDoSetAttr);
   virtual void DidChangeLengthList(PRUint8 aAttrEnum, bool aDoSetAttr);
   virtual void DidChangePointList(bool aDoSetAttr);
   virtual void DidChangePathSegList(bool aDoSetAttr);
   virtual void DidChangeTransformList(bool aDoSetAttr);
   virtual void DidChangeString(PRUint8 aAttrEnum) {}
+  void DidChangeStringList(bool aIsConditionalProcessingAttribute,
+                           PRUint8 aAttrEnum);
 
   virtual void DidAnimateLength(PRUint8 aAttrEnum);
   virtual void DidAnimateNumber(PRUint8 aAttrEnum);
   virtual void DidAnimateNumberPair(PRUint8 aAttrEnum);
   virtual void DidAnimateInteger(PRUint8 aAttrEnum);
   virtual void DidAnimateIntegerPair(PRUint8 aAttrEnum);
   virtual void DidAnimateAngle(PRUint8 aAttrEnum);
   virtual void DidAnimateBoolean(PRUint8 aAttrEnum);
@@ -484,31 +489,53 @@ protected:
                          StringInfo *aStringInfo,
                          PRUint32 aStringCount) :
       mStrings(aStrings), mStringInfo(aStringInfo), mStringCount(aStringCount)
       {}
 
     void Reset(PRUint8 aAttrEnum);
   };
 
+  friend class mozilla::DOMSVGStringList;
+
+  struct StringListInfo {
+    nsIAtom**    mName;
+  };
+
+  struct StringListAttributesInfo {
+    SVGStringList*    mStringLists;
+    StringListInfo*   mStringListInfo;
+    PRUint32          mStringListCount;
+
+    StringListAttributesInfo(SVGStringList  *aStringLists,
+                             StringListInfo *aStringListInfo,
+                             PRUint32 aStringListCount) :
+      mStringLists(aStringLists), mStringListInfo(aStringListInfo),
+      mStringListCount(aStringListCount)
+      {}
+
+    void Reset(PRUint8 aAttrEnum);
+  };
+
   virtual LengthAttributesInfo GetLengthInfo();
   virtual NumberAttributesInfo GetNumberInfo();
   virtual NumberPairAttributesInfo GetNumberPairInfo();
   virtual IntegerAttributesInfo GetIntegerInfo();
   virtual IntegerPairAttributesInfo GetIntegerPairInfo();
   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 SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio();
   virtual NumberListAttributesInfo GetNumberListInfo();
   virtual LengthListAttributesInfo GetLengthListInfo();
   virtual StringAttributesInfo GetStringInfo();
+  virtual StringListAttributesInfo GetStringListInfo();
 
   static nsSVGEnumMapping sSVGUnitTypesMap[];
 
 private:
   void UnsetAttrInternal(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                          bool aNotify);
 
   nsRefPtr<mozilla::css::StyleRule> mContentStyleRule;
deleted file mode 100644
--- a/content/svg/content/src/nsSVGElementList.h
+++ /dev/null
@@ -1,152 +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 mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Scooter Morris.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * 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 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 ***** */
-
-/**
- * This file is used to help create a mapping from a specified SVG element to
- * attributes supported by that element. This mapping can be used to help
- * ensure that we don't accidentally implement support for attributes like
- * requiredFeatures on elements for which the SVG specification does not
- * define support.
- *
- * To use, include this file into another file after defining the SVG_ELEMENT
- * C preprocessor macro as appropriate.
- *
- * The following constants represent the following attributes:
- *
- * ATTRS_CONDITIONAL
- *   The requiredFeatures, requiredExtensions, and systemLanguage attributes
- *
- * ATTRS_EXTERNAL
- *   The externalResourcesRequired attribute
- *
- * ATTRS_ALL
- *   A convenience value indicating support for all of the above
- *
- * ATTRS_NONE
- *   A convenience value indicating support for none of the above
- */
-
-//This file must not have include guards.
-
-#define ATTRS_NONE        0x00
-#define ATTRS_CONDITIONAL 0x01
-#define ATTRS_EXTERNAL    0x02
-#define ATTRS_ALL         (ATTRS_CONDITIONAL | ATTRS_EXTERNAL)
-// tags
-SVG_ELEMENT(a, ATTRS_ALL)
-SVG_ELEMENT(altGlyph, ATTRS_ALL)
-SVG_ELEMENT(altGlyphDef, ATTRS_NONE)
-SVG_ELEMENT(altGlyphItem, ATTRS_NONE)
-SVG_ELEMENT(animate, ATTRS_ALL)
-SVG_ELEMENT(animateColor, ATTRS_ALL)
-SVG_ELEMENT(animateMotion, ATTRS_ALL)
-SVG_ELEMENT(animateTransform, ATTRS_ALL)
-SVG_ELEMENT(circle, ATTRS_ALL)
-SVG_ELEMENT(clipPath, ATTRS_ALL)
-SVG_ELEMENT(colorProfile, ATTRS_NONE)
-SVG_ELEMENT(cursor, ATTRS_ALL)
-SVG_ELEMENT(definition_src, ATTRS_NONE)
-SVG_ELEMENT(defs, ATTRS_ALL)
-SVG_ELEMENT(desc, ATTRS_NONE)
-SVG_ELEMENT(ellipse, ATTRS_ALL)
-SVG_ELEMENT(feBlend, ATTRS_NONE)
-SVG_ELEMENT(feColorMatrix, ATTRS_NONE)
-SVG_ELEMENT(feComponentTransfer, ATTRS_NONE)
-SVG_ELEMENT(feComposite, ATTRS_NONE)
-SVG_ELEMENT(feConvolveMatrix, ATTRS_NONE)
-SVG_ELEMENT(feDiffuseLighting, ATTRS_NONE)
-SVG_ELEMENT(feDisplacementMap, ATTRS_NONE)
-SVG_ELEMENT(feDistantLight, ATTRS_NONE)
-SVG_ELEMENT(feFlood, ATTRS_NONE)
-SVG_ELEMENT(feFuncR, ATTRS_NONE)
-SVG_ELEMENT(feFuncG, ATTRS_NONE)
-SVG_ELEMENT(feFuncB, ATTRS_NONE)
-SVG_ELEMENT(feFuncA, ATTRS_NONE)
-SVG_ELEMENT(feGaussianBlur, ATTRS_NONE)
-SVG_ELEMENT(feImage, ATTRS_EXTERNAL)
-SVG_ELEMENT(feMerge, ATTRS_NONE)
-SVG_ELEMENT(feMergeNode, ATTRS_NONE)
-SVG_ELEMENT(feMorphology, ATTRS_NONE)
-SVG_ELEMENT(feOffset, ATTRS_NONE)
-SVG_ELEMENT(fePointLight, ATTRS_NONE)
-SVG_ELEMENT(feSpecularLighting, ATTRS_NONE)
-SVG_ELEMENT(feSpotLight, ATTRS_NONE)
-SVG_ELEMENT(feTile, ATTRS_NONE)
-SVG_ELEMENT(feTurbulence, ATTRS_NONE)
-SVG_ELEMENT(filter, ATTRS_EXTERNAL)
-SVG_ELEMENT(font, ATTRS_EXTERNAL)
-SVG_ELEMENT(font_face, ATTRS_NONE)
-SVG_ELEMENT(font_face_format, ATTRS_NONE)
-SVG_ELEMENT(font_face_name, ATTRS_NONE)
-SVG_ELEMENT(font_face_src, ATTRS_NONE)
-SVG_ELEMENT(font_face_uri, ATTRS_NONE)
-SVG_ELEMENT(foreignObject, ATTRS_ALL)
-SVG_ELEMENT(g, ATTRS_ALL)
-SVG_ELEMENT(glyph, ATTRS_NONE)
-SVG_ELEMENT(glyphRef, ATTRS_NONE)
-SVG_ELEMENT(hkern, ATTRS_NONE)
-SVG_ELEMENT(image, ATTRS_ALL)
-SVG_ELEMENT(line, ATTRS_ALL)
-SVG_ELEMENT(linearGradient, ATTRS_EXTERNAL)
-SVG_ELEMENT(marker, ATTRS_NONE)
-SVG_ELEMENT(mask, ATTRS_ALL)
-SVG_ELEMENT(metadata, ATTRS_NONE)
-SVG_ELEMENT(missingGlyph, ATTRS_NONE)
-SVG_ELEMENT(mpath, ATTRS_EXTERNAL)
-SVG_ELEMENT(path, ATTRS_ALL)
-SVG_ELEMENT(pattern, ATTRS_ALL)
-SVG_ELEMENT(polygon, ATTRS_ALL)
-SVG_ELEMENT(polyline, ATTRS_ALL)
-SVG_ELEMENT(radialGradient, ATTRS_EXTERNAL)
-SVG_ELEMENT(rect, ATTRS_ALL)
-SVG_ELEMENT(script, ATTRS_EXTERNAL)
-SVG_ELEMENT(set, ATTRS_ALL)
-SVG_ELEMENT(stop, ATTRS_NONE)
-SVG_ELEMENT(style, ATTRS_NONE)
-SVG_ELEMENT(svg, ATTRS_ALL)
-SVG_ELEMENT(svgSwitch, ATTRS_ALL) // switch is a C++ keyword, hence svgSwitch
-SVG_ELEMENT(symbol, ATTRS_NONE)
-SVG_ELEMENT(text, ATTRS_ALL)
-SVG_ELEMENT(textPath, ATTRS_ALL)
-SVG_ELEMENT(title, ATTRS_NONE)
-SVG_ELEMENT(tref, ATTRS_ALL)
-SVG_ELEMENT(tspan, ATTRS_ALL)
-SVG_ELEMENT(use, ATTRS_ALL)
-SVG_ELEMENT(view, ATTRS_EXTERNAL)
-SVG_ELEMENT(vkern, ATTRS_NONE)
--- a/content/svg/content/src/nsSVGEllipseElement.cpp
+++ b/content/svg/content/src/nsSVGEllipseElement.cpp
@@ -97,18 +97,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Ellipse)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGEllipseElement,nsSVGEllipseElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGEllipseElement,nsSVGEllipseElementBase)
 
 DOMCI_NODE_DATA(SVGEllipseElement, nsSVGEllipseElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGEllipseElement)
-  NS_NODE_INTERFACE_TABLE4(nsSVGEllipseElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGEllipseElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGEllipseElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGEllipseElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGEllipseElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGEllipseElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGEllipseElement::nsSVGEllipseElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGEllipseElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGFeatures.cpp
+++ b/content/svg/content/src/nsSVGFeatures.cpp
@@ -42,30 +42,23 @@
  * This file contains code to help implement the Conditional Processing
  * section of the SVG specification (i.e. the <switch> element and the
  * requiredFeatures, requiredExtensions and systemLanguage attributes).
  *
  *   http://www.w3.org/TR/SVG11/struct.html#ConditionalProcessing
  */
 
 #include "nsSVGFeatures.h"
-#include "nsGkAtoms.h"
 #include "nsIContent.h"
-#include "nsContentUtils.h"
-#include "nsWhitespaceTokenizer.h"
-#include "nsCharSeparatedTokenizer.h"
-#include "nsStyleUtil.h"
-#include "nsSVGUtils.h"
-#include "nsServiceManagerUtils.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
 /*static*/ bool
-nsSVGFeatures::HaveFeature(nsISupports* aObject, const nsAString& aFeature)
+nsSVGFeatures::HasFeature(nsISupports* aObject, const nsAString& aFeature)
 {
   if (aFeature.EqualsLiteral("http://www.w3.org/TR/SVG11/feature#Script")) {
     nsCOMPtr<nsIContent> content(do_QueryInterface(aObject));
     if (content) {
       nsIDocument *doc = content->GetCurrentDoc();
       if (doc && doc->IsResourceDoc()) {
         // no scripting in SVG images or external resource documents
         return false;
@@ -77,173 +70,17 @@ nsSVGFeatures::HaveFeature(nsISupports* 
 #define SVG_UNSUPPORTED_FEATURE(str)
 #include "nsSVGFeaturesList.h"
 #undef SVG_SUPPORTED_FEATURE
 #undef SVG_UNSUPPORTED_FEATURE
   return false;
 }
 
 /*static*/ bool
-nsSVGFeatures::HaveFeatures(nsISupports* aObject, const nsSubstring& aFeatures)
-{
-  nsWhitespaceTokenizer tokenizer(aFeatures);
-  while (tokenizer.hasMoreTokens()) {
-    if (!HaveFeature(aObject, tokenizer.nextToken())) {
-      return false;
-    }
-  }
-  return true;
-}
-
-/*static*/ bool
-nsSVGFeatures::HaveExtension(const nsAString& aExtension)
+nsSVGFeatures::HasExtension(const nsAString& aExtension)
 {
 #define SVG_SUPPORTED_EXTENSION(str) if (aExtension.EqualsLiteral(str)) return true;
   SVG_SUPPORTED_EXTENSION("http://www.w3.org/1999/xhtml")
   SVG_SUPPORTED_EXTENSION("http://www.w3.org/1998/Math/MathML")
 #undef SVG_SUPPORTED_EXTENSION
 
   return false;
 }
-
-/*static*/ bool
-nsSVGFeatures::HaveExtensions(const nsSubstring& aExtensions)
-{
-  nsWhitespaceTokenizer tokenizer(aExtensions);
-  while (tokenizer.hasMoreTokens()) {
-    if (!HaveExtension(tokenizer.nextToken())) {
-      return false;
-    }
-  }
-  return true;
-}
-
-/*static*/ bool
-nsSVGFeatures::MatchesLanguagePreferences(const nsSubstring& aAttribute,
-                                          const nsSubstring& aAcceptLangs) 
-{
-  const nsDefaultStringComparator defaultComparator;
-
-  nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
-    attributeTokenizer(aAttribute, ',');
-
-  while (attributeTokenizer.hasMoreTokens()) {
-    const nsSubstring &attributeToken = attributeTokenizer.nextToken();
-    nsCharSeparatedTokenizer languageTokenizer(aAcceptLangs, ',');
-    while (languageTokenizer.hasMoreTokens()) {
-      if (nsStyleUtil::DashMatchCompare(attributeToken,
-                                        languageTokenizer.nextToken(),
-                                        defaultComparator)) {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-/*static*/ PRInt32
-nsSVGFeatures::GetBestLanguagePreferenceRank(const nsSubstring& aAttribute,
-                                             const nsSubstring& aAcceptLangs) 
-{
-  const nsDefaultStringComparator defaultComparator;
-
-  nsCharSeparatedTokenizer attributeTokenizer(aAttribute, ',');
-  PRInt32 lowestRank = -1;
-
-  while (attributeTokenizer.hasMoreTokens()) {
-    const nsSubstring &attributeToken = attributeTokenizer.nextToken();
-    nsCharSeparatedTokenizer languageTokenizer(aAcceptLangs, ',');
-    PRInt32 index = 0;
-    while (languageTokenizer.hasMoreTokens()) {
-      const nsSubstring &languageToken = languageTokenizer.nextToken();
-      bool exactMatch = (languageToken == attributeToken);
-      bool prefixOnlyMatch =
-        !exactMatch &&
-        nsStyleUtil::DashMatchCompare(attributeToken,
-                                      languageTokenizer.nextToken(),
-                                      defaultComparator);
-      if (index == 0 && exactMatch) {
-        // best possible match
-        return 0;
-      }
-      if ((exactMatch || prefixOnlyMatch) &&
-          (lowestRank == -1 || 2 * index + prefixOnlyMatch < lowestRank)) {
-        lowestRank = 2 * index + prefixOnlyMatch;
-      }
-      ++index;
-    }
-  }
-  return lowestRank;
-}
-
-/*static*/ bool
-nsSVGFeatures::ElementSupportsAttributes(const nsIAtom *aTagName, PRUint16 aAttr)
-{
-#define SVG_ELEMENT(_atom, _supports) if (aTagName == nsGkAtoms::_atom) return (_supports & aAttr) != 0;
-#include "nsSVGElementList.h"
-#undef SVG_ELEMENT
-  return false;
-}
-
-const nsString * const nsSVGFeatures::kIgnoreSystemLanguage = (nsString *) 0x01;
-
-/*static*/ bool
-nsSVGFeatures::PassesConditionalProcessingTests(nsIContent *aContent,
-                                                const nsString *aAcceptLangs)
-{
-  if (!aContent->IsElement()) {
-    return false;
-  }
-
-  if (!ElementSupportsAttributes(aContent->Tag(), ATTRS_CONDITIONAL)) {
-    return true;
-  }
-
-  // Required Features
-  nsAutoString value;
-  if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::requiredFeatures, value)) {
-    if (value.IsEmpty() || !HaveFeatures(aContent, value)) {
-      return false;
-    }
-  }
-
-  // Required Extensions
-  //
-  // The requiredExtensions  attribute defines a list of required language
-  // extensions. Language extensions are capabilities within a user agent that
-  // go beyond the feature set defined in the SVG specification.
-  // Each extension is identified by a URI reference.
-  // For now, claim that mozilla's SVG implementation supports XHTML and MathML.
-  if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::requiredExtensions, value)) {
-    if (value.IsEmpty() || !HaveExtensions(value)) {
-      return false;
-    }
-  }
-
-  if (aAcceptLangs == kIgnoreSystemLanguage) {
-    return true;
-  }
-
-  // systemLanguage
-  //
-  // Evaluates to "true" if one of the languages indicated by user preferences
-  // exactly equals one of the languages given in the value of this parameter,
-  // or if one of the languages indicated by user preferences exactly equals a
-  // prefix of one of the languages given in the value of this parameter such
-  // that the first tag character following the prefix is "-".
-  if (aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::systemLanguage,
-                        value)) {
-
-    const nsAutoString acceptLangs(aAcceptLangs ? *aAcceptLangs :
-      Preferences::GetLocalizedString("intl.accept_languages"));
-
-    // Get our language preferences
-    if (!acceptLangs.IsEmpty()) {
-      return MatchesLanguagePreferences(value, acceptLangs);
-    } else {
-      // For now, evaluate to true.
-      NS_WARNING("no default language specified for systemLanguage conditional test");
-      return !value.IsEmpty();
-    }
-  }
-
-  return true;
-}
--- a/content/svg/content/src/nsSVGFeatures.h
+++ b/content/svg/content/src/nsSVGFeatures.h
@@ -36,119 +36,33 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGFEATURES_H__
 #define __NS_SVGFEATURES_H__
 
 #include "nsString.h"
 
-class nsIContent;
-class nsIAtom;
-
 class nsSVGFeatures
 {
 public:
   /**
    * Check whether we support the given feature string.
    *
    * @param aObject the object, which should support the feature,
    *        for example nsIDOMNode or nsIDOMDOMImplementation
    * @param aFeature one of the feature strings specified at
    *    http://www.w3.org/TR/SVG11/feature.html
    */
   static bool
-  HaveFeature(nsISupports* aObject, const nsAString& aFeature);
-
-  /**
-   * Compare the language name(s) in a systemLanguage attribute to the
-   * user's language preferences, as defined in
-   * http://www.w3.org/TR/SVG11/struct.html#SystemLanguageAttribute
-   * We have a match if a language name in the users language preferences
-   * exactly equals one of the language names or exactly equals a prefix of
-   * one of the language names in the systemLanguage attribute.
-   * @returns 2 * the lowest index in the aAcceptLangs that matches + 1
-   * if only the prefix matches, or -1 if no indices match.
-   * XXX This algorithm is O(M*N).
-   */
-  static int
-  GetBestLanguagePreferenceRank(const nsSubstring& aAttribute,
-                                const nsSubstring& aAcceptLangs);
-
-  /**
-   * Special value to pass to PassesConditionalProcessingTests to ignore systemLanguage
-   * attributes
-   */
-  static const nsString * const kIgnoreSystemLanguage;
-
-  /**
-   * Check whether the conditional processing attributes requiredFeatures,
-   * requiredExtensions and systemLanguage all "return true" if they apply to
-   * and are specified on the given element. Returns true if this element
-   * should be rendered, false if it should not.
-   *
-   * @param aContent the element to test
-   * @param aAcceptLangs Optional parameter to pass in the value of the
-   *   intl.accept_languages preference if the caller has it cached.
-   *   Alternatively, pass in kIgnoreSystemLanguage to skip the systemLanguage
-   *   check if the caller is giving that special treatment.
-   */
-  static bool
-  PassesConditionalProcessingTests(nsIContent *aContent,
-                                   const nsString *aAcceptLangs = nsnull);
-
-private:
-  /**
-   * Check whether we support the given list of feature strings.
-   *
-   * @param aObject the object, which should support the feature,
-   *        for example nsIDOMNode or nsIDOMDOMImplementation
-   * @param aFeatures a whitespace separated list containing one or more of the
-   *   feature strings specified at http://www.w3.org/TR/SVG11/feature.html
-   */
-  static bool
-  HaveFeatures(nsISupports* aObject, const nsSubstring& aFeatures);
+  HasFeature(nsISupports* aObject, const nsAString& aFeature);
 
   /**
    * Check whether we support the given extension string.
    *
    * @param aExtension the URI of an extension. Known extensions are
    *   "http://www.w3.org/1999/xhtml" and "http://www.w3.org/1998/Math/MathML"
    */
   static bool
-  HaveExtension(const nsAString& aExtension);
-
-  /**
-   * Check whether we support the given list of extension strings.
-   *
-   * @param aExtension a whitespace separated list containing one or more
-   *   extension strings
-   */
-  static bool
-  HaveExtensions(const nsSubstring& aExtensions);
-
-  /**
-   * Compare the language name(s) in a systemLanguage attribute to the
-   * user's language preferences, as defined in
-   * http://www.w3.org/TR/SVG11/struct.html#SystemLanguageAttribute
-   * We have a match if a language name in the users language preferences
-   * exactly equals one of the language names or exactly equals a prefix of
-   * one of the language names in the systemLanguage attribute.
-   * XXX This algorithm is O(M*N).
-   */
-  static bool
-  MatchesLanguagePreferences(const nsSubstring& aAttribute,
-                             const nsSubstring& aAcceptLangs); 
-
-  /**
-   * Check whether this element supports the specified attributes
-   * (i.e. whether the SVG specification defines the attributes
-   * for the specified element).
-   *
-   * @param aTagName the tag for the element
-   * @param aAttr the conditional to test for, either
-   *    ATTRS_TEST or ATTRS_EXTERNAL
-   */
-  static bool
-  ElementSupportsAttributes(const nsIAtom *aTagName, PRUint16 aAttr);
+  HasExtension(const nsAString& aExtension);
 };
 
 #endif // __NS_SVGFEATURES_H__
--- a/content/svg/content/src/nsSVGFilterElement.cpp
+++ b/content/svg/content/src/nsSVGFilterElement.cpp
@@ -79,18 +79,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Filter)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGFilterElement,nsSVGFilterElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGFilterElement,nsSVGFilterElementBase)
 
 DOMCI_NODE_DATA(SVGFilterElement, nsSVGFilterElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGFilterElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGFilterElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGFilterElement,
+  NS_NODE_INTERFACE_TABLE6(nsSVGFilterElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGFilterElement,
                            nsIDOMSVGURIReference)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFilterElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGFilterElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGFilterElement::nsSVGFilterElement(already_AddRefed<nsINodeInfo> aNodeInfo)
--- a/content/svg/content/src/nsSVGFilterElement.h
+++ b/content/svg/content/src/nsSVGFilterElement.h
@@ -36,25 +36,27 @@
 
 #ifndef __NS_SVGFILTERELEMENT_H__
 #define __NS_SVGFILTERELEMENT_H__
 
 #include "nsSVGGraphicElement.h"
 #include "nsIDOMSVGFilterElement.h"
 #include "nsIDOMSVGURIReference.h"
 #include "nsIDOMSVGUnitTypes.h"
+#include "DOMSVGTests.h"
 #include "nsSVGLength2.h"
 #include "nsSVGIntegerPair.h"
 #include "nsSVGEnum.h"
 #include "nsSVGString.h"
 
 typedef nsSVGGraphicElement nsSVGFilterElementBase;
 
 class nsSVGFilterElement : public nsSVGFilterElementBase,
                            public nsIDOMSVGFilterElement,
+                           public DOMSVGTests,
                            public nsIDOMSVGURIReference,
                            public nsIDOMSVGUnitTypes
 {
   friend class nsSVGFilterFrame;
   friend class nsAutoFilterInstance;
 
 protected:
   friend nsresult NS_NewSVGFilterElement(nsIContent **aResult,
--- a/content/svg/content/src/nsSVGForeignObjectElement.cpp
+++ b/content/svg/content/src/nsSVGForeignObjectElement.cpp
@@ -57,18 +57,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(ForeignObject
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGForeignObjectElement,nsSVGForeignObjectElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGForeignObjectElement,nsSVGForeignObjectElementBase)
 
 DOMCI_NODE_DATA(SVGForeignObjectElement, nsSVGForeignObjectElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGForeignObjectElement)
-  NS_NODE_INTERFACE_TABLE4(nsSVGForeignObjectElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGForeignObjectElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGForeignObjectElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGForeignObjectElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGForeignObjectElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGForeignObjectElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGForeignObjectElement::nsSVGForeignObjectElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGForeignObjectElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGForeignObjectElement.h
+++ b/content/svg/content/src/nsSVGForeignObjectElement.h
@@ -36,22 +36,24 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGFOREIGNOBJECTELEMENT_H__
 #define __NS_SVGFOREIGNOBJECTELEMENT_H__
 
 #include "nsSVGGraphicElement.h"
 #include "nsIDOMSVGForeignObjectElem.h"
+#include "DOMSVGTests.h"
 #include "nsSVGLength2.h"
 
 typedef nsSVGGraphicElement nsSVGForeignObjectElementBase;
 
 class nsSVGForeignObjectElement : public nsSVGForeignObjectElementBase,
-                                  public nsIDOMSVGForeignObjectElement
+                                  public nsIDOMSVGForeignObjectElement,
+                                  public DOMSVGTests
 {
   friend class nsSVGForeignObjectFrame;
 
 protected:
   friend nsresult NS_NewSVGForeignObjectElement(nsIContent **aResult,
                                                 already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGForeignObjectElement(already_AddRefed<nsINodeInfo> aNodeInfo);
 
--- a/content/svg/content/src/nsSVGGElement.cpp
+++ b/content/svg/content/src/nsSVGGElement.cpp
@@ -35,23 +35,25 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/Util.h"
 
 #include "nsSVGGraphicElement.h"
 #include "nsIDOMSVGGElement.h"
+#include "DOMSVGTests.h"
 
 using namespace mozilla;
 
 typedef nsSVGGraphicElement nsSVGGElementBase;
 
 class nsSVGGElement : public nsSVGGElementBase,
-                      public nsIDOMSVGGElement
+                      public nsIDOMSVGGElement,
+                      public DOMSVGTests
 {
 protected:
   friend nsresult NS_NewSVGGElement(nsIContent **aResult,
                                     already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGGElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   
 public:
   // interfaces:
@@ -83,18 +85,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(G)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGGElement,nsSVGGElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGGElement,nsSVGGElementBase)
 
 DOMCI_NODE_DATA(SVGGElement, nsSVGGElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGGElement)
-  NS_NODE_INTERFACE_TABLE4(nsSVGGElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGGElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGGElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGGElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGGElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGGElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGGElement::nsSVGGElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGGElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGGradientElement.cpp
+++ b/content/svg/content/src/nsSVGGradientElement.cpp
@@ -178,18 +178,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(LinearGradien
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGLinearGradientElement,nsSVGLinearGradientElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGLinearGradientElement,nsSVGLinearGradientElementBase)
 
 DOMCI_NODE_DATA(SVGLinearGradientElement, nsSVGLinearGradientElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGLinearGradientElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGLinearGradientElement, nsIDOMNode,
+  NS_NODE_INTERFACE_TABLE6(nsSVGLinearGradientElement, nsIDOMNode,
                            nsIDOMElement, nsIDOMSVGElement,
+                           nsIDOMSVGTests,
                            nsIDOMSVGGradientElement,
                            nsIDOMSVGLinearGradientElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGLinearGradientElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGLinearGradientElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
@@ -267,18 +268,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(RadialGradien
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGRadialGradientElement,nsSVGRadialGradientElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGRadialGradientElement,nsSVGRadialGradientElementBase)
 
 DOMCI_NODE_DATA(SVGRadialGradientElement, nsSVGRadialGradientElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGRadialGradientElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGRadialGradientElement, nsIDOMNode,
+  NS_NODE_INTERFACE_TABLE6(nsSVGRadialGradientElement, nsIDOMNode,
                            nsIDOMElement, nsIDOMSVGElement,
+                           nsIDOMSVGTests,
                            nsIDOMSVGGradientElement,
                            nsIDOMSVGRadialGradientElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGRadialGradientElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGRadialGradientElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
--- a/content/svg/content/src/nsSVGGradientElement.h
+++ b/content/svg/content/src/nsSVGGradientElement.h
@@ -36,28 +36,30 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGGRADIENTELEMENT_H__
 #define __NS_SVGGRADIENTELEMENT_H__
 
 #include "nsIDOMSVGURIReference.h"
 #include "nsIDOMSVGGradientElement.h"
+#include "DOMSVGTests.h"
 #include "nsIDOMSVGUnitTypes.h"
 #include "nsSVGStylableElement.h"
 #include "nsSVGLength2.h"
 #include "nsSVGEnum.h"
 #include "nsSVGString.h"
 #include "SVGAnimatedTransformList.h"
 
 //--------------------- Gradients------------------------
 
 typedef nsSVGStylableElement nsSVGGradientElementBase;
 
 class nsSVGGradientElement : public nsSVGGradientElementBase,
+                             public DOMSVGTests,
                              public nsIDOMSVGURIReference,
                              public nsIDOMSVGUnitTypes
 {
   friend class nsSVGGradientFrame;
 
 protected:
   nsSVGGradientElement(already_AddRefed<nsINodeInfo> aNodeInfo);
 
--- a/content/svg/content/src/nsSVGImageElement.cpp
+++ b/content/svg/content/src/nsSVGImageElement.cpp
@@ -67,18 +67,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Image)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGImageElement,nsSVGImageElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGImageElement,nsSVGImageElementBase)
 
 DOMCI_NODE_DATA(SVGImageElement, nsSVGImageElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGImageElement)
-  NS_NODE_INTERFACE_TABLE7(nsSVGImageElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGImageElement,
+  NS_NODE_INTERFACE_TABLE8(nsSVGImageElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGImageElement,
                            nsIDOMSVGURIReference, imgIDecoderObserver,
                            nsIImageLoadingContent)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGImageElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGImageElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
--- a/content/svg/content/src/nsSVGLineElement.cpp
+++ b/content/svg/content/src/nsSVGLineElement.cpp
@@ -101,18 +101,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Line)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGLineElement,nsSVGLineElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGLineElement,nsSVGLineElementBase)
 
 DOMCI_NODE_DATA(SVGLineElement, nsSVGLineElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGLineElement)
-  NS_NODE_INTERFACE_TABLE4(nsSVGLineElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGLineElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGLineElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGLineElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGLineElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGLineElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGLineElement::nsSVGLineElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGLineElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGMaskElement.cpp
+++ b/content/svg/content/src/nsSVGMaskElement.cpp
@@ -70,19 +70,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Mask)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGMaskElement,nsSVGMaskElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGMaskElement,nsSVGMaskElementBase)
 
 DOMCI_NODE_DATA(SVGMaskElement, nsSVGMaskElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGMaskElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGMaskElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGMaskElement,
-                           nsIDOMSVGUnitTypes)
+  NS_NODE_INTERFACE_TABLE6(nsSVGMaskElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGMaskElement, nsIDOMSVGUnitTypes)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGMaskElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGMaskElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGMaskElement::nsSVGMaskElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGMaskElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGMaskElement.h
+++ b/content/svg/content/src/nsSVGMaskElement.h
@@ -34,26 +34,28 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGMASKELEMENT_H__
 #define __NS_SVGMASKELEMENT_H__
 
 #include "nsSVGStylableElement.h"
 #include "nsIDOMSVGMaskElement.h"
+#include "DOMSVGTests.h"
 #include "nsIDOMSVGUnitTypes.h"
 #include "nsSVGLength2.h"
 #include "nsSVGEnum.h"
 
 //--------------------- Masks ------------------------
 
 typedef nsSVGStylableElement nsSVGMaskElementBase;
 
 class nsSVGMaskElement : public nsSVGMaskElementBase,
                          public nsIDOMSVGMaskElement,
+                         public DOMSVGTests,
                          public nsIDOMSVGUnitTypes
 {
   friend class nsSVGMaskFrame;
 
 protected:
   friend nsresult NS_NewSVGMaskElement(nsIContent **aResult,
                                        already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGMaskElement(already_AddRefed<nsINodeInfo> aNodeInfo);
--- a/content/svg/content/src/nsSVGPathElement.cpp
+++ b/content/svg/content/src/nsSVGPathElement.cpp
@@ -62,19 +62,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Path)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGPathElement,nsSVGPathElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGPathElement,nsSVGPathElementBase)
 
 DOMCI_NODE_DATA(SVGPathElement, nsSVGPathElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGPathElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGPathElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGPathElement,
-                           nsIDOMSVGAnimatedPathData)
+  NS_NODE_INTERFACE_TABLE6(nsSVGPathElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGPathElement, nsIDOMSVGAnimatedPathData)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPathElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGPathElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGPathElement::nsSVGPathElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGPathElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGPathGeometryElement.cpp
+++ b/content/svg/content/src/nsSVGPathGeometryElement.cpp
@@ -31,16 +31,29 @@
  * 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 "nsSVGPathGeometryElement.h"
 
+//----------------------------------------------------------------------
+// nsISupports methods
+
+NS_IMPL_ADDREF_INHERITED(nsSVGPathGeometryElement, nsSVGPathGeometryElementBase)
+NS_IMPL_RELEASE_INHERITED(nsSVGPathGeometryElement, nsSVGPathGeometryElementBase)
+
+NS_INTERFACE_MAP_BEGIN(nsSVGPathGeometryElement)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTests)
+NS_INTERFACE_MAP_END_INHERITING(nsSVGPathGeometryElementBase)
+
+//----------------------------------------------------------------------
+// Implementation
+
 nsSVGPathGeometryElement::nsSVGPathGeometryElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGPathGeometryElementBase(aNodeInfo)
 {
 }
 
 bool
 nsSVGPathGeometryElement::AttributeDefinesGeometry(const nsIAtom *aName)
 {
--- a/content/svg/content/src/nsSVGPathGeometryElement.h
+++ b/content/svg/content/src/nsSVGPathGeometryElement.h
@@ -33,35 +33,40 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGPATHGEOMETRYELEMENT_H__
 #define __NS_SVGPATHGEOMETRYELEMENT_H__
 
 #include "nsSVGGraphicElement.h"
+#include "DOMSVGTests.h"
 #include "nsTArray.h"
 #include "gfxPath.h"
 #include "gfxMatrix.h"
 
 struct nsSVGMark {
   float x, y, angle;
   nsSVGMark(float aX, float aY, float aAngle) :
     x(aX), y(aY), angle(aAngle) {}
 };
 
 class gfxContext;
 
 typedef nsSVGGraphicElement nsSVGPathGeometryElementBase;
 
-class nsSVGPathGeometryElement : public nsSVGPathGeometryElementBase
+class nsSVGPathGeometryElement : public nsSVGPathGeometryElementBase,
+                                 public DOMSVGTests
 {
 public:
   nsSVGPathGeometryElement(already_AddRefed<nsINodeInfo> aNodeInfo);
 
+  // interfaces:
+  NS_DECL_ISUPPORTS_INHERITED
+
   virtual bool AttributeDefinesGeometry(const nsIAtom *aName);
   virtual bool IsMarkable();
   virtual void GetMarkPoints(nsTArray<nsSVGMark> *aMarks);
   virtual void ConstructPath(gfxContext *aCtx) = 0;
   virtual already_AddRefed<gfxFlattenedPath> GetFlattenedPath(const gfxMatrix &aMatrix);
 };
 
 #endif
--- a/content/svg/content/src/nsSVGPatternElement.cpp
+++ b/content/svg/content/src/nsSVGPatternElement.cpp
@@ -80,20 +80,20 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Pattern)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGPatternElement,nsSVGPatternElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGPatternElement,nsSVGPatternElementBase)
 
 DOMCI_NODE_DATA(SVGPatternElement, nsSVGPatternElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGPatternElement)
-  NS_NODE_INTERFACE_TABLE7(nsSVGPatternElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGFitToViewBox,
-                           nsIDOMSVGURIReference, nsIDOMSVGPatternElement,
-                           nsIDOMSVGUnitTypes)
+  NS_NODE_INTERFACE_TABLE8(nsSVGPatternElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGFitToViewBox, nsIDOMSVGURIReference,
+                           nsIDOMSVGPatternElement, nsIDOMSVGUnitTypes)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPatternElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGPatternElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGPatternElement::nsSVGPatternElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGPatternElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGPatternElement.h
+++ b/content/svg/content/src/nsSVGPatternElement.h
@@ -38,32 +38,34 @@
 
 #ifndef __NS_SVGPATTERNELEMENT_H__
 #define __NS_SVGPATTERNELEMENT_H__
 
 #include "nsSVGStylableElement.h"
 #include "nsIDOMSVGURIReference.h"
 #include "nsIDOMSVGFitToViewBox.h"
 #include "nsIDOMSVGPatternElement.h"
+#include "DOMSVGTests.h"
 #include "nsIDOMSVGUnitTypes.h"
 #include "nsSVGLength2.h"
 #include "nsSVGEnum.h"
 #include "nsSVGString.h"
 #include "nsSVGViewBox.h"
 #include "SVGAnimatedPreserveAspectRatio.h"
 #include "SVGAnimatedTransformList.h"
 
 //--------------------- Patterns ------------------------
 
 typedef nsSVGStylableElement nsSVGPatternElementBase;
 
 class nsSVGPatternElement : public nsSVGPatternElementBase,
+                            public nsIDOMSVGPatternElement,
+                            public DOMSVGTests,
                             public nsIDOMSVGURIReference,
                             public nsIDOMSVGFitToViewBox,
-                            public nsIDOMSVGPatternElement,
                             public nsIDOMSVGUnitTypes
 {
   friend class nsSVGPatternFrame;
 
 protected:
   friend nsresult NS_NewSVGPatternElement(nsIContent **aResult,
                                           already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGPatternElement(already_AddRefed<nsINodeInfo> aNodeInfo);
--- a/content/svg/content/src/nsSVGPolygonElement.cpp
+++ b/content/svg/content/src/nsSVGPolygonElement.cpp
@@ -77,18 +77,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Polygon)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGPolygonElement,nsSVGPolygonElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGPolygonElement,nsSVGPolygonElementBase)
 
 DOMCI_NODE_DATA(SVGPolygonElement, nsSVGPolygonElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGPolygonElement)
-  NS_NODE_INTERFACE_TABLE4(nsSVGPolygonElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGPolygonElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGPolygonElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGPolygonElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPolygonElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGPolygonElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGPolygonElement::nsSVGPolygonElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGPolygonElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGPolylineElement.cpp
+++ b/content/svg/content/src/nsSVGPolylineElement.cpp
@@ -71,18 +71,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Polyline)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGPolylineElement,nsSVGPolylineElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGPolylineElement,nsSVGPolylineElementBase)
 
 DOMCI_NODE_DATA(SVGPolylineElement, nsSVGPolylineElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGPolylineElement)
-  NS_NODE_INTERFACE_TABLE4(nsSVGPolylineElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGPolylineElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGPolylineElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGPolylineElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPolylineElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGPolylineElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGPolylineElement::nsSVGPolylineElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGPolylineElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGRectElement.cpp
+++ b/content/svg/content/src/nsSVGRectElement.cpp
@@ -98,18 +98,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Rect)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGRectElement,nsSVGRectElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGRectElement,nsSVGRectElementBase)
 
 DOMCI_NODE_DATA(SVGRectElement, nsSVGRectElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGRectElement)
-  NS_NODE_INTERFACE_TABLE4(nsSVGRectElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGRectElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGRectElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGRectElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGRectElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGRectElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGRectElement::nsSVGRectElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGRectElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -177,18 +177,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsSVGSVGElement,nsSVGSVGElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGSVGElement,nsSVGSVGElementBase)
 
 DOMCI_NODE_DATA(SVGSVGElement, nsSVGSVGElement)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsSVGSVGElement)
-  NS_NODE_INTERFACE_TABLE7(nsSVGSVGElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGSVGElement,
+  NS_NODE_INTERFACE_TABLE8(nsSVGSVGElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGSVGElement,
                            nsIDOMSVGFitToViewBox, nsIDOMSVGLocatable,
                            nsIDOMSVGZoomAndPan)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGSVGElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGSVGElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
--- a/content/svg/content/src/nsSVGSVGElement.h
+++ b/content/svg/content/src/nsSVGSVGElement.h
@@ -37,16 +37,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGSVGELEMENT_H__
 #define __NS_SVGSVGELEMENT_H__
 
 #include "nsSVGStylableElement.h"
 #include "nsIDOMSVGSVGElement.h"
+#include "DOMSVGTests.h"
 #include "nsIDOMSVGFitToViewBox.h"
 #include "nsIDOMSVGLocatable.h"
 #include "nsIDOMSVGZoomAndPan.h"
 #include "nsIDOMSVGMatrix.h"
 #include "nsIDOMSVGPoint.h"
 #include "nsSVGLength2.h"
 #include "nsSVGEnum.h"
 #include "nsSVGViewBox.h"
@@ -113,16 +114,17 @@ public:
     return width != rhs.width || height != rhs.height;
   }
   float width;
   float height;
 };
 
 class nsSVGSVGElement : public nsSVGSVGElementBase,
                         public nsIDOMSVGSVGElement,
+                        public DOMSVGTests,
                         public nsIDOMSVGFitToViewBox,
                         public nsIDOMSVGLocatable,
                         public nsIDOMSVGZoomAndPan
 {
   friend class nsSVGOuterSVGFrame;
   friend class nsSVGInnerSVGFrame;
   friend class nsSVGImageFrame;
 
--- a/content/svg/content/src/nsSVGSetElement.cpp
+++ b/content/svg/content/src/nsSVGSetElement.cpp
@@ -77,19 +77,19 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Set)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGSetElement,nsSVGSetElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGSetElement,nsSVGSetElementBase)
 
 DOMCI_NODE_DATA(SVGSetElement, nsSVGSetElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGSetElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGSetElement, nsIDOMNode, nsIDOMElement,
+  NS_NODE_INTERFACE_TABLE6(nsSVGSetElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement, nsIDOMSVGAnimationElement,
-                           nsIDOMSVGSetElement)
+                           nsIDOMSVGTests, nsIDOMSVGSetElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGSetElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGSetElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGSetElement::nsSVGSetElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGSetElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGSwitchElement.cpp
+++ b/content/svg/content/src/nsSVGSwitchElement.cpp
@@ -31,18 +31,18 @@
  * 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 "mozilla/Util.h"
 
-#include "nsSVGFeatures.h"
 #include "nsSVGSwitchElement.h"
+#include "DOMSVGTests.h"
 #include "nsIFrame.h"
 #include "nsISVGChildFrame.h"
 #include "nsSVGUtils.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
 ////////////////////////////////////////////////////////////////////////
@@ -66,18 +66,19 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_ADDREF_INHERITED(nsSVGSwitchElement,nsSVGSwitchElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGSwitchElement,nsSVGSwitchElementBase)
 
 DOMCI_NODE_DATA(SVGSwitchElement, nsSVGSwitchElement)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsSVGSwitchElement)
-  NS_NODE_INTERFACE_TABLE4(nsSVGSwitchElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGSwitchElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGSwitchElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGSwitchElement,
+                           nsIDOMSVGTests)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGSwitchElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGSwitchElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGSwitchElement::nsSVGSwitchElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGSwitchElementBase(aNodeInfo)
@@ -170,47 +171,54 @@ nsSVGSwitchElement::FindActiveChild() co
     Preferences::GetLocalizedString("intl.accept_languages");
 
   if (allowReorder && !acceptLangs.IsEmpty()) {
     PRInt32 bestLanguagePreferenceRank = -1;
     nsIContent *bestChild = nsnull;
     for (nsIContent* child = nsINode::GetFirstChild();
          child;
          child = child->GetNextSibling()) {
-      if (nsSVGFeatures::PassesConditionalProcessingTests(
-            child, nsSVGFeatures::kIgnoreSystemLanguage)) {
-        nsAutoString value;
-        if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::systemLanguage,
-                           value)) {
+
+      if (!child->IsElement()) {
+        continue;
+      }
+      nsCOMPtr<DOMSVGTests> tests(do_QueryInterface(child));
+      if (tests) {
+        if (tests->PassesConditionalProcessingTests(
+                            DOMSVGTests::kIgnoreSystemLanguage)) {
           PRInt32 languagePreferenceRank =
-            nsSVGFeatures::GetBestLanguagePreferenceRank(value, acceptLangs);
+              tests->GetBestLanguagePreferenceRank(acceptLangs);
           switch (languagePreferenceRank) {
           case 0:
             // best possible match
             return child;
           case -1:
             // not found
             break;
           default:
             if (bestLanguagePreferenceRank == -1 ||
                 languagePreferenceRank < bestLanguagePreferenceRank) {
               bestLanguagePreferenceRank = languagePreferenceRank;
               bestChild = child;
             }
             break;
           }
-        } else if (!bestChild) {
-          bestChild = child;
         }
+      } else if (!bestChild) {
+         bestChild = child;
       }
     }
     return bestChild;
   }
 
   for (nsIContent* child = nsINode::GetFirstChild();
        child;
        child = child->GetNextSibling()) {
-    if (nsSVGFeatures::PassesConditionalProcessingTests(child, &acceptLangs)) {
+    if (!child->IsElement()) {
+      continue;
+    }
+    nsCOMPtr<DOMSVGTests> tests(do_QueryInterface(child));
+    if (!tests || tests->PassesConditionalProcessingTests(&acceptLangs)) {
       return child;
     }
   }
   return nsnull;
 }
--- a/content/svg/content/src/nsSVGSwitchElement.h
+++ b/content/svg/content/src/nsSVGSwitchElement.h
@@ -36,21 +36,23 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGSWITCHELEMENT_H__
 #define __NS_SVGSWITCHELEMENT_H__
 
 #include "nsSVGGraphicElement.h"
 #include "nsIDOMSVGSwitchElement.h"
+#include "DOMSVGTests.h"
 
 typedef nsSVGGraphicElement nsSVGSwitchElementBase;
 
 class nsSVGSwitchElement : public nsSVGSwitchElementBase,
-                           public nsIDOMSVGSwitchElement
+                           public nsIDOMSVGSwitchElement,
+                           public DOMSVGTests
 {
   friend class nsSVGSwitchFrame;
 protected:
   friend nsresult NS_NewSVGSwitchElement(nsIContent **aResult,
                                          already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGSwitchElement(already_AddRefed<nsINodeInfo> aNodeInfo);
 
 public:
--- a/content/svg/content/src/nsSVGSymbolElement.cpp
+++ b/content/svg/content/src/nsSVGSymbolElement.cpp
@@ -32,28 +32,30 @@
  * 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 "mozilla/Util.h"
 
 #include "nsIDOMSVGSymbolElement.h"
+#include "DOMSVGTests.h"
 #include "nsSVGStylableElement.h"
 #include "nsSVGViewBox.h"
 #include "SVGAnimatedPreserveAspectRatio.h"
 #include "nsIDOMSVGFitToViewBox.h"
 #include "nsGkAtoms.h"
 
 using namespace mozilla;
 typedef nsSVGStylableElement nsSVGSymbolElementBase;
 
 class nsSVGSymbolElement : public nsSVGSymbolElementBase,
-                           public nsIDOMSVGFitToViewBox,
-                           public nsIDOMSVGSymbolElement
+                           public nsIDOMSVGSymbolElement,
+                           public DOMSVGTests,
+                           public nsIDOMSVGFitToViewBox
 {
 protected:
   friend nsresult NS_NewSVGSymbolElement(nsIContent **aResult,
                                          already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGSymbolElement(already_AddRefed<nsINodeInfo> aNodeInfo);
 
 public:
   // interfaces:
--- a/content/svg/content/src/nsSVGTSpanElement.cpp
+++ b/content/svg/content/src/nsSVGTSpanElement.cpp
@@ -90,20 +90,21 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(TSpan)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGTSpanElement,nsSVGTSpanElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGTSpanElement,nsSVGTSpanElementBase)
 
 DOMCI_NODE_DATA(SVGTSpanElement, nsSVGTSpanElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGTSpanElement)
-  NS_NODE_INTERFACE_TABLE6(nsSVGTSpanElement, nsIDOMNode, nsIDOMElement,
+  NS_NODE_INTERFACE_TABLE7(nsSVGTSpanElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement, nsIDOMSVGTSpanElement,
                            nsIDOMSVGTextPositioningElement,
-                           nsIDOMSVGTextContentElement)
+                           nsIDOMSVGTextContentElement,
+                           nsIDOMSVGTests)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGTSpanElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGTSpanElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGTSpanElement::nsSVGTSpanElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGTSpanElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGTextContentElement.cpp
+++ b/content/svg/content/src/nsSVGTextContentElement.cpp
@@ -36,16 +36,26 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGTextContentElement.h"
 #include "DOMSVGPoint.h"
 
 using namespace mozilla;
 
+//----------------------------------------------------------------------
+// nsISupports methods
+
+NS_IMPL_ADDREF_INHERITED(nsSVGTextContentElement, nsSVGTextContentElementBase)
+NS_IMPL_RELEASE_INHERITED(nsSVGTextContentElement, nsSVGTextContentElementBase)
+
+NS_INTERFACE_MAP_BEGIN(nsSVGTextContentElement)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTests)
+NS_INTERFACE_MAP_END_INHERITING(nsSVGTextContentElementBase)
+
 /* readonly attribute nsIDOMSVGAnimatedLength textLength; */
 NS_IMETHODIMP nsSVGTextContentElement::GetTextLength(nsIDOMSVGAnimatedLength * *aTextLength)
 {
   NS_NOTYETIMPLEMENTED("nsSVGTextContentElement::GetTextLength");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /* readonly attribute nsIDOMSVGAnimatedEnumeration lengthAdjust; */
--- a/content/svg/content/src/nsSVGTextContentElement.h
+++ b/content/svg/content/src/nsSVGTextContentElement.h
@@ -37,28 +37,31 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGTEXTCONTENTELEMENTBASE_H__
 #define __NS_SVGTEXTCONTENTELEMENTBASE_H__
 
 #include "nsIDOMSVGTextContentElement.h"
 #include "nsSVGTextContainerFrame.h"
 #include "nsSVGStylableElement.h"
+#include "DOMSVGTests.h"
 
 typedef nsSVGStylableElement nsSVGTextContentElementBase;
 
 /**
  * Note that nsSVGTextElement does not inherit nsSVGTextPositioningElement, or
  * this class - it reimplements us instead (see its documenting comment). The
  * upshot is that any changes to this class also need to be made in
  * nsSVGTextElement.
  */
-class nsSVGTextContentElement : public nsSVGTextContentElementBase
+class nsSVGTextContentElement : public nsSVGTextContentElementBase,
+                                public DOMSVGTests
 {
 public:
+  NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGTEXTCONTENTELEMENT
 
 protected:
 
   nsSVGTextContentElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsSVGTextContentElementBase(aNodeInfo)
   {}
 
--- a/content/svg/content/src/nsSVGTextElement.cpp
+++ b/content/svg/content/src/nsSVGTextElement.cpp
@@ -48,16 +48,17 @@
 #include "nsDOMError.h"
 #include "SVGAnimatedLengthList.h"
 #include "DOMSVGAnimatedLengthList.h"
 #include "SVGLengthList.h"
 #include "SVGNumberList.h"
 #include "SVGAnimatedNumberList.h"
 #include "DOMSVGAnimatedNumberList.h"
 #include "DOMSVGPoint.h"
+#include "DOMSVGTests.h"
 
 using namespace mozilla;
 
 typedef nsSVGGraphicElement nsSVGTextElementBase;
 
 /**
  * This class does not inherit nsSVGTextPositioningElement - it reimplements it
  * instead.
@@ -66,17 +67,18 @@ typedef nsSVGGraphicElement nsSVGTextEle
  * nsSVGGraphicElement, but we don't want two instances of nsSVGStylableElement
  * and all the classes it inherits. Instead we choose to inherit one of the
  * classes (nsSVGGraphicElement) and reimplement the missing pieces from the
  * other (nsSVGTextPositioningElement (and thus nsSVGTextContentElement)). Care
  * must be taken when making changes to the reimplemented pieces to keep
  * nsSVGTextPositioningElement in sync (and vice versa).
  */
 class nsSVGTextElement : public nsSVGTextElementBase,
-                         public nsIDOMSVGTextElement // nsIDOMSVGTextPositioningElement
+                         public nsIDOMSVGTextElement, // nsIDOMSVGTextPositioningElement
+                         public DOMSVGTests
 {
 protected:
   friend nsresult NS_NewSVGTextElement(nsIContent **aResult,
                                        already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGTextElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   
 public:
   // interfaces:
@@ -125,20 +127,21 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(Text)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGTextElement,nsSVGTextElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGTextElement,nsSVGTextElementBase)
 
 DOMCI_NODE_DATA(SVGTextElement, nsSVGTextElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGTextElement)
-  NS_NODE_INTERFACE_TABLE6(nsSVGTextElement, nsIDOMNode, nsIDOMElement,
+  NS_NODE_INTERFACE_TABLE7(nsSVGTextElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement, nsIDOMSVGTextElement,
                            nsIDOMSVGTextPositioningElement,
-                           nsIDOMSVGTextContentElement)
+                           nsIDOMSVGTextContentElement,
+                           nsIDOMSVGTests)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGTextElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGTextElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGTextElement::nsSVGTextElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGTextElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGTextPathElement.cpp
+++ b/content/svg/content/src/nsSVGTextPathElement.cpp
@@ -88,19 +88,20 @@ NS_IMPL_NS_NEW_SVG_ELEMENT(TextPath)
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(nsSVGTextPathElement,nsSVGTextPathElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGTextPathElement,nsSVGTextPathElementBase)
 
 DOMCI_NODE_DATA(SVGTextPathElement, nsSVGTextPathElement)
 
 NS_INTERFACE_TABLE_HEAD(nsSVGTextPathElement)
-  NS_NODE_INTERFACE_TABLE6(nsSVGTextPathElement, nsIDOMNode, nsIDOMElement,
+  NS_NODE_INTERFACE_TABLE7(nsSVGTextPathElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement, nsIDOMSVGTextPathElement,
-                           nsIDOMSVGTextContentElement, nsIDOMSVGURIReference)
+                           nsIDOMSVGTextContentElement, nsIDOMSVGTests,
+                           nsIDOMSVGURIReference)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGTextPathElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGTextPathElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGTextPathElement::nsSVGTextPathElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsSVGTextPathElementBase(aNodeInfo)
--- a/content/svg/content/src/nsSVGUseElement.cpp
+++ b/content/svg/content/src/nsSVGUseElement.cpp
@@ -87,18 +87,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsSVGUseElement,nsSVGUseElementBase)
 NS_IMPL_RELEASE_INHERITED(nsSVGUseElement,nsSVGUseElementBase)
 
 DOMCI_NODE_DATA(SVGUseElement, nsSVGUseElement)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsSVGUseElement)
-  NS_NODE_INTERFACE_TABLE6(nsSVGUseElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGURIReference,
+  NS_NODE_INTERFACE_TABLE7(nsSVGUseElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement, nsIDOMSVGTests,
+                           nsIDOMSVGURIReference,
                            nsIDOMSVGUseElement, nsIMutationObserver)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGUseElement)
   if (aIID.Equals(NS_GET_IID(nsSVGUseElement)))
     foundInterface = reinterpret_cast<nsISupports*>(this);
   else
 NS_INTERFACE_MAP_END_INHERITING(nsSVGUseElementBase)
 
 //----------------------------------------------------------------------
--- a/content/svg/content/src/nsSVGUseElement.h
+++ b/content/svg/content/src/nsSVGUseElement.h
@@ -35,16 +35,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGUSEELEMENT_H__
 #define __NS_SVGUSEELEMENT_H__
 
 #include "nsIDOMSVGAnimatedString.h"
 #include "nsIDOMSVGURIReference.h"
 #include "nsIDOMSVGUseElement.h"
+#include "DOMSVGTests.h"
 #include "nsStubMutationObserver.h"
 #include "nsSVGGraphicElement.h"
 #include "nsSVGLength2.h"
 #include "nsSVGString.h"
 #include "nsTArray.h"
 #include "nsReferencedElement.h"
 #include "mozilla/dom/FromParser.h"
 
@@ -58,18 +59,19 @@ class nsINodeInfo;
 nsresult
 NS_NewSVGSVGElement(nsIContent **aResult,
                     already_AddRefed<nsINodeInfo> aNodeInfo,
                     mozilla::dom::FromParser aFromParser);
 
 typedef nsSVGGraphicElement nsSVGUseElementBase;
 
 class nsSVGUseElement : public nsSVGUseElementBase,
+                        public nsIDOMSVGUseElement,
+                        public DOMSVGTests,
                         public nsIDOMSVGURIReference,
-                        public nsIDOMSVGUseElement,
                         public nsStubMutationObserver
 {
   friend class nsSVGUseFrame;
 protected:
   friend nsresult NS_NewSVGUseElement(nsIContent **aResult,
                                       already_AddRefed<nsINodeInfo> aNodeInfo);
   nsSVGUseElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsSVGUseElement();
--- a/content/svg/content/test/test_SVGxxxList.xhtml
+++ b/content/svg/content/test/test_SVGxxxList.xhtml
@@ -271,86 +271,43 @@ var tests = [
       for (var prop in itemA) {
         if (!SVGPathSeg.hasOwnProperty(prop) &&
             prop != 'pathSegTypeAsLetter') {
           is(itemA[prop], itemB[prop], message);
         }
       }
     }
   },
-/*
-  {
-    // SVGPathSegList test:
-    target_element_id: 'path',
-    attr_name: 'd',
-    prop_name: null, // SVGAnimatedPathData is an inherited interface!
-    bv_name: 'normalizedPathSegList',
-    av_name: 'animatedNormalizedPathSegList',
-    el_type: 'SVGPathElement',
-    prop_type: null,
-    list_type: 'SVGPathSegList',
-    item_type: 'SVGPathSeg',
-    attr_val_3a: '',
-    attr_val_3b: '',
-    attr_val_4 : '',
-    attr_val_5a: '',
-    attr_val_5b: '',
-    item_constructor: function() {
-      // XXX return different values each time
-      return SVGPathElement.createSVGPathSegLinetoAbs(1, 1);
-    },
-    item_is: function(itemA, itemB, message) {
-      ok(typeof(itemA.pathSegTypeAsLetter) != 'undefined' &&
-         typeof(itemB.pathSegTypeAsLetter) != 'undefined',
-         'expecting pathSegTypeAsLetter property');
-
-      // First: are we dealing  with the same type of segment?
-      is(itemA.pathSegTypeAsLetter, itemB.pathSegTypeAsLetter, message);
-      if (itemA.pathSegTypeAsLetter != itemB.pathSegTypeAsLetter)
-        return;  // The rest of this function is nonsense if types don't match.
-
-      // Make sure property-counts match (so we can iterate across itemA's
-      // properties and not worry about itemB having extra properties that
-      // we might be skipping over).
-      is(keys(itemA).length, keys(itemB).length,
-        'expecting same property-count when comparing path segs of same type.');
-
-      // Compare the properties, skipping the constant properties inherited
-      // from 'SVGPathSeg', and skipping the pathSegTypeAsLetter field since we
-      // already checked that above. 
-      for (var prop in itemA) {
-        if (!SVGPathSeg.hasOwnProperty(prop) &&
-            prop != 'pathSegTypeAsLetter') {
-          is(itemA[prop], itemB[prop], message);
-        }
-      }
-    }
-  },
   {
     // SVGStringList test:
     target_element_id: 'g',
     attr_name: 'requiredFeatures', // requiredExtensions, systemLanguage, viewTarget
     prop_name: null, // SVGStringList attributes are not animatable
     bv_name: 'requiredFeatures',
     av_name: null,
     el_type: 'SVGGElement',
     prop_type: null,
     list_type: 'SVGStringList',
     item_type: 'DOMString',
-    attr_val_3a: '',
-    attr_val_3b: '',
-    attr_val_4 : '',
-    attr_val_5a: '',
-    attr_val_5b: '',
+    attr_val_3a: 'http://www.w3.org/TR/SVG11/feature#Shape http://www.w3.org/TR/SVG11/feature#Image ' +
+                 'http://www.w3.org/TR/SVG11/feature#Style',
+    attr_val_3b: 'http://www.w3.org/TR/SVG11/feature#CoreAttribute http://www.w3.org/TR/SVG11/feature#Structure ' +
+                 'http://www.w3.org/TR/SVG11/feature#Gradient',
+    attr_val_4 : 'http://www.w3.org/TR/SVG11/feature#Pattern http://www.w3.org/TR/SVG11/feature#Clip ' +
+                 'http://www.w3.org/TR/SVG11/feature#Mask http://www.w3.org/TR/SVG11/feature#Extensibility',
+    attr_val_5a: 'http://www.w3.org/TR/SVG11/feature#BasicStructure http://www.w3.org/TR/SVG11/feature#BasicText ' +
+                 'http://www.w3.org/TR/SVG11/feature#BasicPaintAttribute http://www.w3.org/TR/SVG11/feature#BasicGraphicsAttribute ' +
+                 'http://www.w3.org/TR/SVG11/feature#BasicClip',
+    attr_val_5b: 'http://www.w3.org/TR/SVG11/feature#DocumentEventsAttribute http://www.w3.org/TR/SVG11/feature#GraphicalEventsAttribute ' +
+                 'http://www.w3.org/TR/SVG11/feature#AnimationEventsAttribute http://www.w3.org/TR/SVG11/feature#Hyperlinking ' +
+                 'http://www.w3.org/TR/SVG11/feature#XlinkAttribute',
     item_constructor: function() {
-      // XXX return a meaningful string
-      return ;
+      return 'http://www.w3.org/TR/SVG11/feature#XlinkAttribute';
     }
   },
-  */
   {
     // SVGTransformList test:
     target_element_id: 'g',
     attr_name: 'transform', // gradientTransform, patternTransform
     prop_name: 'transform',
     bv_name: 'baseVal',
     av_name: 'animVal',
     el_type: 'SVGGElement',
@@ -530,46 +487,49 @@ function run_baseVal_API_tests()
     ok(t.baseVal.getItem(0) === item,
        'The list item at index 0 should be the exact same object as the '+
        'object that was passed to the '+t.list_type+'.initialize() method, '+
        'since the item that was passed to that method did not already '+
        'belong to a list.');
 
     t.element.setAttribute(t.attr_name, t.attr_val_4);
 
-    var old_items = get_array_of_list_items(t.baseVal);
-    item = t.baseVal.getItem(3);
-    res = t.baseVal.initialize(item);
+    if (t.item_type != "DOMString") {
+      var old_items = get_array_of_list_items(t.baseVal);
+      item = t.baseVal.getItem(3);
+      res = t.baseVal.initialize(item);
 
-    ok(res !== item &&
-       t.baseVal.getItem(0) !== item &&
-       t.baseVal.getItem(0) !== old_items[0] &&
-       res === t.baseVal.getItem(0),
-       'The method '+t.list_type+'.initialize() should clone the object that '+
-       'is passed in if that object is already in a list.');
-    // [SVGWG issue] not what the spec currently says
+      ok(res !== item &&
+         t.baseVal.getItem(0) !== item &&
+         t.baseVal.getItem(0) !== old_items[0] &&
+         res === t.baseVal.getItem(0),
+         'The method '+t.list_type+'.initialize() should clone the object that '+
+         'is passed in if that object is already in a list.');
+      // [SVGWG issue] not what the spec currently says
 
-    item = t.baseVal.getItem(0);
-    res = t.baseVal.initialize(item);
+
+      item = t.baseVal.getItem(0);
+      res = t.baseVal.initialize(item);
 
-    ok(res !== item &&
-       t.baseVal.getItem(0) !== item,
-       'The method '+t.list_type+'.initialize() should clone the object that '+
-       'is passed in, even if that object is the only item in that list.');
-    // [SVGWG issue] not what the spec currently says
+      ok(res !== item &&
+         t.baseVal.getItem(0) !== item,
+         'The method '+t.list_type+'.initialize() should clone the object that '+
+         'is passed in, even if that object is the only item in that list.');
+      // [SVGWG issue] not what the spec currently says
 
-    threw = false;
-    try {
-      t.baseVal.initialize({});
-    } catch(e) {
-      threw = true;
+      threw = false;
+      try {
+        t.baseVal.initialize({});
+      } catch(e) {
+        threw = true;
+      }
+      ok(threw,
+         'The method '+t.list_type+'.initialize() should throw if passed an '+
+         'object of the wrong type.');
     }
-    ok(threw,
-       'The method '+t.list_type+'.initialize() should throw if passed an '+
-       'object of the wrong type.');
 
     // Test .insertItemBefore():
 
     t.element.setAttribute(t.attr_name, t.attr_val_4);
 
     old_items = get_array_of_list_items(t.baseVal);
     item = t.item_constructor();
     res = t.baseVal.insertItemBefore(item, 2);
@@ -599,61 +559,67 @@ function run_baseVal_API_tests()
        'method is out of bounds, the supplied list item should be appended '+
        'to the list.');
 
     item = t.baseVal.getItem(4);
     res = t.baseVal.insertItemBefore(item, 2);
 
     is(t.baseVal.numberOfItems, 7,
        'The '+t.list_type+' object should contain seven list items.');
-    ok(res !== item &&
-       t.baseVal.getItem(2) !== item &&
-       t.baseVal.getItem(2) !== old_items[2] &&
-       res === t.baseVal.getItem(2),
-       'The method '+t.list_type+'.insertItemBefore() should clone the '+
-       'object that is passed in if that object is already in a list.');
-    // [SVGWG issue] not what the spec currently says
+    if (t.item_type != "DOMString") {
+      ok(res !== item &&
+         t.baseVal.getItem(2) !== item &&
+         t.baseVal.getItem(2) !== old_items[2] &&
+         res === t.baseVal.getItem(2),
+         'The method '+t.list_type+'.insertItemBefore() should clone the '+
+         'object that is passed in if that object is already in a list.');
+      // [SVGWG issue] not what the spec currently says
+    }
 
     item = t.baseVal.getItem(2);
     res = t.baseVal.insertItemBefore(item, 2);
 
     is(t.baseVal.numberOfItems, 8,
        'The '+t.list_type+' object should contain eight list items.');
-    ok(res !== item &&
-       t.baseVal.getItem(2) !== item,
-       'The method '+t.list_type+'.insertItemBefore() should clone the '+
-       'object that is passed in, even if that object is the item in '+
-       'the list at the index specified.');
-    // [SVGWG issue] not what the spec currently says
+    if (t.item_type != "DOMString") {
+      ok(res !== item &&
+         t.baseVal.getItem(2) !== item,
+         'The method '+t.list_type+'.insertItemBefore() should clone the '+
+         'object that is passed in, even if that object is the item in '+
+         'the list at the index specified.');
+      // [SVGWG issue] not what the spec currently says
 
-    threw = false;
-    try {
-      t.baseVal.insertItemBefore({}, 2);
-    } catch(e) {
-      threw = true;
+      threw = false;
+      try {
+        t.baseVal.insertItemBefore({}, 2);
+      } catch(e) {
+        threw = true;
+      }
+      ok(threw,
+         'The method '+t.list_type+'.insertItemBefore() should throw if passed '+
+         'an object of the wrong type.');
     }
-    ok(threw,
-       'The method '+t.list_type+'.insertItemBefore() should throw if passed '+
-       'an object of the wrong type.');
 
     // Test .replaceItem():
 
     t.element.setAttribute(t.attr_name, t.attr_val_4);
 
     old_items = get_array_of_list_items(t.baseVal);
     item = t.item_constructor();
     res = t.baseVal.replaceItem(item, 2);
 
     is(t.baseVal.numberOfItems, 4,
        'The '+t.list_type+' object should contain four list items.');
-    ok(res === item,
-       'The list item returned by '+t.list_type+'.replaceItem() should be '+
-       'the exact same object as the item that was passed to that method, '+
-       'since the item that was passed to that method did not already belong '+
-       'to a list.');
+    if (t.item_type != "DOMString") {
+      ok(res === item,
+         'The list item returned by '+t.list_type+'.replaceItem() should be '+
+         'the exact same object as the item that was passed to that method, '+
+         'since the item that was passed to that method did not already belong '+
+         'to a list.');
+    }
     ok(t.baseVal.getItem(2) === item,
        'The list item at index 2 should be the exact same object as the '+
        'object that was passed to the '+t.list_type+'.replaceItem() method, '+
        'since the item that was passed to that method did not already belong '+
        'to a list.');
     ok(t.baseVal.getItem(3) === old_items[3],
        'The list item that was at index 3 should still be at index 3 after '+
        'the item at index 2 was replaced using the '+t.list_type+
@@ -672,59 +638,65 @@ function run_baseVal_API_tests()
        'an index that is out of bounds.');
 
     old_items = get_array_of_list_items(t.baseVal);
     item = t.baseVal.getItem(3);
     res = t.baseVal.replaceItem(item, 1);
 
     is(t.baseVal.numberOfItems, 4,
        'The '+t.list_type+' object should contain four list items.');
-    ok(res !== item &&
-       t.baseVal.getItem(1) !== item &&
-       t.baseVal.getItem(1) !== old_items[1] &&
-       res === t.baseVal.getItem(1),
-       'The method '+t.list_type+'.replaceItem() should clone the object '+
-       'that is passed in if that object is already in a list.');
-    // [SVGWG issue] not what the spec currently says
+    if (t.item_type != "DOMString") {
+      ok(res !== item &&
+         t.baseVal.getItem(1) !== item &&
+         t.baseVal.getItem(1) !== old_items[1] &&
+         res === t.baseVal.getItem(1),
+         'The method '+t.list_type+'.replaceItem() should clone the object '+
+         'that is passed in if that object is already in a list.');
+      // [SVGWG issue] not what the spec currently says
+    }
 
     item = t.baseVal.getItem(1);
     res = t.baseVal.replaceItem(item, 1);
 
     is(t.baseVal.numberOfItems, 4,
        'The '+t.list_type+' object should contain four list items.');
-    ok(res !== item &&
-       t.baseVal.getItem(1) !== item,
-       'The method '+t.list_type+'.replaceItem() should clone the object '+
-       'that is passed in, even if the object that object and the object '+
-       'that is being replaced are the exact same objects.');
-    // [SVGWG issue] not what the spec currently says
+    if (t.item_type != "DOMString") {
+      ok(res !== item &&
+         t.baseVal.getItem(1) !== item,
+         'The method '+t.list_type+'.replaceItem() should clone the object '+
+         'that is passed in, even if the object that object and the object '+
+         'that is being replaced are the exact same objects.');
+      // [SVGWG issue] not what the spec currently says
 
-    threw = false;
-    try {
-      t.baseVal.replaceItem({}, 2);
-    } catch(e) {
-      threw = true;
+      threw = false;
+      try {
+        t.baseVal.replaceItem({}, 2);
+      } catch(e) {
+        threw = true;
+      }
+      ok(threw,
+         'The method '+t.list_type+'.replaceItem() should throw if passed '+
+         'an object of the wrong type.');
     }
-    ok(threw,
-       'The method '+t.list_type+'.replaceItem() should throw if passed '+
-       'an object of the wrong type.');
 
     // Test .removeItem():
 
     t.element.setAttribute(t.attr_name, t.attr_val_4);
 
     old_items = get_array_of_list_items(t.baseVal);
     item = t.baseVal.getItem(2);
     res = t.baseVal.removeItem(2);
 
     is(t.baseVal.numberOfItems, 3,
        'The '+t.list_type+' object should contain three list items.');
-    ok(res === item,
-       'The list item returned by '+t.list_type+'.removeItem() should be the '+
-       'exact same object as the item that was at the specified index.');
+    if (t.item_type != "DOMString") {
+      ok(res === item,
+         'The list item returned by '+t.list_type+'.removeItem() should be the '+
+         'exact same object as the item that was at the specified index.');
+    }
     ok(t.baseVal.getItem(1) === old_items[1],
        'The list item that was at index 1 should still be at index 1 after '+
        'the item at index 2 was removed using the '+t.list_type+
        '.replaceItem() method.');
     ok(t.baseVal.getItem(2) === old_items[3],
        'The list item that was at index 3 should still be at index 2 after '+
        'the item at index 2 was removed using the '+t.list_type+
        '.replaceItem() method.');
@@ -764,46 +736,48 @@ function run_baseVal_API_tests()
        'appending a new item using the '+t.list_type+'.appendItem() '+
        'method.');
 
     item = t.baseVal.getItem(2);
     res = t.baseVal.appendItem(item);
 
     is(t.baseVal.numberOfItems, 6,
        'The '+t.list_type+' object should contain six list items.');
-    ok(res !== item &&
-       t.baseVal.getItem(5) !== item &&
-       res === t.baseVal.getItem(5),
-       'The method '+t.list_type+'.appendItem() should clone the object '+
-       'that is passed in if that object is already in a list.');
-    // [SVGWG issue] not what the spec currently says
+    if (t.item_type != "DOMString") {
+      ok(res !== item &&
+         t.baseVal.getItem(5) !== item &&
+         res === t.baseVal.getItem(5),
+         'The method '+t.list_type+'.appendItem() should clone the object '+
+         'that is passed in if that object is already in a list.');
+      // [SVGWG issue] not what the spec currently says
+    }
 
     item = t.baseVal.getItem(5);
     res = t.baseVal.appendItem(item);
 
     is(t.baseVal.numberOfItems, 7,
        'The '+t.list_type+' object should contain seven list items.');
-    ok(res !== item &&
-       t.baseVal.getItem(6) !== item,
-       'The method '+t.list_type+'.appendItem() should clone the object '+
-       'that is passed in, if that object is already the last item in '+
-       'that list.');
-    // [SVGWG issue] not what the spec currently says
-
-
+    if (t.item_type != "DOMString") {
+      ok(res !== item &&
+         t.baseVal.getItem(6) !== item,
+         'The method '+t.list_type+'.appendItem() should clone the object '+
+         'that is passed in, if that object is already the last item in '+
+         'that list.');
+      // [SVGWG issue] not what the spec currently says
 
-    threw = false;
-    try {
-      t.baseVal.appendItem({});
-    } catch(e) {
-      threw = true;
+      threw = false;
+      try {
+        t.baseVal.appendItem({});
+      } catch(e) {
+        threw = true;
+      }
+      ok(threw,
+         'The method '+t.list_type+'.appendItem() should throw if passed '+
+         'an object of the wrong type.');
     }
-    ok(threw,
-       'The method '+t.list_type+'.appendItem() should throw if passed '+
-       'an object of the wrong type.');
   }
 }
 
 
 /**
  * This function tests the SVGXxxList API for the anim val list (see also the
  * comment for test_baseVal_API).
  */
@@ -948,43 +922,47 @@ function run_basic_setAttribute_tests()
          'time the item at a given index in the '+t.list_type+' for '+
          t.av_path+' is accessed, given that the index was not made invalid '+
          'by a change in list length between the successive accesses.');
     }
 
     // Test the effect of setting the attribute to new values:
 
     t.old_baseVal_items = get_array_of_list_items(t.baseVal);
-    t.old_animVal_items = get_array_of_list_items(t.animVal);
+    if (t.animVal) {
+      t.old_animVal_items = get_array_of_list_items(t.animVal);
+    }
 
     t.element.setAttribute(t.attr_name, t.attr_val_3a);
     t.element.setAttribute(t.attr_name, t.attr_val_5a);
 
     ok(t.baseVal.numberOfItems == 5 && t.baseVal.getItem(4) != null,
        'The length of the '+t.list_type+' object for '+t.bv_path+' should '+
        'have been set to 5 by the setAttribute() call.');
 
     if (t.animVal) {
       ok(t.baseVal.numberOfItems == t.animVal.numberOfItems,
          'Since no animations are active, the length of the '+t.list_type+' '+
          'objects for '+t.bv_path+' and '+t.av_path+' should be the same '+
          '(5).');
     }
 
-    ok(t.baseVal.getItem(2) === t.old_baseVal_items[2],
-       'After its attribute changes, list items in the '+t.list_type+' for '+
-       t.bv_path+' that are at indexes that existed prior to the attribute '+
-       'change should be the exact same objects as the objects that were '+
-       'at those indexes prior to the attribute change.');
+    if (t.item_type != "DOMString") {
+      ok(t.baseVal.getItem(2) === t.old_baseVal_items[2],
+         'After its attribute changes, list items in the '+t.list_type+' for '+
+         t.bv_path+' that are at indexes that existed prior to the attribute '+
+         'change should be the exact same objects as the objects that were '+
+         'at those indexes prior to the attribute change.');
 
-    ok(t.baseVal.getItem(3) !== t.old_baseVal_items[3],
-       'After its attribute changes, list items in the '+t.list_type+' for '+
-       t.bv_path+' that are at indexes that did not exist prior to the '+
-       'attribute change should not be the same objects as any objects that '+
-       'were at those indexes at some earlier time.');
+      ok(t.baseVal.getItem(3) !== t.old_baseVal_items[3],
+         'After its attribute changes, list items in the '+t.list_type+' for '+
+         t.bv_path+' that are at indexes that did not exist prior to the '+
+         'attribute change should not be the same objects as any objects that '+
+         'were at those indexes at some earlier time.');
+    }
 
     if (t.animVal) {
       ok(t.animVal.getItem(2) === t.old_animVal_items[2],
          'After its attribute changes, list items in the '+t.list_type+' for '+
          t.av_path+' that are at indexes that existed prior to the attribute '+
          'change should be the exact same objects as the objects that were '+
          'at those indexes prior to the attribute change.');
 
@@ -1345,17 +1323,19 @@ function run_tests()
       t.item_is = function(itemA, itemB, message) {
       ok(typeof(itemA.value) != 'undefined' &&
          typeof(itemB.value) != 'undefined',
          'expecting value property');
         is(itemA.value, itemB.value, message);
       };
     }
 
-    t.element.appendChild(create_animate_elements(t));
+    if (t.animVal) {
+      t.element.appendChild(create_animate_elements(t));
+    }
   }
 
   // Run the major test groups:
 
   run_baseVal_API_tests();
   run_animVal_API_tests();
   run_basic_setAttribute_tests();
   run_list_mutation_tests();
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -419,16 +419,17 @@
 #include "nsIDOMSVGRectElement.h"
 #include "nsIDOMSVGScriptElement.h"
 #include "nsIDOMSVGStopElement.h"
 #include "nsIDOMSVGStylable.h"
 #include "nsIDOMSVGStyleElement.h"
 #include "nsIDOMSVGSVGElement.h"
 #include "nsIDOMSVGSwitchElement.h"
 #include "nsIDOMSVGSymbolElement.h"
+#include "nsIDOMSVGTests.h"
 #include "nsIDOMSVGTextElement.h"
 #include "nsIDOMSVGTextPathElement.h"
 #include "nsIDOMSVGTitleElement.h"
 #include "nsIDOMSVGTransform.h"
 #include "nsIDOMSVGTransformable.h"
 #include "nsIDOMSVGTransformList.h"
 #include "nsIDOMSVGTSpanElement.h"
 #include "nsIDOMSVGUnitTypes.h"
@@ -1240,16 +1241,18 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(SVGPoint, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGPointList, nsSVGPointListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGPreserveAspectRatio, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGRect, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(SVGStringList, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)    
   NS_DEFINE_CLASSINFO_DATA(SVGTransform, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGTransformList, nsSVGTransformListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGZoomEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(HTMLCanvasElement, nsElementSH,
@@ -3087,55 +3090,61 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGDocument)
     DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   // SVG element classes
 
   DOM_CLASSINFO_MAP_BEGIN(SVGAElement, nsIDOMSVGAElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGAltGlyphElement, nsIDOMSVGAltGlyphElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTextPositioningElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTextContentElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGAnimateElement, nsIDOMSVGAnimateElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGAnimateTransformElement,
                           nsIDOMSVGAnimateTransformElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateTransformElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGAnimateMotionElement,
                           nsIDOMSVGAnimateMotionElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateMotionElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGSetElement,
                           nsIDOMSVGSetElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSetElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGMpathElement, nsIDOMSVGMpathElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
@@ -3143,41 +3152,42 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN(TimeEvent, nsIDOMTimeEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMTimeEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGCircleElement, nsIDOMSVGCircleElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGCircleElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGClipPathElement, nsIDOMSVGClipPathElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGClipPathElement)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGLocatable)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTransformable)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUnitTypes)
-    DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
+    DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGDefsElement, nsIDOMSVGDefsElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGDefsElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGDescElement, nsIDOMSVGDescElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGDescElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGEllipseElement, nsIDOMSVGEllipseElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGEllipseElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGFEBlendElement, nsIDOMSVGFEBlendElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEBlendElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
@@ -3326,104 +3336,116 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFETurbulenceElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGFilterElement, nsIDOMSVGFilterElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUnitTypes)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGGElement, nsIDOMSVGGElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGGElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGImageElement, nsIDOMSVGImageElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGImageElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGLinearGradientElement, nsIDOMSVGLinearGradientElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGGradientElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGLinearGradientElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUnitTypes)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGLineElement, nsIDOMSVGLineElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGLineElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGMarkerElement, nsIDOMSVGMarkerElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGMarkerElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGMaskElement, nsIDOMSVGMaskElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGMaskElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUnitTypes)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGMetadataElement, nsIDOMSVGMetadataElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGMetadataElement)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGPathElement, nsIDOMSVGPathElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGPathElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedPathData)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGPatternElement, nsIDOMSVGPatternElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGPatternElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUnitTypes)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGPolygonElement, nsIDOMSVGPolygonElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGPolygonElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedPoints)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGPolylineElement, nsIDOMSVGPolylineElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGPolylineElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimatedPoints)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGRadialGradientElement, nsIDOMSVGRadialGradientElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGGradientElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGRadialGradientElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUnitTypes)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGRectElement, nsIDOMSVGRectElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGRectElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGScriptElement, nsIDOMSVGScriptElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGScriptElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
@@ -3440,68 +3462,75 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGSVGElement, nsIDOMSVGSVGElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSVGElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGLocatable)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGZoomAndPan)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGSwitchElement, nsIDOMSVGSwitchElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSwitchElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGSymbolElement, nsIDOMSVGSymbolElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSymbolElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFitToViewBox)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGTextElement, nsIDOMSVGTextElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTextPositioningElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTextContentElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGTextPathElement, nsIDOMSVGTextPathElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTextContentElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGTitleElement, nsIDOMSVGTitleElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTitleElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGTSpanElement, nsIDOMSVGTSpanElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTextPositioningElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTextContentElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStylable)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(SVGUnknownElement, nsIDOMSVGElement)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGUseElement, nsIDOMSVGUseElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUseElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   // other SVG classes
 
   DOM_CLASSINFO_MAP_BEGIN(SVGAngle, nsIDOMSVGAngle)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAngle)
@@ -3695,16 +3724,20 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(SVGPreserveAspectRatio, nsIDOMSVGPreserveAspectRatio)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGPreserveAspectRatio)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGRect, nsIDOMSVGRect)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGRect)
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN(SVGStringList, nsIDOMSVGStringList)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGStringList)
+  DOM_CLASSINFO_MAP_END
+
   DOM_CLASSINFO_MAP_BEGIN(SVGTransform, nsIDOMSVGTransform)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTransform)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGTransformList, nsIDOMSVGTransformList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTransformList)
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -50,30 +50,33 @@
 #include "nsContentUtils.h"
 #include "xpcpublic.h"
 
 namespace mozilla {
 class DOMSVGLengthList;
 class DOMSVGNumberList;
 class DOMSVGPathSegList;
 class DOMSVGPointList;
+class DOMSVGStringList;
 class DOMSVGTransformList;
 }
 class nsGlobalWindow;
 class nsIDOMDocument;
 class nsIDOMHTMLOptionsCollection;
 class nsIDOMNodeList;
 class nsIDOMSVGLength;
 class nsIDOMSVGLengthList;
 class nsIDOMSVGNumber;
 class nsIDOMSVGNumberList;
 class nsIDOMSVGPathSeg;
 class nsIDOMSVGPathSegList;
 class nsIDOMSVGPoint;
 class nsIDOMSVGPointList;
+class nsIDOMSVGStringList;
+class nsIDOMSVGTests;
 class nsIDOMSVGTransform;
 class nsIDOMSVGTransformList;
 class nsIDOMWindow;
 class nsIForm;
 class nsIHTMLDocument;
 class nsNPAPIPluginInstance;
 
 struct nsDOMClassInfoData;
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -336,16 +336,17 @@ DOMCI_CLASS(SVGPathSegLinetoVerticalAbs)
 DOMCI_CLASS(SVGPathSegLinetoVerticalRel)
 DOMCI_CLASS(SVGPathSegList)
 DOMCI_CLASS(SVGPathSegMovetoAbs)
 DOMCI_CLASS(SVGPathSegMovetoRel)
 DOMCI_CLASS(SVGPoint)
 DOMCI_CLASS(SVGPointList)
 DOMCI_CLASS(SVGPreserveAspectRatio)
 DOMCI_CLASS(SVGRect)
+DOMCI_CLASS(SVGStringList)
 DOMCI_CLASS(SVGTransform)
 DOMCI_CLASS(SVGTransformList)
 DOMCI_CLASS(SVGZoomEvent)
 
 // Canvas
 DOMCI_CLASS(HTMLCanvasElement)
 DOMCI_CLASS(CanvasRenderingContext2D)
 DOMCI_CLASS(CanvasGradient)
--- a/dom/interfaces/svg/Makefile.in
+++ b/dom/interfaces/svg/Makefile.in
@@ -108,20 +108,22 @@ XPIDLSRCS	= \
 		nsIDOMSVGPolylineElement.idl \
 		nsIDOMSVGPresAspectRatio.idl \
 		nsIDOMSVGRect.idl \
 		nsIDOMSVGRectElement.idl \
 		nsIDOMSVGScriptElement.idl \
 		nsIDOMSVGSetElement.idl \
 		nsIDOMSVGSVGElement.idl \
 		nsIDOMSVGStopElement.idl \
+		nsIDOMSVGStringList.idl \
 		nsIDOMSVGStylable.idl \
 		nsIDOMSVGStyleElement.idl \
 		nsIDOMSVGSwitchElement.idl \
 		nsIDOMSVGSymbolElement.idl \
+		nsIDOMSVGTests.idl \
 		nsIDOMSVGTextContentElement.idl \
 		nsIDOMSVGTextElement.idl \
 		nsIDOMSVGTextPathElement.idl \
 		nsIDOMSVGTextPositionElem.idl \
 		nsIDOMSVGTitleElement.idl \
 		nsIDOMSVGTransform.idl \
 		nsIDOMSVGTransformList.idl \
 		nsIDOMSVGTransformable.idl \
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/svg/nsIDOMSVGStringList.idl
@@ -0,0 +1,59 @@
+/* -*- Mode: IDL; 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
+ * Robert Longson
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * 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 "domstubs.idl"
+
+[scriptable, uuid(481f01a5-0bbb-4abf-8623-f3c2fb5642a9)]
+interface nsIDOMSVGStringList : nsISupports
+{ 
+  readonly attribute unsigned long numberOfItems;
+
+  void clear();
+          // raises(nsIDOMDOMException);
+  DOMString initialize(in DOMString newItem);
+                    // raises(nsIDOMDOMException);
+  DOMString getItem(in unsigned long index);
+                    // raises(nsIDOMDOMException);
+  DOMString insertItemBefore(in DOMString newItem, in unsigned long index);
+                    // raises(nsIDOMDOMException);
+  DOMString replaceItem(in DOMString newItem, in unsigned long index);
+                    // raises(nsIDOMDOMException);
+  DOMString removeItem(in unsigned long index);
+                    // raises(nsIDOMDOMException);
+  DOMString appendItem(in DOMString newItem);
+                    // raises(nsIDOMDOMException);
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/svg/nsIDOMSVGTests.idl
@@ -0,0 +1,49 @@
+/* -*- Mode: IDL; 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
+ * Robert Longson
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * 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 "nsIDOMSVGStringList.idl"
+
+[scriptable, uuid(b6186ed0-0861-11e1-be50-0800200c9a66)]
+interface nsIDOMSVGTests : nsISupports
+{
+  readonly attribute nsIDOMSVGStringList requiredFeatures;
+  readonly attribute nsIDOMSVGStringList requiredExtensions;
+  readonly attribute nsIDOMSVGStringList systemLanguage;
+
+  boolean hasExtension(in DOMString extension);
+};
+
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -138,17 +138,17 @@
 #include "nsIScrollableFrame.h"
 
 #include "nsIXBLService.h"
 
 #undef NOISY_FIRST_LETTER
 
 #include "nsMathMLParts.h"
 #include "nsIDOMSVGFilters.h"
-#include "nsSVGFeatures.h"
+#include "DOMSVGTests.h"
 #include "nsSVGEffects.h"
 #include "nsSVGUtils.h"
 #include "nsSVGOuterSVGFrame.h"
 
 #include "nsRefreshDriver.h"
 #include "nsRuleProcessorData.h"
 
 using namespace mozilla;
@@ -4790,17 +4790,18 @@ nsCSSFrameConstructor::FindSVGData(Eleme
     // and do the PassesConditionalProcessingTests call in
     // nsSVGOuterSVGFrame::Init.
     static const FrameConstructionData sOuterSVGData =
       FCDATA_DECL(FCDATA_SKIP_ABSPOS_PUSH | FCDATA_DISALLOW_GENERATED_CONTENT,
                   NS_NewSVGOuterSVGFrame);
     return &sOuterSVGData;
   }
   
-  if (!nsSVGFeatures::PassesConditionalProcessingTests(aElement)) {
+  nsCOMPtr<DOMSVGTests> tests(do_QueryInterface(aElement));
+  if (tests && !tests->PassesConditionalProcessingTests()) {
     // Elements with failing conditional processing attributes never get
     // rendered.  Note that this is not where we select which frame in a
     // <switch> to render!  That happens in nsSVGSwitchFrame::PaintSVG.
     return &sContainerData;
   }
 
   // Prevent bad frame types being children of filters or parents of filter
   // primitives:
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/conditions-06.svg
@@ -0,0 +1,69 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg id="svg-root" width="100%" height="100%"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink" onload="runtest()">
+  <title>Test conditional processing DOM interface</title>
+  <defs>
+    <script>
+      function runtest() {
+        try {
+          var r1 = document.getElementById("r1");
+          var r2 = document.getElementById("r2");
+          var r3 = document.getElementById("r3");
+          var i0 = r1.requiredFeatures.getItem(0);
+          var i1 = r1.requiredFeatures.getItem(1);
+
+          if(i0 != "http://www.w3.org/TR/SVG11/feature#Shape") {
+            r1.removeAttribute("requiredFeatures");
+            return;
+          }
+          if(i1 != "this.is.a.bogus.feature.string") {
+            r1.removeAttribute("requiredFeatures");
+            return;
+          }
+          if(r1.requiredFeatures.numberOfItems != 2) {
+            r1.removeAttribute("requiredFeatures");
+            return;
+          }
+          r2.requiredFeatures.appendItem(i1);
+          if(r1.requiredFeatures.numberOfItems != 2) {
+            r1.removeAttribute("requiredFeatures");
+            return;
+          }
+          if(r2.requiredFeatures.numberOfItems != 1) {
+            r1.removeAttribute("requiredFeatures");
+            return;
+          }
+          r3.requiredFeatures.insertItemBefore(i0,0);
+          if(r3.requiredFeatures.numberOfItems != 2) {
+            r3.setAttribute("fill", "red");
+            return;
+          }
+          if(r1.requiredFeatures.numberOfItems != 2) {
+            r1.removeAttribute("requiredFeatures");
+            return;
+          }
+        } catch(e) {
+          var f = document.getElementById("fail");
+          f.setAttribute("fill", "red");
+        }
+      }
+    </script>
+  </defs>
+
+  <rect width="100%" height="100%" fill="lime"/>
+  <!-- background images -->
+  <rect x="100" y="100" width="100" height="100" fill="lime"/>
+  <rect x="190" y="100" width="100" height="100" fill="lime"/>
+  <rect x="300" y="100" width="100" height="100" fill="red"/>
+
+  <!-- tests -->
+  <rect id="r1" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Shape this.is.a.bogus.feature.string" x="100" y="100" width="100" height="100" fill="red"/>
+  <rect id="r2" x="190" y="100" width="100" height="100" fill="red"/>
+  <rect id="r3" x="300" y="100" width="100" height="100" fill="lime" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Shape"/>
+
+  <rect id="fail" width="100%" height="100%" fill="none"/>
+</svg>
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -36,16 +36,17 @@ include svg-integration/reftest.list
 == clipPath-basic-05.svg pass.svg
 == clipPath-winding-01.svg pass.svg
 == clip-surface-clone-01.svg clip-surface-clone-01-ref.svg
 fails-if(Android) == conditions-01.svg pass.svg # bug 652050
 == conditions-02.svg pass.svg
 == conditions-03.svg pass.svg
 == conditions-04.svg pass.svg
 == conditions-05.svg about:blank
+== conditions-06.svg pass.svg
 == currentColor-01.svg pass.svg
 == currentColor-02.svg pass.svg
 == currentColor-03.svg pass.svg
 == data-uri-with-filter-01.xhtml data-uri-with-filter-01-ref.svg
 == data-uri-with-gradient-01.xhtml data-uri-with-gradient-01-ref.svg
 == data-uri-with-pattern-01.xhtml pass.svg
 == dynamic-attr-removal-1.svg pass.svg
 == dynamic-attr-removal-2.svg pass.svg
--- a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp
+++ b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGOuterSVGFrame.h"
 #include "nsIDOMSVGSVGElement.h"
 #include "nsSVGSVGElement.h"
 #include "nsSVGTextFrame.h"
 #include "nsSVGForeignObjectFrame.h"
+#include "DOMSVGTests.h"
 #include "nsDisplayList.h"
 #include "nsStubMutationObserver.h"
 #include "gfxContext.h"
 #include "gfxMatrix.h"
 #include "gfxRect.h"
 #include "nsIContentViewer.h"
 #include "nsIDocShell.h"
 #include "nsIDOMDocument.h"
@@ -160,17 +161,18 @@ nsSVGOuterSVGFrame::Init(nsIContent* aCo
   NS_ASSERTION(svgElement, "Content is not an SVG 'svg' element!");
 #endif
 
   AddStateBits(NS_STATE_IS_OUTER_SVG);
 
   // Check for conditional processing attributes here rather than in
   // nsCSSFrameConstructor::FindSVGData because we want to avoid
   // simply giving failing outer <svg> elements an nsSVGContainerFrame.
-  if (!nsSVGFeatures::PassesConditionalProcessingTests(aContent)) {
+  nsSVGSVGElement *svg = static_cast<nsSVGSVGElement*>(aContent);
+  if (!svg->PassesConditionalProcessingTests()) {
     AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD);
   }
 
   nsresult rv = nsSVGOuterSVGFrameBase::Init(aContent, aParent, aPrevInFlow);
 
   nsIDocument* doc = mContent->GetCurrentDoc();
   if (doc) {
     // we only care about our content's zoom and pan values if it's the root element
--- a/layout/svg/base/src/nsSVGOuterSVGFrame.h
+++ b/layout/svg/base/src/nsSVGOuterSVGFrame.h
@@ -38,17 +38,16 @@
 
 #ifndef __NS_SVGOUTERSVGFRAME_H__
 #define __NS_SVGOUTERSVGFRAME_H__
 
 #include "nsSVGContainerFrame.h"
 #include "nsISVGSVGFrame.h"
 #include "nsIDOMSVGPoint.h"
 #include "nsIDOMSVGNumber.h"
-#include "nsSVGFeatures.h"
 #include "gfxMatrix.h"
 
 class nsSVGForeignObjectFrame;
 
 ////////////////////////////////////////////////////////////////////////
 // nsSVGOuterSVGFrame class
 
 typedef nsSVGDisplayContainerFrame nsSVGOuterSVGFrameBase;