Merge fx-team with mozilla-central
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Thu, 17 Jan 2013 16:14:57 -0800
changeset 119127 b52c02f77cf5b76027fea25412e629cd3d551cb3
parent 119126 4a1b771880d830a75f83593b31493c0874166b13 (current diff)
parent 119122 d29ffd3357285b4797bff60bc3fb69cf4e71dfe6 (diff)
child 119128 fffc4af51c86adc5e28d8fe7831cbad2906a50ec
child 119226 75d9c44ed26750c62aec5d68656077458d60bac1
child 119387 a7234e6f89f2fe0c28608c209916db45533e92fe
push id24192
push usermozilla@noorenberghe.ca
push dateFri, 18 Jan 2013 00:18:36 +0000
treeherdermozilla-central@b52c02f77cf5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone21.0a1
first release with
nightly linux32
b52c02f77cf5 / 21.0a1 / 20130118030915 / files
nightly linux64
b52c02f77cf5 / 21.0a1 / 20130118030915 / files
nightly mac
b52c02f77cf5 / 21.0a1 / 20130118030915 / files
nightly win32
b52c02f77cf5 / 21.0a1 / 20130118030915 / files
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
Merge fx-team with mozilla-central
content/html/content/src/nsDOMValidityState.cpp
content/html/content/src/nsDOMValidityState.h
content/html/content/src/nsHTMLObjectElement.cpp
content/svg/content/src/DOMSVGPoint.cpp
content/svg/content/src/nsSVGPatternElement.cpp
content/svg/content/src/nsSVGPatternElement.h
content/svg/content/src/nsSVGSymbolElement.cpp
content/svg/content/src/nsSVGUseElement.cpp
content/svg/content/src/nsSVGUseElement.h
dom/interfaces/svg/nsIDOMSVGAnimatedPathData.idl
dom/interfaces/svg/nsIDOMSVGLocatable.idl
dom/interfaces/svg/nsIDOMSVGTransformable.idl
layout/reftests/css-calc/background-linear-gradient-1-ref.html
layout/reftests/css-calc/background-linear-gradient-1.html
layout/reftests/css-calc/background-position-1-ref.html
layout/reftests/css-calc/background-position-1.html
layout/reftests/css-calc/background-size-1-ref.html
layout/reftests/css-calc/background-size-1.html
layout/reftests/css-calc/border-radius-1-ref.html
layout/reftests/css-calc/border-radius-1.html
layout/reftests/css-calc/height-block-1-ref.html
layout/reftests/css-calc/height-block-1.html
layout/reftests/css-calc/height-table-1-ref.html
layout/reftests/css-calc/height-table-1.html
layout/reftests/css-calc/margin-block-1-ref.html
layout/reftests/css-calc/margin-block-1.html
layout/reftests/css-calc/max-height-block-1-ref.html
layout/reftests/css-calc/max-height-block-1.html
layout/reftests/css-calc/max-width-block-1.html
layout/reftests/css-calc/max-width-block-intrinsic-1-ref.html
layout/reftests/css-calc/max-width-block-intrinsic-1.html
layout/reftests/css-calc/min-height-block-1.html
layout/reftests/css-calc/min-width-block-1.html
layout/reftests/css-calc/min-width-block-intrinsic-1-ref.html
layout/reftests/css-calc/min-width-block-intrinsic-1.html
layout/reftests/css-calc/offsets-absolute-bottom-1.html
layout/reftests/css-calc/offsets-absolute-left-1.html
layout/reftests/css-calc/offsets-absolute-right-1.html
layout/reftests/css-calc/offsets-absolute-top-1-ref.html
layout/reftests/css-calc/offsets-absolute-top-1.html
layout/reftests/css-calc/offsets-relative-bottom-1.html
layout/reftests/css-calc/offsets-relative-left-1-ref.html
layout/reftests/css-calc/offsets-relative-left-1.html
layout/reftests/css-calc/offsets-relative-right-1.html
layout/reftests/css-calc/offsets-relative-top-1-ref.html
layout/reftests/css-calc/offsets-relative-top-1.html
layout/reftests/css-calc/padding-block-1-ref.html
layout/reftests/css-calc/padding-block-1.html
layout/reftests/css-calc/text-indent-1-ref.html
layout/reftests/css-calc/text-indent-1.html
layout/reftests/css-calc/text-indent-intrinsic-1-ref.html
layout/reftests/css-calc/text-indent-intrinsic-1.html
layout/reftests/css-calc/transform-origin-1-ref.html
layout/reftests/css-calc/transform-origin-1.html
layout/reftests/css-calc/vertical-align-1-ref.html
layout/reftests/css-calc/vertical-align-1.html
layout/reftests/css-calc/width-block-1-ref.html
layout/reftests/css-calc/width-block-1.html
layout/reftests/css-calc/width-block-intrinsic-1-ref.html
layout/reftests/css-calc/width-block-intrinsic-1.html
layout/reftests/css-calc/width-table-auto-1-ref.html
layout/reftests/css-calc/width-table-auto-1.html
layout/reftests/css-calc/width-table-fixed-1-ref.html
layout/reftests/css-calc/width-table-fixed-1.html
mobile/android/base/tests/testClearPrivateData.java.in
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -53,18 +53,16 @@ NotificationController::~NotificationCon
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationCollector: AddRef/Release and cycle collection
 
 NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(NotificationController)
 NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(NotificationController)
 
-NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(NotificationController)
   if (tmp->mDocument)
     tmp->Shutdown();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(NotificationController)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHangingChildDocuments)
@@ -860,26 +858,18 @@ NotificationController::ContentInsertion
     }
 
     node = node->GetNextSibling();
   }
 
   return haveToUpdate;
 }
 
-NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController::ContentInsertion)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(NotificationController::ContentInsertion)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mContainer)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(NotificationController::ContentInsertion)
-  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mContainer");
-  cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mContainer.get()));
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_1(NotificationController::ContentInsertion,
+                           mContainer)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(NotificationController::ContentInsertion,
                                      AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(NotificationController::ContentInsertion,
                                        Release)
 
 void
 NotificationController::ContentInsertion::Process()
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -99,18 +99,16 @@ DocAccessible::~DocAccessible()
 {
   NS_ASSERTION(!mPresShell, "LastRelease was never called!?!");
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(DocAccessible)
-
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DocAccessible, Accessible)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentNode)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotificationController)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVirtualCursor)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildDocuments)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAccessibleCache)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
--- a/accessible/src/msaa/HyperTextAccessibleWrap.cpp
+++ b/accessible/src/msaa/HyperTextAccessibleWrap.cpp
@@ -4,19 +4,27 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "HyperTextAccessibleWrap.h"
 
 #include "nsEventShell.h"
 
+#include "mozilla/StaticPtr.h"
+
 using namespace mozilla;
 using namespace mozilla::a11y;
 
+StaticRefPtr<Accessible> HyperTextAccessibleWrap::sLastTextChangeAcc;
+StaticAutoPtr<nsString> HyperTextAccessibleWrap::sLastTextChangeString;
+uint32_t HyperTextAccessibleWrap::sLastTextChangeStart = 0;
+uint32_t HyperTextAccessibleWrap::sLastTextChangeEnd = 0;
+bool HyperTextAccessibleWrap::sLastTextChangeWasInsert = false;
+
 NS_IMPL_ISUPPORTS_INHERITED0(HyperTextAccessibleWrap,
                              HyperTextAccessible)
 
 STDMETHODIMP
 HyperTextAccessibleWrap::QueryInterface(REFIID aIID, void** aInstancePtr)
 {
   if (!aInstancePtr)
     return E_FAIL;
@@ -44,55 +52,50 @@ HyperTextAccessibleWrap::QueryInterface(
 nsresult
 HyperTextAccessibleWrap::HandleAccEvent(AccEvent* aEvent)
 {
   uint32_t eventType = aEvent->GetEventType();
 
   if (eventType == nsIAccessibleEvent::EVENT_TEXT_REMOVED ||
       eventType == nsIAccessibleEvent::EVENT_TEXT_INSERTED) {
     Accessible* accessible = aEvent->GetAccessible();
-    if (accessible) {
-      nsCOMPtr<nsIWinAccessNode> winAccessNode(do_QueryObject(accessible));
-      if (winAccessNode) {
-        void *instancePtr = NULL;
-        nsresult rv = winAccessNode->QueryNativeInterface(IID_IAccessibleText,
-                                                          &instancePtr);
-        if (NS_SUCCEEDED(rv)) {
-          NS_IF_RELEASE(gTextEvent);
-          NS_IF_ADDREF(gTextEvent = downcast_accEvent(aEvent));
+    if (accessible && accessible->IsHyperText()) {
+      sLastTextChangeAcc = accessible;
+      if (!sLastTextChangeString)
+        sLastTextChangeString = new nsString();
 
-          (static_cast<IUnknown*>(instancePtr))->Release();
-        }
-      }
+      AccTextChangeEvent* event = downcast_accEvent(aEvent);
+      event->GetModifiedText(*sLastTextChangeString);
+      sLastTextChangeStart = event->GetStartOffset();
+      sLastTextChangeEnd = sLastTextChangeStart + event->GetLength();
+      sLastTextChangeWasInsert = event->IsTextInserted();
     }
   }
 
   return HyperTextAccessible::HandleAccEvent(aEvent);
 }
 
 nsresult
 HyperTextAccessibleWrap::GetModifiedText(bool aGetInsertedText,
                                          nsAString& aText,
                                          uint32_t* aStartOffset,
                                          uint32_t* aEndOffset)
 {
   aText.Truncate();
   *aStartOffset = 0;
   *aEndOffset = 0;
 
-  if (!gTextEvent)
+  if (!sLastTextChangeAcc)
     return NS_OK;
 
-  bool isInserted = gTextEvent->IsTextInserted();
-  if (aGetInsertedText != isInserted)
+  if (aGetInsertedText != sLastTextChangeWasInsert)
     return NS_OK;
 
-  Accessible* targetAcc = gTextEvent->GetAccessible();
-  if (targetAcc != this)
+  if (sLastTextChangeAcc != this)
     return NS_OK;
 
-  *aStartOffset = gTextEvent->GetStartOffset();
-  *aEndOffset = *aStartOffset + gTextEvent->GetLength();
-  gTextEvent->GetModifiedText(aText);
+  *aStartOffset = sLastTextChangeStart;
+  *aEndOffset = sLastTextChangeEnd;
+  aText.Append(*sLastTextChangeString);
 
   return NS_OK;
 }
 
--- a/accessible/src/msaa/HyperTextAccessibleWrap.h
+++ b/accessible/src/msaa/HyperTextAccessibleWrap.h
@@ -8,16 +8,19 @@
 #ifndef mozilla_a11y_HyperTextAccessibleWrap_h__
 #define mozilla_a11y_HyperTextAccessibleWrap_h__
 
 #include "HyperTextAccessible.h"
 #include "ia2AccessibleEditableText.h"
 #include "ia2AccessibleHypertext.h"
 
 namespace mozilla {
+template<class T> class StaticAutoPtr;
+template<class T> class StaticRefPtr;
+
 namespace a11y {
 
 class HyperTextAccessibleWrap : public HyperTextAccessible,
                                 public ia2AccessibleHypertext,
                                 public ia2AccessibleEditableText
 {
 public:
   HyperTextAccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
@@ -31,14 +34,22 @@ public:
 
   // Accessible
   virtual nsresult HandleAccEvent(AccEvent* aEvent);
 
 protected:
   virtual nsresult GetModifiedText(bool aGetInsertedText, nsAString& aText,
                                    uint32_t *aStartOffset,
                                    uint32_t *aEndOffset);
+
+  static StaticRefPtr<Accessible> sLastTextChangeAcc;
+  static StaticAutoPtr<nsString> sLastTextChangeString;
+  static bool sLastTextChangeWasInsert;
+  static uint32_t sLastTextChangeStart;
+  static uint32_t sLastTextChangeEnd;
+
+  friend void PlatformInit();
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/src/msaa/Platform.cpp
+++ b/accessible/src/msaa/Platform.cpp
@@ -3,31 +3,34 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Platform.h"
 
 #include "AccEvent.h"
 #include "Compatibility.h"
-#include "nsAccessNodeWrap.h"
+#include "HyperTextAccessibleWrap.h"
 #include "nsWinUtils.h"
 
+#include "mozilla/ClearOnShutdown.h"
+
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 void
 a11y::PlatformInit()
 {
   Compatibility::Init();
 
   nsWinUtils::MaybeStartWindowEmulation();
+  ClearOnShutdown(&HyperTextAccessibleWrap::sLastTextChangeAcc);
+  ClearOnShutdown(&HyperTextAccessibleWrap::sLastTextChangeString);
 }
 
 void
 a11y::PlatformShutdown()
 {
-  NS_IF_RELEASE(nsAccessNodeWrap::gTextEvent);
   ::DestroyCaret();
 
   nsWinUtils::ShutdownWindowEmulation();
 }
 
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -22,18 +22,16 @@
 #include "nsIDOMHTMLElement.h"
 #include "nsINameSpaceManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsIServiceManager.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
-AccTextChangeEvent* nsAccessNodeWrap::gTextEvent = nullptr;
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNodeWrap
 ////////////////////////////////////////////////////////////////////////////////
 
 nsAccessNodeWrap::
   nsAccessNodeWrap(nsIContent* aContent, DocAccessible* aDoc) :
   nsAccessNode(aContent, aDoc)
 {
--- a/accessible/src/msaa/nsAccessNodeWrap.h
+++ b/accessible/src/msaa/nsAccessNodeWrap.h
@@ -42,18 +42,16 @@
   } MOZ_SEH_EXCEPT(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(),       \
                                                           GetExceptionInformation())) \
   { }                                                                                 \
   return E_FAIL;
 
 namespace mozilla {
 namespace a11y {
 
-class AccTextChangeEvent;
-
 #ifdef __GNUC__
 // Inheriting from both XPCOM and MSCOM interfaces causes a lot of warnings
 // about virtual functions being hidden by each other. This is done by
 // design, so silence the warning.
 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
 #endif
 
 class nsAccessNodeWrap : public nsAccessNode,
@@ -78,25 +76,16 @@ public: // construction, destruction
                                                  void** aInstancePtr);
 
     static int FilterA11yExceptions(unsigned int aCode, EXCEPTION_POINTERS *aExceptionInfo);
 
   static LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg,
                                      WPARAM WParam, LPARAM lParam);
 
   static nsRefPtrHashtable<nsPtrHashKey<void>, DocAccessible> sHWNDCache;
-
-protected:
-
-  /**
-   * It is used in HyperTextAccessibleWrap for IA2::newText/oldText
-   * implementation.
-   */
-  static AccTextChangeEvent* gTextEvent;
-  friend void PlatformShutdown();
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 /**
  * Converts nsresult to HRESULT.
  */
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -21,16 +21,17 @@ builtin(include, build/autoconf/gcc-pr39
 builtin(include, build/autoconf/llvm-pr8927.m4)dnl
 builtin(include, build/autoconf/frameptr.m4)dnl
 builtin(include, build/autoconf/compiler-opts.m4)dnl
 builtin(include, build/autoconf/expandlibs.m4)dnl
 builtin(include, build/autoconf/arch.m4)dnl
 builtin(include, build/autoconf/android.m4)dnl
 builtin(include, build/autoconf/zlib.m4)dnl
 builtin(include, build/autoconf/linux.m4)dnl
+builtin(include, build/autoconf/python-virtualenv.m4)dnl
 
 MOZ_PROG_CHECKMSYS()
 
 # Read the user's .mozconfig script.  We can't do this in
 # configure.in: autoconf puts the argument parsing code above anything
 # expanded from configure.in, and we need to get the configure options
 # from .mozconfig in place before that argument parsing code.
 MOZ_READ_MOZCONFIG(.)
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -734,17 +734,18 @@ var AlertsHelper = {
     function send(appName, appIcon) {
       shell.sendChromeEvent({
         type: "desktop-notification",
         id: uid,
         icon: imageUrl,
         title: title,
         text: text,
         appName: appName,
-        appIcon: appIcon
+        appIcon: appIcon,
+        manifestURL: manifestUrl
       });
     }
 
     if (!manifestUrl || !manifestUrl.length) {
       send(null, null);
     }
 
     // If we have a manifest URL, get the icon and title from the manifest
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -5,17 +5,17 @@
 MOZ_APP_BASENAME=B2G
 MOZ_APP_VENDOR=Mozilla
 
 MOZ_APP_VERSION=21.0a1
 MOZ_APP_UA_NAME=Firefox
 
 MOZ_UA_OS_AGNOSTIC=1
 
-MOZ_B2G_VERSION=1.0.0-prerelease
+MOZ_B2G_VERSION=1.0.0.0-prerelease
 MOZ_B2G_OS_NAME=Boot2Gecko
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=
 MOZ_SERVICES_COMMON=1
new file mode 100644
--- /dev/null
+++ b/b2g/test/b2g-unittest-requirements.txt
@@ -0,0 +1,2 @@
+mozprocess==0.8
+mozdevice==0.18
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -964,18 +964,21 @@ var SocialToolbar = {
           dynamicResizer.start(panel, notificationFrame);
           setTimeout(function() {
             dispatchPanelEvent("socialFrameShow");
           }, 0);
         }, true);
       }
     });
 
-    let toolbarButtonIcon = document.getAnonymousElementByAttribute(aToolbarButton, "class", "toolbarbutton-icon");
-    panel.openPopup(toolbarButtonIcon, "bottomcenter topright", 0, 0, false, false);
+    let navBar = document.getElementById("nav-bar");
+    let anchor = navBar.getAttribute("mode") == "text" ?
+                   document.getAnonymousElementByAttribute(aToolbarButton, "class", "toolbarbutton-text") :
+                   document.getAnonymousElementByAttribute(aToolbarButton, "class", "toolbarbutton-icon");
+    panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
   },
 
   setPanelErrorMessage: function SocialToolbar_setPanelErrorMessage(aNotificationFrame) {
     if (!aNotificationFrame)
       return;
 
     let src = aNotificationFrame.getAttribute("src");
     aNotificationFrame.removeAttribute("src");
--- a/browser/components/downloads/content/allDownloadsViewOverlay.js
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.js
@@ -36,16 +36,32 @@ const DOWNLOAD_VIEW_SUPPORTED_COMMANDS =
  ["cmd_delete", "cmd_copy", "cmd_paste", "cmd_selectAll",
   "downloadsCmd_pauseResume", "downloadsCmd_cancel",
   "downloadsCmd_open", "downloadsCmd_show", "downloadsCmd_retry",
   "downloadsCmd_openReferrer", "downloadsCmd_clearDownloads"];
 
 const NOT_AVAILABLE = Number.MAX_VALUE;
 
 /**
+ * Download a URL.
+ *
+ * @param aURL
+ *        the url to download (nsIURI object)
+ * @param [optional] aFileName
+ *        the destination file name
+ */
+function DownloadURL(aURL, aFileName) {
+  // For private browsing, try to get document out of the most recent browser
+  // window, or provide our own if there's no browser window.
+  let browserWin = RecentWindow.getMostRecentBrowserWindow();
+  let initiatingDoc = browserWin ? browserWin.document : document;
+  saveURL(aURL, aFileName, null, true, true, undefined, initiatingDoc);
+}
+
+/**
  * A download element shell is responsible for handling the commands and the
  * displayed data for a single download view element. The download element
  * could represent either a past download (for which we get data from places)  or
  * a "session" download (using a data-item object. See DownloadsCommon.jsm), or both.
  *
  * Once initialized with either a data item or a places node, the created richlistitem
  * can be accessed through the |element| getter, and can then be inserted/removed from
  * a richlistbox.
@@ -155,17 +171,17 @@ DownloadElementShell.prototype = {
 
   get _downloadURIObj() {
     if (!("__downloadURIObj" in this))
       this.__downloadURIObj = NetUtil.newURI(this.downloadURI);
     return this.__downloadURIObj;
   },
 
   _getIcon: function DES__getIcon() {
-    let metaData = this._getDownloadMetaData();
+    let metaData = this.getDownloadMetaData();
     if ("filePath" in metaData)
       return "moz-icon://" + metaData.filePath + "?size=32";
 
     if (this._placesNode) {
       // Try to extract an extension from the uri.
       let ext = this._downloadURIObj.QueryInterface(Ci.nsIURL).fileExtension;
       if (ext)
         return "moz-icon://." + ext + "?size=32";
@@ -208,17 +224,17 @@ DownloadElementShell.prototype = {
   },
 
   _fetchTargetFileInfo: function DES__fetchTargetFileInfo(aUpdateMetaDataAndStatusUI = false) {
     if (this._targetFileInfoFetched)
       throw new Error("_fetchTargetFileInfo should not be called if the information was already fetched");
     if (!this.active)
       throw new Error("Trying to _fetchTargetFileInfo on an inactive download shell");
 
-    let path = this._getDownloadMetaData().filePath;
+    let path = this.getDownloadMetaData().filePath;
 
     // In previous version, the target file annotations were not set,
     // so we cannot tell where is the file.
     if (path === undefined) {
       this._targetFileInfoFetched = true;
       this._targetFileExists = false;
       if (aUpdateMetaDataAndStatusUI) {
         this._metaData = null;
@@ -280,34 +296,34 @@ DownloadElementShell.prototype = {
    *
    * - state - any download state defined in nsIDownloadManager.  If this field
    *   is not set, the download state is unknown.
    * - endTime: the end time of the download.
    * - filePath: the downloaded file path on the file system, when it
    *   was downloaded.  The file may not exist.  This is set for session
    *   downloads that have a local file set, and for history downloads done
    *   after the landing of bug 591289.
+   * - fileName: the downloaded file name on the file system. Set if filePath
+   *   is set.
    * - displayName: the user-facing label for the download.  This is always
    *   set.  If available, it's set to the downloaded file name.  If not,
    *   the places title for the download uri is used it's set.  As a last
    *   resort, we fallback to the download uri.
    * - fileSize (only set for downloads which completed succesfully):
    *   the downloaded file size.  For downloads done after the landing of
    *   bug 826991, this value is "static" - that is, it does not necessarily
    *   mean that the file is in place and has this size.
    */
-  _getDownloadMetaData: function DES__getDownloadMetaData() {
-    if (!this.active)
-      throw new Error("_getDownloadMetaData called for an inactive item.");
-
+  getDownloadMetaData: function DES_getDownloadMetaData() {
     if (!this._metaData) {
       if (this._dataItem) {
         this._metaData = {
           state:       this._dataItem.state,
           endTime:     this._dataItem.endTime,
+          fileName:    this._dataItem.target,
           displayName: this._dataItem.target
         };
         if (this._dataItem.done)
           this._metaData.fileSize = this._dataItem.maxBytes;
         if (this._dataItem.localFile)
           this._metaData.filePath = this._dataItem.localFile.path;
       }
       else {
@@ -323,18 +339,19 @@ DownloadElementShell.prototype = {
           }
 
           // This is actually the start-time, but it's the best we can get.
           this._metaData.endTime = this._placesNode.time / 1000;
         }
 
         try {
           let targetFileURI = this._getAnnotation(DESTINATION_FILE_URI_ANNO);
-          [this._metaData.filePath, this._metaData.displayName] =
+          [this._metaData.filePath, this._metaData.fileName] =
             this._extractFilePathAndNameFromFileURI(targetFileURI);
+          this._metaData.displayName = this._metaData.fileName;
         }
         catch(ex) {
           this._metaData.displayName = this._placesNode.title || this.downloadURI;
         }
       }
     }
     return this._metaData;
   },
@@ -368,17 +385,17 @@ DownloadElementShell.prototype = {
         return s.stateScanning;
       }
 
       throw new Error("_getStatusText called with a bogus download state");
     }
 
     // This is a not-in-progress or history download.
     let stateLabel = "";
-    let state = this._getDownloadMetaData().state;
+    let state = this.getDownloadMetaData().state;
     switch (state) {
       case nsIDM.DOWNLOAD_FAILED:
         stateLabel = s.stateFailed;
         break;
       case nsIDM.DOWNLOAD_CANCELED:
         stateLabel = s.stateCanceled;
         break;
       case nsIDM.DOWNLOAD_BLOCKED_PARENTAL:
@@ -387,17 +404,17 @@ DownloadElementShell.prototype = {
       case nsIDM.DOWNLOAD_BLOCKED_POLICY:
         stateLabel = s.stateBlockedPolicy;
         break;
       case nsIDM.DOWNLOAD_DIRTY:
         stateLabel = s.stateDirty;
         break;
       case nsIDM.DOWNLOAD_FINISHED:{
         // For completed downloads, show the file size (e.g. "1.5 MB")
-        let metaData = this._getDownloadMetaData();
+        let metaData = this.getDownloadMetaData();
         if ("fileSize" in metaData) {
           let [size, unit] = DownloadUtils.convertByteUnits(metaData.fileSize);
           stateLabel = s.sizeWithUnits(size, unit);
           break;
         }
         // Fallback to default unknown state.
       }
       default:
@@ -405,17 +422,17 @@ DownloadElementShell.prototype = {
         break;
     }
 
     // TODO (bug 829201): history downloads should get the referrer from Places.
     let referrer = this._dataItem && this._dataItem.referrer ||
                    this.downloadURI;
     let [displayHost, fullHost] = DownloadUtils.getURIHost(referrer);
 
-    let date = new Date(this._getDownloadMetaData().endTime);
+    let date = new Date(this.getDownloadMetaData().endTime);
     let [displayDate, fullDate] = DownloadUtils.getReadableDates(date);
 
     // We use the same XUL label to display the state, the host name, and the
     // end time.
     let firstPart = s.statusSeparator(stateLabel, displayHost);
     return s.statusSeparator(firstPart, displayDate);
   },
 
@@ -431,17 +448,17 @@ DownloadElementShell.prototype = {
 
   // Updates the download state attribute (and by that hide/unhide the
   // appropriate buttons and context menu items), the status text label,
   // and the progress meter.
   _updateDownloadStatusUI: function  DES__updateDownloadStatusUI() {
     if (!this.active)
       throw new Error("_updateDownloadStatusUI called for an inactive item.");
 
-    let state = this._getDownloadMetaData().state;
+    let state = this.getDownloadMetaData().state;
     if (state !== undefined)
       this._element.setAttribute("state", state);
 
     this._element.setAttribute("status", this._getStatusText());
 
     // For past-downloads, we're done. For session-downloads, we may also need
     // to update the progress-meter.
     if (!this._dataItem)
@@ -469,105 +486,108 @@ DownloadElementShell.prototype = {
     if (this._progressElement) {
       let event = document.createEvent("Events");
       event.initEvent("ValueChange", true, true);
       this._progressElement.dispatchEvent(event);
     }
   },
 
   _updateDisplayNameAndIcon: function DES__updateDisplayNameAndIcon() {
-    let metaData = this._getDownloadMetaData();
+    let metaData = this.getDownloadMetaData();
     this._element.setAttribute("displayName", metaData.displayName);
     this._element.setAttribute("image", this._getIcon());
   },
 
   _updateUI: function DES__updateUI() {
     if (!this.active)
       throw new Error("Trying to _updateUI on an inactive download shell");
 
     this._metaData = null;
     this._targetFileInfoFetched = false;
 
     this._updateDisplayNameAndIcon();
 
     // For history downloads done in past releases, the downloads/metaData
     // annotation is not set, and therefore we cannot tell the download
     // state without the target file information.
-    if (this._dataItem || this._getDownloadMetaData().state !== undefined)
+    if (this._dataItem || this.getDownloadMetaData().state !== undefined)
       this._updateDownloadStatusUI();
     else
       this._fetchTargetFileInfo(true);
   },
 
   placesNodeIconChanged: function DES_placesNodeIconChanged() {
     if (!this._dataItem)
       this._element.setAttribute("image", this._getIcon());
   },
 
   placesNodeTitleChanged: function DES_placesNodeTitleChanged() {
     // If there's a file path, we use the leaf name for the title.
-    if (!this._dataItem && this.active && !this._getDownloadMetaData().filePath) {
+    if (!this._dataItem && this.active && !this.getDownloadMetaData().filePath) {
       this._metaData = null;
       this._updateDisplayNameAndIcon();
     }
   },
 
   placesNodeAnnotationChanged: function DES_placesNodeAnnotationChanged(aAnnoName) {
     this._annotations.delete(aAnnoName);
     if (!this._dataItem && this.active) {
       if (aAnnoName == DOWNLOAD_META_DATA_ANNO) {
-        let metaData = this._getDownloadMetaData();
+        let metaData = this.getDownloadMetaData();
         let annotatedMetaData = this._getAnnotatedMetaData();
         metaData.endTme = annotatedMetaData.endTime;
         if ("fileSize" in annotatedMetaData)
           metaData.fileSize = annotatedMetaData.fileSize;
         else
           delete metaData.fileSize;
 
         if (metaData.state != annotatedMetaData.state) {
           metaData.state = annotatedMetaData.state;
           if (this._element.selected)
             goUpdateDownloadCommands();
         }
 
         this._updateDownloadStatusUI();
       }
       else if (aAnnoName == DESTINATION_FILE_URI_ANNO) {
-        let metaData = this._getDownloadMetaData();
+        let metaData = this.getDownloadMetaData();
         let targetFileURI = this._getAnnotation(DESTINATION_FILE_URI_ANNO);
-        [metaData.filePath, metaData.displayName] =
+        [metaData.filePath, metaData.fileName] =
             this._extractFilePathAndNameFromFileURI(targetFileURI);
+        metaData.displayName = metaData.fileName;
         this._updateDisplayNameAndIcon();
 
         if (this._targetFileInfoFetched) {
           // This will also update the download commands if necessary.
           this._targetFileInfoFetched = false;
           this._fetchTargetFileInfo();
         }
       }
     }
   },
 
   /* DownloadView */
   onStateChange: function DES_onStateChange(aOldState) {
-    let metaData = this._getDownloadMetaData();
+    let metaData = this.getDownloadMetaData();
     metaData.state = this.dataItem.state;
     if (aOldState != nsIDM.DOWNLOAD_FINISHED && aOldState != metaData.state) {
       // See comment in DVI_onStateChange in downloads.js (the panel-view)
       this._element.setAttribute("image", this._getIcon() + "&state=normal");
       metaData.fileSize = this._dataItem.maxBytes;
       if (this._targetFileInfoFetched) {
         this._targetFileInfoFetched = false;
         this._fetchTargetFileInfo();
       }
     }
 
     this._updateDownloadStatusUI();
     if (this._element.selected)
       goUpdateDownloadCommands();
+    else
+      goUpdateCommand("downloadsCmd_clearDownloads");
   },
 
   /* DownloadView */
   onProgressChange: function DES_onProgressChange() {
     this._updateDownloadStatusUI();
   },
 
   /* nsIController */
@@ -583,30 +603,30 @@ DownloadElementShell.prototype = {
         if (this._dataItem && !this._dataItem.openable)
           return false;
 
         if (this._targetFileInfoFetched)
           return this._targetFileExists;
 
         // If the target file information is not yet fetched,
         // temporarily assume that the file is in place.
-        return this._getDownloadMetaData().state == nsIDM.DOWNLOAD_FINISHED;
+        return this.getDownloadMetaData().state == nsIDM.DOWNLOAD_FINISHED;
       }
       case "downloadsCmd_show": {
         // TODO: Bug 827010 - Handle part-file asynchronously.
         if (this._dataItem &&
             this._dataItem.partFile && this._dataItem.partFile.exists())
           return true;
 
         if (this._targetFileInfoFetched)
           return this._targetFileExists;
 
         // If the target file information is not yet fetched,
         // temporarily assume that the file is in place.
-        return this._getDownloadMetaData().state == nsIDM.DOWNLOAD_FINISHED;
+        return this.getDownloadMetaData().state == nsIDM.DOWNLOAD_FINISHED;
       }
       case "downloadsCmd_pauseResume":
         return this._dataItem && this._dataItem.inProgress && this._dataItem.resumable;
       case "downloadsCmd_retry":
         // An history download can always be retried.
         return !this._dataItem || this._dataItem.canRetry;
       case "downloadsCmd_openReferrer":
         return this._dataItem && !!this._dataItem.referrer;
@@ -620,42 +640,36 @@ DownloadElementShell.prototype = {
     }
     return false;
   },
 
   _retryAsHistoryDownload: function DES__retryAsHistoryDownload() {
     // In future we may try to download into the same original target uri, when
     // we have it.  Though that requires verifying the path is still valid and
     // may surprise the user if he wants to be requested every time.
-
-    // For private browsing, try to get document out of the most recent browser
-    // window, or provide our own if there's no browser window.
-    let browserWin = RecentWindow.getMostRecentBrowserWindow();
-    let initiatingDoc = browserWin ? browserWin.document : document;
-    saveURL(this.downloadURI, this._getDownloadMetaData().displayName, null, true, true, undefined,
-            initiatingDoc);
+    DownloadURL(this.downloadURI, this.getDownloadMetaData().fileName);
   },
 
   /* nsIController */
   doCommand: function DES_doCommand(aCommand) {
     switch (aCommand) {
       case "downloadsCmd_open": {
         let file = this._dataItem ?
           this.dataItem.localFile :
-          new FileUtils.File(this._getDownloadMetaData().filePath);
+          new FileUtils.File(this.getDownloadMetaData().filePath);
 
         DownloadsCommon.openDownloadedFile(file, null, window);
         break;
       }
       case "downloadsCmd_show": {
         if (this._dataItem) {
           this._dataItem.showLocalFile();
         }
         else {
-          let file = new FileUtils.File(this._getDownloadMetaData().filePath);
+          let file = new FileUtils.File(this.getDownloadMetaData().filePath);
           DownloadsCommon.showDownloadedFile(file);
         }
         break;
       }
       case "downloadsCmd_openReferrer": {
         openURL(this._dataItem.referrer);
         break;
       }
@@ -686,18 +700,18 @@ DownloadElementShell.prototype = {
 
   // Returns whether or not the download handled by this shell should
   // show up in the search results for the given term.  Both the display
   // name for the download and the url are searched.
   matchesSearchTerm: function DES_matchesSearchTerm(aTerm) {
     if (!aTerm)
       return true;
     aTerm = aTerm.toLowerCase();
-    return this._getDownloadMetaData().displayName.toLowerCase().indexOf(aTerm) != -1 ||
-           this.downloadURI.toLowerCase().indexOf(aTerm) != -1;
+    return this.getDownloadMetaData().displayName.toLowerCase().contains(aTerm) ||
+           this.downloadURI.toLowerCase().contains(aTerm);
   },
 
   // Handles return kepress on the element (the keypress listener is
   // set in the DownloadsPlacesView object).
   doDefaultCommand: function DES_doDefaultCommand() {
     function getDefaultCommandForState(aState) {
       switch (aState) {
         case nsIDM.DOWNLOAD_FINISHED:
@@ -715,17 +729,17 @@ DownloadElementShell.prototype = {
           return "downloadsCmd_show";
         case nsIDM.DOWNLOAD_BLOCKED_PARENTAL:
         case nsIDM.DOWNLOAD_DIRTY:
         case nsIDM.DOWNLOAD_BLOCKED_POLICY:
           return "downloadsCmd_openReferrer";
       }
       return "";
     }
-    let command = getDefaultCommandForState(this._getDownloadMetaData().state);
+    let command = getDefaultCommandForState(this.getDownloadMetaData().state);
     if (this.isCommandEnabled(command))
       this.doCommand(command);
   },
 
   /**
    * At the first time an item is selected, we don't yet have
    * the target file information.  Thus the call to goUpdateDownloadCommands
    * in DPV_onSelect would result in best-guess enabled/disabled result.
@@ -749,17 +763,17 @@ DownloadElementShell.prototype = {
  * A richlistitem in this view can represent either a past download or a session
  * download, or both. Session downloads are shown first in the view, and as long
  * as they exist they "collapses" their history "counterpart" (So we don't show two
  * items for every download).
  */
 function DownloadsPlacesView(aRichListBox, aActive = true) {
   this._richlistbox = aRichListBox;
   this._richlistbox._placesView = this;
-  this._richlistbox.controllers.appendController(this);
+  window.controllers.insertControllerAt(0, this);
 
   // Map download URLs to download element shells regardless of their type
   this._downloadElementsShellsForURI = new Map();
 
   // Map download data items to their element shells.
   this._viewItemsForDataItems = new WeakMap();
 
   // Points to the last session download element. We keep track of this
@@ -773,17 +787,17 @@ function DownloadsPlacesView(aRichListBo
   // Register as a downloads view. The places data will be initialized by
   // the places setter.
   this._initiallySelectedElement = null;
   let downloadsData = DownloadsCommon.getData(window.opener || window);
   downloadsData.addView(this);
 
   // Make sure to unregister the view if the window is closed.
   window.addEventListener("unload", function() {
-    this._richlistbox.controllers.removeController(this);
+    window.controllers.removeController(this);
     downloadsData.removeView(this);
     this.result = null;
   }.bind(this), true);
   // Resizing the window may change items visibility.
   window.addEventListener("resize", function() {
     this._ensureVisibleElementsAreActive();
   }.bind(this), true);
 }
@@ -954,31 +968,34 @@ DownloadsPlacesView.prototype = {
       if (this.searchTerm) {
         newOrUpdatedShell.element.hidden =
           !newOrUpdatedShell.element._shell.matchesSearchTerm(this.searchTerm);
       }
     }
 
     // If aDocumentFragment is defined this is a batch change, so it's up to
     // the caller to append the fragment and activate the visible shells.
-    if (!aDocumentFragment)
+    if (!aDocumentFragment) {
       this._ensureVisibleElementsAreActive();
+      goUpdateCommand("downloadsCmd_clearDownloads");
+    }
   },
 
   _removeElement: function DPV__removeElement(aElement) {
     // If the element was selected exclusively, select its next
     // sibling first, if any.
     if (aElement.nextSibling &&
         this._richlistbox.selectedItems &&
         this._richlistbox.selectedItems.length > 0 &&
         this._richlistbox.selectedItems[0] == aElement) {
       this._richlistbox.selectItem(aElement.nextSibling);
     }
     this._richlistbox.removeChild(aElement);
     this._ensureVisibleElementsAreActive();
+    goUpdateCommand("downloadsCmd_clearDownloads");
   },
 
   _removeHistoryDownloadFromView:
   function DPV__removeHistoryDownloadFromView(aPlacesNode) {
     let downloadURI = aPlacesNode.uri;
     let shellsForURI = this._downloadElementsShellsForURI.get(downloadURI, null);
     if (shellsForURI) {
       for (let shell of shellsForURI) {
@@ -1167,28 +1184,27 @@ DownloadsPlacesView.prototype = {
       }
       catch(ex) {
         Cu.reportError(ex);
       }
     }
 
     this._appendDownloadsFragment(elementsToAppendFragment);
     this._ensureVisibleElementsAreActive();
+    goUpdateDownloadCommands();
   },
 
   _appendDownloadsFragment: function DPV__appendDownloadsFragment(aDOMFragment) {
     // Workaround multiple reflows hang by removing the richlistbox
     // and adding it back when we're done.
     let parentNode = this._richlistbox.parentNode;
     let nextSibling = this._richlistbox.nextSibling;
-    this._richlistbox.controllers.removeController(this);
     parentNode.removeChild(this._richlistbox);
     this._richlistbox.appendChild(aDOMFragment);
     parentNode.insertBefore(this._richlistbox, nextSibling);
-    this._richlistbox.controllers.appendController(this);
   },
 
   nodeInserted: function DPV_nodeInserted(aParent, aPlacesNode) {
     this._addDownloadData(null, aPlacesNode);
   },
 
   nodeRemoved: function DPV_nodeRemoved(aParent, aPlacesNode, aOldIndex) {
     this._removeHistoryDownloadFromView(aPlacesNode);
@@ -1281,37 +1297,63 @@ DownloadsPlacesView.prototype = {
 
   onDataItemRemoved: function DPV_onDataItemRemoved(aDataItem) {
     this._removeSessionDownloadFromView(aDataItem);
   },
 
   getViewItem: function(aDataItem)
     this._viewItemsForDataItems.get(aDataItem, null),
 
-  supportsCommand: function(aCommand)
-    DOWNLOAD_VIEW_SUPPORTED_COMMANDS.indexOf(aCommand) != -1,
+  supportsCommand: function DPV_supportsCommand(aCommand) {
+    if (DOWNLOAD_VIEW_SUPPORTED_COMMANDS.indexOf(aCommand) != -1) {
+      // The clear-downloads command may be performed by the toolbar-button,
+      // which can be focused on OS X.  Thus enable this command even if the
+      // richlistbox is not focused.
+      // For other commands, be prudent and disable them unless the richlistview
+      // is focused. It's important to make the decision here rather than in
+      // isCommandEnabled.  Otherwise our controller may "steal" commands from
+      // other controls in the window (see goUpdateCommand &
+      // getControllerForCommand).
+      if (document.activeElement == this._richlistbox ||
+          aCommand == "downloadsCmd_clearDownloads") {
+        return true;
+      }
+    }
+    return false;
+  },
 
   isCommandEnabled: function DPV_isCommandEnabled(aCommand) {
-    let selectedElements = this._richlistbox.selectedItems;
     switch (aCommand) {
       case "cmd_copy":
-        return selectedElements && selectedElements.length > 0;
+        return this._richlistbox.selectedItems.length > 0;
       case "cmd_selectAll":
         return true;
       case "cmd_paste":
         return this._canDownloadClipboardURL();
       case "downloadsCmd_clearDownloads":
-        return !!this._richlistbox.firstChild;
+        return this._canClearDownloads();
       default:
-        return Array.every(selectedElements, function(element) {
+        return Array.every(this._richlistbox.selectedItems, function(element) {
           return element._shell.isCommandEnabled(aCommand);
         });
     }
   },
 
+  _canClearDownloads: function DPV__canClearDownloads() {
+    // Downloads can be cleared if there's at least one removeable download in
+    // the list (either a history download or a completed session download).
+    // Because history downloads are always removable and are listed after the
+    // session downloads, check from bottom to top.
+    for (let elt = this._richlistbox.lastChild; elt; elt = elt.previousSibling) {
+      if (elt._shell.placesNode || !elt._shell.dataItem.inProgress)
+        return true;
+    }
+    return false;
+  },
+
   _copySelectedDownloadsToClipboard:
   function DPV__copySelectedDownloadsToClipboard() {
     let selectedElements = this._richlistbox.selectedItems;
     let urls = [e._shell.downloadURI for each (e in selectedElements)];
 
     Cc["@mozilla.org/widget/clipboardhelper;1"].
     getService(Ci.nsIClipboardHelper).copyString(urls.join("\n"), document);
   },
@@ -1342,17 +1384,17 @@ DownloadsPlacesView.prototype = {
 
   _canDownloadClipboardURL: function DPV__canDownloadClipboardURL() {
     let [url, name] = this._getURLFromClipboardData();
     return url != "";
   },
 
   _downloadURLFromClipboard: function DPV__downloadURLFromClipboard() {
     let [url, name] = this._getURLFromClipboardData();
-    saveURL(url, name || url, null, true, true, undefined, document);
+    DownloadURL(url, name);
   },
 
   doCommand: function DPV_doCommand(aCommand) {
     switch (aCommand) {
       case "cmd_copy":
         this._copySelectedDownloadsToClipboard();
         break;
       case "cmd_selectAll":
@@ -1367,16 +1409,19 @@ DownloadsPlacesView.prototype = {
         } else {
           Services.downloads.cleanUp();
         }
         if (this.result) {
           Cc["@mozilla.org/browser/download-history;1"]
             .getService(Ci.nsIDownloadHistory)
             .removeAllDownloads();
         }
+        // There may be no selection or focus change as a result
+        // of these change, and we want the command updated immediately.
+        goUpdateCommand("downloadsCmd_clearDownloads");
         break;
       default: {
         let selectedElements = this._richlistbox.selectedItems;
         for (let element of selectedElements) {
           element._shell.doCommand(aCommand);
         }
       }
     }
@@ -1387,17 +1432,17 @@ DownloadsPlacesView.prototype = {
   onContextMenu: function DPV_onContextMenu(aEvent)
   {
     let element = this._richlistbox.selectedItem;
     if (!element || !element._shell)
       return false;
 
     // Set the state attribute so that only the appropriate items are displayed.
     let contextMenu = document.getElementById("downloadsContextMenu");
-    let state = element._shell._getDownloadMetaData().state;
+    let state = element._shell.getDownloadMetaData().state;
     if (state !== undefined)
       contextMenu.setAttribute("state", state);
     else
       contextMenu.removeAttribute("state");
 
     return true;
   },
 
@@ -1442,16 +1487,61 @@ DownloadsPlacesView.prototype = {
   onSelect: function DPV_onSelect() {
     goUpdateDownloadCommands();
 
     let selectedElements = this._richlistbox.selectedItems;
     for (let elt of selectedElements) {
       if (elt._shell)
         elt._shell.onSelect();
     }
+  },
+
+  onDragStart: function DPV_onDragStart(aEvent) {
+    // TODO Bug 831358: Support d&d for multiple selection.
+    // For now, we just drag the first element.
+    let selectedItem = this._richlistbox.selectedItem;
+    if (!selectedItem)
+      return;
+
+    let metaData = selectedItem._shell.getDownloadMetaData();
+    if (!("filePath" in metaData))
+      return;
+    let file = new FileUtils.File(metaData.filePath);
+    if (!file.exists())
+      return;
+
+    let dt = aEvent.dataTransfer;
+    dt.mozSetDataAt("application/x-moz-file", file, 0);
+    let url = Services.io.newFileURI(file).spec;
+    dt.setData("text/uri-list", url);
+    dt.setData("text/plain", url);
+    dt.effectAllowed = "copyMove";
+    dt.addElement(selectedItem);
+  },
+
+  onDragOver: function DPV_onDragOver(aEvent) {
+    let types = aEvent.dataTransfer.types;
+    if (types.contains("text/uri-list") ||
+        types.contains("text/x-moz-url") ||
+        types.contains("text/plain")) {
+      aEvent.preventDefault();
+    }
+  },
+
+  onDrop: function DPV_onDrop(aEvent) {
+    let dt = aEvent.dataTransfer;
+    // If dragged item is from our source, do not try to
+    // redownload already downloaded file.
+    if (dt.mozGetDataAt("application/x-moz-file", 0))
+      return;
+
+    let name = { };
+    let url = Services.droppedLinkHandler.dropLink(aEvent, name);
+    if (url)
+      DownloadURL(url, name.value);
   }
 };
 
 for (let methodName of ["load", "applyFilter", "selectNode", "selectItems"]) {
   DownloadsPlacesView.prototype[methodName] = function() {
     throw new Error("|" + methodName + "| is not implemented by the downloads view.");
   }
 }
--- a/browser/components/downloads/content/allDownloadsViewOverlay.xul
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.xul
@@ -41,16 +41,19 @@
 
   <richlistbox flex="1"
                seltype="multiple"
                id="downloadsRichListBox" context="downloadsContextMenu"
                onscroll="return this._placesView.onScroll();"
                onkeypress="return this._placesView.onKeyPress(event);"
                ondblclick="return this._placesView.onDoubleClick(event);"
                oncontextmenu="return this._placesView.onContextMenu(event);"
+               ondragstart="this._placesView.onDragStart(event);"
+               ondragover="this._placesView.onDragOver(event);"
+               ondrop="this._placesView.onDrop(event);"
                onfocus="goUpdateDownloadCommands();"
                onselect="this._placesView.onSelect();"
                onblur="goUpdateDownloadCommands();"/>
 
   <commandset id="downloadCommands"
               commandupdater="true"
               events="focus,select,contextmenu"
               oncommandupdate="goUpdateDownloadCommands();">
--- a/browser/components/downloads/src/DownloadsCommon.jsm
+++ b/browser/components/downloads/src/DownloadsCommon.jsm
@@ -731,21 +731,21 @@ DownloadsDataCtor.prototype = {
    * Removes the data item with the specified identifier.
    *
    * This method can be called at most once per download identifier.
    */
   _removeDataItem: function DD_removeDataItem(aDownloadId)
   {
     if (aDownloadId in this.dataItems) {
       let dataItem = this.dataItems[aDownloadId];
+      this.dataItems[aDownloadId] = null;
       this._views.forEach(
         function (view) view.onDataItemRemoved(dataItem)
       );
     }
-    this.dataItems[aDownloadId] = null;
   },
 
   //////////////////////////////////////////////////////////////////////////////
   //// Persistent data loading
 
   /**
    * Represents an executing statement, allowing its cancellation.
    */
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -507,17 +507,17 @@ nsBrowserContentHandler.prototype = {
     }
     if (cmdLine.handleFlag("preferences", false)) {
       openPreferences();
       cmdLine.preventDefault = true;
     }
     if (cmdLine.handleFlag("silent", false))
       cmdLine.preventDefault = true;
 #ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
-    if (cmdLine.findFlag("private-window", false) >= 0) {
+    if (cmdLine.handleFlag("private-window", false)) {
       openWindow(null, this.chromeURL, "_blank",
         "chrome,dialog=no,private,all" + this.getFeatures(cmdLine),
         "about:privatebrowsing");
       cmdLine.preventDefault = true;
     }
 #else
     if (cmdLine.findFlag("private-toggle", false) >= 0)
       cmdLine.preventDefault = true;
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -1239,16 +1239,17 @@ let gPrivateBrowsingListener = {
 
 let ContentArea = {
   _specialViews: new Map(),
 
   init: function CA_init() {
     this._deck = document.getElementById("placesViewsDeck");
     this._toolbar = document.getElementById("placesToolbar");
     ContentTree.init();
+    this._setupView();
   },
 
   /**
    * Gets the content view to be used for loading the given query.
    * If a custom view was set by setContentViewForQueryString, that
    * view would be returned, else the default tree view is returned
    *
    * @param aQueryString
@@ -1375,20 +1376,16 @@ let ContentTree = {
   }),
 
   openSelectedNode: function CT_openSelectedNode(aEvent) {
     let view = this.view;
     PlacesUIUtils.openNodeWithEvent(view.selectedNode, aEvent, view);
   },
 
   onClick: function CT_onClick(aEvent) {
-    // Only handle clicks on tree children.
-    if (aEvent.target.localName != "treechildren")
-      return;
-
     let node = this.view.selectedNode;
     if (node) {
       let doubleClick = aEvent.button == 0 && aEvent.detail == 2;
       let middleClick = aEvent.button == 1 && aEvent.detail == 1;
       if (PlacesUtils.nodeIsURI(node) && (doubleClick || middleClick)) {
         // Open associated uri in the browser.
         this.openSelectedNode(aEvent);
       }
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -368,18 +368,17 @@
               flex="1"
               type="places"
               flatList="true"
               selectfirstnode="true"
               enableColumnDrag="true"
               onfocus="PlacesOrganizer.updateDetailsPane(event)"
               onselect="PlacesOrganizer.updateDetailsPane(event)"
               onkeypress="ContentTree.onKeyPress(event);"
-              onopenflatcontainer="PlacesOrganizer.openFlatContainer(aContainer);"
-              onclick="ContentTree.onClick(event);">
+              onopenflatcontainer="PlacesOrganizer.openFlatContainer(aContainer);">
           <treecols id="placeContentColumns" context="placesColumnsContext">
             <treecol label="&col.name.label;" id="placesContentTitle" anonid="title" flex="5" primary="true" ordinal="1" 
                       persist="width hidden ordinal sortActive sortDirection"/>
             <splitter class="tree-splitter"/>
             <treecol label="&col.tags.label;" id="placesContentTags" anonid="tags" flex="2"
                       persist="width hidden ordinal sortActive sortDirection"/>
             <splitter class="tree-splitter"/>
             <treecol label="&col.url.label;" id="placesContentUrl" anonid="url" flex="5"
@@ -398,17 +397,17 @@
                       persist="width hidden ordinal sortActive sortDirection"/>
             <splitter class="tree-splitter"/>
             <treecol label="&col.dateadded.label;" id="placesContentDateAdded" anonid="dateAdded" flex="1" hidden="true"
                       persist="width hidden ordinal sortActive sortDirection"/>
             <splitter class="tree-splitter"/>
             <treecol label="&col.lastmodified.label;" id="placesContentLastModified" anonid="lastModified" flex="1" hidden="true"
                       persist="width hidden ordinal sortActive sortDirection"/>
           </treecols>
-          <treechildren flex="1"/>
+          <treechildren flex="1" onclick="ContentTree.onClick(event);"/>
         </tree>
       </deck>
       <deck id="detailsDeck" style="height: 11em;">
         <vbox id="itemsCountBox" align="center">
           <spacer flex="3"/>
           <label id="itemsCountText"/>
           <spacer flex="1"/>
           <description id="selectItemDescription">
--- a/browser/components/privatebrowsing/test/browser/perwindow/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/perwindow/Makefile.in
@@ -10,16 +10,19 @@ relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_BROWSER_FILES =  \
 		head.js \
 		browser_privatebrowsing_certexceptionsui.js \
 		browser_privatebrowsing_concurrent.js \
 		browser_privatebrowsing_concurrent_page.html \
+		browser_privatebrowsing_cookieacceptdialog.js \
+		browser_privatebrowsing_cookieacceptdialog.html \
+		browser_privatebrowsing_crh.js \
 		browser_privatebrowsing_downloadLastDir.js \
 		browser_privatebrowsing_downloadLastDir_c.js \
 		browser_privatebrowsing_downloadLastDir_toggle.js \
 		browser_privatebrowsing_DownloadLastDirWithCPS.js \
 		browser_privatebrowsing_geoprompt.js \
 		browser_privatebrowsing_geoprompt_page.html \
 		browser_privatebrowsing_lastpbcontextexited.js \
 		browser_privatebrowsing_localStorage.js \
@@ -43,18 +46,9 @@ MOCHITEST_BROWSER_FILES =  \
 		browser_privatebrowsing_windowtitle.js \
 		browser_privatebrowsing_windowtitle_page.html \
 		browser_privatebrowsing_zoom.js \
 		browser_privatebrowsing_zoomrestore.js \
 		popup.html \
 		title.sjs \
 		$(NULL)
 
-# Temporarily disabled on OS X for bug 822284
-ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
-MOCHITEST_BROWSER_FILES += \
-		browser_privatebrowsing_cookieacceptdialog.js \
-		browser_privatebrowsing_cookieacceptdialog.html \
-		browser_privatebrowsing_crh.js \
-		$(NULL)
-endif
-
 include $(topsrcdir)/config/rules.mk
--- a/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_cookieacceptdialog.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_cookieacceptdialog.js
@@ -55,85 +55,98 @@ function test() {
       isSecure: false,
       expires: time,
       status: 0,
       policy: 0,
       isSession: false,
       expiry: time,
       isHttpOnly: true,
       QueryInterface: function(iid) {
-        const validIIDs = [Ci.nsISupports,
-                           Ci.nsICookie,
-                           Ci.nsICookie2];
+        const validIIDs = [Ci.nsISupports, Ci.nsICookie, Ci.nsICookie2];
         for (var i = 0; i < validIIDs.length; ++i)
           if (iid == validIIDs[i])
             return this;
         throw Cr.NS_ERROR_NO_INTERFACE;
       }
     };
     cp.cookieDialog(aWindow, cookie, "mozilla.org", 10, false, remember);
   }
 
   function checkSettingDialog(aIsPrivateWindow, aWindow, aCallback) {
-    aWindow.gBrowser.selectedTab = aWindow.gBrowser.addTab();
     let selectedBrowser = aWindow.gBrowser.selectedBrowser;
 
     function onLoad() {
+      if (aWindow.content.location.href != TEST_URL) {
+        selectedBrowser.loadURI(TEST_URL);
+        return;
+      }
       selectedBrowser.removeEventListener("load", onLoad, true);
       Services.ww.unregisterNotification(observer);
 
-      ok(aIsPrivateWindow, "Confirm setting dialog is not displayed for private window");
+      ok(aIsPrivateWindow,
+         "Confirm setting dialog is not displayed for private window");
 
       executeSoon(aCallback);
     }
     selectedBrowser.addEventListener("load", onLoad, true);
 
     function observer(aSubject, aTopic, aData) {
       if (aTopic != "domwindowopened")
         return;
       selectedBrowser.removeEventListener("load", onLoad, true);
       Services.ww.unregisterNotification(observer);
-
-      ok(!aIsPrivateWindow, "Confirm setting dialog is displayed for normal window");
-
+      ok(!aIsPrivateWindow,
+         "Confirm setting dialog is displayed for normal window");
       let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
       executeSoon(function () {
-        win.close();
-        executeSoon(aCallback);
+        info("Wait for window close");
+        waitForWindowClose(win, aCallback);
       });
     }
     Services.ww.registerNotification(observer);
 
     selectedBrowser.loadURI(TEST_URL);
   }
 
-  var windowsToClose = [];
-  function testOnWindow(options, callback) {
-    var win = OpenBrowserWindow(options);
-    win.addEventListener("load", function onLoad() {
-      win.removeEventListener("load", onLoad, false);
-      windowsToClose.push(win);
-      callback(win);
-    }, false);
+  let windowsToClose = [];
+  function testOnWindow(aIsPrivate, aCallback) {
+    whenNewWindowLoaded({private: aIsPrivate}, function(aWin) {
+      windowsToClose.push(aWin);
+      aCallback(aWin);
+    });
   }
 
   registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("network.cookie.lifetimePolicy");
     windowsToClose.forEach(function(win) {
-      Services.prefs.clearUserPref("network.cookie.lifetimePolicy");
       win.close();
     });
   });
 
-  // ask all cookies
+  // Ask all cookies
   Services.prefs.setIntPref("network.cookie.lifetimePolicy", 1);
 
-  testOnWindow({private: true}, function(aPrivWin) {
+  testOnWindow(true, function(aPrivWin) {
+    info("Test on private window");
     checkRememberOption(true, aPrivWin, function() {
       checkSettingDialog(true, aPrivWin, function() {
-        testOnWindow(undefined, function(aWin) {
+        testOnWindow(false, function(aWin) {
+          info("Test on public window");
           checkRememberOption(false, aWin, function() {
             checkSettingDialog(false, aWin, finish);
           });
         });
       });
     });
   });
 }
+
+function waitForWindowClose(aWin, aCallback) {
+  function observer(aSubject, aTopic, aData) {
+    if (aTopic == "domwindowclosed") {
+      info("Window closed");
+      Services.ww.unregisterNotification(observer);
+      executeSoon(aCallback);
+    }
+  }
+  Services.ww.registerNotification(observer);
+  aWin.close();
+}
--- a/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_crh.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_crh.js
@@ -18,31 +18,42 @@ function test() {
       is(crhCommand.hasAttribute("disabled"), aPrivateMode,
         "Clear Recent History command should be disabled according to the private browsing mode");
 
       executeSoon(aCallback);
     });
   };
 
   let windowsToClose = [];
-  function testOnWindow(options, callback) {
-    let win = OpenBrowserWindow(options);
-    win.addEventListener("load", function onLoad() {
-      win.removeEventListener("load", onLoad, false);
-      windowsToClose.push(win);
-      callback(win);
-    }, false);
+  let testURI = "about:blank";
+
+  function testOnWindow(aIsPrivate, aCallback) {
+    whenNewWindowLoaded({private: aIsPrivate}, function(aWin) {
+      windowsToClose.push(aWin);
+      aWin.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
+        if (aWin.content.location.href != testURI) {
+          aWin.gBrowser.loadURI(testURI);
+          return;
+        }
+        aWin.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
+        executeSoon(function() aCallback(aWin));
+      }, true);
+
+      aWin.gBrowser.loadURI(testURI);
+    });
   };
 
   registerCleanupFunction(function() {
     windowsToClose.forEach(function(win) {
       win.close();
     });
   });
 
-  testOnWindow({private: true}, function(win) {
+  testOnWindow(true, function(win) {
+    info("Test on private window");
     checkDisableOption(true, win, function() {
-      testOnWindow({}, function(win) {
+      testOnWindow(false, function(win) {
+        info("Test on public window");
         checkDisableOption(false, win, finish);
       });
     });
   });
 }
--- a/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_lastpbcontextexited.js
+++ b/browser/components/privatebrowsing/test/browser/perwindow/browser_privatebrowsing_lastpbcontextexited.js
@@ -1,26 +1,49 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 function test() {
   // We need to open a new window for this so that its docshell would get destroyed
   // when clearing the PB mode flag.
-  let newWin = OpenBrowserWindow({private: true});
+  function runTest(aCloseWindow, aCallback) {
+    let newWin = OpenBrowserWindow({private: true});
+    SimpleTest.waitForFocus(function() {
+      let expectedExiting = true;
+      let expectedExited = false;
+      let observerExiting = {
+        observe: function(aSubject, aTopic, aData) {
+          is(aTopic, "last-pb-context-exiting", "Correct topic should be dispatched (exiting)");
+          is(expectedExiting, true, "notification not expected yet (exiting)");
+          expectedExited = true;
+          Services.obs.removeObserver(observerExiting, "last-pb-context-exiting", false);
+        }
+      };
+      let observerExited = {
+        observe: function(aSubject, aTopic, aData) {
+          is(aTopic, "last-pb-context-exited", "Correct topic should be dispatched (exited)");
+          is(expectedExited, true, "notification not expected yet (exited)");
+          Services.obs.removeObserver(observerExited, "last-pb-context-exited", false);
+          aCallback();
+        }
+      };
+      Services.obs.addObserver(observerExiting, "last-pb-context-exiting", false);
+      Services.obs.addObserver(observerExited, "last-pb-context-exited", false);
+      expectedExiting = true;
+      aCloseWindow(newWin);
+      newWin = null;
+      SpecialPowers.forceGC();
+    }, newWin);
+  }
+
   waitForExplicitFinish();
-  SimpleTest.waitForFocus(function() {
-    let expected = false;
-    let observer = {
-      observe: function(aSubject, aTopic, aData) {
-        is(aTopic, "last-pb-context-exited", "Correct topic should be dispatched");
-        is(expected, true, "notification not expected yet");
-        Services.obs.removeObserver(observer, "last-pb-context-exited", false);
-        finish();
-      }
-    };
-    Services.obs.addObserver(observer, "last-pb-context-exited", false);
-    expected = true;
-    newWin.close(); // this will cause the docshells to leave PB mode
-    newWin = null;
-    SpecialPowers.forceGC();
-  }, newWin);
+
+  runTest(function(newWin) {
+      // Simulate pressing the window close button
+      newWin.document.getElementById("cmd_closeWindow").doCommand();
+    }, function () {
+      runTest(function(newWin) {
+          // Simulate closing the last tab
+          newWin.document.getElementById("cmd_close").doCommand();
+        }, finish);
+    });
 }
--- a/browser/components/shell/test/browser_420786.js
+++ b/browser/components/shell/test/browser_420786.js
@@ -72,14 +72,24 @@ function onPageLoad() {
 function test() {
   var osString = Cc["@mozilla.org/xre/app-info;1"].
                  getService(Ci.nsIXULRuntime).OS;
   if (osString != "Linux") {
     todo(false, "This test is Linux specific for now.");
     return;
   }
 
+  try {
+    // If GSettings is available, then the GConf tests
+    // will fail
+    var gsettings = Cc["@mozilla.org/gsettings-service;1"].
+                    getService(Ci.nsIGSettingsService).
+                    getCollectionForSchema("org.gnome.desktop.background");
+    todo(false, "This test doesn't work when GSettings is available");
+    return;
+  } catch(e) { }
+
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", onPageLoad, true);
   content.location = "about:logo";
 
   waitForExplicitFinish();
 }
--- a/browser/components/shell/test/unit/test_421977.js
+++ b/browser/components/shell/test/unit/test_421977.js
@@ -62,16 +62,25 @@ function checkShellToGConfColor(aShellCo
 }
 
 function run_test() {
 
   // This test is Linux specific for now
   if (!("@mozilla.org/gnome-gconf-service;1" in Cc))
     return;
 
+  try {
+    // If GSettings is available, then the GConf tests
+    // will fail
+    var gsettings = Cc["@mozilla.org/gsettings-service;1"].
+                    getService(Ci.nsIGSettingsService).
+                    getCollectionForSchema("org.gnome.desktop.background");
+    return;
+  } catch(e) { }
+
   gGConf = Cc["@mozilla.org/gnome-gconf-service;1"].
            getService(Ci.nsIGConfService);
 
   gShell = Cc["@mozilla.org/browser/shell-service;1"].
            getService(Ci.nsIShellService);
 
   // Save the original background color so that we can restore it
   // after the test.
--- a/build/ConfigStatus.py
+++ b/build/ConfigStatus.py
@@ -6,49 +6,28 @@
 # drop-in replacement for autoconf 2.13's config.status, with features
 # borrowed from autoconf > 2.5, and additional features.
 
 from __future__ import with_statement
 from optparse import OptionParser
 import sys, re, os, posixpath, ntpath
 import errno
 from StringIO import StringIO
+from os.path import relpath
+
 # Standalone js doesn't have virtualenv.
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'config'))
 from Preprocessor import Preprocessor
 
 # Basic logging facility
 verbose = False
 def log(string):
     if verbose:
         print >>sys.stderr, string
 
-# We need relpath, but it is introduced in python 2.6
-# http://docs.python.org/library/os.path.html
-def my_relpath(path, start):
-    """
-    Return a relative version of a path
-    from /usr/lib/python2.6/posixpath.py
-    """
-
-    if not path:
-        raise ValueError("no path specified")
-
-    start_list = os.path.abspath(start).split(os.path.sep)
-    path_list = os.path.abspath(path).split(os.path.sep)
-
-    # Work out how much of the filepath is shared by start and path.
-    i = len(os.path.commonprefix([start_list, path_list]))
-
-    rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
-    if not rel_list:
-        return os.curdir
-    return os.path.join(*rel_list)
-
-relpath = getattr(os.path, "relpath", my_relpath)
 
 def ensureParentDir(file):
     '''Ensures the directory parent to the given file exists'''
     dir = os.path.dirname(file)
     if dir and not os.path.exists(dir):
         try:
             os.makedirs(dir)
         except OSError, error:
new file mode 100644
--- /dev/null
+++ b/build/autoconf/python-virtualenv.m4
@@ -0,0 +1,77 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_PYTHON],
+[
+
+dnl We honor the Python path defined in an environment variable. This is used
+dnl to pass the virtualenv's Python from the main configure to SpiderMonkey's
+dnl configure, for example.
+if test -z "$PYTHON"; then
+  MOZ_PATH_PROGS(PYTHON, $PYTHON python2.7 python)
+  if test -z "$PYTHON"; then
+      AC_MSG_ERROR([python was not found in \$PATH])
+  fi
+else
+  AC_MSG_RESULT([Using Python from environment variable \$PYTHON])
+fi
+
+_virtualenv_topsrcdir=
+_virtualenv_populate_path=
+
+dnl If this is a mozilla-central, we'll find the virtualenv in the top
+dnl source directory. If this is a SpiderMonkey build, we assume we're at
+dnl js/src and try to find the virtualenv from the mozilla-central root.
+for base in $MOZILLA_CENTRAL_PATH $_topsrcdir $_topsrcdir/../..; do
+  possible=$base/build/virtualenv/populate_virtualenv.py
+
+  if test -e $possible; then
+    _virtualenv_topsrcdir=$base
+    _virtualenv_populate_path=$possible
+    break
+  fi
+done
+
+if test -z $_virtualenv_populate_path; then
+    AC_MSG_ERROR([Unable to find Virtualenv population script. In order
+to build, you will need mozilla-central's virtualenv.
+
+If you are building from a mozilla-central checkout, you should never see this
+message. If you are building from a source archive, the source archive was
+likely not created properly (it is missing the virtualenv files).
+
+If you have a copy of mozilla-central available, define the
+MOZILLA_CENTRAL_PATH environment variable to the top source directory of
+mozilla-central and relaunch configure.])
+
+fi
+
+if test -z $DONT_POPULATE_VIRTUALENV; then
+  AC_MSG_RESULT([Creating Python environment])
+  dnl This verifies our Python version is sane and ensures the Python
+  dnl virtualenv is present and up to date. It sanitizes the environment
+  dnl for us, so we don't need to clean anything out.
+  $PYTHON $_virtualenv_populate_path \
+    $_virtualenv_topsrcdir $MOZ_BUILD_ROOT/_virtualenv || exit 1
+
+  case "$host_os" in
+  mingw*)
+    PYTHON=`cd $MOZ_BUILD_ROOT && pwd -W`/_virtualenv/Scripts/python.exe
+    ;;
+  *)
+    PYTHON=$MOZ_BUILD_ROOT/_virtualenv/bin/python
+    ;;
+  esac
+fi
+
+AC_SUBST(PYTHON)
+
+AC_MSG_CHECKING([Python environment is Mozilla virtualenv])
+$PYTHON -c "import mozbuild.base"
+if test "$?" != 0; then
+    AC_MSG_ERROR([Python environment does not appear to be sane.])
+fi
+AC_MSG_RESULT([yes])
+])
+
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -269,48 +269,47 @@ class Automation(object):
   def setupPermissionsDatabase(self, profileDir, permissions):
     # Open database and create table
     permDB = sqlite3.connect(os.path.join(profileDir, "permissions.sqlite"))
     cursor = permDB.cursor();
 
     cursor.execute("PRAGMA user_version=3");
 
     # SQL copied from nsPermissionManager.cpp
-    cursor.execute("""CREATE TABLE moz_hosts (
-       id INTEGER PRIMARY KEY,
-       host TEXT,
-       type TEXT,
-       permission INTEGER,
-       expireType INTEGER,
-       expireTime INTEGER,
-       appId INTEGER,
-       isInBrowserElement INTEGER)""")
+    cursor.execute("""CREATE TABLE IF NOT EXISTS moz_hosts (
+      id INTEGER PRIMARY KEY,
+      host TEXT,
+      type TEXT,
+      permission INTEGER,
+      expireType INTEGER,
+      expireTime INTEGER,
+      appId INTEGER,
+      isInBrowserElement INTEGER)""")
 
     # Insert desired permissions
-    c = 0
     for perm in permissions.keys():
       for host,allow in permissions[perm]:
-        c += 1
-        cursor.execute("INSERT INTO moz_hosts values(?, ?, ?, ?, 0, 0, 0, 0)",
-                       (c, host, perm, 1 if allow else 2))
+        cursor.execute("INSERT INTO moz_hosts values(NULL, ?, ?, ?, 0, 0, 0, 0)",
+                       (host, perm, 1 if allow else 2))
 
     # Commit and close
     permDB.commit()
     cursor.close()
 
   def setupTestApps(self, profileDir, apps):
-    webappJSONTemplate = Template(""""$name": {
-"origin": "$origin",
-"installOrigin": "$origin",
-"receipt": null,
-"installTime": 132333986000,
-"manifestURL": "$manifestURL",
-"localId": $localId,
-"appStatus": $appStatus,
-"csp": "$csp"
+    webappJSONTemplate = Template(""""$id": {
+  "origin": "$origin",
+  "installOrigin": "$origin",
+  "receipt": null,
+  "installTime": 132333986000,
+  "manifestURL": "$manifestURL",
+  "localId": $localId,
+  "id": "$id",
+  "appStatus": $appStatus,
+  "csp": "$csp"
 }""")
 
     manifestTemplate = Template("""{
   "name": "$name",
   "csp": "$csp",
   "description": "$description",
   "launch_path": "/",
   "developer": {
@@ -328,46 +327,109 @@ class Automation(object):
   "default_locale": "en-US",
   "icons": {
   }
 }
 """)
 
     # Create webapps/webapps.json
     webappsDir = os.path.join(profileDir, "webapps")
-    os.mkdir(webappsDir);
+    if not os.access(webappsDir, os.F_OK):
+      os.mkdir(webappsDir)
+
+    lineRe = re.compile(r'(.*?)"(.*?)": (.*)')
+
+    webappsJSONFilename = os.path.join(webappsDir, "webapps.json")
+    webappsJSON = []
+    if os.access(webappsJSONFilename, os.F_OK):
+      # If there is an existing webapps.json file (which will be the case for
+      # b2g), we parse the data in the existing file before appending test
+      # test apps to it.
+      startId = 1
+      webappsJSONFile = open(webappsJSONFilename, "r")
+      contents = webappsJSONFile.read()
 
-    webappsJSON = []
+      for app_content in contents.split('},'):
+        app = {}
+        # ghetto json parser needed due to lack of json/simplejson on test slaves
+        for line in app_content.split('\n'):
+          m = lineRe.match(line)
+          if m:
+            value = m.groups()[2]
+            # remove any trailing commas
+            if value[-1:] == ',':
+              value = value[:-1]
+            # set the app name from a line that looks like this:
+            # "name.gaiamobile.org": {
+            if value == '{':
+              app['id'] = m.groups()[1]
+            # parse string, None, bool and int types
+            elif value[0:1] == '"':
+              app[m.groups()[1]] = value[1:-1]
+            elif value == "null":
+              app[m.groups()[1]] = None
+            elif value == "true":
+              app[m.groups()[1]] = True
+            elif value == "false":
+              app[m.groups()[1]] = False
+            else:
+              app[m.groups()[1]] = int(value)
+        if app:
+          webappsJSON.append(app)
+
+      webappsJSONFile.close()
+
+    startId = 1
+    for app in webappsJSON:
+      if app['localId'] >= startId:
+        startId = app['localId'] + 1
+      if not app.get('csp'):
+        app['csp'] = ''
+      if not app.get('appStatus'):
+        app['appStatus'] = 3
+
     for localId, app in enumerate(apps):
-      app['localId'] = localId + 1 # Has to be 1..n
-      webappsJSON.append(webappJSONTemplate.substitute(app))
-    webappsJSON = '{\n' + ',\n'.join(webappsJSON) + '\n}\n'
+      app['localId'] = localId + startId # localId must be from 1..N
+      if not app.get('id'):
+        app['id'] = app['name']
+      webappsJSON.append(app)
 
-    webappsJSONFile = open(os.path.join(webappsDir, "webapps.json"), "a")
-    webappsJSONFile.write(webappsJSON)
+    contents = []
+    for app in webappsJSON:
+      contents.append(webappJSONTemplate.substitute(app))
+    contents = '{\n' + ',\n'.join(contents) + '\n}\n'
+
+    webappsJSONFile = open(webappsJSONFilename, "w")
+    webappsJSONFile.write(contents)
     webappsJSONFile.close()
 
     # Create manifest file for each app.
     for app in apps:
       manifest = manifestTemplate.substitute(app)
 
       manifestDir = os.path.join(webappsDir, app['name'])
       os.mkdir(manifestDir)
 
       manifestFile = open(os.path.join(manifestDir, "manifest.webapp"), "a")
       manifestFile.write(manifest)
       manifestFile.close()
 
-  def initializeProfile(self, profileDir, extraPrefs = [], useServerLocations = False):
+  def initializeProfile(self, profileDir, extraPrefs=[],
+                        useServerLocations=False,
+                        initialProfile=None):
     " Sets up the standard testing profile."
 
     prefs = []
     # Start with a clean slate.
     shutil.rmtree(profileDir, True)
-    os.mkdir(profileDir)
+
+    if initialProfile:
+      shutil.copytree(initialProfile, profileDir)
+    else:
+      os.mkdir(profileDir)
 
     # Set up permissions database
     locations = self.readLocations()
     self.setupPermissionsDatabase(profileDir,
       {'allowXULXBL':[(l.host, 'noxul' not in l.options) for l in locations]});
 
     part = """\
 user_pref("social.skipLoadingProviders", true);
@@ -595,49 +657,49 @@ user_pref("camino.use_system_proxy_setti
       },
       {
         'name': 'https_example_csp_certified',
         'csp': "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'",
         'origin': 'https://example.com',
         'manifestURL': 'https://example.com/manifest_csp_cert.webapp',
         'description': 'https://example.com Certified App with manifest policy',
         'appStatus': _APP_STATUS_CERTIFIED
-      }, 
+      },
       {
         'name': 'https_example_csp_installed',
         'csp': "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'",
         'origin': 'https://example.com',
         'manifestURL': 'https://example.com/manifest_csp_inst.webapp',
         'description': 'https://example.com Installed App with manifest policy',
         'appStatus': _APP_STATUS_INSTALLED
-      }, 
+      },
       {
         'name': 'https_example_csp_privileged',
         'csp': "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'",
         'origin': 'https://example.com',
         'manifestURL': 'https://example.com/manifest_csp_priv.webapp',
         'description': 'https://example.com Privileged App with manifest policy',
         'appStatus': _APP_STATUS_PRIVILEGED
-      }, 
+      },
       {
         'name': 'https_a_domain_certified',
-        'csp' : "",
+        'csp': "",
         'origin': 'https://acertified.com',
         'manifestURL': 'https://acertified.com/manifest.webapp',
         'description': 'https://acertified.com Certified App',
         'appStatus': _APP_STATUS_CERTIFIED
-      }, 
+      },
       {
         'name': 'https_a_domain_privileged',
         'csp': "",
         'origin': 'https://aprivileged.com',
         'manifestURL': 'https://aprivileged.com/manifest.webapp',
         'description': 'https://aprivileged.com Privileged App ',
         'appStatus': _APP_STATUS_PRIVILEGED
-      }, 
+      },
     ];
     self.setupTestApps(profileDir, apps)
 
   def addCommonOptions(self, parser):
     "Adds command-line options which are common to mochitest and reftest."
 
     parser.add_option("--setpref",
                       action = "append", type = "string",
@@ -1028,17 +1090,17 @@ user_pref("camino.use_system_proxy_setti
 
   def checkForCrashes(self, profileDir, symbolsPath):
     return automationutils.checkForCrashes(os.path.join(profileDir, "minidumps"), symbolsPath, self.lastTestSeen)
 
   def runApp(self, testURL, env, app, profileDir, extraArgs,
              runSSLTunnel = False, utilityPath = None,
              xrePath = None, certPath = None,
              debuggerInfo = None, symbolsPath = None,
-             timeout = -1, maxTime = None):
+             timeout = -1, maxTime = None, onLaunch = None):
     """
     Run the app, log the duration it took to execute, return the status code.
     Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
     """
 
     if utilityPath == None:
       utilityPath = self.DIST_BIN
     if xrePath == None:
@@ -1085,16 +1147,21 @@ user_pref("camino.use_system_proxy_setti
     self.lastTestSeen = "automation.py"
     proc = self.Process([cmd] + args,
                  env = self.environment(env, xrePath = xrePath,
                                    crashreporter = not debuggerInfo),
                  stdout = outputPipe,
                  stderr = subprocess.STDOUT)
     self.log.info("INFO | automation.py | Application pid: %d", proc.pid)
 
+    if onLaunch is not None:
+      # Allow callers to specify an onLaunch callback to be fired after the
+      # app is launched.
+      onLaunch()
+
     status = self.waitForFinish(proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath)
     self.log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
 
     # Do a final check for zombie child processes.
     zombieProcesses = self.checkForZombies(processLog)
 
     crashed = self.checkForCrashes(profileDir, symbolsPath)
 
--- a/build/mobile/b2gautomation.py
+++ b/build/mobile/b2gautomation.py
@@ -43,17 +43,17 @@ class B2GRemoteAutomation(Automation):
         self._is_emulator = False
         self.test_script = None
         self.test_script_args = None
 
         # Default our product to b2g
         self._product = "b2g"
         self.lastTestSeen = "b2gautomation.py"
         # Default log finish to mochitest standard
-        self.logFinish = 'INFO SimpleTest FINISHED' 
+        self.logFinish = 'INFO SimpleTest FINISHED'
         Automation.__init__(self)
 
     def setEmulator(self, is_emulator):
         self._is_emulator = is_emulator
 
     def setDeviceManager(self, deviceManager):
         self._devicemanager = deviceManager
 
@@ -80,17 +80,17 @@ class B2GRemoteAutomation(Automation):
         # so no copying of os.environ
         if env is None:
             env = {}
 
         # We always hide the results table in B2G; it's much slower if we don't.
         env['MOZ_HIDE_RESULTS_TABLE'] = '1'
         return env
 
-    def waitForNet(self): 
+    def waitForNet(self):
         active = False
         time_out = 0
         while not active and time_out < 40:
             data = self._devicemanager._runCmd(['shell', '/system/bin/netcfg']).stdout.readlines()
             data.pop(0)
             for line in data:
                 if (re.search(r'UP\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3}', line)):
                     active = True
@@ -101,25 +101,30 @@ class B2GRemoteAutomation(Automation):
 
     def checkForCrashes(self, directory, symbolsPath):
         # XXX: This will have to be updated after crash reporting on b2g
         # is in place.
         dumpDir = tempfile.mkdtemp()
         self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
         crashed = automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
         try:
-          shutil.rmtree(dumpDir)
+            shutil.rmtree(dumpDir)
         except:
-          print "WARNING: unable to remove directory: %s" % (dumpDir)
+            print "WARNING: unable to remove directory: %s" % (dumpDir)
         return crashed
 
-    def initializeProfile(self, profileDir, extraPrefs = [], useServerLocations = False):
+    def initializeProfile(self,  profileDir, extraPrefs=[],
+                          useServerLocations=False,
+                          initialProfile=None):
         # add b2g specific prefs
         extraPrefs.extend(["browser.manifestURL='dummy (bug 772307)'"])
-        return Automation.initializeProfile(self, profileDir, extraPrefs, useServerLocations)
+        return Automation.initializeProfile(self, profileDir,
+                                            extraPrefs,
+                                            useServerLocations,
+                                            initialProfile)
 
     def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
         # if remote profile is specified, use that instead
         if (self._remoteProfile):
             profileDir = self._remoteProfile
 
         cmd, args = Automation.buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs)
 
@@ -160,17 +165,17 @@ class B2GRemoteAutomation(Automation):
     def getDeviceStatus(self, serial=None):
         # Get the current status of the device.  If we know the device
         # serial number, we look for that, otherwise we use the (presumably
         # only) device shown in 'adb devices'.
         serial = serial or self._devicemanager.deviceSerial
         status = 'unknown'
 
         for line in self._devicemanager._runCmd(['devices']).stdout.readlines():
-            result =  re.match('(.*?)\t(.*)', line)
+            result = re.match('(.*?)\t(.*)', line)
             if result:
                 thisSerial = result.group(1)
                 if not serial or thisSerial == serial:
                     serial = thisSerial
                     status = result.group(2)
 
         return (serial, status)
 
@@ -218,19 +223,19 @@ class B2GRemoteAutomation(Automation):
 
         # reboot device so it starts up with the mochitest profile
         # XXX:  We could potentially use 'stop b2g' + 'start b2g' to achieve
         # a similar effect; will see which is more stable while attempting
         # to bring up the continuous integration.
         if not self._is_emulator:
             self.rebootDevice()
             time.sleep(5)
-            #wait for wlan to come up 
+            #wait for wlan to come up
             if not self.waitForNet():
-                raise Exception("network did not come up, please configure the network" + 
+                raise Exception("network did not come up, please configure the network" +
                                 " prior to running before running the automation framework")
 
         # stop b2g
         self._devicemanager._runCmd(['shell', 'stop', 'b2g'])
         time.sleep(5)
 
         # relaunch b2g inside b2g instance
         instance = self.B2GInstance(self._devicemanager)
@@ -329,15 +334,38 @@ class B2GRemoteAutomation(Automation):
             lines = []
             while True:
                 try:
                     lines.append(self.queue.get_nowait())
                 except Queue.Empty:
                     break
             return '\n'.join(lines)
 
-        def wait(self, timeout = None):
+        def wait(self, timeout=None):
             # this should never happen
             raise Exception("'wait' called on B2GInstance")
 
         def kill(self):
             # this should never happen
             raise Exception("'kill' called on B2GInstance")
+
+
+class B2GDesktopAutomation(Automation):
+
+    def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
+        """ build the application command line """
+
+        cmd = os.path.abspath(app)
+        args = []
+
+        if debuggerInfo:
+            args.extend(debuggerInfo["args"])
+            args.append(cmd)
+            cmd = os.path.abspath(debuggerInfo["path"])
+
+        if self.IS_MAC:
+            args.append("-foreground")
+
+        profileDirectory = profileDir + "/"
+
+        args.extend(("-profile", profileDirectory))
+        args.extend(extraArgs)
+        return cmd, args
--- a/build/unix/elfhack/elf.cpp
+++ b/build/unix/elfhack/elf.cpp
@@ -254,17 +254,25 @@ Elf::Elf(std::ifstream &file)
         if (phdr.p_type == PT_PHDR)
             segment->addSection(phdr_section);
         for (int j = 1; j < ehdr->e_shnum; j++)
             if (phdr.contains(sections[j]))
                 segment->addSection(sections[j]);
         // Make sure that our view of segments corresponds to the original
         // ELF file.
         assert(segment->getFileSize() == phdr.p_filesz);
-        assert(segment->getMemSize() == phdr.p_memsz);
+        // gold makes TLS segments end on an aligned virtual address, even
+        // when the underlying section ends before that, while bfd ld
+        // doesn't. It's fine if we don't keep that alignment.
+        unsigned int memsize = segment->getMemSize();
+        if (phdr.p_type == PT_TLS && memsize != phdr.p_memsz) {
+            unsigned int align = segment->getAlign();
+            memsize = (memsize + align - 1) & ~(align - 1);
+        }
+        assert(memsize == phdr.p_memsz);
         segments.push_back(segment);
     }
 
     new (&eh_entry) ElfLocation(ehdr->e_entry, this);
 }
 
 Elf::~Elf()
 {
--- a/build/unix/elfhack/test.c
+++ b/build/unix/elfhack/test.c
@@ -117,18 +117,22 @@ static int ret = 1;
 int print_status() {
     fprintf(stderr, "%s\n", ret ? "FAIL" : "PASS");
     return ret;
 }
 
 /* On ARM, this creates a .tbss section before .init_array, which
  * elfhack could then pick instead of .init_array.
  * Also, when .tbss is big enough, elfhack may wrongfully consider
- * following sections as part of the PT_TLS segment. */
-__thread int foo[1024];
+ * following sections as part of the PT_TLS segment.
+ * Finally, gold makes TLS segments end on an aligned virtual address,
+ * even when the underlying section ends before that, and elfhack
+ * sanity checks may yield an error. */
+__thread int foo;
+__thread long long int bar[512];
 
 void end_test() {
     static int count = 0;
     /* Only exit when both constructors have been called */
     if (++count == 2)
         ret = 0;
 }
 
--- a/build/valgrind/cross-architecture.sup
+++ b/build/valgrind/cross-architecture.sup
@@ -250,16 +250,24 @@
    Bug 812423
    Memcheck:Leak
    fun:malloc
    fun:_ZN2js15ArgumentsObject6createI18CopyStackFrameArgsEEPS0_P9JSContextN2JS6HandleIP8JSScriptEENS7_IP10JSFunctionEEjRT_
    fun:_ZN2js15ArgumentsObject14createExpectedEP9JSContextPNS_10StackFrameE
    ...
 }
 {
+   Bug 812423
+   Memcheck:Leak
+   fun:malloc
+   fun:_ZN2js15ArgumentsObject6createI13CopyFrameArgsEEPS0_P9JSContextN2JS6HandleIP8JSScriptEENS7_IP10JSFunctionEEjRT_
+   fun:_ZN2js15ArgumentsObject14createExpectedEP9JSContextNS_16AbstractFramePtrE
+   ...
+}
+{
    Bug 823782
    Memcheck:Leak
    fun:malloc
    ...
    fun:_ZN2js6ctypes7LibraryL7DeclareEP9JSContextjPN2JS5ValueE
    ...
 }
 {
--- a/build/virtualenv/populate_virtualenv.py
+++ b/build/virtualenv/populate_virtualenv.py
@@ -240,22 +240,18 @@ class VirtualenvManager(object):
         program = [sys.executable, setup]
         program.extend(arguments)
 
         # We probably could call the contents of this file inside the context
         # of this interpreter using execfile() or similar. However, if global
         # variables like sys.path are adjusted, this could cause all kinds of
         # havoc. While this may work, invoking a new process is safer.
 
-        # TODO Use check_output when we require Python 2.7.
-        fn = getattr(subprocess, 'check_output',
-                VirtualenvManager._check_output)
-
         try:
-            output = fn(program, cwd=directory, stderr=subprocess.STDOUT)
+            output = subprocess.check_output(program, cwd=directory, stderr=subprocess.STDOUT)
             print(output)
         except subprocess.CalledProcessError as e:
             if 'Python.h: No such file or directory' in e.output:
                 print('WARNING: Python.h not found. Install Python development headers.')
             else:
                 print(e.output)
 
             raise Exception('Error installing package: %s' % directory)
@@ -289,31 +285,16 @@ class VirtualenvManager(object):
 
         If you run a random Python script and wish to "activate" the
         virtualenv, you can simply instantiate an instance of this class
         and call .ensure() and .activate() to make the virtualenv active.
         """
 
         execfile(self.activate_path, dict(__file__=self.activate_path))
 
-    # TODO Eliminate when we require Python 2.7.
-    @staticmethod
-    def _check_output(*args, **kwargs):
-        """Python 2.6 compatible implementation of subprocess.check_output."""
-        proc = subprocess.Popen(stdout=subprocess.PIPE, *args, **kwargs)
-        output, unused_err = proc.communicate()
-        retcode = proc.poll()
-        if retcode:
-            cmd = kwargs.get('args', args[0])
-            e = subprocess.CalledProcessError(retcode, cmd)
-            e.output = output
-            raise e
-
-        return output
-
 
 def verify_python_version(log_handle):
     """Ensure the current version of Python is sufficient."""
     major, minor = sys.version_info[:2]
 
     if major != MINIMUM_PYTHON_MAJOR or minor < MINIMUM_PYTHON_MINOR:
         log_handle.write('Python %d.%d or greater (but not Python 3) is '
             'required to build. ' %
--- a/configure.in
+++ b/configure.in
@@ -142,39 +142,17 @@ if test -e $_objdir/CLOBBER; then
     echo "	***"
     exit 1
     break;
   fi
 else
   touch $_objdir/CLOBBER
 fi
 
-MOZ_PATH_PROGS(PYTHON, $PYTHON python2.7 python)
-if test -z "$PYTHON"; then
-    AC_MSG_ERROR([python was not found in \$PATH])
-fi
-
-AC_MSG_RESULT([Creating Python environment])
-dnl This verifies our Python version is sane and ensures the Python
-dnl virtualenv is present and up to date. It sanitizes the environment
-dnl for us, so we don't need to clean anything out.
-$PYTHON $_topsrcdir/build/virtualenv/populate_virtualenv.py \
-    $_topsrcdir $MOZ_BUILD_ROOT/_virtualenv || exit 1
-
-dnl Create a virtualenv where we can install local Python packages
-case "$host_os" in
-mingw*)
-    PYTHON=`cd $MOZ_BUILD_ROOT && pwd -W`/_virtualenv/Scripts/python.exe
-    ;;
-*)
-    PYTHON=$MOZ_BUILD_ROOT/_virtualenv/bin/python
-    ;;
-esac
-
-AC_SUBST(PYTHON)
+MOZ_PYTHON
 
 MOZ_DEFAULT_COMPILER
 
 COMPILE_ENVIRONMENT=1
 MOZ_ARG_DISABLE_BOOL(compile-environment,
 [  --disable-compile-environment
                           Disable compiler/library checks.],
     COMPILE_ENVIRONMENT= )
@@ -1398,16 +1376,19 @@ if test -n "$MOZ_LLVM_HACKS"; then
 fi
 AC_SUBST(MOZ_NO_WLZDEFS)
 AC_SUBST(MOZ_CFLAGS_NSS)
 
 dnl ========================================================
 dnl GNU specific defaults
 dnl ========================================================
 if test "$GNU_CC"; then
+    # Per bug 719659 comment 2, some of the headers on ancient build machines
+    # may require gnu89 inline semantics.  But otherwise, we use C99.
+    CFLAGS="$CFLAGS -std=gnu99 -fgnu89-inline"
     # FIXME: Let us build with strict aliasing. bug 414641.
     CFLAGS="$CFLAGS -fno-strict-aliasing"
     MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@'
     MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@'
     DSO_LDOPTS='-shared'
     if test "$GCC_USE_GNU_LD"; then
         # Some tools like ASan use a runtime library that is only
         # linked against executables, so we must allow undefined
@@ -9342,15 +9323,18 @@ if test -n "$MOZ_GLUE_PROGRAM_LDFLAGS"; 
 fi
 if test "$MOZ_NATIVE_ZLIB" != 1 -a "$OS_ARCH" = "WINNT"; then
    MOZ_ZLIB_LIBS=
 fi
 export MOZ_NATIVE_ZLIB
 export MOZ_ZLIB_CFLAGS
 export MOZ_ZLIB_LIBS
 export MOZ_APP_NAME
+export DONT_POPULATE_VIRTUALENV=1
+export PYTHON
+export MOZILLA_CENTRAL_PATH=$_topsrcdir
 export STLPORT_CPPFLAGS
 export STLPORT_LDFLAGS
 export STLPORT_LIBS
 AC_OUTPUT_SUBDIRS(js/src)
 ac_configure_args="$_SUBDIR_CONFIG_ARGS"
 
 fi # COMPILE_ENVIRONMENT && !LIBXUL_SDK_DIR
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -433,16 +433,23 @@ public:
   {
     return sSecurityManager;
   }
 
   // Returns the subject principal. Guaranteed to return non-null. May only
   // be called when nsContentUtils is initialized.
   static nsIPrincipal* GetSubjectPrincipal();
 
+  // Returns the principal of the given JS object. This should never be null
+  // for any object in the XPConnect runtime.
+  //
+  // In general, being interested in the principal of an object is enough to
+  // guarantee that the return value is non-null.
+  static nsIPrincipal* GetObjectPrincipal(JSObject* aObj);
+
   static nsresult GenerateStateKey(nsIContent* aContent,
                                    const nsIDocument* aDocument,
                                    nsACString& aKey);
 
   /**
    * Create a new nsIURI from aSpec, using aBaseURI as the base.  The
    * origin charset of the new nsIURI will be the document charset of
    * aDocument.
@@ -2205,16 +2212,17 @@ private:
   // Combined code for PushNull() and Push(JSContext*)
   bool DoPush(JSContext* cx);
 
   nsCOMPtr<nsIScriptContext> mScx;
   bool mScriptIsRunning;
   bool mPushedSomething;
 #ifdef DEBUG
   JSContext* mPushedContext;
+  unsigned mCompartmentDepthOnEntry;
 #endif
 };
 
 class NS_STACK_CLASS nsAutoScriptBlocker {
 public:
   nsAutoScriptBlocker(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     nsContentUtils::AddScriptBlocker();
--- a/content/base/src/EventSource.cpp
+++ b/content/base/src/EventSource.cpp
@@ -74,18 +74,16 @@ EventSource::~EventSource()
 {
   Close();
 }
 
 //-----------------------------------------------------------------------------
 // EventSource::nsISupports
 //-----------------------------------------------------------------------------
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(EventSource)
-
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(EventSource)
   bool isBlack = tmp->IsBlack();
   if (isBlack || tmp->mWaitingForOnStopRequest) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->MarkForCC();
     }
     if (!isBlack && tmp->PreservingWrapper()) {
       xpc_UnmarkGrayObject(tmp->GetWrapperPreserveColor());
@@ -525,25 +523,17 @@ public:
 
     return NS_OK;
   }
 
 private:
   nsRefPtr<EventSource> mEventSource;
 };
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(AsyncVerifyRedirectCallbackFwr)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AsyncVerifyRedirectCallbackFwr)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventSource)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AsyncVerifyRedirectCallbackFwr)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventSource)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_1(AsyncVerifyRedirectCallbackFwr, mEventSource)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AsyncVerifyRedirectCallbackFwr)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(AsyncVerifyRedirectCallbackFwr)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(AsyncVerifyRedirectCallbackFwr)
--- a/content/base/src/FileIOObject.cpp
+++ b/content/base/src/FileIOObject.cpp
@@ -24,18 +24,16 @@ NS_IMPL_ADDREF_INHERITED(FileIOObject, n
 NS_IMPL_RELEASE_INHERITED(FileIOObject, nsDOMEventTargetHelper)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FileIOObject)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
   NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(FileIOObject)
-
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FileIOObject,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProgressNotifier)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mError)
   // Can't traverse mChannel because it's a multithreaded object.
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FileIOObject,
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -958,18 +958,16 @@ FragmentOrElement::FireNodeInserted(nsID
     }
   }
 }
 
 //----------------------------------------------------------------------
 
 // nsISupports implementation
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(FragmentOrElement)
-
 #define SUBTREE_UNBINDINGS_PER_RUNNABLE 500
 
 class ContentUnbinder : public nsRunnable
 {
 public:
   ContentUnbinder()
   {
     nsLayoutStatics::AddRef();
--- a/content/base/src/WebSocket.cpp
+++ b/content/base/src/WebSocket.cpp
@@ -571,18 +571,16 @@ WebSocket::Constructor(JSContext* aCx,
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
   return webSocket.forget();
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(WebSocket)
-
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(WebSocket)
   bool isBlack = tmp->IsBlack();
   if (isBlack|| tmp->mKeepingAlive) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->MarkForCC();
     }
     if (!isBlack && tmp->PreservingWrapper()) {
       xpc_UnmarkGrayObject(tmp->GetWrapperPreserveColor());
--- a/content/base/src/nsContentIterator.cpp
+++ b/content/base/src/nsContentIterator.cpp
@@ -1141,17 +1141,16 @@ protected:
 };
 
 NS_IMPL_ADDREF_INHERITED(nsContentSubtreeIterator, nsContentIterator)
 NS_IMPL_RELEASE_INHERITED(nsContentSubtreeIterator, nsContentIterator)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsContentSubtreeIterator)
 NS_INTERFACE_MAP_END_INHERITING(nsContentIterator)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsContentSubtreeIterator)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsContentSubtreeIterator, nsContentIterator)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRange)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsContentSubtreeIterator, nsContentIterator)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRange)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -39,17 +39,16 @@
 #endif
 
 using namespace mozilla::dom;
 
 nsBaseContentList::~nsBaseContentList()
 {
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsBaseContentList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsBaseContentList)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mElements)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBaseContentList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   if (nsCCUncollectableMarker::sGeneration && tmp->IsBlack() &&
       MOZ_LIKELY(!cb.WantAllTraces())) {
@@ -140,17 +139,16 @@ nsBaseContentList::IndexOf(nsIContent *a
 }
 
 int32_t
 nsBaseContentList::IndexOf(nsIContent* aContent)
 {
   return IndexOf(aContent, true);
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsSimpleContentList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsSimpleContentList,
                                                   nsBaseContentList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsSimpleContentList,
                                                 nsBaseContentList)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -62,17 +62,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsICSSLoaderObserver)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocumentObserver)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsContentSink)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsContentSink)
   if (tmp->mDocument) {
     tmp->mDocument->RemoveObserver(tmp);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParser)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNodeInfoManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mScriptLoader)
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -2326,16 +2326,27 @@ nsContentUtils::GetSubjectPrincipal()
   // When the ssm says the subject is null, that means system principal.
   if (!subject)
     sSecurityManager->GetSystemPrincipal(getter_AddRefs(subject));
 
   return subject;
 }
 
 // static
+nsIPrincipal*
+nsContentUtils::GetObjectPrincipal(JSObject* aObj)
+{
+  // This is duplicated from nsScriptSecurityManager. We don't call through there
+  // because the API unnecessarily requires a JSContext for historical reasons.
+  JSCompartment *compartment = js::GetObjectCompartment(aObj);
+  JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
+  return nsJSPrincipals::get(principals);
+}
+
+// static
 nsresult
 nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
                                           const nsAString& aSpec,
                                           nsIDocument* aDocument,
                                           nsIURI* aBaseURI)
 {
   return NS_NewURI(aResult, aSpec,
                    aDocument ? aDocument->GetDocumentCharacterSet().get() : nullptr,
@@ -3071,16 +3082,18 @@ nsCxPusher::DoPush(JSContext* cx)
     mScriptIsRunning = false;
     mScx = nullptr;
     return false;
   }
 
   mPushedSomething = true;
 #ifdef DEBUG
   mPushedContext = cx;
+  if (cx)
+    mCompartmentDepthOnEntry = js::GetEnterCompartmentDepth(cx);
 #endif
   return true;
 }
 
 bool
 nsCxPusher::PushNull()
 {
   return DoPush(nullptr);
@@ -3095,16 +3108,24 @@ nsCxPusher::Pop()
     mPushedSomething = false;
 
     NS_ASSERTION(!mScriptIsRunning, "Huh, this can't be happening, "
                  "mScriptIsRunning can't be set here!");
 
     return;
   }
 
+  // When we push a context, we may save the frame chain and pretend like we
+  // haven't entered any compartment. This gets restored on Pop(), but we can
+  // run into trouble if a Push/Pop are interleaved with a
+  // JSAutoEnterCompartment. Make sure the compartment depth right before we
+  // pop is the same as it was right after we pushed.
+  MOZ_ASSERT_IF(mPushedContext, mCompartmentDepthOnEntry ==
+                                js::GetEnterCompartmentDepth(mPushedContext));
+
   JSContext *unused;
   stack->Pop(&unused);
 
   NS_ASSERTION(unused == mPushedContext, "Unexpected context popped");
 
   if (!mScriptIsRunning && mScx) {
     // No JS is running in the context, but executing the event handler might have
     // caused some JS to run. Tell the script context that it's done.
--- a/content/base/src/nsDOMAttribute.cpp
+++ b/content/base/src/nsDOMAttribute.cpp
@@ -42,18 +42,16 @@ nsDOMAttribute::nsDOMAttribute(nsDOMAttr
   NS_ABORT_IF_FALSE(mNodeInfo, "We must get a nodeinfo here!");
   NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ATTRIBUTE_NODE,
                     "Wrong nodeType");
 
   // We don't add a reference to our content. It will tell us
   // to drop our reference when it goes away.
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMAttribute)
-
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMAttribute)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 
   if (!nsINode::Traverse(tmp, cb)) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
--- a/content/base/src/nsDOMAttributeMap.cpp
+++ b/content/base/src/nsDOMAttributeMap.cpp
@@ -50,18 +50,16 @@ nsDOMAttributeMap::~nsDOMAttributeMap()
 
 void
 nsDOMAttributeMap::DropReference()
 {
   mAttributeCache.Enumerate(RemoveMapRef, nullptr);
   mContent = nullptr;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMAttributeMap)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttributeMap)
   tmp->DropReference();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 PLDHashOperator
 TraverseMapEntry(nsAttrHashKey::KeyType aKey, nsRefPtr<nsDOMAttribute>& aData,
                  void* aUserArg)
--- a/content/base/src/nsDOMDataChannel.cpp
+++ b/content/base/src/nsDOMDataChannel.cpp
@@ -97,18 +97,16 @@ private:
   {
     DC_BINARY_TYPE_ARRAYBUFFER,
     DC_BINARY_TYPE_BLOB,
   } mBinaryType;
 };
 
 DOMCI_DATA(DataChannel, nsDOMDataChannel)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDataChannel)
-
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDataChannel,
                                                   nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDataChannel,
                                                 nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -50,18 +50,16 @@ using namespace mozilla;
 
 #define LOAD_STR "load"
 #define LOADSTART_STR "loadstart"
 #define LOADEND_STR "loadend"
 
 using mozilla::dom::EncodingUtils;
 using mozilla::dom::FileIOObject;
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMFileReader)
-
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMFileReader,
                                                   FileIOObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFile)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrincipal)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMFileReader,
                                                 FileIOObject)
--- a/content/base/src/nsDOMMutationObserver.cpp
+++ b/content/base/src/nsDOMMutationObserver.cpp
@@ -39,18 +39,16 @@ nsINodeList*
 nsDOMMutationRecord::RemovedNodes()
 {
   if (!mRemovedNodes) {
     mRemovedNodes = new nsSimpleContentList(mTarget);
   }
   return mRemovedNodes;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMutationRecord)
-
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMMutationRecord)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMMutationRecord)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMMutationRecord)
 
@@ -335,18 +333,16 @@ nsMutationReceiver::ContentRemoved(nsIDo
 void nsMutationReceiver::NodeWillBeDestroyed(const nsINode *aNode)
 {
   NS_ASSERTION(!mParent, "Shouldn't have mParent here!");
   Disconnect(true);
 }
 
 // Observer
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMutationObserver)
-
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMMutationObserver)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMMutationObserver)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMMutationObserver)
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1469,18 +1469,16 @@ nsDocument::~nsDocument()
   // We don't want to leave residual locks on images. Make sure we're in an
   // unlocked state, and then clear the table.
   SetImageLockingState(false);
   mImageTracker.Clear();
 
   mPlugins.Clear();
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
-
 NS_INTERFACE_TABLE_HEAD(nsDocument)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_DOCUMENT_INTERFACE_TABLE_BEGIN(nsDocument)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocument)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocumentXBL)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIScriptObjectPrincipal)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMEventTarget)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsISupportsWeakReference)
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -159,18 +159,16 @@ protected:
   // Used when context has already been serialized for
   // table cell selections (where parent is <tr>)
   bool              mDisableContextSerialize;
   bool              mIsCopying;  // Set to true only while copying
   bool              mNodeIsContainer;
   nsStringBuffer*   mCachedBuffer;
 };
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocumentEncoder)
-
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDocumentEncoder)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDocumentEncoder)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDocumentEncoder)
    NS_INTERFACE_MAP_ENTRY(nsIDocumentEncoder)
    NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -252,18 +252,16 @@ nsContentView::GetId(nsContentViewId* aI
 // does not count chrome frames when determining depth, nor does it
 // prevent chrome recursion.  Number is fairly arbitrary, but meant to
 // keep number of shells to a reasonable number on accidental recursion with a
 // small (but not 1) branching factor.  With large branching factors the number
 // of shells can rapidly become huge and run us out of memory.  To solve that,
 // we'd need to re-institute a fixed version of bug 98158.
 #define MAX_DEPTH_CONTENT_FRAMES 10
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameLoader)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFrameLoader)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildMessageManager)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameLoader)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -52,18 +52,16 @@ IsChromeProcess()
   if (!rt)
     return true;
 
   uint32_t type;
   rt->GetProcessType(&type);
   return type == nsIXULRuntime::PROCESS_TYPE_DEFAULT;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsFrameMessageManager)
-
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager)
   uint32_t count = tmp->mListeners.Length();
   for (uint32_t i = 0; i < count; i++) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mListeners[i] mListener");
     cb.NoteXPCOMChild(tmp->mListeners[i].mListener.get());
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildManagers)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -57,18 +57,16 @@ nsGenericDOMDataNode::~nsGenericDOMDataN
 {
   NS_PRECONDITION(!IsInDoc(),
                   "Please remove this from the document properly");
   if (GetParent()) {
     NS_RELEASE(mParent);
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericDOMDataNode)
-
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGenericDOMDataNode)
   nsINode::Trace(tmp, aCallback, aClosure);
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGenericDOMDataNode)
   return Element::CanSkip(tmp, aRemovingAllowed);
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -150,18 +150,16 @@ nsInProcessTabChildGlobal::Init()
   nsIURI* docURI = mOwner->OwnerDoc()->GetDocumentURI();
   if (mGlobal && NS_SUCCEEDED(mGlobal->GetJSObject(&global)) && docURI) {
     xpc::SetLocationForGlobal(global, docURI);
   }
 
   return NS_OK;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsInProcessTabChildGlobal)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsInProcessTabChildGlobal,
                                                 nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal)
   nsFrameScriptExecutor::Unlink(tmp);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsInProcessTabChildGlobal,
--- a/content/base/src/nsNodeInfo.cpp
+++ b/content/base/src/nsNodeInfo.cpp
@@ -143,17 +143,16 @@ nsNodeInfo::nsNodeInfo(nsIAtom *aName, n
       NS_ABORT_IF_FALSE(aNodeType == UINT16_MAX,
                         "Unknown node type");
   }
 }
 
 
 // nsISupports
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfo)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsNodeInfo)
 
 static const char* kNSURIs[] = {
   " ([none])",
   " (xmlns)",
   " (xml)",
   " (xhtml)",
   " (XLink)",
--- a/content/base/src/nsNodeInfoManager.cpp
+++ b/content/base/src/nsNodeInfoManager.cpp
@@ -124,18 +124,16 @@ nsNodeInfoManager::~nsNodeInfoManager()
   if (gNodeInfoManagerLeakPRLog)
     PR_LOG(gNodeInfoManagerLeakPRLog, PR_LOG_DEBUG,
            ("NODEINFOMANAGER %p destroyed", this));
 #endif
 
   nsLayoutStatics::Release();
 }
 
-
-NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsNodeInfoManager)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsNodeInfoManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsNodeInfoManager)
   if (tmp->mDocument &&
       nsCCUncollectableMarker::InGeneration(cb,
                                             tmp->mDocument->GetMarkedCCGeneration())) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
   if (tmp->mNonDocumentNodeInfos) {
--- a/content/base/src/nsNodeIterator.cpp
+++ b/content/base/src/nsNodeIterator.cpp
@@ -151,17 +151,16 @@ nsNodeIterator::~nsNodeIterator()
     if (!mDetached && mRoot)
         mRoot->RemoveMutationObserver(this);
 }
 
 /*
  * nsISupports and cycle collection stuff
  */
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeIterator)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsNodeIterator)
     if (!tmp->mDetached && tmp->mRoot)
         tmp->mRoot->RemoveMutationObserver(tmp);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFilter)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsNodeIterator)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -248,18 +248,16 @@ nsRange::CreateRange(nsIDOMNode* aStartP
   range.forget(aRange);
   return rv;
 }
 
 /******************************************************
  * nsISupports
  ******************************************************/
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsRange)
-
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsRange)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsRange)
 
 DOMCI_DATA(Range, nsRange)
 
 // QueryInterface implementation for nsRange
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsRange)
   NS_INTERFACE_MAP_ENTRY(nsIDOMRange)
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -17,16 +17,17 @@
 #include "mozilla/dom/Element.h"
 #include "nsGkAtoms.h"
 #include "nsNetUtil.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptRuntime.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
+#include "nsJSPrincipals.h"
 #include "nsContentPolicyUtils.h"
 #include "nsIHttpChannel.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsIScriptElement.h"
 #include "nsIDOMHTMLScriptElement.h"
 #include "nsIDocShell.h"
 #include "nsContentUtils.h"
 #include "nsUnicharUtils.h"
@@ -850,23 +851,28 @@ nsScriptLoader::EvaluateScript(nsScriptL
   nsCOMPtr<nsIScriptElement> oldCurrent = mCurrentScript;
   mCurrentScript = aRequest->mElement;
 
   // It's very important to use aRequest->mURI, not the final URI of the channel
   // aRequest ended up getting script data from, as the script filename.
   nsAutoCString url;
   nsContentUtils::GetWrapperSafeScriptFilename(mDocument, aRequest->mURI, url);
 
-  bool isUndefined;
-  rv = context->EvaluateString(aScript, globalObject->GetGlobalJSObject(),
-                               mDocument->NodePrincipal(),
-                               aRequest->mOriginPrincipal,
-                               url.get(), aRequest->mLineNo,
-                               JSVersion(aRequest->mJSVersion), nullptr,
-                               &isUndefined);
+  JSVersion version = JSVersion(aRequest->mJSVersion);
+  if (version != JSVERSION_UNKNOWN) {
+    JS::CompileOptions options(context->GetNativeContext());
+    options.setFileAndLine(url.get(), aRequest->mLineNo)
+           .setVersion(JSVersion(aRequest->mJSVersion));
+    if (aRequest->mOriginPrincipal) {
+      options.setOriginPrincipals(nsJSPrincipals::get(aRequest->mOriginPrincipal));
+    }
+    JS::Value ignored;
+    rv = context->EvaluateString(aScript, *globalObject->GetGlobalJSObject(),
+                                 options, /* aCoerceToString = */ false, &ignored);
+  }
 
   // Put the old script back in case it wants to do anything else.
   mCurrentScript = oldCurrent;
 
   JSContext *cx = nullptr; // Initialize this to keep GCC happy.
   cx = context->GetNativeContext();
   JSAutoRequest ar(cx);
   context->SetProcessingScriptTag(oldProcessingScriptTag);
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -333,18 +333,16 @@ XMLHttpRequestAuthPrompt::PromptPassword
                                          bool* aRetval)
 {
   *aRetval = false;
   return NS_OK;
 }
 
 /////////////////////////////////////////////
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXHREventTarget)
-
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXHREventTarget,
                                                   nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXHREventTarget,
                                                 nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
@@ -561,18 +559,16 @@ nsXMLHttpRequest::ResetResponse()
 }
 
 void
 nsXMLHttpRequest::SetRequestObserver(nsIRequestObserver* aObserver)
 {
   mRequestObserver = aObserver;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequest)
-
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsXMLHttpRequest)
   bool isBlack = tmp->IsBlack();
   if (isBlack || tmp->mWaitingForOnStopRequest) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->MarkForCC();
     }
     if (!isBlack && tmp->PreservingWrapper()) {
       xpc_UnmarkGrayObject(tmp->GetWrapperPreserveColor());
@@ -3506,25 +3502,17 @@ public:
 
     return NS_OK;
   }
 
 private:
   nsRefPtr<nsXMLHttpRequest> mXHR;
 };
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(AsyncVerifyRedirectCallbackForwarder)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AsyncVerifyRedirectCallbackForwarder)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mXHR)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AsyncVerifyRedirectCallbackForwarder)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mXHR)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_1(AsyncVerifyRedirectCallbackForwarder, mXHR)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AsyncVerifyRedirectCallbackForwarder)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(AsyncVerifyRedirectCallbackForwarder)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(AsyncVerifyRedirectCallbackForwarder)
@@ -4007,18 +3995,16 @@ nsXMLHttpProgressEvent::nsXMLHttpProgres
   mInner = aInner;
   mCurProgress = aCurrentProgress;
   mMaxProgress = aMaxProgress;
 }
 
 nsXMLHttpProgressEvent::~nsXMLHttpProgressEvent()
 {}
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpProgressEvent)
-
 DOMCI_DATA(XMLHttpProgressEvent, nsXMLHttpProgressEvent)
 
 // QueryInterface implementation for nsXMLHttpProgressEvent
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLHttpProgressEvent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMProgressEvent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEvent, nsIDOMProgressEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMProgressEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMLSProgressEvent)
@@ -4085,18 +4071,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamListener)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXMLHttpRequestXPCOMifier)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXMLHttpRequestXPCOMifier)
 
 // Can't NS_IMPL_CYCLE_COLLECTION_1 because mXHR has ambiguous
 // inheritance from nsISupports.
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequestXPCOMifier)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLHttpRequestXPCOMifier)
 if (tmp->mXHR) {
   tmp->mXHR->mXPCOMifier = nullptr;
 }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mXHR)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXMLHttpRequestXPCOMifier)
--- a/content/base/test/test_websocket_basic.html
+++ b/content/base/test/test_websocket_basic.html
@@ -119,23 +119,23 @@ function testWebSocket2() {
       is(e.data, testMessage + messageCount, "[2] Received message");
     if (messageCount % displayInterval == 1) {
       gTestElement.textContent += " " + messageCount;
     }
   };
 }
 
 /**
- * Sends 100+1 test messages, then receives them, calling forcegc() at each step.
+ * Sends testcount+1 test messages, then receives them, calling forcegc() at each step.
  */
 function testWebSocket3() {
   gTestElement.textContent = "Running testWebSocket3() [can take a little while]";
 
   const displayInterval = 10;
-  const testCount = 100;
+  const testCount = 10;
   const testMessage = "test message 3.";
 
   var messageCount = 0;
 
   ws = new WebSocket(kUrl, "test");
   // Set this before onopen() is called,
   // otherwise its display would be delayed by forcegc() calls...
   gTestElement.textContent += "\nSending :";
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -1631,19 +1631,19 @@ CanvasRenderingContext2D::BeginPath()
 {
   mPath = nullptr;
   mPathBuilder = nullptr;
   mDSPathBuilder = nullptr;
   mPathTransformWillUpdate = false;
 }
 
 void
-CanvasRenderingContext2D::Fill()
+CanvasRenderingContext2D::Fill(const CanvasWindingRule& winding)
 {
-  EnsureUserSpacePath();
+  EnsureUserSpacePath(winding);
 
   if (!mPath) {
     return;
   }
 
   mgfx::Rect bounds;
 
   if (NeedToDrawShadow()) {
@@ -1682,19 +1682,19 @@ CanvasRenderingContext2D::Stroke()
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     Stroke(mPath, CanvasGeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
            strokeOptions, DrawOptions(state.globalAlpha, UsedOperation()));
 
   Redraw();
 }
 
 void
-CanvasRenderingContext2D::Clip()
+CanvasRenderingContext2D::Clip(const CanvasWindingRule& winding)
 {
-  EnsureUserSpacePath();
+  EnsureUserSpacePath(winding);
 
   if (!mPath) {
     return;
   }
 
   mTarget->PushClip(mPath);
   CurrentState().clipsPushed.push_back(mPath);
 }
@@ -1843,19 +1843,21 @@ CanvasRenderingContext2D::EnsureWritable
     mDSPathBuilder =
       mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
     mPathTransformWillUpdate = false;
     mPath = nullptr;
   }
 }
 
 void
-CanvasRenderingContext2D::EnsureUserSpacePath()
+CanvasRenderingContext2D::EnsureUserSpacePath(const CanvasWindingRule& winding)
 {
   FillRule fillRule = CurrentState().fillRule;
+  if(winding == CanvasWindingRuleValues::Evenodd)
+    fillRule = FILL_EVEN_ODD;
 
   if (!mPath && !mPathBuilder && !mDSPathBuilder) {
     EnsureTarget();
     mPathBuilder = mTarget->CreatePathBuilder(fillRule);
   }
 
   if (mPathBuilder) {
     mPath = mPathBuilder->Finish();
@@ -2831,29 +2833,31 @@ CanvasRenderingContext2D::SetMozDashOffs
 {
   ContextState& state = CurrentState();
   if (!state.dash.IsEmpty()) {
     state.dashOffset = mozDashOffset;
   }
 }
 
 bool
-CanvasRenderingContext2D::IsPointInPath(double x, double y)
+CanvasRenderingContext2D::IsPointInPath(double x, double y, const CanvasWindingRule& winding)
 {
   if (!FloatValidate(x,y)) {
     return false;
   }
 
-  EnsureUserSpacePath();
+  EnsureUserSpacePath(winding);
   if (!mPath) {
     return false;
   }
+
   if (mPathTransformWillUpdate) {
     return mPath->ContainsPoint(Point(x, y), mPathToDS);
   }
+
   return mPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
 }
 
 bool
 CanvasRenderingContext2D::IsPointInStroke(double x, double y)
 {
   if (!FloatValidate(x,y)) {
     return false;
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -12,16 +12,17 @@
 #include "nsColor.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "nsHTMLVideoElement.h"
 #include "CanvasUtils.h"
 #include "gfxFont.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/UnionTypes.h"
+#include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 
 #define NS_CANVASGRADIENTAZURE_PRIVATE_IID \
     {0x28425a6a, 0x90e0, 0x4d42, {0x9c, 0x75, 0xff, 0x60, 0x09, 0xb3, 0x10, 0xa8}}
 #define NS_CANVASPATTERNAZURE_PRIVATE_IID \
     {0xc9bacc25, 0x28da, 0x421e, {0x9a, 0x4b, 0xbb, 0xd6, 0x93, 0x05, 0x12, 0xbc}}
 
 class nsIDOMXULElement;
 
@@ -233,20 +234,20 @@ public:
     StyleColorToString(CurrentState().shadowColor, shadowColor);
   }
 
   void SetShadowColor(const nsAString& shadowColor);
   void ClearRect(double x, double y, double w, double h);
   void FillRect(double x, double y, double w, double h);
   void StrokeRect(double x, double y, double w, double h);
   void BeginPath();
-  void Fill();
+  void Fill(const CanvasWindingRule& winding);
   void Stroke();
-  void Clip();
-  bool IsPointInPath(double x, double y);
+  void Clip(const CanvasWindingRule& winding);
+  bool IsPointInPath(double x, double y, const CanvasWindingRule& winding);
   bool IsPointInStroke(double x, double y);
   void FillText(const nsAString& text, double x, double y,
                 const mozilla::dom::Optional<double>& maxWidth,
                 mozilla::ErrorResult& error);
   void StrokeText(const nsAString& text, double x, double y,
                   const mozilla::dom::Optional<double>& maxWidth,
                   mozilla::ErrorResult& error);
   already_AddRefed<nsIDOMTextMetrics>
@@ -582,17 +583,17 @@ protected:
   /* This function ensures there is a writable pathbuilder available, this
    * pathbuilder may be working in user space or in device space or
    * device space.
    * After calling this function mPathTransformWillUpdate will be false
    */
   void EnsureWritablePath();
 
   // Ensures a path in UserSpace is available.
-  void EnsureUserSpacePath();
+  void EnsureUserSpacePath(const CanvasWindingRule& winding = CanvasWindingRuleValues::Nonzero);
 
   /**
    * Needs to be called before updating the transform. This makes a call to
    * EnsureTarget() so you don't have to.
    */
   void TransformWillUpdate();
 
   // Report the fillRule has changed.
--- a/content/canvas/src/ImageData.cpp
+++ b/content/canvas/src/ImageData.cpp
@@ -17,18 +17,16 @@ namespace dom {
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(ImageData)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(ImageData)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImageData)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(ImageData)
-
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ImageData)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mData)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ImageData)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
--- a/content/canvas/src/WebGLUniformLocation.cpp
+++ b/content/canvas/src/WebGLUniformLocation.cpp
@@ -19,24 +19,16 @@ WebGLUniformLocation::WebGLUniformLocati
     , mProgram(program)
     , mProgramGeneration(program->Generation())
     , mLocation(location)
     , mInfo(info)
 {
     mElementSize = info.ElementSize();
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(WebGLUniformLocation)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebGLUniformLocation)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mProgram)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebGLUniformLocation)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mProgram)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_1(WebGLUniformLocation, mProgram)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLUniformLocation)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLUniformLocation)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLUniformLocation)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -31,16 +31,17 @@ MOCHITEST_FILES = \
 	image_red.png \
 	image_transparent.png \
 	image_green.png \
 	image_green-redirect \
 	image_green-redirect^headers^ \
 	test_drawImageIncomplete.html \
 	test_canvas_font_setter.html \
 	test_2d.clearRect.image.offscreen.html \
+	test_2d.clip.winding.html \
 	test_2d.composite.canvas.destination-atop.html \
 	test_2d.composite.canvas.destination-in.html \
 	test_2d.composite.canvas.source-in.html \
 	test_2d.composite.canvas.source-out.html \
 	test_2d.composite.canvas.multiply.html \
 	test_2d.composite.canvas.screen.html \
 	test_2d.composite.canvas.overlay.html \
 	test_2d.composite.canvas.darken.html \
@@ -88,16 +89,18 @@ MOCHITEST_FILES = \
 	test_2d.composite.uncovered.fill.soft-light.html \
 	test_2d.composite.uncovered.fill.difference.html \
 	test_2d.composite.uncovered.fill.exclusion.html \
 	test_2d.composite.uncovered.fill.hue.html \
 	test_2d.composite.uncovered.fill.saturation.html \
 	test_2d.composite.uncovered.fill.color.html \
 	test_2d.composite.uncovered.fill.luminosity.html \
 	test_2d.drawImage.zerocanvas.html \
+	test_2d.fill.winding.html \
+	test_2d.isPointInPath.winding.html \
 	test_2d.strokeRect.zero.5.html \
 	test_toBlob.html \
 	test_toDataURL_alpha.html \
 	test_toDataURL_lowercase_ascii.html \
 	test_toDataURL_parameters.html \
 	test_mozGetAsFile.html \
 	test_canvas_strokeStyle_getter.html \
 	test_bug613794.html \
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.clip.winding.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.clip.winding</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="100"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    ok(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'rgb(255,0,0)';
+ctx.fillRect(0, 0, 100, 100);
+ctx.fillStyle = 'rgb(0,255,0)';
+ctx.beginPath();
+ctx.rect(0, 0, 100, 100);
+ctx.rect(25, 25, 50, 50);
+ctx.clip();
+ctx.beginPath();
+ctx.fillRect(0, 0, 100, 100);
+isPixel(ctx, 50,50, 0,255,0,255, "50,50", "0,255,0,255", 5);
+
+ctx.fillStyle = 'rgb(255,0,0)';
+ctx.fillRect(0, 0, 100, 100);
+ctx.fillStyle = 'rgb(0,255,0)';
+ctx.beginPath();
+ctx.rect(0, 0, 100, 100);
+ctx.rect(25, 25, 50, 50);
+ctx.clip('evenodd');
+ctx.fillRect(0, 0, 100, 100);
+isPixel(ctx, 50,50, 255,0,0,255, "50,50", "255,0,0,255", 5);
+
+SimpleTest.finish();
+
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.fill.winding.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.fill.winding</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="100"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    ok(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = 'rgb(255,0,0)';
+ctx.beginPath();
+ctx.fillRect(0, 0, 100, 100);
+ctx.fillStyle = 'rgb(0,255,0)';
+ctx.beginPath();
+ctx.rect(0, 0, 100, 100);
+ctx.rect(25, 25, 50, 50);
+ctx.fill();
+isPixel(ctx, 50,50, 0,255,0,255, "50,50", "0,255,0,255", 5);
+
+ctx.fillStyle = 'rgb(255,0,0)';
+ctx.fillRect(0, 0, 100, 100);
+ctx.fillStyle = 'rgb(0,255,0)';
+ctx.beginPath();
+ctx.rect(0, 0, 100, 100);
+ctx.rect(25, 25, 50, 50);
+ctx.fill('evenodd');
+isPixel(ctx, 50,50, 255,0,0,255, "50,50", "255,0,0,255", 5);
+
+SimpleTest.finish();
+
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.isPointInPath.winding.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.isPointInPath.winding</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="100"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.beginPath();
+ctx.rect(0, 0, 100, 100);
+ctx.rect(25, 25, 50, 50);
+ok(ctx.isPointInPath(50, 50));
+
+ctx.beginPath();
+ctx.rect(0, 0, 100, 100);
+ctx.rect(25, 25, 50, 50);
+ok(ctx.isPointInPath(50, 50, 'evenodd') == false);
+
+SimpleTest.finish();
+
+});
+</script>
+
--- a/content/events/src/nsDOMDataContainerEvent.cpp
+++ b/content/events/src/nsDOMDataContainerEvent.cpp
@@ -8,18 +8,16 @@
 
 nsDOMDataContainerEvent::nsDOMDataContainerEvent(nsPresContext *aPresContext,
                                                  nsEvent *aEvent)
   : nsDOMEvent(aPresContext, aEvent)
 {
   mData.Init();
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDataContainerEvent)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDataContainerEvent,
                                                 nsDOMEvent)
   if (tmp->mData.IsInitialized())
     tmp->mData.Clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDataContainerEvent,
                                                   nsDOMEvent)
--- a/content/events/src/nsDOMDataTransfer.cpp
+++ b/content/events/src/nsDOMDataTransfer.cpp
@@ -25,17 +25,16 @@
 #include "nsCRT.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIWebNavigation.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIScriptContext.h"
 
 using namespace mozilla;
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDataTransfer)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMDataTransfer)
   if (tmp->mFiles) {
     tmp->mFiles->Disconnect();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mFiles)
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragTarget)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragImage)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/events/src/nsDOMDeviceMotionEvent.cpp
+++ b/content/events/src/nsDOMDeviceMotionEvent.cpp
@@ -1,17 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsDOMClassInfoID.h"
 #include "nsDOMDeviceMotionEvent.h"
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDeviceMotionEvent)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDeviceMotionEvent, nsDOMEvent)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAcceleration)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAccelerationIncludingGravity)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRotationRate)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDeviceMotionEvent, nsDOMEvent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAcceleration)
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -96,18 +96,16 @@ nsDOMEvent::~nsDOMEvent()
 {
   NS_ASSERT_OWNINGTHREAD(nsDOMEvent);
 
   if (mEventIsInternal && mEvent) {
     delete mEvent;
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEvent)
-
 DOMCI_DATA(Event, nsDOMEvent)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEvent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEvent)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Event)
 NS_INTERFACE_MAP_END
--- a/content/events/src/nsDOMEventTargetHelper.cpp
+++ b/content/events/src/nsDOMEventTargetHelper.cpp
@@ -13,18 +13,16 @@
 #include "prprf.h"
 #include "nsGlobalWindow.h"
 #include "nsDOMEvent.h"
 #include "mozilla/Likely.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEventTargetHelper)
-
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDOMEventTargetHelper)
   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
     char name[512];
     nsAutoString uri;
--- a/content/events/src/nsDOMMessageEvent.cpp
+++ b/content/events/src/nsDOMMessageEvent.cpp
@@ -3,18 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsDOMMessageEvent.h"
 #include "nsContentUtils.h"
 #include "jsapi.h"
 #include "nsDOMClassInfoID.h"
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMessageEvent)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMMessageEvent, nsDOMEvent)
   if (tmp->mDataRooted) {
     tmp->UnrootData();
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSource)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMMessageEvent, nsDOMEvent)
--- a/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
+++ b/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
@@ -26,18 +26,16 @@ nsDOMNotifyAudioAvailableEvent::nsDOMNot
   MOZ_COUNT_CTOR(nsDOMNotifyAudioAvailableEvent);
   if (mEvent) {
     mEvent->message = aEventType;
   }
 }
 
 DOMCI_DATA(NotifyAudioAvailableEvent, nsDOMNotifyAudioAvailableEvent)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMNotifyAudioAvailableEvent)
-
 NS_IMPL_ADDREF_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
 NS_IMPL_RELEASE_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMNotifyAudioAvailableEvent, nsDOMEvent)
   if (tmp->mCachedArray) {
     tmp->mCachedArray = nullptr;
     NS_DROP_JS_OBJECTS(tmp, nsDOMNotifyAudioAvailableEvent);
   }
--- a/content/events/src/nsDOMTouchEvent.cpp
+++ b/content/events/src/nsDOMTouchEvent.cpp
@@ -137,30 +137,23 @@ nsDOMTouch::Equals(nsIDOMTouch* aTouch)
 // TouchList
 nsDOMTouchList::nsDOMTouchList(nsTArray<nsCOMPtr<nsIDOMTouch> > &aTouches)
 {
   mPoints.AppendElements(aTouches);
 }
 
 DOMCI_DATA(TouchList, nsDOMTouchList)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTouchList)
-
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMTouchList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMTouchList)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TouchList)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMTouchList)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPoints)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMTouchList)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mPoints)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_1(nsDOMTouchList, mPoints)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMTouchList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMTouchList)
 
 NS_IMETHODIMP
 nsDOMTouchList::GetLength(uint32_t* aLength)
 {
   *aLength = mPoints.Length();
@@ -214,18 +207,16 @@ nsDOMTouchEvent::nsDOMTouchEvent(nsPresC
 nsDOMTouchEvent::~nsDOMTouchEvent()
 {
   if (mEventIsInternal && mEvent) {
     delete static_cast<nsTouchEvent*>(mEvent);
     mEvent = nullptr;
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTouchEvent)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTouches)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTargetTouches)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChangedTouches)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTouches)
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -70,18 +70,16 @@ nsDOMUIEvent::nsDOMUIEvent(nsPresContext
     {
        nsCOMPtr<nsIDOMWindow> window = do_GetInterface(container);
        if (window)
           mView = do_QueryInterface(window);
     }
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMUIEvent)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMUIEvent, nsDOMEvent)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mView)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMUIEvent, nsDOMEvent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mView)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
--- a/content/events/src/nsDOMXULCommandEvent.cpp
+++ b/content/events/src/nsDOMXULCommandEvent.cpp
@@ -16,18 +16,16 @@ nsDOMXULCommandEvent::nsDOMXULCommandEve
     mEventIsInternal = false;
   }
   else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMXULCommandEvent)
-
 NS_IMPL_ADDREF_INHERITED(nsDOMXULCommandEvent, nsDOMUIEvent)
 NS_IMPL_RELEASE_INHERITED(nsDOMXULCommandEvent, nsDOMUIEvent)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMXULCommandEvent,
                                                 nsDOMUIEvent)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSourceEvent)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -146,18 +146,16 @@ nsEventListenerManager::RemoveAllListene
 }
 
 void
 nsEventListenerManager::Shutdown()
 {
   nsDOMEvent::Shutdown();
 }
 
-NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsEventListenerManager)
-
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsEventListenerManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsEventListenerManager, Release)
 
 inline void
 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
                             nsListenerStruct& aField,
                             const char* aName,
                             unsigned aFlags)
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -872,18 +872,16 @@ nsEventStateManager::Observe(nsISupports
     } else if (data.EqualsLiteral("dom.popup_allowed_events")) {
       nsDOMEvent::PopupAllowedEventsChanged();
     }
   }
 
   return NS_OK;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventStateManager)
-
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsEventStateManager)
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
    NS_INTERFACE_MAP_ENTRY(nsIObserver)
    NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsEventStateManager)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsEventStateManager)
--- a/content/html/content/public/nsIConstraintValidation.h
+++ b/content/html/content/public/nsIConstraintValidation.h
@@ -5,19 +5,24 @@
 
 #ifndef nsIConstraintValidition_h___
 #define nsIConstraintValidition_h___
 
 #include "nsISupports.h"
 #include "nsAutoPtr.h"
 #include "nsString.h"
 
-class nsDOMValidityState;
 class nsIDOMValidityState;
 
+namespace mozilla {
+namespace dom {
+class ValidityState;
+}
+}
+
 #define NS_ICONSTRAINTVALIDATION_IID \
 { 0xca3824dc, 0x4f5c, 0x4878, \
  { 0xa6, 0x8a, 0x95, 0x54, 0x5f, 0xfa, 0x4b, 0xf9 } }
 
 /**
  * This interface is for form elements implementing the validity constraint API.
  * See: http://dev.w3.org/html5/spec/forms.html#the-constraint-validation-api
  *
@@ -25,17 +30,17 @@ class nsIDOMValidityState;
  * and only them.
  */
 class nsIConstraintValidation : public nsISupports
 {
 public:
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONSTRAINTVALIDATION_IID);
 
-  friend class nsDOMValidityState;
+  friend class mozilla::dom::ValidityState;
 
   static const uint16_t sContentSpecifiedMaxLengthMessage;
 
   virtual ~nsIConstraintValidation();
 
   bool IsValid() const { return mValidityBitField == 0; }
 
   bool IsCandidateForConstraintValidation() const {
@@ -54,16 +59,23 @@ public:
     VALIDITY_STATE_RANGE_OVERFLOW   = 0x20, // 0b00100000
     VALIDITY_STATE_STEP_MISMATCH    = 0x40, // 0b01000000
     VALIDITY_STATE_CUSTOM_ERROR     = 0x80  // 0b10000000
   };
 
   void SetValidityState(ValidityStateType mState,
                         bool mValue);
 
+  // Web IDL binding methods
+  bool WillValidate() const {
+    return IsCandidateForConstraintValidation();
+  }
+  mozilla::dom::ValidityState* Validity();
+  bool CheckValidity();
+
 protected:
 
   // You can't instantiate an object from that class.
   nsIConstraintValidation();
 
   nsresult GetValidity(nsIDOMValidityState** aValidity);
   nsresult CheckValidity(bool* aValidity);
   void     SetCustomValidity(const nsAString& aError);
@@ -74,30 +86,31 @@ protected:
 
   void SetBarredFromConstraintValidation(bool aBarred);
 
   virtual nsresult GetValidationMessage(nsAString& aValidationMessage,
                                         ValidityStateType aType) {
                      return NS_OK;
                    }
 
+protected:
+  /**
+   * A pointer to the ValidityState object.
+   */
+  nsRefPtr<mozilla::dom::ValidityState>  mValidity;
+
 private:
 
   /**
    * A bitfield representing the current validity state of the element.
    * Each bit represent an error. All bits to zero means the element is valid.
    */
   int8_t                        mValidityBitField;
 
   /**
-   * A pointer to the ValidityState object.
-   */
-  nsRefPtr<nsDOMValidityState>  mValidity;
-
-  /**
    * Keeps track whether the element is barred from constraint validation.
    */
   bool                          mBarredFromConstraintValidation;
 
   /**
    * The string representing the custom error.
    */
   nsString                      mCustomValidity;
@@ -106,42 +119,43 @@ private:
 /**
  * Use these macro for class inheriting from nsIConstraintValidation to forward
  * functions to nsIConstraintValidation.
  */
 #define NS_FORWARD_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY           \
   NS_IMETHOD GetValidity(nsIDOMValidityState** aValidity) {                   \
     return nsIConstraintValidation::GetValidity(aValidity);                   \
   }                                                                           \
-  NS_IMETHOD GetWillValidate(bool* aWillValidate) {                         \
-    *aWillValidate = IsCandidateForConstraintValidation();                    \
+  NS_IMETHOD GetWillValidate(bool* aWillValidate) {                           \
+    *aWillValidate = WillValidate();                                          \
     return NS_OK;                                                             \
   }                                                                           \
   NS_IMETHOD GetValidationMessage(nsAString& aValidationMessage) {            \
     return nsIConstraintValidation::GetValidationMessage(aValidationMessage); \
   }                                                                           \
-  NS_IMETHOD CheckValidity(bool* aValidity) {                               \
+  using nsIConstraintValidation::CheckValidity;                               \
+  NS_IMETHOD CheckValidity(bool* aValidity) {                                 \
     return nsIConstraintValidation::CheckValidity(aValidity);                 \
   }
 
 #define NS_FORWARD_NSICONSTRAINTVALIDATION                                    \
   NS_FORWARD_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY                 \
   NS_IMETHOD SetCustomValidity(const nsAString& aError) {                     \
     nsIConstraintValidation::SetCustomValidity(aError);                       \
     return NS_OK;                                                             \
   }
 
 
 /* Use these macro when class declares functions from nsIConstraintValidation */
 #define NS_IMPL_NSICONSTRAINTVALIDATION_EXCEPT_SETCUSTOMVALIDITY(_from)       \
   NS_IMETHODIMP _from::GetValidity(nsIDOMValidityState** aValidity) {         \
     return nsIConstraintValidation::GetValidity(aValidity);                   \
   }                                                                           \
-  NS_IMETHODIMP _from::GetWillValidate(bool* aWillValidate) {               \
-    *aWillValidate = IsCandidateForConstraintValidation();                    \
+  NS_IMETHODIMP _from::GetWillValidate(bool* aWillValidate) {                 \
+    *aWillValidate = WillValidate();                                          \
     return NS_OK;                                                             \
   }                                                                           \
   NS_IMETHODIMP _from::GetValidationMessage(nsAString& aValidationMessage) {  \
     return nsIConstraintValidation::GetValidationMessage(aValidationMessage); \
   }                                                                           \
   NS_IMETHODIMP _from::CheckValidity(bool* aValidity) {                     \
     return nsIConstraintValidation::CheckValidity(aValidity);                 \
   }
--- a/content/html/content/src/HTMLCanvasElement.cpp
+++ b/content/html/content/src/HTMLCanvasElement.cpp
@@ -141,42 +141,31 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(HTMLCanv
 NS_IMPL_CYCLE_COLLECTING_RELEASE(HTMLCanvasPrintState)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(HTMLCanvasPrintState)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozCanvasPrintState)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozCanvasPrintState)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLCanvasPrintState)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(HTMLCanvasPrintState)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCanvas)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_3(HTMLCanvasPrintState, mCanvas, mContext, mCallback)
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HTMLCanvasPrintState)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCanvas)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 // ---------------------------------------------------------------------------
 
 HTMLCanvasElement::HTMLCanvasElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo), 
     mWriteOnly(false)
 {
 }
 
 HTMLCanvasElement::~HTMLCanvasElement()
 {
   ResetPrintCallback();
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLCanvasElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLCanvasElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrintCallback)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrintState)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOriginalCanvas)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
--- a/content/html/content/src/HTMLDataListElement.cpp
+++ b/content/html/content/src/HTMLDataListElement.cpp
@@ -23,17 +23,16 @@ HTMLDataListElement::WrapNode(JSContext 
   return HTMLDataListElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
 }
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLDataListElement,
                                                 nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOptions)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLDataListElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLDataListElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOptions)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLDataListElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLDataListElement, Element)
 
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/HTMLObjectElement.cpp
@@ -0,0 +1,557 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:set et sw=2 sts=2 cin:
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/Util.h"
+
+#include "nsAutoPtr.h"
+#include "nsGenericHTMLElement.h"
+#include "nsAttrValueInlines.h"
+#include "nsObjectLoadingContent.h"
+#include "nsGkAtoms.h"
+#include "nsError.h"
+#include "nsIDocument.h"
+#include "nsIPluginDocument.h"
+#include "nsIDOMDocument.h"
+#include "nsIDOMSVGDocument.h"
+#include "nsIDOMGetSVGDocument.h"
+#include "nsIDOMHTMLObjectElement.h"
+#include "nsFormSubmission.h"
+#include "nsIObjectFrame.h"
+#include "nsNPAPIPluginInstance.h"
+#include "nsIConstraintValidation.h"
+#include "nsIWidget.h"
+
+namespace mozilla {
+namespace dom {
+
+class HTMLObjectElement MOZ_FINAL : public nsGenericHTMLFormElement
+                                  , public nsObjectLoadingContent
+                                  , public nsIDOMHTMLObjectElement
+                                  , public nsIConstraintValidation
+                                  , public nsIDOMGetSVGDocument
+{
+public:
+  using nsIConstraintValidation::GetValidationMessage;
+
+  HTMLObjectElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                    FromParser aFromParser = NOT_FROM_PARSER);
+  virtual ~HTMLObjectElement();
+
+  // nsISupports
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // nsIDOMNode
+  NS_FORWARD_NSIDOMNODE_TO_NSINODE
+
+  // nsIDOMElement
+  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
+
+  // nsIDOMHTMLElement
+  NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
+
+  virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
+
+  // nsIDOMHTMLObjectElement
+  NS_DECL_NSIDOMHTMLOBJECTELEMENT
+
+  // nsIDOMGetSVGDocument
+  NS_DECL_NSIDOMGETSVGDOCUMENT
+
+  virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
+                              nsIContent *aBindingParent,
+                              bool aCompileEventHandlers);
+  virtual void UnbindFromTree(bool aDeep = true,
+                              bool aNullParent = true);
+  virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom *aName,
+                           nsIAtom *aPrefix, const nsAString &aValue,
+                           bool aNotify);
+  virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
+                             bool aNotify);
+
+  virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex);
+  virtual IMEState GetDesiredIMEState();
+
+  // Overriden nsIFormControl methods
+  NS_IMETHOD_(uint32_t) GetType() const
+  {
+    return NS_FORM_OBJECT;
+  }
+
+  NS_IMETHOD Reset();
+  NS_IMETHOD SubmitNamesValues(nsFormSubmission *aFormSubmission);
+
+  virtual bool IsDisabled() const { return false; }
+
+  virtual void DoneAddingChildren(bool aHaveNotified);
+  virtual bool IsDoneAddingChildren();
+
+  virtual bool ParseAttribute(int32_t aNamespaceID,
+                                nsIAtom *aAttribute,
+                                const nsAString &aValue,
+                                nsAttrValue &aResult);
+  virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
+  NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom *aAttribute) const;
+  virtual nsEventStates IntrinsicState() const;
+  virtual void DestroyContent();
+
+  // nsObjectLoadingContent
+  virtual uint32_t GetCapabilities() const;
+
+  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  nsresult CopyInnerTo(Element* aDest);
+
+  void StartObjectLoad() { StartObjectLoad(true); }
+
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLObjectElement,
+                                                     nsGenericHTMLFormElement)
+
+  virtual nsXPCClassInfo* GetClassInfo();
+
+  virtual nsIDOMNode* AsDOMNode() { return this; }
+private:
+  /**
+   * Calls LoadObject with the correct arguments to start the plugin load.
+   */
+  NS_HIDDEN_(void) StartObjectLoad(bool aNotify);
+
+  /**
+   * Returns if the element is currently focusable regardless of it's tabindex
+   * value. This is used to know the default tabindex value.
+   */
+  bool IsFocusableForTabIndex();
+  
+  virtual void GetItemValueText(nsAString& text);
+  virtual void SetItemValueText(const nsAString& text);
+
+  bool mIsDoneAddingChildren;
+};
+
+HTMLObjectElement::HTMLObjectElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                                     FromParser aFromParser)
+  : nsGenericHTMLFormElement(aNodeInfo),
+    mIsDoneAddingChildren(!aFromParser)
+{
+  RegisterFreezableElement();
+  SetIsNetworkCreated(aFromParser == FROM_PARSER_NETWORK);
+
+  // <object> is always barred from constraint validation.
+  SetBarredFromConstraintValidation(true);
+
+  // By default we're in the loading state
+  AddStatesSilently(NS_EVENT_STATE_LOADING);
+}
+
+HTMLObjectElement::~HTMLObjectElement()
+{
+  UnregisterFreezableElement();
+  DestroyImageLoadingContent();
+}
+
+bool
+HTMLObjectElement::IsDoneAddingChildren()
+{
+  return mIsDoneAddingChildren;
+}
+
+void
+HTMLObjectElement::DoneAddingChildren(bool aHaveNotified)
+{
+  mIsDoneAddingChildren = true;
+
+  // If we're already in a document, we need to trigger the load
+  // Otherwise, BindToTree takes care of that.
+  if (IsInDoc()) {
+    StartObjectLoad(aHaveNotified);
+  }
+}
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLObjectElement,
+                                                  nsGenericHTMLFormElement)
+  nsObjectLoadingContent::Traverse(tmp, cb);
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_ADDREF_INHERITED(HTMLObjectElement, Element)
+NS_IMPL_RELEASE_INHERITED(HTMLObjectElement, Element)
+
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLObjectElement)
+  NS_HTML_CONTENT_INTERFACE_TABLE_BEGIN(HTMLObjectElement)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, nsIDOMHTMLObjectElement)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, imgINotificationObserver)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, nsIRequestObserver)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, nsIStreamListener)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, nsIFrameLoaderOwner)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, nsIObjectLoadingContent)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, nsIImageLoadingContent)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, imgIOnloadBlocker)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, nsIInterfaceRequestor)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, nsIChannelEventSink)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, nsIConstraintValidation)
+    NS_INTERFACE_TABLE_ENTRY(HTMLObjectElement, nsIDOMGetSVGDocument)
+  NS_OFFSET_AND_INTERFACE_TABLE_END
+  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLObjectElement,
+                                               nsGenericHTMLFormElement)
+NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLObjectElement)
+
+NS_IMPL_ELEMENT_CLONE(HTMLObjectElement)
+
+// nsIConstraintValidation
+NS_IMPL_NSICONSTRAINTVALIDATION(HTMLObjectElement)
+
+NS_IMETHODIMP
+HTMLObjectElement::GetForm(nsIDOMHTMLFormElement **aForm)
+{
+  return nsGenericHTMLFormElement::GetForm(aForm);
+}
+
+void
+HTMLObjectElement::GetItemValueText(nsAString& aValue)
+{
+  GetData(aValue);
+}
+
+void
+HTMLObjectElement::SetItemValueText(const nsAString& aValue)
+{
+  SetData(aValue);
+}
+
+nsresult
+HTMLObjectElement::BindToTree(nsIDocument *aDocument,
+                              nsIContent *aParent,
+                              nsIContent *aBindingParent,
+                              bool aCompileEventHandlers)
+{
+  nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
+                                                     aBindingParent,
+                                                     aCompileEventHandlers);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = nsObjectLoadingContent::BindToTree(aDocument, aParent,
+                                          aBindingParent,
+                                          aCompileEventHandlers);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Don't kick off load from being bound to a plugin document - the plugin
+  // document will call nsObjectLoadingContent::InitializeFromChannel() for the
+  // initial load.
+  nsCOMPtr<nsIPluginDocument> pluginDoc = do_QueryInterface(aDocument);
+
+  // If we already have all the children, start the load.
+  if (mIsDoneAddingChildren && !pluginDoc) {
+    void (HTMLObjectElement::*start)() = &HTMLObjectElement::StartObjectLoad;
+    nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this, start));
+  }
+
+  return NS_OK;
+}
+
+void
+HTMLObjectElement::UnbindFromTree(bool aDeep,
+                                  bool aNullParent)
+{
+  nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent);
+  nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
+}
+
+
+
+nsresult
+HTMLObjectElement::SetAttr(int32_t aNameSpaceID, nsIAtom *aName,
+                           nsIAtom *aPrefix, const nsAString &aValue,
+                           bool aNotify)
+{
+  nsresult rv = nsGenericHTMLFormElement::SetAttr(aNameSpaceID, aName, aPrefix,
+                                                  aValue, aNotify);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // if aNotify is false, we are coming from the parser or some such place;
+  // we'll get bound after all the attributes have been set, so we'll do the
+  // object load from BindToTree/DoneAddingChildren.
+  // Skip the LoadObject call in that case.
+  // We also don't want to start loading the object when we're not yet in
+  // a document, just in case that the caller wants to set additional
+  // attributes before inserting the node into the document.
+  if (aNotify && IsInDoc() && mIsDoneAddingChildren &&
+      aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::data) {
+    return LoadObject(aNotify, true);
+  }
+
+  return NS_OK;
+}
+
+nsresult
+HTMLObjectElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
+                             bool aNotify)
+{
+  nsresult rv = nsGenericHTMLFormElement::UnsetAttr(aNameSpaceID,
+                                                    aAttribute, aNotify);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // See comment in SetAttr
+  if (aNotify && IsInDoc() && mIsDoneAddingChildren &&
+      aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::data) {
+    return LoadObject(aNotify, true);
+  }
+
+  return NS_OK;
+}
+
+bool
+HTMLObjectElement::IsFocusableForTabIndex()
+{
+  nsIDocument* doc = GetCurrentDoc();
+  if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
+    return false;
+  }
+
+  return IsEditableRoot() ||
+         (Type() == eType_Document &&
+          nsContentUtils::IsSubDocumentTabbable(this));
+}
+
+bool
+HTMLObjectElement::IsHTMLFocusable(bool aWithMouse,
+                                   bool *aIsFocusable, int32_t *aTabIndex)
+{
+  // TODO: this should probably be managed directly by IsHTMLFocusable.
+  // See bug 597242.
+  nsIDocument *doc = GetCurrentDoc();
+  if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
+    if (aTabIndex) {
+      GetTabIndex(aTabIndex);
+    }
+
+    *aIsFocusable = false;
+
+    return false;
+  }
+
+  // This method doesn't call nsGenericHTMLFormElement intentionally.
+  // TODO: It should probably be changed when bug 597242 will be fixed.
+  if (Type() == eType_Plugin || IsEditableRoot() ||
+      (Type() == eType_Document && nsContentUtils::IsSubDocumentTabbable(this))) {
+    // Has plugin content: let the plugin decide what to do in terms of
+    // internal focus from mouse clicks
+    if (aTabIndex) {
+      GetTabIndex(aTabIndex);
+    }
+
+    *aIsFocusable = true;
+
+    return false;
+  }
+
+  // TODO: this should probably be managed directly by IsHTMLFocusable.
+  // See bug 597242.
+  const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::tabindex);
+
+  *aIsFocusable = attrVal && attrVal->Type() == nsAttrValue::eInteger;
+
+  if (aTabIndex && *aIsFocusable) {
+    *aTabIndex = attrVal->GetIntegerValue();
+  }
+
+  return false;
+}
+
+nsIContent::IMEState
+HTMLObjectElement::GetDesiredIMEState()
+{
+  if (Type() == eType_Plugin) {
+    return IMEState(IMEState::PLUGIN);
+  }
+   
+  return nsGenericHTMLFormElement::GetDesiredIMEState();
+}
+
+NS_IMETHODIMP
+HTMLObjectElement::Reset()
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HTMLObjectElement::SubmitNamesValues(nsFormSubmission *aFormSubmission)
+{
+  nsAutoString name;
+  if (!GetAttr(kNameSpaceID_None, nsGkAtoms::name, name)) {
+    // No name, don't submit.
+
+    return NS_OK;
+  }
+
+  nsIFrame* frame = GetPrimaryFrame();
+
+  nsIObjectFrame *objFrame = do_QueryFrame(frame);
+  if (!objFrame) {
+    // No frame, nothing to submit.
+
+    return NS_OK;
+  }
+
+  nsRefPtr<nsNPAPIPluginInstance> pi;
+  objFrame->GetPluginInstance(getter_AddRefs(pi));
+  if (!pi)
+    return NS_OK;
+
+  nsAutoString value;
+  nsresult rv = pi->GetFormValue(value);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return aFormSubmission->AddNameValuePair(name, value);
+}
+
+NS_IMPL_STRING_ATTR(HTMLObjectElement, Align, align)
+NS_IMPL_STRING_ATTR(HTMLObjectElement, Archive, archive)
+NS_IMPL_STRING_ATTR(HTMLObjectElement, Border, border)
+NS_IMPL_URI_ATTR_WITH_BASE(HTMLObjectElement, Code, code, codebase)
+NS_IMPL_URI_ATTR(HTMLObjectElement, CodeBase, codebase)
+NS_IMPL_STRING_ATTR(HTMLObjectElement, CodeType, codetype)
+NS_IMPL_URI_ATTR_WITH_BASE(HTMLObjectElement, Data, data, codebase)
+NS_IMPL_BOOL_ATTR(HTMLObjectElement, Declare, declare)
+NS_IMPL_STRING_ATTR(HTMLObjectElement, Height, height)
+NS_IMPL_INT_ATTR(HTMLObjectElement, Hspace, hspace)
+NS_IMPL_STRING_ATTR(HTMLObjectElement, Name, name)
+NS_IMPL_STRING_ATTR(HTMLObjectElement, Standby, standby)
+NS_IMPL_STRING_ATTR(HTMLObjectElement, Type, type)
+NS_IMPL_STRING_ATTR(HTMLObjectElement, UseMap, usemap)
+NS_IMPL_INT_ATTR(HTMLObjectElement, Vspace, vspace)
+NS_IMPL_STRING_ATTR(HTMLObjectElement, Width, width)
+
+int32_t
+HTMLObjectElement::TabIndexDefault()
+{
+  return IsFocusableForTabIndex() ? 0 : -1;
+}
+
+NS_IMETHODIMP
+HTMLObjectElement::GetContentDocument(nsIDOMDocument **aContentDocument)
+{
+  NS_ENSURE_ARG_POINTER(aContentDocument);
+
+  *aContentDocument = nullptr;
+
+  if (!IsInDoc()) {
+    return NS_OK;
+  }
+
+  // XXXbz should this use GetCurrentDoc()?  sXBL/XBL2 issue!
+  nsIDocument *sub_doc = OwnerDoc()->GetSubDocumentFor(this);
+  if (!sub_doc) {
+    return NS_OK;
+  }
+
+  return CallQueryInterface(sub_doc, aContentDocument);
+}
+
+NS_IMETHODIMP
+HTMLObjectElement::GetSVGDocument(nsIDOMDocument **aResult)
+{
+  return GetContentDocument(aResult);
+}
+
+bool
+HTMLObjectElement::ParseAttribute(int32_t aNamespaceID,
+                                  nsIAtom *aAttribute,
+                                  const nsAString &aValue,
+                                  nsAttrValue &aResult)
+{
+  if (aNamespaceID == kNameSpaceID_None) {
+    if (aAttribute == nsGkAtoms::align) {
+      return ParseAlignValue(aValue, aResult);
+    }
+    if (ParseImageAttribute(aAttribute, aValue, aResult)) {
+      return true;
+    }
+  }
+
+  return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
+                                                  aValue, aResult);
+}
+
+static void
+MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
+                      nsRuleData *aData)
+{
+  nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aData);
+  nsGenericHTMLFormElement::MapImageMarginAttributeInto(aAttributes, aData);
+  nsGenericHTMLFormElement::MapImageSizeAttributesInto(aAttributes, aData);
+  nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aData);
+}
+
+NS_IMETHODIMP_(bool)
+HTMLObjectElement::IsAttributeMapped(const nsIAtom *aAttribute) const
+{
+  static const MappedAttributeEntry* const map[] = {
+    sCommonAttributeMap,
+    sImageMarginSizeAttributeMap,
+    sImageBorderAttributeMap,
+    sImageAlignAttributeMap,
+  };
+
+  return FindAttributeDependence(aAttribute, map);
+}
+
+
+nsMapRuleToAttributesFunc
+HTMLObjectElement::GetAttributeMappingFunction() const
+{
+  return &MapAttributesIntoRule;
+}
+
+void
+HTMLObjectElement::StartObjectLoad(bool aNotify)
+{
+  // BindToTree can call us asynchronously, and we may be removed from the tree
+  // in the interim
+  if (!IsInDoc() || !OwnerDoc()->IsActive()) {
+    return;
+  }
+
+  LoadObject(aNotify);
+  SetIsNetworkCreated(false);
+}
+
+nsEventStates
+HTMLObjectElement::IntrinsicState() const
+{
+  return nsGenericHTMLFormElement::IntrinsicState() | ObjectState();
+}
+
+uint32_t
+HTMLObjectElement::GetCapabilities() const
+{
+  return nsObjectLoadingContent::GetCapabilities() | eSupportClassID;
+}
+
+void
+HTMLObjectElement::DestroyContent()
+{
+  nsObjectLoadingContent::DestroyContent();
+  nsGenericHTMLFormElement::DestroyContent();
+}
+
+nsresult
+HTMLObjectElement::CopyInnerTo(Element* aDest)
+{
+  nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (aDest->OwnerDoc()->IsStaticDocument()) {
+    CreateStaticClone(static_cast<HTMLObjectElement*>(aDest));
+  }
+
+  return rv;
+}
+
+} // namespace dom
+} // namespace mozilla
+
+DOMCI_NODE_DATA(HTMLObjectElement, mozilla::dom::HTMLObjectElement)
+
+NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Object)
--- a/content/html/content/src/HTMLPropertiesCollection.cpp
+++ b/content/html/content/src/HTMLPropertiesCollection.cpp
@@ -23,17 +23,16 @@ namespace dom {
 static PLDHashOperator
 TraverseNamedProperties(const nsAString& aKey, PropertyNodeList* aEntry, void* aData)
 {
   nsCycleCollectionTraversalCallback* cb = static_cast<nsCycleCollectionTraversalCallback*>(aData);
   cb->NoteXPCOMChild(static_cast<nsINodeList*>(aEntry));
   return PL_DHASH_NEXT;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLPropertiesCollection)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HTMLPropertiesCollection)
   // SetDocument(nullptr) ensures that we remove ourselves as a mutation observer
   tmp->SetDocument(nullptr);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNames)
   tmp->mNamedItemEntries.Clear();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mProperties)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
@@ -413,17 +412,16 @@ PropertyNodeList::GetParentObject()
 }
 
 JSObject*
 PropertyNodeList::WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap)
 {
   return PropertyNodeListBinding::Wrap(cx, scope, this, triedToWrap);
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(PropertyNodeList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PropertyNodeList)
   // SetDocument(nullptr) ensures that we remove ourselves as a mutation observer
   tmp->SetDocument(nullptr);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCollection)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mElements)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -524,23 +522,17 @@ PropertyNodeList::EnsureFresh()
   }
 }
 
 PropertyStringList::PropertyStringList(HTMLPropertiesCollection* aCollection)
   : nsDOMStringList()
   , mCollection(aCollection)
 { }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(PropertyStringList)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PropertyStringList)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCollection)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PropertyStringList)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCollection)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_1(PropertyStringList, mCollection)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(PropertyStringList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(PropertyStringList)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PropertyStringList)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDOMStringList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMStringList)
--- a/content/html/content/src/HTMLTableElement.cpp
+++ b/content/html/content/src/HTMLTableElement.cpp
@@ -78,17 +78,16 @@ TableRowsCollection::TableRowsCollection
 TableRowsCollection::~TableRowsCollection()
 {
   // we do NOT have a ref-counted reference to mParent, so do NOT
   // release it!  this is to avoid circular references.  The
   // instantiator who provided mParent is responsible for managing our
   // reference for us.
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(TableRowsCollection)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TableRowsCollection)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOrphanRows)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TableRowsCollection)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOrphanRows)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -322,17 +321,16 @@ HTMLTableElement::~HTMLTableElement()
 }
 
 JSObject*
 HTMLTableElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
 {
   return HTMLTableElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLTableElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLTableElement, nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTBodies)
   if (tmp->mRows) {
     tmp->mRows->ParentDestroyed();
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRows)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLTableElement,
--- a/content/html/content/src/HTMLTableRowElement.cpp
+++ b/content/html/content/src/HTMLTableRowElement.cpp
@@ -21,17 +21,16 @@ namespace dom {
 
 JSObject*
 HTMLTableRowElement::WrapNode(JSContext *aCx, JSObject *aScope,
                               bool *aTriedToWrap)
 {
   return HTMLTableRowElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLTableRowElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLTableRowElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCells)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableRowElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableRowElement, Element)
 
--- a/content/html/content/src/HTMLTableSectionElement.cpp
+++ b/content/html/content/src/HTMLTableSectionElement.cpp
@@ -22,17 +22,16 @@ namespace dom {
 
 JSObject*
 HTMLTableSectionElement::WrapNode(JSContext *aCx, JSObject *aScope,
                                   bool *aTriedToWrap)
 {
   return HTMLTableSectionElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLTableSectionElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLTableSectionElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRows)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLTableSectionElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLTableSectionElement, Element)
 
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -49,16 +49,17 @@ EXPORTS_mozilla/dom = \
 		HTMLTableCellElement.h \
 		HTMLTableColElement.h \
 		HTMLTableElement.h \
 		HTMLTableRowElement.h \
 		HTMLTableSectionElement.h \
 		HTMLTitleElement.h \
 		HTMLUnknownElement.h \
 		UndoManager.h \
+		ValidityState.h \
 		$(NULL)
 
 CPPSRCS		= \
 		HTMLPropertiesCollection.cpp \
 		nsClientRect.cpp \
 		nsHTMLDNSPrefetch.cpp \
 		nsGenericHTMLElement.cpp \
 		nsGenericHTMLFrameElement.cpp \
@@ -88,17 +89,17 @@ CPPSRCS		= \
 		nsHTMLLegendElement.cpp \
 		nsHTMLLinkElement.cpp \
 		nsHTMLMapElement.cpp \
 		nsHTMLMenuElement.cpp \
 		nsHTMLMenuItemElement.cpp \
 		nsHTMLMetaElement.cpp \
 		nsHTMLMeterElement.cpp \
 		nsHTMLModElement.cpp \
-		nsHTMLObjectElement.cpp \
+		HTMLObjectElement.cpp \
 		nsHTMLSharedObjectElement.cpp \
 		nsHTMLOptionElement.cpp \
 		nsHTMLOptGroupElement.cpp \
 		nsHTMLOutputElement.cpp \
 		HTMLParagraphElement.cpp \
 		HTMLPreElement.cpp \
 		nsHTMLProgressElement.cpp \
 		HTMLScriptElement.cpp \
@@ -111,17 +112,17 @@ CPPSRCS		= \
 		HTMLTableCaptionElement.cpp \
 		HTMLTableCellElement.cpp \
 		HTMLTableColElement.cpp \
 		HTMLTableRowElement.cpp \
 		HTMLTableSectionElement.cpp \
 		nsHTMLTextAreaElement.cpp \
 		HTMLTitleElement.cpp \
 		HTMLUnknownElement.cpp \
-		nsDOMValidityState.cpp \
+		ValidityState.cpp \
 		nsIConstraintValidation.cpp \
 		nsRadioVisitor.cpp \
 		nsDOMStringMap.cpp \
 		UndoManager.cpp \
 		$(NULL)
 
 ifdef MOZ_MEDIA
 CPPSRCS		+= \
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/ValidityState.cpp
@@ -0,0 +1,107 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/ValidityState.h"
+#include "mozilla/dom/ValidityStateBinding.h"
+
+#include "nsDOMClassInfoID.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsContentUtils.h"
+
+DOMCI_DATA(ValidityState, mozilla::dom::ValidityState)
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(ValidityState)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ValidityState)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ValidityState)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ValidityState)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsIDOMValidityState)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMValidityState)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ValidityState)
+NS_INTERFACE_MAP_END
+
+ValidityState::ValidityState(nsIConstraintValidation* aConstraintValidation)
+  : mConstraintValidation(aConstraintValidation)
+{
+  SetIsDOMBinding();
+}
+
+NS_IMETHODIMP
+ValidityState::GetValueMissing(bool* aValueMissing)
+{
+  *aValueMissing = ValueMissing();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ValidityState::GetTypeMismatch(bool* aTypeMismatch)
+{
+  *aTypeMismatch = TypeMismatch();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ValidityState::GetPatternMismatch(bool* aPatternMismatch)
+{
+  *aPatternMismatch = PatternMismatch();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ValidityState::GetTooLong(bool* aTooLong)
+{
+  *aTooLong = TooLong();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ValidityState::GetRangeUnderflow(bool* aRangeUnderflow)
+{
+  *aRangeUnderflow = RangeUnderflow();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ValidityState::GetRangeOverflow(bool* aRangeOverflow)
+{
+  *aRangeOverflow = RangeOverflow();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ValidityState::GetStepMismatch(bool* aStepMismatch)
+{
+  *aStepMismatch = StepMismatch();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ValidityState::GetCustomError(bool* aCustomError)
+{
+  *aCustomError = CustomError();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ValidityState::GetValid(bool* aValid)
+{
+  *aValid = Valid();
+  return NS_OK;
+}
+
+JSObject*
+ValidityState::WrapObject(JSContext* aCx, JSObject* aScope,
+                          bool* aTriedToWrap)
+{
+  return ValidityStateBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
+} // namespace dom
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/ValidityState.h
@@ -0,0 +1,104 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_ValidityState_h
+#define mozilla_dom_ValidityState_h
+
+#include "nsIDOMValidityState.h"
+#include "nsIConstraintValidation.h"
+#include "nsWrapperCache.h"
+
+struct JSObject;
+struct JSContext;
+
+namespace mozilla {
+namespace dom {
+
+class ValidityState MOZ_FINAL : public nsIDOMValidityState,
+                                public nsWrapperCache
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ValidityState)
+  NS_DECL_NSIDOMVALIDITYSTATE
+
+  friend class ::nsIConstraintValidation;
+
+  nsIConstraintValidation* GetParentObject() const {
+    return mConstraintValidation;
+  }
+
+  virtual JSObject* WrapObject(JSContext *aCx, JSObject *aScope,
+                               bool *aTriedToWrap) MOZ_OVERRIDE;
+
+  // Web IDL methods
+  bool ValueMissing() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_VALUE_MISSING);
+  }
+  bool TypeMismatch() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TYPE_MISMATCH);
+  }
+  bool PatternMismatch() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_PATTERN_MISMATCH);
+  }
+  bool TooLong() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TOO_LONG);
+  }
+  bool RangeUnderflow() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_UNDERFLOW);
+  }
+  bool RangeOverflow() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_OVERFLOW);
+  }
+  bool StepMismatch() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_STEP_MISMATCH);
+  }
+  bool CustomError() const
+  {
+    return GetValidityState(nsIConstraintValidation::VALIDITY_STATE_CUSTOM_ERROR);
+  }
+  bool Valid() const
+  {
+    return !mConstraintValidation || mConstraintValidation->IsValid();
+  }
+
+protected:
+  ValidityState(nsIConstraintValidation* aConstraintValidation);
+
+  /**
+   * This function should be called by nsIConstraintValidation
+   * to set mConstraintValidation to null to be sure
+   * it will not be used when the object is destroyed.
+   */
+  inline void Disconnect()
+  {
+    mConstraintValidation = nullptr;
+  }
+
+  /**
+   * Helper function to get a validity state from constraint validation instance.
+   */
+  inline bool GetValidityState(nsIConstraintValidation::ValidityStateType aState) const
+  {
+    return mConstraintValidation &&
+           mConstraintValidation->GetValidityState(aState);
+  }
+
+  // Weak reference to owner which will call Disconnect() when being destroyed.
+  nsIConstraintValidation*       mConstraintValidation;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_ValidityState_h
+
--- a/content/html/content/src/nsDOMStringMap.cpp
+++ b/content/html/content/src/nsDOMStringMap.cpp
@@ -9,17 +9,16 @@
 
 #include "nsGenericHTMLElement.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/DOMStringMapBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMStringMap)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStringMap)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMStringMap)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   // Check that mElement exists in case the unlink code is run more than once.
   if (tmp->mElement) {
deleted file mode 100644
--- a/content/html/content/src/nsDOMValidityState.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsDOMValidityState.h"
-
-#include "nsDOMClassInfoID.h"
-
-
-DOMCI_DATA(ValidityState, nsDOMValidityState)
-
-NS_IMPL_ADDREF(nsDOMValidityState)
-NS_IMPL_RELEASE(nsDOMValidityState)
-
-NS_INTERFACE_MAP_BEGIN(nsDOMValidityState)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMValidityState)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMValidityState)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ValidityState)
-NS_INTERFACE_MAP_END
-
-nsDOMValidityState::nsDOMValidityState(nsIConstraintValidation* aConstraintValidation)
-  : mConstraintValidation(aConstraintValidation)
-{
-}
-
-NS_IMETHODIMP
-nsDOMValidityState::GetValueMissing(bool* aValueMissing)
-{
-  *aValueMissing = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_VALUE_MISSING);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMValidityState::GetTypeMismatch(bool* aTypeMismatch)
-{
-  *aTypeMismatch = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TYPE_MISMATCH);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMValidityState::GetPatternMismatch(bool* aPatternMismatch)
-{
-  *aPatternMismatch = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_PATTERN_MISMATCH);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMValidityState::GetTooLong(bool* aTooLong)
-{
-  *aTooLong = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_TOO_LONG);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMValidityState::GetRangeUnderflow(bool* aRangeUnderflow)
-{
-  *aRangeUnderflow = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_UNDERFLOW);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMValidityState::GetRangeOverflow(bool* aRangeOverflow)
-{
-  *aRangeOverflow = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_RANGE_OVERFLOW);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMValidityState::GetStepMismatch(bool* aStepMismatch)
-{
-  *aStepMismatch = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_STEP_MISMATCH);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMValidityState::GetCustomError(bool* aCustomError)
-{
-  *aCustomError = GetValidityState(nsIConstraintValidation::VALIDITY_STATE_CUSTOM_ERROR);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMValidityState::GetValid(bool* aValid)
-{
-  *aValid = !mConstraintValidation || mConstraintValidation->IsValid();
-  return NS_OK;
-}
-
deleted file mode 100644
--- a/content/html/content/src/nsDOMValidityState.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsDOMValidityState_h__
-#define nsDOMValidityState_h__
-
-#include "nsIDOMValidityState.h"
-#include "nsIConstraintValidation.h"
-
-
-class nsDOMValidityState MOZ_FINAL : public nsIDOMValidityState
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOMVALIDITYSTATE
-
-  friend class nsIConstraintValidation;
-
-protected:
-  nsDOMValidityState(nsIConstraintValidation* aConstraintValidation);
-
-  /**
-   * This function should be called by nsIConstraintValidation
-   * to set mConstraintValidation to null to be sure
-   * it will not be used when the object is destroyed.
-   */
-  inline void Disconnect()
-  {
-    mConstraintValidation = nullptr;
-  }
-
-  /**
-   * Helper function to get a validity state from constraint validation instance.
-   */
-  inline bool GetValidityState(nsIConstraintValidation::ValidityStateType aState) const
-  {
-    return mConstraintValidation &&
-           mConstraintValidation->GetValidityState(aState);
-  }
-
-  // Weak reference to owner which will call Disconnect() when being destroyed.
-  nsIConstraintValidation*       mConstraintValidation;
-};
-
-#endif // nsDOMValidityState_h__
-
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -10,16 +10,17 @@
 #include "nsIDOMHTMLElement.h"
 #include "nsINameSpaceManager.h"  // for kNameSpaceID_None
 #include "nsIFormControl.h"
 #include "nsGkAtoms.h"
 #include "nsContentCreatorFunctions.h"
 #include "mozilla/ErrorResult.h"
 #include "nsContentUtils.h"
 #include "nsIDOMHTMLMenuElement.h"
+#include "mozilla/dom/ValidityState.h"
 
 class nsIDOMAttr;
 class nsIDOMEventListener;
 class nsIDOMNodeList;
 class nsIFrame;
 class nsIStyleRule;
 class nsChildContentList;
 class nsDOMCSSDeclaration;
--- a/content/html/content/src/nsGenericHTMLFrameElement.cpp
+++ b/content/html/content/src/nsGenericHTMLFrameElement.cpp
@@ -12,17 +12,16 @@
 #include "nsIAppsService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDOMApplicationRegistry.h"
 #include "nsIPermissionManager.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameLoader)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_TABLE_HEAD(nsGenericHTMLFrameElement)
   NS_INTERFACE_TABLE_INHERITED3(nsGenericHTMLFrameElement,
                                 nsIFrameLoaderOwner,
--- a/content/html/content/src/nsHTMLButtonElement.cpp
+++ b/content/html/content/src/nsHTMLButtonElement.cpp
@@ -54,16 +54,19 @@ class nsHTMLButtonElement : public nsGen
 {
 public:
   using nsIConstraintValidation::GetValidationMessage;
 
   nsHTMLButtonElement(already_AddRefed<nsINodeInfo> aNodeInfo,
                       FromParser aFromParser = NOT_FROM_PARSER);
   virtual ~nsHTMLButtonElement();
 
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLButtonElement,
+                                           nsGenericHTMLFormElement)
+
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
@@ -147,16 +150,25 @@ nsHTMLButtonElement::nsHTMLButtonElement
 }
 
 nsHTMLButtonElement::~nsHTMLButtonElement()
 {
 }
 
 // nsISupports
 
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLButtonElement,
+                                                  nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLButtonElement,
+                                                nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 NS_IMPL_ADDREF_INHERITED(nsHTMLButtonElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLButtonElement, Element)
 
 
 DOMCI_NODE_DATA(HTMLButtonElement, nsHTMLButtonElement)
 
 // QueryInterface implementation for nsHTMLButtonElement
 NS_INTERFACE_TABLE_HEAD(nsHTMLButtonElement)
--- a/content/html/content/src/nsHTMLFieldSetElement.cpp
+++ b/content/html/content/src/nsHTMLFieldSetElement.cpp
@@ -37,22 +37,23 @@ nsHTMLFieldSetElement::~nsHTMLFieldSetEl
     mDependentElements[i]->ForgetFieldSet(this);
   }
 }
 
 // nsISupports
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLFieldSetElement,
                                                 nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mElements)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLFieldSetElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLFieldSetElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElements)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLFieldSetElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLFieldSetElement, Element)
 
 DOMCI_NODE_DATA(HTMLFieldSetElement, nsHTMLFieldSetElement)
 
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -281,17 +281,16 @@ ElementTraverser(const nsAString& key, n
 {
   nsCycleCollectionTraversalCallback *cb = 
     static_cast<nsCycleCollectionTraversalCallback*>(userArg);
  
   cb->NoteXPCOMChild(element);
   return PL_DHASH_NEXT;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLFormElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLFormElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControls)
   tmp->mSelectedRadioButtons.EnumerateRead(ElementTraverser, &cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLFormElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLFormElement, Element)
@@ -2175,17 +2174,16 @@ ControlTraverser(const nsAString& key, n
 {
   nsCycleCollectionTraversalCallback *cb = 
     static_cast<nsCycleCollectionTraversalCallback*>(userArg);
  
   cb->NoteXPCOMChild(control);
   return PL_DHASH_NEXT;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsFormControlList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFormControlList)
   tmp->Clear();
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFormControlList)
   tmp->mNameLookupTable.EnumerateRead(ControlTraverser, &cb);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -629,29 +629,30 @@ nsHTMLInputElement::GetEditorState() con
     "Single line text controls need to have a state associated with them");
 
   return mInputData.mState;
 }
 
 
 // nsISupports
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLInputElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLInputElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
   if (tmp->IsSingleLineTextControl(false)) {
     tmp->mInputData.mState->Traverse(cb);
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFiles)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFileList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLInputElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFiles)
   if (tmp->mFileList) {
     tmp->mFileList->Disconnect();
     tmp->mFileList = nullptr;
   }
   if (tmp->IsSingleLineTextControl(false)) {
     tmp->mInputData.mState->Unlink();
--- a/content/html/content/src/nsHTMLLinkElement.cpp
+++ b/content/html/content/src/nsHTMLLinkElement.cpp
@@ -120,17 +120,16 @@ nsHTMLLinkElement::nsHTMLLinkElement(alr
     Link(this)
 {
 }
 
 nsHTMLLinkElement::~nsHTMLLinkElement()
 {
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLLinkElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLLinkElement,
                                                   nsGenericHTMLElement)
   tmp->nsStyleLinkElement::Traverse(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLLinkElement,
                                                 nsGenericHTMLElement)
   tmp->nsStyleLinkElement::Unlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/html/content/src/nsHTMLMapElement.cpp
+++ b/content/html/content/src/nsHTMLMapElement.cpp
@@ -49,17 +49,16 @@ protected:
 NS_IMPL_NS_NEW_HTML_ELEMENT(Map)
 
 
 nsHTMLMapElement::nsHTMLMapElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLMapElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLMapElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAreas)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLMapElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLMapElement, Element)
 
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -425,18 +425,16 @@ NS_IMETHODIMP nsHTMLMediaElement::MediaL
 NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::GetInterface(const nsIID & aIID, void **aResult)
 {
   return QueryInterface(aIID, aResult);
 }
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLMediaElement, nsGenericHTMLElement)
 NS_IMPL_RELEASE_INHERITED(nsHTMLMediaElement, nsGenericHTMLElement)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLMediaElement)
-
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLMediaElement, nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcStream)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSrcAttrStream)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourcePointer)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoadBlockedDoc)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSourceLoadCandidate)
   for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mStream);
deleted file mode 100644
--- a/content/html/content/src/nsHTMLObjectElement.cpp
+++ /dev/null
@@ -1,557 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-// vim:set et sw=2 sts=2 cin:
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/Util.h"
-
-#include "nsAutoPtr.h"
-#include "nsGenericHTMLElement.h"
-#include "nsAttrValueInlines.h"
-#include "nsObjectLoadingContent.h"
-#include "nsGkAtoms.h"
-#include "nsError.h"
-#include "nsIDocument.h"
-#include "nsIPluginDocument.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMSVGDocument.h"
-#include "nsIDOMGetSVGDocument.h"
-#include "nsIDOMHTMLObjectElement.h"
-#include "nsFormSubmission.h"
-#include "nsIObjectFrame.h"
-#include "nsNPAPIPluginInstance.h"
-#include "nsIConstraintValidation.h"
-#include "nsIWidget.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-class nsHTMLObjectElement : public nsGenericHTMLFormElement
-                          , public nsObjectLoadingContent
-                          , public nsIDOMHTMLObjectElement
-                          , public nsIConstraintValidation
-                          , public nsIDOMGetSVGDocument
-{
-public:
-  using nsIConstraintValidation::GetValidationMessage;
-
-  nsHTMLObjectElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                      mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER);
-  virtual ~nsHTMLObjectElement();
-
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-
-  // nsIDOMElement
-  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
-
-  // nsIDOMHTMLElement
-  NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
-
-  virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
-
-  // nsIDOMHTMLObjectElement
-  NS_DECL_NSIDOMHTMLOBJECTELEMENT
-
-  // nsIDOMGetSVGDocument
-  NS_DECL_NSIDOMGETSVGDOCUMENT
-
-  virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
-                              nsIContent *aBindingParent,
-                              bool aCompileEventHandlers);
-  virtual void UnbindFromTree(bool aDeep = true,
-                              bool aNullParent = true);
-  virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom *aName,
-                           nsIAtom *aPrefix, const nsAString &aValue,
-                           bool aNotify);
-  virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
-                             bool aNotify);
-
-  virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex);
-  virtual IMEState GetDesiredIMEState();
-
-  // Overriden nsIFormControl methods
-  NS_IMETHOD_(uint32_t) GetType() const
-  {
-    return NS_FORM_OBJECT;
-  }
-
-  NS_IMETHOD Reset();
-  NS_IMETHOD SubmitNamesValues(nsFormSubmission *aFormSubmission);
-
-  virtual bool IsDisabled() const { return false; }
-
-  virtual void DoneAddingChildren(bool aHaveNotified);
-  virtual bool IsDoneAddingChildren();
-
-  virtual bool ParseAttribute(int32_t aNamespaceID,
-                                nsIAtom *aAttribute,
-                                const nsAString &aValue,
-                                nsAttrValue &aResult);
-  virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
-  NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom *aAttribute) const;
-  virtual nsEventStates IntrinsicState() const;
-  virtual void DestroyContent();
-
-  // nsObjectLoadingContent
-  virtual uint32_t GetCapabilities() const;
-
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
-  nsresult CopyInnerTo(Element* aDest);
-
-  void StartObjectLoad() { StartObjectLoad(true); }
-
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLObjectElement,
-                                                     nsGenericHTMLFormElement)
-
-  virtual nsXPCClassInfo* GetClassInfo();
-
-  virtual nsIDOMNode* AsDOMNode() { return this; }
-private:
-  /**
-   * Calls LoadObject with the correct arguments to start the plugin load.
-   */
-  NS_HIDDEN_(void) StartObjectLoad(bool aNotify);
-
-  /**
-   * Returns if the element is currently focusable regardless of it's tabindex
-   * value. This is used to know the default tabindex value.
-   */
-  bool IsFocusableForTabIndex();
-  
-  virtual void GetItemValueText(nsAString& text);
-  virtual void SetItemValueText(const nsAString& text);
-
-  bool mIsDoneAddingChildren;
-};
-
-
-NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Object)
-
-
-nsHTMLObjectElement::nsHTMLObjectElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                                         FromParser aFromParser)
-  : nsGenericHTMLFormElement(aNodeInfo),
-    mIsDoneAddingChildren(!aFromParser)
-{
-  RegisterFreezableElement();
-  SetIsNetworkCreated(aFromParser == FROM_PARSER_NETWORK);
-
-  // <object> is always barred from constraint validation.
-  SetBarredFromConstraintValidation(true);
-
-  // By default we're in the loading state
-  AddStatesSilently(NS_EVENT_STATE_LOADING);
-}
-
-nsHTMLObjectElement::~nsHTMLObjectElement()
-{
-  UnregisterFreezableElement();
-  DestroyImageLoadingContent();
-}
-
-bool
-nsHTMLObjectElement::IsDoneAddingChildren()
-{
-  return mIsDoneAddingChildren;
-}
-
-void
-nsHTMLObjectElement::DoneAddingChildren(bool aHaveNotified)
-{
-  mIsDoneAddingChildren = true;
-
-  // If we're already in a document, we need to trigger the load
-  // Otherwise, BindToTree takes care of that.
-  if (IsInDoc()) {
-    StartObjectLoad(aHaveNotified);
-  }
-}
-
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLObjectElement)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLObjectElement,
-                                                  nsGenericHTMLFormElement)
-  nsObjectLoadingContent::Traverse(tmp, cb);
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_ADDREF_INHERITED(nsHTMLObjectElement, Element)
-NS_IMPL_RELEASE_INHERITED(nsHTMLObjectElement, Element)
-
-DOMCI_NODE_DATA(HTMLObjectElement, nsHTMLObjectElement)
-
-NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLObjectElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE_BEGIN(nsHTMLObjectElement)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIDOMHTMLObjectElement)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, imgINotificationObserver)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIRequestObserver)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIStreamListener)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIFrameLoaderOwner)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIObjectLoadingContent)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIImageLoadingContent)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, imgIOnloadBlocker)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIInterfaceRequestor)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIChannelEventSink)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIConstraintValidation)
-    NS_INTERFACE_TABLE_ENTRY(nsHTMLObjectElement, nsIDOMGetSVGDocument)
-  NS_OFFSET_AND_INTERFACE_TABLE_END
-  NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLObjectElement,
-                                               nsGenericHTMLFormElement)
-NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLObjectElement)
-
-NS_IMPL_ELEMENT_CLONE(nsHTMLObjectElement)
-
-// nsIConstraintValidation
-NS_IMPL_NSICONSTRAINTVALIDATION(nsHTMLObjectElement)
-
-NS_IMETHODIMP
-nsHTMLObjectElement::GetForm(nsIDOMHTMLFormElement **aForm)
-{
-  return nsGenericHTMLFormElement::GetForm(aForm);
-}
-
-void
-nsHTMLObjectElement::GetItemValueText(nsAString& aValue)
-{
-  GetData(aValue);
-}
-
-void
-nsHTMLObjectElement::SetItemValueText(const nsAString& aValue)
-{
-  SetData(aValue);
-}
-
-nsresult
-nsHTMLObjectElement::BindToTree(nsIDocument *aDocument,
-                                nsIContent *aParent,
-                                nsIContent *aBindingParent,
-                                bool aCompileEventHandlers)
-{
-  nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
-                                                     aBindingParent,
-                                                     aCompileEventHandlers);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = nsObjectLoadingContent::BindToTree(aDocument, aParent,
-                                          aBindingParent,
-                                          aCompileEventHandlers);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Don't kick off load from being bound to a plugin document - the plugin
-  // document will call nsObjectLoadingContent::InitializeFromChannel() for the
-  // initial load.
-  nsCOMPtr<nsIPluginDocument> pluginDoc = do_QueryInterface(aDocument);
-
-  // If we already have all the children, start the load.
-  if (mIsDoneAddingChildren && !pluginDoc) {
-    void (nsHTMLObjectElement::*start)() = &nsHTMLObjectElement::StartObjectLoad;
-    nsContentUtils::AddScriptRunner(NS_NewRunnableMethod(this, start));
-  }
-
-  return NS_OK;
-}
-
-void
-nsHTMLObjectElement::UnbindFromTree(bool aDeep,
-                                    bool aNullParent)
-{
-  nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent);
-  nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
-}
-
-
-
-nsresult
-nsHTMLObjectElement::SetAttr(int32_t aNameSpaceID, nsIAtom *aName,
-                             nsIAtom *aPrefix, const nsAString &aValue,
-                             bool aNotify)
-{
-  nsresult rv = nsGenericHTMLFormElement::SetAttr(aNameSpaceID, aName, aPrefix,
-                                                  aValue, aNotify);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // if aNotify is false, we are coming from the parser or some such place;
-  // we'll get bound after all the attributes have been set, so we'll do the
-  // object load from BindToTree/DoneAddingChildren.
-  // Skip the LoadObject call in that case.
-  // We also don't want to start loading the object when we're not yet in
-  // a document, just in case that the caller wants to set additional
-  // attributes before inserting the node into the document.
-  if (aNotify && IsInDoc() && mIsDoneAddingChildren &&
-      aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::data) {
-    return LoadObject(aNotify, true);
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsHTMLObjectElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
-                               bool aNotify)
-{
-  nsresult rv = nsGenericHTMLFormElement::UnsetAttr(aNameSpaceID,
-                                                    aAttribute, aNotify);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // See comment in SetAttr
-  if (aNotify && IsInDoc() && mIsDoneAddingChildren &&
-      aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::data) {
-    return LoadObject(aNotify, true);
-  }
-
-  return NS_OK;
-}
-
-bool
-nsHTMLObjectElement::IsFocusableForTabIndex()
-{
-  nsIDocument* doc = GetCurrentDoc();
-  if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
-    return false;
-  }
-
-  return IsEditableRoot() ||
-         (Type() == eType_Document &&
-          nsContentUtils::IsSubDocumentTabbable(this));
-}
-
-bool
-nsHTMLObjectElement::IsHTMLFocusable(bool aWithMouse,
-                                     bool *aIsFocusable, int32_t *aTabIndex)
-{
-  // TODO: this should probably be managed directly by IsHTMLFocusable.
-  // See bug 597242.
-  nsIDocument *doc = GetCurrentDoc();
-  if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
-    if (aTabIndex) {
-      GetTabIndex(aTabIndex);
-    }
-
-    *aIsFocusable = false;
-
-    return false;
-  }
-
-  // This method doesn't call nsGenericHTMLFormElement intentionally.
-  // TODO: It should probably be changed when bug 597242 will be fixed.
-  if (Type() == eType_Plugin || IsEditableRoot() ||
-      (Type() == eType_Document && nsContentUtils::IsSubDocumentTabbable(this))) {
-    // Has plugin content: let the plugin decide what to do in terms of
-    // internal focus from mouse clicks
-    if (aTabIndex) {
-      GetTabIndex(aTabIndex);
-    }
-
-    *aIsFocusable = true;
-
-    return false;
-  }
-
-  // TODO: this should probably be managed directly by IsHTMLFocusable.
-  // See bug 597242.
-  const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::tabindex);
-
-  *aIsFocusable = attrVal && attrVal->Type() == nsAttrValue::eInteger;
-
-  if (aTabIndex && *aIsFocusable) {
-    *aTabIndex = attrVal->GetIntegerValue();
-  }
-
-  return false;
-}
-
-nsIContent::IMEState
-nsHTMLObjectElement::GetDesiredIMEState()
-{
-  if (Type() == eType_Plugin) {
-    return IMEState(IMEState::PLUGIN);
-  }
-   
-  return nsGenericHTMLFormElement::GetDesiredIMEState();
-}
-
-NS_IMETHODIMP
-nsHTMLObjectElement::Reset()
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHTMLObjectElement::SubmitNamesValues(nsFormSubmission *aFormSubmission)
-{
-  nsAutoString name;
-  if (!GetAttr(kNameSpaceID_None, nsGkAtoms::name, name)) {
-    // No name, don't submit.
-
-    return NS_OK;
-  }
-
-  nsIFrame* frame = GetPrimaryFrame();
-
-  nsIObjectFrame *objFrame = do_QueryFrame(frame);
-  if (!objFrame) {
-    // No frame, nothing to submit.
-
-    return NS_OK;
-  }
-
-  nsRefPtr<nsNPAPIPluginInstance> pi;
-  objFrame->GetPluginInstance(getter_AddRefs(pi));
-  if (!pi)
-    return NS_OK;
-
-  nsAutoString value;
-  nsresult rv = pi->GetFormValue(value);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return aFormSubmission->AddNameValuePair(name, value);
-}
-
-NS_IMPL_STRING_ATTR(nsHTMLObjectElement, Align, align)
-NS_IMPL_STRING_ATTR(nsHTMLObjectElement, Archive, archive)
-NS_IMPL_STRING_ATTR(nsHTMLObjectElement, Border, border)
-NS_IMPL_URI_ATTR_WITH_BASE(nsHTMLObjectElement, Code, code, codebase)
-NS_IMPL_URI_ATTR(nsHTMLObjectElement, CodeBase, codebase)
-NS_IMPL_STRING_ATTR(nsHTMLObjectElement, CodeType, codetype)
-NS_IMPL_URI_ATTR_WITH_BASE(nsHTMLObjectElement, Data, data, codebase)
-NS_IMPL_BOOL_ATTR(nsHTMLObjectElement, Declare, declare)
-NS_IMPL_STRING_ATTR(nsHTMLObjectElement, Height, height)
-NS_IMPL_INT_ATTR(nsHTMLObjectElement, Hspace, hspace)
-NS_IMPL_STRING_ATTR(nsHTMLObjectElement, Name, name)
-NS_IMPL_STRING_ATTR(nsHTMLObjectElement, Standby, standby)
-NS_IMPL_STRING_ATTR(nsHTMLObjectElement, Type, type)
-NS_IMPL_STRING_ATTR(nsHTMLObjectElement, UseMap, usemap)
-NS_IMPL_INT_ATTR(nsHTMLObjectElement, Vspace, vspace)
-NS_IMPL_STRING_ATTR(nsHTMLObjectElement, Width, width)
-
-int32_t
-nsHTMLObjectElement::TabIndexDefault()
-{
-  return IsFocusableForTabIndex() ? 0 : -1;
-}
-
-NS_IMETHODIMP
-nsHTMLObjectElement::GetContentDocument(nsIDOMDocument **aContentDocument)
-{
-  NS_ENSURE_ARG_POINTER(aContentDocument);
-
-  *aContentDocument = nullptr;
-
-  if (!IsInDoc()) {
-    return NS_OK;
-  }
-
-  // XXXbz should this use GetCurrentDoc()?  sXBL/XBL2 issue!
-  nsIDocument *sub_doc = OwnerDoc()->GetSubDocumentFor(this);
-  if (!sub_doc) {
-    return NS_OK;
-  }
-
-  return CallQueryInterface(sub_doc, aContentDocument);
-}
-
-NS_IMETHODIMP
-nsHTMLObjectElement::GetSVGDocument(nsIDOMDocument **aResult)
-{
-  return GetContentDocument(aResult);
-}
-
-bool
-nsHTMLObjectElement::ParseAttribute(int32_t aNamespaceID,
-                                    nsIAtom *aAttribute,
-                                    const nsAString &aValue,
-                                    nsAttrValue &aResult)
-{
-  if (aNamespaceID == kNameSpaceID_None) {
-    if (aAttribute == nsGkAtoms::align) {
-      return ParseAlignValue(aValue, aResult);
-    }
-    if (ParseImageAttribute(aAttribute, aValue, aResult)) {
-      return true;
-    }
-  }
-
-  return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
-                                                  aValue, aResult);
-}
-
-static void
-MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
-                      nsRuleData *aData)
-{
-  nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapImageMarginAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aData);
-}
-
-NS_IMETHODIMP_(bool)
-nsHTMLObjectElement::IsAttributeMapped(const nsIAtom *aAttribute) const
-{
-  static const MappedAttributeEntry* const map[] = {
-    sCommonAttributeMap,
-    sImageMarginSizeAttributeMap,
-    sImageBorderAttributeMap,
-    sImageAlignAttributeMap,
-  };
-
-  return FindAttributeDependence(aAttribute, map);
-}
-
-
-nsMapRuleToAttributesFunc
-nsHTMLObjectElement::GetAttributeMappingFunction() const
-{
-  return &MapAttributesIntoRule;
-}
-
-void
-nsHTMLObjectElement::StartObjectLoad(bool aNotify)
-{
-  // BindToTree can call us asynchronously, and we may be removed from the tree
-  // in the interim
-  if (!IsInDoc() || !OwnerDoc()->IsActive()) {
-    return;
-  }
-
-  LoadObject(aNotify);
-  SetIsNetworkCreated(false);
-}
-
-nsEventStates
-nsHTMLObjectElement::IntrinsicState() const
-{
-  return nsGenericHTMLFormElement::IntrinsicState() | ObjectState();
-}
-
-uint32_t
-nsHTMLObjectElement::GetCapabilities() const
-{
-  return nsObjectLoadingContent::GetCapabilities() | eSupportClassID;
-}
-
-void
-nsHTMLObjectElement::DestroyContent()
-{
-  nsObjectLoadingContent::DestroyContent();
-  nsGenericHTMLFormElement::DestroyContent();
-}
-
-nsresult
-nsHTMLObjectElement::CopyInnerTo(Element* aDest)
-{
-  nsresult rv = nsGenericHTMLFormElement::CopyInnerTo(aDest);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (aDest->OwnerDoc()->IsStaticDocument()) {
-    CreateStaticClone(static_cast<nsHTMLObjectElement*>(aDest));
-  }
-
-  return rv;
-}
--- a/content/html/content/src/nsHTMLOutputElement.cpp
+++ b/content/html/content/src/nsHTMLOutputElement.cpp
@@ -102,26 +102,27 @@ nsHTMLOutputElement::nsHTMLOutputElement
 
 nsHTMLOutputElement::~nsHTMLOutputElement()
 {
   if (mTokenList) {
     mTokenList->DropReference();
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLOutputElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLOutputElement,
                                                 nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
   if (tmp->mTokenList) {
     tmp->mTokenList->DropReference();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mTokenList)
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLOutputElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTokenList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLOutputElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLOutputElement, Element)
 
 DOMCI_NODE_DATA(HTMLOutputElement, nsHTMLOutputElement)
 
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -130,21 +130,25 @@ nsHTMLSelectElement::nsHTMLSelectElement
 
 nsHTMLSelectElement::~nsHTMLSelectElement()
 {
   mOptions->DropReference();
 }
 
 // ISupports
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLSelectElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLSelectElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOptions)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLSelectElement,
+                                                nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLSelectElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLSelectElement, Element)
 
 
 DOMCI_NODE_DATA(HTMLSelectElement, nsHTMLSelectElement)
 
 // QueryInterface implementation for nsHTMLSelectElement
@@ -1973,17 +1977,16 @@ nsHTMLOptionCollection::GetOptionIndex(m
       return NS_OK;
     }
   }
 
   return NS_ERROR_FAILURE;
 }
 
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLOptionCollection)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHTMLOptionCollection)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mElements)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHTMLOptionCollection)
   {
     uint32_t i;
     for (i = 0; i < tmp->mElements.Length(); ++i) {
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -377,18 +377,18 @@ public:
                                 nsAttrValue& aResult);
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               int32_t aModType) const;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLSelectElement,
-                                                     nsGenericHTMLFormElement)
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLSelectElement,
+                                           nsGenericHTMLFormElement)
 
   nsHTMLOptionCollection *GetOptions()
   {
     return mOptions;
   }
 
   static nsHTMLSelectElement *FromSupports(nsISupports *aSupports)
   {
--- a/content/html/content/src/nsHTMLSharedObjectElement.cpp
+++ b/content/html/content/src/nsHTMLSharedObjectElement.cpp
@@ -201,17 +201,16 @@ nsHTMLSharedObjectElement::DoneAddingChi
     // If we're already in a document, we need to trigger the load
     // Otherwise, BindToTree takes care of that.
     if (IsInDoc()) {
       StartObjectLoad(aHaveNotified);
     }
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLSharedObjectElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLSharedObjectElement,
                                                   nsGenericHTMLElement)
   nsObjectLoadingContent::Traverse(tmp, cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLSharedObjectElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLSharedObjectElement, Element)
 
--- a/content/html/content/src/nsHTMLStyleElement.cpp
+++ b/content/html/content/src/nsHTMLStyleElement.cpp
@@ -105,17 +105,16 @@ nsHTMLStyleElement::nsHTMLStyleElement(a
 {
   AddMutationObserver(this);
 }
 
 nsHTMLStyleElement::~nsHTMLStyleElement()
 {
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLStyleElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLStyleElement,
                                                   nsGenericHTMLElement)
   tmp->nsStyleLinkElement::Traverse(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLStyleElement,
                                                 nsGenericHTMLElement)
   tmp->nsStyleLinkElement::Unlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/html/content/src/nsHTMLTextAreaElement.cpp
+++ b/content/html/content/src/nsHTMLTextAreaElement.cpp
@@ -295,24 +295,25 @@ nsHTMLTextAreaElement::nsHTMLTextAreaEle
   // until someone calls UpdateEditableState on us, apparently!  Also
   // by default we don't have to show validity UI and so forth.
   AddStatesSilently(NS_EVENT_STATE_ENABLED |
                     NS_EVENT_STATE_OPTIONAL |
                     NS_EVENT_STATE_VALID);
 }
 
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLTextAreaElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLTextAreaElement,
                                                 nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
   tmp->mState.Unlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLTextAreaElement,
                                                   nsGenericHTMLFormElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mValidity)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
   tmp->mState.Traverse(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLTextAreaElement, Element)
 NS_IMPL_RELEASE_INHERITED(nsHTMLTextAreaElement, Element)
 
 
--- a/content/html/content/src/nsIConstraintValidation.cpp
+++ b/content/html/content/src/nsIConstraintValidation.cpp
@@ -3,45 +3,52 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIConstraintValidation.h"
 
 #include "nsAString.h"
 #include "nsGenericHTMLElement.h"
 #include "nsHTMLFormElement.h"
-#include "nsDOMValidityState.h"
+#include "mozilla/dom/ValidityState.h"
 #include "nsIFormControl.h"
 #include "nsContentUtils.h"
 
 const uint16_t nsIConstraintValidation::sContentSpecifiedMaxLengthMessage = 256;
 
 nsIConstraintValidation::nsIConstraintValidation()
   : mValidityBitField(0)
-  , mValidity(nullptr)
   // By default, all elements are subjects to constraint validation.
   , mBarredFromConstraintValidation(false)
 {
 }
 
 nsIConstraintValidation::~nsIConstraintValidation()
 {
   if (mValidity) {
     mValidity->Disconnect();
   }
 }
 
+mozilla::dom::ValidityState*
+nsIConstraintValidation::Validity()
+{
+  if (!mValidity) {
+    mValidity = new mozilla::dom::ValidityState(this);
+  }
+
+  return mValidity;
+}
+
 nsresult
 nsIConstraintValidation::GetValidity(nsIDOMValidityState** aValidity)
 {
-  if (!mValidity) {
-    mValidity = new nsDOMValidityState(this);
-  }
+  NS_ENSURE_ARG_POINTER(aValidity);
 
-  NS_ADDREF(*aValidity = mValidity);
+  NS_ADDREF(*aValidity = Validity());
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage)
 {
   aValidationMessage.Truncate();
@@ -84,32 +91,40 @@ nsIConstraintValidation::GetValidationMe
     }
   } else {
     aValidationMessage.Truncate();
   }
 
   return NS_OK;
 }
 
-nsresult
-nsIConstraintValidation::CheckValidity(bool* aValidity)
+bool
+nsIConstraintValidation::CheckValidity()
 {
   if (!IsCandidateForConstraintValidation() || IsValid()) {
-    *aValidity = true;
-    return NS_OK;
+    return true;
   }
 
-  *aValidity = false;
-
   nsCOMPtr<nsIContent> content = do_QueryInterface(this);
   NS_ASSERTION(content, "This class should be inherited by HTML elements only!");
 
-  return nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
-                                              NS_LITERAL_STRING("invalid"),
-                                              false, true);
+  nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
+                                       NS_LITERAL_STRING("invalid"),
+                                       false, true);
+  return false;
+}
+
+nsresult
+nsIConstraintValidation::CheckValidity(bool* aValidity)
+{
+  NS_ENSURE_ARG_POINTER(aValidity);
+
+  *aValidity = CheckValidity();
+
+  return NS_OK;
 }
 
 void
 nsIConstraintValidation::SetValidityState(ValidityStateType aState,
                                           bool aValue)
 {
   bool previousValidity = IsValid();
 
--- a/content/html/document/src/ImageDocument.cpp
+++ b/content/html/document/src/ImageDocument.cpp
@@ -215,17 +215,16 @@ ImageDocument::ImageDocument()
   // NOTE! nsDocument::operator new() zeroes out all members, so don't
   // bother initializing members to 0.
 }
 
 ImageDocument::~ImageDocument()
 {
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(ImageDocument)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ImageDocument, MediaDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImageContent)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ImageDocument, MediaDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mImageContent)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/html/document/src/PluginDocument.cpp
+++ b/content/html/document/src/PluginDocument.cpp
@@ -103,17 +103,16 @@ PluginStreamListener::OnStartRequest(nsI
   // bother initializing members to 0.
 
 PluginDocument::PluginDocument()
 {}
 
 PluginDocument::~PluginDocument()
 {}
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(PluginDocument)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PluginDocument, MediaDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPluginContent)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PluginDocument, MediaDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPluginContent)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -1283,18 +1283,16 @@ HTMLContentSink::~HTMLContentSink()
 
   delete mHeadContext;
 
   for (i = 0; uint32_t(i) < ArrayLength(mNodeInfoCache); ++i) {
     NS_IF_RELEASE(mNodeInfoCache[i]);
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLContentSink)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLContentSink, nsContentSink)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mHTMLDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mBody)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mHead)
   for (uint32_t i = 0; i < ArrayLength(tmp->mNodeInfoCache); ++i) {
     NS_IF_RELEASE(tmp->mNodeInfoCache[i]);
   }
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -200,17 +200,16 @@ nsHTMLDocument::nsHTMLDocument()
   // NOTE! nsDocument::operator new() zeroes out all members, so don't
   // bother initializing members to 0.
 
   mIsRegularHTML = true;
   mDefaultElementType = kNameSpaceID_XHTML;
   mCompatMode = eCompatibility_NavQuirks;
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLDocument)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
   NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()),
                "Shouldn't traverse nsHTMLDocument!");
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImages)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mApplets)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEmbeds)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLinks)
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -993,17 +993,16 @@ void MediaDecoderStateMachine::AudioLoop
     playbackRate = mPlaybackRate;
     if (playbackRate != 1.0) {
       NS_ASSERTION(playbackRate != 0,
           "Don't set the playbackRate to 0 on an AudioStream.");
       mAudioStream->SetPlaybackRate(playbackRate);
     }
   }
   while (1) {
-
     // Wait while we're not playing, and we're not shutting down, or we're
     // playing and we've got no audio to play.
     {
       ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
       NS_ASSERTION(mState != DECODER_STATE_DECODING_METADATA,
                    "Should have meta data before audio started playing.");
       while (mState != DECODER_STATE_SHUTDOWN &&
              !mStopAudioThread &&
@@ -1256,17 +1255,17 @@ void MediaDecoderStateMachine::StopPlayb
 }
 
 void MediaDecoderStateMachine::StartPlayback()
 {
   LOG(PR_LOG_DEBUG, ("%p StartPlayback()", mDecoder.get()));
 
   NS_ASSERTION(!IsPlaying(), "Shouldn't be playing when StartPlayback() is called");
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
-  LOG(PR_LOG_DEBUG, ("%p StartPlayback", mDecoder.get()));
+
   mDecoder->NotifyPlaybackStarted();
   mPlayStartTime = TimeStamp::Now();
 
   NS_ASSERTION(IsPlaying(), "Should report playing by end of StartPlayback()");
   if (NS_FAILED(StartAudioThread())) {
     NS_WARNING("Failed to create audio thread"); 
   }
   mDecoder->GetReentrantMonitor().NotifyAll();
@@ -2027,16 +2026,24 @@ nsresult MediaDecoderStateMachine::RunSt
   NS_ENSURE_TRUE(resource, NS_ERROR_NULL_POINTER);
 
   switch (mState) {
     case DECODER_STATE_SHUTDOWN: {
       if (IsPlaying()) {
         StopPlayback();
       }
       StopAudioThread();
+      // If mAudioThread is non-null after StopAudioThread completes, we are
+      // running in a nested event loop waiting for Shutdown() on
+      // mAudioThread to complete.  Return to the event loop and let it
+      // finish processing before continuing with shutdown.
+      if (mAudioThread) {
+        MOZ_ASSERT(mStopAudioThread);
+        return NS_OK;
+      }
       StopDecodeThread();
       // Now that those threads are stopped, there's no possibility of
       // mPendingWakeDecoder being needed again. Revoke it.
       mPendingWakeDecoder = nullptr;
       NS_ASSERTION(mState == DECODER_STATE_SHUTDOWN,
                    "How did we escape from the shutdown state?");
       // We must daisy-chain these events to destroy the decoder. We must
       // destroy the decoder on the main thread, but we can't destroy the
@@ -2182,17 +2189,17 @@ nsresult MediaDecoderStateMachine::RunSt
       StopPlayback();
 
       if (mState != DECODER_STATE_COMPLETED) {
         // While we're presenting a frame we can change state. Whatever changed
         // our state should have scheduled another state machine run.
         NS_ASSERTION(IsStateMachineScheduled(), "Must have timer scheduled");
         return NS_OK;
       }
- 
+
       StopAudioThread();
       if (mDecoder->GetState() == MediaDecoder::PLAY_STATE_PLAYING) {
         int64_t videoTime = HasVideo() ? mVideoFrameEndTime : 0;
         int64_t clockTime = std::max(mEndTime, std::max(videoTime, GetAudioClock()));
         UpdatePlaybackPosition(clockTime);
         nsCOMPtr<nsIRunnable> event =
           NS_NewRunnableMethod(mDecoder, &MediaDecoder::PlaybackEnded);
         NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
@@ -2624,17 +2631,17 @@ void MediaDecoderStateMachine::TimeoutEx
   // Otherwise, an event has already been dispatched to run the state machine
   // as soon as possible. Nothing else needed to do, the state machine is
   // going to run anyway.
 }
 
 void MediaDecoderStateMachine::ScheduleStateMachineWithLockAndWakeDecoder() {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   mon.NotifyAll();
-  ScheduleStateMachine(0);
+  ScheduleStateMachine();
 }
 
 nsresult MediaDecoderStateMachine::ScheduleStateMachine(int64_t aUsecs) {
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
   NS_ABORT_IF_FALSE(GetStateMachineThread(),
     "Must have a state machine thread to schedule");
 
   if (mState == DECODER_STATE_SHUTDOWN) {
--- a/content/media/nsDOMMediaStream.cpp
+++ b/content/media/nsDOMMediaStream.cpp
@@ -15,18 +15,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMediaStream)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MediaStream)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMMediaStream)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMMediaStream)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMediaStream)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMMediaStream)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMMediaStream)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 // LocalMediaStream currently is the same C++ class as MediaStream;
 // they may eventually split
@@ -37,18 +35,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMMediaStream, nsDOMMediaStream)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMLocalMediaStream)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(LocalMediaStream)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMLocalMediaStream)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMLocalMediaStream)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMLocalMediaStream)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMLocalMediaStream)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMLocalMediaStream)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 
 nsDOMMediaStream::~nsDOMMediaStream()
--- a/content/media/webaudio/AudioBuffer.cpp
+++ b/content/media/webaudio/AudioBuffer.cpp
@@ -9,18 +9,16 @@
 #include "nsContentUtils.h"
 #include "AudioContext.h"
 #include "jsfriendapi.h"
 #include "mozilla/ErrorResult.h"
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(AudioBuffer)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioBuffer)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChannels)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioBuffer)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
--- a/content/smil/nsDOMTimeEvent.cpp
+++ b/content/smil/nsDOMTimeEvent.cpp
@@ -34,18 +34,16 @@ nsDOMTimeEvent::nsDOMTimeEvent(nsPresCon
       nsCOMPtr<nsIDOMWindow> window = do_GetInterface(container);
       if (window) {
         mView = do_QueryInterface(window);
       }
     }
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTimeEvent)
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMTimeEvent, nsDOMEvent)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mView)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMTimeEvent, nsDOMEvent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mView)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
copy from content/svg/content/src/DOMSVGPoint.cpp
copy to content/svg/content/nsISVGPoint.cpp
--- a/content/svg/content/src/DOMSVGPoint.cpp
+++ b/content/svg/content/nsISVGPoint.cpp
@@ -16,17 +16,16 @@
 // See the architecture comment in DOMSVGPointList.h.
 
 using namespace mozilla;
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPoint)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPoint)
   // We may not belong to a list, so we must null check tmp->mList.
   if (tmp->mList) {
     tmp->mList->mItems[tmp->mListIndex] = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/svg/content/src/DOMSVGLength.cpp
+++ b/content/svg/content/src/DOMSVGLength.cpp
@@ -16,17 +16,16 @@
 // See the architecture comment in DOMSVGAnimatedLengthList.h.
 
 namespace mozilla {
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGLength)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGLength)
   // We may not belong to a list, so we must null check tmp->mList.
   if (tmp->mList) {
     tmp->mList->mItems[tmp->mListIndex] = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGLength)
--- a/content/svg/content/src/DOMSVGLengthList.cpp
+++ b/content/svg/content/src/DOMSVGLengthList.cpp
@@ -35,17 +35,16 @@ void UpdateListIndicesFromIndex(nsTArray
 } // namespace
 
 namespace mozilla {
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our DOMSVGAnimatedLengthList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGLengthList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGLengthList)
   if (tmp->mAList) {
     if (tmp->IsAnimValList()) {
       tmp->mAList->mAnimVal = nullptr;
     } else {
       tmp->mAList->mBaseVal = nullptr;
     }
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mAList)
--- a/content/svg/content/src/DOMSVGNumber.cpp
+++ b/content/svg/content/src/DOMSVGNumber.cpp
@@ -15,17 +15,16 @@
 // See the architecture comment in DOMSVGAnimatedNumberList.h.
 
 using namespace mozilla;
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGNumber)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumber)
   // We may not belong to a list, so we must null check tmp->mList.
   if (tmp->mList) {
     tmp->mList->mItems[tmp->mListIndex] = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGNumber)
--- a/content/svg/content/src/DOMSVGNumberList.cpp
+++ b/content/svg/content/src/DOMSVGNumberList.cpp
@@ -35,17 +35,16 @@ void UpdateListIndicesFromIndex(nsTArray
 }
 
 } // namespace
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our DOMSVGAnimatedNumberList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGNumberList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGNumberList)
   if (tmp->mAList) {
     if (tmp->IsAnimValList()) {
       tmp->mAList->mAnimVal = nullptr;
     } else {
       tmp->mAList->mBaseVal = nullptr;
     }
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mAList)
--- a/content/svg/content/src/DOMSVGPathSeg.cpp
+++ b/content/svg/content/src/DOMSVGPathSeg.cpp
@@ -15,17 +15,16 @@
 // See the architecture comment in DOMSVGPathSegList.h.
 
 using namespace mozilla;
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPathSeg)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSeg)
   // We may not belong to a list, so we must null check tmp->mList.
   if (tmp->mList) {
     tmp->mList->ItemAt(tmp->mListIndex) = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -359,155 +358,8 @@ DOMSVGPathSeg::CreateFor(DOMSVGPathSegLi
   case PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
     return new DOMSVGPathSegCurvetoQuadraticSmoothRel(aList, aListIndex, aIsAnimValItem);
   default:
     NS_NOTREACHED("Invalid path segment type");
     return nullptr;
   }
 }
 
-
-
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegClosePath()
-{
-  return new DOMSVGPathSegClosePath();
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegMovetoAbs(float x, float y)
-{
-  return new DOMSVGPathSegMovetoAbs(x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegMovetoRel(float x, float y)
-{
-  return new DOMSVGPathSegMovetoRel(x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoAbs(float x, float y)
-{
-  return new DOMSVGPathSegLinetoAbs(x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoRel(float x, float y)
-{
-  return new DOMSVGPathSegLinetoRel(x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoCubicAbs(float x, float y,
-                                float x1, float y1,
-                                float x2, float y2)
-{
-  // Note that we swap from DOM API argument order to the argument order used
-  // in the <path> element's 'd' attribute (i.e. we put the arguments for the
-  // end point of the segment last instead of first).
-
-  return new DOMSVGPathSegCurvetoCubicAbs(x1, y1, x2, y2, x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoCubicRel(float x, float y,
-                                float x1, float y1,
-                                float x2, float y2)
-{
-  // See comment in NS_NewSVGPathSegCurvetoCubicAbs!
-
-  return new DOMSVGPathSegCurvetoCubicRel(x1, y1, x2, y2, x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoQuadraticAbs(float x, float y,
-                                    float x1, float y1)
-{
-  // See comment in NS_NewSVGPathSegCurvetoCubicAbs!
-
-  return new DOMSVGPathSegCurvetoQuadraticAbs(x1, y1, x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoQuadraticRel(float x, float y,
-                                    float x1, float y1)
-{
-  // See comment in NS_NewSVGPathSegCurvetoCubicAbs!
-
-  return new DOMSVGPathSegCurvetoQuadraticRel(x1, y1, x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegArcAbs(float x, float y,
-                       float r1, float r2, float angle,
-                       bool largeArcFlag, bool sweepFlag)
-{
-  // See comment in NS_NewSVGPathSegCurvetoCubicAbs!
-
-  return new DOMSVGPathSegArcAbs(r1, r2, angle, largeArcFlag, sweepFlag, x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegArcRel(float x, float y,
-                       float r1, float r2, float angle,
-                       bool largeArcFlag, bool sweepFlag)
-{
-  // See comment in NS_NewSVGPathSegCurvetoCubicAbs!
-
-  return new DOMSVGPathSegArcRel(r1, r2, angle, largeArcFlag, sweepFlag, x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoHorizontalAbs(float x)
-{
-  return new DOMSVGPathSegLinetoHorizontalAbs(x);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoHorizontalRel(float x)
-{
-  return new DOMSVGPathSegLinetoHorizontalRel(x);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoVerticalAbs(float y)
-{
-  return new DOMSVGPathSegLinetoVerticalAbs(y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoVerticalRel(float y)
-{
-  return new DOMSVGPathSegLinetoVerticalRel(y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoCubicSmoothAbs(float x, float y,
-                                      float x2, float y2)
-{
-  // See comment in NS_NewSVGPathSegCurvetoCubicAbs!
-
-  return new DOMSVGPathSegCurvetoCubicSmoothAbs(x2, y2, x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoCubicSmoothRel(float x, float y,
-                                      float x2, float y2)
-{
-  // See comment in NS_NewSVGPathSegCurvetoCubicAbs!
-
-  return new DOMSVGPathSegCurvetoCubicSmoothRel(x2, y2, x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y)
-{
-  return new DOMSVGPathSegCurvetoQuadraticSmoothAbs(x, y);
-}
-
-DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoQuadraticSmoothRel(float x, float y)
-{
-  return new DOMSVGPathSegCurvetoQuadraticSmoothRel(x, y);
-}
-
--- a/content/svg/content/src/DOMSVGPathSeg.h
+++ b/content/svg/content/src/DOMSVGPathSeg.h
@@ -723,80 +723,11 @@ public:
   void SetY(float aY, ErrorResult& rv);
 
 protected:
   float mArgs[2];
 };
 
 } // namespace mozilla
 
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegClosePath();
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegMovetoAbs(float x, float y);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegMovetoRel(float x, float y);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoAbs(float x, float y);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoRel(float x, float y);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoCubicAbs(float x, float y,
-                                float x1, float y1,
-                                float x2, float y2);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoCubicRel(float x, float y,
-                                float x1, float y1,
-                                float x2, float y2);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoQuadraticAbs(float x, float y,
-                                    float x1, float y1);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoQuadraticRel(float x, float y,
-                                    float x1, float y1);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegArcAbs(float x, float y,
-                       float r1, float r2, float angle,
-                       bool largeArcFlag, bool sweepFlag);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegArcRel(float x, float y,
-                       float r1, float r2, float angle,
-                       bool largeArcFlag, bool sweepFlag);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoHorizontalAbs(float x);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoHorizontalRel(float x);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoVerticalAbs(float y);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegLinetoVerticalRel(float y);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoCubicSmoothAbs(float x, float y,
-                                      float x2, float y2);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoCubicSmoothRel(float x, float y,
-                                      float x2, float y2);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y);
-
-mozilla::DOMSVGPathSeg*
-NS_NewSVGPathSegCurvetoQuadraticSmoothRel(float x, float y);
-
 #undef MOZ_SVG_LIST_INDEX_BIT_COUNT
 
 #endif // MOZILLA_DOMSVGPATHSEG_H__
--- a/content/svg/content/src/DOMSVGPathSegList.cpp
+++ b/content/svg/content/src/DOMSVGPathSegList.cpp
@@ -16,17 +16,16 @@
 
 // See the comment in this file's header.
 
 namespace mozilla {
 
 static nsSVGAttrTearoffTable<void, DOMSVGPathSegList>
   sSVGPathSegListTearoffTable;
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPathSegList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPathSegList)
   // No unlinking of mElement, we'd need to null out the value pointer (the
   // object it points to is held by the element) and null-check it everywhere.
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPathSegList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
--- a/content/svg/content/src/DOMSVGPoint.cpp
+++ b/content/svg/content/src/DOMSVGPoint.cpp
@@ -12,49 +12,16 @@
 #include "nsContentUtils.h" // NS_ENSURE_FINITE
 #include "mozilla/dom/SVGMatrix.h"
 #include "mozilla/dom/SVGPointBinding.h"
 
 // See the architecture comment in DOMSVGPointList.h.
 
 using namespace mozilla;
 
-// We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
-// clear our list's weak ref to us to be safe. (The other option would be to
-// not unlink and rely on the breaking of the other edges in the cycle, as
-// NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPoint)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPoint)
-  // We may not belong to a list, so we must null check tmp->mList.
-  if (tmp->mList) {
-    tmp->mList->mItems[tmp->mListIndex] = nullptr;
-  }
-NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPoint)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mList)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMSVGPoint)
-NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGPoint)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGPoint)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGPoint)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(DOMSVGPoint) // pseudo-interface
-  NS_INTERFACE_MAP_ENTRY(nsISVGPoint)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
 float
 DOMSVGPoint::X()
 {
   if (mIsAnimValItem && HasOwner()) {
     Element()->FlushAnimations(); // May make HasOwner() == false
   }
   return HasOwner() ? InternalItem().mX : mPt.mX;
 }
@@ -119,47 +86,8 @@ DOMSVGPoint::MatrixTransform(dom::SVGMat
 {
   float x = HasOwner() ? InternalItem().mX : mPt.mX;
   float y = HasOwner() ? InternalItem().mY : mPt.mY;
 
   gfxPoint pt = matrix.Matrix().Transform(gfxPoint(x, y));
   nsCOMPtr<nsISVGPoint> newPoint = new DOMSVGPoint(pt);
   return newPoint.forget();
 }
-
-void
-DOMSVGPoint::InsertingIntoList(DOMSVGPointList *aList,
-                               uint32_t aListIndex,
-                               bool aIsAnimValItem)
-{
-  NS_ABORT_IF_FALSE(!HasOwner(), "Inserting item that already has an owner");
-
-  mList = aList;
-  mListIndex = aListIndex;
-  mIsReadonly = false;
-  mIsAnimValItem = aIsAnimValItem;
-
-  NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGPoint!");
-}
-
-void
-DOMSVGPoint::RemovingFromList()
-{
-  mPt = InternalItem();
-  mList = nullptr;
-  NS_ABORT_IF_FALSE(!mIsReadonly, "mIsReadonly set for list");
-  mIsAnimValItem = false;
-}
-
-SVGPoint&
-DOMSVGPoint::InternalItem()
-{
-  return mList->InternalList().mItems[mListIndex];
-}
-
-#ifdef DEBUG
-bool
-DOMSVGPoint::IndexIsValid()
-{
-  return mListIndex < mList->InternalList().Length();
-}
-#endif
-
--- a/content/svg/content/src/DOMSVGPoint.h
+++ b/content/svg/content/src/DOMSVGPoint.h
@@ -14,27 +14,16 @@
 #include "nsISVGPoint.h"
 #include "nsTArray.h"
 #include "SVGPoint.h"
 #include "nsWrapperCache.h"
 #include "mozilla/Attributes.h"
 
 class nsSVGElement;
 
-// We make DOMSVGPoint a pseudo-interface to allow us to QI to it in order to
-// check that the objects that scripts pass to DOMSVGPointList methods are
-// our *native* point objects.
-//
-// {d6b6c440-af8d-40ee-856b-02a317cab275}
-#define MOZILLA_DOMSVGPOINT_IID \
-  { 0xd6b6c440, 0xaf8d, 0x40ee, \
-    { 0x85, 0x6b, 0x02, 0xa3, 0x17, 0xca, 0xb2, 0x75 } }
-
-#define MOZ_SVG_LIST_INDEX_BIT_COUNT 30
-
 namespace mozilla {
 
 namespace dom {
 class SVGMatrix;
 }
 
 /**
  * Class DOMSVGPoint
@@ -48,191 +37,76 @@ class SVGMatrix;
  * important points regarding these DOM wrapper structures.
  *
  * See the architecture comment in DOMSVGLength.h (yes, LENGTH) for an overview
  * of the important points regarding how this specific class works.
  */
 class DOMSVGPoint MOZ_FINAL : public nsISVGPoint
 {
 public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOMSVGPOINT_IID)
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPoint)
-
   /**
    * Generic ctor for DOMSVGPoint objects that are created for an attribute.
    */
   DOMSVGPoint(DOMSVGPointList *aList,
               uint32_t aListIndex,
               bool aIsAnimValItem)
     : nsISVGPoint()
-    , mList(aList)
-    , mListIndex(aListIndex)
-    , mIsReadonly(false)
-    , mIsAnimValItem(aIsAnimValItem)
   {
+    mList = aList;
+    mListIndex = aListIndex;
+    mIsAnimValItem = aIsAnimValItem;
+
     // These shifts are in sync with the members.
     NS_ABORT_IF_FALSE(aList &&
                       aListIndex <= MaxListIndex(), "bad arg");
 
     NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGPoint!");
   }
 
   explicit DOMSVGPoint(const DOMSVGPoint *aPt = nullptr)
     : nsISVGPoint()
-    , mList(nullptr)
-    , mListIndex(0)
-    , mIsReadonly(false)
-    , mIsAnimValItem(false)
   {
     if (aPt) {
       mPt = aPt->ToSVGPoint();
     }
   }
 
   DOMSVGPoint(float aX, float aY)
     : nsISVGPoint()
-    , mList(nullptr)
-    , mListIndex(0)
-    , mIsReadonly(false)
-    , mIsAnimValItem(false)
   {
     mPt.mX = aX;
     mPt.mY = aY;
   }
 
   explicit DOMSVGPoint(const gfxPoint &aPt)
     : nsISVGPoint()
-    , mList(nullptr)
-    , mListIndex(0)
-    , mIsReadonly(false)
-    , mIsAnimValItem(false)
   {
     mPt.mX = float(aPt.x);
     mPt.mY = float(aPt.y);
     NS_ASSERTION(NS_finite(mPt.mX) && NS_finite(mPt.mX),
                  "DOMSVGPoint coords are not finite");
   }
 
 
-  virtual ~DOMSVGPoint() {
-    // Our mList's weak ref to us must be nulled out when we die. If GC has
-    // unlinked us using the cycle collector code, then that has already
-    // happened, and mList is null.
-    if (mList) {
-      mList->mItems[mListIndex] = nullptr;
-    }
-  }
-
   // WebIDL
   virtual float X();
   virtual void SetX(float aX, ErrorResult& rv);
   virtual float Y();
   virtual void SetY(float aY, ErrorResult& rv);
   virtual already_AddRefed<nsISVGPoint> MatrixTransform(dom::SVGMatrix& matrix);
   nsISupports* GetParentObject() MOZ_OVERRIDE {
     return mList;
   }
 
-  /**
-   * Create an unowned copy of this object. The caller is responsible for the
-   * first AddRef()!
-   */
-  DOMSVGPoint* Clone() {
+  nsISVGPoint* Clone() {
     return new DOMSVGPoint(this);
   }
 
-  bool IsInList() const {
-    return !!mList;
-  }
-
-  /**
-   * In future, if this class is used for non-list points, this will be
-   * different to IsInList(). "Owner" here means that the instance has an
-   * internal counterpart from which it gets its values. (A better name may
-   * be HasWrappee().)
-   */
-  bool HasOwner() const {
-    return !!mList;
-  }
-
-  /**
-   * This method is called to notify this DOM object that it is being inserted
-   * into a list, and give it the information it needs as a result.
-   *
-   * This object MUST NOT already belong to a list when this method is called.
-   * That's not to say that script can't move these DOM objects between
-   * lists - it can - it's just that the logic to handle that (and send out
-   * the necessary notifications) is located elsewhere (in DOMSVGPointList).)
-   */
-  void InsertingIntoList(DOMSVGPointList *aList,
-                         uint32_t aListIndex,
-                         bool aIsAnimValItem);
-
-  static uint32_t MaxListIndex() {
-    return (1U << MOZ_SVG_LIST_INDEX_BIT_COUNT) - 1;
-  }
-
-  /// This method is called to notify this object that its list index changed.
-  void UpdateListIndex(uint32_t aListIndex) {
-    mListIndex = aListIndex;
-  }
-
-  /**
-   * This method is called to notify this DOM object that it is about to be
-   * removed from its current DOM list so that it can first make a copy of its
-   * internal counterpart's values. (If it didn't do this, then it would
-   * "lose" its value on being removed.)
-   */
-  void RemovingFromList();
-
-  SVGPoint ToSVGPoint() const {
-    return HasOwner() ? const_cast<DOMSVGPoint*>(this)->InternalItem() : mPt;
-  }
-
-  bool IsReadonly() const {
-    return mIsReadonly;
-  }
-  void SetReadonly(bool aReadonly) {
-    mIsReadonly = aReadonly;
-  }
-
 protected:
 
   nsSVGElement* Element() {
     return mList->Element();
   }
-
-  /**
-   * Get a reference to the internal SVGPoint list item that this DOM wrapper
-   * object currently wraps.
-   *
-   * To simplify the code we just have this one method for obtaining both
-   * baseVal and animVal internal items. This means that animVal items don't
-   * get const protection, but then our setter methods guard against changing
-   * animVal items.
-   */
-  SVGPoint& InternalItem();
-
-#ifdef DEBUG
-  bool IndexIsValid();
-#endif
-
-  nsRefPtr<DOMSVGPointList> mList;
-
-  // Bounds for the following are checked in the ctor, so be sure to update
-  // that if you change the capacity of any of the following.
-
-  uint32_t mListIndex:MOZ_SVG_LIST_INDEX_BIT_COUNT;
-  uint32_t mIsReadonly:1;    // uint32_t because MSVC won't pack otherwise
-  uint32_t mIsAnimValItem:1; // uint32_t because MSVC won't pack otherwise
-
-  // The following member is only used when we're not in a list:
-  SVGPoint mPt;
 };
 
-NS_DEFINE_STATIC_IID_ACCESSOR(DOMSVGPoint, MOZILLA_DOMSVGPOINT_IID)
-
 } // namespace mozilla
 
-#undef MOZ_SVG_LIST_INDEX_BIT_COUNT
-
 #endif // MOZILLA_DOMSVGPOINT_H__
--- a/content/svg/content/src/DOMSVGPointList.cpp
+++ b/content/svg/content/src/DOMSVGPointList.cpp
@@ -14,20 +14,18 @@
 #include "mozilla/dom/SVGPointListBinding.h"
 #include <algorithm>
 
 // See the comment in this file's header.
 
 // local helper functions
 namespace {
 
-using mozilla::DOMSVGPoint;
-
 void
-UpdateListIndicesFromIndex(nsTArray<DOMSVGPoint*>& aItemsArray,
+UpdateListIndicesFromIndex(nsTArray<mozilla::nsISVGPoint*>& aItemsArray,
                            uint32_t aStartingIndex)
 {
   uint32_t length = aItemsArray.Length();
 
   for (uint32_t i = aStartingIndex; i < length; ++i) {
     if (aItemsArray[i]) {
       aItemsArray[i]->UpdateListIndex(i);
     }
@@ -36,17 +34,16 @@ UpdateListIndicesFromIndex(nsTArray<DOMS
 
 } // namespace
 
 namespace mozilla {
 
 static nsSVGAttrTearoffTable<void, DOMSVGPointList>
   sSVGPointListTearoffTable;
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGPointList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGPointList)
   // No unlinking of mElement, we'd need to null out the value pointer (the
   // object it points to is held by the element) and null-check it everywhere.
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMSVGPointList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
@@ -105,20 +102,20 @@ DOMSVGPointList::InternalListWillChangeT
 {
   // When the number of items in our internal counterpart changes, we MUST stay
   // in sync. Everything in the scary comment in
   // DOMSVGLengthList::InternalBaseValListWillChangeTo applies here too!
 
   uint32_t oldLength = mItems.Length();
 
   uint32_t newLength = aNewValue.Length();
-  if (newLength > DOMSVGPoint::MaxListIndex()) {
+  if (newLength > nsISVGPoint::MaxListIndex()) {
     // It's safe to get out of sync with our internal list as long as we have
     // FEWER items than it does.
-    newLength = DOMSVGPoint::MaxListIndex();
+    newLength = nsISVGPoint::MaxListIndex();
   }
 
   nsRefPtr<DOMSVGPointList> kungFuDeathGrip;
   if (newLength < oldLength) {
     // RemovingFromList() might clear last reference to |this|.
     // Retain a temporary reference to keep from dying before returning.
     kungFuDeathGrip = this;
   }
@@ -210,21 +207,17 @@ DOMSVGPointList::Initialize(nsISVGPoint&
   // If aNewItem is already in a list we should insert a clone of aNewItem,
   // and for consistency, this should happen even if *this* is the list that
   // aNewItem is currently in. Note that in the case of aNewItem being in this
   // list, the Clear() call before the InsertItemBefore() call would remove it
   // from this list, and so the InsertItemBefore() call would not insert a
   // clone of aNewItem, it would actually insert aNewItem. To prevent that
   // from happening we have to do the clone here, if necessary.
 
-  nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(&aNewItem);
-  if (!domItem) {
-    aError.Throw(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR);
-    return nullptr;
-  }
+  nsCOMPtr<nsISVGPoint> domItem = &aNewItem;
   if (domItem->HasOwner() || domItem->IsReadonly()) {
     domItem = domItem->Clone(); // must do this before changing anything!
   }
 
   ErrorResult rv;
   Clear(rv);
   MOZ_ASSERT(!rv.Failed());
   return InsertItemBefore(*domItem, 0, aError);
@@ -250,26 +243,22 @@ DOMSVGPointList::InsertItemBefore(nsISVG
                                   ErrorResult& aError)
 {
   if (IsAnimValList()) {
     aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     return nullptr;
   }
 
   aIndex = std::min(aIndex, LengthNoFlush());
-  if (aIndex >= DOMSVGPoint::MaxListIndex()) {
+  if (aIndex >= nsISVGPoint::MaxListIndex()) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return nullptr;
   }
 
-  nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(&aNewItem);
-  if (!domItem) {
-    aError.Throw(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR);
-    return nullptr;
-  }
+  nsCOMPtr<nsISVGPoint> domItem = &aNewItem;
   if (domItem->HasOwner() || domItem->IsReadonly()) {
     domItem = domItem->Clone(); // must do this before changing anything!
   }
 
   // Ensure we have enough memory so we can avoid complex error handling below:
   if (!mItems.SetCapacity(mItems.Length() + 1) ||
       !InternalList().SetCapacity(InternalList().Length() + 1)) {
     aError.Throw(NS_ERROR_OUT_OF_MEMORY);
@@ -306,21 +295,17 @@ DOMSVGPointList::ReplaceItem(nsISVGPoint
     return nullptr;
   }
 
   if (aIndex >= LengthNoFlush()) {
     aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return nullptr;
   }
 
-  nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(&aNewItem);
-  if (!domItem) {
-    aError.Throw(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR);
-    return nullptr;
-  }
+  nsCOMPtr<nsISVGPoint> domItem = &aNewItem;
   if (domItem->HasOwner() || domItem->IsReadonly()) {
     domItem = domItem->Clone(); // must do this before changing anything!
   }
 
   nsAttrValue emptyOrOldValue = Element()->WillChangePointList();
   if (mItems[aIndex]) {
     // Notify any existing DOM item of removal *before* modifying the lists so
     // that the DOM item can copy the *old* value at its index:
@@ -361,17 +346,17 @@ DOMSVGPointList::RemoveItem(uint32_t aIn
   MaybeRemoveItemFromAnimValListAt(aIndex);
 
   // We have to return the removed item, so make sure it exists:
   EnsureItemAt(aIndex);
 
   // Notify the DOM item of removal *before* modifying the lists so that the
   // DOM item can copy its *old* value:
   mItems[aIndex]->RemovingFromList();
-  nsRefPtr<DOMSVGPoint> result = mItems[aIndex];
+  nsCOMPtr<nsISVGPoint> result = mItems[aIndex];
 
   InternalList().RemoveItem(aIndex);
   mItems.RemoveElementAt(aIndex);
 
   UpdateListIndicesFromIndex(mItems, aIndex);
 
   Element()->DidChangePointList(emptyOrOldValue);
   if (AttrIsAnimating()) {
@@ -404,17 +389,17 @@ DOMSVGPointList::MaybeInsertNullInAnimVa
   if (!animVal) {
     // No animVal list wrapper
     return;
   }
 
   NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(),
                     "animVal list not in sync!");
 
-  animVal->mItems.InsertElementAt(aIndex, static_cast<DOMSVGPoint*>(nullptr));
+  animVal->mItems.InsertElementAt(aIndex, static_cast<nsISVGPoint*>(nullptr));
 
   UpdateListIndicesFromIndex(animVal->mItems, aIndex + 1);
 }
 
 void
 DOMSVGPointList::MaybeRemoveItemFromAnimValListAt(uint32_t aIndex)
 {
   NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
--- a/content/svg/content/src/DOMSVGPointList.h
+++ b/content/svg/content/src/DOMSVGPointList.h
@@ -11,18 +11,16 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsSVGElement.h"
 #include "nsTArray.h"
 #include "SVGPointList.h" // IWYU pragma: keep
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
 
-class nsIDOMSVGPoint;
-
 namespace mozilla {
 
 class DOMSVGPoint;
 class nsISVGPoint;
 class SVGAnimatedPointList;
 
 /**
  * Class DOMSVGPointList
@@ -47,17 +45,18 @@ class SVGAnimatedPointList;
  * items are friends of us and responsible for nulling out our pointers to
  * them when they die.
  *
  * Our DOM items are created lazily on demand as and when script requests them.
  */
 class DOMSVGPointList MOZ_FINAL : public nsISupports,
                                   public nsWrapperCache
 {
-  friend class DOMSVGPoint;
+  friend class nsISVGPoint;
+  friend class mozilla::DOMSVGPoint;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPointList)
 
   virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
                                bool *triedToWrap);
 
@@ -203,28 +202,28 @@ private:
    * base val and anim val internal lists. This means that anim val lists don't
    * get const protection, but our setter methods guard against changing
    * anim val lists.
    */
   SVGPointList& InternalList() const;
 
   SVGAnimatedPointList& InternalAList() const;
 
-  /// Creates a DOMSVGPoint for aIndex, if it doesn't already exist.
+  /// Creates an nsISVGPoint for aIndex, if it doesn't already exist.
   void EnsureItemAt(uint32_t aIndex);
 
   void MaybeInsertNullInAnimValListAt(uint32_t aIndex);
   void MaybeRemoveItemFromAnimValListAt(uint32_t aIndex);
 
-  // Weak refs to our DOMSVGPoint items. The items are friends and take care
+  // Weak refs to our nsISVGPoint items. The items are friends and take care
   // of clearing our pointer to them when they die.
-  nsTArray<DOMSVGPoint*> mItems;
+  nsTArray<nsISVGPoint*> mItems;
 
   // Strong ref to our element to keep it alive. We hold this not only for
-  // ourself, but also for our DOMSVGPoint items too.
+  // ourself, but also for our nsISVGPoint items too.
   nsRefPtr<nsSVGElement> mElement;
 
   bool mIsAnimValList;
 };
 
 } // namespace mozilla
 
 #endif // MOZILLA_DOMSVGPOINTLIST_H__
--- a/content/svg/content/src/DOMSVGTransform.cpp
+++ b/content/svg/content/src/DOMSVGTransform.cpp
@@ -22,17 +22,16 @@ static nsSVGAttrTearoffTable<DOMSVGTrans
 
 //----------------------------------------------------------------------
 // nsISupports methods:
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our list's weak ref to us to be safe. (The other option would be to
 // not unlink and rely on the breaking of the other edges in the cycle, as
 // NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGTransform)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGTransform)
   // We may not belong to a list, so we must null check tmp->mList.
   if (tmp->mList) {
     tmp->mList->mItems[tmp->mListIndex] = nullptr;
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/svg/content/src/DOMSVGTransformList.cpp
+++ b/content/svg/content/src/DOMSVGTransformList.cpp
@@ -32,17 +32,16 @@ void UpdateListIndicesFromIndex(
 } // anonymous namespace
 
 namespace mozilla {
 
 // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
 // clear our DOMSVGAnimatedTransformList's weak ref to us to be safe. (The other
 // option would be to not unlink and rely on the breaking of the other edges in
 // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
-NS_IMPL_CYCLE_COLLECTION_CLASS(DOMSVGTransformList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGTransformList)
   if (tmp->mAList) {
     if (tmp->IsAnimValList()) {
       tmp->mAList->mAnimVal = nullptr;
     } else {
       tmp->mAList->mBaseVal = nullptr;
     }
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mAList)
--- a/content/svg/content/src/Makefile.in
+++ b/content/svg/content/src/Makefile.in
@@ -30,16 +30,17 @@ CPPSRCS		= \
 		DOMSVGPoint.cpp \
 		DOMSVGPointList.cpp \
 		DOMSVGStringList.cpp \
 		DOMSVGTests.cpp \
 		DOMSVGTransform.cpp \
 		DOMSVGTransformList.cpp \
 		nsDOMSVGZoomEvent.cpp \
 		nsDOMSVGEvent.cpp \
+		nsISVGPoint.cpp \
 		nsSVGAngle.cpp \
 		nsSVGBoolean.cpp \
 		nsSVGClass.cpp \
 		nsSVGClipPathElement.cpp \
 		nsSVGDataParser.cpp \
 		nsSVGElement.cpp \
 		nsSVGElementFactory.cpp \
 		nsSVGEnum.cpp \
@@ -50,23 +51,20 @@ CPPSRCS		= \
 		nsSVGIntegerPair.cpp \
 		nsSVGLength2.cpp \
 		nsSVGMarkerElement.cpp \
 		nsSVGMaskElement.cpp \
 		nsSVGNumber2.cpp \
 		nsSVGNumberPair.cpp \
 		nsSVGPathDataParser.cpp \
 		nsSVGPathGeometryElement.cpp \
-		nsSVGPatternElement.cpp \
 		nsSVGPolyElement.cpp \
 		nsSVGString.cpp \
 		nsSVGRect.cpp \
-		nsSVGSymbolElement.cpp \
 		nsSVGUnknownElement.cpp \
-		nsSVGUseElement.cpp \
 		nsSVGViewBox.cpp \
 		SVGAElement.cpp \
 		SVGAltGlyphElement.cpp \
 		SVGAngle.cpp \
 		SVGAnimatedAngle.cpp \
 		SVGAnimatedBoolean.cpp \
 		SVGAnimatedLengthList.cpp \
 		SVGAnimatedNumberList.cpp \
@@ -106,40 +104,43 @@ CPPSRCS		= \
 		SVGNumberList.cpp \
 		SVGNumberListSMILType.cpp \
 		SVGNumberPairSMILType.cpp \
 		SVGOrientSMILType.cpp \
 		SVGPathData.cpp \
 		SVGPathElement.cpp \
 		SVGPathSegUtils.cpp \
 		SVGPathSegListSMILType.cpp \
+		SVGPatternElement.cpp \
 		SVGPointList.cpp \
 		SVGPointListSMILType.cpp \
 		SVGPolygonElement.cpp \
 		SVGPolylineElement.cpp \
 		SVGPreserveAspectRatio.cpp \
 		SVGRectElement.cpp \
 		SVGScriptElement.cpp \
 		SVGSetElement.cpp \
 		SVGStopElement.cpp \
 		SVGStringList.cpp \
 		SVGStyleElement.cpp \
+		SVGSymbolElement.cpp \
 		SVGSVGElement.cpp \
 		SVGSwitchElement.cpp \
 		SVGTextContentElement.cpp \
 		SVGTextElement.cpp \
 		SVGTextPathElement.cpp \
 		SVGTextPositioningElement.cpp \
 		SVGTitleElement.cpp \
 		SVGTransform.cpp \
 		SVGTransformableElement.cpp \
 		SVGTransformList.cpp \
 		SVGTransformListParser.cpp \
 		SVGTransformListSMILType.cpp \
 		SVGTSpanElement.cpp \
+		SVGUseElement.cpp \
 		SVGViewBoxSMILType.cpp \
 		SVGViewElement.cpp \
 		$(NULL)
 
 include $(topsrcdir)/config/config.mk
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
@@ -172,32 +173,35 @@ EXPORTS_mozilla/dom = \
 	SVGGraphicsElement.h \
 	SVGImageElement.h \
 	SVGLineElement.h \
 	SVGLocatableElement.h \
 	SVGMatrix.h \
 	SVGMetadataElement.h \
 	SVGMPathElement.h \
 	SVGPathElement.h \
+	SVGPatternElement.h \
 	SVGPolygonElement.h \
 	SVGPolylineElement.h \
 	SVGRectElement.h \
 	SVGScriptElement.h \
 	SVGSetElement.h \
 	SVGStopElement.h \
 	SVGStyleElement.h \
+	SVGSymbolElement.h \
 	SVGSVGElement.h \
 	SVGSwitchElement.h \
 	SVGTextContentElement.h \
 	SVGTextElement.h \
 	SVGTextPathElement.h \
 	SVGTextPositioningElement.h \
 	SVGTitleElement.h \
 	SVGTransformableElement.h \
 	SVGTSpanElement.h \
+	SVGUseElement.h \
 	SVGViewElement.h \
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES += 	\
 		-I$(srcdir)/../../../xml/content/src \
 		-I$(srcdir)/../../../../dom \
--- a/content/svg/content/src/SVGAnimationElement.cpp
+++ b/content/svg/content/src/SVGAnimationElement.cpp
@@ -22,17 +22,16 @@ NS_IMPL_RELEASE_INHERITED(SVGAnimationEl
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SVGAnimationElement)
   NS_INTERFACE_MAP_ENTRY(nsISMILAnimationElement)
   NS_INTERFACE_MAP_ENTRY(nsIDOMElementTimeControl)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTests)
 NS_INTERFACE_MAP_END_INHERITING(SVGAnimationElementBase)
 
 // Cycle collection magic -- based on nsSVGUseElement
-NS_IMPL_CYCLE_COLLECTION_CLASS(SVGAnimationElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGAnimationElement,
                                                 SVGAnimationElementBase)
   tmp->mHrefTarget.Unlink();
   tmp->mTimedElement.Unlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGAnimationElement,
                                                   SVGAnimationElementBase)
--- a/content/svg/content/src/SVGGraphicsElement.cpp
+++ b/content/svg/content/src/SVGGraphicsElement.cpp
@@ -4,22 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGGraphicsElement.h"
 #include "mozilla/dom/SVGGraphicsElementBinding.h"
 
 namespace mozilla {
 namespace dom {
 
-JSObject*
-SVGGraphicsElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
-{
-  return SVGGraphicsElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
-}
-
 //----------------------------------------------------------------------
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(SVGGraphicsElement, SVGGraphicsElementBase)
 NS_IMPL_RELEASE_INHERITED(SVGGraphicsElement, SVGGraphicsElementBase)
 
 NS_INTERFACE_MAP_BEGIN(SVGGraphicsElement)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTests)
--- a/content/svg/content/src/SVGGraphicsElement.h
+++ b/content/svg/content/src/SVGGraphicsElement.h
@@ -4,42 +4,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SVGGraphicsElement_h
 #define mozilla_dom_SVGGraphicsElement_h
 
 #include "mozilla/dom/SVGTransformableElement.h"
 #include "DOMSVGTests.h"
 
-#define MOZILLA_SVGGRAPHICSELEMENT_IID \
-  { 0xe57b8fe5, 0x9088, 0x446e, \
-    {0xa1, 0x87, 0xd1, 0xdb, 0xbb, 0x58, 0xce, 0xdc}}
-
 namespace mozilla {
 namespace dom {
 
 typedef SVGTransformableElement SVGGraphicsElementBase;
 
 class SVGGraphicsElement : public SVGGraphicsElementBase,
                            public DOMSVGTests
 {
 protected:
   SVGGraphicsElement(already_AddRefed<nsINodeInfo> aNodeInfo);
 
 public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_SVGGRAPHICSELEMENT_IID)
-  NS_FORWARD_NSIDOMSVGLOCATABLE(SVGLocatableElement::)
-  NS_FORWARD_NSIDOMSVGTRANSFORMABLE(SVGTransformableElement::)
-
-protected:
-  virtual JSObject* WrapNode(JSContext *cx, JSObject *scope, bool *triedToWrap) MOZ_OVERRIDE;
-
 };
 
-NS_DEFINE_STATIC_IID_ACCESSOR(SVGGraphicsElement,
-                              MOZILLA_SVGGRAPHICSELEMENT_IID)
-
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_SVGGraphicsElement_h
--- a/content/svg/content/src/SVGLocatableElement.cpp
+++ b/content/svg/content/src/SVGLocatableElement.cpp
@@ -16,61 +16,34 @@ namespace dom {
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(SVGLocatableElement, nsSVGElement)
 NS_IMPL_RELEASE_INHERITED(SVGLocatableElement, nsSVGElement)
 
 NS_INTERFACE_MAP_BEGIN(SVGLocatableElement)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLocatable)
+  NS_INTERFACE_MAP_ENTRY(mozilla::dom::SVGLocatableElement)
 NS_INTERFACE_MAP_END_INHERITING(nsSVGElement)
 
 
 //----------------------------------------------------------------------
-// nsIDOMSVGLocatable methods
-
-/* readonly attribute nsIDOMSVGElement nearestViewportElement; */
-NS_IMETHODIMP
-SVGLocatableElement::GetNearestViewportElement(nsIDOMSVGElement * *aNearestViewportElement)
-{
-  nsCOMPtr<nsIDOMSVGElement> domElem = do_QueryInterface(GetNearestViewportElement());
-  domElem.forget(aNearestViewportElement);
-  return NS_OK;
-}
 
 nsSVGElement*
 SVGLocatableElement::GetNearestViewportElement()
 {
   return SVGContentUtils::GetNearestViewportElement(this);
 }
 
-/* readonly attribute nsIDOMSVGElement farthestViewportElement; */
-NS_IMETHODIMP
-SVGLocatableElement::GetFarthestViewportElement(nsIDOMSVGElement * *aFarthestViewportElement)
-{
-  NS_IF_ADDREF(*aFarthestViewportElement = SVGContentUtils::GetOuterSVGElement(this));
-  return NS_OK;
-}
-
 nsSVGElement*
 SVGLocatableElement::GetFarthestViewportElement()
 {
   return SVGContentUtils::GetOuterSVGElement(this);
 }
 
-/* nsIDOMSVGRect getBBox (); */
-NS_IMETHODIMP
-SVGLocatableElement::GetBBox(nsIDOMSVGRect **_retval)
-{
-  ErrorResult rv;
-  *_retval = GetBBox(rv).get();
-  return rv.ErrorCode();
-}
-
 already_AddRefed<nsIDOMSVGRect>
 SVGLocatableElement::GetBBox(ErrorResult& rv)
 {
   nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
 
   if (!frame || (frame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
     rv.Throw(NS_ERROR_FAILURE);
     return nullptr;
@@ -82,75 +55,39 @@ SVGLocatableElement::GetBBox(ErrorResult
     return nullptr;
   }
 
   nsCOMPtr<nsIDOMSVGRect> rect;
   rv = NS_NewSVGRect(getter_AddRefs(rect), nsSVGUtils::GetBBox(frame));
   return rect.forget();
 }
 
-/* SVGMatrix getCTM (); */
-NS_IMETHODIMP
-SVGLocatableElement::GetCTM(nsISupports * *aCTM)
-{
-  *aCTM = GetCTM().get();
-  return NS_OK;
-}
-
 already_AddRefed<SVGMatrix>
 SVGLocatableElement::GetCTM()
 {
   gfxMatrix m = SVGContentUtils::GetCTM(this, false);
   nsCOMPtr<SVGMatrix> mat = m.IsSingular() ? nullptr : new SVGMatrix(m);
   return mat.forget();
 }
 
-/* SVGMatrix getScreenCTM (); */
-NS_IMETHODIMP
-SVGLocatableElement::GetScreenCTM(nsISupports * *aCTM)
-{
-  *aCTM = GetScreenCTM().get();
-  return NS_OK;
-}
-
 already_AddRefed<SVGMatrix>
 SVGLocatableElement::GetScreenCTM()
 {
   gfxMatrix m = SVGContentUtils::GetCTM(this, true);
   nsCOMPtr<SVGMatrix> mat = m.IsSingular() ? nullptr : new SVGMatrix(m);
   return mat.forget();
 }
 
-/* SVGMatrix getTransformToElement (in nsIDOMSVGElement element); */
-NS_IMETHODIMP
-SVGLocatableElement::GetTransformToElement(nsIDOMSVGElement *element,
-                                           nsISupports **_retval)
-{
-  nsCOMPtr<nsSVGElement> elem = do_QueryInterface(element);
-  if (!elem)
-    return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
-  ErrorResult rv;
-  *_retval = GetTransformToElement(*elem, rv).get();
-  return rv.ErrorCode();
-}
-
 already_AddRefed<SVGMatrix>
-SVGLocatableElement::GetTransformToElement(nsSVGElement& aElement,
+SVGLocatableElement::GetTransformToElement(SVGLocatableElement& aElement,
                                            ErrorResult& rv)
 {
-  nsCOMPtr<nsIDOMSVGLocatable> target = do_QueryInterface(&aElement);
-  if (!target) {
-    rv.Throw(NS_NOINTERFACE);
-    return nullptr;
-  }
-
   // the easiest way to do this (if likely to increase rounding error):
   nsCOMPtr<SVGMatrix> ourScreenCTM = GetScreenCTM();
-  nsCOMPtr<SVGMatrix> targetScreenCTM;
-  target->GetScreenCTM(getter_AddRefs(targetScreenCTM));
+  nsCOMPtr<SVGMatrix> targetScreenCTM = aElement.GetScreenCTM();
   if (!ourScreenCTM || !targetScreenCTM) {
     rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
   nsCOMPtr<SVGMatrix> tmp = targetScreenCTM->Inverse(rv);
   if (rv.Failed()) return nullptr;
 
   nsCOMPtr<SVGMatrix> mat = tmp->Multiply(*ourScreenCTM).get();
--- a/content/svg/content/src/SVGLocatableElement.h
+++ b/content/svg/content/src/SVGLocatableElement.h
@@ -2,46 +2,45 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef SVGLocatableElement_h
 #define SVGLocatableElement_h
 
 #include "nsSVGElement.h"
-#include "nsIDOMSVGLocatable.h"
 
 #define MOZILLA_SVGLOCATABLEELEMENT_IID \
   { 0xe20176ba, 0xc48d, 0x4704, \
     {0x89, 0xec, 0xe6, 0x69, 0x6c, 0xb7, 0xb8, 0xb3} }
 
+class nsIDOMSVGRect;
+
 namespace mozilla {
 
 namespace dom {
 class SVGMatrix;
 
-class SVGLocatableElement : public nsSVGElement,
-                            public nsIDOMSVGLocatable
+class SVGLocatableElement : public nsSVGElement
 {
 public:
   SVGLocatableElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsSVGElement(aNodeInfo) {}
   virtual ~SVGLocatableElement() {}
 
   NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_SVGLOCATABLEELEMENT_IID)
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIDOMSVGLOCATABLE
 
   // WebIDL
   nsSVGElement* GetNearestViewportElement();
   nsSVGElement* GetFarthestViewportElement();
   already_AddRefed<nsIDOMSVGRect> GetBBox(ErrorResult& rv);
   already_AddRefed<SVGMatrix> GetCTM();
   already_AddRefed<SVGMatrix> GetScreenCTM();
-  already_AddRefed<SVGMatrix> GetTransformToElement(nsSVGElement& aElement,
+  already_AddRefed<SVGMatrix> GetTransformToElement(SVGLocatableElement& aElement,
                                                     ErrorResult& rv);
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(SVGLocatableElement,
                               MOZILLA_SVGLOCATABLEELEMENT_IID)
 
 } // namespace dom
 } // namespace mozilla
--- a/content/svg/content/src/SVGMPathElement.cpp
+++ b/content/svg/content/src/SVGMPathElement.cpp
@@ -27,17 +27,16 @@ SVGMPathElement::WrapNode(JSContext *aCx
 }
 
 nsSVGElement::StringInfo SVGMPathElement::sStringInfo[1] =
 {
   { &nsGkAtoms::href, kNameSpaceID_XLink, false }
 };
 
 // Cycle collection magic -- based on nsSVGUseElement
-NS_IMPL_CYCLE_COLLECTION_CLASS(SVGMPathElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGMPathElement,
                                                 SVGMPathElementBase)
   tmp->UnlinkHrefTarget(false);
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGMPathElement,
                                                   SVGMPathElementBase)
   tmp->mHrefTarget.Traverse(&cb);
--- a/content/svg/content/src/SVGMatrix.cpp
+++ b/content/svg/content/src/SVGMatrix.cpp
@@ -13,30 +13,17 @@
 const double radPerDegree = 2.0 * M_PI / 360.0;
 
 namespace mozilla {
 namespace dom {
 
 //----------------------------------------------------------------------
 // nsISupports methods:
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(SVGMatrix)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SVGMatrix)
-NS_IMPL_CYCLE_COLLECTION_UNLINK(mTransform)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(SVGMatrix)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransform)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(SVGMatrix)
-NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
+  NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(SVGMatrix, mTransform)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(SVGMatrix)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(SVGMatrix)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SVGMatrix)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(mozilla::dom::SVGMatrix) // pseudo-interface
   NS_INTERFACE_MAP_ENTRY(nsISupports)
--- a/content/svg/content/src/SVGPathElement.cpp
+++ b/content/svg/content/src/SVGPathElement.cpp
@@ -9,302 +9,490 @@
 #include "DOMSVGPathSeg.h"
 #include "DOMSVGPathSegList.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/SVGPathElement.h"
 #include "DOMSVGPoint.h"
 #include "gfxContext.h"
 #include <algorithm>
+#include "mozilla/dom/SVGPathElementBinding.h"
 
 DOMCI_NODE_DATA(SVGPathElement, mozilla::dom::SVGPathElement)
 
 NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Path)
 
 namespace mozilla {
 namespace dom {
 
+JSObject*
+SVGPathElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
+{
+  return SVGPathElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
+
 nsSVGElement::NumberInfo SVGPathElement::sNumberInfo = 
 { &nsGkAtoms::pathLength, 0, false };
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(SVGPathElement,SVGPathElementBase)
 NS_IMPL_RELEASE_INHERITED(SVGPathElement,SVGPathElementBase)
 
 NS_INTERFACE_TABLE_HEAD(SVGPathElement)
-  NS_NODE_INTERFACE_TABLE5(SVGPathElement, nsIDOMNode, nsIDOMElement,
+  NS_NODE_INTERFACE_TABLE4(SVGPathElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement,
-                           nsIDOMSVGPathElement, nsIDOMSVGAnimatedPathData)
+                           nsIDOMSVGPathElement)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPathElement)
 NS_INTERFACE_MAP_END_INHERITING(SVGPathElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 SVGPathElement::SVGPathElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : SVGPathElementBase(aNodeInfo)
 {
+  SetIsDOMBinding();
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGPathElement)
 
 //----------------------------------------------------------------------
 // nsIDOMSVGPathElement methods:
 
 /* readonly attribute nsIDOMSVGAnimatedNumber pathLength; */
 NS_IMETHODIMP
 SVGPathElement::GetPathLength(nsIDOMSVGAnimatedNumber * *aPathLength)
 {
-  return mPathLength.ToDOMAnimatedNumber(aPathLength, this);
+  *aPathLength = PathLength().get();
+  return NS_OK;
+}
+
+already_AddRefed<nsIDOMSVGAnimatedNumber>
+SVGPathElement::PathLength()
+{
+  nsCOMPtr<nsIDOMSVGAnimatedNumber> number;
+  mPathLength.ToDOMAnimatedNumber(getter_AddRefs(number), this);
+  return number.forget();
 }
 
 /* float getTotalLength (); */
 NS_IMETHODIMP
 SVGPathElement::GetTotalLength(float *_retval)
 {
-  *_retval = 0;
+  ErrorResult rv;
+  *_retval = GetTotalLength(rv);
+  return rv.ErrorCode();
+}
 
+float
+SVGPathElement::GetTotalLength(ErrorResult& rv)
+{
   nsRefPtr<gfxFlattenedPath> flat = GetFlattenedPath(gfxMatrix());
 
-  if (!flat)
-    return NS_ERROR_FAILURE;
+  if (!flat) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return 0.f;
+  }
 
-  *_retval = flat->GetLength();
-
-  return NS_OK;
+  return flat->GetLength();
 }
 
 /* DOMSVGPoint getPointAtLength (in float distance); */
 NS_IMETHODIMP
 SVGPathElement::GetPointAtLength(float distance, nsISupports **_retval)
 {
   NS_ENSURE_FINITE(distance, NS_ERROR_ILLEGAL_VALUE);
 
+  ErrorResult rv;
+  *_retval = GetPointAtLength(distance, rv).get();
+  return rv.ErrorCode();
+}
+
+already_AddRefed<nsISVGPoint>
+SVGPathElement::GetPointAtLength(float distance, ErrorResult& rv)
+{
   nsRefPtr<gfxFlattenedPath> flat = GetFlattenedPath(gfxMatrix());
-  if (!flat)
-    return NS_ERROR_FAILURE;
+  if (!flat) {
+    rv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
 
   float totalLength = flat->GetLength();
   if (mPathLength.IsExplicitlySet()) {
     float pathLength = mPathLength.GetAnimValue();
     if (pathLength <= 0) {
-      return NS_ERROR_FAILURE;
+      rv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
     }
     distance *= totalLength / pathLength;
   }
   distance = std::max(0.f,         distance);
   distance = std::min(totalLength, distance);
 
-  NS_ADDREF(*_retval = new DOMSVGPoint(flat->FindPoint(gfxPoint(distance, 0))));
-  return NS_OK;
+  nsCOMPtr<nsISVGPoint> point = new DOMSVGPoint(flat->FindPoint(gfxPoint(distance, 0)));
+  return point.forget();
 }
 
 /* unsigned long getPathSegAtLength (in float distance); */
 NS_IMETHODIMP
 SVGPathElement::GetPathSegAtLength(float distance, uint32_t *_retval)
 {
   NS_ENSURE_FINITE(distance, NS_ERROR_ILLEGAL_VALUE);
-  *_retval = mD.GetAnimValue().GetPathSegAtLength(distance);
+  *_retval = GetPathSegAtLength(distance);
   return NS_OK;
 }
 
+uint32_t
+SVGPathElement::GetPathSegAtLength(float distance)
+{
+  return mD.GetAnimValue().GetPathSegAtLength(distance);
+}
+
 /* nsISupports createSVGPathSegClosePath (); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegClosePath(nsISupports **_retval)
 {
-  nsISupports* seg = NS_NewSVGPathSegClosePath();
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegClosePath().get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegClosePath>
+SVGPathElement::CreateSVGPathSegClosePath()
+{
+  nsRefPtr<DOMSVGPathSegClosePath> pathSeg = new DOMSVGPathSegClosePath();
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegMovetoAbs (in float x, in float y); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegMovetoAbs(float x, float y, nsISupports **_retval)
 {
   NS_ENSURE_FINITE2(x, y, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegMovetoAbs(x, y);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegMovetoAbs(x, y).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegMovetoAbs>
+SVGPathElement::CreateSVGPathSegMovetoAbs(float x, float y)
+{
+  nsRefPtr<DOMSVGPathSegMovetoAbs> pathSeg = new DOMSVGPathSegMovetoAbs(x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegMovetoRel (in float x, in float y); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegMovetoRel(float x, float y, nsISupports **_retval)
 {
   NS_ENSURE_FINITE2(x, y, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegMovetoRel(x, y);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegMovetoRel(x, y).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegMovetoRel>
+SVGPathElement::CreateSVGPathSegMovetoRel(float x, float y)
+{
+  nsRefPtr<DOMSVGPathSegMovetoRel> pathSeg = new DOMSVGPathSegMovetoRel(x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegLinetoAbs (in float x, in float y); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegLinetoAbs(float x, float y, nsISupports **_retval)
 {
   NS_ENSURE_FINITE2(x, y, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegLinetoAbs(x, y);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegLinetoAbs(x, y).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegLinetoAbs>
+SVGPathElement::CreateSVGPathSegLinetoAbs(float x, float y)
+{
+  nsRefPtr<DOMSVGPathSegLinetoAbs> pathSeg = new DOMSVGPathSegLinetoAbs(x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegLinetoRel (in float x, in float y); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegLinetoRel(float x, float y, nsISupports **_retval)
 {
   NS_ENSURE_FINITE2(x, y, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegLinetoRel(x, y);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegLinetoRel(x, y).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegLinetoRel>
+SVGPathElement::CreateSVGPathSegLinetoRel(float x, float y)
+{
+  nsRefPtr<DOMSVGPathSegLinetoRel> pathSeg = new DOMSVGPathSegLinetoRel(x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegCurvetoCubicAbs (in float x, in float y, in float x1, in float y1, in float x2, in float y2); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2, nsISupports **_retval)
 {
   NS_ENSURE_FINITE6(x, y, x1, y1, x2, y2, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegCurvetoCubicAbs(x, y, x1, y1, x2, y2);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegCurvetoCubicAbs(x, y, x1, y1, x2, y2).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegCurvetoCubicAbs>
+SVGPathElement::CreateSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2)
+{
+  // Note that we swap from DOM API argument order to the argument order used
+  // in the <path> element's 'd' attribute (i.e. we put the arguments for the
+  // end point of the segment last instead of first).
+  nsRefPtr<DOMSVGPathSegCurvetoCubicAbs> pathSeg =
+    new DOMSVGPathSegCurvetoCubicAbs(x1, y1, x2, y2, x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegCurvetoCubicRel (in float x, in float y, in float x1, in float y1, in float x2, in float y2); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2, nsISupports **_retval)
 {
   NS_ENSURE_FINITE6(x, y, x1, y1, x2, y2, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegCurvetoCubicRel(x, y, x1, y1, x2, y2);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegCurvetoCubicRel(x, y, x1, y1, x2, y2).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegCurvetoCubicRel>
+SVGPathElement::CreateSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2)
+{
+  // See comment in CreateSVGPathSegCurvetoCubicAbs
+  nsRefPtr<DOMSVGPathSegCurvetoCubicRel> pathSeg =
+    new DOMSVGPathSegCurvetoCubicRel(x1, y1, x2, y2, x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegCurvetoQuadraticAbs (in float x, in float y, in float x1, in float y1); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1, nsISupports **_retval)
 {
   NS_ENSURE_FINITE4(x, y, x1, y1, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegCurvetoQuadraticAbs(x, y, x1, y1);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegCurvetoQuadraticAbs(x, y, x1, y1).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegCurvetoQuadraticAbs>
+SVGPathElement::CreateSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1)
+{
+  // See comment in CreateSVGPathSegCurvetoCubicAbs
+  nsRefPtr<DOMSVGPathSegCurvetoQuadraticAbs> pathSeg =
+    new DOMSVGPathSegCurvetoQuadraticAbs(x1, y1, x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegCurvetoQuadraticRel (in float x, in float y, in float x1, in float y1); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1, nsISupports **_retval)
 {
   NS_ENSURE_FINITE4(x, y, x1, y1, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegCurvetoQuadraticRel(x, y, x1, y1);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegCurvetoQuadraticRel(x, y, x1, y1).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegCurvetoQuadraticRel>
+SVGPathElement::CreateSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1)
+{
+  // See comment in CreateSVGPathSegCurvetoCubicAbs
+  nsRefPtr<DOMSVGPathSegCurvetoQuadraticRel> pathSeg =
+    new DOMSVGPathSegCurvetoQuadraticRel(x1, y1, x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegArcAbs (in float x, in float y, in float r1, in float r2, in float angle, in boolean largeArcFlag, in boolean sweepFlag); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag, nsISupports **_retval)
 {
   NS_ENSURE_FINITE5(x, y, r1, r2, angle, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegArcAbs(x, y, r1, r2, angle,
-                                                 largeArcFlag, sweepFlag);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegArcAbs(x, y, r1, r2, angle, largeArcFlag, sweepFlag).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegArcAbs>
+SVGPathElement::CreateSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
+{
+  // See comment in CreateSVGPathSegCurvetoCubicAbs
+  nsRefPtr<DOMSVGPathSegArcAbs> pathSeg =
+    new DOMSVGPathSegArcAbs(r1, r2, angle, largeArcFlag, sweepFlag, x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegArcRel (in float x, in float y, in float r1, in float r2, in float angle, in boolean largeArcFlag, in boolean sweepFlag); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag, nsISupports **_retval)
 {
   NS_ENSURE_FINITE5(x, y, r1, r2, angle, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegArcRel(x, y, r1, r2, angle,
-                                                 largeArcFlag, sweepFlag);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegArcRel(x, y, r1, r2, angle, largeArcFlag, sweepFlag).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegArcRel>
+SVGPathElement::CreateSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
+{
+  // See comment in CreateSVGPathSegCurvetoCubicAbs
+  nsRefPtr<DOMSVGPathSegArcRel> pathSeg =
+    new DOMSVGPathSegArcRel(r1, r2, angle, largeArcFlag, sweepFlag, x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegLinetoHorizontalAbs (in float x); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegLinetoHorizontalAbs(float x, nsISupports **_retval)
 {
   NS_ENSURE_FINITE(x, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegLinetoHorizontalAbs(x);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegLinetoHorizontalAbs(x).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegLinetoHorizontalAbs>
+SVGPathElement::CreateSVGPathSegLinetoHorizontalAbs(float x)
+{
+  nsRefPtr<DOMSVGPathSegLinetoHorizontalAbs> pathSeg =
+    new DOMSVGPathSegLinetoHorizontalAbs(x);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegLinetoHorizontalRel (in float x); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegLinetoHorizontalRel(float x, nsISupports **_retval)
 {
   NS_ENSURE_FINITE(x, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegLinetoHorizontalRel(x);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegLinetoHorizontalRel(x).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegLinetoHorizontalRel>
+SVGPathElement::CreateSVGPathSegLinetoHorizontalRel(float x)
+{
+  nsRefPtr<DOMSVGPathSegLinetoHorizontalRel> pathSeg =
+    new DOMSVGPathSegLinetoHorizontalRel(x);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegLinetoVerticalAbs (in float y); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegLinetoVerticalAbs(float y, nsISupports **_retval)
 {
   NS_ENSURE_FINITE(y, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegLinetoVerticalAbs(y);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegLinetoVerticalAbs(y).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegLinetoVerticalAbs>
+SVGPathElement::CreateSVGPathSegLinetoVerticalAbs(float y)
+{
+  nsRefPtr<DOMSVGPathSegLinetoVerticalAbs> pathSeg =
+    new DOMSVGPathSegLinetoVerticalAbs(y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegLinetoVerticalRel (in float y); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegLinetoVerticalRel(float y, nsISupports **_retval)
 {
   NS_ENSURE_FINITE(y, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegLinetoVerticalRel(y);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegLinetoVerticalRel(y).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegLinetoVerticalRel>
+SVGPathElement::CreateSVGPathSegLinetoVerticalRel(float y)
+{
+  nsRefPtr<DOMSVGPathSegLinetoVerticalRel> pathSeg =
+    new DOMSVGPathSegLinetoVerticalRel(y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegCurvetoCubicSmoothAbs (in float x, in float y, in float x2, in float y2); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2, nsISupports **_retval)
 {
   NS_ENSURE_FINITE4(x, y, x2, y2, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegCurvetoCubicSmoothAbs(x, y, x2, y2);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegCurvetoCubicSmoothAbs(x, y, x2, y2).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegCurvetoCubicSmoothAbs>
+SVGPathElement::CreateSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2)
+{
+  // See comment in CreateSVGPathSegCurvetoCubicAbs
+  nsRefPtr<DOMSVGPathSegCurvetoCubicSmoothAbs> pathSeg =
+    new DOMSVGPathSegCurvetoCubicSmoothAbs(x2, y2, x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegCurvetoCubicSmoothRel (in float x, in float y, in float x2, in float y2); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2, nsISupports **_retval)
 {
   NS_ENSURE_FINITE4(x, y, x2, y2, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegCurvetoCubicSmoothRel(x, y, x2, y2);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegCurvetoCubicSmoothRel(x, y, x2, y2).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegCurvetoCubicSmoothRel>
+SVGPathElement::CreateSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2)
+{
+  // See comment in CreateSVGPathSegCurvetoCubicAbs
+  nsRefPtr<DOMSVGPathSegCurvetoCubicSmoothRel> pathSeg =
+    new DOMSVGPathSegCurvetoCubicSmoothRel(x2, y2, x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegCurvetoQuadraticSmoothAbs (in float x, in float y); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y, nsISupports **_retval)
 {
   NS_ENSURE_FINITE2(x, y, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegCurvetoQuadraticSmoothAbs(x, y);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegCurvetoQuadraticSmoothAbs(x, y).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegCurvetoQuadraticSmoothAbs>
+SVGPathElement::CreateSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y)
+{
+  nsRefPtr<DOMSVGPathSegCurvetoQuadraticSmoothAbs> pathSeg =
+    new DOMSVGPathSegCurvetoQuadraticSmoothAbs(x, y);
+  return pathSeg.forget();
 }
 
 /* nsISupports createSVGPathSegCurvetoQuadraticSmoothRel (in float x, in float y); */
 NS_IMETHODIMP
 SVGPathElement::CreateSVGPathSegCurvetoQuadraticSmoothRel(float x, float y, nsISupports **_retval)
 {
   NS_ENSURE_FINITE2(x, y, NS_ERROR_ILLEGAL_VALUE);
-  nsISupports* seg = NS_NewSVGPathSegCurvetoQuadraticSmoothRel(x, y);
-  NS_ENSURE_TRUE(seg, NS_ERROR_OUT_OF_MEMORY);
-  return CallQueryInterface(seg, _retval);
+  *_retval = CreateSVGPathSegCurvetoQuadraticSmoothRel(x, y).get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGPathSegCurvetoQuadraticSmoothRel>
+SVGPathElement::CreateSVGPathSegCurvetoQuadraticSmoothRel(float x, float y)
+{
+  nsRefPtr<DOMSVGPathSegCurvetoQuadraticSmoothRel> pathSeg =
+    new DOMSVGPathSegCurvetoQuadraticSmoothRel(x, y);
+  return pathSeg.forget();
+}
+
+already_AddRefed<DOMSVGPathSegList>
+SVGPathElement::PathSegList()
+{
+  return DOMSVGPathSegList::GetDOMWrapper(mD.GetBaseValKey(), this, false);
+}
+
+already_AddRefed<DOMSVGPathSegList>
+SVGPathElement::AnimatedPathSegList()
+{
+  return DOMSVGPathSegList::GetDOMWrapper(mD.GetAnimValKey(), this, true);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 /* virtual */ bool
 SVGPathElement::HasValidDimensions() const
 {
@@ -313,36 +501,16 @@ SVGPathElement::HasValidDimensions() con
 
 nsSVGElement::NumberAttributesInfo
 SVGPathElement::GetNumberInfo()
 {
   return NumberAttributesInfo(&mPathLength, &sNumberInfo, 1);
 }
 
 //----------------------------------------------------------------------
-// nsIDOMSVGAnimatedPathData methods:
-
-/* readonly attribute DOMSVGPathSegList pathSegList; */
-NS_IMETHODIMP SVGPathElement::GetPathSegList(nsISupports * *aPathSegList)
-{
-  void *key = mD.GetBaseValKey();
-  *aPathSegList = DOMSVGPathSegList::GetDOMWrapper(key, this, false).get();
-  return *aPathSegList ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-/* readonly attribute DOMSVGPathSegList animatedPathSegList; */
-NS_IMETHODIMP SVGPathElement::GetAnimatedPathSegList(nsISupports * *aAnimatedPathSegList)
-{
-  void *key = mD.GetAnimValKey();
-  *aAnimatedPathSegList =
-    DOMSVGPathSegList::GetDOMWrapper(key, this, true).get();
-  return *aAnimatedPathSegList ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
-}
-
-//----------------------------------------------------------------------
 // nsIContent methods
 
 NS_IMETHODIMP_(bool)
 SVGPathElement::IsAttributeMapped(const nsIAtom* name) const
 {
   static const MappedAttributeEntry* const map[] = {
     sMarkersMap
   };
--- a/content/svg/content/src/SVGPathElement.h
+++ b/content/svg/content/src/SVGPathElement.h
@@ -1,50 +1,52 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SVGPathElement_h
 #define mozilla_dom_SVGPathElement_h
 
-#include "nsIDOMSVGAnimatedPathData.h"
 #include "nsIDOMSVGPathElement.h"
 #include "nsSVGNumber2.h"
 #include "nsSVGPathGeometryElement.h"
 #include "SVGAnimatedPathSegList.h"
+#include "DOMSVGPathSeg.h"
 
 nsresult NS_NewSVGPathElement(nsIContent **aResult,
                               already_AddRefed<nsINodeInfo> aNodeInfo);
 
 class gfxContext;
 
 typedef nsSVGPathGeometryElement SVGPathElementBase;
 
 namespace mozilla {
+
+class nsISVGPoint;
+
 namespace dom {
 
 class SVGPathElement MOZ_FINAL : public SVGPathElementBase,
-                                 public nsIDOMSVGPathElement,
-                                 public nsIDOMSVGAnimatedPathData
+                                 public nsIDOMSVGPathElement
 {
 friend class nsSVGPathFrame;
 
 protected:
   friend nsresult (::NS_NewSVGPathElement(nsIContent **aResult,
                                           already_AddRefed<nsINodeInfo> aNodeInfo));
+  virtual JSObject* WrapNode(JSContext *cx, JSObject *scope, bool *triedToWrap) MOZ_OVERRIDE;
   SVGPathElement(already_AddRefed<nsINodeInfo> aNodeInfo);
 
 public:
   typedef SVGAnimatedPathSegList SVGAnimatedPathSegList;
   // interfaces:
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGPATHELEMENT
-  NS_DECL_NSIDOMSVGANIMATEDPATHDATA
 
   // xxx I wish we could use virtual inheritance
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
   NS_FORWARD_NSIDOMSVGELEMENT(SVGPathElementBase::)
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const;
@@ -82,16 +84,53 @@ public:
 
   /**
    * Gets the ratio of the actual path length to the content author's estimated
    * length (as provided by the <path> element's 'pathLength' attribute). This
    * is used to scale stroke dashing, and to scale offsets along a textPath.
    */
   gfxFloat GetPathLengthScale(PathLengthScaleForType aFor);
 
+  // WebIDL
+  already_AddRefed<nsIDOMSVGAnimatedNumber> PathLength();
+  float GetTotalLength(ErrorResult& rv);
+  already_AddRefed<nsISVGPoint> GetPointAtLength(float distance, ErrorResult& rv);
+  uint32_t GetPathSegAtLength(float distance);
+  already_AddRefed<DOMSVGPathSegClosePath> CreateSVGPathSegClosePath();
+  already_AddRefed<DOMSVGPathSegMovetoAbs> CreateSVGPathSegMovetoAbs(float x, float y);
+  already_AddRefed<DOMSVGPathSegMovetoRel> CreateSVGPathSegMovetoRel(float x, float y);
+  already_AddRefed<DOMSVGPathSegLinetoAbs> CreateSVGPathSegLinetoAbs(float x, float y);
+  already_AddRefed<DOMSVGPathSegLinetoRel> CreateSVGPathSegLinetoRel(float x, float y);
+  already_AddRefed<DOMSVGPathSegCurvetoCubicAbs>
+    CreateSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2);
+  already_AddRefed<DOMSVGPathSegCurvetoCubicRel>
+    CreateSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2);
+  already_AddRefed<DOMSVGPathSegCurvetoQuadraticAbs>
+    CreateSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1);
+  already_AddRefed<DOMSVGPathSegCurvetoQuadraticRel>
+    CreateSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1);
+  already_AddRefed<DOMSVGPathSegArcAbs>
+    CreateSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag);
+  already_AddRefed<DOMSVGPathSegArcRel>
+    CreateSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag);
+  already_AddRefed<DOMSVGPathSegLinetoHorizontalAbs> CreateSVGPathSegLinetoHorizontalAbs(float x);
+  already_AddRefed<DOMSVGPathSegLinetoHorizontalRel> CreateSVGPathSegLinetoHorizontalRel(float x);
+  already_AddRefed<DOMSVGPathSegLinetoVerticalAbs> CreateSVGPathSegLinetoVerticalAbs(float y);
+  already_AddRefed<DOMSVGPathSegLinetoVerticalRel> CreateSVGPathSegLinetoVerticalRel(float y);
+  already_AddRefed<DOMSVGPathSegCurvetoCubicSmoothAbs>
+    CreateSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2);
+  already_AddRefed<DOMSVGPathSegCurvetoCubicSmoothRel>
+    CreateSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2);
+  already_AddRefed<DOMSVGPathSegCurvetoQuadraticSmoothAbs>
+    CreateSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y);
+  already_AddRefed<DOMSVGPathSegCurvetoQuadraticSmoothRel>
+    CreateSVGPathSegCurvetoQuadraticSmoothRel(float x, float y);
+  already_AddRefed<DOMSVGPathSegList> PathSegList();
+  already_AddRefed<DOMSVGPathSegList> AnimatedPathSegList();
+
 protected:
 
   // nsSVGElement method
   virtual NumberAttributesInfo GetNumberInfo();
 
   SVGAnimatedPathSegList mD;
   nsSVGNumber2 mPathLength;
   static NumberInfo sNumberInfo;
rename from content/svg/content/src/nsSVGPatternElement.cpp
rename to content/svg/content/src/SVGPatternElement.cpp
--- a/content/svg/content/src/nsSVGPatternElement.cpp
+++ b/content/svg/content/src/SVGPatternElement.cpp
@@ -4,226 +4,306 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Util.h"
 
 #include "DOMSVGAnimatedTransformList.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsCOMPtr.h"
 #include "nsGkAtoms.h"
-#include "nsSVGPatternElement.h"
+#include "mozilla/dom/SVGPatternElement.h"
+#include "mozilla/dom/SVGPatternElementBinding.h"
+
+NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Pattern)
+
+DOMCI_NODE_DATA(SVGPatternElement, mozilla::dom::SVGPatternElement)
 
-using namespace mozilla;
-using namespace mozilla::dom;
+namespace mozilla {
+namespace dom {
+
+JSObject*
+SVGPatternElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
+{
+  return SVGPatternElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
 
 //--------------------- Patterns ------------------------
 
-nsSVGElement::LengthInfo nsSVGPatternElement::sLengthInfo[4] =
+nsSVGElement::LengthInfo SVGPatternElement::sLengthInfo[4] =
 {
   { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X },
   { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y },
   { &nsGkAtoms::width, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::X },
   { &nsGkAtoms::height, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE, SVGContentUtils::Y },
 };
 
-nsSVGElement::EnumInfo nsSVGPatternElement::sEnumInfo[2] =
+nsSVGElement::EnumInfo SVGPatternElement::sEnumInfo[2] =
 {
   { &nsGkAtoms::patternUnits,
     sSVGUnitTypesMap,
     nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX
   },
   { &nsGkAtoms::patternContentUnits,
     sSVGUnitTypesMap,
     nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE
   }
 };
 
-nsSVGElement::StringInfo nsSVGPatternElement::sStringInfo[1] =
+nsSVGElement::StringInfo SVGPatternElement::sStringInfo[1] =
 {
   { &nsGkAtoms::href, kNameSpaceID_XLink, true }
 };
 
-NS_IMPL_NS_NEW_SVG_ELEMENT(Pattern)
-
 //----------------------------------------------------------------------
 // nsISupports methods
 
-NS_IMPL_ADDREF_INHERITED(nsSVGPatternElement,nsSVGPatternElementBase)
-NS_IMPL_RELEASE_INHERITED(nsSVGPatternElement,nsSVGPatternElementBase)
+NS_IMPL_ADDREF_INHERITED(SVGPatternElement,SVGPatternElementBase)
+NS_IMPL_RELEASE_INHERITED(SVGPatternElement,SVGPatternElementBase)
 
-DOMCI_NODE_DATA(SVGPatternElement, nsSVGPatternElement)
-
-NS_INTERFACE_TABLE_HEAD(nsSVGPatternElement)
-  NS_NODE_INTERFACE_TABLE7(nsSVGPatternElement, nsIDOMNode, nsIDOMElement,
+NS_INTERFACE_TABLE_HEAD(SVGPatternElement)
+  NS_NODE_INTERFACE_TABLE7(SVGPatternElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement,
                            nsIDOMSVGFitToViewBox, nsIDOMSVGURIReference,
                            nsIDOMSVGPatternElement, nsIDOMSVGUnitTypes)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGPatternElement)
-NS_INTERFACE_MAP_END_INHERITING(nsSVGPatternElementBase)
+NS_INTERFACE_MAP_END_INHERITING(SVGPatternElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
-nsSVGPatternElement::nsSVGPatternElement(already_AddRefed<nsINodeInfo> aNodeInfo)
-  : nsSVGPatternElementBase(aNodeInfo)
+SVGPatternElement::SVGPatternElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+  : SVGPatternElementBase(aNodeInfo)
 {
+  SetIsDOMBinding();
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode method
 
-NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGPatternElement)
+NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGPatternElement)
 
 //----------------------------------------------------------------------
 // nsIDOMSVGFitToViewBox methods
 
 /* readonly attribute nsIDOMSVGAnimatedRect viewBox; */
-NS_IMETHODIMP nsSVGPatternElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox)
+NS_IMETHODIMP SVGPatternElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox)
 {
-  return mViewBox.ToDOMAnimatedRect(aViewBox, this);
+  *aViewBox = ViewBox().get();
+  return NS_OK;
+}
+
+already_AddRefed<nsIDOMSVGAnimatedRect>
+SVGPatternElement::ViewBox()
+{
+  nsCOMPtr<nsIDOMSVGAnimatedRect> rect;
+  mViewBox.ToDOMAnimatedRect(getter_AddRefs(rect), this);
+  return rect.forget();
 }
 
 /* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */
 NS_IMETHODIMP
-nsSVGPatternElement::GetPreserveAspectRatio(nsISupports
-                                            **aPreserveAspectRatio)
+SVGPatternElement::GetPreserveAspectRatio(nsISupports **aPreserveAspectRatio)
+{
+  *aPreserveAspectRatio = PreserveAspectRatio().get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
+SVGPatternElement::PreserveAspectRatio()
 {
   nsRefPtr<DOMSVGAnimatedPreserveAspectRatio> ratio;
   mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(getter_AddRefs(ratio), this);
-  ratio.forget(aPreserveAspectRatio);
-  return NS_OK;
+  return ratio.forget();
 }
 
 //----------------------------------------------------------------------
 // nsIDOMSVGPatternElement methods
 
 /* readonly attribute nsIDOMSVGAnimatedEnumeration patternUnits; */
-NS_IMETHODIMP nsSVGPatternElement::GetPatternUnits(nsIDOMSVGAnimatedEnumeration * *aPatternUnits)
+NS_IMETHODIMP SVGPatternElement::GetPatternUnits(nsIDOMSVGAnimatedEnumeration * *aPatternUnits)
 {
-  return mEnumAttributes[PATTERNUNITS].ToDOMAnimatedEnum(aPatternUnits, this);
+  *aPatternUnits = PatternUnits().get();
+  return NS_OK;
+}
+
+already_AddRefed<nsIDOMSVGAnimatedEnumeration>
+SVGPatternElement::PatternUnits()
+{
+  return mEnumAttributes[PATTERNUNITS].ToDOMAnimatedEnum(this);
 }
 
 /* readonly attribute nsIDOMSVGAnimatedEnumeration patternContentUnits; */
-NS_IMETHODIMP nsSVGPatternElement::GetPatternContentUnits(nsIDOMSVGAnimatedEnumeration * *aPatternUnits)
+NS_IMETHODIMP SVGPatternElement::GetPatternContentUnits(nsIDOMSVGAnimatedEnumeration * *aPatternUnits)
 {
-  return mEnumAttributes[PATTERNCONTENTUNITS].ToDOMAnimatedEnum(aPatternUnits, this);
+  *aPatternUnits = PatternContentUnits().get();
+  return NS_OK;
+}
+
+already_AddRefed<nsIDOMSVGAnimatedEnumeration>
+SVGPatternElement::PatternContentUnits()
+{
+  return mEnumAttributes[PATTERNCONTENTUNITS].ToDOMAnimatedEnum(this);
 }
 
 /* readonly attribute nsISupports patternTransform; */
-NS_IMETHODIMP nsSVGPatternElement::GetPatternTransform(nsISupports * *aPatternTransform)
+NS_IMETHODIMP SVGPatternElement::GetPatternTransform(nsISupports * *aPatternTransform)
+{
+  *aPatternTransform = PatternTransform().get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGAnimatedTransformList>
+SVGPatternElement::PatternTransform()
 {
   // We're creating a DOM wrapper, so we must tell GetAnimatedTransformList
   // to allocate the SVGAnimatedTransformList if it hasn't already done so:
-  *aPatternTransform = DOMSVGAnimatedTransformList::GetDOMWrapper(
-                         GetAnimatedTransformList(DO_ALLOCATE), this).get();
-  return NS_OK;
+  return DOMSVGAnimatedTransformList::GetDOMWrapper(
+           GetAnimatedTransformList(DO_ALLOCATE), this);
 }
 
 /* readonly attribute nsIDOMSVGAnimatedLength x; */
-NS_IMETHODIMP nsSVGPatternElement::GetX(nsIDOMSVGAnimatedLength * *aX)
+NS_IMETHODIMP SVGPatternElement::GetX(nsIDOMSVGAnimatedLength * *aX)
 {
-  return mLengthAttributes[X].ToDOMAnimatedLength(aX, this);
+  *aX = X().get();
+  return NS_OK;
+}
+
+already_AddRefed<nsIDOMSVGAnimatedLength>
+SVGPatternElement::X()
+{
+  return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this);
 }
 
 /* readonly attribute nsIDOMSVGAnimatedLength y; */
-NS_IMETHODIMP nsSVGPatternElement::GetY(nsIDOMSVGAnimatedLength * *aY)
+NS_IMETHODIMP SVGPatternElement::GetY(nsIDOMSVGAnimatedLength * *aY)
 {
-  return mLengthAttributes[Y].ToDOMAnimatedLength(aY, this);
+  *aY = Y().get();
+  return NS_OK;
+}
+
+already_AddRefed<nsIDOMSVGAnimatedLength>
+SVGPatternElement::Y()
+{
+  return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this);
 }
 
 /* readonly attribute nsIDOMSVGAnimatedLength width; */
-NS_IMETHODIMP nsSVGPatternElement::GetWidth(nsIDOMSVGAnimatedLength * *aWidth)
+NS_IMETHODIMP SVGPatternElement::GetWidth(nsIDOMSVGAnimatedLength * *aWidth)
 {
-  return mLengthAttributes[WIDTH].ToDOMAnimatedLength(aWidth, this);
+  *aWidth = Width().get();
+  return NS_OK;
+}
+
+already_AddRefed<nsIDOMSVGAnimatedLength>
+SVGPatternElement::Width()
+{
+  return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this);
 }
 
 /* readonly attribute nsIDOMSVGAnimatedLength height; */
-NS_IMETHODIMP nsSVGPatternElement::GetHeight(nsIDOMSVGAnimatedLength * *aHeight)
+NS_IMETHODIMP SVGPatternElement::GetHeight(nsIDOMSVGAnimatedLength * *aHeight)
 {
-  return mLengthAttributes[HEIGHT].ToDOMAnimatedLength(aHeight, this);
+  *aHeight = Height().get();
+  return NS_OK;
 }
 
+already_AddRefed<nsIDOMSVGAnimatedLength>
+SVGPatternElement::Height()
+{
+  return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this);
+}
 
 //----------------------------------------------------------------------
 // nsIDOMSVGURIReference methods:
 
 /* readonly attribute nsIDOMSVGAnimatedString href; */
 NS_IMETHODIMP
-nsSVGPatternElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
+SVGPatternElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
 {
-  return mStringAttributes[HREF].ToDOMAnimatedString(aHref, this);
+  *aHref = Href().get();
+  return NS_OK;
+}
+
+already_AddRefed<nsIDOMSVGAnimatedString>
+SVGPatternElement::Href()
+{
+  nsCOMPtr<nsIDOMSVGAnimatedString> href;
+  mStringAttributes[HREF].ToDOMAnimatedString(getter_AddRefs(href), this);
+  return href.forget();
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 NS_IMETHODIMP_(bool)
-nsSVGPatternElement::IsAttributeMapped(const nsIAtom* name) const
+SVGPatternElement::IsAttributeMapped(const nsIAtom* name) const
 {
   static const MappedAttributeEntry* const map[] = {
     sFEFloodMap,
     sFiltersMap,
     sFontSpecificationMap,
     sGradientStopMap,
     sLightingEffectsMap,
     sMarkersMap,
     sTextContentElementsMap,
     sViewportsMap
   };
 
   return FindAttributeDependence(name, map) ||
-    nsSVGPatternElementBase::IsAttributeMapped(name);
+    SVGPatternElementBase::IsAttributeMapped(name);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 SVGAnimatedTransformList*
-nsSVGPatternElement::GetAnimatedTransformList(uint32_t aFlags)
+SVGPatternElement::GetAnimatedTransformList(uint32_t aFlags)
 {
   if (!mPatternTransform && (aFlags & DO_ALLOCATE)) {
     mPatternTransform = new SVGAnimatedTransformList();
   }
   return mPatternTransform;
 }
 
 /* virtual */ bool
-nsSVGPatternElement::HasValidDimensions() const
+SVGPatternElement::HasValidDimensions() const
 {
-  return mLengthAttributes[WIDTH].IsExplicitlySet() &&
-         mLengthAttributes[WIDTH].GetAnimValInSpecifiedUnits() > 0 &&
-         mLengthAttributes[HEIGHT].IsExplicitlySet() &&
-         mLengthAttributes[HEIGHT].GetAnimValInSpecifiedUnits() > 0;
+  return mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() &&
+         mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0 &&
+         mLengthAttributes[ATTR_HEIGHT].IsExplicitlySet() &&
+         mLengthAttributes[ATTR_HEIGHT].GetAnimValInSpecifiedUnits() > 0;
 }
 
 nsSVGElement::LengthAttributesInfo
-nsSVGPatternElement::GetLengthInfo()
+SVGPatternElement::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               ArrayLength(sLengthInfo));
 }
 
 nsSVGElement::EnumAttributesInfo
-nsSVGPatternElement::GetEnumInfo()
+SVGPatternElement::GetEnumInfo()
 {
   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
                             ArrayLength(sEnumInfo));
 }
 
 nsSVGViewBox *
-nsSVGPatternElement::GetViewBox()
+SVGPatternElement::GetViewBox()
 {
   return &mViewBox;
 }
 
 SVGAnimatedPreserveAspectRatio *
-nsSVGPatternElement::GetPreserveAspectRatio()
+SVGPatternElement::GetPreserveAspectRatio()
 {
   return &mPreserveAspectRatio;
 }
 
 nsSVGElement::StringAttributesInfo
-nsSVGPatternElement::GetStringInfo()
+SVGPatternElement::GetStringInfo()
 {
   return StringAttributesInfo(mStringAttributes, sStringInfo,
                               ArrayLength(sStringInfo));
 }
 
+} // namespace dom
+} // namespace mozilla
rename from content/svg/content/src/nsSVGPatternElement.h
rename to content/svg/content/src/SVGPatternElement.h
--- a/content/svg/content/src/nsSVGPatternElement.h
+++ b/content/svg/content/src/SVGPatternElement.h
@@ -1,44 +1,53 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef __NS_SVGPATTERNELEMENT_H__
-#define __NS_SVGPATTERNELEMENT_H__
+#ifndef mozilla_dom_SVGPatternElement_h
+#define mozilla_dom_SVGPatternElement_h
 
 #include "nsIDOMSVGFitToViewBox.h"
 #include "nsIDOMSVGPatternElement.h"
 #include "nsIDOMSVGUnitTypes.h"
 #include "nsIDOMSVGURIReference.h"
 #include "nsSVGEnum.h"
 #include "nsSVGLength2.h"
 #include "nsSVGString.h"
 #include "nsSVGElement.h"
 #include "nsSVGViewBox.h"
 #include "SVGAnimatedPreserveAspectRatio.h"
 #include "SVGAnimatedTransformList.h"
 
-//--------------------- Patterns ------------------------
+class nsSVGPatternFrame;
+
+nsresult NS_NewSVGPatternElement(nsIContent **aResult,
+                                 already_AddRefed<nsINodeInfo> aNodeInfo);
 
-typedef nsSVGElement nsSVGPatternElementBase;
+namespace mozilla {
+class DOMSVGAnimatedTransformList;
+
+namespace dom {
 
-class nsSVGPatternElement : public nsSVGPatternElementBase,
-                            public nsIDOMSVGPatternElement,
-                            public nsIDOMSVGURIReference,
-                            public nsIDOMSVGFitToViewBox,
-                            public nsIDOMSVGUnitTypes
+typedef nsSVGElement SVGPatternElementBase;
+
+class SVGPatternElement MOZ_FINAL : public SVGPatternElementBase,
+                                    public nsIDOMSVGPatternElement,
+                                    public nsIDOMSVGURIReference,
+                                    public nsIDOMSVGFitToViewBox,
+                                    public nsIDOMSVGUnitTypes
 {
-  friend class nsSVGPatternFrame;
+  friend class ::nsSVGPatternFrame;
 
 protected:
-  friend nsresult NS_NewSVGPatternElement(nsIContent **aResult,
-                                          already_AddRefed<nsINodeInfo> aNodeInfo);
-  nsSVGPatternElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  friend nsresult (::NS_NewSVGPatternElement(nsIContent **aResult,
+                                             already_AddRefed<nsINodeInfo> aNodeInfo));
+  SVGPatternElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual JSObject* WrapNode(JSContext *cx, JSObject *scope, bool *triedToWrap) MOZ_OVERRIDE;
 
 public:
   typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
 
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
 
   // Pattern Element
@@ -66,26 +75,39 @@ public:
   // nsSVGSVGElement methods:
   virtual bool HasValidDimensions() const;
 
   virtual mozilla::SVGAnimatedTransformList*
     GetAnimatedTransformList(uint32_t aFlags = 0);
   virtual nsIAtom* GetTransformListAttrName() const {
     return nsGkAtoms::patternTransform;
   }
+
+  // WebIDL
+  already_AddRefed<nsIDOMSVGAnimatedRect> ViewBox();
+  already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
+  already_AddRefed<nsIDOMSVGAnimatedEnumeration> PatternUnits();
+  already_AddRefed<nsIDOMSVGAnimatedEnumeration> PatternContentUnits();
+  already_AddRefed<DOMSVGAnimatedTransformList> PatternTransform();
+  already_AddRefed<nsIDOMSVGAnimatedLength> X();
+  already_AddRefed<nsIDOMSVGAnimatedLength> Y();
+  already_AddRefed<nsIDOMSVGAnimatedLength> Width();
+  already_AddRefed<nsIDOMSVGAnimatedLength> Height();
+  already_AddRefed<nsIDOMSVGAnimatedString> Href();
+
 protected:
 
   virtual LengthAttributesInfo GetLengthInfo();
   virtual EnumAttributesInfo GetEnumInfo();
   virtual nsSVGViewBox *GetViewBox();
   virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio();
   virtual StringAttributesInfo GetStringInfo();
 
   // nsIDOMSVGPatternElement values
-  enum { X, Y, WIDTH, HEIGHT };
+  enum { ATTR_X, ATTR_Y, ATTR_WIDTH, ATTR_HEIGHT };
   nsSVGLength2 mLengthAttributes[4];
   static LengthInfo sLengthInfo[4];
 
   enum { PATTERNUNITS, PATTERNCONTENTUNITS };
   nsSVGEnum mEnumAttributes[2];
   static EnumInfo sEnumInfo[2];
 
   nsAutoPtr<mozilla::SVGAnimatedTransformList> mPatternTransform;
@@ -95,9 +117,12 @@ protected:
   nsSVGString mStringAttributes[1];
   static StringInfo sStringInfo[1];
 
   // nsIDOMSVGFitToViewbox properties
   nsSVGViewBox mViewBox;
   SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
 };
 
-#endif
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_SVGPatternElement_h
--- a/content/svg/content/src/SVGPoint.h
+++ b/content/svg/content/src/SVGPoint.h
@@ -16,20 +16,18 @@ namespace mozilla {
  *
  * The DOM wrapper class for this class is DOMSVGPoint.
  */
 class SVGPoint
 {
 public:
 
   SVGPoint()
-#ifdef DEBUG
     : mX(0.0f)
     , mY(0.0f)
-#endif
   {}
 
   SVGPoint(float aX, float aY)
     : mX(aX)
     , mY(aY)
   {
     NS_ASSERTION(IsValid(), "Constructed an invalid SVGPoint");
   }
@@ -60,16 +58,29 @@ public:
   }
 
 #ifdef DEBUG
   bool IsValid() const {
     return NS_finite(mX) && NS_finite(mY);
   }
 #endif
 
+  void SetX(float aX)
+    { mX = aX; }
+  void SetY(float aY)
+    { mY = aY; }
+  float GetX() const
+    { return mX; }
+  float GetY() const
+    { return mY; }
+
+  bool operator!=(const SVGPoint &rhs) const {
+    return mX != rhs.mX || mY != rhs.mY;
+  }
+
   float mX;
   float mY;
 };
 
 inline SVGPoint operator+(const SVGPoint& aP1,
                           const SVGPoint& aP2)
 {
   return SVGPoint(aP1.mX + aP2.mX, aP1.mY + aP2.mY);
--- a/content/svg/content/src/SVGPointList.h
+++ b/content/svg/content/src/SVGPointList.h
@@ -13,28 +13,30 @@
 #include "nsIWeakReferenceUtils.h"
 #include "nsSVGElement.h"
 #include "nsTArray.h"
 #include "SVGPoint.h"
 
 #include <string.h>
 
 namespace mozilla {
+class nsISVGPoint;
 
 /**
  * ATTENTION! WARNING! WATCH OUT!!
  *
  * Consumers that modify objects of this type absolutely MUST keep the DOM
  * wrappers for those lists (if any) in sync!! That's why this class is so
  * locked down.
  *
  * The DOM wrapper class for this class is DOMSVGPointList.
  */
 class SVGPointList
 {
+  friend class mozilla::nsISVGPoint;
   friend class SVGAnimatedPointList;
   friend class DOMSVGPointList;
   friend class DOMSVGPoint;
 
 public:
 
   SVGPointList(){}
   ~SVGPointList(){}
--- a/content/svg/content/src/SVGSVGElement.cpp
+++ b/content/svg/content/src/SVGSVGElement.cpp
@@ -49,62 +49,60 @@ namespace mozilla {
 namespace dom {
 
 JSObject*
 SVGSVGElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
 {
   return SVGSVGElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
 }
 
-NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(nsSVGTranslatePoint::DOMVal, mElement)
+NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(DOMSVGTranslatePoint, mElement)
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGTranslatePoint::DOMVal)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGTranslatePoint::DOMVal)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGTranslatePoint)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGTranslatePoint)
 
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGTranslatePoint::DOMVal)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGTranslatePoint)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   // We have to qualify nsISVGPoint because NS_GET_IID looks for a class in the
   // global namespace
   NS_INTERFACE_MAP_ENTRY(mozilla::nsISVGPoint)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-nsresult
-nsSVGTranslatePoint::ToDOMVal(SVGSVGElement *aElement,
-                              nsISupports **aResult)
+nsISVGPoint*
+DOMSVGTranslatePoint::Clone()
 {
-  NS_ADDREF(*aResult = new DOMVal(this, aElement));
-  return NS_OK;
+  return new DOMSVGTranslatePoint(this);
 }
 
 nsISupports*
-nsSVGTranslatePoint::DOMVal::GetParentObject()
+DOMSVGTranslatePoint::GetParentObject()
 {
   return static_cast<nsIDOMSVGSVGElement*>(mElement);
 }
 
 void
-nsSVGTranslatePoint::DOMVal::SetX(float aValue, ErrorResult& rv)
+DOMSVGTranslatePoint::SetX(float aValue, ErrorResult& rv)
 {
-  rv = mElement->SetCurrentTranslate(aValue, mVal->GetY());
+  rv = mElement->SetCurrentTranslate(aValue, mPt.GetY());
 }
 
 void
-nsSVGTranslatePoint::DOMVal::SetY(float aValue, ErrorResult& rv)
+DOMSVGTranslatePoint::SetY(float aValue, ErrorResult& rv)
 {
-  rv = mElement->SetCurrentTranslate(mVal->GetX(), aValue);
+  rv = mElement->SetCurrentTranslate(mPt.GetX(), aValue);
 }
 
 already_AddRefed<nsISVGPoint>
-nsSVGTranslatePoint::DOMVal::MatrixTransform(SVGMatrix& matrix)
+DOMSVGTranslatePoint::MatrixTransform(SVGMatrix& matrix)
 {
   float a = matrix.A(), b = matrix.B(), c = matrix.C();
   float d = matrix.D(), e = matrix.E(), f = matrix.F();
-  float x = mVal->GetX();
-  float y = mVal->GetY();
+  float x = mPt.GetX();
+  float y = mPt.GetY();
 
   nsCOMPtr<nsISVGPoint> point = new DOMSVGPoint(a*x + c*y + e, b*x + d*y + f);
   return point.forget();
 }
 
 nsSVGElement::LengthInfo SVGSVGElement::sLengthInfo[4] =
 {
   { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
@@ -125,17 +123,16 @@ nsSVGElement::EnumInfo SVGSVGElement::sE
     sZoomAndPanMap,
     SVG_ZOOMANDPAN_MAGNIFY
   }
 };
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(SVGSVGElement)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGSVGElement,
                                                 SVGSVGElementBase)
   if (tmp->mTimedDocumentRoot) {
     tmp->mTimedDocumentRoot->Unlink();
   }
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGSVGElement,
                                                   SVGSVGElementBase)
@@ -357,18 +354,17 @@ SVGSVGElement::GetCurrentTranslate(nsISu
 {
   *aCurrentTranslate = CurrentTranslate().get();
   return NS_OK;
 }
 
 already_AddRefed<nsISVGPoint>
 SVGSVGElement::CurrentTranslate()
 {
-  nsCOMPtr<nsISVGPoint> point;
-  mCurrentTranslate.ToDOMVal(this, getter_AddRefs(point));
+  nsCOMPtr<nsISVGPoint> point = new DOMSVGTranslatePoint(&mCurrentTranslate, this);
   return point.forget();
 }
 
 /* unsigned long suspendRedraw (in unsigned long max_wait_milliseconds); */
 NS_IMETHODIMP
 SVGSVGElement::SuspendRedraw(uint32_t max_wait_milliseconds, uint32_t *_retval)
 {
   *_retval = SuspendRedraw(max_wait_milliseconds);
@@ -788,17 +784,17 @@ SVGSVGElement::SetCurrentScaleTranslate(
   // the state of currentScale and currentTranslate immediately before the
   // change that caused the event's dispatch, which is *not* necessarily the
   // same thing as the values of currentScale and currentTranslate prior to
   // their own last change.
   mPreviousScale = mCurrentScale;
   mPreviousTranslate = mCurrentTranslate;
   
   mCurrentScale = s;
-  mCurrentTranslate = nsSVGTranslatePoint(x, y);
+  mCurrentTranslate = SVGPoint(x, y);
 
   // now dispatch the appropriate event if we are the root element
   nsIDocument* doc = GetCurrentDoc();
   if (doc) {
     nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
     if (presShell && IsRoot()) {
       bool scaling = (mPreviousScale != mCurrentScale);
       nsEventStatus status = nsEventStatus_eIgnore;
@@ -960,17 +956,17 @@ SVGSVGElement::GetViewBoxTransform() con
                                               GetPreserveAspectRatioWithOverride());
 }
 
 void
 SVGSVGElement::UpdateHasChildrenOnlyTransform()
 {
   bool hasChildrenOnlyTransform =
     HasViewBoxOrSyntheticViewBox() ||
-    (IsRoot() && (mCurrentTranslate != nsSVGTranslatePoint(0.0f, 0.0f) ||
+    (IsRoot() && (mCurrentTranslate != SVGPoint(0.0f, 0.0f) ||
                   mCurrentScale != 1.0f));
   mHasChildrenOnlyTransform = hasChildrenOnlyTransform;
 }
 
 void
 SVGSVGElement::ChildrenOnlyTransformChanged(uint32_t aFlags)
 {
   // Avoid wasteful calls:
--- a/content/svg/content/src/SVGSVGElement.h
+++ b/content/svg/content/src/SVGSVGElement.h
@@ -3,17 +3,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_SVGSVGElement_h
 #define mozilla_dom_SVGSVGElement_h
 
 #include "mozilla/dom/FromParser.h"
 #include "nsIDOMSVGFitToViewBox.h"
-#include "nsIDOMSVGLocatable.h"
 #include "nsISVGPoint.h"
 #include "nsIDOMSVGSVGElement.h"
 #include "nsSVGEnum.h"
 #include "nsSVGLength2.h"
 #include "SVGGraphicsElement.h"
 #include "nsSVGViewBox.h"
 #include "SVGPreserveAspectRatio.h"
 #include "SVGAnimatedPreserveAspectRatio.h"
@@ -35,67 +34,39 @@ class SVGFragmentIdentifier;
 
 namespace dom {
 class SVGAngle;
 class SVGMatrix;
 class SVGViewElement;
 
 class SVGSVGElement;
 
-class nsSVGTranslatePoint {
+class DOMSVGTranslatePoint MOZ_FINAL : public nsISVGPoint {
 public:
-  nsSVGTranslatePoint()
-    : mX(0.0f)
-    , mY(0.0f)
-  {}
+  DOMSVGTranslatePoint(SVGPoint* aPt, SVGSVGElement *aElement)
+    : nsISVGPoint(aPt), mElement(aElement) {}
 
-  nsSVGTranslatePoint(float aX, float aY)
-    : mX(aX)
-    , mY(aY)
-  {}
+  DOMSVGTranslatePoint(DOMSVGTranslatePoint* aPt)
+    : nsISVGPoint(&aPt->mPt), mElement(aPt->mElement) {}
 
-  void SetX(float aX)
-    { mX = aX; }
-  void SetY(float aY)
-    { mY = aY; }
-  float GetX() const
-    { return mX; }
-  float GetY() const
-    { return mY; }
-
-  nsresult ToDOMVal(SVGSVGElement *aElement, nsISupports **aResult);
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGTranslatePoint)
 
-  bool operator!=(const nsSVGTranslatePoint &rhs) const {
-    return mX != rhs.mX || mY != rhs.mY;
-  }
-
-private:
-
-  struct DOMVal MOZ_FINAL : public nsISVGPoint {
-    DOMVal(nsSVGTranslatePoint* aVal, SVGSVGElement *aElement)
-      : nsISVGPoint(), mVal(aVal), mElement(aElement) {}
-
-    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMVal)
+  virtual nsISVGPoint* Clone();
 
-    // WebIDL
-    virtual float X() { return mVal->GetX(); }
-    virtual float Y() { return mVal->GetY(); }
-    virtual void SetX(float aValue, ErrorResult& rv);
-    virtual void SetY(float aValue, ErrorResult& rv);
-    virtual already_AddRefed<nsISVGPoint> MatrixTransform(SVGMatrix& matrix);
+  // WebIDL
+  virtual float X() { return mPt.GetX(); }
+  virtual float Y() { return mPt.GetY(); }
+  virtual void SetX(float aValue, ErrorResult& rv);
+  virtual void SetY(float aValue, ErrorResult& rv);
+  virtual already_AddRefed<nsISVGPoint> MatrixTransform(SVGMatrix& matrix);
 
-    virtual nsISupports* GetParentObject() MOZ_OVERRIDE;
+  virtual nsISupports* GetParentObject() MOZ_OVERRIDE;
 
-    nsSVGTranslatePoint *mVal; // kept alive because it belongs to mElement
-    nsRefPtr<SVGSVGElement> mElement;
-  };
-
-  float mX;
-  float mY;
+  nsRefPtr<SVGSVGElement> mElement;
 };
 
 class svgFloatSize {
 public:
   svgFloatSize(float aWidth, float aHeight)
     : width(aWidth)
     , height(aHeight)
   {}
@@ -149,24 +120,24 @@ public:
    * to be set by a single operation that dispatches a single SVGScroll event
    * (instead of two).
    */
   NS_IMETHOD SetCurrentTranslate(float x, float y);
 
   /**
    * Retrieve the value of currentScale and currentTranslate.
    */
-  const nsSVGTranslatePoint& GetCurrentTranslate() { return mCurrentTranslate; }
+  const SVGPoint& GetCurrentTranslate() { return mCurrentTranslate; }
   float GetCurrentScale() { return mCurrentScale; }
 
   /**
    * Retrieve the value of currentScale, currentTranslate.x or
    * currentTranslate.y prior to the last change made to any one of them.
    */
-  const nsSVGTranslatePoint& GetPreviousTranslate() { return mPreviousTranslate; }
+  const SVGPoint& GetPreviousTranslate() { return mPreviousTranslate; }
   float GetPreviousScale() { return mPreviousScale; }
 
   nsSMILTimeContainer* GetTimedDocumentRoot();
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
 
@@ -408,28 +379,28 @@ private:
 
   // The time container for animations within this SVG document fragment. Set
   // for all outermost <svg> elements (not nested <svg> elements).
   nsAutoPtr<nsSMILTimeContainer> mTimedDocumentRoot;
 
   // zoom and pan
   // IMPORTANT: see the comment in RecordCurrentScaleTranslate before writing
   // code to change any of these!
-  nsSVGTranslatePoint               mCurrentTranslate;
-  float                             mCurrentScale;
-  nsSVGTranslatePoint               mPreviousTranslate;
-  float                             mPreviousScale;
+  SVGPoint mCurrentTranslate;
+  float    mCurrentScale;
+  SVGPoint mPreviousTranslate;
+  float    mPreviousScale;
 
   // For outermost <svg> elements created from parsing, animation is started by
   // the onload event in accordance with the SVG spec, but for <svg> elements
   // created by script or promoted from inner <svg> to outermost <svg> we need
   // to manually kick off animation when they are bound to the tree.
-  bool                              mStartAnimationOnBindToTree;
-  bool                              mImageNeedsTransformInvalidation;
-  bool                              mIsPaintingSVGImageElement;
-  bool                              mHasChildrenOnlyTransform;
-  bool                              mUseCurrentView;
+  bool     mStartAnimationOnBindToTree;
+  bool     mImageNeedsTransformInvalidation;
+  bool     mIsPaintingSVGImageElement;
+  bool     mHasChildrenOnlyTransform;
+  bool     mUseCurrentView;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // SVGSVGElement_h
--- a/content/svg/content/src/SVGStyleElement.cpp
+++ b/content/svg/content/src/SVGStyleElement.cpp
@@ -31,17 +31,16 @@ NS_IMPL_RELEASE_INHERITED(SVGStyleElemen
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(SVGStyleElement)
   NS_NODE_INTERFACE_TABLE7(SVGStyleElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement, nsIDOMSVGStyleElement,
                            nsIDOMLinkStyle, nsIStyleSheetLinkingElement,
                            nsIMutationObserver)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGStyleElement)
 NS_INTERFACE_MAP_END_INHERITING(SVGStyleElementBase)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(SVGStyleElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGStyleElement,
                                                   SVGStyleElementBase)
   tmp->nsStyleLinkElement::Traverse(cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGStyleElement,
                                                 SVGStyleElementBase)
   tmp->nsStyleLinkElement::Unlink();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/svg/content/src/SVGSwitchElement.cpp
+++ b/content/svg/content/src/SVGSwitchElement.cpp
@@ -23,17 +23,16 @@ JSObject*
 SVGSwitchElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
 {
   return SVGSwitchElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
 }
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(SVGSwitchElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGSwitchElement,
                                                   SVGSwitchElementBase)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActiveChild)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGSwitchElement,
                                                 SVGSwitchElementBase)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mActiveChild)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
rename from content/svg/content/src/nsSVGSymbolElement.cpp
rename to content/svg/content/src/SVGSymbolElement.cpp
--- a/content/svg/content/src/nsSVGSymbolElement.cpp
+++ b/content/svg/content/src/SVGSymbolElement.cpp
@@ -1,147 +1,125 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/Util.h"
-
-#include "nsIDOMSVGSymbolElement.h"
-#include "DOMSVGTests.h"
-#include "nsSVGElement.h"
-#include "nsSVGViewBox.h"
-#include "SVGAnimatedPreserveAspectRatio.h"
-#include "nsIDOMSVGFitToViewBox.h"
-#include "nsGkAtoms.h"
+#include "mozilla/dom/SVGSymbolElement.h"
+#include "mozilla/dom/SVGSymbolElementBinding.h"
 
-using namespace mozilla;
-using namespace mozilla::dom;
-
-typedef nsSVGElement nsSVGSymbolElementBase;
+NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Symbol)
 
-class nsSVGSymbolElement : public nsSVGSymbolElementBase,
-                           public nsIDOMSVGSymbolElement,
-                           public DOMSVGTests,
-                           public nsIDOMSVGFitToViewBox
-{
-protected:
-  friend nsresult NS_NewSVGSymbolElement(nsIContent **aResult,
-                                         already_AddRefed<nsINodeInfo> aNodeInfo);
-  nsSVGSymbolElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+DOMCI_NODE_DATA(SVGSymbolElement, mozilla::dom::SVGSymbolElement)
 
-public:
-  // interfaces:
-
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIDOMSVGSYMBOLELEMENT
-  NS_DECL_NSIDOMSVGFITTOVIEWBOX
-
-  // xxx I wish we could use virtual inheritance
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
-  NS_FORWARD_NSIDOMSVGELEMENT(nsSVGElement::)
-
-  // nsIContent interface
-  NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const;
+namespace mozilla {
+namespace dom {
 
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
-  virtual nsXPCClassInfo* GetClassInfo();
-
-  virtual nsIDOMNode* AsDOMNode() { return this; }
-protected:
-  virtual nsSVGViewBox *GetViewBox();
-  virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio();
-
-  nsSVGViewBox mViewBox;
-  SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
-};
-
-NS_IMPL_NS_NEW_SVG_ELEMENT(Symbol)
+JSObject*
+SVGSymbolElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
+{
+  return SVGSymbolElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
-NS_IMPL_ADDREF_INHERITED(nsSVGSymbolElement,nsSVGSymbolElementBase)
-NS_IMPL_RELEASE_INHERITED(nsSVGSymbolElement,nsSVGSymbolElementBase)
-
-DOMCI_NODE_DATA(SVGSymbolElement, nsSVGSymbolElement)
+NS_IMPL_ADDREF_INHERITED(SVGSymbolElement,SVGSymbolElementBase)
+NS_IMPL_RELEASE_INHERITED(SVGSymbolElement,SVGSymbolElementBase)
 
-NS_INTERFACE_TABLE_HEAD(nsSVGSymbolElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGSymbolElement, nsIDOMNode, nsIDOMElement,
+NS_INTERFACE_TABLE_HEAD(SVGSymbolElement)
+  NS_NODE_INTERFACE_TABLE6(SVGSymbolElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement, nsIDOMSVGFitToViewBox,
-                           nsIDOMSVGSymbolElement)
+                           nsIDOMSVGSymbolElement, nsIDOMSVGTests)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGSymbolElement)
-NS_INTERFACE_MAP_END_INHERITING(nsSVGSymbolElementBase)
+NS_INTERFACE_MAP_END_INHERITING(SVGSymbolElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
-nsSVGSymbolElement::nsSVGSymbolElement(already_AddRefed<nsINodeInfo> aNodeInfo)
-  : nsSVGSymbolElementBase(aNodeInfo)
+SVGSymbolElement::SVGSymbolElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+  : SVGSymbolElementBase(aNodeInfo)
 {
+  SetIsDOMBinding();
 }
 
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
-NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGSymbolElement)
+NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGSymbolElement)
 
 //----------------------------------------------------------------------
 // nsIDOMSVGFitToViewBox methods
 
 /* readonly attribute nsIDOMSVGAnimatedRect viewBox; */
-NS_IMETHODIMP nsSVGSymbolElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox)
+NS_IMETHODIMP SVGSymbolElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox)
 {
-  return mViewBox.ToDOMAnimatedRect(aViewBox, this);
+  *aViewBox = ViewBox().get();
+  return NS_OK;
+}
+
+already_AddRefed<nsIDOMSVGAnimatedRect>
+SVGSymbolElement::ViewBox()
+{
+  nsCOMPtr<nsIDOMSVGAnimatedRect> rect;
+  mViewBox.ToDOMAnimatedRect(getter_AddRefs(rect), this);
+  return rect.forget();
 }
 
 /* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */
 NS_IMETHODIMP
-nsSVGSymbolElement::GetPreserveAspectRatio(nsISupports
-                                           **aPreserveAspectRatio)
+SVGSymbolElement::GetPreserveAspectRatio(nsISupports
+                                         **aPreserveAspectRatio)
+{
+  *aPreserveAspectRatio = PreserveAspectRatio().get();
+  return NS_OK;
+}
+
+already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
+SVGSymbolElement::PreserveAspectRatio()
 {
   nsRefPtr<DOMSVGAnimatedPreserveAspectRatio> ratio;
   mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(getter_AddRefs(ratio), this);
-  ratio.forget(aPreserveAspectRatio);
-  return NS_OK;
+  return ratio.forget();
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 NS_IMETHODIMP_(bool)
-nsSVGSymbolElement::IsAttributeMapped(const nsIAtom* name) const
+SVGSymbolElement::IsAttributeMapped(const nsIAtom* name) const
 {
   static const MappedAttributeEntry* const map[] = {
     sColorMap,
     sFEFloodMap,
     sFillStrokeMap,
     sFiltersMap,
     sFontSpecificationMap,
     sGradientStopMap,
     sGraphicsMap,
     sLightingEffectsMap,
     sMarkersMap,
     sTextContentElementsMap,
     sViewportsMap
    };
 
   return FindAttributeDependence(name, map) ||
-    nsSVGSymbolElementBase::IsAttributeMapped(name);
+    SVGSymbolElementBase::IsAttributeMapped(name);
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 nsSVGViewBox *
-nsSVGSymbolElement::GetViewBox()
+SVGSymbolElement::GetViewBox()
 {
   return &mViewBox;
 }
 
 SVGAnimatedPreserveAspectRatio *
-nsSVGSymbolElement::GetPreserveAspectRatio()
+SVGSymbolElement::GetPreserveAspectRatio()
 {
   return &mPreserveAspectRatio;
 }
+
+} // namespace dom
+} // namespace mozilla
copy from content/svg/content/src/nsSVGSymbolElement.cpp
copy to content/svg/content/src/SVGSymbolElement.h
--- a/content/svg/content/src/nsSVGSymbolElement.cpp
+++ b/content/svg/content/src/SVGSymbolElement.h
@@ -1,37 +1,42 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/Util.h"
+#ifndef mozilla_dom_SVGSymbolElement_h
+#define mozilla_dom_SVGSymbolElement_h
 
 #include "nsIDOMSVGSymbolElement.h"
 #include "DOMSVGTests.h"
 #include "nsSVGElement.h"
 #include "nsSVGViewBox.h"
 #include "SVGAnimatedPreserveAspectRatio.h"
 #include "nsIDOMSVGFitToViewBox.h"
 #include "nsGkAtoms.h"
 
-using namespace mozilla;
-using namespace mozilla::dom;
+nsresult NS_NewSVGSymbolElement(nsIContent **aResult,
+                                already_AddRefed<nsINodeInfo> aNodeInfo);
 
-typedef nsSVGElement nsSVGSymbolElementBase;
+namespace mozilla {
+namespace dom {
 
-class nsSVGSymbolElement : public nsSVGSymbolElementBase,
-                           public nsIDOMSVGSymbolElement,
-                           public DOMSVGTests,
-                           public nsIDOMSVGFitToViewBox
+typedef nsSVGElement SVGSymbolElementBase;
+
+class SVGSymbolElement MOZ_FINAL : public SVGSymbolElementBase,
+                                   public nsIDOMSVGSymbolElement,
+                                   public DOMSVGTests,
+                                   public nsIDOMSVGFitToViewBox
 {
 protected:
-  friend nsresult NS_NewSVGSymbolElement(nsIContent **aResult,
-                                         already_AddRefed<nsINodeInfo> aNodeInfo);
-  nsSVGSymbolElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  friend nsresult (::NS_NewSVGSymbolElement(nsIContent **aResult,
+                                            already_AddRefed<nsINodeInfo> aNodeInfo));
+  SVGSymbolElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual JSObject* WrapNode(JSContext *cx, JSObject *scope, bool *triedToWrap) MOZ_OVERRIDE;
 
 public:
   // interfaces:
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGSYMBOLELEMENT
   NS_DECL_NSIDOMSVGFITTOVIEWBOX
 
@@ -43,105 +48,25 @@ public:
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* name) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+  // WebIDL
+  already_AddRefed<nsIDOMSVGAnimatedRect> ViewBox();
+  already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
+
 protected:
   virtual nsSVGViewBox *GetViewBox();
   virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio();
 
   nsSVGViewBox mViewBox;
   SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
 };
 
-NS_IMPL_NS_NEW_SVG_ELEMENT(Symbol)
-
-//----------------------------------------------------------------------
-// nsISupports methods
-
-NS_IMPL_ADDREF_INHERITED(nsSVGSymbolElement,nsSVGSymbolElementBase)
-NS_IMPL_RELEASE_INHERITED(nsSVGSymbolElement,nsSVGSymbolElementBase)
-
-DOMCI_NODE_DATA(SVGSymbolElement, nsSVGSymbolElement)
-
-NS_INTERFACE_TABLE_HEAD(nsSVGSymbolElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGSymbolElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement, nsIDOMSVGFitToViewBox,
-                           nsIDOMSVGSymbolElement)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGSymbolElement)
-NS_INTERFACE_MAP_END_INHERITING(nsSVGSymbolElementBase)
-
-//----------------------------------------------------------------------
-// Implementation
-
-nsSVGSymbolElement::nsSVGSymbolElement(already_AddRefed<nsINodeInfo> aNodeInfo)
-  : nsSVGSymbolElementBase(aNodeInfo)
-{
-}
-
-
-//----------------------------------------------------------------------
-// nsIDOMNode methods
-
-NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGSymbolElement)
-
-//----------------------------------------------------------------------
-// nsIDOMSVGFitToViewBox methods
-
-/* readonly attribute nsIDOMSVGAnimatedRect viewBox; */
-NS_IMETHODIMP nsSVGSymbolElement::GetViewBox(nsIDOMSVGAnimatedRect * *aViewBox)
-{
-  return mViewBox.ToDOMAnimatedRect(aViewBox, this);
-}
+} // namespace dom
+} // namespace mozilla
 
-/* readonly attribute SVGPreserveAspectRatio preserveAspectRatio; */
-NS_IMETHODIMP
-nsSVGSymbolElement::GetPreserveAspectRatio(nsISupports
-                                           **aPreserveAspectRatio)
-{
-  nsRefPtr<DOMSVGAnimatedPreserveAspectRatio> ratio;
-  mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(getter_AddRefs(ratio), this);
-  ratio.forget(aPreserveAspectRatio);
-  return NS_OK;
-}
-
-//----------------------------------------------------------------------
-// nsIContent methods
-
-NS_IMETHODIMP_(bool)
-nsSVGSymbolElement::IsAttributeMapped(const nsIAtom* name) const
-{
-  static const MappedAttributeEntry* const map[] = {
-    sColorMap,
-    sFEFloodMap,
-    sFillStrokeMap,
-    sFiltersMap,
-    sFontSpecificationMap,
-    sGradientStopMap,
-    sGraphicsMap,
-    sLightingEffectsMap,
-    sMarkersMap,
-    sTextContentElementsMap,
-    sViewportsMap
-   };
-
-  return FindAttributeDependence(name, map) ||
-    nsSVGSymbolElementBase::IsAttributeMapped(name);
-}
-
-//----------------------------------------------------------------------
-// nsSVGElement methods
-
-nsSVGViewBox *
-nsSVGSymbolElement::GetViewBox()
-{
-  return &mViewBox;
-}
-
-SVGAnimatedPreserveAspectRatio *
-nsSVGSymbolElement::GetPreserveAspectRatio()
-{
-  return &mPreserveAspectRatio;
-}
+#endif // mozilla_dom_SVGSymbolElement_h
--- a/content/svg/content/src/SVGTransformableElement.cpp
+++ b/content/svg/content/src/SVGTransformableElement.cpp
@@ -15,31 +15,19 @@ namespace dom {
 
 //----------------------------------------------------------------------
 // nsISupports methods
 
 NS_IMPL_ADDREF_INHERITED(SVGTransformableElement, SVGLocatableElement)
 NS_IMPL_RELEASE_INHERITED(SVGTransformableElement, SVGLocatableElement)
 
 NS_INTERFACE_MAP_BEGIN(SVGTransformableElement)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTransformable)
+  NS_INTERFACE_MAP_ENTRY(mozilla::dom::SVGTransformableElement)
 NS_INTERFACE_MAP_END_INHERITING(SVGLocatableElement)
 
-
-//----------------------------------------------------------------------
-// nsIDOMSVGTransformable methods
-/* readonly attribute nsISupports transform; */
-
-NS_IMETHODIMP
-SVGTransformableElement::GetTransform(nsISupports **aTransform)
-{
-  *aTransform = Transform().get();
-  return NS_OK;
-}
-
 already_AddRefed<DOMSVGAnimatedTransformList>
 SVGTransformableElement::Transform()
 {
   // We're creating a DOM wrapper, so we must tell GetAnimatedTransformList
   // to allocate the SVGAnimatedTransformList if it hasn't already done so:
   return DOMSVGAnimatedTransformList::GetDOMWrapper(
            GetAnimatedTransformList(DO_ALLOCATE), this).get();
 
--- a/content/svg/content/src/SVGTransformableElement.h
+++ b/content/svg/content/src/SVGTransformableElement.h
@@ -2,39 +2,36 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef SVGTransformableElement_h
 #define SVGTransformableElement_h
 
 #include "mozilla/dom/SVGLocatableElement.h"
-#include "nsIDOMSVGTransformable.h"
 #include "gfxMatrix.h"
 #include "SVGAnimatedTransformList.h"
 
 #define MOZILLA_SVGTRANSFORMABLEELEMENT_IID \
   { 0x77888cba, 0x0b43, 0x4654, \
     {0x96, 0x3c, 0xf5, 0x50, 0xfc, 0xb5, 0x5e, 0x32}}
 
 namespace mozilla {
 class DOMSVGAnimatedTransformList;
 
 namespace dom {
-class SVGTransformableElement : public SVGLocatableElement,
-                                public nsIDOMSVGTransformable
+class SVGTransformableElement : public SVGLocatableElement
 {
 public:
   SVGTransformableElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : SVGLocatableElement(aNodeInfo) {}
   virtual ~SVGTransformableElement() {}
 
   NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_SVGTRANSFORMABLEELEMENT_IID)
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIDOMSVGTRANSFORMABLE
 
   // WebIDL
   already_AddRefed<DOMSVGAnimatedTransformList> Transform();
 
   // nsIContent interface
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
rename from content/svg/content/src/nsSVGUseElement.cpp
rename to content/svg/content/src/SVGUseElement.cpp
--- a/content/svg/content/src/nsSVGUseElement.cpp
+++ b/content/svg/content/src/SVGUseElement.cpp
@@ -1,236 +1,280 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Util.h"
 
-#include "nsSVGUseElement.h"
+#include "mozilla/dom/SVGUseElement.h"
+#include "mozilla/dom/SVGUseElementBinding.h"
 #include "nsIDOMSVGGElement.h"
 #include "nsGkAtoms.h"
 #include "mozilla/dom/SVGSVGElement.h"
 #include "nsIDOMSVGSymbolElement.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "mozilla/dom/Element.h"
 #include "nsContentUtils.h"
 
-using namespace mozilla;
-using namespace mozilla::dom;
+DOMCI_NODE_DATA(SVGUseElement, mozilla::dom::SVGUseElement)
+
+NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Use)
+
+namespace mozilla {
+namespace dom {
+
+JSObject*
+SVGUseElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
+{
+  return SVGUseElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
+}
 
 ////////////////////////////////////////////////////////////////////////
 // implementation
 
-nsSVGElement::LengthInfo nsSVGUseElement::sLengthInfo[4] =
+nsSVGElement::LengthInfo SVGUseElement::sLengthInfo[4] =
 {
   { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
   { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
   { &nsGkAtoms::width, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
   { &nsGkAtoms::height, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
 };
 
-nsSVGElement::StringInfo nsSVGUseElement::sStringInfo[1] =
+nsSVGElement::StringInfo SVGUseElement::sStringInfo[1] =
 {
   { &nsGkAtoms::href, kNameSpaceID_XLink, true }
 };
 
-NS_IMPL_NS_NEW_SVG_ELEMENT(Use)
-
 //----------------------------------------------------------------------
 // nsISupports methods
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsSVGUseElement)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsSVGUseElement,
-                                                nsSVGUseElementBase)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGUseElement,
+                                                SVGUseElementBase)
   nsAutoScriptBlocker scriptBlocker;
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOriginal)
   tmp->DestroyAnonymousContent();
   tmp->UnlinkSource();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsSVGUseElement,
-                                                  nsSVGUseElementBase)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGUseElement,
+                                                  SVGUseElementBase)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOriginal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mClone)
   tmp->mSource.Traverse(&cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_ADDREF_INHERITED(nsSVGUseElement,nsSVGUseElementBase)
-NS_IMPL_RELEASE_INHERITED(nsSVGUseElement,nsSVGUseElementBase)
+NS_IMPL_ADDREF_INHERITED(SVGUseElement,SVGUseElementBase)
+NS_IMPL_RELEASE_INHERITED(SVGUseElement,SVGUseElementBase)
 
-DOMCI_NODE_DATA(SVGUseElement, nsSVGUseElement)
-
-NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsSVGUseElement)
-  NS_NODE_INTERFACE_TABLE6(nsSVGUseElement, nsIDOMNode, nsIDOMElement,
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(SVGUseElement)
+  NS_NODE_INTERFACE_TABLE6(SVGUseElement, nsIDOMNode, nsIDOMElement,
                            nsIDOMSVGElement,
                            nsIDOMSVGURIReference,
                            nsIDOMSVGUseElement, nsIMutationObserver)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGUseElement)
-  if (aIID.Equals(NS_GET_IID(nsSVGUseElement)))
+  if (aIID.Equals(NS_GET_IID(mozilla::dom::SVGUseElement)))
     foundInterface = reinterpret_cast<nsISupports*>(this);
   else
-NS_INTERFACE_MAP_END_INHERITING(nsSVGUseElementBase)
+NS_INTERFACE_MAP_END_INHERITING(SVGUseElementBase)
 
 //----------------------------------------------------------------------
 // Implementation
 
 #ifdef _MSC_VER
 // Disable "warning C4355: 'this' : used in base member initializer list".
 // We can ignore that warning because we know that mSource's constructor 
 // doesn't dereference the pointer passed to it.
 #pragma warning(push)
 #pragma warning(disable:4355)
 #endif
-nsSVGUseElement::nsSVGUseElement(already_AddRefed<nsINodeInfo> aNodeInfo)