Merge inbound to mozilla-central. a=merge
authorGurzau Raul <rgurzau@mozilla.com>
Tue, 30 Jan 2018 12:01:49 +0200
changeset 401460 9746e0a0a81cc089ff65e30ae902864846cd1b94
parent 401360 a23e3bbd20191317ba5a9a1e17fb86caffc7b756 (current diff)
parent 401459 d32017c991aa5c848ead56d8f0b31ac18f86cff3 (diff)
child 401461 05c3d963a3555a39a74dfc04184278fbe84a6a2f
child 401501 a680bba448c42b4b63f344b0f1f6671f3ab483e7
push id58825
push userrgurzau@mozilla.com
push dateTue, 30 Jan 2018 10:11:38 +0000
treeherderautoland@05c3d963a355 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone60.0a1
first release with
nightly linux32
9746e0a0a81c / 60.0a1 / 20180130102929 / files
nightly linux64
9746e0a0a81c / 60.0a1 / 20180130102929 / files
nightly mac
9746e0a0a81c / 60.0a1 / 20180130102929 / files
nightly win32
9746e0a0a81c / 60.0a1 / 20180130102929 / files
nightly win64
9746e0a0a81c / 60.0a1 / 20180130102929 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
browser/components/enterprisepolicies/Policies.jsm
browser/components/migration/MigrationUtils.jsm
browser/extensions/pocket/content/pktApi.jsm
browser/extensions/shield-recipe-client/bootstrap.js
browser/extensions/shield-recipe-client/content/AboutPages.jsm
browser/extensions/shield-recipe-client/lib/AddonStudies.jsm
browser/extensions/shield-recipe-client/lib/PreferenceExperiments.jsm
browser/extensions/shield-recipe-client/lib/ShieldPreferences.jsm
browser/extensions/shield-recipe-client/lib/ShieldRecipeClient.jsm
browser/extensions/shield-recipe-client/test/browser/browser_AddonStudies.js
browser/extensions/shield-recipe-client/test/browser/browser_PreferenceExperiments.js
browser/extensions/shield-recipe-client/test/browser/browser_ShieldRecipeClient.js
browser/extensions/shield-recipe-client/test/browser/head.js
dom/base/nsContentUtils.cpp
dom/html/nsGenericHTMLElement.cpp
dom/interfaces/html/nsIDOMHTMLDocument.idl
dom/interfaces/html/nsIDOMHTMLElement.idl
dom/time/DateCacheCleaner.cpp
dom/time/DateCacheCleaner.h
dom/time/TimeChangeObserver.cpp
dom/time/TimeChangeObserver.h
dom/time/TimeManager.cpp
dom/time/TimeManager.h
dom/time/TimeService.cpp
dom/time/TimeService.h
dom/time/moz.build
dom/time/nsITimeService.idl
dom/webidl/MozTimeManager.webidl
mobile/android/chrome/content/browser.js
mobile/android/components/HelperAppDialog.js
old-configure.in
testing/marionette/interaction.js
toolkit/components/places/SyncedBookmarksMirror.jsm
toolkit/mozapps/extensions/nsBlocklistService.js
tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
--- a/accessible/base/nsCoreUtils.cpp
+++ b/accessible/base/nsCoreUtils.cpp
@@ -5,18 +5,16 @@
 
 #include "nsCoreUtils.h"
 
 #include "nsIAccessibleTypes.h"
 
 #include "nsIBaseWindow.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocument.h"
-#include "nsIDOMHTMLDocument.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsRange.h"
 #include "nsIBoxObject.h"
 #include "nsXULElement.h"
 #include "mozilla/dom/BoxObject.h"
 #include "nsIDocShell.h"
 #include "nsIObserverService.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -8,16 +8,17 @@
 #include "nsIXBLAccessible.h"
 
 #include "EmbeddedObjCollector.h"
 #include "AccGroupInfo.h"
 #include "AccIterator.h"
 #include "nsAccUtils.h"
 #include "nsAccessibilityService.h"
 #include "ApplicationAccessible.h"
+#include "nsGenericHTMLElement.h"
 #include "NotificationController.h"
 #include "nsEventShell.h"
 #include "nsTextEquivUtils.h"
 #include "DocAccessibleChild.h"
 #include "EventTree.h"
 #include "GeckoProfiler.h"
 #include "Relation.h"
 #include "Role.h"
@@ -25,17 +26,16 @@
 #include "States.h"
 #include "StyleInfo.h"
 #include "TableAccessible.h"
 #include "TableCellAccessible.h"
 #include "TreeWalker.h"
 
 #include "nsIDOMElement.h"
 #include "nsIDOMNodeFilter.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMTreeWalker.h"
 #include "nsIDOMXULButtonElement.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULLabelElement.h"
 #include "nsIDOMXULSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
@@ -71,16 +71,17 @@
 #include "nsAttrName.h"
 
 #ifdef DEBUG
 #include "nsIDOMCharacterData.h"
 #endif
 
 #include "mozilla/Assertions.h"
 #include "mozilla/BasicEvents.h"
+#include "mozilla/ErrorResult.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Unused.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
@@ -784,20 +785,18 @@ Accessible::XULElmName(DocAccessible* aD
   } else {
     nsCOMPtr<nsIDOMXULSelectControlItemElement> itemEl = do_QueryInterface(aElm);
     if (itemEl) {
       itemEl->GetLabel(aName);
     } else {
       nsCOMPtr<nsIDOMXULSelectControlElement> select = do_QueryInterface(aElm);
       // Use label if this is not a select control element which
       // uses label attribute to indicate which option is selected
-      if (!select) {
-        nsCOMPtr<nsIDOMXULElement> xulEl(do_QueryInterface(aElm));
-        if (xulEl)
-          xulEl->GetAttribute(NS_LITERAL_STRING("label"), aName);
+      if (!select && aElm->IsElement()) {
+        aElm->AsElement()->GetAttribute(NS_LITERAL_STRING("label"), aName);
       }
     }
   }
 
   // CASES #2 and #3 ------ label as a child or <label control="id" ... > </label>
   if (aName.IsEmpty()) {
     Accessible* labelAcc = nullptr;
     XULLabelIterator iter(aDocument, aElm);
@@ -1068,21 +1067,18 @@ Accessible::NativeAttributes()
     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::_class, _class);
 
   // Expose tag.
   nsAutoString tagName;
   mContent->NodeInfo()->GetName(tagName);
   nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tag, tagName);
 
   // Expose draggable object attribute.
-  nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mContent);
-  if (htmlElement) {
-    bool draggable = false;
-    htmlElement->GetDraggable(&draggable);
-    if (draggable) {
+  if (auto htmlElement = nsGenericHTMLElement::FromContent(mContent)) {
+    if (htmlElement->Draggable()) {
       nsAccUtils::SetAccAttr(attributes, nsGkAtoms::draggable,
                              NS_LITERAL_STRING("true"));
     }
   }
 
   // Don't calculate CSS-based object attributes when no frame (i.e.
   // the accessible is unattached from the tree).
   if (!mContent->GetPrimaryFrame())
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -41,19 +41,17 @@ const nsIAccessibleTable = Components.in
 const nsIAccessibleTableCell = Components.interfaces.nsIAccessibleTableCell;
 const nsIAccessibleTraversalRule = Components.interfaces.nsIAccessibleTraversalRule;
 const nsIAccessibleValue = Components.interfaces.nsIAccessibleValue;
 
 const nsIObserverService = Components.interfaces.nsIObserverService;
 
 const nsIDOMDocument = Components.interfaces.nsIDOMDocument;
 const nsIDOMEvent = Components.interfaces.nsIDOMEvent;
-const nsIDOMHTMLDocument = Components.interfaces.nsIDOMHTMLDocument;
 const nsIDOMNode = Components.interfaces.nsIDOMNode;
-const nsIDOMHTMLElement = Components.interfaces.nsIDOMHTMLElement;
 const nsIDOMWindow = Components.interfaces.nsIDOMWindow;
 const nsIDOMXULElement = Components.interfaces.nsIDOMXULElement;
 
 const nsIPropertyElement = Components.interfaces.nsIPropertyElement;
 
 // //////////////////////////////////////////////////////////////////////////////
 // OS detect
 
--- a/accessible/tests/mochitest/editabletext/editabletext.js
+++ b/accessible/tests/mochitest/editabletext/editabletext.js
@@ -198,17 +198,17 @@ function editableTextTest(aID) {
   // ////////////////////////////////////////////////////////////////////////////
   // Implementation details.
 
   function getValue() {
     var elm = getNode(aID);
     if (elm instanceof Components.interfaces.nsIDOMNSEditableElement)
       return elm.value;
 
-    if (elm instanceof Components.interfaces.nsIDOMHTMLDocument)
+    if (ChromeUtils.getClassName(elm) == "HTMLDocument")
       return elm.body.textContent;
 
     return elm.textContent;
   }
 
   /**
    * Common checkers.
    */
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -58,16 +58,24 @@ var gA11yEventDumpToConsole = false;
 var gA11yEventDumpToAppConsole = false;
 
 /**
  * Semicolon separated set of logging features.
  */
 var gA11yEventDumpFeature = "";
 
 /**
+ * Function to detect HTML elements when given a node.
+ */
+function isHTMLElement(aNode) {
+  return aNode.nodeType == aNode.ELEMENT_NODE &&
+         aNode.namespaceURI == "http://www.w3.org/1999/xhtml";
+}
+
+/**
  * Executes the function when requested event is handled.
  *
  * @param aEventType  [in] event type
  * @param aTarget     [in] event target
  * @param aFunc       [in] function to call when event is handled
  * @param aContext    [in, optional] object in which context the function is
  *                    called
  * @param aArg1       [in, optional] argument passed into the function
@@ -1054,26 +1062,26 @@ function synthClick(aNodeOrID, aCheckerO
   this.invoke = function synthClick_invoke() {
     var targetNode = this.DOMNode;
     if (targetNode instanceof nsIDOMDocument) {
       targetNode =
         this.DOMNode.body ? this.DOMNode.body : this.DOMNode.documentElement;
     }
 
     // Scroll the node into view, otherwise synth click may fail.
-    if (targetNode instanceof nsIDOMHTMLElement) {
+    if (isHTMLElement(targetNode)) {
       targetNode.scrollIntoView(true);
     } else if (targetNode instanceof nsIDOMXULElement) {
       var targetAcc = getAccessible(targetNode);
       targetAcc.scrollTo(SCROLL_TYPE_ANYWHERE);
     }
 
     var x = 1, y = 1;
     if (aArgs && ("where" in aArgs) && aArgs.where == "right") {
-      if (targetNode instanceof nsIDOMHTMLElement)
+      if (isHTMLElement(targetNode))
         x = targetNode.offsetWidth - 1;
       else if (targetNode instanceof nsIDOMXULElement)
         x = targetNode.boxObject.width - 1;
     }
     synthesizeMouse(targetNode, x, y, aArgs ? aArgs : {});
   };
 
   this.finalCheck = function synthClick_finalCheck() {
@@ -2073,25 +2081,25 @@ var gLogger =
 
     var dumpElm = document.getElementById(gA11yEventDumpID);
     if (!dumpElm) {
       ok(false,
          "No dump element '" + gA11yEventDumpID + "' within the document!");
       return;
     }
 
-    var containerTagName = document instanceof nsIDOMHTMLDocument ?
+    var containerTagName = ChromeUtils.getClassName(document) == "HTMLDocument" ?
       "div" : "description";
 
     var container = document.createElement(containerTagName);
     if (aHasIndent)
       container.setAttribute("style", "padding-left: 10px;");
 
     if (aPreEmphText) {
-      var inlineTagName = document instanceof nsIDOMHTMLDocument ?
+      var inlineTagName = ChromeUtils.getClassName(document) == "HTMLDocument" ?
         "span" : "description";
       var emphElm = document.createElement(inlineTagName);
       emphElm.setAttribute("style", "color: blue;");
       emphElm.textContent = aPreEmphText;
 
       container.appendChild(emphElm);
     }
 
--- a/accessible/windows/sdn/sdnAccessible.cpp
+++ b/accessible/windows/sdn/sdnAccessible.cpp
@@ -7,17 +7,16 @@
 #include "sdnAccessible-inl.h"
 #include "ISimpleDOM_i.c"
 
 #include "DocAccessibleWrap.h"
 
 #include "nsAttrName.h"
 #include "nsCoreUtils.h"
 #include "nsIAccessibleTypes.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsICSSDeclaration.h"
 #include "nsNameSpaceManager.h"
 #include "nsServiceManagerUtils.h"
 #include "nsWinUtils.h"
 #include "nsRange.h"
 
 #include "mozilla/dom/BorrowedAttrInfo.h"
 #include "mozilla/dom/Element.h"
@@ -85,30 +84,25 @@ sdnAccessible::get_nodeInfo(BSTR __RPC_F
   *aNodeValue = nullptr;
   *aNumChildren = 0;
   *aUniqueID = 0;
   *aNodeType = 0;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mNode));
-
-  uint16_t nodeType = 0;
-  DOMNode->GetNodeType(&nodeType);
+  uint16_t nodeType = mNode->NodeType();
   *aNodeType = static_cast<unsigned short>(nodeType);
 
   if (*aNodeType !=  NODETYPE_TEXT) {
-    nsAutoString nodeName;
-    DOMNode->GetNodeName(nodeName);
-    *aNodeName = ::SysAllocString(nodeName.get());
+    *aNodeName = ::SysAllocString(mNode->NodeName().get());
   }
 
   nsAutoString nodeValue;
-  DOMNode->GetNodeValue(nodeValue);
+  mNode->GetNodeValue(nodeValue);
   *aNodeValue = ::SysAllocString(nodeValue.get());
 
   *aNameSpaceID = mNode->IsContent()
     ? static_cast<short>(mNode->AsContent()->GetNameSpaceID())
     : 0;
 
   // This is a unique ID for every content node. The 3rd party accessibility
   // application can compare this to the childID we return for events such as
--- a/accessible/windows/sdn/sdnTextAccessible.cpp
+++ b/accessible/windows/sdn/sdnTextAccessible.cpp
@@ -37,18 +37,17 @@ sdnTextAccessible::get_domText(BSTR __RP
     return E_INVALIDARG;
   *aText = nullptr;
 
   if (mAccessible->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString nodeValue;
 
-  nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mAccessible->GetContent()));
-  DOMNode->GetNodeValue(nodeValue);
+  mAccessible->GetContent()->GetNodeValue(nodeValue);
   if (nodeValue.IsEmpty())
     return S_FALSE;
 
   *aText = ::SysAllocStringLen(nodeValue.get(), nodeValue.Length());
   return *aText ? S_OK : E_OUTOFMEMORY;
 }
 
 STDMETHODIMP
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -424,20 +424,20 @@ this.ExtensionsUI = {
         hideClose: true,
         timeout: Date.now() + 30000,
         popupIconURL: icon,
         eventCallback(topic) {
           if (topic == "showing") {
             let doc = this.browser.ownerDocument;
         // eslint-disable-next-line no-unsanitized/property
             doc.getElementById("addon-installed-notification-header")
-               .innerHTML = msg1;
+               .unsafeSetInnerHTML(msg1);
             // eslint-disable-next-line no-unsanitized/property
             doc.getElementById("addon-installed-notification-message")
-               .innerHTML = msg2;
+               .unsafeSetInnerHTML(msg2);
           } else if (topic == "dismissed") {
             resolve();
           }
         }
       };
 
       popups.show(target, "addon-installed", "", "addons-notification-icon",
                   action, null, options);
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -644,31 +644,36 @@ function prompt(aBrowser, aRequest) {
             warning.hidden = false;
             let string;
             let bundle = chromeWin.gNavigatorBundle;
 
             let learnMoreText =
               bundle.getString("getUserMedia.shareScreen.learnMoreLabel");
             let baseURL =
               Services.urlFormatter.formatURLPref("app.support.baseURL");
-            let learnMore =
-              "<label class='text-link' href='" + baseURL + "screenshare-safety'>" +
-              learnMoreText + "</label>";
+
+            let learnMore = chromeWin.document.createElement("label");
+            learnMore.className = "text-link";
+            learnMore.setAttribute("href", baseURL + "screenshare-safety");
+            learnMore.textContent = learnMoreText;
 
             if (type == "screen") {
               string = bundle.getFormattedString("getUserMedia.shareScreenWarning.message",
-                                                 [learnMore]);
+                                                 ["<>"]);
             } else {
               let brand =
                 doc.getElementById("bundle_brand").getString("brandShortName");
               string = bundle.getFormattedString("getUserMedia.shareFirefoxWarning.message",
-                                                 [brand, learnMore]);
+                                                 [brand, "<>"]);
             }
-            // eslint-disable-next-line no-unsanitized/property
-            warning.innerHTML = string;
+
+            let [pre, post] = string.split("<>");
+            warning.textContent = pre;
+            warning.appendChild(learnMore);
+            warning.appendChild(chromeWin.document.createTextNode(post));
           }
 
           let perms = Services.perms;
           let chromeUri = Services.io.newURI(doc.documentURI);
           perms.add(chromeUri, "MediaManagerVideo", perms.ALLOW_ACTION,
                     perms.EXPIRE_SESSION);
 
           video.deviceId = deviceId;
--- a/devtools/client/inspector/components/InspectorTabPanel.js
+++ b/devtools/client/inspector/components/InspectorTabPanel.js
@@ -20,18 +20,20 @@ const { div } = dom;
  */
 class InspectorTabPanel extends Component {
   static get propTypes() {
     return {
       // ID of the node that should be rendered as the content.
       id: PropTypes.string.isRequired,
       // Optional prefix for panel IDs.
       idPrefix: PropTypes.string,
-      // Optional mount callback
+      // Optional mount callback.
       onMount: PropTypes.func,
+      // Optional unmount callback.
+      onUnmount: PropTypes.func,
     };
   }
 
   static get defaultProps() {
     return {
       idPrefix: "",
     };
   }
@@ -47,16 +49,20 @@ class InspectorTabPanel extends Componen
       this.props.onMount(this.refs.content, this.props);
     }
   }
 
   componentWillUnmount() {
     let doc = this.refs.content.ownerDocument;
     let panels = doc.getElementById("tabpanels");
 
+    if (this.props.onUnmount) {
+      this.props.onUnmount(this.refs.content, this.props);
+    }
+
     // Move panel's content node back into list of tab panels.
     panels.appendChild(this.refs.content.firstChild);
   }
 
   render() {
     return (
       div({
         ref: "content",
--- a/devtools/client/inspector/toolsidebar.js
+++ b/devtools/client/inspector/toolsidebar.js
@@ -132,16 +132,17 @@ ToolSidebar.prototype = {
   addFrameTab: function (id, title, url, selected, index) {
     let panel = this.InspectorTabPanel({
       id: id,
       idPrefix: this.TABPANEL_ID_PREFIX,
       key: id,
       title: title,
       url: url,
       onMount: this.onSidePanelMounted.bind(this),
+      onUnmount: this.onSidePanelUnmounted.bind(this),
     });
 
     this.addTab(id, title, panel, selected, index);
   },
 
   onSidePanelMounted: function (content, props) {
     let iframe = content.querySelector("iframe");
     if (!iframe || iframe.getAttribute("src")) {
@@ -158,16 +159,30 @@ ToolSidebar.prototype = {
       }
       this.emit(props.id + "-ready");
     };
 
     iframe.addEventListener("load", onIFrameLoaded, true);
     iframe.setAttribute("src", props.url);
   },
 
+  onSidePanelUnmounted: function (content, props) {
+    let iframe = content.querySelector("iframe");
+    if (!iframe || !iframe.hasAttribute("src")) {
+      return;
+    }
+
+    let win = iframe.contentWindow;
+    if ("destroy" in win) {
+      win.destroy(this._toolPanel, iframe);
+    }
+
+    iframe.removeAttribute("src");
+  },
+
   /**
    * Remove an existing tab.
    * @param {String} tabId The ID of the tab that was used to register it, or
    * the tab id attribute value if the tab existed before the sidebar
    * got created.
    * @param {String} tabPanelId Optional. If provided, this ID will be used
    * instead of the tabId to retrieve and remove the corresponding <tabpanel>
    */
--- a/devtools/client/jsonview/components/MainTabbedArea.js
+++ b/devtools/client/jsonview/components/MainTabbedArea.js
@@ -56,36 +56,39 @@ define(function (require, exports, modul
     }
 
     render() {
       return (
         Tabs({
           tabActive: this.state.tabActive,
           onAfterChange: this.onTabChanged},
           TabPanel({
+            id: "json",
             className: "json",
             title: JSONView.Locale.$STR("jsonViewer.tab.JSON")},
             JsonPanel({
               data: this.state.json,
               expandedNodes: this.props.expandedNodes,
               actions: this.props.actions,
               searchFilter: this.state.searchFilter
             })
           ),
           TabPanel({
+            id: "rawdata",
             className: "rawdata",
             title: JSONView.Locale.$STR("jsonViewer.tab.RawData")},
             TextPanel({
               isValidJson: !(this.state.json instanceof Error) &&
                            document.readyState != "loading",
               data: this.state.jsonText,
               actions: this.props.actions
             })
           ),
           TabPanel({
+            id: "headers",
             className: "headers",
             title: JSONView.Locale.$STR("jsonViewer.tab.Headers")},
             HeadersPanel({
               data: this.props.headers,
               actions: this.props.actions,
               searchFilter: this.props.searchFilter
             })
           )
--- a/devtools/client/shared/components/tabs/Tabs.js
+++ b/devtools/client/shared/components/tabs/Tabs.js
@@ -67,24 +67,25 @@ define(function (require, exports, modul
     }
 
     constructor(props) {
       super(props);
 
       this.state = {
         tabActive: props.tabActive,
 
-        // This array is used to store an information whether a tab
-        // at specific index has already been created (e.g. selected
-        // at least once).
-        // If yes, it's rendered even if not currently selected.
-        // This is because in some cases we don't want to re-create
-        // tab content when it's being unselected/selected.
-        // E.g. in case of an iframe being used as a tab-content
-        // we want the iframe to stay in the DOM.
+        // This array is used to store an object containing information on whether a tab
+        // at a specified index has already been created (e.g. selected at least once) and
+        // the tab id. An example of the object structure is the following:
+        // [{ isCreated: true, tabId: "ruleview" }, { isCreated: false, tabId: "foo" }].
+        // If the tab at the specified index has already been created, it's rendered even
+        // if not currently selected. This is because in some cases we don't want
+        // to re-create tab content when it's being unselected/selected.
+        // E.g. in case of an iframe being used as a tab-content we want the iframe to
+        // stay in the DOM.
         created: [],
 
         // True if tabs can't fit into available horizontal space.
         overflow: false,
       };
 
       this.onOverflow = this.onOverflow.bind(this);
       this.onUnderflow = this.onUnderflow.bind(this);
@@ -111,34 +112,56 @@ define(function (require, exports, modul
       let index = this.state.tabActive;
       if (this.props.onMount) {
         this.props.onMount(index);
       }
     }
 
     componentWillReceiveProps(nextProps) {
       let { children, tabActive } = nextProps;
+      let panels = children.filter(panel => panel);
+      let created = [...this.state.created];
 
-      // Check type of 'tabActive' props to see if it's valid
-      // (it's 0-based index).
+      // If the children props has changed due to an addition or removal of a tab,
+      // update the state's created array with the latest tab ids and whether or not
+      // the tab is already created.
+      if (this.state.created.length != panels.length) {
+        created = panels.map(panel => {
+          // Get whether or not the tab has already been created from the previous state.
+          let createdEntry = this.state.created.find(entry => {
+            return entry && entry.tabId === panel.props.id;
+          });
+          let isCreated = !!createdEntry && createdEntry.isCreated;
+          let tabId = panel.props.id;
+
+          return {
+            isCreated,
+            tabId,
+          };
+        });
+      }
+
+      // Check type of 'tabActive' props to see if it's valid (it's 0-based index).
       if (typeof tabActive === "number") {
-        let panels = children.filter((panel) => panel);
-
         // Reset to index 0 if index overflows the range of panel array
         tabActive = (tabActive < panels.length && tabActive >= 0) ?
           tabActive : 0;
 
-        let created = [...this.state.created];
-        created[tabActive] = true;
+        created[tabActive] = Object.assign({}, created[tabActive], {
+          isCreated: true,
+        });
 
         this.setState({
-          created,
           tabActive,
         });
       }
+
+      this.setState({
+        created,
+      });
     }
 
     componentWillUnmount() {
       let node = findDOMNode(this);
       node.removeEventListener("keydown", this.onKeyDown);
 
       if (this.props.showAllTabsMenu) {
         node.removeEventListener("overflow", this.onOverflow);
@@ -204,21 +227,23 @@ define(function (require, exports, modul
       if (onBeforeChange) {
         let cancel = onBeforeChange(index);
         if (cancel) {
           return;
         }
       }
 
       let created = [...this.state.created];
-      created[index] = true;
+      created[index] = Object.assign({}, created[index], {
+        isCreated: true,
+      });
 
       let newState = Object.assign({}, this.state, {
+        created,
         tabActive: index,
-        created: created
       });
 
       this.setState(newState, () => {
         // Properly set focus on selected tab.
         let node = findDOMNode(this);
         let selectedTab = node.querySelector(".is-active > a");
         if (selectedTab) {
           selectedTab.focus();
@@ -330,16 +355,18 @@ define(function (require, exports, modul
         .filter((tab) => tab)
         .map((tab, index) => {
           let selected = selectedIndex === index;
           if (renderOnlySelected && !selected) {
             return null;
           }
 
           let id = tab.props.id;
+          let isCreated = this.state.created[index] &&
+            this.state.created[index].isCreated;
 
           // Use 'visibility:hidden' + 'height:0' for hiding content of non-selected
           // tab. It's faster than 'display:none' because it avoids triggering frame
           // destruction and reconstruction. 'width' is not changed to avoid relayout.
           let style = {
             visibility: selected ? "visible" : "hidden",
             height: selected ? "100%" : "0",
           };
@@ -349,23 +376,23 @@ define(function (require, exports, modul
           if (typeof tab.panel == "function" && selected) {
             tab.panel = tab.panel(tab);
           }
           let panel = tab.panel || tab;
 
           return (
             dom.div({
               id: id ? id + "-panel" : "panel-" + index,
-              key: index,
+              key: id,
               style: style,
               className: selected ? "tab-panel-box" : "tab-panel-box hidden",
               role: "tabpanel",
               "aria-labelledby": id ? id + "-tab" : "tab-" + index,
             },
-              (selected || this.state.created[index]) ? panel : null
+              (selected || isCreated) ? panel : null
             )
           );
         });
 
       return (
         dom.div({className: "panels"},
           panels
         )
@@ -383,16 +410,18 @@ define(function (require, exports, modul
   }
 
   /**
    * Renders simple tab 'panel'.
    */
   class Panel extends Component {
     static get propTypes() {
       return {
+        id: PropTypes.string.isRequired,
+        className: PropTypes.string,
         title: PropTypes.string.isRequired,
         children: PropTypes.oneOfType([
           PropTypes.array,
           PropTypes.element
         ]).isRequired
       };
     }
 
--- a/devtools/client/webconsole/net/components/net-info-body.js
+++ b/devtools/client/webconsole/net/components/net-info-body.js
@@ -93,74 +93,82 @@ class NetInfoBody extends Component {
     let hasParams = request.queryString && request.queryString.length;
     let hasPostData = request.bodySize > 0;
 
     let panels = [];
 
     // Headers tab
     panels.push(
       TabPanel({
+        id: "headers",
         className: "headers",
         key: "headers",
         title: Locale.$STR("netRequest.headers")},
         HeadersTab({data: data, actions: actions})
       )
     );
 
     // URL parameters tab
     if (hasParams) {
       panels.push(
         TabPanel({
+          id: "params",
           className: "params",
           key: "params",
           title: Locale.$STR("netRequest.params")},
           ParamsTab({data: data, actions: actions})
         )
       );
     }
 
     // Posted data tab
     if (hasPostData) {
       panels.push(
         TabPanel({
+          id: "post",
           className: "post",
           key: "post",
           title: Locale.$STR("netRequest.post")},
           PostTab({data: data, actions: actions})
         )
       );
     }
 
     // Response tab
     panels.push(
-      TabPanel({className: "response", key: "response",
+      TabPanel({
+        id: "response",
+        className: "response",
+        key: "response",
         title: Locale.$STR("netRequest.response")},
         ResponseTab({data: data, actions: actions})
       )
     );
 
     // Cookies tab
     if (this.hasCookies()) {
       panels.push(
         TabPanel({
+          id: "cookies",
           className: "cookies",
           key: "cookies",
           title: Locale.$STR("netRequest.cookies")},
           CookiesTab({
             data: data,
             actions: actions
           })
         )
       );
     }
 
     // Stacktrace tab
     if (this.hasStackTrace()) {
       panels.push(
         TabPanel({
+          id: "stacktrace-tab",
           className: "stacktrace-tab",
           key: "stacktrace",
           title: Locale.$STR("netRequest.callstack")},
           StackTraceTab({
             data: data,
             actions: actions,
             sourceMapService: sourceMapService,
           })
--- a/devtools/server/actors/object.js
+++ b/devtools/server/actors/object.js
@@ -1848,21 +1848,25 @@ DebuggerServer.ObjectActorPreviewers.Obj
           let actor = hooks.createValueGrip(obj.makeDebuggeeValue(node));
           preview.childNodes.push(actor);
           if (preview.childNodes.length == OBJECT_PREVIEW_MAX_ITEMS) {
             break;
           }
         }
       }
     } else if (rawObj instanceof Ci.nsIDOMElement) {
-      // Add preview for DOM element attributes.
-      if (rawObj instanceof Ci.nsIDOMHTMLElement) {
+      // For HTML elements (in an HTML document, at least), the nodeName is an
+      // uppercased version of the actual element name.  Check for HTML
+      // elements, that is elements in the HTML namespace, and lowercase the
+      // nodeName in that case.
+      if (rawObj.namespaceURI == "http://www.w3.org/1999/xhtml") {
         preview.nodeName = preview.nodeName.toLowerCase();
       }
 
+      // Add preview for DOM element attributes.
       preview.attributes = {};
       preview.attributesLength = rawObj.attributes.length;
       for (let attr of rawObj.attributes) {
         preview.attributes[attr.nodeName] = hooks.createValueGrip(attr.value);
       }
     } else if (obj.class == "Attr") {
       preview.value = hooks.createValueGrip(rawObj.value);
     } else if (rawObj instanceof Ci.nsIDOMText ||
--- a/devtools/server/actors/styles.js
+++ b/devtools/server/actors/styles.js
@@ -1009,17 +1009,17 @@ var StyleRuleActor = protocol.ActorClass
             // Special case about:PreferenceStyleSheet, as it is generated on
             // the fly and the URI is not registered with the about:handler
             // https://bugzilla.mozilla.org/show_bug.cgi?id=935803#c37
             this._parentSheet.href !== "about:PreferenceStyleSheet");
   },
 
   getDocument: function (sheet) {
     if (sheet.ownerNode) {
-      return sheet.ownerNode instanceof Ci.nsIDOMHTMLDocument ?
+      return sheet.ownerNode.nodeType == sheet.ownerNode.DOCUMENT_NODE ?
              sheet.ownerNode : sheet.ownerNode.ownerDocument;
     } else if (sheet.parentStyleSheet) {
       return this.getDocument(sheet.parentStyleSheet);
     }
     throw (new Error("Failed trying to get the document of an invalid stylesheet"));
   },
 
   toString: function () {
--- a/devtools/server/actors/stylesheets.js
+++ b/devtools/server/actors/stylesheets.js
@@ -169,17 +169,17 @@ var StyleSheetActor = protocol.ActorClas
   },
 
   /**
    * Returns the stylesheet href or the document href if the sheet is inline.
    */
   get safeHref() {
     let href = this.href;
     if (!href) {
-      if (this.ownerNode instanceof Ci.nsIDOMHTMLDocument) {
+      if (this.ownerNode.nodeType == this.ownerNode.DOCUMENT_NODE) {
         href = this.ownerNode.location.href;
       } else if (this.ownerNode.ownerDocument &&
                  this.ownerNode.ownerDocument.location) {
         href = this.ownerNode.ownerDocument.location.href;
       }
     }
     return href;
   },
@@ -295,17 +295,17 @@ var StyleSheetActor = protocol.ActorClas
    */
   form: function (detail) {
     if (detail === "actorid") {
       return this.actorID;
     }
 
     let docHref;
     if (this.ownerNode) {
-      if (this.ownerNode instanceof Ci.nsIDOMHTMLDocument) {
+      if (this.ownerNode.nodeType == this.ownerNode.DOCUMENT_NODE) {
         docHref = this.ownerNode.location.href;
       } else if (this.ownerNode.ownerDocument && this.ownerNode.ownerDocument.location) {
         docHref = this.ownerNode.ownerDocument.location.href;
       }
     }
 
     let form = {
       actor: this.actorID,  // actorID is set when this actor is added to a pool
--- a/docshell/base/nsDocShellTreeOwner.cpp
+++ b/docshell/base/nsDocShellTreeOwner.cpp
@@ -33,20 +33,18 @@
 #include "Link.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/SVGTitleElement.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMFileList.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsIFormControl.h"
 #include "nsIDOMHTMLInputElement.h"
-#include "nsIDOMHTMLDocument.h"
 #include "nsIImageLoadingContent.h"
 #include "nsIWebNavigation.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsIPresShell.h"
 #include "nsIStringBundle.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsIDOMWindowCollection.h"
 #include "nsIWindowWatcher.h"
 #include "nsPIWindowWatcher.h"
 #include "nsIPrompt.h"
--- a/dom/base/Attr.cpp
+++ b/dom/base/Attr.cpp
@@ -44,17 +44,17 @@ namespace dom {
 bool Attr::sInitialized;
 
 Attr::Attr(nsDOMAttributeMap *aAttrMap,
            already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
            const nsAString  &aValue)
   : nsIAttribute(aAttrMap, aNodeInfo), mValue(aValue)
 {
   MOZ_ASSERT(mNodeInfo, "We must get a nodeinfo here!");
-  MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::ATTRIBUTE_NODE,
+  MOZ_ASSERT(mNodeInfo->NodeType() == 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(Attr)
 
@@ -139,18 +139,17 @@ Attr::SetOwnerDocument(nsIDocument* aDoc
 
   nsIDocument *doc = OwnerDoc();
   NS_ASSERTION(doc != aDocument, "bad call to Attr::SetOwnerDocument");
   doc->DeleteAllPropertiesFor(this);
 
   RefPtr<mozilla::dom::NodeInfo> newNodeInfo;
   newNodeInfo = aDocument->NodeInfoManager()->
     GetNodeInfo(mNodeInfo->NameAtom(), mNodeInfo->GetPrefixAtom(),
-                mNodeInfo->NamespaceID(),
-                nsIDOMNode::ATTRIBUTE_NODE);
+                mNodeInfo->NamespaceID(), ATTRIBUTE_NODE);
   NS_ASSERTION(newNodeInfo, "GetNodeInfo lies");
   mNodeInfo.swap(newNodeInfo);
 
   return NS_OK;
 }
 
 void
 Attr::GetName(nsAString& aName)
--- a/dom/base/Attr.h
+++ b/dom/base/Attr.h
@@ -36,18 +36,17 @@ class Attr final : public nsIAttribute,
 
 public:
   Attr(nsDOMAttributeMap* aAttrMap,
        already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
        const nsAString& aValue);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
-  // nsIDOMNode interface
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
+  // nsINode interface
   virtual void GetTextContentInternal(nsAString& aTextContent,
                                       OOMReporter& aError) override;
   virtual void SetTextContentInternal(const nsAString& aTextContent,
                                       nsIPrincipal* aSubjectPrincipal,
                                       ErrorResult& aError) override;
   virtual void GetNodeValueInternal(nsAString& aNodeValue) override;
   virtual void SetNodeValueInternal(const nsAString& aNodeValue,
                                     ErrorResult& aError) override;
--- a/dom/base/Comment.h
+++ b/dom/base/Comment.h
@@ -15,17 +15,17 @@ namespace mozilla {
 namespace dom {
 
 class Comment final : public nsGenericDOMDataNode,
                       public nsIDOMComment
 {
 private:
   void Init()
   {
-    MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE,
+    MOZ_ASSERT(mNodeInfo->NodeType() == COMMENT_NODE,
                "Bad NodeType in aNodeInfo");
   }
 
   virtual ~Comment();
 
 public:
   explicit Comment(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     : nsGenericDOMDataNode(aNodeInfo)
@@ -37,19 +37,16 @@ public:
     : nsGenericDOMDataNode(aNodeInfoManager->GetCommentNodeInfo())
   {
     Init();
   }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-
   // nsIDOMCharacterData
   NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
   using nsGenericDOMDataNode::SetData; // Prevent hiding overloaded virtual function.
 
   // nsIDOMComment
   // Empty interface
 
   // nsINode
--- a/dom/base/DirectionalityUtils.cpp
+++ b/dom/base/DirectionalityUtils.cpp
@@ -207,17 +207,16 @@
 #include "mozilla/dom/DirectionalityUtils.h"
 
 #include "nsINode.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/dom/Element.h"
-#include "nsIDOMHTMLDocument.h"
 #include "nsUnicodeProperties.h"
 #include "nsTextFragment.h"
 #include "nsAttrValue.h"
 #include "nsTextNode.h"
 #include "nsCheapSets.h"
 
 namespace mozilla {
 
@@ -384,17 +383,17 @@ WalkDescendantsSetDirectionFromText(Elem
   nsIContent* child = aElement->GetFirstChild();
   while (child) {
     if (child->IsElement() &&
         DoesNotAffectDirectionOfAncestors(child->AsElement())) {
       child = child->GetNextNonChildNode(aElement);
       continue;
     }
 
-    if (child->NodeType() == nsIDOMNode::TEXT_NODE &&
+    if (child->NodeType() == nsINode::TEXT_NODE &&
         child != aChangedNode) {
       Directionality textNodeDir = GetDirectionFromText(child->GetText());
       if (textNodeDir != eDir_NotSet) {
         // We found a descendant text node with strong directional characters.
         // Set the directionality of aElement to the corresponding value.
         aElement->SetDirectionality(textNodeDir, aNotify);
         return static_cast<nsTextNode*>(child);
       }
@@ -485,17 +484,17 @@ public:
 
 private:
   nsCheapSet<nsPtrHashKey<Element>> mElements;
   // Only used for comparison.
   Element* mElementToBeRemoved;
 
   static nsTextNodeDirectionalityMap* GetDirectionalityMap(nsINode* aTextNode)
   {
-    MOZ_ASSERT(aTextNode->NodeType() == nsIDOMNode::TEXT_NODE,
+    MOZ_ASSERT(aTextNode->NodeType() == nsINode::TEXT_NODE,
                "Must be a text node");
     nsTextNodeDirectionalityMap* map = nullptr;
 
     if (aTextNode->HasTextNodeDirectionalityMap()) {
       map = static_cast<nsTextNodeDirectionalityMap * >
         (aTextNode->GetProperty(nsGkAtoms::textNodeDirectionalityMap));
     }
 
@@ -711,17 +710,17 @@ WalkDescendantsResetAutoDirection(Elemen
 {
   nsIContent* child = aElement->GetFirstChild();
   while (child) {
     if (child->IsElement() && child->AsElement()->HasDirAuto()) {
       child = child->GetNextNonChildNode(aElement);
       continue;
     }
 
-    if (child->NodeType() == nsIDOMNode::TEXT_NODE &&
+    if (child->NodeType() == nsINode::TEXT_NODE &&
         child->HasTextNodeDirectionalityMap()) {
       nsTextNodeDirectionalityMap::ResetTextNodeDirection(static_cast<nsTextNode*>(child), nullptr);
       // Don't call nsTextNodeDirectionalityMap::EnsureMapIsClearFor(child)
       // since ResetTextNodeDirection may have kept elements in child's
       // DirectionalityMap.
     }
     child = child->GetNextNode(aElement);
   }
@@ -782,17 +781,17 @@ WalkDescendantsClearAncestorDirAuto(Elem
     child->ClearAncestorHasDirAuto();
     child = child->GetNextNode(aElement);
   }
 }
 
 void SetAncestorDirectionIfAuto(nsTextNode* aTextNode, Directionality aDir,
                                 bool aNotify = true)
 {
-  MOZ_ASSERT(aTextNode->NodeType() == nsIDOMNode::TEXT_NODE,
+  MOZ_ASSERT(aTextNode->NodeType() == nsINode::TEXT_NODE,
              "Must be a text node");
 
   Element* parent = aTextNode->GetParentElement();
   while (parent && parent->NodeOrAncestorHasDirAuto()) {
     if (DoesNotParticipateInAutoDirection(parent) || parent->HasFixedDir()) {
       break;
     }
 
--- a/dom/base/DocumentFragment.h
+++ b/dom/base/DocumentFragment.h
@@ -23,50 +23,47 @@ namespace dom {
 class Element;
 
 class DocumentFragment : public FragmentOrElement,
                          public nsIDOMDocumentFragment
 {
 private:
   void Init()
   {
-    MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
+    MOZ_ASSERT(mNodeInfo->NodeType() == DOCUMENT_FRAGMENT_NODE &&
                mNodeInfo->Equals(nsGkAtoms::documentFragmentNodeName,
                                  kNameSpaceID_None),
                "Bad NodeType in aNodeInfo");
   }
 
 public:
   using FragmentOrElement::GetFirstChild;
   using nsINode::QuerySelector;
   using nsINode::QuerySelectorAll;
   // Make sure bindings can see our superclass' protected GetElementById method.
   using nsINode::GetElementById;
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DocumentFragment, FragmentOrElement)
 
-  // interface nsIDOMNode
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-
   // interface nsIDOMDocumentFragment
   NS_DECL_NSIDOMDOCUMENTFRAGMENT
 
   explicit DocumentFragment(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : FragmentOrElement(aNodeInfo), mHost(nullptr)
   {
     Init();
   }
 
   explicit DocumentFragment(nsNodeInfoManager* aNodeInfoManager)
     : FragmentOrElement(aNodeInfoManager->GetNodeInfo(
                                             nsGkAtoms::documentFragmentNodeName,
                                             nullptr, kNameSpaceID_None,
-                                            nsIDOMNode::DOCUMENT_FRAGMENT_NODE)),
+                                            DOCUMENT_FRAGMENT_NODE)),
       mHost(nullptr)
   {
     Init();
   }
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
--- a/dom/base/DocumentType.cpp
+++ b/dom/base/DocumentType.cpp
@@ -44,18 +44,17 @@ NS_NewDOMDocumentType(nsNodeInfoManager*
   if (!aName) {
     rv.Throw(NS_ERROR_INVALID_POINTER);
     return nullptr;
   }
 
   already_AddRefed<mozilla::dom::NodeInfo> ni =
     aNodeInfoManager->GetNodeInfo(nsGkAtoms::documentTypeNodeName, nullptr,
                                   kNameSpaceID_None,
-                                  nsIDOMNode::DOCUMENT_TYPE_NODE,
-                                  aName);
+                                  nsINode::DOCUMENT_TYPE_NODE, aName);
 
   RefPtr<mozilla::dom::DocumentType> docType =
     new mozilla::dom::DocumentType(ni, aPublicId, aSystemId, aInternalSubset);
   return docType.forget();
 }
 
 namespace mozilla {
 namespace dom {
@@ -70,17 +69,17 @@ DocumentType::DocumentType(already_AddRe
                            const nsAString& aPublicId,
                            const nsAString& aSystemId,
                            const nsAString& aInternalSubset) :
   DocumentTypeForward(aNodeInfo),
   mPublicId(aPublicId),
   mSystemId(aSystemId),
   mInternalSubset(aInternalSubset)
 {
-  MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
+  MOZ_ASSERT(mNodeInfo->NodeType() == DOCUMENT_TYPE_NODE,
              "Bad NodeType in aNodeInfo");
 }
 
 DocumentType::~DocumentType()
 {
 }
 
 NS_IMPL_ISUPPORTS_INHERITED(DocumentType, nsGenericDOMDataNode, nsIDOMNode,
--- a/dom/base/DocumentType.h
+++ b/dom/base/DocumentType.h
@@ -29,19 +29,16 @@ namespace dom {
 class DocumentTypeForward : public nsGenericDOMDataNode,
                             public nsIDOMDocumentType
 {
 public:
   explicit DocumentTypeForward(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsGenericDOMDataNode(aNodeInfo)
   {
   }
-
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
 };
 
 class DocumentType final : public DocumentTypeForward
 {
 public:
   DocumentType(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
                const nsAString& aPublicId,
                const nsAString& aSystemId,
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1247,17 +1247,17 @@ Element::AttachShadowInternal(bool aClos
     return nullptr;
   }
 
   nsAutoScriptBlocker scriptBlocker;
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfo->NodeInfoManager()->GetNodeInfo(
     nsGkAtoms::documentFragmentNodeName, nullptr, kNameSpaceID_None,
-    nsIDOMNode::DOCUMENT_FRAGMENT_NODE);
+    DOCUMENT_FRAGMENT_NODE);
 
   RefPtr<nsXBLDocumentInfo> docInfo = new nsXBLDocumentInfo(OwnerDoc());
 
   nsXBLPrototypeBinding* protoBinding = new nsXBLPrototypeBinding();
   aError = protoBinding->Init(NS_LITERAL_CSTRING("shadowroot"),
                               docInfo, nullptr, true);
   if (aError.Failed()) {
     delete protoBinding;
@@ -1428,17 +1428,17 @@ Element::SetAttributeNS(const nsAString&
                         const nsAString& aValue,
                         nsIPrincipal* aTriggeringPrincipal,
                         ErrorResult& aError)
 {
   RefPtr<mozilla::dom::NodeInfo> ni;
   aError =
     nsContentUtils::GetNodeInfoFromQName(aNamespaceURI, aQualifiedName,
                                          mNodeInfo->NodeInfoManager(),
-                                         nsIDOMNode::ATTRIBUTE_NODE,
+                                         ATTRIBUTE_NODE,
                                          getter_AddRefs(ni));
   if (aError.Failed()) {
     return;
   }
 
   aError = SetAttr(ni->NamespaceID(), ni->NameAtom(), ni->GetPrefixAtom(),
                    aValue, aTriggeringPrincipal, true);
 }
@@ -2240,18 +2240,17 @@ Element::GetExistingAttrNameFromQName(co
   const nsAttrName* name = InternalGetAttrNameFromQName(aStr);
   if (!name) {
     return nullptr;
   }
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   if (name->IsAtom()) {
     nodeInfo = mNodeInfo->NodeInfoManager()->
-      GetNodeInfo(name->Atom(), nullptr, kNameSpaceID_None,
-                  nsIDOMNode::ATTRIBUTE_NODE);
+      GetNodeInfo(name->Atom(), nullptr, kNameSpaceID_None, ATTRIBUTE_NODE);
   }
   else {
     nodeInfo = name->NodeInfo();
   }
 
   return nodeInfo.forget();
 }
 
@@ -2704,17 +2703,17 @@ Element::SetAttrAndNotify(int32_t aNames
         !SetAndSwapMappedAttribute(aName, aParsedValue, &oldValueSet, &rv)) {
       rv = mAttrsAndChildren.SetAndSwapAttr(aName, aParsedValue, &oldValueSet);
     }
   }
   else {
     RefPtr<mozilla::dom::NodeInfo> ni;
     ni = mNodeInfo->NodeInfoManager()->GetNodeInfo(aName, aPrefix,
                                                    aNamespaceID,
-                                                   nsIDOMNode::ATTRIBUTE_NODE);
+                                                   ATTRIBUTE_NODE);
 
     rv = mAttrsAndChildren.SetAndSwapAttr(ni, aParsedValue, &oldValueSet);
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   PostIdMaybeChange(aNamespaceID, aName, &valueForAfterSetAttr);
 
   // If the old value owns its own data, we know it is OK to keep using it.
@@ -3942,29 +3941,29 @@ Element::GetOuterHTML(nsAString& aOuterH
 void
 Element::SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError)
 {
   nsCOMPtr<nsINode> parent = GetParentNode();
   if (!parent) {
     return;
   }
 
-  if (parent->NodeType() == nsIDOMNode::DOCUMENT_NODE) {
+  if (parent->NodeType() == DOCUMENT_NODE) {
     aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     return;
   }
 
   if (OwnerDoc()->IsHTMLDocument()) {
     nsAtom* localName;
     int32_t namespaceID;
     if (parent->IsElement()) {
       localName = parent->NodeInfo()->NameAtom();
       namespaceID = parent->NodeInfo()->NamespaceID();
     } else {
-      NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE,
+      NS_ASSERTION(parent->NodeType() == DOCUMENT_FRAGMENT_NODE,
         "How come the parent isn't a document, a fragment or an element?");
       localName = nsGkAtoms::body;
       namespaceID = kNameSpaceID_XHTML;
     }
     RefPtr<DocumentFragment> fragment =
       new DocumentFragment(OwnerDoc()->NodeInfoManager());
     nsContentUtils::ParseFragmentHTML(aOuterHTML,
                                       fragment,
@@ -3976,23 +3975,23 @@ Element::SetOuterHTML(const nsAString& a
     parent->ReplaceChild(*fragment, *this, aError);
     return;
   }
 
   nsCOMPtr<nsINode> context;
   if (parent->IsElement()) {
     context = parent;
   } else {
-    NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE,
+    NS_ASSERTION(parent->NodeType() == DOCUMENT_FRAGMENT_NODE,
       "How come the parent isn't a document, a fragment or an element?");
     RefPtr<mozilla::dom::NodeInfo> info =
       OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::body,
                                                  nullptr,
                                                  kNameSpaceID_XHTML,
-                                                 nsIDOMNode::ELEMENT_NODE);
+                                                 ELEMENT_NODE);
     context = NS_NewHTMLBodyElement(info.forget(), FROM_PARSER_FRAGMENT);
   }
 
   nsCOMPtr<nsIDOMDocumentFragment> df;
   aError = nsContentUtils::CreateContextualFragment(context,
                                                     aOuterHTML,
                                                     true,
                                                     getter_AddRefs(df));
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -199,17 +199,17 @@ class Grid;
 class Element : public FragmentOrElement
 {
 public:
 #ifdef MOZILLA_INTERNAL_API
   explicit Element(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) :
     FragmentOrElement(aNodeInfo),
     mState(NS_EVENT_STATE_MOZ_READONLY)
   {
-    MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE,
+    MOZ_ASSERT(mNodeInfo->NodeType() == ELEMENT_NODE,
                "Bad NodeType in aNodeInfo");
     SetIsElement();
   }
 
   ~Element()
   {
     NS_ASSERTION(!HasServoData(), "expected ServoData to be cleared earlier");
   }
@@ -1111,17 +1111,17 @@ public:
       slots->mAttributeMap = new nsDOMAttributeMap(this);
     }
 
     return slots->mAttributeMap;
   }
 
   void GetAttributeNames(nsTArray<nsString>& aResult);
 
-  void GetAttribute(const nsAString& aName, nsString& aReturn)
+  void GetAttribute(const nsAString& aName, nsAString& aReturn)
   {
     DOMString str;
     GetAttribute(aName, str);
     str.ToString(aReturn);
   }
 
   void GetAttribute(const nsAString& aName, DOMString& aReturn);
   void GetAttributeNS(const nsAString& aNamespaceURI,
@@ -2189,39 +2189,9 @@ nsresult                                
     return NS_OK;                                                     \
   }                                                                   \
   NS_IMETHODIMP                                                       \
   _class::Set##_method(bool aValue)                                   \
   {                                                                   \
     return SetBoolAttr(nsGkAtoms::_atom, aValue);                     \
   }
 
-#define NS_FORWARD_NSIDOMELEMENT_TO_GENERIC                                   \
-typedef mozilla::dom::Element Element;                                        \
-NS_IMETHOD GetTagName(nsAString& aTagName) final override                     \
-{                                                                             \
-  Element::GetTagName(aTagName);                                              \
-  return NS_OK;                                                               \
-}                                                                             \
-using Element::GetAttribute;                                                  \
-NS_IMETHOD GetAttribute(const nsAString& name, nsAString& _retval) final      \
-  override                                                                    \
-{                                                                             \
-  nsString attr;                                                              \
-  GetAttribute(name, attr);                                                   \
-  _retval = attr;                                                             \
-  return NS_OK;                                                               \
-}                                                                             \
-NS_IMETHOD SetAttribute(const nsAString& name,                                \
-                        const nsAString& value) override                      \
-{                                                                             \
-  mozilla::ErrorResult rv;                                                    \
-  Element::SetAttribute(name, value, nullptr, rv);                            \
-  return rv.StealNSResult();                                                  \
-}                                                                             \
-using Element::HasAttribute;                                                  \
-NS_IMETHOD HasAttribute(const nsAString& name,                                \
-                           bool* _retval) final override                      \
-{                                                                             \
-  *_retval = HasAttribute(name);                                              \
-  return NS_OK;                                                               \
-}
 #endif // mozilla_dom_Element_h__
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -1291,18 +1291,18 @@ public:
 
   ~ContentUnbinder()
   {
     Run();
   }
 
   void UnbindSubtree(nsIContent* aNode)
   {
-    if (aNode->NodeType() != nsIDOMNode::ELEMENT_NODE &&
-        aNode->NodeType() != nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+    if (aNode->NodeType() != nsINode::ELEMENT_NODE &&
+        aNode->NodeType() != nsINode::DOCUMENT_FRAGMENT_NODE) {
       return;
     }
     FragmentOrElement* container = static_cast<FragmentOrElement*>(aNode);
     uint32_t childCount = container->mAttrsAndChildren.ChildCount();
     if (childCount) {
       // Invalidate cached array of child nodes
       container->InvalidateChildNodes();
 
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -57,17 +57,16 @@
 #include "nsMimeTypes.h"
 #include "nsNetUtil.h"
 #include "nsRFPService.h"
 #include "nsStringStream.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIStringStream.h"
 #include "nsIHttpChannel.h"
 #include "nsIHttpChannelInternal.h"
-#include "TimeManager.h"
 #include "nsStreamUtils.h"
 #include "WidgetUtils.h"
 #include "nsIPresentationService.h"
 #include "nsIScriptError.h"
 
 #include "mozilla/dom/MediaDevices.h"
 #include "MediaManager.h"
 
@@ -193,17 +192,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCredentials)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaDevices)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTimeManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresentation)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRServiceTest)
@@ -243,20 +241,16 @@ Navigator::Invalidate()
 
   if (mConnection) {
     mConnection->Shutdown();
     mConnection = nullptr;
   }
 
   mMediaDevices = nullptr;
 
-  if (mTimeManager) {
-    mTimeManager = nullptr;
-  }
-
   if (mPresentation) {
     mPresentation = nullptr;
   }
 
   mServiceWorkerContainer = nullptr;
 
   if (mMediaKeySystemAccessManager) {
     mMediaKeySystemAccessManager->Shutdown();
@@ -1497,33 +1491,16 @@ Navigator::GetConnection(ErrorResult& aR
       return nullptr;
     }
     mConnection = network::Connection::CreateForWindow(mWindow);
   }
 
   return mConnection;
 }
 
-#ifdef MOZ_TIME_MANAGER
-time::TimeManager*
-Navigator::GetMozTime(ErrorResult& aRv)
-{
-  if (!mWindow) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  if (!mTimeManager) {
-    mTimeManager = new time::TimeManager(mWindow);
-  }
-
-  return mTimeManager;
-}
-#endif
-
 already_AddRefed<ServiceWorkerContainer>
 Navigator::ServiceWorker()
 {
   MOZ_ASSERT(mWindow);
 
   if (!mServiceWorkerContainer) {
     mServiceWorkerContainer = new ServiceWorkerContainer(mWindow);
   }
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -70,20 +70,16 @@ class Connection;
 } // namespace network
 
 class Presentation;
 class LegacyMozTCPSocket;
 class VRDisplay;
 class VRServiceTest;
 class StorageManager;
 
-namespace time {
-class TimeManager;
-} // namespace time
-
 class Navigator final : public nsISupports
                       , public nsWrapperCache
 {
 public:
   explicit Navigator(nsPIDOMWindowInner* aInnerWindow);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Navigator)
@@ -177,19 +173,16 @@ public:
   GamepadServiceTest* RequestGamepadServiceTest();
   already_AddRefed<Promise> GetVRDisplays(ErrorResult& aRv);
   void GetActiveVRDisplays(nsTArray<RefPtr<VRDisplay>>& aDisplays) const;
   VRServiceTest* RequestVRServiceTest();
   bool IsWebVRContentDetected() const;
   bool IsWebVRContentPresenting() const;
   void RequestVRPresentation(VRDisplay& aDisplay);
   nsINetworkProperties* GetNetworkProperties();
-#ifdef MOZ_TIME_MANAGER
-  time::TimeManager* GetMozTime(ErrorResult& aRv);
-#endif // MOZ_TIME_MANAGER
 
   Presentation* GetPresentation(ErrorResult& aRv);
 
   bool SendBeacon(const nsAString& aUrl,
                   const Nullable<fetch::BodyInit>& aData,
                   ErrorResult& aRv);
 
   void MozGetUserMedia(const MediaStreamConstraints& aConstraints,
@@ -266,17 +259,16 @@ private:
   RefPtr<nsPluginArray> mPlugins;
   RefPtr<Permissions> mPermissions;
   RefPtr<Geolocation> mGeolocation;
   RefPtr<battery::BatteryManager> mBatteryManager;
   RefPtr<Promise> mBatteryPromise;
   RefPtr<network::Connection> mConnection;
   RefPtr<CredentialsContainer> mCredentials;
   RefPtr<MediaDevices> mMediaDevices;
-  RefPtr<time::TimeManager> mTimeManager;
   RefPtr<ServiceWorkerContainer> mServiceWorkerContainer;
   nsCOMPtr<nsPIDOMWindowInner> mWindow;
   RefPtr<Presentation> mPresentation;
   RefPtr<GamepadServiceTest> mGamepadServiceTest;
   nsTArray<RefPtr<Promise> > mVRGetDisplaysPromises;
   RefPtr<VRServiceTest> mVRServiceTest;
   nsTArray<uint32_t> mRequestedVibrationPattern;
   RefPtr<StorageManager> mStorageManager;
--- a/dom/base/NodeInfo.cpp
+++ b/dom/base/NodeInfo.cpp
@@ -17,16 +17,17 @@
 #include "mozilla/Likely.h"
 
 #include "nsNodeInfoManager.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsAtom.h"
 #include "nsDOMString.h"
 #include "nsCRT.h"
+#include "nsINode.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "mozilla/Sprintf.h"
 #include "nsIDocument.h"
 #include "nsGkAtoms.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsNameSpaceManager.h"
 
@@ -65,44 +66,44 @@ NodeInfo::NodeInfo(nsAtom *aName, nsAtom
   if (aPrefix) {
     mQualifiedName = nsDependentAtomString(mInner.mPrefix) +
                      NS_LITERAL_STRING(":") +
                      nsDependentAtomString(mInner.mName);
   } else {
     mInner.mName->ToString(mQualifiedName);
   }
 
-  MOZ_ASSERT_IF(aNodeType != nsIDOMNode::ELEMENT_NODE &&
-                aNodeType != nsIDOMNode::ATTRIBUTE_NODE &&
+  MOZ_ASSERT_IF(aNodeType != nsINode::ELEMENT_NODE &&
+                aNodeType != nsINode::ATTRIBUTE_NODE &&
                 aNodeType != UINT16_MAX,
                 aNamespaceID == kNameSpaceID_None && !aPrefix);
 
   switch (aNodeType) {
-    case nsIDOMNode::ELEMENT_NODE:
-    case nsIDOMNode::ATTRIBUTE_NODE:
+    case nsINode::ELEMENT_NODE:
+    case nsINode::ATTRIBUTE_NODE:
       // Correct the case for HTML
-      if (aNodeType == nsIDOMNode::ELEMENT_NODE &&
+      if (aNodeType == nsINode::ELEMENT_NODE &&
           aNamespaceID == kNameSpaceID_XHTML && GetDocument() &&
           GetDocument()->IsHTMLDocument()) {
         nsContentUtils::ASCIIToUpper(mQualifiedName, mNodeName);
       } else {
         mNodeName = mQualifiedName;
       }
       mInner.mName->ToString(mLocalName);
       break;
-    case nsIDOMNode::TEXT_NODE:
-    case nsIDOMNode::CDATA_SECTION_NODE:
-    case nsIDOMNode::COMMENT_NODE:
-    case nsIDOMNode::DOCUMENT_NODE:
-    case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
+    case nsINode::TEXT_NODE:
+    case nsINode::CDATA_SECTION_NODE:
+    case nsINode::COMMENT_NODE:
+    case nsINode::DOCUMENT_NODE:
+    case nsINode::DOCUMENT_FRAGMENT_NODE:
       mInner.mName->ToString(mNodeName);
       SetDOMStringToNull(mLocalName);
       break;
-    case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
-    case nsIDOMNode::DOCUMENT_TYPE_NODE:
+    case nsINode::PROCESSING_INSTRUCTION_NODE:
+    case nsINode::DOCUMENT_TYPE_NODE:
       mInner.mExtraName->ToString(mNodeName);
       SetDOMStringToNull(mLocalName);
       break;
     default:
       MOZ_ASSERT(aNodeType == UINT16_MAX, "Unknown node type");
   }
 }
 
--- a/dom/base/NodeInfoInlines.h
+++ b/dom/base/NodeInfoInlines.h
@@ -3,17 +3,17 @@
 /* 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_NodeInfoInlines_h___
 #define mozilla_dom_NodeInfoInlines_h___
 
 #include "nsAtom.h"
-#include "nsIDOMNode.h"
+#include "nsINode.h"
 #include "nsDOMString.h"
 #include "nsGkAtoms.h"
 
 namespace mozilla {
 namespace dom {
 
 inline bool
 NodeInfo::Equals(NodeInfo *aNodeInfo) const
@@ -70,47 +70,47 @@ NodeInfo::QualifiedNameEquals(nsAtom* aN
 
 } // namespace dom
 } // namespace mozilla
 
 inline void
 CheckValidNodeInfo(uint16_t aNodeType, nsAtom *aName, int32_t aNamespaceID,
                    nsAtom* aExtraName)
 {
-  MOZ_ASSERT(aNodeType == nsIDOMNode::ELEMENT_NODE ||
-             aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
-             aNodeType == nsIDOMNode::TEXT_NODE ||
-             aNodeType == nsIDOMNode::CDATA_SECTION_NODE ||
-             aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
-             aNodeType == nsIDOMNode::COMMENT_NODE ||
-             aNodeType == nsIDOMNode::DOCUMENT_NODE ||
-             aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||
-             aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE ||
+  MOZ_ASSERT(aNodeType == nsINode::ELEMENT_NODE ||
+             aNodeType == nsINode::ATTRIBUTE_NODE ||
+             aNodeType == nsINode::TEXT_NODE ||
+             aNodeType == nsINode::CDATA_SECTION_NODE ||
+             aNodeType == nsINode::PROCESSING_INSTRUCTION_NODE ||
+             aNodeType == nsINode::COMMENT_NODE ||
+             aNodeType == nsINode::DOCUMENT_NODE ||
+             aNodeType == nsINode::DOCUMENT_TYPE_NODE ||
+             aNodeType == nsINode::DOCUMENT_FRAGMENT_NODE ||
              aNodeType == UINT16_MAX,
              "Invalid nodeType");
-  MOZ_ASSERT((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
-              aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
+  MOZ_ASSERT((aNodeType == nsINode::PROCESSING_INSTRUCTION_NODE ||
+              aNodeType == nsINode::DOCUMENT_TYPE_NODE) ==
              !!aExtraName,
              "Supply aExtraName for and only for PIs and doctypes");
-  MOZ_ASSERT(aNodeType == nsIDOMNode::ELEMENT_NODE ||
-             aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
+  MOZ_ASSERT(aNodeType == nsINode::ELEMENT_NODE ||
+             aNodeType == nsINode::ATTRIBUTE_NODE ||
              aNodeType == UINT16_MAX ||
              aNamespaceID == kNameSpaceID_None,
              "Only attributes and elements can be in a namespace");
   MOZ_ASSERT(aName && aName != nsGkAtoms::_empty, "Invalid localName");
-  MOZ_ASSERT(((aNodeType == nsIDOMNode::TEXT_NODE) ==
+  MOZ_ASSERT(((aNodeType == nsINode::TEXT_NODE) ==
               (aName == nsGkAtoms::textTagName)) &&
-             ((aNodeType == nsIDOMNode::CDATA_SECTION_NODE) ==
+             ((aNodeType == nsINode::CDATA_SECTION_NODE) ==
               (aName == nsGkAtoms::cdataTagName)) &&
-             ((aNodeType == nsIDOMNode::COMMENT_NODE) ==
+             ((aNodeType == nsINode::COMMENT_NODE) ==
               (aName == nsGkAtoms::commentTagName)) &&
-             ((aNodeType == nsIDOMNode::DOCUMENT_NODE) ==
+             ((aNodeType == nsINode::DOCUMENT_NODE) ==
               (aName == nsGkAtoms::documentNodeName)) &&
-             ((aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) ==
+             ((aNodeType == nsINode::DOCUMENT_FRAGMENT_NODE) ==
               (aName == nsGkAtoms::documentFragmentNodeName)) &&
-             ((aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
+             ((aNodeType == nsINode::DOCUMENT_TYPE_NODE) ==
               (aName == nsGkAtoms::documentTypeNodeName)) &&
-             ((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==
+             ((aNodeType == nsINode::PROCESSING_INSTRUCTION_NODE) ==
               (aName == nsGkAtoms::processingInstructionTagName)),
              "Wrong localName for nodeType");
 }
 
 #endif /* mozilla_dom_NodeInfoInlines_h___ */
--- a/dom/base/Selection.cpp
+++ b/dom/base/Selection.cpp
@@ -2525,17 +2525,17 @@ Selection::Collapse(const RawRangeBounda
     return;
   }
 
   if (!aPoint.IsSet()) {
     aRv.Throw(NS_ERROR_INVALID_ARG);
     return;
   }
 
-  if (aPoint.Container()->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) {
+  if (aPoint.Container()->NodeType() == nsINode::DOCUMENT_TYPE_NODE) {
     aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
     return;
   }
 
   // RawRangeBoundary::IsSetAndValid() checks if the point actually refers
   // a child of the container when IsSet() is true.  If its offset hasn't been
   // computed yet, this just checks it with its mRef.  So, we can avoid
   // computing offset here.
@@ -3225,17 +3225,17 @@ Selection::SelectAllChildrenJS(nsINode& 
   AutoRestore<bool> calledFromJSRestorer(mCalledByJS);
   mCalledByJS = true;
   SelectAllChildren(aNode, aRv);
 }
 
 void
 Selection::SelectAllChildren(nsINode& aNode, ErrorResult& aRv)
 {
-  if (aNode.NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) {
+  if (aNode.NodeType() == nsINode::DOCUMENT_TYPE_NODE) {
     aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
     return;
   }
 
   if (!HasSameRoot(aNode)) {
     // Return with no error
     return;
   }
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -6,17 +6,16 @@
 
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/ShadowRootBinding.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "ChildIterator.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfoID.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsIStyleSheetLinkingElement.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLSlotElement.h"
 #include "nsXBLPrototypeBinding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -421,17 +421,16 @@ EXTRA_JS_MODULES += [
     'IndexedDBHelper.jsm',
 ]
 
 LOCAL_INCLUDES += [
     '../battery',
     '../events',
     '../media',
     '../network',
-    '../time',
     '/caps',
     '/docshell/base',
     '/dom/base',
     '/dom/file',
     '/dom/geolocation',
     '/dom/html',
     '/dom/ipc',
     '/dom/storage',
--- a/dom/base/nsContentAreaDragDrop.cpp
+++ b/dom/base/nsContentAreaDragDrop.cpp
@@ -537,19 +537,21 @@ DragDataProducer::Produce(DataTransfer* 
         image->GetCurrentURI(getter_AddRefs(imageURI));
         if (imageURI) {
           nsAutoCString spec;
           rv = imageURI->GetSpec(spec);
           NS_ENSURE_SUCCESS(rv, rv);
           CopyUTF8toUTF16(spec, mUrlString);
         }
 
-        nsCOMPtr<nsIDOMElement> imageElement(do_QueryInterface(image));
+        nsCOMPtr<Element> imageElement(do_QueryInterface(image));
         // XXXbz Shouldn't we use the "title" attr for title?  Using
         // "alt" seems very wrong....
+        // XXXbz Also, what if this is an nsIImageLoadingContent
+        // that's not an <html:img>?
         if (imageElement) {
           imageElement->GetAttribute(NS_LITERAL_STRING("alt"), mTitleString);
         }
 
         if (mTitleString.IsEmpty()) {
           mTitleString = mUrlString;
         }
 
@@ -848,38 +850,32 @@ DragDataProducer::GetDraggableSelectionD
 
       nsCOMPtr<nsIDOMNode> selectionEnd;
       inSelection->GetFocusNode(getter_AddRefs(selectionEnd));
 
       // look for a selection around a single node, like an image.
       // in this case, drag the image, rather than a serialization of the HTML
       // XXX generalize this to other draggable element types?
       if (selectionStart == selectionEnd) {
-        bool hasChildren;
-        selectionStart->HasChildNodes(&hasChildren);
-        if (hasChildren) {
+        nsCOMPtr<nsIContent> selStartContent = do_QueryInterface(selectionStart);
+        if (selStartContent && selStartContent->HasChildNodes()) {
           // see if just one node is selected
           int32_t anchorOffset, focusOffset;
           inSelection->GetAnchorOffset(&anchorOffset);
           inSelection->GetFocusOffset(&focusOffset);
           if (abs(anchorOffset - focusOffset) == 1) {
-            nsCOMPtr<nsIContent> selStartContent =
-              do_QueryInterface(selectionStart);
-
-            if (selStartContent) {
-              int32_t childOffset =
-                (anchorOffset < focusOffset) ? anchorOffset : focusOffset;
-              nsIContent *childContent =
-                selStartContent->GetChildAt_Deprecated(childOffset);
-              // if we find an image, we'll fall into the node-dragging code,
-              // rather the the selection-dragging code
-              if (nsContentUtils::IsDraggableImage(childContent)) {
-                NS_ADDREF(*outImageOrLinkNode = childContent);
-                return NS_OK;
-              }
+            int32_t childOffset =
+              (anchorOffset < focusOffset) ? anchorOffset : focusOffset;
+            nsIContent *childContent =
+              selStartContent->GetChildAt_Deprecated(childOffset);
+            // if we find an image, we'll fall into the node-dragging code,
+            // rather the the selection-dragging code
+            if (nsContentUtils::IsDraggableImage(childContent)) {
+              NS_ADDREF(*outImageOrLinkNode = childContent);
+              return NS_OK;
             }
           }
         }
       }
 
       // indicate that a link or text is selected
       *outDragSelectedText = true;
     }
--- a/dom/base/nsContentList.cpp
+++ b/dom/base/nsContentList.cpp
@@ -2,17 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 /*
  * nsBaseContentList is a basic list of content nodes; nsContentList
  * is a commonly used NodeList implementation (used for
- * getElementsByTagName, some properties on nsIDOMHTMLDocument, etc).
+ * getElementsByTagName, some properties on HTMLDocument/Document, etc).
  */
 
 #include "nsContentList.h"
 #include "nsIContent.h"
 #include "nsIDOMNode.h"
 #include "nsIDocument.h"
 #include "mozilla/dom/Element.h"
 #include "nsWrapperCacheInlines.h"
--- a/dom/base/nsContentList.h
+++ b/dom/base/nsContentList.h
@@ -2,17 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 /*
  * nsBaseContentList is a basic list of content nodes; nsContentList
  * is a commonly used NodeList implementation (used for
- * getElementsByTagName, some properties on nsIDOMHTMLDocument, etc).
+ * getElementsByTagName, some properties on HTMLDocument/Document, etc).
  */
 
 #ifndef nsContentList_h___
 #define nsContentList_h___
 
 #include "mozilla/Attributes.h"
 #include "nsContentListDeclarations.h"
 #include "nsISupports.h"
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -47,16 +47,17 @@
 #include "mozilla/dom/ElementInlines.h"
 #include "mozilla/dom/FileSystemSecurity.h"
 #include "mozilla/dom/FileBlobImpl.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/HTMLSlotElement.h"
 #include "mozilla/dom/HTMLTemplateElement.h"
 #include "mozilla/dom/IDTracker.h"
 #include "mozilla/dom/IPCBlobUtils.h"
+#include "mozilla/dom/NodeBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/dom/TouchEvent.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/XULCommandEvent.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/EventDispatcher.h"
@@ -127,17 +128,16 @@
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocument.h"
 #include "nsIDocumentEncoder.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentType.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMElement.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsIDragService.h"
 #include "nsIFormControl.h"
 #include "nsIForm.h"
@@ -2541,17 +2541,17 @@ nsContentUtils::ContentIsHostIncludingDe
   const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor)
 {
   NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
   NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
 
   do {
     if (aPossibleDescendant == aPossibleAncestor)
       return true;
-    if (aPossibleDescendant->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+    if (aPossibleDescendant->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) {
       aPossibleDescendant =
         static_cast<const DocumentFragment*>(aPossibleDescendant)->GetHost();
     } else {
       aPossibleDescendant = aPossibleDescendant->GetParentNode();
     }
   } while (aPossibleDescendant);
 
   return false;
@@ -2752,19 +2752,19 @@ nsContentUtils::GetCommonFlattenedTreeAn
   });
 }
 
 /* static */
 bool
 nsContentUtils::PositionIsBefore(nsINode* aNode1, nsINode* aNode2)
 {
   return (aNode2->CompareDocumentPosition(*aNode1) &
-    (nsIDOMNode::DOCUMENT_POSITION_PRECEDING |
-     nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED)) ==
-    nsIDOMNode::DOCUMENT_POSITION_PRECEDING;
+    (NodeBinding::DOCUMENT_POSITION_PRECEDING |
+     NodeBinding::DOCUMENT_POSITION_DISCONNECTED)) ==
+    NodeBinding::DOCUMENT_POSITION_PRECEDING;
 }
 
 /* static */
 int32_t
 nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
                               nsINode* aParent2, int32_t aOffset2,
                               bool* aDisconnected)
 {
@@ -3799,28 +3799,29 @@ nsContentUtils::GetStaticRequest(nsIDocu
   aRequest->GetStaticRequest(aLoadingDocument, getter_AddRefs(retval));
   return retval.forget();
 }
 
 // static
 bool
 nsContentUtils::ContentIsDraggable(nsIContent* aContent)
 {
-  nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aContent);
-  if (htmlElement) {
-    bool draggable = false;
-    htmlElement->GetDraggable(&draggable);
-    if (draggable)
+  MOZ_ASSERT(aContent);
+
+  if (auto htmlElement = nsGenericHTMLElement::FromContent(aContent)) {
+    if (htmlElement->Draggable()) {
       return true;
-
-    if (aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
-                                           nsGkAtoms::draggable,
-                                           nsGkAtoms::_false,
-                                           eIgnoreCase))
+    }
+
+    if (htmlElement->AttrValueIs(kNameSpaceID_None,
+                                 nsGkAtoms::draggable,
+                                 nsGkAtoms::_false,
+                                 eIgnoreCase)) {
       return false;
+    }
   }
 
   // special handling for content area image and link dragging
   return IsDraggableImage(aContent) || IsDraggableLink(aContent);
 }
 
 // static
 bool
@@ -9628,18 +9629,18 @@ StartElement(Element* aContent, StringBu
   // pre/textarea/listing is a textnode and starts with a \n.
   // But because browsers haven't traditionally had that behavior,
   // we're not changing our behavior either - yet.
   if (aContent->IsHTMLElement()) {
     if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
         localName == nsGkAtoms::listing) {
       nsIContent* fc = aContent->GetFirstChild();
       if (fc &&
-          (fc->NodeType() == nsIDOMNode::TEXT_NODE ||
-           fc->NodeType() == nsIDOMNode::CDATA_SECTION_NODE)) {
+          (fc->NodeType() == nsINode::TEXT_NODE ||
+           fc->NodeType() == nsINode::CDATA_SECTION_NODE)) {
         const nsTextFragment* text = fc->GetText();
         if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) {
           aBuilder.Append("\n");
         }
       }
     }
   }*/
 }
@@ -9692,80 +9693,80 @@ IsVoidTag(Element* aElement)
 
 bool
 nsContentUtils::SerializeNodeToMarkup(nsINode* aRoot,
                                       bool aDescendentsOnly,
                                       nsAString& aOut)
 {
   // If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true
   MOZ_ASSERT(aDescendentsOnly ||
-             aRoot->NodeType() != nsIDOMNode::DOCUMENT_NODE);
+             aRoot->NodeType() != nsINode::DOCUMENT_NODE);
 
   nsINode* current = aDescendentsOnly ?
     nsNodeUtils::GetFirstChildOfTemplateOrNode(aRoot) : aRoot;
 
   if (!current) {
     return true;
   }
 
   StringBuilder builder;
   nsIContent* next;
   while (true) {
     bool isVoid = false;
     switch (current->NodeType()) {
-      case nsIDOMNode::ELEMENT_NODE: {
+      case nsINode::ELEMENT_NODE: {
         Element* elem = current->AsElement();
         StartElement(elem, builder);
         isVoid = IsVoidTag(elem);
         if (!isVoid &&
             (next = nsNodeUtils::GetFirstChildOfTemplateOrNode(current))) {
           current = next;
           continue;
         }
         break;
       }
 
-      case nsIDOMNode::TEXT_NODE:
-      case nsIDOMNode::CDATA_SECTION_NODE: {
+      case nsINode::TEXT_NODE:
+      case nsINode::CDATA_SECTION_NODE: {
         const nsTextFragment* text = static_cast<nsIContent*>(current)->GetText();
         nsIContent* parent = current->GetParent();
         if (ShouldEscape(parent)) {
           AppendEncodedCharacters(text, builder);
         } else {
           builder.Append(text);
         }
         break;
       }
 
-      case nsIDOMNode::COMMENT_NODE: {
+      case nsINode::COMMENT_NODE: {
         builder.Append("<!--");
         builder.Append(static_cast<nsIContent*>(current)->GetText());
         builder.Append("-->");
         break;
       }
 
-      case nsIDOMNode::DOCUMENT_TYPE_NODE: {
+      case nsINode::DOCUMENT_TYPE_NODE: {
         builder.Append("<!DOCTYPE ");
         builder.Append(current->NodeName());
         builder.Append(">");
         break;
       }
 
-      case nsIDOMNode::PROCESSING_INSTRUCTION_NODE: {
+      case nsINode::PROCESSING_INSTRUCTION_NODE: {
         builder.Append("<?");
         builder.Append(current->NodeName());
         builder.Append(" ");
         builder.Append(static_cast<nsIContent*>(current)->GetText());
         builder.Append(">");
         break;
       }
     }
 
     while (true) {
-      if (!isVoid && current->NodeType() == nsIDOMNode::ELEMENT_NODE) {
+      if (!isVoid && current->NodeType() == nsINode::ELEMENT_NODE) {
         builder.Append("</");
         nsIContent* elem = static_cast<nsIContent*>(current);
         if (elem->IsHTMLElement() || elem->IsSVGElement() ||
             elem->IsMathMLElement()) {
           builder.Append(elem->NodeInfo()->NameAtom());
         } else {
           builder.Append(current->NodeName());
         }
@@ -9782,17 +9783,17 @@ nsContentUtils::SerializeNodeToMarkup(ns
         break;
       }
 
       current = current->GetParentNode();
 
       // Handle template element. If the parent is a template's content,
       // then adjust the parent to be the template element.
       if (current != aRoot &&
-          current->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+          current->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) {
         DocumentFragment* frag = static_cast<DocumentFragment*>(current);
         nsIContent* fragHost = frag->GetHost();
         if (fragHost && nsNodeUtils::IsTemplateElement(fragHost)) {
           current = fragHost;
         }
       }
 
       if (aDescendentsOnly && current == aRoot) {
@@ -9904,17 +9905,18 @@ nsContentUtils::GetPresentationURL(nsIDo
 
   nsCOMPtr<nsILoadContext> loadContext(do_QueryInterface(aDocShell));
   nsCOMPtr<nsIDOMElement> topFrameElement;
   loadContext->GetTopFrameElement(getter_AddRefs(topFrameElement));
   if (!topFrameElement) {
     return;
   }
 
-  topFrameElement->GetAttribute(NS_LITERAL_STRING("mozpresentation"), aPresentationUrl);
+  nsCOMPtr<Element> topFrameElt = do_QueryInterface(topFrameElement);
+  topFrameElt->GetAttribute(NS_LITERAL_STRING("mozpresentation"), aPresentationUrl);
 }
 
 /* static */ nsIDocShell*
 nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget)
 {
   nsCOMPtr<nsPIDOMWindowInner> innerWindow;
 
   if (nsCOMPtr<nsINode> node = do_QueryInterface(aTarget)) {
--- a/dom/base/nsDOMAttributeMap.cpp
+++ b/dom/base/nsDOMAttributeMap.cpp
@@ -239,17 +239,17 @@ nsDOMAttributeMap::SetNamedItemNS(Attr& 
     const nsAttrName* name = mContent->GetAttrNameAt(i);
     int32_t attrNS = name->NamespaceID();
     nsAtom* nameAtom = name->LocalName();
 
     // we're purposefully ignoring the prefix.
     if (aAttr.NodeInfo()->Equals(nameAtom, attrNS)) {
       oldNi = mContent->NodeInfo()->NodeInfoManager()->
         GetNodeInfo(nameAtom, name->GetPrefix(), aAttr.NodeInfo()->NamespaceID(),
-                    nsIDOMNode::ATTRIBUTE_NODE);
+                    nsINode::ATTRIBUTE_NODE);
       break;
     }
   }
 
   RefPtr<Attr> oldAttr;
 
   if (oldNi) {
     oldAttr = GetAttribute(oldNi);
@@ -326,17 +326,17 @@ nsDOMAttributeMap::IndexedGetter(uint32_
   const nsAttrName* name = mContent->GetAttrNameAt(aIndex);
   NS_ENSURE_TRUE(name, nullptr);
 
   aFound = true;
   // Don't use the nodeinfo even if one exists since it can have the wrong
   // owner document.
   RefPtr<mozilla::dom::NodeInfo> ni = mContent->NodeInfo()->NodeInfoManager()->
     GetNodeInfo(name->LocalName(), name->GetPrefix(), name->NamespaceID(),
-                nsIDOMNode::ATTRIBUTE_NODE);
+                nsINode::ATTRIBUTE_NODE);
   return GetAttribute(ni);
 }
 
 Attr*
 nsDOMAttributeMap::Item(uint32_t aIndex)
 {
   bool dummy;
   return IndexedGetter(aIndex, dummy);
@@ -389,17 +389,17 @@ nsDOMAttributeMap::GetAttrNodeInfo(const
     nsAtom* nameAtom = name->LocalName();
 
     // we're purposefully ignoring the prefix.
     if (nameSpaceID == attrNS &&
         nameAtom->Equals(aLocalName)) {
       RefPtr<mozilla::dom::NodeInfo> ni;
       ni = mContent->NodeInfo()->NodeInfoManager()->
         GetNodeInfo(nameAtom, name->GetPrefix(), nameSpaceID,
-                    nsIDOMNode::ATTRIBUTE_NODE);
+                    nsINode::ATTRIBUTE_NODE);
 
       return ni.forget();
     }
   }
 
   return nullptr;
 }
 
--- a/dom/base/nsDOMSerializer.cpp
+++ b/dom/base/nsDOMSerializer.cpp
@@ -46,24 +46,22 @@ SetUpEncoder(nsIDOMNode *aRoot, const ns
   *aEncoder = nullptr;
 
   nsresult rv;
   nsCOMPtr<nsIDocumentEncoder> encoder =
     do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "application/xhtml+xml", &rv);
   if (NS_FAILED(rv))
     return rv;
 
-  bool entireDocument = true;
-  nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(aRoot));
-  if (!domDoc) {
-    entireDocument = false;
-    rv = aRoot->GetOwnerDocument(getter_AddRefs(domDoc));
-    if (NS_FAILED(rv))
-      return rv;
-  }
+  nsCOMPtr<nsINode> root = do_QueryInterface(aRoot);
+  MOZ_ASSERT(root);
+
+  nsIDocument* doc = root->OwnerDoc();
+  bool entireDocument = (doc == root);
+  nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
 
   // This method will fail if no document
   rv = encoder->Init(domDoc, NS_LITERAL_STRING("application/xhtml+xml"),
                      nsIDocumentEncoder::OutputRaw |
                      nsIDocumentEncoder::OutputDontRewriteEncodingDeclaration);
 
   if (NS_FAILED(rv))
     return rv;
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -123,17 +123,16 @@
 #include "nsIFormControl.h"
 
 #include "nsBidiUtils.h"
 
 #include "nsContentCreatorFunctions.h"
 
 #include "nsIScriptContext.h"
 #include "nsBindingManager.h"
-#include "nsIDOMHTMLDocument.h"
 #include "nsHTMLDocument.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIRequest.h"
 #include "nsHostObjectProtocolHandler.h"
 
 #include "nsCharsetSource.h"
 #include "nsIParser.h"
 #include "nsIContentSink.h"
@@ -2163,17 +2162,17 @@ nsDocument::Init()
 
   mNodeInfoManager = new nsNodeInfoManager();
   nsresult rv = mNodeInfoManager->Init(this);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // mNodeInfo keeps NodeInfoManager alive!
   mNodeInfo = mNodeInfoManager->GetDocumentNodeInfo();
   NS_ENSURE_TRUE(mNodeInfo, NS_ERROR_OUT_OF_MEMORY);
-  MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+  MOZ_ASSERT(mNodeInfo->NodeType() == DOCUMENT_NODE,
              "Bad NodeType in aNodeInfo");
 
   NS_ASSERTION(OwnerDoc() == this, "Our nodeinfo is busted!");
 
   // If after creation the owner js global is not set for a document
   // we use the default compartment for this document, instead of creating
   // wrapper in some random compartment when the document is exposed to js
   // via some events.
@@ -5807,17 +5806,17 @@ nsIDocument::GetController() const
 // nsIDOMDocument interface
 //
 DocumentType*
 nsIDocument::GetDoctype() const
 {
   for (nsIContent* child = GetFirstChild();
        child;
        child = child->GetNextSibling()) {
-    if (child->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) {
+    if (child->NodeType() == DOCUMENT_TYPE_NODE) {
       return static_cast<DocumentType*>(child);
     }
   }
   return nullptr;
 }
 
 NS_IMETHODIMP
 nsDocument::GetDoctype(nsIDOMDocumentType** aDoctype)
@@ -5995,17 +5994,17 @@ nsDocument::CreateElementNS(const nsAStr
                             const nsAString& aQualifiedName,
                             const ElementCreationOptionsOrString& aOptions,
                             ErrorResult& rv)
 {
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   rv = nsContentUtils::GetNodeInfoFromQName(aNamespaceURI,
                                             aQualifiedName,
                                             mNodeInfoManager,
-                                            nsIDOMNode::ELEMENT_NODE,
+                                            ELEMENT_NODE,
                                             getter_AddRefs(nodeInfo));
   if (rv.Failed()) {
     return nullptr;
   }
 
   const nsString* is = nullptr;
   if (CustomElementRegistry::IsCustomElementEnabled() &&
       aOptions.IsElementCreationOptions()) {
@@ -6169,18 +6168,17 @@ nsIDocument::CreateAttribute(const nsASt
   if (IsHTMLDocument()) {
     nsContentUtils::ASCIIToLower(aName, name);
   } else {
     name = aName;
   }
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   res = mNodeInfoManager->GetNodeInfo(name, nullptr, kNameSpaceID_None,
-                                      nsIDOMNode::ATTRIBUTE_NODE,
-                                      getter_AddRefs(nodeInfo));
+                                      ATTRIBUTE_NODE, getter_AddRefs(nodeInfo));
   if (NS_FAILED(res)) {
     rv.Throw(res);
     return nullptr;
   }
 
   RefPtr<Attr> attribute = new Attr(nullptr, nodeInfo.forget(),
                                     EmptyString());
   return attribute.forget();
@@ -6190,17 +6188,17 @@ already_AddRefed<Attr>
 nsIDocument::CreateAttributeNS(const nsAString& aNamespaceURI,
                                const nsAString& aQualifiedName,
                                ErrorResult& rv)
 {
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   rv = nsContentUtils::GetNodeInfoFromQName(aNamespaceURI,
                                             aQualifiedName,
                                             mNodeInfoManager,
-                                            nsIDOMNode::ATTRIBUTE_NODE,
+                                            ATTRIBUTE_NODE,
                                             getter_AddRefs(nodeInfo));
   if (rv.Failed()) {
     return nullptr;
   }
 
   RefPtr<Attr> attribute = new Attr(nullptr, nodeInfo.forget(),
                                     EmptyString());
   return attribute.forget();
@@ -6450,28 +6448,28 @@ nsIDocument::GetCharacterSet(nsAString& 
 }
 
 already_AddRefed<nsINode>
 nsIDocument::ImportNode(nsINode& aNode, bool aDeep, ErrorResult& rv) const
 {
   nsINode* imported = &aNode;
 
   switch (imported->NodeType()) {
-    case nsIDOMNode::DOCUMENT_NODE:
+    case DOCUMENT_NODE:
     {
       break;
     }
-    case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
-    case nsIDOMNode::ATTRIBUTE_NODE:
-    case nsIDOMNode::ELEMENT_NODE:
-    case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
-    case nsIDOMNode::TEXT_NODE:
-    case nsIDOMNode::CDATA_SECTION_NODE:
-    case nsIDOMNode::COMMENT_NODE:
-    case nsIDOMNode::DOCUMENT_TYPE_NODE:
+    case DOCUMENT_FRAGMENT_NODE:
+    case ATTRIBUTE_NODE:
+    case ELEMENT_NODE:
+    case PROCESSING_INSTRUCTION_NODE:
+    case TEXT_NODE:
+    case CDATA_SECTION_NODE:
+    case COMMENT_NODE:
+    case DOCUMENT_TYPE_NODE:
     {
       return nsNodeUtils::Clone(imported, aDeep, mNodeInfoManager, nullptr, rv);
     }
     default:
     {
       NS_WARNING("Don't know how to clone this nodetype for importNode.");
     }
   }
@@ -6796,16 +6794,59 @@ nsIDocument::GetHtmlChildElement(nsAtom*
        child;
        child = child->GetNextSibling()) {
     if (child->IsHTMLElement(aTag))
       return child->AsElement();
   }
   return nullptr;
 }
 
+nsGenericHTMLElement*
+nsIDocument::GetBody()
+{
+  Element* html = GetHtmlElement();
+  if (!html) {
+    return nullptr;
+  }
+
+  for (nsIContent* child = html->GetFirstChild();
+       child;
+       child = child->GetNextSibling()) {
+    if (child->IsHTMLElement(nsGkAtoms::body) ||
+        child->IsHTMLElement(nsGkAtoms::frameset)) {
+      return static_cast<nsGenericHTMLElement*>(child);
+    }
+  }
+
+  return nullptr;
+}
+
+void
+nsIDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv)
+{
+  nsCOMPtr<Element> root = GetRootElement();
+
+  // The body element must be either a body tag or a frameset tag. And we must
+  // have a root element to be able to add kids to it.
+  if (!newBody ||
+      !newBody->IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset) ||
+      !root) {
+    rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
+    return;
+  }
+
+  // Use DOM methods so that we pass through the appropriate security checks.
+  nsCOMPtr<Element> currentBody = GetBody();
+  if (currentBody) {
+    root->ReplaceChild(*newBody, *currentBody, rv);
+  } else {
+    root->AppendChild(*newBody, rv);
+  }
+}
+
 Element*
 nsDocument::GetTitleElement()
 {
   // mMayHaveTitleElement will have been set to true if any HTML or SVG
   // <title> element has been bound to this document. So if it's false,
   // we know there is nothing to do here. This avoids us having to search
   // the whole DOM if someone calls document.title on a large document
   // without a title.
@@ -6896,35 +6937,34 @@ nsDocument::SetTitle(const nsAString& aT
   mozAutoDocUpdate updateBatch(this, UPDATE_CONTENT_MODEL, true);
 
   nsCOMPtr<Element> title = GetTitleElement();
   if (rootElement->IsSVGElement(nsGkAtoms::svg)) {
     if (!title) {
       RefPtr<mozilla::dom::NodeInfo> titleInfo =
         mNodeInfoManager->GetNodeInfo(nsGkAtoms::title, nullptr,
                                       kNameSpaceID_SVG,
-                                      nsIDOMNode::ELEMENT_NODE);
+                                      ELEMENT_NODE);
       NS_NewSVGElement(getter_AddRefs(title), titleInfo.forget(),
                        NOT_FROM_PARSER);
       if (!title) {
         return NS_OK;
       }
       rootElement->InsertChildBefore(title, rootElement->GetFirstChild(), true);
     }
   } else if (rootElement->IsHTMLElement()) {
     if (!title) {
       Element* head = GetHeadElement();
       if (!head) {
         return NS_OK;
       }
 
       RefPtr<mozilla::dom::NodeInfo> titleInfo;
       titleInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::title, nullptr,
-          kNameSpaceID_XHTML,
-          nsIDOMNode::ELEMENT_NODE);
+          kNameSpaceID_XHTML, ELEMENT_NODE);
       title = NS_NewHTMLTitleElement(titleInfo.forget());
       if (!title) {
         return NS_OK;
       }
 
       head->AppendChildTo(title, true);
     }
   } else {
@@ -7594,17 +7634,17 @@ nsIDocument::AdoptNode(nsINode& aAdopted
       nsContentUtils::MaybeFireNodeRemoved(adoptedNode, parent,
                                            adoptedNode->OwnerDoc());
     }
   }
 
   nsAutoScriptBlocker scriptBlocker;
 
   switch (adoptedNode->NodeType()) {
-    case nsIDOMNode::ATTRIBUTE_NODE:
+    case ATTRIBUTE_NODE:
     {
       // Remove from ownerElement.
       RefPtr<Attr> adoptedAttr = static_cast<Attr*>(adoptedNode);
 
       nsCOMPtr<Element> ownerElement = adoptedAttr->GetOwnerElement(rv);
       if (rv.Failed()) {
         return nullptr;
       }
@@ -7616,30 +7656,30 @@ nsIDocument::AdoptNode(nsINode& aAdopted
           return nullptr;
         }
 
         newAttr.swap(adoptedAttr);
       }
 
       break;
     }
-    case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
+    case DOCUMENT_FRAGMENT_NODE:
     {
       if (adoptedNode->IsShadowRoot()) {
         rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
         return nullptr;
       }
       MOZ_FALLTHROUGH;
     }
-    case nsIDOMNode::ELEMENT_NODE:
-    case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
-    case nsIDOMNode::TEXT_NODE:
-    case nsIDOMNode::CDATA_SECTION_NODE:
-    case nsIDOMNode::COMMENT_NODE:
-    case nsIDOMNode::DOCUMENT_TYPE_NODE:
+    case ELEMENT_NODE:
+    case PROCESSING_INSTRUCTION_NODE:
+    case TEXT_NODE:
+    case CDATA_SECTION_NODE:
+    case COMMENT_NODE:
+    case DOCUMENT_TYPE_NODE:
     {
       // Don't allow adopting a node's anonymous subtree out from under it.
       if (adoptedNode->AsContent()->IsRootOfAnonymousSubtree()) {
         rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
         return nullptr;
       }
 
       // We don't want to adopt an element into its own contentDocument or into
@@ -7671,17 +7711,17 @@ nsIDocument::AdoptNode(nsINode& aAdopted
         // TODO Fully tear down the binding.
         if (adoptedNode->IsElement()) {
           adoptedNode->AsElement()->SetXBLBinding(nullptr);
         }
       }
 
       break;
     }
-    case nsIDOMNode::DOCUMENT_NODE:
+    case DOCUMENT_NODE:
     {
       rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
       return nullptr;
     }
     default:
     {
       NS_WARNING("Don't know how to adopt this nodetype for adoptNode.");
 
@@ -8499,18 +8539,17 @@ nsDocument::CreateElem(const nsAString& 
   bool nsAware = aPrefix != nullptr || aNamespaceID != GetDefaultNamespaceID();
   NS_ASSERTION(NS_SUCCEEDED(nsContentUtils::CheckQName(qName, nsAware)),
                "Don't pass invalid prefixes to nsDocument::CreateElem, "
                "check caller.");
 #endif
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   mNodeInfoManager->GetNodeInfo(aName, aPrefix, aNamespaceID,
-                                nsIDOMNode::ELEMENT_NODE,
-                                getter_AddRefs(nodeInfo));
+                                ELEMENT_NODE, getter_AddRefs(nodeInfo));
   NS_ENSURE_TRUE(nodeInfo, nullptr);
 
   nsCOMPtr<Element> element;
   nsresult rv = NS_NewElement(getter_AddRefs(element), nodeInfo.forget(),
                               NOT_FROM_PARSER, aIs);
   return NS_SUCCEEDED(rv) ? element.forget() : nullptr;
 }
 
@@ -10111,22 +10150,25 @@ already_AddRefed<nsIDocument>
 nsIDocument::CreateStaticClone(nsIDocShell* aCloneContainer)
 {
   nsDocument* thisAsDoc = static_cast<nsDocument*>(this);
   mCreatingStaticClone = true;
 
   // Make document use different container during cloning.
   RefPtr<nsDocShell> originalShell = mDocumentContainer.get();
   SetContainer(static_cast<nsDocShell*>(aCloneContainer));
-  nsCOMPtr<nsIDOMNode> clonedNode;
-  nsresult rv = thisAsDoc->CloneNode(true, 1, getter_AddRefs(clonedNode));
+  ErrorResult rv;
+  nsCOMPtr<nsINode> clonedNode = thisAsDoc->CloneNode(true, rv);
   SetContainer(originalShell);
 
   RefPtr<nsDocument> clonedDoc;
-  if (NS_SUCCEEDED(rv)) {
+  if (rv.Failed()) {
+    // Don't return yet; we need to reset mCreatingStaticClone
+    rv.SuppressException();
+  } else {
     nsCOMPtr<nsIDocument> tmp = do_QueryInterface(clonedNode);
     if (tmp) {
       clonedDoc = static_cast<nsDocument*>(tmp.get());
       if (IsStaticDocument()) {
         clonedDoc->mOriginalDocument = mOriginalDocument;
       } else {
         clonedDoc->mOriginalDocument = this;
       }
@@ -12412,26 +12454,26 @@ static void
 AddSizeOfNodeTree(nsIContent* aNode, nsWindowSizes& aWindowSizes)
 {
   size_t nodeSize = 0;
   aNode->AddSizeOfIncludingThis(aWindowSizes, &nodeSize);
 
   // This is where we transfer the nodeSize obtained from
   // nsINode::AddSizeOfIncludingThis() to a value in nsWindowSizes.
   switch (aNode->NodeType()) {
-  case nsIDOMNode::ELEMENT_NODE:
+  case nsINode::ELEMENT_NODE:
     aWindowSizes.mDOMElementNodesSize += nodeSize;
     break;
-  case nsIDOMNode::TEXT_NODE:
+  case nsINode::TEXT_NODE:
     aWindowSizes.mDOMTextNodesSize += nodeSize;
     break;
-  case nsIDOMNode::CDATA_SECTION_NODE:
+  case nsINode::CDATA_SECTION_NODE:
     aWindowSizes.mDOMCDATANodesSize += nodeSize;
     break;
-  case nsIDOMNode::COMMENT_NODE:
+  case nsINode::COMMENT_NODE:
     aWindowSizes.mDOMCommentNodesSize += nodeSize;
     break;
   default:
     aWindowSizes.mDOMOtherSize += nodeSize;
     break;
   }
 
   if (EventListenerManager* elm = aNode->GetExistingListenerManager()) {
@@ -12981,17 +13023,17 @@ nsIDocument::SetStateObject(nsIStructure
   mStateObjectCached = nullptr;
 }
 
 already_AddRefed<Element>
 nsIDocument::CreateHTMLElement(nsAtom* aTag)
 {
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(aTag, nullptr, kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           ELEMENT_NODE);
   MOZ_ASSERT(nodeInfo, "GetNodeInfo should never fail");
 
   nsCOMPtr<Element> element;
   DebugOnly<nsresult> rv = NS_NewHTMLElement(getter_AddRefs(element),
                                              nodeInfo.forget(),
                                              mozilla::dom::NOT_FROM_PARSER);
 
   MOZ_ASSERT(NS_SUCCEEDED(rv), "NS_NewHTMLElement should never fail");
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -636,19 +636,16 @@ public:
   static bool IsShadowDOMEnabled(JSContext* aCx, JSObject* aObject);
   // Check whether shadow DOM is enabled for the document this node belongs to.
   static bool IsShadowDOMEnabled(const nsINode* aNode);
 private:
   void AddOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet);
   void SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages);
 
 public:
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE_OVERRIDABLE
-
   // nsIDOMDocument
   NS_DECL_NSIDOMDOCUMENT
 
   // nsIDOMDocumentXBL
   NS_DECL_NSIDOMDOCUMENTXBL
 
   using mozilla::dom::DocumentOrShadowRoot::GetElementById;
   using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagName;
--- a/dom/base/nsDocumentEncoder.cpp
+++ b/dom/base/nsDocumentEncoder.cpp
@@ -399,41 +399,41 @@ nsDocumentEncoder::SerializeNodeStart(ns
       aOriginalNode && aOriginalNode->IsElement() ?
         aOriginalNode->AsElement() : nullptr;
     mSerializer->AppendElementStart(node->AsElement(),
                                     originalElement, aStr);
     return NS_OK;
   }
 
   switch (node->NodeType()) {
-    case nsIDOMNode::TEXT_NODE:
+    case nsINode::TEXT_NODE:
     {
       mSerializer->AppendText(static_cast<nsIContent*>(node),
                               aStartOffset, aEndOffset, aStr);
       break;
     }
-    case nsIDOMNode::CDATA_SECTION_NODE:
+    case nsINode::CDATA_SECTION_NODE:
     {
       mSerializer->AppendCDATASection(static_cast<nsIContent*>(node),
                                       aStartOffset, aEndOffset, aStr);
       break;
     }
-    case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
+    case nsINode::PROCESSING_INSTRUCTION_NODE:
     {
       mSerializer->AppendProcessingInstruction(static_cast<nsIContent*>(node),
                                                aStartOffset, aEndOffset, aStr);
       break;
     }
-    case nsIDOMNode::COMMENT_NODE:
+    case nsINode::COMMENT_NODE:
     {
       mSerializer->AppendComment(static_cast<nsIContent*>(node),
                                  aStartOffset, aEndOffset, aStr);
       break;
     }
-    case nsIDOMNode::DOCUMENT_TYPE_NODE:
+    case nsINode::DOCUMENT_TYPE_NODE:
     {
       mSerializer->AppendDoctype(static_cast<nsIContent*>(node), aStr);
       break;
     }
   }
 
   return NS_OK;
 }
@@ -542,17 +542,17 @@ nsDocumentEncoder::SerializeToStringIter
       node = current->GetNextSibling();
       if (!node) {
         // Perhaps parent node has siblings.
         current = current->GetParentNode();
 
         // Handle template element. If the parent is a template's content,
         // then adjust the parent to be the template element.
         if (current && current != aNode &&
-            current->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+            current->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) {
           DocumentFragment* frag = static_cast<DocumentFragment*>(current);
           nsIContent* host = frag->GetHost();
           if (host && host->IsHTMLElement(nsGkAtoms::_template)) {
             current = host;
           }
         }
       }
     }
@@ -1179,16 +1179,17 @@ protected:
   nsresult PromoteRange(nsIDOMRange *inRange);
   nsresult PromoteAncestorChain(nsCOMPtr<nsIDOMNode> *ioNode,
                                 int32_t *ioStartOffset,
                                 int32_t *ioEndOffset);
   nsresult GetPromotedPoint(Endpoint aWhere, nsIDOMNode *aNode, int32_t aOffset,
                             nsCOMPtr<nsIDOMNode> *outNode, int32_t *outOffset, nsIDOMNode *aCommon);
   nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode *aParent, int32_t aOffset);
   bool IsMozBR(nsIDOMNode* aNode);
+  bool IsMozBR(Element* aNode);
   nsresult GetNodeLocation(nsIDOMNode *inChild, nsCOMPtr<nsIDOMNode> *outParent, int32_t *outOffset);
   bool IsRoot(nsIDOMNode* aNode);
   bool IsFirstNode(nsIDOMNode *aNode);
   bool IsLastNode(nsIDOMNode *aNode);
   bool IsEmptyTextContent(nsIDOMNode* aNode);
   virtual bool IncludeInContext(nsINode *aNode) override;
   virtual int32_t
   GetImmediateContextCount(const nsTArray<nsINode*>& aAncestorArray) override;
@@ -1544,21 +1545,21 @@ nsHTMLCopyEncoder::PromoteAncestorChain(
 
   //save the editable state of the ioNode, so we don't promote an ancestor if it has different editable state
   nsCOMPtr<nsINode> node = do_QueryInterface(*ioNode);
   bool isEditable = node->IsEditable();
 
   // loop for as long as we can promote both endpoints
   while (!done)
   {
-    rv = (*ioNode)->GetParentNode(getter_AddRefs(parent));
-    if ((NS_FAILED(rv)) || !parent)
+    node = do_QueryInterface(*ioNode);
+    parent = do_QueryInterface(node->GetParentNode());
+    if (!parent) {
       done = true;
-    else
-    {
+    } else {
       // passing parent as last param to GetPromotedPoint() allows it to promote only one level
       // up the hierarchy.
       rv = GetPromotedPoint( kStart, *ioNode, *ioStartOffset, address_of(frontNode), &frontOffset, parent);
       NS_ENSURE_SUCCESS(rv, rv);
       // then we make the same attempt with the endpoint
       rv = GetPromotedPoint( kEnd, *ioNode, *ioEndOffset, address_of(endNode), &endOffset, parent);
       NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1768,43 +1769,50 @@ nsHTMLCopyEncoder::GetChildAt(nsIDOMNode
   return resultNode;
 }
 
 bool
 nsHTMLCopyEncoder::IsMozBR(nsIDOMNode* aNode)
 {
   MOZ_ASSERT(aNode);
   nsCOMPtr<Element> element = do_QueryInterface(aNode);
-  return element &&
-         element->IsHTMLElement(nsGkAtoms::br) &&
-         element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
-                              NS_LITERAL_STRING("_moz"), eIgnoreCase);
+  return element && IsMozBR(element);
+}
+
+bool
+nsHTMLCopyEncoder::IsMozBR(Element* aElement)
+{
+  return aElement->IsHTMLElement(nsGkAtoms::br) &&
+         aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
+                               NS_LITERAL_STRING("_moz"), eIgnoreCase);
 }
 
 nsresult
 nsHTMLCopyEncoder::GetNodeLocation(nsIDOMNode *inChild,
                                    nsCOMPtr<nsIDOMNode> *outParent,
                                    int32_t *outOffset)
 {
   NS_ASSERTION((inChild && outParent && outOffset), "bad args");
-  nsresult result = NS_ERROR_NULL_POINTER;
   if (inChild && outParent && outOffset)
   {
-    result = inChild->GetParentNode(getter_AddRefs(*outParent));
-    if ((NS_SUCCEEDED(result)) && (*outParent))
-    {
-      nsCOMPtr<nsIContent> content = do_QueryInterface(*outParent);
-      nsCOMPtr<nsIContent> cChild = do_QueryInterface(inChild);
-      if (!cChild || !content)
-        return NS_ERROR_NULL_POINTER;
+    nsCOMPtr<nsIContent> child = do_QueryInterface(inChild);
+    if (!child) {
+      return NS_ERROR_NULL_POINTER;
+    }
 
-      *outOffset = content->ComputeIndexOf(cChild);
+    nsIContent* parent = child->GetParent();
+    if (!parent) {
+      return NS_ERROR_NULL_POINTER;
     }
+
+    *outParent = do_QueryInterface(parent);
+    *outOffset = parent->ComputeIndexOf(child);
+    return NS_OK;
   }
-  return result;
+  return NS_ERROR_NULL_POINTER;
 }
 
 bool
 nsHTMLCopyEncoder::IsRoot(nsIDOMNode* aNode)
 {
   nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
   if (!content) {
     return false;
@@ -1817,96 +1825,54 @@ nsHTMLCopyEncoder::IsRoot(nsIDOMNode* aN
   return content->IsAnyOfHTMLElements(nsGkAtoms::body,
                                       nsGkAtoms::td,
                                       nsGkAtoms::th);
 }
 
 bool
 nsHTMLCopyEncoder::IsFirstNode(nsIDOMNode *aNode)
 {
-  nsCOMPtr<nsIDOMNode> parent;
-  int32_t offset, j=0;
-  nsresult rv = GetNodeLocation(aNode, address_of(parent), &offset);
-  if (NS_FAILED(rv))
-  {
-    NS_NOTREACHED("failure in IsFirstNode");
-    return false;
-  }
-  if (offset == 0)  // easy case, we are first dom child
-    return true;
-  if (!parent)
-    return true;
-
+  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
   // need to check if any nodes before us are really visible.
   // Mike wrote something for me along these lines in nsSelectionController,
   // but I don't think it's ready for use yet - revisit.
   // HACK: for now, simply consider all whitespace text nodes to be
   // invisible formatting nodes.
-  nsCOMPtr<nsIDOMNodeList> childList;
-  nsCOMPtr<nsIDOMNode> child;
+  for (nsIContent* sibling = node->GetPreviousSibling();
+       sibling;
+       sibling = sibling->GetPreviousSibling()) {
+    if (!sibling->TextIsOnlyWhitespace()) {
+      return false;
+    }
+  }
 
-  rv = parent->GetChildNodes(getter_AddRefs(childList));
-  if (NS_FAILED(rv) || !childList)
-  {
-    NS_NOTREACHED("failure in IsFirstNode");
-    return true;
-  }
-  while (j < offset)
-  {
-    childList->Item(j, getter_AddRefs(child));
-    if (!IsEmptyTextContent(child))
-      return false;
-    j++;
-  }
   return true;
 }
 
-
 bool
 nsHTMLCopyEncoder::IsLastNode(nsIDOMNode *aNode)
 {
-  nsCOMPtr<nsIDOMNode> parent;
-  int32_t offset,j;
-  nsresult rv = GetNodeLocation(aNode, address_of(parent), &offset);
-  if (NS_FAILED(rv))
-  {
-    NS_NOTREACHED("failure in IsLastNode");
-    return false;
-  }
-  nsCOMPtr<nsINode> parentNode = do_QueryInterface(parent);
-  if (!parentNode) {
-    return true;
-  }
-
-  uint32_t numChildren = parentNode->Length();
-  if (offset+1 == (int32_t)numChildren) // easy case, we are last dom child
-    return true;
+  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
   // need to check if any nodes after us are really visible.
   // Mike wrote something for me along these lines in nsSelectionController,
   // but I don't think it's ready for use yet - revisit.
   // HACK: for now, simply consider all whitespace text nodes to be
   // invisible formatting nodes.
-  j = (int32_t)numChildren-1;
-  nsCOMPtr<nsIDOMNodeList>childList;
-  nsCOMPtr<nsIDOMNode> child;
-  rv = parent->GetChildNodes(getter_AddRefs(childList));
-  if (NS_FAILED(rv) || !childList)
-  {
-    NS_NOTREACHED("failure in IsLastNode");
-    return true;
+  for (nsIContent* sibling = node->GetNextSibling();
+       sibling;
+       sibling = sibling->GetNextSibling()) {
+    if (sibling->IsElement() && IsMozBR(sibling->AsElement())) {
+      // we ignore trailing moz BRs.
+      continue;
+    }
+    if (!sibling->TextIsOnlyWhitespace()) {
+      return false;
+    }
   }
-  while (j > offset)
-  {
-    childList->Item(j, getter_AddRefs(child));
-    j--;
-    if (IsMozBR(child))  // we ignore trailing moz BRs.
-      continue;
-    if (!IsEmptyTextContent(child))
-      return false;
-  }
+
   return true;
 }
 
 bool
 nsHTMLCopyEncoder::IsEmptyTextContent(nsIDOMNode* aNode)
 {
   nsCOMPtr<nsIContent> cont = do_QueryInterface(aNode);
   return cont && cont->TextIsOnlyWhitespace();
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -42,16 +42,17 @@
 #include "nsIObserverService.h"
 #include "nsIObjectFrame.h"
 #include "nsBindingManager.h"
 #include "nsStyleCoord.h"
 #include "TabChild.h"
 #include "nsFrameLoader.h"
 #include "nsNumberControlFrame.h"
 #include "nsNetUtil.h"
+#include "nsRange.h"
 
 #include "mozilla/ContentEvents.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/HTMLSlotElement.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
@@ -2425,47 +2426,51 @@ nsFocusManager::UpdateCaret(bool aMoveCa
   }
 
   SetCaretVisible(presShell, browseWithCaret, aContent);
 }
 
 void
 nsFocusManager::MoveCaretToFocus(nsIPresShell* aPresShell, nsIContent* aContent)
 {
-  // domDoc is a document interface we can create a range with
-  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aPresShell->GetDocument());
-  if (domDoc) {
+  nsCOMPtr<nsIDocument> doc = aPresShell->GetDocument();
+  if (doc) {
     RefPtr<nsFrameSelection> frameSelection = aPresShell->FrameSelection();
     nsCOMPtr<nsISelection> domSelection =
       frameSelection->GetSelection(SelectionType::eNormal);
     if (domSelection) {
-      nsCOMPtr<nsIDOMNode> currentFocusNode(do_QueryInterface(aContent));
       // First clear the selection. This way, if there is no currently focused
       // content, the selection will just be cleared.
       domSelection->RemoveAllRanges();
-      if (currentFocusNode) {
-        nsCOMPtr<nsIDOMRange> newRange;
-        nsresult rv = domDoc->CreateRange(getter_AddRefs(newRange));
-        if (NS_SUCCEEDED(rv)) {
-          // Set the range to the start of the currently focused node
-          // Make sure it's collapsed
-          newRange->SelectNodeContents(currentFocusNode);
-          nsCOMPtr<nsIDOMNode> firstChild;
-          currentFocusNode->GetFirstChild(getter_AddRefs(firstChild));
-          if (!firstChild ||
-              aContent->IsNodeOfType(nsINode::eHTML_FORM_CONTROL)) {
-            // If current focus node is a leaf, set range to before the
-            // node by using the parent as a container.
-            // This prevents it from appearing as selected.
-            newRange->SetStartBefore(currentFocusNode);
-            newRange->SetEndBefore(currentFocusNode);
-          }
-          domSelection->AddRange(newRange);
-          domSelection->CollapseToStart();
+      if (aContent) {
+        ErrorResult rv;
+        RefPtr<nsRange> newRange = doc->CreateRange(rv);
+        if (NS_WARN_IF(rv.Failed())) {
+          rv.SuppressException();
+          return;
         }
+
+        // Set the range to the start of the currently focused node
+        // Make sure it's collapsed
+        {
+          IgnoredErrorResult ignored;
+          newRange->SelectNodeContents(*aContent, ignored);
+        }
+
+        if (!aContent->GetFirstChild() ||
+            aContent->IsNodeOfType(nsINode::eHTML_FORM_CONTROL)) {
+          // If current focus node is a leaf, set range to before the
+          // node by using the parent as a container.
+          // This prevents it from appearing as selected.
+          IgnoredErrorResult err1, err2;
+          newRange->SetStartBefore(*aContent, err1);
+          newRange->SetEndBefore(*aContent, err2);
+        }
+        domSelection->AddRange(newRange);
+        domSelection->CollapseToStart();
       }
     }
   }
 }
 
 nsresult
 nsFocusManager::SetCaretVisible(nsIPresShell* aPresShell,
                                 bool aVisible,
@@ -2583,17 +2588,17 @@ nsFocusManager::GetSelectionLocation(nsI
   if (startContent) {
     startFrame = startContent->GetPrimaryFrame();
     if (isCollapsed) {
       // Next check to see if our caret is at the very end of a node
       // If so, the caret is actually sitting in front of the next
       // logical frame's primary node - so for this case we need to
       // change caretContent to that node.
 
-      if (startContent->NodeType() == nsIDOMNode::TEXT_NODE) {
+      if (startContent->NodeType() == nsINode::TEXT_NODE) {
         nsAutoString nodeValue;
         startContent->AppendTextTo(nodeValue);
 
         bool isFormControl =
           startContent->IsNodeOfType(nsINode::eHTML_FORM_CONTROL);
 
         if (nodeValue.Length() == startOffset && !isFormControl &&
             startContent != aDocument->GetRootElement()) {
@@ -3951,54 +3956,60 @@ nsFocusManager::GetFocusInSelection(nsPI
       testContent = nextTestContent;
       nextTestContent = nullptr;
     }
   }
 
   // We couldn't find an anchor that was an ancestor of the selection start
   // Method #2: look for anchor in selection's primary range (depth first search)
 
-  // Turn into nodes so that we can use GetNextSibling() and GetFirstChild()
-  nsCOMPtr<nsIDOMNode> selectionNode(do_QueryInterface(aStartSelection));
-  nsCOMPtr<nsIDOMNode> endSelectionNode(do_QueryInterface(aEndSelection));
-  nsCOMPtr<nsIDOMNode> testNode;
+  nsCOMPtr<nsIContent> selectionNode = aStartSelection;
+  nsCOMPtr<nsIContent> endSelectionNode = aEndSelection;
+  nsCOMPtr<nsIContent> testNode;
 
   do {
-    testContent = do_QueryInterface(selectionNode);
+    testContent = selectionNode;
 
     // We're looking for any focusable link that could be part of the
     // main document's selection.
     nsCOMPtr<nsIURI> uri;
     if (testContent == currentFocus ||
         testContent->IsLink(getter_AddRefs(uri))) {
       testContent.forget(aFocusedContent);
       return;
     }
 
-    selectionNode->GetFirstChild(getter_AddRefs(testNode));
+    nsIContent* testNode = selectionNode->GetFirstChild();
     if (testNode) {
       selectionNode = testNode;
       continue;
     }
 
     if (selectionNode == endSelectionNode)
       break;
-    selectionNode->GetNextSibling(getter_AddRefs(testNode));
+    testNode = selectionNode->GetNextSibling();
     if (testNode) {
       selectionNode = testNode;
       continue;
     }
 
     do {
-      selectionNode->GetParentNode(getter_AddRefs(testNode));
+      // GetParent is OK here, instead of GetParentNode, because the only case
+      // where the latter returns something different from the former is when
+      // GetParentNode is the document.  But in that case we would simply get
+      // null for selectionNode when setting it to testNode->GetNextSibling()
+      // (because a document has no next sibling).  And then the next iteration
+      // of this loop would get null for GetParentNode anyway, and break out of
+      // all the loops.
+      testNode = selectionNode->GetParent();
       if (!testNode || testNode == endSelectionNode) {
         selectionNode = nullptr;
         break;
       }
-      testNode->GetNextSibling(getter_AddRefs(selectionNode));
+      selectionNode = testNode->GetNextSibling();
       if (selectionNode)
         break;
       selectionNode = testNode;
     } while (true);
   }
   while (selectionNode && selectionNode != endSelectionNode);
 }
 
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -38,23 +38,23 @@
 #include "nsFrameLoader.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsSubDocumentFrame.h"
 #include "nsError.h"
 #include "nsISHistory.h"
 #include "nsISHistoryInternal.h"
-#include "nsIDOMHTMLDocument.h"
 #include "nsIXULWindow.h"
 #include "nsIMozBrowserFrame.h"
 #include "nsISHistory.h"
 #include "NullPrincipal.h"
 #include "nsIScriptError.h"
 #include "nsGlobalWindow.h"
+#include "nsHTMLDocument.h"
 #include "nsPIWindowRoot.h"
 #include "nsLayoutUtils.h"
 #include "nsMappedAttributes.h"
 #include "nsView.h"
 #include "nsBaseWidget.h"
 #include "nsQueryObject.h"
 
 #include "nsIURI.h"
@@ -893,30 +893,35 @@ nsFrameLoader::Show(int32_t marginWidth,
   NS_ENSURE_TRUE(mDocShell, false);
 
   // Trigger editor re-initialization if midas is turned on in the
   // sub-document. This shouldn't be necessary, but given the way our
   // editor works, it is. See
   // https://bugzilla.mozilla.org/show_bug.cgi?id=284245
   presShell = mDocShell->GetPresShell();
   if (presShell) {
-    nsCOMPtr<nsIDOMHTMLDocument> doc =
-      do_QueryInterface(presShell->GetDocument());
-
-    if (doc) {
+    nsIDocument* doc = presShell->GetDocument();
+    nsHTMLDocument* htmlDoc = doc ? doc->AsHTMLDocument() : nullptr;
+
+    if (htmlDoc) {
       nsAutoString designMode;
-      doc->GetDesignMode(designMode);
+      htmlDoc->GetDesignMode(designMode);
 
       if (designMode.EqualsLiteral("on")) {
         // Hold on to the editor object to let the document reattach to the
         // same editor object, instead of creating a new one.
         RefPtr<HTMLEditor> htmlEditor = mDocShell->GetHTMLEditor();
         Unused << htmlEditor;
-        doc->SetDesignMode(NS_LITERAL_STRING("off"));
-        doc->SetDesignMode(NS_LITERAL_STRING("on"));
+        {
+          IgnoredErrorResult rv;
+          htmlDoc->SetDesignMode(NS_LITERAL_STRING("off"), Nothing(), rv);
+        }
+
+        IgnoredErrorResult rv;
+        htmlDoc->SetDesignMode(NS_LITERAL_STRING("on"), Nothing(), rv);
       } else {
         // Re-initialize the presentation for contenteditable documents
         bool editable = false,
              hasEditingSession = false;
         mDocShell->GetEditable(&editable);
         mDocShell->GetHasEditingSession(&hasEditingSession);
         RefPtr<HTMLEditor> htmlEditor = mDocShell->GetHTMLEditor();
         if (editable && hasEditingSession && htmlEditor) {
--- a/dom/base/nsGenericDOMDataNode.cpp
+++ b/dom/base/nsGenericDOMDataNode.cpp
@@ -40,32 +40,32 @@
 #include "nsWrapperCacheInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsGenericDOMDataNode::nsGenericDOMDataNode(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
   : nsIContent(aNodeInfo)
 {
-  MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
-             mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
-             mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
-             mNodeInfo->NodeType() == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
-             mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
+  MOZ_ASSERT(mNodeInfo->NodeType() == TEXT_NODE ||
+             mNodeInfo->NodeType() == CDATA_SECTION_NODE ||
+             mNodeInfo->NodeType() == COMMENT_NODE ||
+             mNodeInfo->NodeType() == PROCESSING_INSTRUCTION_NODE ||
+             mNodeInfo->NodeType() == DOCUMENT_TYPE_NODE,
              "Bad NodeType in aNodeInfo");
 }
 
 nsGenericDOMDataNode::nsGenericDOMDataNode(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
   : nsIContent(aNodeInfo)
 {
-  MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
-             mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
-             mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
-             mNodeInfo->NodeType() == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
-             mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
+  MOZ_ASSERT(mNodeInfo->NodeType() == TEXT_NODE ||
+             mNodeInfo->NodeType() == CDATA_SECTION_NODE ||
+             mNodeInfo->NodeType() == COMMENT_NODE ||
+             mNodeInfo->NodeType() == PROCESSING_INSTRUCTION_NODE ||
+             mNodeInfo->NodeType() == DOCUMENT_TYPE_NODE,
              "Bad NodeType in aNodeInfo");
 }
 
 nsGenericDOMDataNode::~nsGenericDOMDataNode()
 {
   NS_PRECONDITION(!IsInUncomposedDoc(),
                   "Please remove this from the document properly");
   if (GetParent()) {
@@ -305,17 +305,17 @@ nsGenericDOMDataNode::SetTextInternal(ui
       endOffset,
       aLength,
       aDetails
     };
     nsNodeUtils::CharacterDataWillChange(this, &info);
   }
 
   Directionality oldDir = eDir_NotSet;
-  bool dirAffectsAncestor = (NodeType() == nsIDOMNode::TEXT_NODE &&
+  bool dirAffectsAncestor = (NodeType() == TEXT_NODE &&
                              TextNodeWillChangeDirection(this, &oldDir, aOffset));
 
   if (aOffset == 0 && endOffset == textLength) {
     // Replacing whole text or old text was empty.  Don't bother to check for
     // bidi in this string if the document already has bidi enabled.
     // If this is marked as "maybe modified frequently", the text should be
     // stored as char16_t since converting char* to char16_t* is expensive.
     bool ok =
@@ -372,17 +372,17 @@ nsGenericDOMDataNode::SetTextInternal(ui
     // If we found bidi characters in mText.SetTo() above, indicate that the
     // document contains bidi characters.
     document->SetBidiEnabled();
   }
 
   if (dirAffectsAncestor) {
     // dirAffectsAncestor being true implies that we have a text node, see
     // above.
-    MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE);
+    MOZ_ASSERT(NodeType() == TEXT_NODE);
     TextNodeChangedDirection(static_cast<nsTextNode*>(this), oldDir, aNotify);
   }
 
   // Notify observers
   if (aNotify) {
     CharacterDataChangeInfo info = {
       aOffset == textLength,
       aOffset,
@@ -932,18 +932,18 @@ nsGenericDOMDataNode::ThreadSafeTextIsOn
   }
 
   return true;
 }
 
 bool
 nsGenericDOMDataNode::HasTextForTranslation()
 {
-  if (NodeType() != nsIDOMNode::TEXT_NODE &&
-      NodeType() != nsIDOMNode::CDATA_SECTION_NODE) {
+  if (NodeType() != TEXT_NODE &&
+      NodeType() != CDATA_SECTION_NODE) {
     return false;
   }
 
   if (mText.Is2b()) {
     // The fragment contains non-8bit characters which means there
     // was at least one "interesting" character to trigger non-8bit.
     return true;
   }
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -223,17 +223,16 @@
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/Location.h"
 #include "nsHTMLDocument.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "prrng.h"
 #include "nsSandboxFlags.h"
-#include "TimeChangeObserver.h"
 #include "mozilla/dom/AudioContext.h"
 #include "mozilla/dom/BrowserElementDictionariesBinding.h"
 #include "mozilla/dom/cache/CacheStorage.h"
 #include "mozilla/dom/Console.h"
 #include "mozilla/dom/Fetch.h"
 #include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/HashChangeEvent.h"
 #include "mozilla/dom/IntlUtils.h"
@@ -6868,28 +6867,16 @@ nsGlobalWindowInner::IsVRContentPresenti
     if (display->IsAnyPresenting(gfx::kVRGroupAll)) {
       return true;
     }
   }
   return false;
 }
 
 void
-nsGlobalWindowInner::EnableTimeChangeNotifications()
-{
-  mozilla::time::AddWindowListener(this);
-}
-
-void
-nsGlobalWindowInner::DisableTimeChangeNotifications()
-{
-  mozilla::time::RemoveWindowListener(this);
-}
-
-void
 nsGlobalWindowInner::AddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const
 {
   aWindowSizes.mDOMOtherSize += aWindowSizes.mState.mMallocSizeOf(this);
 
   EventListenerManager* elm = GetExistingListenerManager();
   if (elm) {
     aWindowSizes.mDOMOtherSize +=
       elm->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -484,19 +484,16 @@ public:
   virtual void EnableDeviceSensor(uint32_t aType) override;
   virtual void DisableDeviceSensor(uint32_t aType) override;
 
 #if defined(MOZ_WIDGET_ANDROID)
   virtual void EnableOrientationChangeListener() override;
   virtual void DisableOrientationChangeListener() override;
 #endif
 
-  virtual void EnableTimeChangeNotifications() override;
-  virtual void DisableTimeChangeNotifications() override;
-
   bool IsClosedOrClosing() {
     return mCleanedUp;
   }
 
   bool
   IsCleanedUp() const
   {
     return mCleanedUp;
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -221,17 +221,16 @@
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/Location.h"
 #include "nsHTMLDocument.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "prrng.h"
 #include "nsSandboxFlags.h"
-#include "TimeChangeObserver.h"
 #include "mozilla/dom/AudioContext.h"
 #include "mozilla/dom/BrowserElementDictionariesBinding.h"
 #include "mozilla/dom/cache/CacheStorage.h"
 #include "mozilla/dom/Console.h"
 #include "mozilla/dom/Fetch.h"
 #include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/HashChangeEvent.h"
 #include "mozilla/dom/IntlUtils.h"
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -63,16 +63,17 @@ class nsCachableElementsByNameNodeList;
 class nsIDocShell;
 class nsDocShell;
 class nsDOMNavigationTiming;
 class nsFrameLoader;
 class nsGlobalWindowInner;
 class nsHTMLCSSStyleSheet;
 class nsHTMLDocument;
 class nsHTMLStyleSheet;
+class nsGenericHTMLElement;
 class nsAtom;
 class nsIBFCacheEntry;
 class nsIChannel;
 class nsIContent;
 class nsIContentSink;
 class nsIDocShell;
 class nsIDocShellTreeItem;
 class nsIDocumentEncoder;
@@ -1270,16 +1271,21 @@ public:
   // Get the canonical <body> element, or return null if there isn't one (e.g.
   // if the root isn't <html> or if the <body> isn't there)
   mozilla::dom::HTMLBodyElement* GetBodyElement();
   // Get the canonical <head> element, or return null if there isn't one (e.g.
   // if the root isn't <html> or if the <head> isn't there)
   Element* GetHeadElement() {
     return GetHtmlChildElement(nsGkAtoms::head);
   }
+  // Get the "body" in the sense of document.body: The first <body> or
+  // <frameset> that's a child of a root <html>
+  nsGenericHTMLElement* GetBody();
+  // Set the "body" in the sense of document.body.
+  void SetBody(nsGenericHTMLElement* aBody, mozilla::ErrorResult& rv);
 
   /**
    * Accessors to the collection of stylesheets owned by this document.
    * Style sheets are ordered, most significant last.
    */
 
   /**
    * These exists to allow us to on-demand load user-agent style sheets that
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -509,90 +509,16 @@ bool
 nsINode::IsAnonymousContentInSVGUseSubtree() const
 {
   MOZ_ASSERT(IsInAnonymousSubtree());
   nsIContent* parent = AsContent()->GetBindingParent();
   // Watch out for parentless native-anonymous subtrees.
   return parent && parent->IsSVGElement(nsGkAtoms::use);
 }
 
-nsresult
-nsINode::GetParentNode(nsIDOMNode** aParentNode)
-{
-  *aParentNode = nullptr;
-
-  nsINode *parent = GetParentNode();
-
-  return parent ? CallQueryInterface(parent, aParentNode) : NS_OK;
-}
-
-nsresult
-nsINode::GetChildNodes(nsIDOMNodeList** aChildNodes)
-{
-  NS_ADDREF(*aChildNodes = ChildNodes());
-
-  return NS_OK;
-}
-
-nsresult
-nsINode::GetFirstChild(nsIDOMNode** aNode)
-{
-  nsIContent* child = GetFirstChild();
-  if (child) {
-    return CallQueryInterface(child, aNode);
-  }
-
-  *aNode = nullptr;
-
-  return NS_OK;
-}
-
-nsresult
-nsINode::GetLastChild(nsIDOMNode** aNode)
-{
-  nsIContent* child = GetLastChild();
-  if (child) {
-    return CallQueryInterface(child, aNode);
-  }
-
-  *aNode = nullptr;
-
-  return NS_OK;
-}
-
-nsresult
-nsINode::GetPreviousSibling(nsIDOMNode** aPrevSibling)
-{
-  *aPrevSibling = nullptr;
-
-  nsIContent *sibling = GetPreviousSibling();
-
-  return sibling ? CallQueryInterface(sibling, aPrevSibling) : NS_OK;
-}
-
-nsresult
-nsINode::GetNextSibling(nsIDOMNode** aNextSibling)
-{
-  *aNextSibling = nullptr;
-
-  nsIContent *sibling = GetNextSibling();
-
-  return sibling ? CallQueryInterface(sibling, aNextSibling) : NS_OK;
-}
-
-nsresult
-nsINode::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
-{
-  *aOwnerDocument = nullptr;
-
-  nsIDocument *ownerDoc = GetOwnerDocument();
-
-  return ownerDoc ? CallQueryInterface(ownerDoc, aOwnerDocument) : NS_OK;
-}
-
 void
 nsINode::GetNodeValueInternal(nsAString& aNodeValue)
 {
   SetDOMStringToNull(aNodeValue);
 }
 
 nsINode*
 nsINode::RemoveChild(nsINode& aOldChild, ErrorResult& aError)
@@ -613,43 +539,27 @@ nsINode::RemoveChild(nsINode& aOldChild,
     aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
     return nullptr;
   }
 
   RemoveChildAt_Deprecated(index, true);
   return &aOldChild;
 }
 
-nsresult
-nsINode::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
-{
-  nsCOMPtr<nsINode> oldChild = do_QueryInterface(aOldChild);
-  if (!oldChild) {
-    return NS_ERROR_NULL_POINTER;
-  }
-
-  ErrorResult rv;
-  RemoveChild(*oldChild, rv);
-  if (!rv.Failed()) {
-    NS_ADDREF(*aReturn = aOldChild);
-  }
-  return rv.StealNSResult();
-}
-
 void
 nsINode::Normalize()
 {
   // First collect list of nodes to be removed
   AutoTArray<nsCOMPtr<nsIContent>, 50> nodes;
 
   bool canMerge = false;
   for (nsIContent* node = this->GetFirstChild();
        node;
        node = node->GetNextNode(this)) {
-    if (node->NodeType() != nsIDOMNode::TEXT_NODE) {
+    if (node->NodeType() != TEXT_NODE) {
       canMerge = false;
       continue;
     }
 
     if (canMerge || node->TextLength() == 0) {
       // No need to touch canMerge. That way we can merge across empty
       // textnodes if and only if the node before is a textnode
       nodes.AppendElement(node);
@@ -692,22 +602,22 @@ nsINode::Normalize()
   // Merge and remove all nodes
   nsAutoString tmpStr;
   for (uint32_t i = 0; i < nodes.Length(); ++i) {
     nsIContent* node = nodes[i];
     // Merge with previous node unless empty
     const nsTextFragment* text = node->GetText();
     if (text->GetLength()) {
       nsIContent* target = node->GetPreviousSibling();
-      NS_ASSERTION((target && target->NodeType() == nsIDOMNode::TEXT_NODE) ||
+      NS_ASSERTION((target && target->NodeType() == TEXT_NODE) ||
                    hasRemoveListeners,
                    "Should always have a previous text sibling unless "
                    "mutation events messed us up");
       if (!hasRemoveListeners ||
-          (target && target->NodeType() == nsIDOMNode::TEXT_NODE)) {
+          (target && target->NodeType() == TEXT_NODE)) {
         nsTextNode* t = static_cast<nsTextNode*>(target);
         if (text->Is2b()) {
           t->AppendTextForNormalize(text->Get2b(), text->GetLength(), true, node);
         }
         else {
           tmpStr.Truncate();
           text->AppendTo(tmpStr);
           t->AppendTextForNormalize(tmpStr.get(), tmpStr.Length(), true, node);
@@ -908,21 +818,21 @@ nsINode::GetUserData(JSContext* aCx, con
 uint16_t
 nsINode::CompareDocumentPosition(nsINode& aOtherNode) const
 {
   if (this == &aOtherNode) {
     return 0;
   }
   if (GetPreviousSibling() == &aOtherNode) {
     MOZ_ASSERT(GetParentNode() == aOtherNode.GetParentNode());
-    return static_cast<uint16_t>(nsIDOMNode::DOCUMENT_POSITION_PRECEDING);
+    return NodeBinding::DOCUMENT_POSITION_PRECEDING;
   }
   if (GetNextSibling() == &aOtherNode) {
     MOZ_ASSERT(GetParentNode() == aOtherNode.GetParentNode());
-    return static_cast<uint16_t>(nsIDOMNode::DOCUMENT_POSITION_FOLLOWING);
+    return NodeBinding::DOCUMENT_POSITION_FOLLOWING;
   }
 
   AutoTArray<const nsINode*, 32> parents1, parents2;
 
   const nsINode *node1 = &aOtherNode, *node2 = this;
 
   // Check if either node is an attribute
   const Attr* attr1 = nullptr;
@@ -944,26 +854,26 @@ nsINode::CompareDocumentPosition(nsINode
       // Compare position between the attributes.
 
       uint32_t i;
       const nsAttrName* attrName;
       for (i = 0; (attrName = elem->GetAttrNameAt(i)); ++i) {
         if (attrName->Equals(attr1->NodeInfo())) {
           NS_ASSERTION(!attrName->Equals(attr2->NodeInfo()),
                        "Different attrs at same position");
-          return nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
-            nsIDOMNode::DOCUMENT_POSITION_PRECEDING;
+          return NodeBinding::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
+            NodeBinding::DOCUMENT_POSITION_PRECEDING;
         }
         if (attrName->Equals(attr2->NodeInfo())) {
-          return nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
-            nsIDOMNode::DOCUMENT_POSITION_FOLLOWING;
+          return NodeBinding::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
+            NodeBinding::DOCUMENT_POSITION_FOLLOWING;
         }
       }
       NS_NOTREACHED("neither attribute in the element");
-      return nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED;
+      return NodeBinding::DOCUMENT_POSITION_DISCONNECTED;
     }
 
     if (elem) {
       node2 = elem;
       parents2.AppendElement(attr2);
     }
   }
 
@@ -984,49 +894,49 @@ nsINode::CompareDocumentPosition(nsINode
 
   // Check if the nodes are disconnected.
   uint32_t pos1 = parents1.Length();
   uint32_t pos2 = parents2.Length();
   const nsINode* top1 = parents1.ElementAt(--pos1);
   const nsINode* top2 = parents2.ElementAt(--pos2);
   if (top1 != top2) {
     return top1 < top2 ?
-      (nsIDOMNode::DOCUMENT_POSITION_PRECEDING |
-       nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED |
-       nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC) :
-      (nsIDOMNode::DOCUMENT_POSITION_FOLLOWING |
-       nsIDOMNode::DOCUMENT_POSITION_DISCONNECTED |
-       nsIDOMNode::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+      (NodeBinding::DOCUMENT_POSITION_PRECEDING |
+       NodeBinding::DOCUMENT_POSITION_DISCONNECTED |
+       NodeBinding::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC) :
+      (NodeBinding::DOCUMENT_POSITION_FOLLOWING |
+       NodeBinding::DOCUMENT_POSITION_DISCONNECTED |
+       NodeBinding::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
   }
 
   // Find where the parent chain differs and check indices in the parent.
   const nsINode* parent = top1;
   uint32_t len;
   for (len = std::min(pos1, pos2); len > 0; --len) {
     const nsINode* child1 = parents1.ElementAt(--pos1);
     const nsINode* child2 = parents2.ElementAt(--pos2);
     if (child1 != child2) {
       // child1 or child2 can be an attribute here. This will work fine since
       // ComputeIndexOf will return -1 for the attribute making the
       // attribute be considered before any child.
       return parent->ComputeIndexOf(child1) < parent->ComputeIndexOf(child2) ?
-        static_cast<uint16_t>(nsIDOMNode::DOCUMENT_POSITION_PRECEDING) :
-        static_cast<uint16_t>(nsIDOMNode::DOCUMENT_POSITION_FOLLOWING);
+        NodeBinding::DOCUMENT_POSITION_PRECEDING :
+        NodeBinding::DOCUMENT_POSITION_FOLLOWING;
     }
     parent = child1;
   }
 
   // We hit the end of one of the parent chains without finding a difference
   // between the chains. That must mean that one node is an ancestor of the
   // other. The one with the shortest chain must be the ancestor.
   return pos1 < pos2 ?
-    (nsIDOMNode::DOCUMENT_POSITION_PRECEDING |
-     nsIDOMNode::DOCUMENT_POSITION_CONTAINS) :
-    (nsIDOMNode::DOCUMENT_POSITION_FOLLOWING |
-     nsIDOMNode::DOCUMENT_POSITION_CONTAINED_BY);
+    (NodeBinding::DOCUMENT_POSITION_PRECEDING |
+     NodeBinding::DOCUMENT_POSITION_CONTAINS) :
+    (NodeBinding::DOCUMENT_POSITION_FOLLOWING |
+     NodeBinding::DOCUMENT_POSITION_CONTAINED_BY);
 }
 
 bool
 nsINode::IsSameNode(nsINode *other)
 {
   return other == this;
 }
 
@@ -1050,17 +960,17 @@ nsINode::IsEqualNode(nsINode* aOther)
     mozilla::dom::NodeInfo* nodeInfo1 = node1->mNodeInfo;
     mozilla::dom::NodeInfo* nodeInfo2 = node2->mNodeInfo;
     if (!nodeInfo1->Equals(nodeInfo2) ||
         nodeInfo1->GetExtraName() != nodeInfo2->GetExtraName()) {
       return false;
     }
 
     switch(nodeType) {
-      case nsIDOMNode::ELEMENT_NODE:
+      case ELEMENT_NODE:
       {
         // Both are elements (we checked that their nodeinfos are equal). Do the
         // check on attributes.
         Element* element1 = node1->AsElement();
         Element* element2 = node2->AsElement();
         uint32_t attrCount = element1->GetAttrCount();
         if (attrCount != element2->GetAttrCount()) {
           return false;
@@ -1080,49 +990,49 @@ nsINode::IsEqualNode(nsINode* aOther)
                                      attrName->LocalName(),
                                      string1,
                                      eCaseMatters)) {
             return false;
           }
         }
         break;
       }
-      case nsIDOMNode::TEXT_NODE:
-      case nsIDOMNode::COMMENT_NODE:
-      case nsIDOMNode::CDATA_SECTION_NODE:
-      case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
+      case TEXT_NODE:
+      case COMMENT_NODE:
+      case CDATA_SECTION_NODE:
+      case PROCESSING_INSTRUCTION_NODE:
       {
         string1.Truncate();
         static_cast<nsIContent*>(node1)->AppendTextTo(string1);
         string2.Truncate();
         static_cast<nsIContent*>(node2)->AppendTextTo(string2);
 
         if (!string1.Equals(string2)) {
           return false;
         }
 
         break;
       }
-      case nsIDOMNode::DOCUMENT_NODE:
-      case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
+      case DOCUMENT_NODE:
+      case DOCUMENT_FRAGMENT_NODE:
         break;
-      case nsIDOMNode::ATTRIBUTE_NODE:
+      case ATTRIBUTE_NODE:
       {
         NS_ASSERTION(node1 == this && node2 == aOther,
                      "Did we come upon an attribute node while walking a "
                      "subtree?");
         node1->GetNodeValue(string1);
         node2->GetNodeValue(string2);
 
         // Returning here as to not bother walking subtree. And there is no
         // risk that we're half way through walking some other subtree since
         // attribute nodes doesn't appear in subtrees.
         return string1.Equals(string2);
       }
-      case nsIDOMNode::DOCUMENT_TYPE_NODE:
+      case DOCUMENT_TYPE_NODE:
       {
         nsCOMPtr<nsIDOMDocumentType> docType1 = do_QueryInterface(node1);
         nsCOMPtr<nsIDOMDocumentType> docType2 = do_QueryInterface(node2);
 
         NS_ASSERTION(docType1 && docType2, "Why don't we have a document type node?");
 
         // Public ID
         docType1->GetPublicId(string1);
@@ -1436,17 +1346,17 @@ bool
 nsINode::UnoptimizableCCNode() const
 {
   const uintptr_t problematicFlags = (NODE_IS_ANONYMOUS_ROOT |
                                       NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
                                       NODE_IS_NATIVE_ANONYMOUS_ROOT |
                                       NODE_MAY_BE_IN_BINDING_MNGR |
                                       NODE_IS_IN_SHADOW_TREE);
   return HasFlag(problematicFlags) ||
-         NodeType() == nsIDOMNode::ATTRIBUTE_NODE ||
+         NodeType() == ATTRIBUTE_NODE ||
          // For strange cases like xbl:content/xbl:children
          (IsElement() &&
           AsElement()->IsInNamespace(kNameSpaceID_XBL));
 }
 
 /* static */
 bool
 nsINode::Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb)
@@ -1495,17 +1405,17 @@ nsINode::Traverse(nsINode *tmp, nsCycleC
       static_cast<nsCOMArray<nsISupports>*>(tmp->GetProperty(nsGkAtoms::keepobjectsalive));
     if (objects) {
       for (int32_t i = 0; i < objects->Count(); ++i) {
          cb.NoteXPCOMChild(objects->ObjectAt(i));
       }
     }
   }
 
-  if (tmp->NodeType() != nsIDOMNode::DOCUMENT_NODE &&
+  if (tmp->NodeType() != DOCUMENT_NODE &&
       tmp->HasFlag(NODE_HAS_LISTENERMANAGER)) {
     nsContentUtils::TraverseListenerManager(tmp, cb);
   }
 
   return true;
 }
 
 /* static */
@@ -1514,17 +1424,17 @@ nsINode::Unlink(nsINode* tmp)
 {
   tmp->ReleaseWrapper(tmp);
 
   nsSlots *slots = tmp->GetExistingSlots();
   if (slots) {
     slots->Unlink();
   }
 
-  if (tmp->NodeType() != nsIDOMNode::DOCUMENT_NODE &&
+  if (tmp->NodeType() != DOCUMENT_NODE &&
       tmp->HasFlag(NODE_HAS_LISTENERMANAGER)) {
     nsContentUtils::RemoveListenerManager(tmp);
     tmp->UnsetFlags(NODE_HAS_LISTENERMANAGER);
   }
 
   if (tmp->HasProperties()) {
     nsNodeUtils::UnlinkUserData(tmp);
     tmp->DeleteProperty(nsGkAtoms::keepobjectsalive);
@@ -1983,26 +1893,26 @@ bool IsAllowedAsChild(nsIContent* aNewCh
         aNewChild->GetShadowRoot()) &&
        nsContentUtils::ContentIsHostIncludingDescendantOf(aParent,
                                                           aNewChild))) {
     return false;
   }
 
   // The allowed child nodes differ for documents and elements
   switch (aNewChild->NodeType()) {
-  case nsIDOMNode::COMMENT_NODE :
-  case nsIDOMNode::PROCESSING_INSTRUCTION_NODE :
+  case nsINode::COMMENT_NODE :
+  case nsINode::PROCESSING_INSTRUCTION_NODE :
     // OK in both cases
     return true;
-  case nsIDOMNode::TEXT_NODE :
-  case nsIDOMNode::CDATA_SECTION_NODE :
-  case nsIDOMNode::ENTITY_REFERENCE_NODE :
+  case nsINode::TEXT_NODE :
+  case nsINode::CDATA_SECTION_NODE :
+  case nsINode::ENTITY_REFERENCE_NODE :
     // Allowed under Elements and DocumentFragments
-    return aParent->NodeType() != nsIDOMNode::DOCUMENT_NODE;
-  case nsIDOMNode::ELEMENT_NODE :
+    return aParent->NodeType() != nsINode::DOCUMENT_NODE;
+  case nsINode::ELEMENT_NODE :
     {
       if (!aParent->IsNodeOfType(nsINode::eDOCUMENT)) {
         // Always ok to have elements under other elements or document fragments
         return true;
       }
 
       nsIDocument* parentDocument = static_cast<nsIDocument*>(aParent);
       Element* rootElement = parentDocument->GetRootElement();
@@ -2029,17 +1939,17 @@ bool IsAllowedAsChild(nsIContent* aNewCh
       int32_t insertIndex = aParent->ComputeIndexOf(aRefChild);
 
       // Now we're OK in the following two cases only:
       // 1) We're replacing something that's not before the doctype
       // 2) We're inserting before something that comes after the doctype
       return aIsReplace ? (insertIndex >= doctypeIndex) :
         insertIndex > doctypeIndex;
     }
-  case nsIDOMNode::DOCUMENT_TYPE_NODE :
+  case nsINode::DOCUMENT_TYPE_NODE :
     {
       if (!aParent->IsNodeOfType(nsINode::eDOCUMENT)) {
         // doctypes only allowed under documents
         return false;
       }
 
       nsIDocument* parentDocument = static_cast<nsIDocument*>(aParent);
       nsIContent* docTypeContent = parentDocument->GetDoctype();
@@ -2064,17 +1974,17 @@ bool IsAllowedAsChild(nsIContent* aNewCh
       int32_t rootIndex = aParent->ComputeIndexOf(rootElement);
       int32_t insertIndex = aParent->ComputeIndexOf(aRefChild);
 
       // Now we're OK if and only if insertIndex <= rootIndex.  Indeed, either
       // we end up replacing aRefChild or we end up before it.  Either one is
       // ok as long as aRefChild is not after rootElement.
       return insertIndex <= rootIndex;
     }
-  case nsIDOMNode::DOCUMENT_FRAGMENT_NODE :
+  case nsINode::DOCUMENT_FRAGMENT_NODE :
     {
       // Note that for now we only allow nodes inside document fragments if
       // they're allowed inside elements.  If we ever change this to allow
       // doctype nodes in document fragments, we'll need to update this code.
       // Also, there's a version of this code in ReplaceOrInsertBefore.  If you
       // change this code, change that too.
       if (!aParent->IsNodeOfType(nsINode::eDOCUMENT)) {
         // All good here
@@ -2202,17 +2112,17 @@ nsINode::ReplaceOrInsertBefore(bool aRep
     nsINode* oldParent = aNewChild->GetParentNode();
     if (oldParent) {
       nsContentUtils::MaybeFireNodeRemoved(aNewChild, oldParent,
                                            aNewChild->OwnerDoc());
     }
 
     // If we're inserting a fragment, fire for all the children of the
     // fragment
-    if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+    if (nodeType == DOCUMENT_FRAGMENT_NODE) {
       static_cast<FragmentOrElement*>(aNewChild)->FireNodeRemovedForChildren();
     }
     // Verify that our aRefChild is still sensible
     if (aRefChild && aRefChild->GetParentNode() != this) {
       aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
       return nullptr;
     }
   }
@@ -2303,17 +2213,17 @@ nsINode::ReplaceOrInsertBefore(bool aRep
         // And recompute nodeToInsertBefore, just in case.
         if (aReplace) {
           nodeToInsertBefore = aRefChild->GetNextSibling();
         } else {
           nodeToInsertBefore = aRefChild;
         }
       }
     }
-  } else if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+  } else if (nodeType == DOCUMENT_FRAGMENT_NODE) {
     // Make sure to remove all the fragment's kids.  We need to do this before
     // we start inserting anything, so we will run out XBL destructors and
     // binding teardown (GOD, I HATE THESE THINGS) before we insert anything
     // into the DOM.
     uint32_t count = newContent->GetChildCount();
 
     fragChildren.emplace();
 
@@ -2462,17 +2372,17 @@ nsINode::ReplaceOrInsertBefore(bool aRep
   }
 
   /*
    * Check if we're inserting a document fragment. If we are, we need
    * to actually add its children individually (i.e. we don't add the
    * actual document fragment).
    */
   nsINode* result = aReplace ? aRefChild : aNewChild;
-  if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+  if (nodeType == DOCUMENT_FRAGMENT_NODE) {
     if (!aReplace) {
       mb.Init(this, true, true);
     }
     nsAutoMutationBatch* mutationBatch = nsAutoMutationBatch::GetCurrentBatch();
     if (mutationBatch) {
       mutationBatch->RemovalDone();
       mutationBatch->SetPrevSibling(GetChildAt_Deprecated(insPos - 1));
       mutationBatch->SetNextSibling(GetChildAt_Deprecated(insPos));
@@ -2665,23 +2575,23 @@ nsINode::Contains(const nsINode* aOther)
 
   return nsContentUtils::ContentIsDescendantOf(other, this);
 }
 
 uint32_t
 nsINode::Length() const
 {
   switch (NodeType()) {
-  case nsIDOMNode::DOCUMENT_TYPE_NODE:
+  case DOCUMENT_TYPE_NODE:
     return 0;
 
-  case nsIDOMNode::TEXT_NODE:
-  case nsIDOMNode::CDATA_SECTION_NODE:
-  case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
-  case nsIDOMNode::COMMENT_NODE:
+  case TEXT_NODE:
+  case CDATA_SECTION_NODE:
+  case PROCESSING_INSTRUCTION_NODE:
+  case COMMENT_NODE:
     MOZ_ASSERT(IsContent());
     return AsContent()->TextLength();
 
   default:
     return GetChildCount();
   }
 }
 
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -20,16 +20,17 @@
 #include "nsWindowSizes.h"          // for nsStyleSizes
 #include "mozilla/ErrorResult.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/EventTarget.h" // for base class
 #include "js/TypeDecls.h"     // for Handle, Value, JSObject, JSContext
 #include "mozilla/dom/DOMString.h"
 #include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/NodeBinding.h"
 #include "nsTHashtable.h"
 #include <iosfwd>
 
 // Including 'windows.h' will #define GetClassInfo to something else.
 #ifdef XP_WIN
 #ifdef GetClassInfo
 #undef GetClassInfo
 #endif
@@ -299,16 +300,36 @@ public:
   typedef mozilla::dom::DOMPointInit DOMPointInit;
   typedef mozilla::dom::DOMQuad DOMQuad;
   typedef mozilla::dom::DOMRectReadOnly DOMRectReadOnly;
   typedef mozilla::dom::OwningNodeOrString OwningNodeOrString;
   typedef mozilla::dom::TextOrElementOrDocument TextOrElementOrDocument;
   typedef mozilla::dom::CallerType CallerType;
   typedef mozilla::ErrorResult ErrorResult;
 
+  // XXXbz Maybe we should codegen a class holding these constants and
+  // inherit from it...
+  static const auto ELEMENT_NODE = mozilla::dom::NodeBinding::ELEMENT_NODE;
+  static const auto ATTRIBUTE_NODE = mozilla::dom::NodeBinding::ATTRIBUTE_NODE;
+  static const auto TEXT_NODE = mozilla::dom::NodeBinding::TEXT_NODE;
+  static const auto CDATA_SECTION_NODE =
+    mozilla::dom::NodeBinding::CDATA_SECTION_NODE;
+  static const auto ENTITY_REFERENCE_NODE =
+    mozilla::dom::NodeBinding::ENTITY_REFERENCE_NODE;
+  static const auto ENTITY_NODE = mozilla::dom::NodeBinding::ENTITY_NODE;
+  static const auto PROCESSING_INSTRUCTION_NODE =
+    mozilla::dom::NodeBinding::PROCESSING_INSTRUCTION_NODE;
+  static const auto COMMENT_NODE = mozilla::dom::NodeBinding::COMMENT_NODE;
+  static const auto DOCUMENT_NODE = mozilla::dom::NodeBinding::DOCUMENT_NODE;
+  static const auto DOCUMENT_TYPE_NODE =
+    mozilla::dom::NodeBinding::DOCUMENT_TYPE_NODE;
+  static const auto DOCUMENT_FRAGMENT_NODE =
+    mozilla::dom::NodeBinding::DOCUMENT_FRAGMENT_NODE;
+  static const auto NOTATION_NODE = mozilla::dom::NodeBinding::NOTATION_NODE;
+
   template<class T>
   using Sequence = mozilla::dom::Sequence<T>;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODE_IID)
 
   // The |aNodeSize| outparam on this function is where the actual node size
   // value is put. It gets added to the appropriate value within |aSizes| by
   // AddSizeOfNodeTree().
@@ -707,18 +728,17 @@ public:
   inline bool IsAnyOfMathMLElements(First aFirst, Args... aArgs) const
   {
     return IsMathMLElement() && IsNodeInternal(aFirst, aArgs...);
   }
 
   bool IsShadowRoot() const
   {
     const bool isShadowRoot = IsInShadowTree() && !GetParentNode();
-    MOZ_ASSERT_IF(isShadowRoot,
-                  NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE);
+    MOZ_ASSERT_IF(isShadowRoot, NodeType() == DOCUMENT_FRAGMENT_NODE);
     return isShadowRoot;
   }
 
   /**
    * Insert a content node before another or at the end.
    * This method handles calling BindToTree on the child appropriately.
    *
    * @param aKid the content to insert
@@ -1728,39 +1748,39 @@ public:
   void SetPointerLock() { SetBoolFlag(ElementHasPointerLock); }
   void ClearPointerLock() { ClearBoolFlag(ElementHasPointerLock); }
   bool MayHaveAnimations() const { return GetBoolFlag(ElementHasAnimations); }
   void SetMayHaveAnimations() { SetBoolFlag(ElementHasAnimations); }
   void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); }
   void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); }
   bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); }
   void SetHasDirAutoSet() {
-    MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
+    MOZ_ASSERT(NodeType() != TEXT_NODE,
                "SetHasDirAutoSet on text node");
     SetBoolFlag(NodeHasDirAutoSet);
   }
   void ClearHasDirAutoSet() {
-    MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
+    MOZ_ASSERT(NodeType() != TEXT_NODE,
                "ClearHasDirAutoSet on text node");
     ClearBoolFlag(NodeHasDirAutoSet);
   }
   bool HasDirAutoSet() const
     { return GetBoolFlag(NodeHasDirAutoSet); }
   void SetHasTextNodeDirectionalityMap() {
-    MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE,
+    MOZ_ASSERT(NodeType() == TEXT_NODE,
                "SetHasTextNodeDirectionalityMap on non-text node");
     SetBoolFlag(NodeHasTextNodeDirectionalityMap);
   }
   void ClearHasTextNodeDirectionalityMap() {
-    MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE,
+    MOZ_ASSERT(NodeType() == TEXT_NODE,
                "ClearHasTextNodeDirectionalityMap on non-text node");
     ClearBoolFlag(NodeHasTextNodeDirectionalityMap);
   }
   bool HasTextNodeDirectionalityMap() const {
-    MOZ_ASSERT(NodeType() == nsIDOMNode::TEXT_NODE,
+    MOZ_ASSERT(NodeType() == TEXT_NODE,
                "HasTextNodeDirectionalityMap on non-text node");
     return GetBoolFlag(NodeHasTextNodeDirectionalityMap);
   }
 
   void SetAncestorHasDirAuto() { SetBoolFlag(NodeAncestorHasDirAuto); }
   void ClearAncestorHasDirAuto() { ClearBoolFlag(NodeAncestorHasDirAuto); }
   bool AncestorHasDirAuto() const { return GetBoolFlag(NodeAncestorHasDirAuto); }
 
@@ -2069,35 +2089,24 @@ protected:
   }
 
 #ifdef DEBUG
   // Note: virtual so that IsInNativeAnonymousSubtree can be called accross
   // module boundaries.
   virtual void CheckNotNativeAnonymous() const;
 #endif
 
-  // These are just used to implement nsIDOMNode using
-  // NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER and for quickstubs.
-  nsresult GetParentNode(nsIDOMNode** aParentNode);
-  nsresult GetChildNodes(nsIDOMNodeList** aChildNodes);
-  nsresult GetFirstChild(nsIDOMNode** aFirstChild);
-  nsresult GetLastChild(nsIDOMNode** aLastChild);
-  nsresult GetPreviousSibling(nsIDOMNode** aPrevSibling);
-  nsresult GetNextSibling(nsIDOMNode** aNextSibling);
-  nsresult GetOwnerDocument(nsIDOMDocument** aOwnerDocument);
-
   void EnsurePreInsertionValidity1(nsINode& aNewChild, nsINode* aRefChild,
                                    mozilla::ErrorResult& aError);
   void EnsurePreInsertionValidity2(bool aReplace, nsINode& aNewChild,
                                    nsINode* aRefChild,
                                    mozilla::ErrorResult& aError);
   nsINode* ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
                                  nsINode* aRefChild,
                                  mozilla::ErrorResult& aError);
-  nsresult RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn);
 
   /**
    * Returns the Element that should be used for resolving namespaces
    * on this node (ie the ownerElement for attributes, the documentElement for
    * documents, the node itself for elements and for other nodes the parentNode
    * if it is an element).
    */
   virtual mozilla::dom::Element* GetNameSpaceElement() = 0;
@@ -2264,115 +2273,9 @@ ToSupports(nsINode* aPointer)
 }
 
 inline nsISupports*
 ToCanonicalSupports(nsINode* aPointer)
 {
   return aPointer;
 }
 
-#define NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER(...) \
-  NS_IMETHOD GetNodeName(nsAString& aNodeName) __VA_ARGS__ override \
-  { \
-    aNodeName = nsINode::NodeName(); \
-    return NS_OK; \
-  } \
-  NS_IMETHOD GetNodeValue(nsAString& aNodeValue) __VA_ARGS__ override \
-  { \
-    nsINode::GetNodeValue(aNodeValue); \
-    return NS_OK; \
-  } \
-  NS_IMETHOD SetNodeValue(const nsAString& aNodeValue) __VA_ARGS__ override \
-  { \
-    mozilla::ErrorResult rv; \
-    nsINode::SetNodeValue(aNodeValue, rv); \
-    return rv.StealNSResult(); \
-  } \
-  NS_IMETHOD GetNodeType(uint16_t* aNodeType) __VA_ARGS__ override \
-  { \
-    *aNodeType = nsINode::NodeType(); \
-    return NS_OK; \
-  } \
-  NS_IMETHOD GetParentNode(nsIDOMNode** aParentNode) __VA_ARGS__ override \
-  { \
-    return nsINode::GetParentNode(aParentNode); \
-  } \
-  NS_IMETHOD GetChildNodes(nsIDOMNodeList** aChildNodes) __VA_ARGS__ override \
-  { \
-    return nsINode::GetChildNodes(aChildNodes); \
-  } \
-  NS_IMETHOD GetFirstChild(nsIDOMNode** aFirstChild) __VA_ARGS__ override \
-  { \
-    return nsINode::GetFirstChild(aFirstChild); \
-  } \
-  NS_IMETHOD GetLastChild(nsIDOMNode** aLastChild) __VA_ARGS__ override \
-  { \
-    return nsINode::GetLastChild(aLastChild); \
-  } \
-  NS_IMETHOD GetPreviousSibling(nsIDOMNode** aPreviousSibling) __VA_ARGS__ override \
-  { \
-    return nsINode::GetPreviousSibling(aPreviousSibling); \
-  } \
-  NS_IMETHOD GetNextSibling(nsIDOMNode** aNextSibling) __VA_ARGS__ override \
-  { \
-    return nsINode::GetNextSibling(aNextSibling); \
-  } \
-  NS_IMETHOD GetOwnerDocument(nsIDOMDocument** aOwnerDocument) __VA_ARGS__ override \
-  { \
-    return nsINode::GetOwnerDocument(aOwnerDocument); \
-  } \
-  NS_IMETHOD RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aResult) __VA_ARGS__ override \
-  { \
-    return nsINode::RemoveChild(aOldChild, aResult); \
-  } \
-  NS_IMETHOD HasChildNodes(bool* aResult) __VA_ARGS__ override \
-  { \
-    *aResult = nsINode::HasChildNodes(); \
-    return NS_OK; \
-  } \
-  NS_IMETHOD CloneNode(bool aDeep, uint8_t aArgc, nsIDOMNode** aResult) __VA_ARGS__ override \
-  { \
-    if (aArgc == 0) { \
-      aDeep = true; \
-    } \
-    mozilla::ErrorResult rv; \
-    nsCOMPtr<nsINode> clone = nsINode::CloneNode(aDeep, rv); \
-    if (rv.Failed()) { \
-      return rv.StealNSResult(); \
-    } \
-    *aResult = clone.forget().take()->AsDOMNode(); \
-    return NS_OK; \
-  } \
-  NS_IMETHOD GetNamespaceURI(nsAString& aNamespaceURI) __VA_ARGS__ override \
-  { \
-    nsINode::GetNamespaceURI(aNamespaceURI); \
-    return NS_OK; \
-  } \
-  NS_IMETHOD GetPrefix(nsAString& aPrefix) __VA_ARGS__ override \
-  { \
-    nsINode::GetPrefix(aPrefix); \
-    return NS_OK; \
-  } \
-  NS_IMETHOD GetLocalName(nsAString& aLocalName) __VA_ARGS__ override \
-  { \
-    aLocalName = nsINode::LocalName(); \
-    return NS_OK; \
-  } \
-  NS_IMETHOD GetTextContent(nsAString& aTextContent) __VA_ARGS__ override \
-  { \
-    mozilla::ErrorResult rv; \
-    nsINode::GetTextContent(aTextContent, rv); \
-    return rv.StealNSResult(); \
-  } \
-  NS_IMETHOD SetTextContent(const nsAString& aTextContent) __VA_ARGS__ override \
-  { \
-    mozilla::ErrorResult rv; \
-    nsINode::SetTextContent(aTextContent, rv); \
-    return rv.StealNSResult(); \
-  }
-
-#define NS_FORWARD_NSIDOMNODE_TO_NSINODE \
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER(final)
-
-#define NS_FORWARD_NSIDOMNODE_TO_NSINODE_OVERRIDABLE \
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE_HELPER()
-
 #endif /* nsINode_h___ */
--- a/dom/base/nsNodeInfoManager.cpp
+++ b/dom/base/nsNodeInfoManager.cpp
@@ -349,34 +349,34 @@ nsNodeInfoManager::GetNodeInfo(const nsA
 
 already_AddRefed<NodeInfo>
 nsNodeInfoManager::GetTextNodeInfo()
 {
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
 
   if (!mTextNodeInfo) {
     nodeInfo = GetNodeInfo(nsGkAtoms::textTagName, nullptr, kNameSpaceID_None,
-                           nsIDOMNode::TEXT_NODE, nullptr);
+                           nsINode::TEXT_NODE, nullptr);
     // Hold a weak ref; the nodeinfo will let us know when it goes away
     mTextNodeInfo = nodeInfo;
   } else {
     nodeInfo = mTextNodeInfo;
   }
 
   return nodeInfo.forget();
 }
 
 already_AddRefed<NodeInfo>
 nsNodeInfoManager::GetCommentNodeInfo()
 {
   RefPtr<NodeInfo> nodeInfo;
 
   if (!mCommentNodeInfo) {
     nodeInfo = GetNodeInfo(nsGkAtoms::commentTagName, nullptr,
-                           kNameSpaceID_None, nsIDOMNode::COMMENT_NODE,
+                           kNameSpaceID_None, nsINode::COMMENT_NODE,
                            nullptr);
     // Hold a weak ref; the nodeinfo will let us know when it goes away
     mCommentNodeInfo = nodeInfo;
   }
   else {
     nodeInfo = mCommentNodeInfo;
   }
 
@@ -386,17 +386,17 @@ nsNodeInfoManager::GetCommentNodeInfo()
 already_AddRefed<NodeInfo>
 nsNodeInfoManager::GetDocumentNodeInfo()
 {
   RefPtr<NodeInfo> nodeInfo;
 
   if (!mDocumentNodeInfo) {
     NS_ASSERTION(mDocument, "Should have mDocument!");
     nodeInfo = GetNodeInfo(nsGkAtoms::documentNodeName, nullptr,
-                           kNameSpaceID_None, nsIDOMNode::DOCUMENT_NODE,
+                           kNameSpaceID_None, nsINode::DOCUMENT_NODE,
                            nullptr);
     // Hold a weak ref; the nodeinfo will let us know when it goes away
     mDocumentNodeInfo = nodeInfo;
 
     --mNonDocumentNodeInfos;
     if (!mNonDocumentNodeInfos) {
       mDocument->Release(); // Don't set mDocument to null!
     }
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -353,17 +353,17 @@ nsNodeUtils::LastRelease(nsINode* aNode)
     if (aNode->IsHTMLElement(nsGkAtoms::img) &&
         aNode->HasFlag(ADDED_TO_FORM)) {
       HTMLImageElement* imageElem = static_cast<HTMLImageElement*>(aNode);
       imageElem->ClearForm(true);
     }
   }
   aNode->UnsetFlags(NODE_HAS_PROPERTIES);
 
-  if (aNode->NodeType() != nsIDOMNode::DOCUMENT_NODE &&
+  if (aNode->NodeType() != nsINode::DOCUMENT_NODE &&
       aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
 #ifdef DEBUG
     if (nsContentUtils::IsInitialized()) {
       EventListenerManager* manager =
         nsContentUtils::GetExistingListenerManagerForNode(aNode);
       if (!manager) {
         NS_ERROR("Huh, our bit says we have a listener manager list, "
                  "but there's nothing in the hash!?!!");
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -553,19 +553,16 @@ public:
    */
   virtual void DisableDeviceSensor(uint32_t aType) = 0;
 
 #if defined(MOZ_WIDGET_ANDROID)
   virtual void EnableOrientationChangeListener() = 0;
   virtual void DisableOrientationChangeListener() = 0;
 #endif
 
-  virtual void EnableTimeChangeNotifications() = 0;
-  virtual void DisableTimeChangeNotifications() = 0;
-
   /**
    * Tell this window that there is an observer for gamepad input
    *
    * Inner windows only.
    */
   virtual void SetHasGamepadEventListener(bool aHasGamepad = true) = 0;
 
   /**
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -15,17 +15,17 @@
 #include "nsReadableUtils.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMText.h"
 #include "nsError.h"
 #include "nsIContentIterator.h"
-#include "nsIDOMNodeList.h"
+#include "nsINodeList.h"
 #include "nsGkAtoms.h"
 #include "nsContentUtils.h"
 #include "nsGenericDOMDataNode.h"
 #include "nsTextFrame.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/DocumentType.h"
 #include "mozilla/dom/RangeBinding.h"
 #include "mozilla/dom/DOMRect.h"
@@ -60,24 +60,24 @@ nsRange::GetDocGroup() const
  ******************************************************/
 
 static void InvalidateAllFrames(nsINode* aNode)
 {
   NS_PRECONDITION(aNode, "bad arg");
 
   nsIFrame* frame = nullptr;
   switch (aNode->NodeType()) {
-    case nsIDOMNode::TEXT_NODE:
-    case nsIDOMNode::ELEMENT_NODE:
+    case nsINode::TEXT_NODE:
+    case nsINode::ELEMENT_NODE:
     {
       nsIContent* content = static_cast<nsIContent*>(aNode);
       frame = content->GetPrimaryFrame();
       break;
     }
-    case nsIDOMNode::DOCUMENT_NODE:
+    case nsINode::DOCUMENT_NODE:
     {
       nsIDocument* doc = static_cast<nsIDocument*>(aNode);
       nsIPresShell* shell = doc ? doc->GetShell() : nullptr;
       frame = shell ? shell->GetRootFrame() : nullptr;
       break;
     }
   }
   for (nsIFrame* f = frame; f; f = f->GetNextContinuation()) {
@@ -912,17 +912,17 @@ nsRange::ComparePoint(const RawRangeBoun
     return 0;
   }
 
   if (!nsContentUtils::ContentIsDescendantOf(aPoint.Container(), mRoot)) {
     aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
     return 0;
   }
 
-  if (aPoint.Container()->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) {
+  if (aPoint.Container()->NodeType() == nsINode::DOCUMENT_TYPE_NODE) {
     aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
     return 0;
   }
 
   if (aPoint.Offset() > aPoint.Container()->Length()) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return 0;
   }
@@ -2311,21 +2311,26 @@ nsRange::CutContents(DocumentFragment** 
 
           if (endOffset > startOffset)
           {
             if (retval) {
               nsAutoString cutValue;
               rv = charData->SubstringData(startOffset, endOffset - startOffset,
                                            cutValue);
               NS_ENSURE_SUCCESS(rv, rv);
-              nsCOMPtr<nsIDOMNode> clone;
-              rv = charData->CloneNode(false, 1, getter_AddRefs(clone));
-              NS_ENSURE_SUCCESS(rv, rv);
-              clone->SetNodeValue(cutValue);
-              nodeToResult = do_QueryInterface(clone);
+              ErrorResult err;
+              nsCOMPtr<nsINode> clone = node->CloneNode(false, err);
+              if (NS_WARN_IF(err.Failed())) {
+                return err.StealNSResult();
+              }
+              clone->SetNodeValue(cutValue, err);
+              if (NS_WARN_IF(err.Failed())) {
+                return err.StealNSResult();
+              }
+              nodeToResult = clone;
             }
 
             nsMutationGuard guard;
             rv = charData->DeleteData(startOffset, endOffset - startOffset);
             NS_ENSURE_SUCCESS(rv, rv);
             NS_ENSURE_STATE(!guard.Mutated(0) ||
                             ValidateCurrentNode(this, iter));
           }
@@ -2339,21 +2344,26 @@ nsRange::CutContents(DocumentFragment** 
           rv = charData->GetLength(&dataLength);
           NS_ENSURE_SUCCESS(rv, rv);
 
           if (dataLength >= startOffset) {
             if (retval) {
               nsAutoString cutValue;
               rv = charData->SubstringData(startOffset, dataLength, cutValue);
               NS_ENSURE_SUCCESS(rv, rv);
-              nsCOMPtr<nsIDOMNode> clone;
-              rv = charData->CloneNode(false, 1, getter_AddRefs(clone));
-              NS_ENSURE_SUCCESS(rv, rv);
-              clone->SetNodeValue(cutValue);
-              nodeToResult = do_QueryInterface(clone);
+              ErrorResult err;
+              nsCOMPtr<nsINode> clone = node->CloneNode(false, err);
+              if (NS_WARN_IF(err.Failed())) {
+                return err.StealNSResult();
+              }
+              clone->SetNodeValue(cutValue, err);
+              if (NS_WARN_IF(err.Failed())) {
+                return err.StealNSResult();
+              }
+              nodeToResult = clone;
             }
 
             nsMutationGuard guard;
             rv = charData->DeleteData(startOffset, dataLength);
             NS_ENSURE_SUCCESS(rv, rv);
             NS_ENSURE_STATE(!guard.Mutated(0) ||
                             ValidateCurrentNode(this, iter));
           }
@@ -2363,21 +2373,26 @@ nsRange::CutContents(DocumentFragment** 
       }
       else if (node == endContainer)
       {
         // Delete or extract everything before endOffset.
         if (retval) {
           nsAutoString cutValue;
           rv = charData->SubstringData(0, endOffset, cutValue);
           NS_ENSURE_SUCCESS(rv, rv);
-          nsCOMPtr<nsIDOMNode> clone;
-          rv = charData->CloneNode(false, 1, getter_AddRefs(clone));
-          NS_ENSURE_SUCCESS(rv, rv);
-          clone->SetNodeValue(cutValue);
-          nodeToResult = do_QueryInterface(clone);
+          ErrorResult err;
+          nsCOMPtr<nsINode> clone = node->CloneNode(false, err);
+          if (NS_WARN_IF(err.Failed())) {
+            return err.StealNSResult();
+          }
+          clone->SetNodeValue(cutValue, err);
+          if (NS_WARN_IF(err.Failed())) {
+            return err.StealNSResult();
+          }
+          nodeToResult = clone;
         }
 
         nsMutationGuard guard;
         rv = charData->DeleteData(0, endOffset);
         NS_ENSURE_SUCCESS(rv, rv);
         NS_ENSURE_STATE(!guard.Mutated(0) ||
                         ValidateCurrentNode(this, iter));
         handled = true;
@@ -2899,17 +2914,17 @@ nsRange::InsertNode(nsINode& aNode, Erro
     return;
   }
 
   // This is the node we'll be inserting before, and its parent
   nsCOMPtr<nsINode> referenceNode;
   nsCOMPtr<nsINode> referenceParentNode = tStartContainer;
 
   nsCOMPtr<nsIDOMText> startTextNode(do_QueryInterface(tStartContainer));
-  nsCOMPtr<nsIDOMNodeList> tChildList;
+  nsCOMPtr<nsINodeList> tChildList;
   if (startTextNode) {
     referenceParentNode = tStartContainer->GetParentNode();
     if (!referenceParentNode) {
       aRv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
       return;
     }
 
     referenceParentNode->EnsurePreInsertionValidity(aNode, tStartContainer,
@@ -2921,28 +2936,20 @@ nsRange::InsertNode(nsINode& aNode, Erro
     nsCOMPtr<nsIDOMText> secondPart;
     aRv = startTextNode->SplitText(tStartOffset, getter_AddRefs(secondPart));
     if (aRv.Failed()) {
       return;
     }
 
     referenceNode = do_QueryInterface(secondPart);
   } else {
-    aRv = tStartContainer->AsDOMNode()->GetChildNodes(getter_AddRefs(tChildList));
-    if (aRv.Failed()) {
-      return;
-    }
+    tChildList = tStartContainer->ChildNodes();
 
     // find the insertion point in the DOM and insert the Node
-    nsCOMPtr<nsIDOMNode> q;
-    aRv = tChildList->Item(tStartOffset, getter_AddRefs(q));
-    referenceNode = do_QueryInterface(q);
-    if (aRv.Failed()) {
-      return;
-    }
+    referenceNode = tChildList->Item(tStartOffset);
 
     tStartContainer->EnsurePreInsertionValidity(aNode, referenceNode, aRv);
     if (aRv.Failed()) {
       return;
     }
   }
 
   // We might need to update the end to include the new node (bug 433662).
@@ -2953,23 +2960,20 @@ nsRange::InsertNode(nsINode& aNode, Erro
   if (referenceNode) {
     int32_t indexInParent = IndexOf(referenceNode);
     if (NS_WARN_IF(indexInParent < 0)) {
       aRv.Throw(NS_ERROR_FAILURE);
       return;
     }
     newOffset = static_cast<uint32_t>(indexInParent);
   } else {
-    aRv = tChildList->GetLength(&newOffset);
-    if (aRv.Failed()) {
-      return;
-    }
+    newOffset = tChildList->Length();
   }
 
-  if (aNode.NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+  if (aNode.NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) {
     newOffset += aNode.GetChildCount();
   } else {
     newOffset++;
   }
 
   // Now actually insert the node
   nsCOMPtr<nsINode> tResultNode;
   tResultNode = referenceParentNode->InsertBefore(aNode, referenceNode, aRv);
@@ -3026,19 +3030,19 @@ nsRange::SurroundContents(nsINode& aNewP
       aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
       return;
     }
   }
 
   // INVALID_NODE_TYPE_ERROR if aNewParent is something that can't be inserted
   // (Document, DocumentType, DocumentFragment)
   uint16_t nodeType = aNewParent.NodeType();
-  if (nodeType == nsIDOMNode::DOCUMENT_NODE ||
-      nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||
-      nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
+  if (nodeType == nsINode::DOCUMENT_NODE ||
+      nodeType == nsINode::DOCUMENT_TYPE_NODE ||
+      nodeType == nsINode::DOCUMENT_FRAGMENT_NODE) {
     aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
     return;
   }
 
   // Extract the contents within the range.
 
   RefPtr<DocumentFragment> docFrag = ExtractContents(aRv);
 
--- a/dom/base/nsTextNode.h
+++ b/dom/base/nsTextNode.h
@@ -22,17 +22,17 @@ class nsNodeInfoManager;
  * Class used to implement DOM text nodes
  */
 class nsTextNode : public mozilla::dom::Text,
                    public nsIDOMText
 {
 private:
   void Init()
   {
-    MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE,
+    MOZ_ASSERT(mNodeInfo->NodeType() == TEXT_NODE,
                "Bad NodeType in aNodeInfo");
   }
 
 public:
   explicit nsTextNode(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : mozilla::dom::Text(aNodeInfo)
   {
     Init();
@@ -42,20 +42,16 @@ public:
     : mozilla::dom::Text(aNodeInfoManager->GetTextNodeInfo())
   {
     Init();
   }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-  using mozilla::dom::Text::GetParentElement;
-
   // nsIDOMCharacterData
   NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
   using nsGenericDOMDataNode::SetData; // Prevent hiding overloaded virtual function.
 
   // nsIDOMText
   NS_FORWARD_NSIDOMTEXT(nsGenericDOMDataNode::)
 
   // nsINode
--- a/dom/base/nsXHTMLContentSerializer.cpp
+++ b/dom/base/nsXHTMLContentSerializer.cpp
@@ -733,54 +733,47 @@ nsXHTMLContentSerializer::IsElementPrefo
 bool
 nsXHTMLContentSerializer::SerializeLIValueAttribute(nsIContent* aElement,
                                                     nsAString& aStr)
 {
   // We are copying and we are at the "first" LI node of OL in selected range.
   // It may not be the first LI child of OL but it's first in the selected range.
   // Note that we get into this condition only once per a OL.
   bool found = false;
-  nsCOMPtr<nsIDOMNode> currNode = do_QueryInterface(aElement);
   nsAutoString valueStr;
 
   olState state (0, false);
 
   if (!mOLStateStack.IsEmpty()) {
     state = mOLStateStack[mOLStateStack.Length()-1];
     // isFirstListItem should be true only before the serialization of the
     // first item in the list.
     state.isFirstListItem = false;
     mOLStateStack[mOLStateStack.Length()-1] = state;
   }
 
   int32_t startVal = state.startVal;
   int32_t offset = 0;
 
   // Traverse previous siblings until we find one with "value" attribute.
-  // offset keeps track of how many previous siblings we had tocurrNode traverse.
+  // offset keeps track of how many previous siblings we had to traverse.
+  nsIContent* currNode = aElement;
   while (currNode && !found) {
-    nsCOMPtr<nsIDOMElement> currElement = do_QueryInterface(currNode);
-    // currElement may be null if it were a text node.
-    if (currElement) {
-      nsAutoString tagName;
-      currElement->GetTagName(tagName);
-      if (tagName.LowerCaseEqualsLiteral("li")) {
-        currElement->GetAttribute(NS_LITERAL_STRING("value"), valueStr);
-        if (valueStr.IsEmpty())
-          offset++;
-        else {
-          found = true;
-          nsresult rv = NS_OK;
-          startVal = valueStr.ToInteger(&rv);
-        }
+    if (currNode->IsHTMLElement(nsGkAtoms::li)) {
+      currNode->AsElement()->GetAttr(kNameSpaceID_None,
+                                     nsGkAtoms::value, valueStr);
+      if (valueStr.IsEmpty()) {
+        offset++;
+      } else {
+        found = true;
+        nsresult rv = NS_OK;
+        startVal = valueStr.ToInteger(&rv);
       }
     }
-    nsCOMPtr<nsIDOMNode> tmp;
-    currNode->GetPreviousSibling(getter_AddRefs(tmp));
-    currNode.swap(tmp);
+    currNode = currNode->GetPreviousSibling();
   }
   // If LI was not having "value", Set the "value" attribute for it.
   // Note that We are at the first LI in the selected range of OL.
   if (offset == 0 && found) {
     // offset = 0 => LI itself has the value attribute and we did not need to traverse back.
     // Just serialize value attribute like other tags.
     NS_ENSURE_TRUE(SerializeAttr(EmptyString(), NS_LITERAL_STRING("value"),
                                  valueStr, aStr, false), false);
@@ -803,38 +796,26 @@ nsXHTMLContentSerializer::SerializeLIVal
   }
 
   return true;
 }
 
 bool
 nsXHTMLContentSerializer::IsFirstChildOfOL(nsIContent* aElement)
 {
-  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
-  nsAutoString parentName;
-
-  nsCOMPtr<nsIDOMNode> parentNode;
-  node->GetParentNode(getter_AddRefs(parentNode));
-  if (parentNode)
-    parentNode->GetNodeName(parentName);
-  else
-    return false;
-
-  if (parentName.LowerCaseEqualsLiteral("ol")) {
-
+  nsIContent* parent = aElement->GetParent();
+  if (parent && parent->NodeName().LowerCaseEqualsLiteral("ol")) {
     if (!mOLStateStack.IsEmpty()) {
       olState state = mOLStateStack[mOLStateStack.Length()-1];
       if (state.isFirstListItem)
         return true;
     }
+  }
 
-    return false;
-  }
-  else
-    return false;
+  return false;
 }
 
 bool
 nsXHTMLContentSerializer::HasNoChildren(nsIContent* aContent) {
 
   for (nsIContent* child = aContent->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -19,16 +19,17 @@
 #include "AccessCheck.h"
 #include "jsfriendapi.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsHTMLTags.h"
 #include "nsIDocShell.h"
 #include "nsIDOMGlobalPropertyInitializer.h"
+#include "nsINode.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "nsIXPConnect.h"
 #include "nsUTF8Utils.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 #include "WrapperFactory.h"
 #include "xpcprivate.h"
@@ -3631,17 +3632,17 @@ CreateXULOrHTMLElement(const GlobalObjec
       return nullptr;
     }
   }
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo =
     doc->NodeInfoManager()->GetNodeInfo(definition->mLocalName,
                                         nullptr,
                                         ns,
-                                        nsIDOMNode::ELEMENT_NODE);
+                                        nsINode::ELEMENT_NODE);
   if (!nodeInfo) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   // Step 6 and Step 7 are in the code output by CGClassConstructor.
   // Step 8.
   nsTArray<RefPtr<Element>>& constructionStack =
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -593,20 +593,16 @@ DOMInterfaces = {
     'nativeType': 'mozilla::dom::HTMLCanvasPrintState',
 },
 
 'MozChannel': {
     'nativeType': 'nsIChannel',
     'notflattened': True
 },
 
-'MozTimeManager': {
-    'nativeType': 'mozilla::dom::time::TimeManager',
-},
-
 'MozStorageAsyncStatementParams': {
     'headerFile': 'mozilla/storage/mozStorageAsyncStatementParams.h',
     'nativeType': 'mozilla::storage::AsyncStatementParams',
 },
 
 'MozStorageStatementParams': {
     'headerFile': 'mozilla/storage/mozStorageStatementParams.h',
     'nativeType': 'mozilla::storage::StatementParams',
--- a/dom/bindings/test/test_bug560072.html
+++ b/dom/bindings/test/test_bug560072.html
@@ -15,19 +15,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 560072 **/
 is(document.body,
-   Object.getOwnPropertyDescriptor(HTMLDocument.prototype, "body").get.call(document),
+   Object.getOwnPropertyDescriptor(Document.prototype, "body").get.call(document),
    "Should get body out of property descriptor");
 
 is(document.body,
-   Object.getOwnPropertyDescriptor(Object.getPrototypeOf(document), "body").get.call(document),
+   Object.getOwnPropertyDescriptor(
+     Object.getPrototypeOf(Object.getPrototypeOf(document)), "body").get.call(document),
    "Should get body out of property descriptor this way too");
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/browser-element/BrowserElementParent.cpp
+++ b/dom/browser-element/BrowserElementParent.cpp
@@ -41,17 +41,17 @@ CreateIframe(Element* aOpenerFrameElemen
 {
   nsNodeInfoManager *nodeInfoManager =
     aOpenerFrameElement->OwnerDoc()->NodeInfoManager();
 
   RefPtr<NodeInfo> nodeInfo =
     nodeInfoManager->GetNodeInfo(nsGkAtoms::iframe,
                                  /* aPrefix = */ nullptr,
                                  kNameSpaceID_XHTML,
-                                 nsIDOMNode::ELEMENT_NODE);
+                                 nsINode::ELEMENT_NODE);
 
   RefPtr<HTMLIFrameElement> popupFrameElement =
     static_cast<HTMLIFrameElement*>(
       NS_NewHTMLIFrameElement(nodeInfo.forget(), mozilla::dom::NOT_FROM_PARSER));
 
   popupFrameElement->SetMozbrowser(true);
 
   // Copy the window name onto the iframe.
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -826,19 +826,19 @@ EventListenerManager::SetEventHandler(ns
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (csp) {
       // let's generate a script sample and pass it as aContent,
       // it will not match the hash, but allows us to pass
       // the script sample in aContent.
       nsAutoString scriptSample, attr, tagName(NS_LITERAL_STRING("UNKNOWN"));
       aName->ToString(attr);
-      nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mTarget));
+      nsCOMPtr<nsINode> domNode(do_QueryInterface(mTarget));
       if (domNode) {
-        domNode->GetNodeName(tagName);
+        tagName = domNode->NodeName();
       }
       // build a "script sample" based on what we know about this element
       scriptSample.Assign(attr);
       scriptSample.AppendLiteral(" attribute on ");
       scriptSample.Append(tagName);
       scriptSample.AppendLiteral(" element");
       nsCOMPtr<nsISupportsString> sampleIString(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
       if (sampleIString) {
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -23,28 +23,28 @@
 #include "mozilla/dom/UIEvent.h"
 
 #include "ContentEventHandler.h"
 #include "IMEContentObserver.h"
 #include "WheelHandlingHelper.h"
 
 #include "nsCOMPtr.h"
 #include "nsFocusManager.h"
+#include "nsGenericHTMLElement.h"
 #include "nsIContent.h"
 #include "nsIContentInlines.h"
 #include "nsIDocument.h"
 #include "nsIFrame.h"
 #include "nsIWidget.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsGkAtoms.h"
 #include "nsIFormControl.h"
 #include "nsIComboboxControlFrame.h"
 #include "nsIScrollableFrame.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsIDOMXULControlElement.h"
 #include "nsNameSpaceManager.h"
 #include "nsIBaseWindow.h"
 #include "nsISelection.h"
 #include "nsITextControlElement.h"
 #include "nsFrameSelection.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
@@ -1986,26 +1986,23 @@ EventStateManager::DetermineDragTargetAn
   nsIContent* originalDragContent = dragContent;
 
   // If a selection isn't being dragged, look for an ancestor with the
   // draggable property set. If one is found, use that as the target of the
   // drag instead of the node that was clicked on. If a draggable node wasn't
   // found, just use the clicked node.
   if (!*aSelection) {
     while (dragContent) {
-      nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(dragContent);
-      if (htmlElement) {
-        bool draggable = false;
-        htmlElement->GetDraggable(&draggable);
-        if (draggable)
+      if (auto htmlElement = nsGenericHTMLElement::FromContent(dragContent)) {
+        if (htmlElement->Draggable()) {
           break;
+        }
       }
       else {
-        nsCOMPtr<nsIDOMXULElement> xulElement = do_QueryInterface(dragContent);
-        if (xulElement) {
+        if (dragContent->IsXULElement()) {
           // All XUL elements are draggable, so if a XUL element is
           // encountered, stop looking for draggable nodes and just use the
           // original clicked node instead.
           // XXXndeakin
           // In the future, we will want to improve this so that XUL has a
           // better way to specify whether something is draggable than just
           // on/off.
           dragContent = mGestureDownContent;
--- a/dom/html/HTMLAudioElement.cpp
+++ b/dom/html/HTMLAudioElement.cpp
@@ -55,17 +55,17 @@ HTMLAudioElement::Audio(const GlobalObje
   if (!win || !(doc = win->GetExtantDoc())) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   already_AddRefed<mozilla::dom::NodeInfo> nodeInfo =
     doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::audio, nullptr,
                                         kNameSpaceID_XHTML,
-                                        nsIDOMNode::ELEMENT_NODE);
+                                        ELEMENT_NODE);
 
   RefPtr<HTMLAudioElement> audio = new HTMLAudioElement(nodeInfo);
   audio->SetHTMLAttr(nsGkAtoms::preload, NS_LITERAL_STRING("auto"), aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   if (aSrc.WasPassed()) {
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/TextEditor.h"
 #include "nsAttrValueInlines.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsIDocument.h"
+#include "nsIDocumentInlines.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsMappedAttributes.h"
 #include "nsIDocShell.h"
 #include "nsRuleWalker.h"
 #include "nsGlobalWindow.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Body)
 
@@ -269,17 +270,17 @@ already_AddRefed<TextEditor>
 HTMLBodyElement::GetAssociatedEditor()
 {
   RefPtr<TextEditor> textEditor = GetTextEditorInternal();
   if (textEditor) {
     return textEditor.forget();
   }
 
   // Make sure this is the actual body of the document
-  if (!IsCurrentBodyElement()) {
+  if (this != OwnerDoc()->GetBodyElement()) {
     return nullptr;
   }
 
   // For designmode, try to get document's editor
   nsPresContext* presContext = GetPresContext(eForComposedDoc);
   if (!presContext) {
     return nullptr;
   }
--- a/dom/html/HTMLDataElement.h
+++ b/dom/html/HTMLDataElement.h
@@ -3,17 +3,16 @@
 /* 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_HTMLDataElement_h
 #define mozilla_dom_HTMLDataElement_h
 
 #include "mozilla/Attributes.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLDataElement final : public nsGenericHTMLElement
 {
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -730,17 +730,17 @@ HTMLImageElement::Image(const GlobalObje
   if (!win || !(doc = win->GetExtantDoc())) {
     aError.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   already_AddRefed<mozilla::dom::NodeInfo> nodeInfo =
     doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::img, nullptr,
                                         kNameSpaceID_XHTML,
-                                        nsIDOMNode::ELEMENT_NODE);
+                                        ELEMENT_NODE);
 
   RefPtr<HTMLImageElement> img = new HTMLImageElement(nodeInfo);
 
   if (aWidth.WasPassed()) {
     img->SetWidth(aWidth.Value(), aError);
     if (aError.Failed()) {
       return nullptr;
     }
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -1882,30 +1882,16 @@ HTMLInputElement::GetList() const
   Element* element = doc->GetElementById(dataListId);
   if (!element || !element->IsHTMLElement(nsGkAtoms::datalist)) {
     return nullptr;
   }
 
   return static_cast<nsGenericHTMLElement*>(element);
 }
 
-NS_IMETHODIMP
-HTMLInputElement::GetList(nsIDOMHTMLElement** aValue)
-{
-  *aValue = nullptr;
-
-  RefPtr<nsGenericHTMLElement> element = GetList();
-  if (!element) {
-    return NS_OK;
-  }
-
-  element.forget(aValue);
-  return NS_OK;
-}
-
 void
 HTMLInputElement::SetValue(Decimal aValue, CallerType aCallerType)
 {
   MOZ_ASSERT(!aValue.isInfinity(), "aValue must not be Infinity!");
 
   if (aValue.isNaN()) {
     IgnoredErrorResult rv;
     SetValue(EmptyString(), aCallerType, rv);
--- a/dom/html/HTMLMapElement.cpp
+++ b/dom/html/HTMLMapElement.cpp
@@ -23,19 +23,18 @@ HTMLMapElement::HTMLMapElement(already_A
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLMapElement)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMapElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAreas)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLMapElement,
-                                             nsGenericHTMLElement,
-                                             nsIDOMHTMLElement)
+NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(HTMLMapElement,
+                                               nsGenericHTMLElement)
 
 NS_IMPL_ELEMENT_CLONE(HTMLMapElement)
 
 
 nsIHTMLCollection*
 HTMLMapElement::Areas()
 {
   if (!mAreas) {
--- a/dom/html/HTMLOptionElement.cpp
+++ b/dom/html/HTMLOptionElement.cpp
@@ -245,18 +245,18 @@ HTMLOptionElement::AfterSetAttr(int32_t 
 
 void
 HTMLOptionElement::GetText(nsAString& aText)
 {
   nsAutoString text;
 
   nsIContent* child = nsINode::GetFirstChild();
   while (child) {
-    if (child->NodeType() == nsIDOMNode::TEXT_NODE ||
-        child->NodeType() == nsIDOMNode::CDATA_SECTION_NODE) {
+    if (child->NodeType() == TEXT_NODE ||
+        child->NodeType() == CDATA_SECTION_NODE) {
       child->AppendTextTo(text);
     }
     if (child->IsHTMLElement(nsGkAtoms::script) ||
         child->IsSVGElement(nsGkAtoms::script)) {
       child = child->GetNextNonChildNode(this);
     } else {
       child = child->GetNextNode(this);
     }
@@ -346,17 +346,17 @@ HTMLOptionElement::Option(const GlobalOb
   if (!win || !(doc = win->GetExtantDoc())) {
     aError.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   already_AddRefed<mozilla::dom::NodeInfo> nodeInfo =
     doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::option, nullptr,
                                         kNameSpaceID_XHTML,
-                                        nsIDOMNode::ELEMENT_NODE);
+                                        ELEMENT_NODE);
 
   RefPtr<HTMLOptionElement> option = new HTMLOptionElement(nodeInfo);
 
   if (!aText.IsEmpty()) {
     // Create a new text node and append it to the option
     RefPtr<nsTextNode> textContent =
       new nsTextNode(option->NodeInfo()->NodeInfoManager());
 
--- a/dom/html/HTMLSlotElement.h
+++ b/dom/html/HTMLSlotElement.h
@@ -2,17 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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_HTMLSlotElement_h
 #define mozilla_dom_HTMLSlotElement_h
 
-#include "nsIDOMHTMLElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 namespace dom {
 
 struct AssignedNodesOptions;
 
@@ -73,9 +72,9 @@ protected:
   WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   nsTArray<RefPtr<nsINode>> mAssignedNodes;
 };
 
 } // namespace dom
 } // namespace mozilla
 
-#endif // mozilla_dom_HTMLSlotElement_h
\ No newline at end of file
+#endif // mozilla_dom_HTMLSlotElement_h
--- a/dom/html/HTMLSpanElement.h
+++ b/dom/html/HTMLSpanElement.h
@@ -3,17 +3,16 @@
 /* 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_HTMLSpanElement_h
 #define mozilla_dom_HTMLSpanElement_h
 
 #include "mozilla/Attributes.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsAtom.h"
 #include "nsRuleData.h"
 
 namespace mozilla {
 namespace dom {
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -724,17 +724,17 @@ HTMLTableElement::DeleteCaption()
 }
 
 already_AddRefed<nsGenericHTMLElement>
 HTMLTableElement::CreateTBody()
 {
   RefPtr<mozilla::dom::NodeInfo> nodeInfo =
     OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::tbody, nullptr,
                                                kNameSpaceID_XHTML,
-                                               nsIDOMNode::ELEMENT_NODE);
+                                               ELEMENT_NODE);
   MOZ_ASSERT(nodeInfo);
 
   RefPtr<nsGenericHTMLElement> newBody =
     NS_NewHTMLTableSectionElement(nodeInfo.forget());
   MOZ_ASSERT(newBody);
 
   nsCOMPtr<nsIContent> referenceNode = nullptr;
   for (nsIContent* child = nsINode::GetLastChild();
--- a/dom/html/HTMLTemplateElement.h
+++ b/dom/html/HTMLTemplateElement.h
@@ -3,17 +3,16 @@
 /* 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_HTMLTemplateElement_h
 #define mozilla_dom_HTMLTemplateElement_h
 
 #include "mozilla/Attributes.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsGenericHTMLElement.h"
 #include "mozilla/dom/DocumentFragment.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTemplateElement final : public nsGenericHTMLElement
 {
--- a/dom/html/HTMLTimeElement.h
+++ b/dom/html/HTMLTimeElement.h
@@ -3,17 +3,16 @@
 /* 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_HTMLTimeElement_h
 #define mozilla_dom_HTMLTimeElement_h
 
 #include "mozilla/Attributes.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLTimeElement final : public nsGenericHTMLElement
 {
--- a/dom/html/HTMLTrackElement.h
+++ b/dom/html/HTMLTrackElement.h
@@ -8,17 +8,16 @@
 #define mozilla_dom_HTMLTrackElement_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/TextTrack.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIHttpChannel.h"
 
 class nsIContent;
 class nsIDocument;
 
 namespace mozilla {
 namespace dom {
--- a/dom/html/ImageDocument.cpp
+++ b/dom/html/ImageDocument.cpp
@@ -27,17 +27,16 @@
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsIChannel.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMElement.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsError.h"
 #include "nsURILoader.h"
 #include "nsIDocShell.h"
 #include "nsIContentViewer.h"
 #include "nsThreadUtils.h"
 #include "nsIScrollableFrame.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/Element.h"
@@ -693,17 +692,17 @@ ImageDocument::CreateSyntheticDocument()
   if (!body) {
     NS_WARNING("no body on image document!");
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::img, nullptr,
                                            kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   mImageContent = NS_NewHTMLImageElement(nodeInfo.forget());
   if (!mImageContent) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mImageContent);
   NS_ENSURE_TRUE(imageLoader, NS_ERROR_UNEXPECTED);
 
--- a/dom/html/MediaDocument.cpp
+++ b/dom/html/MediaDocument.cpp
@@ -203,53 +203,53 @@ nsresult
 MediaDocument::CreateSyntheticDocument()
 {
   // Synthesize an empty html document
   nsresult rv;
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::html, nullptr,
                                            kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   RefPtr<nsGenericHTMLElement> root = NS_NewHTMLHtmlElement(nodeInfo.forget());
   NS_ENSURE_TRUE(root, NS_ERROR_OUT_OF_MEMORY);
 
   NS_ASSERTION(GetChildCount() == 0, "Shouldn't have any kids");
   rv = AppendChildTo(root, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::head, nullptr,
                                            kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   // Create a <head> so our title has somewhere to live
   RefPtr<nsGenericHTMLElement> head = NS_NewHTMLHeadElement(nodeInfo.forget());
   NS_ENSURE_TRUE(head, NS_ERROR_OUT_OF_MEMORY);
 
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::meta, nullptr,
                                            kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   RefPtr<nsGenericHTMLElement> metaContent = NS_NewHTMLMetaElement(nodeInfo.forget());
   NS_ENSURE_TRUE(metaContent, NS_ERROR_OUT_OF_MEMORY);
   metaContent->SetAttr(kNameSpaceID_None, nsGkAtoms::name,
                        NS_LITERAL_STRING("viewport"),
                        true);
 
   metaContent->SetAttr(kNameSpaceID_None, nsGkAtoms::content,
                        NS_LITERAL_STRING("width=device-width; height=device-height;"),
                        true);
   head->AppendChildTo(metaContent, false);
 
   root->AppendChildTo(head, false);
 
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::body, nullptr,
                                            kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   RefPtr<nsGenericHTMLElement> body = NS_NewHTMLBodyElement(nodeInfo.forget());
   NS_ENSURE_TRUE(body, NS_ERROR_OUT_OF_MEMORY);
 
   root->AppendChildTo(body, false);
 
   return NS_OK;
 }
@@ -315,17 +315,17 @@ MediaDocument::GetFileName(nsAString& aR
 }
 
 nsresult
 MediaDocument::LinkStylesheet(const nsAString& aStylesheet)
 {
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::link, nullptr,
                                            kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   RefPtr<nsGenericHTMLElement> link = NS_NewHTMLLinkElement(nodeInfo.forget());
   NS_ENSURE_TRUE(link, NS_ERROR_OUT_OF_MEMORY);
 
   link->SetAttr(kNameSpaceID_None, nsGkAtoms::rel,
                 NS_LITERAL_STRING("stylesheet"), true);
 
   link->SetAttr(kNameSpaceID_None, nsGkAtoms::href, aStylesheet, true);
@@ -335,17 +335,17 @@ MediaDocument::LinkStylesheet(const nsAS
 }
 
 nsresult
 MediaDocument::LinkScript(const nsAString& aScript)
 {
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::script, nullptr,
                                            kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   RefPtr<nsGenericHTMLElement> script = NS_NewHTMLScriptElement(nodeInfo.forget());
   NS_ENSURE_TRUE(script, NS_ERROR_OUT_OF_MEMORY);
 
   script->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
                   NS_LITERAL_STRING("text/javascript"), true);
 
   script->SetAttr(kNameSpaceID_None, nsGkAtoms::src, aScript, true);
--- a/dom/html/PluginDocument.cpp
+++ b/dom/html/PluginDocument.cpp
@@ -217,17 +217,17 @@ PluginDocument::CreateSyntheticPluginDoc
   body->SetAttr(kNameSpaceID_None, nsGkAtoms::marginwidth, zero, false);
   body->SetAttr(kNameSpaceID_None, nsGkAtoms::marginheight, zero, false);
 
 
   // make plugin content
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::embed, nullptr,
                                            kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
   rv = NS_NewHTMLElement(getter_AddRefs(mPluginContent), nodeInfo.forget(),
                          NOT_FROM_PARSER);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // make it a named element
   mPluginContent->SetAttr(kNameSpaceID_None, nsGkAtoms::name,
                           NS_LITERAL_STRING("plugin"), false);
 
--- a/dom/html/VideoDocument.cpp
+++ b/dom/html/VideoDocument.cpp
@@ -103,17 +103,17 @@ VideoDocument::CreateSyntheticVideoDocum
     NS_WARNING("no body on video document!");
     return NS_ERROR_FAILURE;
   }
 
   // make content
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::video, nullptr,
                                            kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   RefPtr<HTMLMediaElement> element =
     static_cast<HTMLMediaElement*>(NS_NewHTMLVideoElement(nodeInfo.forget(),
                                                           NOT_FROM_PARSER));
   if (!element)
     return NS_ERROR_OUT_OF_MEMORY;
   element->SetAutoplay(true);
   element->SetControls(true);
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -21,19 +21,17 @@
 #include "nsCOMPtr.h"
 #include "nsAtom.h"
 #include "nsQueryObject.h"
 #include "nsIContentInlines.h"
 #include "nsIContentViewer.h"
 #include "mozilla/css/Declaration.h"
 #include "nsIDocument.h"
 #include "nsIDocumentEncoder.h"
-#include "nsIDOMHTMLDocument.h"
 #include "nsIDOMDocumentFragment.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsMappedAttributes.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsIHTMLDocument.h"
 #include "nsPIDOMWindow.h"
 #include "nsIURL.h"
 #include "nsEscape.h"
@@ -168,17 +166,16 @@ private:
   // and Focus() is declared (and defined) in nsGenericHTMLElement class.
   RefPtr<nsGenericHTMLElement> mElement;
 };
 
 NS_IMPL_ADDREF_INHERITED(nsGenericHTMLElement, nsGenericHTMLElementBase)
 NS_IMPL_RELEASE_INHERITED(nsGenericHTMLElement, nsGenericHTMLElementBase)
 
 NS_INTERFACE_MAP_BEGIN(nsGenericHTMLElement)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLElement)
   NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElementBase)
 
 nsresult
 nsGenericHTMLElement::CopyInnerTo(Element* aDst, bool aPreallocateChildren)
 {
   MOZ_ASSERT(!aDst->GetUncomposedDoc(),
@@ -338,22 +335,20 @@ nsGenericHTMLElement::GetOffsetRect(CSSI
     if (isAbsolutelyPositioned && !offsetParent) {
       // If this element is absolutely positioned, but we don't have
       // an offset parent it means this element is an absolutely
       // positioned child that's not nested inside another positioned
       // element, in this case the element's frame's parent is the
       // frame for the HTML element so we fail to find the body in the
       // parent chain. We want the offset parent in this case to be
       // the body, so we just get the body element from the document.
-
-      nsCOMPtr<nsIDOMHTMLDocument> html_doc(do_QueryInterface(GetComposedDoc()));
-
-      if (html_doc) {
-        offsetParent = static_cast<nsHTMLDocument*>(html_doc.get())->GetBody();
-      }
+      //
+      // We use GetBodyElement() here, not GetBody(), because we don't want to
+      // end up with framesets here.
+      offsetParent = GetComposedDoc()->GetBodyElement();
     }
   }
 
   // Subtract the parent border unless it uses border-box sizing.
   if (parent &&
       parent->StylePosition()->mBoxSizing != StyleBoxSizing::Border) {
     const nsStyleBorder* border = parent->StyleBorder();
     origin.x -= border->GetComputedBorderWidth(eSideLeft);
@@ -2677,36 +2672,16 @@ already_AddRefed<TextEditor>
 nsGenericHTMLElement::GetAssociatedEditor()
 {
   // If contenteditable is ever implemented, it might need to do something different here?
 
   RefPtr<TextEditor> textEditor = GetTextEditorInternal();
   return textEditor.forget();
 }
 
-bool
-nsGenericHTMLElement::IsCurrentBodyElement()
-{
-  // TODO Bug 698498: Should this handle the case where GetBody returns a
-  //                  frameset?
-  if (!IsHTMLElement(nsGkAtoms::body)) {
-    return false;
-  }
-
-  nsCOMPtr<nsIDOMHTMLDocument> htmlDocument =
-    do_QueryInterface(GetUncomposedDoc());
-  if (!htmlDocument) {
-    return false;
-  }
-
-  nsCOMPtr<nsIDOMHTMLElement> htmlElement;
-  htmlDocument->GetBody(getter_AddRefs(htmlElement));
-  return htmlElement == static_cast<HTMLBodyElement*>(this);
-}
-
 // static
 void
 nsGenericHTMLElement::SyncEditorsOnSubtree(nsIContent* content)
 {
   /* Sync this node */
   nsGenericHTMLElement* element = FromContent(content);
   if (element) {
     RefPtr<TextEditor> textEditor = element->GetAssociatedEditor();
@@ -3125,17 +3100,17 @@ nsGenericHTMLElement::SetInnerText(const
         AppendChildTo(textContent, true);
       }
       if (s == end) {
         break;
       }
       str.Truncate();
       already_AddRefed<mozilla::dom::NodeInfo> ni =
         NodeInfo()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::br,
-          nullptr, kNameSpaceID_XHTML, nsIDOMNode::ELEMENT_NODE);
+          nullptr, kNameSpaceID_XHTML, ELEMENT_NODE);
       RefPtr<HTMLBRElement> br = new HTMLBRElement(ni);
       AppendChildTo(br, true);
     } else {
       str.Append(*s);
     }
     ++s;
   }
 
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -4,17 +4,17 @@
  * 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 nsGenericHTMLElement_h___
 #define nsGenericHTMLElement_h___
 
 #include "mozilla/Attributes.h"
 #include "mozilla/EventForwards.h"
 #include "nsMappedAttributeElement.h"
-#include "nsIDOMHTMLElement.h"
+#include "nsIDOMElement.h"
 #include "nsNameSpaceManager.h"  // for kNameSpaceID_None
 #include "nsIFormControl.h"
 #include "nsGkAtoms.h"
 #include "nsContentCreatorFunctions.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/DOMRect.h"
 #include "mozilla/dom/ValidityState.h"
@@ -42,17 +42,17 @@ class HTMLMenuElement;
 } // namespace mozilla
 
 typedef nsMappedAttributeElement nsGenericHTMLElementBase;
 
 /**
  * A common superclass for HTML elements
  */
 class nsGenericHTMLElement : public nsGenericHTMLElementBase,
-                             public nsIDOMHTMLElement
+                             public nsIDOMElement
 {
 public:
   using Element::SetTabIndex;
   using Element::Focus;
   explicit nsGenericHTMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsGenericHTMLElementBase(aNodeInfo)
   {
     NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
@@ -264,40 +264,16 @@ public:
   /**
    * Get width and height, using given image request if attributes are unset.
    * Pass a reference to the image request, since the method may change the
    * value and we want to use the updated value.
    */
   MOZ_CAN_RUN_SCRIPT
   nsSize GetWidthHeightForImage(RefPtr<imgRequestProxy>& aImageRequest);
 
-  // XPIDL methods
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-
-  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
-
-  NS_IMETHOD GetSpellcheck(bool* aSpellcheck) final override {
-    *aSpellcheck = Spellcheck();
-    return NS_OK;
-  }
-  NS_IMETHOD GetOffsetWidth(int32_t* aOffsetWidth) final override {
-    *aOffsetWidth = OffsetWidth();
-    return NS_OK;
-  }
-  NS_IMETHOD GetOffsetHeight(int32_t* aOffsetHeight) final override {
-    *aOffsetHeight = OffsetHeight();
-    return NS_OK;
-  }
-  NS_IMETHOD GetDraggable(bool* aDraggable) final override {
-    *aDraggable = Draggable();
-    return NS_OK;
-  }
-
-  using nsGenericHTMLElementBase::GetOwnerDocument;
-
   virtual nsIDOMNode* AsDOMNode() override { return this; }
 
 public:
   // Implementation for nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
@@ -934,21 +910,16 @@ protected:
    * Get the frame's offset information for offsetTop/Left/Width/Height.
    * Returns the parent the offset is relative to.
    * @note This method flushes pending notifications (FlushType::Layout).
    * @param aRect the offset information [OUT]
    */
   mozilla::dom::Element* GetOffsetRect(mozilla::CSSIntRect& aRect);
 
   /**
-   * Returns true if this is the current document's body element
-   */
-  bool IsCurrentBodyElement();
-
-  /**
    * Ensures all editors associated with a subtree are synced, for purposes of
    * spellchecking.
    */
   static void SyncEditorsOnSubtree(nsIContent* content);
 
   enum ContentEditableTristate {
     eInherit = -1,
     eFalse = 0,
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -350,17 +350,17 @@ SinkContext::OpenBody()
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
 
     RefPtr<mozilla::dom::NodeInfo> nodeInfo =
       mSink->mNodeInfoManager->GetNodeInfo(nsGkAtoms::body, nullptr,
                                            kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
   NS_ENSURE_TRUE(nodeInfo, NS_ERROR_UNEXPECTED);
 
   // Make the content object
   RefPtr<nsGenericHTMLElement> body =
     NS_NewHTMLBodyElement(nodeInfo.forget(), FROM_PARSER_NETWORK);
   if (!body) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -671,33 +671,33 @@ HTMLContentSink::Init(nsIDocument* aDoc,
 
   // Changed from 8192 to greatly improve page loading performance on
   // large pages.  See bugzilla bug 77540.
   mMaxTextRun = Preferences::GetInt("content.maxtextrun", 8191);
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::html, nullptr,
                                            kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   // Make root part
   mRoot = NS_NewHTMLHtmlElement(nodeInfo.forget());
   if (!mRoot) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   NS_ASSERTION(mDocument->GetChildCount() == 0,
                "Document should have no kids here!");
   rv = mDocument->AppendChildTo(mRoot, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Make head part
   nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::head,
                                            nullptr, kNameSpaceID_XHTML,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   mHead = NS_NewHTMLHeadElement(nodeInfo.forget());
   if (NS_FAILED(rv)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   mRoot->AppendChildTo(mHead, false);
 
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -50,17 +50,16 @@
 
 #include "nsNetCID.h"
 #include "nsICookieService.h"
 
 #include "nsIServiceManager.h"
 #include "nsIConsoleService.h"
 #include "nsIComponentManager.h"
 #include "nsParserCIID.h"
-#include "nsIDOMHTMLElement.h"
 #include "nsNameSpaceManager.h"
 #include "nsGenericHTMLElement.h"
 #include "mozilla/css/Loader.h"
 #include "nsIHttpChannel.h"
 #include "nsIFile.h"
 #include "nsFrameSelection.h"
 #include "nsISelectionPrivate.h" //for toStringwithformat code
 
@@ -203,18 +202,17 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(nsHTM
                                    mAnchors,
                                    mScripts,
                                    mForms,
                                    mWyciwygChannel,
                                    mMidasCommandManager)
 
 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(nsHTMLDocument,
                                              nsDocument,
-                                             nsIHTMLDocument,
-                                             nsIDOMHTMLDocument)
+                                             nsIHTMLDocument)
 
 JSObject*
 nsHTMLDocument::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return HTMLDocumentBinding::Wrap(aCx, this, aGivenProto);
 }
 
 nsresult
@@ -876,55 +874,51 @@ nsIContent*
 nsHTMLDocument::GetUnfocusedKeyEventTarget()
 {
   if (nsGenericHTMLElement* body = GetBody()) {
     return body;
   }
   return nsDocument::GetUnfocusedKeyEventTarget();
 }
 
-//
-// nsIDOMHTMLDocument interface implementation
-//
 already_AddRefed<nsIURI>
 nsHTMLDocument::GetDomainURI()
 {
   nsIPrincipal* principal = NodePrincipal();
 
   nsCOMPtr<nsIURI> uri;
   principal->GetDomain(getter_AddRefs(uri));
   if (uri) {
     return uri.forget();
   }
 
   principal->GetURI(getter_AddRefs(uri));
   return uri.forget();
 }
 
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::GetDomain(nsAString& aDomain)
 {
   nsCOMPtr<nsIURI> uri = GetDomainURI();
 
   if (!uri) {
     SetDOMStringToNull(aDomain);
-    return NS_OK;
+    return;
   }
 
   nsAutoCString hostName;
   nsresult rv = nsContentUtils::GetHostOrIPv6WithBrackets(uri, hostName);
   if (NS_SUCCEEDED(rv)) {
     CopyUTF8toUTF16(hostName, aDomain);
   } else {
     // If we can't get the host from the URI (e.g. about:, javascript:,
     // etc), just return an null string.
     SetDOMStringToNull(aDomain);
   }
-  return NS_OK;
 }
 
 already_AddRefed<nsIURI>
 nsHTMLDocument::CreateInheritingURIForHost(const nsACString& aHostString)
 {
   if (aHostString.IsEmpty()) {
     return nullptr;
   }
@@ -1028,24 +1022,16 @@ nsHTMLDocument::IsRegistrableDomainSuffi
   if (!newURI) {
     // Error: illegal domain
     return false;
   }
   return true;
 }
 
 
-NS_IMETHODIMP
-nsHTMLDocument::SetDomain(const nsAString& aDomain)
-{
-  ErrorResult rv;
-  SetDomain(aDomain, rv);
-  return rv.StealNSResult();
-}
-
 void
 nsHTMLDocument::SetDomain(const nsAString& aDomain, ErrorResult& rv)
 {
   if (mSandboxFlags & SANDBOXED_DOMAIN) {
     // We're sandboxed; disallow setting domain
     rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
@@ -1071,92 +1057,16 @@ nsHTMLDocument::SetDomain(const nsAStrin
     rv.Throw(NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN);
     return;
   }
 
   NS_TryToSetImmutable(newURI);
   rv = NodePrincipal()->SetDomain(newURI);
 }
 
-nsGenericHTMLElement*
-nsHTMLDocument::GetBody()
-{
-  Element* html = GetHtmlElement();
-  if (!html) {
-    return nullptr;
-  }
-
-  for (nsIContent* child = html->GetFirstChild();
-       child;
-       child = child->GetNextSibling()) {
-    if (child->IsHTMLElement(nsGkAtoms::body) ||
-        child->IsHTMLElement(nsGkAtoms::frameset)) {
-      return static_cast<nsGenericHTMLElement*>(child);
-    }
-  }
-
-  return nullptr;
-}
-
-NS_IMETHODIMP
-nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody)
-{
-  *aBody = nullptr;
-
-  nsIContent *body = GetBody();
-
-  return body ? CallQueryInterface(body, aBody) : NS_OK;
-}
-
-NS_IMETHODIMP
-nsHTMLDocument::SetBody(nsIDOMHTMLElement* aBody)
-{
-  nsCOMPtr<nsIContent> newBody = do_QueryInterface(aBody);
-  MOZ_ASSERT(!newBody || newBody->IsHTMLElement(),
-             "How could we be an nsIContent but not actually HTML here?");
-  ErrorResult rv;
-  SetBody(static_cast<nsGenericHTMLElement*>(newBody.get()), rv);
-  return rv.StealNSResult();
-}
-
-void
-nsHTMLDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv)
-{
-  nsCOMPtr<Element> root = GetRootElement();
-
-  // The body element must be either a body tag or a frameset tag. And we must
-  // have a html root tag, otherwise GetBody will not return the newly set
-  // body.
-  if (!newBody ||
-      !newBody->IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset) ||
-      !root || !root->IsHTMLElement() ||
-      !root->IsHTMLElement(nsGkAtoms::html)) {
-    rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
-    return;
-  }
-
-  // Use DOM methods so that we pass through the appropriate security checks.
-  nsCOMPtr<Element> currentBody = GetBodyElement();
-  if (currentBody) {
-    root->ReplaceChild(*newBody, *currentBody, rv);
-  } else {
-    root->AppendChild(*newBody, rv);
-  }
-}
-
-NS_IMETHODIMP
-nsHTMLDocument::GetHead(nsISupports** aHead)
-{
-  *aHead = nullptr;
-
-  Element* head = GetHeadElement();
-
-  return head ? CallQueryInterface(head, aHead) : NS_OK;
-}
-
 nsIHTMLCollection*
 nsHTMLDocument::Images()
 {
   if (!mImages) {
     mImages = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::img, nsGkAtoms::img);
   }
   return mImages;
 }
@@ -1248,24 +1158,16 @@ nsIHTMLCollection*
 nsHTMLDocument::Scripts()
 {
   if (!mScripts) {
     mScripts = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::script, nsGkAtoms::script);
   }
   return mScripts;
 }
 
-NS_IMETHODIMP
-nsHTMLDocument::GetCookie(nsAString& aCookie)
-{
-  ErrorResult rv;
-  GetCookie(aCookie, rv);
-  return rv.StealNSResult();
-}
-
 already_AddRefed<nsIChannel>
 nsHTMLDocument::CreateDummyChannelForCookies(nsIURI* aCodebaseURI)
 {
   // The cookie service reads the privacy status of the channel we pass to it in
   // order to determine which cookie database to query.  In some cases we don't
   // have a proper channel to hand it to the cookie service though.  This
   // function creates a dummy channel that is not used to load anything, for the
   // sole purpose of handing it to the cookie service.  DO NOT USE THIS CHANNEL
@@ -1337,24 +1239,16 @@ nsHTMLDocument::GetCookie(nsAString& aCo
     nsCString cookie;
     service->GetCookieString(codebaseURI, channel, getter_Copies(cookie));
     // CopyUTF8toUTF16 doesn't handle error
     // because it assumes that the input is valid.
     UTF_8_ENCODING->DecodeWithoutBOMHandling(cookie, aCookie);
   }
 }
 
-NS_IMETHODIMP
-nsHTMLDocument::SetCookie(const nsAString& aCookie)
-{
-  ErrorResult rv;
-  SetCookie(aCookie, rv);
-  return rv.StealNSResult();
-}
-
 void
 nsHTMLDocument::SetCookie(const nsAString& aCookie, ErrorResult& rv)
 {
   if (mDisableCookieAccess) {
     return;
   }
 
   // If the document's sandboxed origin flag is set, access to write cookies
@@ -1391,56 +1285,26 @@ nsHTMLDocument::SetCookie(const nsAStrin
       }
     }
 
     NS_ConvertUTF16toUTF8 cookie(aCookie);
     service->SetCookieString(codebaseURI, nullptr, cookie.get(), channel);
   }
 }
 
-NS_IMETHODIMP
-nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
-                     const nsAString& aReplaceOrName,
-                     const nsAString& aFeatures,
-                     JSContext* cx, uint8_t aOptionalArgCount,
-                     nsISupports** aReturn)
-{
-  // When called with 3 or more arguments, document.open() calls window.open().
-  if (aOptionalArgCount > 2) {
-    ErrorResult rv;
-    *aReturn = Open(cx, aContentTypeOrUrl, aReplaceOrName, aFeatures,
-                    false, rv).take();
-    return rv.StealNSResult();
-  }
-
-  nsString type;
-  if (aOptionalArgCount > 0) {
-    type = aContentTypeOrUrl;
-  } else {
-    type.AssignLiteral("text/html");
-  }
-  nsString replace;
-  if (aOptionalArgCount > 1) {
-    replace = aReplaceOrName;
-  }
-  ErrorResult rv;
-  *aReturn = Open(cx, type, replace, rv).take();
-  return rv.StealNSResult();
-}
-
 already_AddRefed<nsPIDOMWindowOuter>
 nsHTMLDocument::Open(JSContext* /* unused */,
                      const nsAString& aURL,
                      const nsAString& aName,
                      const nsAString& aFeatures,
                      bool aReplace,
                      ErrorResult& rv)
 {
-  NS_ASSERTION(nsContentUtils::CanCallerAccess(static_cast<nsIDOMHTMLDocument*>(this)),
-               "XOW should have caught this!");
+  MOZ_ASSERT(nsContentUtils::CanCallerAccess(static_cast<nsIDOMDocument*>(this)),
+             "XOW should have caught this!");
 
   nsCOMPtr<nsPIDOMWindowInner> window = GetInnerWindow();
   if (!window) {
     rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return nullptr;
   }
   nsCOMPtr<nsPIDOMWindowOuter> outer =
     nsPIDOMWindowOuter::GetFromCurrentInner(window);
@@ -1459,18 +1323,18 @@ already_AddRefed<nsIDocument>
 nsHTMLDocument::Open(JSContext* cx,
                      const nsAString& aType,
                      const nsAString& aReplace,
                      ErrorResult& aError)
 {
   // Implements the "When called with two arguments (or fewer)" steps here:
   // https://html.spec.whatwg.org/multipage/webappapis.html#opening-the-input-stream
 
-  NS_ASSERTION(nsContentUtils::CanCallerAccess(static_cast<nsIDOMHTMLDocument*>(this)),
-               "XOW should have caught this!");
+  MOZ_ASSERT(nsContentUtils::CanCallerAccess(static_cast<nsIDOMDocument*>(this)),
+             "XOW should have caught this!");
   if (!IsHTMLDocument() || mDisableDocWrite) {
     // No calling document.open() on XHTML
     aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
 
   if (ShouldThrowOnDynamicMarkupInsertion()) {
     aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
@@ -1806,31 +1670,16 @@ nsHTMLDocument::Open(JSContext* cx,
   DebugOnly<JSObject*> wrapper = GetWrapperPreserveColor();
   MOZ_ASSERT_IF(wrapper,
                 JS_GetCompartmentPrincipals(js::GetObjectCompartment(wrapper)) ==
                 nsJSPrincipals::get(NodePrincipal()));
 
   return kungFuDeathGrip.forget();
 }
 
-NS_IMETHODIMP
-nsHTMLDocument::Clear()
-{
-  // This method has been deprecated
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHTMLDocument::Close()
-{
-  ErrorResult rv;
-  Close(rv);
-  return rv.StealNSResult();
-}
-
 void
 nsHTMLDocument::Close(ErrorResult& rv)
 {
   if (!IsHTMLDocument()) {
     // No calling document.close() on XHTML!
 
     rv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
@@ -1892,75 +1741,79 @@ nsHTMLDocument::Close(ErrorResult& rv)
 void
 nsHTMLDocument::WriteCommon(JSContext *cx,
                             const Sequence<nsString>& aText,
                             bool aNewlineTerminate,
                             mozilla::ErrorResult& rv)
 {
   // Fast path the common case
   if (aText.Length() == 1) {
-    rv = WriteCommon(cx, aText[0], aNewlineTerminate);
+    WriteCommon(cx, aText[0], aNewlineTerminate, rv);
   } else {
     // XXXbz it would be nice if we could pass all the strings to the parser
     // without having to do all this copying and then ask it to start
     // parsing....
     nsString text;
     for (uint32_t i = 0; i < aText.Length(); ++i) {
       text.Append(aText[i]);
     }
-    rv = WriteCommon(cx, text, aNewlineTerminate);
+    WriteCommon(cx, text, aNewlineTerminate, rv);
   }
 }
 
-nsresult
+void
 nsHTMLDocument::WriteCommon(JSContext *cx,
                             const nsAString& aText,
-                            bool aNewlineTerminate)
+                            bool aNewlineTerminate,
+                            ErrorResult& aRv)
 {
   mTooDeepWriteRecursion =
     (mWriteLevel > NS_MAX_DOCUMENT_WRITE_DEPTH || mTooDeepWriteRecursion);
-  NS_ENSURE_STATE(!mTooDeepWriteRecursion);
+  if (NS_WARN_IF(mTooDeepWriteRecursion)) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return;
+  }
 
   if (!IsHTMLDocument() || mDisableDocWrite) {
     // No calling document.write*() on XHTML!
 
-    return NS_ERROR_DOM_INVALID_STATE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
   }
 
 
   if (ShouldThrowOnDynamicMarkupInsertion()) {
-    return NS_ERROR_DOM_INVALID_STATE_ERR;
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
   }
 
   if (mParserAborted) {
     // Hixie says aborting the parser doesn't undefine the insertion point.
     // However, since we null out mParser in that case, we track the
     // theoretically defined insertion point using mParserAborted.
-    return NS_OK;
+    return;
   }
 
   // Implement Step 4.1 of:
   // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#document-write-steps
   if (ShouldIgnoreOpens()) {
-    return NS_OK;
+    return;
   }
 
-  nsresult rv = NS_OK;
-
   void *key = GenerateParserKey();
   if (mParser && !mParser->IsInsertionPointDefined()) {
     if (mIgnoreDestructiveWritesCounter) {
       // Instead of implying a call to document.open(), ignore the call.
       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                       NS_LITERAL_CSTRING("DOM Events"), this,
                                       nsContentUtils::eDOM_PROPERTIES,
                                       "DocumentWriteIgnored",
                                       nullptr, 0,
                                       mDocumentURI);
-      return NS_OK;
+      return;
     }
     // The spec doesn't tell us to ignore opens from here, but we need to
     // ensure opens are ignored here.
     IgnoreOpensDuringUnload ignoreOpenGuard(this);
     mParser->Terminate();
     MOZ_RELEASE_ASSERT(!mParser, "mParser should have been null'd out");
   }
 
@@ -1968,27 +1821,26 @@ nsHTMLDocument::WriteCommon(JSContext *c
     if (mIgnoreDestructiveWritesCounter) {
       // Instead of implying a call to document.open(), ignore the call.
       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                       NS_LITERAL_CSTRING("DOM Events"), this,
                                       nsContentUtils::eDOM_PROPERTIES,
                                       "DocumentWriteIgnored",
                                       nullptr, 0,
                                       mDocumentURI);
-      return NS_OK;
+      return;
     }
-    nsCOMPtr<nsISupports> ignored;
-    rv = Open(NS_LITERAL_STRING("text/html"), EmptyString(), EmptyString(), cx,
-              1, getter_AddRefs(ignored));
+    nsCOMPtr<nsIDocument> ignored  = Open(cx, NS_LITERAL_STRING("text/html"),
+                                          EmptyString(), aRv);
 
     // If Open() fails, or if it didn't create a parser (as it won't
     // if the user chose to not discard the current document through
     // onbeforeunload), don't write anything.
-    if (NS_FAILED(rv) || !mParser) {
-      return rv;
+    if (aRv.Failed() || !mParser) {
+      return;
     }
     MOZ_ASSERT(!JS_IsExceptionPending(cx),
                "Open() succeeded but JS exception is pending");
   }
 
   static NS_NAMED_LITERAL_STRING(new_line, "\n");
 
   // Save the data in cache if the write isn't from within the doc
@@ -2004,49 +1856,35 @@ nsHTMLDocument::WriteCommon(JSContext *c
 
   ++mWriteLevel;
 
   // This could be done with less code, but for performance reasons it
   // makes sense to have the code for two separate Parse() calls here
   // since the concatenation of strings costs more than we like. And
   // why pay that price when we don't need to?
   if (aNewlineTerminate) {
-    rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
+    aRv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
       aText + new_line, key, GetContentTypeInternal(), false);
   } else {
-    rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
+    aRv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
       aText, key, GetContentTypeInternal(), false);
   }
 
   --mWriteLevel;
 
   mTooDeepWriteRecursion = (mWriteLevel != 0 && mTooDeepWriteRecursion);
-
-  return rv;
-}
-
-NS_IMETHODIMP
-nsHTMLDocument::Write(const nsAString& aText, JSContext *cx)
-{
-  return WriteCommon(cx, aText, false);
 }
 
 void
 nsHTMLDocument::Write(JSContext* cx, const Sequence<nsString>& aText,
                       ErrorResult& rv)
 {
   WriteCommon(cx, aText, false, rv);
 }
 
-NS_IMETHODIMP
-nsHTMLDocument::Writeln(const nsAString& aText, JSContext *cx)
-{
-  return WriteCommon(cx, aText, true);
-}
-
 void
 nsHTMLDocument::Writeln(JSContext* cx, const Sequence<nsString>& aText,
                         ErrorResult& rv)
 {
   WriteCommon(cx, aText, true, rv);
 }
 
 void
@@ -2062,166 +1900,136 @@ nsHTMLDocument::RemovedForm()
 }
 
 int32_t
 nsHTMLDocument::GetNumFormsSynchronous()
 {
   return mNumForms;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::GetAlinkColor(nsAString& aAlinkColor)
 {
   aAlinkColor.Truncate();
 
   HTMLBodyElement* body = GetBodyElement();
   if (body) {
     body->GetALink(aAlinkColor);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::SetAlinkColor(const nsAString& aAlinkColor)
 {
   HTMLBodyElement* body = GetBodyElement();
   if (body) {
     body->SetALink(aAlinkColor);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::GetLinkColor(nsAString& aLinkColor)
 {
   aLinkColor.Truncate();
 
   HTMLBodyElement* body = GetBodyElement();
   if (body) {
     body->GetLink(aLinkColor);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::SetLinkColor(const nsAString& aLinkColor)
 {
   HTMLBodyElement* body = GetBodyElement();
   if (body) {
     body->SetLink(aLinkColor);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::GetVlinkColor(nsAString& aVlinkColor)
 {
   aVlinkColor.Truncate();
 
   HTMLBodyElement* body = GetBodyElement();
   if (body) {
     body->GetVLink(aVlinkColor);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::SetVlinkColor(const nsAString& aVlinkColor)
 {
   HTMLBodyElement* body = GetBodyElement();
   if (body) {
     body->SetVLink(aVlinkColor);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::GetBgColor(nsAString& aBgColor)
 {
   aBgColor.Truncate();
 
   HTMLBodyElement* body = GetBodyElement();
   if (body) {
     body->GetBgColor(aBgColor);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::SetBgColor(const nsAString& aBgColor)
 {
   HTMLBodyElement* body = GetBodyElement();
   if (body) {
     body->SetBgColor(aBgColor);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::GetFgColor(nsAString& aFgColor)
 {
   aFgColor.Truncate();
 
   HTMLBodyElement* body = GetBodyElement();
   if (body) {
     body->GetText(aFgColor);
   }
-
-  return NS_OK;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::SetFgColor(const nsAString& aFgColor)
 {
   HTMLBodyElement* body = GetBodyElement();
   if (body) {
     body->SetText(aFgColor);
   }
-
-  return NS_OK;
 }
 
 
 nsIHTMLCollection*
 nsHTMLDocument::Embeds()
 {
   if (!mEmbeds) {
     mEmbeds = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::embed, nsGkAtoms::embed);
   }
   return mEmbeds;
 }
 
-NS_IMETHODIMP
-nsHTMLDocument::GetSelection(nsISelection** aReturn)
-{
-  ErrorResult rv;
-  NS_IF_ADDREF(*aReturn = nsDocument::GetSelection(rv));
-  return rv.StealNSResult();
-}
-
-NS_IMETHODIMP
+void
 nsHTMLDocument::CaptureEvents()
 {
   WarnOnceAbout(nsIDocument::eUseOfCaptureEvents);
-  return NS_OK;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::ReleaseEvents()
 {
   WarnOnceAbout(nsIDocument::eUseOfReleaseEvents);
-  return NS_OK;
 }
 
 // Mapped to document.embeds for NS4 compatibility
 nsIHTMLCollection*
 nsHTMLDocument::Plugins()
 {
   return Embeds();
 }
@@ -2426,26 +2234,25 @@ nsHTMLDocument::GenerateParserKey(void)
       // participate in the context of the script that document.open()ed
       // this document.
       return nullptr;
     }
   }
   return script;
 }
 
-NS_IMETHODIMP
+void
 nsHTMLDocument::GetDesignMode(nsAString& aDesignMode)
 {
   if (HasFlag(NODE_IS_EDITABLE)) {
     aDesignMode.AssignLiteral("on");
   }
   else {
     aDesignMode.AssignLiteral("off");
   }
-  return NS_OK;
 }
 
 void
 nsHTMLDocument::MaybeEditingStateChanged()
 {
   if (!mPendingMaybeEditingStateChanged && mMayStartLayout &&
       mUpdateNestLevel == 0 && (mContentEditableCount > 0) != IsEditingOn()) {
     if (nsContentUtils::IsSafeToRunScript()) {
@@ -2888,26 +2695,16 @@ nsHTMLDocument::EditingStateChanged()
       spellCheckSelection->RemoveAllRanges();
     }
   }
   htmlEditor->SyncRealTimeSpell();
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode)
-{
-  ErrorResult rv;
-  SetDesignMode(aDesignMode, nsContentUtils::GetCurrentJSContext()
-                               ? Some(nsContentUtils::SubjectPrincipal())
-                               : Nothing(), rv);
-  return rv.StealNSResult();
-}
-
 void
 nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode,
                               nsIPrincipal& aSubjectPrincipal,
                               ErrorResult& rv)
 {
   SetDesignMode(aDesignMode, Some(&aSubjectPrincipal), rv);
 }
 
@@ -3362,25 +3159,16 @@ nsHTMLDocument::QueryCommandEnabled(cons
     return false;
   }
 
   bool retval;
   rv = cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, &retval);
   return retval;
 }
 
-NS_IMETHODIMP
-nsHTMLDocument::QueryCommandIndeterm(const nsAString & commandID,
-                                     bool *_retval)
-{
-  ErrorResult rv;
-  *_retval = QueryCommandIndeterm(commandID, rv);
-  return rv.StealNSResult();
-}
-
 bool
 nsHTMLDocument::QueryCommandIndeterm(const nsAString& commandID, ErrorResult& rv)
 {
   nsAutoCString cmdToDispatch;
   if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) {
     return false;
   }
 
@@ -3419,24 +3207,16 @@ nsHTMLDocument::QueryCommandIndeterm(con
   // If command does not have a state_mixed value, this call fails and sets
   // retval to false.  This is fine -- we want to return false in that case
   // anyway (bug 738385), so we just don't throw regardless.
   bool retval = false;
   cmdParams->GetBooleanValue("state_mixed", &retval);
   return retval;
 }
 
-NS_IMETHODIMP
-nsHTMLDocument::QueryCommandState(const nsAString & commandID, bool *_retval)
-{
-  ErrorResult rv;
-  *_retval = QueryCommandState(commandID, rv);
-  return rv.StealNSResult();
-}
-
 bool
 nsHTMLDocument::QueryCommandState(const nsAString& commandID, ErrorResult& rv)
 {
   nsAutoCString cmdToDispatch, paramToCheck;
   bool dummy, dummy2;
   if (!ConvertToMidasInternalCommand(commandID, commandID,
                                      cmdToDispatch, paramToCheck,
                                      dummy, dummy2)) {
@@ -3532,25 +3312,16 @@ nsHTMLDocument::QueryCommandSupported(co
     }
   }
 
   // commandID is supported if it can be converted to a Midas command
   nsAutoCString cmdToDispatch;
   return ConvertToMidasInternalCommand(commandID, cmdToDispatch);
 }
 
-NS_IMETHODIMP
-nsHTMLDocument::QueryCommandValue(const nsAString & commandID,
-                                  nsAString &_retval)
-{
-  ErrorResult rv;
-  QueryCommandValue(commandID, _retval, rv);
-  return rv.StealNSResult();
-}
-
 void
 nsHTMLDocument::QueryCommandValue(const nsAString& commandID,
                                   nsAString& aValue,
                                   ErrorResult& rv)
 {
   aValue.Truncate();
 
   nsAutoCString cmdToDispatch, paramStr;
--- a/dom/html/nsHTMLDocument.h
+++ b/dom/html/nsHTMLDocument.h
@@ -4,17 +4,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 nsHTMLDocument_h___
 #define nsHTMLDocument_h___
 
 #include "mozilla/Attributes.h"
 #include "nsDocument.h"
 #include "nsIHTMLDocument.h"
-#include "nsIDOMHTMLDocument.h"
 #include "nsIHTMLCollection.h"
 #include "nsIScriptElement.h"
 #include "nsTArray.h"
 
 #include "PLDHashTable.h"
 #include "nsIHttpChannel.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsThreadUtils.h"
@@ -30,18 +29,17 @@ class nsILoadGroup;
 
 namespace mozilla {
 namespace dom {
 class HTMLAllCollection;
 } // namespace dom
 } // namespace mozilla
 
 class nsHTMLDocument : public nsDocument,
-                       public nsIHTMLDocument,
-                       public nsIDOMHTMLDocument
+                       public nsIHTMLDocument
 {
 public:
   using nsDocument::SetDocumentURI;
   using nsDocument::GetPlugins;
 
   nsHTMLDocument();
   virtual nsresult Init() override;
 
@@ -89,22 +87,16 @@ public:
 
   // And explicitly import the things from nsDocument that we just shadowed
   using nsDocument::GetImplementation;
   using nsDocument::GetTitle;
   using nsDocument::SetTitle;
   using nsDocument::GetLastStyleSheetSet;
   using nsDocument::MozSetImageElement;
 
-  // nsIDOMNode interface
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-
-  // nsIDOMHTMLDocument interface
-  NS_DECL_NSIDOMHTMLDOCUMENT
-
   mozilla::dom::HTMLAllCollection* All();
 
   nsISupports* ResolveName(const nsAString& aName, nsWrapperCache **aCache);
 
   virtual void AddedForm() override;
   virtual void RemovedForm() override;
   virtual int32_t GetNumFormsSynchronous() override;
   virtual void TearingDownEditor() override;
@@ -161,27 +153,26 @@ public:
   virtual void DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const override;
   // DocAddSizeOfIncludingThis is inherited from nsIDocument.
 
   virtual bool WillIgnoreCharsetOverride() override;
 
   // WebIDL API
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     override;
+  void GetDomain(nsAString& aDomain);
   void SetDomain(const nsAString& aDomain, mozilla::ErrorResult& rv);
   bool IsRegistrableDomainSuffixOfOrEqualTo(const nsAString& aHostSuffixString,
                                             const nsACString& aOrigHost);
   void GetCookie(nsAString& aCookie, mozilla::ErrorResult& rv);
   void SetCookie(const nsAString& aCookie, mozilla::ErrorResult& rv);
   void NamedGetter(JSContext* cx, const nsAString& aName, bool& aFound,
                    JS::MutableHandle<JSObject*> aRetval,
                    mozilla::ErrorResult& rv);
   void GetSupportedNames(nsTArray<nsString>& aNames);
-  nsGenericHTMLElement *GetBody();
-  void SetBody(nsGenericHTMLElement* aBody, mozilla::ErrorResult& rv);
   mozilla::dom::HTMLSharedElement *GetHead() {
     return static_cast<mozilla::dom::HTMLSharedElement*>(GetHeadElement());
   }
   nsIHTMLCollection* Images();
   nsIHTMLCollection* Embeds();
   nsIHTMLCollection* Plugins();
   nsIHTMLCollection* Links();
   nsIHTMLCollection* Forms()
@@ -200,17 +191,17 @@ public:
        const nsAString& aFeatures,
        bool aReplace,
        mozilla::ErrorResult& rv);
   void Close(mozilla::ErrorResult& rv);
   void Write(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText,
              mozilla::ErrorResult& rv);
   void Writeln(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText,
                mozilla::ErrorResult& rv);
-  // XPCOM GetDesignMode is fine.
+  void GetDesignMode(nsAString& aDesignMode);
   void SetDesignMode(const nsAString& aDesignMode,
                      nsIPrincipal& aSubjectPrincipal,
                      mozilla::ErrorResult& rv);
   void SetDesignMode(const nsAString& aDesignMode,
                      const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
                      mozilla::ErrorResult& rv);
   bool ExecCommand(const nsAString& aCommandID, bool aDoShowUI,
                    const nsAString& aValue,
@@ -221,29 +212,34 @@ public:
                            mozilla::ErrorResult& rv);
   bool QueryCommandIndeterm(const nsAString& aCommandID,
                             mozilla::ErrorResult& rv);
   bool QueryCommandState(const nsAString& aCommandID, mozilla::ErrorResult& rv);
   bool QueryCommandSupported(const nsAString& aCommandID,
                              mozilla::dom::CallerType aCallerType);
   void QueryCommandValue(const nsAString& aCommandID, nsAString& aValue,
                          mozilla::ErrorResult& rv);
-  // The XPCOM Get/SetFgColor work OK for us, since they never throw.
-  // The XPCOM Get/SetLinkColor work OK for us, since they never throw.
-  // The XPCOM Get/SetVLinkColor work OK for us, since they never throw.
-  // The XPCOM Get/SetALinkColor work OK for us, since they never throw.
-  // The XPCOM Get/SetBgColor work OK for us, since they never throw.
+  void GetFgColor(nsAString& aFgColor);
+  void SetFgColor(const nsAString& aFgColor);
+  void GetLinkColor(nsAString& aLinkColor);
+  void SetLinkColor(const nsAString& aLinkColor);
+  void GetVlinkColor(nsAString& aAvlinkColor);
+  void SetVlinkColor(const nsAString& aVlinkColor);
+  void GetAlinkColor(nsAString& aAlinkColor);
+  void SetAlinkColor(const nsAString& aAlinkColor);
+  void GetBgColor(nsAString& aBgColor);
+  void SetBgColor(const nsAString& aBgColor);
   nsIHTMLCollection* Anchors();
   nsIHTMLCollection* Applets();
   void Clear() const
   {
     // Deprecated
   }
-  // The XPCOM CaptureEvents works fine for us.
-  // The XPCOM ReleaseEvents works fine for us.
+  void CaptureEvents();
+  void ReleaseEvents();
   // We're picking up GetLocation from Document
   already_AddRefed<mozilla::dom::Location> GetLocation() const
   {
     return nsIDocument::GetLocation();
   }
 
   virtual nsHTMLDocument* AsHTMLDocument() override { return this; }
 
@@ -268,18 +264,18 @@ protected:
   static void DocumentWriteTerminationFunc(nsISupports *aRef);
 
   already_AddRefed<nsIURI> GetDomainURI();
   already_AddRefed<nsIURI> CreateInheritingURIForHost(const nsACString& aHostString);
   already_AddRefed<nsIURI> RegistrableDomainSuffixOfInternal(const nsAString& aHostSuffixString,
                                                              nsIURI* aOrigHost);
 
 
-  nsresult WriteCommon(JSContext *cx, const nsAString& aText,
-                       bool aNewlineTerminate);
+  void WriteCommon(JSContext *cx, const nsAString& aText,
+                   bool aNewlineTerminate, mozilla::ErrorResult& aRv);
   // A version of WriteCommon used by WebIDL bindings
   void WriteCommon(JSContext *cx,
                    const mozilla::dom::Sequence<nsString>& aText,
                    bool aNewlineTerminate,
                    mozilla::ErrorResult& rv);
 
   nsresult CreateAndAddWyciwygChannel(void);
   nsresult RemoveWyciwygChannel(void);
@@ -397,12 +393,11 @@ protected:
    * Temporary flag that is set in EndUpdate() to ignore
    * MaybeEditingStateChanged() script runners from a nested scope.
    */
   bool mPendingMaybeEditingStateChanged;
 };
 
 #define NS_HTML_DOCUMENT_INTERFACE_TABLE_BEGIN(_class)                        \
     NS_DOCUMENT_INTERFACE_TABLE_BEGIN(_class)                                 \
-    NS_INTERFACE_TABLE_ENTRY(_class, nsIHTMLDocument)                         \
-    NS_INTERFACE_TABLE_ENTRY(_class, nsIDOMHTMLDocument)
+    NS_INTERFACE_TABLE_ENTRY(_class, nsIHTMLDocument)
 
 #endif /* nsHTMLDocument_h___ */
--- a/dom/html/nsIFormProcessor.h
+++ b/dom/html/nsIFormProcessor.h
@@ -13,17 +13,21 @@
 
 #ifndef nsIFormProcessor_h__
 #define nsIFormProcessor_h__
 
 #include "nsISupports.h"
 #include "nsStringFwd.h"
 #include "nsTArrayForwardDeclare.h"
 
-class nsIDOMHTMLElement;
+namespace mozilla {
+namespace dom {
+class Element;
+}
+}
 
 // {0ae53c0f-8ea2-4916-bedc-717443c3e185}
 #define NS_FORMPROCESSOR_CID \
 { 0x0ae53c0f, 0x8ea2, 0x4916, { 0xbe, 0xdc, 0x71, 0x74, 0x43, 0xc3, 0xe1, 0x85 } }
 
 #define NS_FORMPROCESSOR_CONTRACTID "@mozilla.org/layout/form-processor;1"
 
 // bf8b1986-8800-424b-b1e5-7a2ca8b9e76c
@@ -48,17 +52,17 @@ public:
    * every form submission.
    *
    *   @param aElement element which the attribute/value pair is submitted for
    *   @param aName    value of the form element name attribute about to be submitted
    *   @param aValue   On entry it contains the value about to be submitted for aName.
    *                   On exit it contains the value which will actually be submitted for aName.
    *
    */
-  virtual nsresult ProcessValue(nsIDOMHTMLElement* aElement,
+  virtual nsresult ProcessValue(mozilla::dom::Element* aElement,
                                 const nsAString& aName,
                                 nsAString& aValue) = 0;
 
   /**
    * The same as above, but with the element unpacked so that this can be
    * called as the result of an IPC message.
    */
   virtual nsresult ProcessValueIPC(const nsAString& aOldValue,
--- a/dom/html/test/test_bug389797.html
+++ b/dom/html/test/test_bug389797.html
@@ -36,20 +36,16 @@ function HTML_TAG(aTagName, aImplClass) 
   // inherit from them do.
   interfacesNonClassinfo[aTagName] =
     [ "nsIDOMNode",
       "nsIDOMElement" ];
 
   var interfaceName = "nsIDOM" + getClassName(aTagName);
   if (interfaceName in SpecialPowers.Ci) {  // no nsIDOMHTMLSpanElement
     interfaces[aTagName].push(interfaceName);
-    interfacesNonClassinfo[aTagName].push("nsIDOMHTMLElement");
-  } else {
-    // Inherits directly from nsIDOMHTMLElement.
-    interfaces[aTagName].push("nsIDOMHTMLElement");
   }
 
   var interfaceNameNS = "nsIDOMNS" + getClassName(aTagName);
   if (interfaceNameNS in SpecialPowers.Ci) {
     interfaces[aTagName].push(interfaceNameNS);
   }
 
   if (arguments.length > 2) {
--- a/dom/interfaces/base/domstubs.idl
+++ b/dom/interfaces/base/domstubs.idl
@@ -45,17 +45,16 @@ interface nsIDOMWindowCollection;
 interface nsIDOMScreen;
 
 // Events
 interface nsIDOMEvent;
 interface nsIDOMEventTarget;
 interface nsIDOMEventListener;
 
 // HTML
-interface nsIDOMHTMLElement;
 interface nsIDOMHTMLFormElement;
 interface nsIDOMHTMLHeadElement;
 
 // Range
 interface nsIDOMRange;
 
 // Crypto
 interface nsIDOMCrypto;
--- a/dom/interfaces/core/nsIDOMElement.idl
+++ b/dom/interfaces/core/nsIDOMElement.idl
@@ -22,15 +22,9 @@ interface nsIDOMMozNamedAttrMap;
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-element
  */
 
 [uuid(6289999b-1008-4269-b42a-413ec5a9d3f4)]
 interface nsIDOMElement : nsIDOMNode
 {
-  readonly attribute DOMString        tagName;
-
-  DOMString          getAttribute(in DOMString name);
-  void               setAttribute(in DOMString name, 
-                                  in DOMString value);
-  boolean            hasAttribute(in DOMString name);
 };
--- a/dom/interfaces/core/nsIDOMNode.idl
+++ b/dom/interfaces/core/nsIDOMNode.idl
@@ -1,73 +1,20 @@
 /* -*- 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 "domstubs.idl"
 
-interface nsIVariant;
-
 /**
  * The nsIDOMNode interface is the primary datatype for the entire
  * Document Object Model.
  * It represents a single node in the document tree.
  *
  * For more information on this interface please see
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
 [uuid(cc35b412-009b-46a3-9be0-76448f12548d)]
 interface nsIDOMNode : nsISupports
 {
-  const unsigned short      ELEMENT_NODE       = 1;
-  const unsigned short      ATTRIBUTE_NODE     = 2;
-  const unsigned short      TEXT_NODE          = 3;
-  const unsigned short      CDATA_SECTION_NODE = 4;
-  const unsigned short      ENTITY_REFERENCE_NODE = 5;
-  const unsigned short      ENTITY_NODE        = 6;
-  const unsigned short      PROCESSING_INSTRUCTION_NODE = 7;
-  const unsigned short      COMMENT_NODE       = 8;
-  const unsigned short      DOCUMENT_NODE      = 9;
-  const unsigned short      DOCUMENT_TYPE_NODE = 10;
-  const unsigned short      DOCUMENT_FRAGMENT_NODE = 11;
-  const unsigned short      NOTATION_NODE      = 12;
-
-  readonly attribute DOMString        nodeName;
-           attribute DOMString        nodeValue;
-                                          // raises(DOMException) on setting
-                                          // raises(DOMException) on retrieval
-  readonly attribute unsigned short   nodeType;
-  readonly attribute nsIDOMNode       parentNode;
-  readonly attribute nsIDOMNodeList   childNodes;
-  readonly attribute nsIDOMNode       firstChild;
-  readonly attribute nsIDOMNode       lastChild;
-  readonly attribute nsIDOMNode       previousSibling;
-  readonly attribute nsIDOMNode       nextSibling;
-  // Modified in DOM Level 2:
-  readonly attribute nsIDOMDocument   ownerDocument;
-  nsIDOMNode                removeChild(in nsIDOMNode oldChild)
-                                         raises(DOMException);
-  boolean                   hasChildNodes();
-  // Modified in DOM Level 4:
-  [optional_argc] nsIDOMNode                cloneNode([optional] in boolean deep);
-  // Introduced in DOM Level 2:
-  readonly attribute DOMString        namespaceURI;
-  // Modified in DOM Core
-  readonly attribute DOMString        prefix;
-
-  // Introduced in DOM Level 2:
-  readonly attribute DOMString        localName;
-
-  // DocumentPosition
-  const unsigned short      DOCUMENT_POSITION_DISCONNECTED = 0x01;
-  const unsigned short      DOCUMENT_POSITION_PRECEDING    = 0x02;
-  const unsigned short      DOCUMENT_POSITION_FOLLOWING    = 0x04;
-  const unsigned short      DOCUMENT_POSITION_CONTAINS     = 0x08;
-  const unsigned short      DOCUMENT_POSITION_CONTAINED_BY = 0x10;
-  const unsigned short      DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
-
-  // Introduced in DOM Level 3:
-           attribute DOMString       textContent;
-                                        // raises(DOMException) on setting
-                                        // raises(DOMException) on retrieval
 };
--- a/dom/interfaces/html/moz.build
+++ b/dom/interfaces/html/moz.build
@@ -3,18 +3,16 @@
 # 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/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM")
 
 XPIDL_SOURCES += [
-    'nsIDOMHTMLDocument.idl',
-    'nsIDOMHTMLElement.idl',
     'nsIDOMHTMLFormElement.idl',
     'nsIDOMHTMLInputElement.idl',
     'nsIDOMHTMLMediaElement.idl',
     'nsIDOMMozBrowserFrame.idl',
     'nsIDOMTimeRanges.idl',
     'nsIDOMValidityState.idl',
     'nsIMozBrowserFrame.idl',
 ]
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLDocument.idl
+++ /dev/null
@@ -1,77 +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 "nsIDOMDocument.idl"
-
-/**
- * The nsIDOMHTMLDocument interface is the interface to a [X]HTML
- * document object.
- *
- * @see <http://www.whatwg.org/html/>
- */
-interface nsISelection;
-
-[uuid(cd31e61f-cfc2-4b91-9385-17b6a2d0633d)]
-interface nsIDOMHTMLDocument : nsIDOMDocument
-{
-           attribute DOMString            domain;
-           attribute DOMString            cookie;
-
-  readonly attribute nsISupports          head;
-           attribute nsIDOMHTMLElement    body;
-
-  // If aContentType is not something supported by nsHTMLDocument and
-  // the HTML content sink, trying to write to the document will
-  // probably throw.
-  // Pass aReplace = true to trigger a replacement of the previous
-  // document in session history; pass false for normal history handling.
-  [implicit_jscontext, optional_argc]
-  nsISupports               open([optional] in DOMString aContentTypeOrUrl,
-                                 [optional] in DOMString aReplaceOrName,
-                                 [optional] in DOMString aFeatures);
-  void                      close();
-
-  [implicit_jscontext]
-  void                      write([optional, Null(Stringify)] in DOMString text);
-  [implicit_jscontext]
-  void                      writeln([optional, Null(Stringify)] in DOMString text);
-
-  /**
-   * Midas additions
-   */
-  attribute DOMString       designMode;
-
-  // returns true if the command is in a indeterminate state (false otherwise)
-  boolean                   queryCommandIndeterm(in DOMString commandID);
-
-  // returns true if the command has been executed (false otherwise)
-  boolean                   queryCommandState(in DOMString commandID);
-
-  // returns the current value of the document or current selection for command
-  DOMString                 queryCommandValue(in DOMString commandID);
-
-
-  // Obsolete APIs
-           attribute DOMString            fgColor;
-           attribute DOMString            bgColor;
-           attribute DOMString            linkColor;
-           attribute DOMString            vlinkColor;
-           attribute DOMString            alinkColor;
-
-  void                      clear();
-
-
-  // DOM Range
-  nsISelection                getSelection();
-
-
-  // More obsolete APIs
-  /**
-   * @deprecated These are old Netscape 4 methods. Do not use,
-   *             the implementation is no-op.
-   */
-  void                      captureEvents();
-  void                      releaseEvents();
-};
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLElement.idl
+++ /dev/null
@@ -1,32 +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 "nsIDOMElement.idl"
-#include "nsIVariant.idl"
-
-interface nsIDOMHTMLMenuElement;
-
-/**
- * The nsIDOMHTMLElement interface is the primary [X]HTML element
- * interface. It represents a single [X]HTML element in the document
- * tree.
- *
- * This interface is trying to follow the DOM Level 2 HTML specification:
- * http://www.w3.org/TR/DOM-Level-2-HTML/
- *
- * with changes from the work-in-progress WHATWG HTML specification:
- * http://www.whatwg.org/specs/web-apps/current-work/
- */
-[uuid(b0c42392-d0e7-4f6a-beb5-a698ce648945)]
-interface nsIDOMHTMLElement : nsIDOMElement
-{
-  readonly attribute boolean          draggable;
-  readonly attribute boolean          spellcheck;
-
-
-  // CSSOM View
-  readonly attribute long             offsetWidth;
-  readonly attribute long             offsetHeight;
-};
--- a/dom/interfaces/html/nsIDOMHTMLFormElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLFormElement.idl
@@ -1,14 +1,14 @@
 /* -*- 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 "nsIDOMHTMLElement.idl"
+#include "nsISupports.idl"
 
 /**
  * The nsIDOMHTMLFormElement interface is the interface to a [X]HTML
  * form element.
  *
  * This interface is trying to follow the DOM Level 2 HTML specification:
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  *
--- a/dom/interfaces/html/nsIDOMHTMLInputElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLInputElement.idl
@@ -1,18 +1,19 @@
 /* -*- 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 "nsIDOMHTMLElement.idl"
+#include "nsISupports.idl"
 
 interface nsIControllers;
 interface nsIDOMFileList;
 interface nsIDOMValidityState;
+interface nsIDOMHTMLFormElement;
 
  /**
   * The nsIDOMHTMLInputElement interface is the interface to a [X]HTML
   * input element.
   *
   * This interface is trying to follow the DOM Level 2 HTML specification:
   * http://www.w3.org/TR/DOM-Level-2-HTML/
   *
@@ -25,16 +26,14 @@ interface nsIDOMHTMLInputElement : nsISu
 {
   readonly attribute DOMString             autocomplete;
            attribute boolean               checked;
   readonly attribute nsIDOMHTMLFormElement form;
            attribute DOMString             formAction;
 
            attribute boolean               indeterminate;
 
-  readonly attribute nsIDOMHTMLElement     list;
-
            attribute DOMString             name;
 
            attribute boolean               readOnly;
 
-  readonly attribute nsIControllers        controllers;	
+  readonly attribute nsIControllers        controllers;
 };
--- a/dom/interfaces/html/nsIDOMHTMLMediaElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLMediaElement.idl
@@ -1,15 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "nsIDOMHTMLElement.idl"
 #include "nsIDOMTimeRanges.idl"
 
 /**
  * The nsIDOMHTMLMediaElement interface is an interface to be implemented by the HTML
  * <audio> and <video> elements.
  *
  * For more information on this interface, please see
  * http://www.whatwg.org/specs/web-apps/current-work/#htmlmediaelement
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -206,17 +206,16 @@
 
 #include "ClearOnShutdown.h"
 #include "ProcessUtils.h"
 #include "URIUtils.h"
 #include "nsContentUtils.h"
 #include "nsIPrincipal.h"
 #include "DomainPolicy.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
-#include "mozilla/dom/time/DateCacheCleaner.h"
 #include "mozilla/ipc/CrashReporterClient.h"
 #include "mozilla/net/NeckoMessageUtils.h"
 #include "mozilla/widget/PuppetBidiKeyboard.h"
 #include "mozilla/RemoteSpellCheckEngineChild.h"
 #include "GMPServiceChild.h"
 #include "GfxInfoBase.h"
 #include "gfxPlatform.h"
 #include "nscore.h" // for NS_FREE_PERMANENT_DATA
@@ -1217,19 +1216,16 @@ ContentChild::InitXPCOM(const XPCOMInitD
     ProcessGlobal* global = ProcessGlobal::Get();
     global->SetInitialProcessData(data);
   }
 
   // The stylesheet cache is not ready yet. Store this URL for future use.
   nsCOMPtr<nsIURI> ucsURL = DeserializeURI(aXPCOMInit.userContentSheetURL());
   nsLayoutStylesheetCache::SetUserContentCSSURL(ucsURL);
 
-  // This will register cross-process observer.
-  mozilla::dom::time::InitializeDateCacheCleaner();
-
   GfxInfoBase::SetFeatureStatus(aXPCOMInit.gfxFeatureStatus());
 
   DataStorage::SetCachedStorageEntries(aXPCOMInit.dataStorage());
 
   // Set the dynamic scalar definitions for this process.
   TelemetryIPC::AddDynamicScalarDefinitions(aXPCOMInit.dynamicScalarDefs());
 
   DOMPrefs::Initialize();
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -52,17 +52,16 @@
 #include "mozilla/dom/PCycleCollectWithLogsParent.h"
 #include "mozilla/dom/ServiceWorkerRegistrar.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/Permissions.h"
 #include "mozilla/dom/PresentationParent.h"
 #include "mozilla/dom/PPresentationParent.h"
 #include "mozilla/dom/PushNotifier.h"
 #include "mozilla/dom/quota/QuotaManagerService.h"
-#include "mozilla/dom/time/DateCacheCleaner.h"
 #include "mozilla/dom/URLClassifierParent.h"
 #include "mozilla/embedding/printingui/PrintingParent.h"
 #include "mozilla/extensions/StreamFilterParent.h"
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/hal_sandbox/PHalParent.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundParent.h"
@@ -623,18 +622,16 @@ ContentParent::StartUp()
 
   if (!XRE_IsParentProcess()) {
     return;
   }
 
   // Note: This reporter measures all ContentParents.
   RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
 
-  mozilla::dom::time::InitializeDateCacheCleaner();
-
   BackgroundChild::Startup();
   ClientManager::Startup();
 
   sDisableUnsafeCPOWWarnings = PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS");
 
 #if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
   sSandboxBrokerPolicyFactory = MakeUnique<SandboxBrokerPolicyFactory>();
 #endif
--- a/dom/mathml/nsMathMLElement.h
+++ b/dom/mathml/nsMathMLElement.h
@@ -32,21 +32,16 @@ class nsMathMLElement final : public nsM
 {
 public:
   explicit nsMathMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
   explicit nsMathMLElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
 
   // Implementation of nsISupports is inherited from nsMathMLElementBase
   NS_DECL_ISUPPORTS_INHERITED
 
-  // Forward implementations of parent interfaces of nsMathMLElement to
-  // our base class
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
-
   nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                       nsIContent* aBindingParent,
                       bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -654,35 +654,31 @@ GMPChild::ActorDestroy(ActorDestroyReaso
   CrashReporterClient::DestroySingleton();
 
   XRE_ShutdownChildProcess();
 }
 
 void
 GMPChild::ProcessingError(Result aCode, const char* aReason)
 {
-  if (!aReason) {
-    aReason = "";
-  }
-
   switch (aCode) {
     case MsgDropped:
       _exit(0); // Don't trigger a crash report.
     case MsgNotKnown:
-      MOZ_CRASH_UNSAFE_PRINTF("aborting because of MsgNotKnown, reason(%s)", aReason);
+      MOZ_CRASH("aborting because of MsgNotKnown");
     case MsgNotAllowed:
-      MOZ_CRASH_UNSAFE_PRINTF("aborting because of MsgNotAllowed, reason(%s)", aReason);
+      MOZ_CRASH("aborting because of MsgNotAllowed");
     case MsgPayloadError:
-      MOZ_CRASH_UNSAFE_PRINTF("aborting because of MsgPayloadError, reason(%s)", aReason);
+      MOZ_CRASH("aborting because of MsgPayloadError");
     case MsgProcessingError:
-      MOZ_CRASH_UNSAFE_PRINTF("aborting because of MsgProcessingError, reason(%s)", aReason);
+      MOZ_CRASH("aborting because of MsgProcessingError");
     case MsgRouteError:
-      MOZ_CRASH_UNSAFE_PRINTF("aborting because of MsgRouteError, reason(%s)", aReason);
+      MOZ_CRASH("aborting because of MsgRouteError");
     case MsgValueError:
-      MOZ_CRASH_UNSAFE_PRINTF("aborting because of MsgValueError, reason(%s)", aReason);
+      MOZ_CRASH("aborting because of MsgValueError");
     default:
       MOZ_CRASH("not reached");
   }
 }
 
 PGMPTimerChild*
 GMPChild::AllocPGMPTimerChild()
 {
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -69,17 +69,16 @@ DIRS += [
     'notification',
     'offline',
     'power',
     'push',
     'quota',
     'security',
     'storage',
     'svg',
-    'time',
     'locales',
     'network',
     'permission',
     'plugins/base',
     'plugins/ipc',
     'indexedDB',
     'system',
     'ipc',
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -13,18 +13,17 @@
 #include "nsCSPContext.h"
 #include "nsCSPParser.h"
 #include "nsCSPService.h"
 #include "nsError.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
-#include "nsIDOMHTMLDocument.h"
-#include "nsIDOMHTMLElement.h"
+#include "nsIDOMDocument.h"
 #include "nsIDOMNode.h"
 #include "nsIHttpChannel.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
@@ -46,16 +45,17 @@
 #include "mozilla/dom/CSPReportBinding.h"
 #include "mozilla/dom/CSPDictionariesBinding.h"
 #include "mozilla/net/ReferrerPolicy.h"
 #include "nsINetworkInterceptController.h"
 #include "nsSandboxFlags.h"
 #include "nsIScriptElement.h"
 #include "nsIEventTarget.h"
 #include "mozilla/dom/DocGroup.h"
+#include "mozilla/dom/Element.h"
 #include "nsXULAppAPI.h"
 
 using namespace mozilla;
 
 static LogModule*
 GetCspContextLog()
 {
   static LazyLogModule gCspContextPRLog("CSPContext");
@@ -184,20 +184,20 @@ nsCSPContext::ShouldLoad(nsContentPolicy
     return NS_OK;
   }
 
   nsAutoString nonce;
   bool parserCreated = false;
   if (!isPreload) {
     if (aContentType == nsIContentPolicy::TYPE_SCRIPT ||
         aContentType == nsIContentPolicy::TYPE_STYLESHEET) {
-      nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aRequestContext);
-      if (htmlElement) {
-        rv = htmlElement->GetAttribute(NS_LITERAL_STRING("nonce"), nonce);
-        NS_ENSURE_SUCCESS(rv, rv);
+      nsCOMPtr<Element> element = do_QueryInterface(aRequestContext);
+      if (element && element->IsHTMLElement()) {
+        // XXXbz What about SVG elements that can have nonce?
+        element->GetAttribute(NS_LITERAL_STRING("nonce"), nonce);
       }
     }
 
     nsCOMPtr<nsIScriptElement> script = do_QueryInterface(aRequestContext);
     if (script && script->GetParserCreated() != mozilla::dom::NOT_FROM_PARSER) {
       parserCreated = true;
     }
   }
--- a/dom/security/nsContentSecurityManager.cpp
+++ b/dom/security/nsContentSecurityManager.cpp
@@ -4,16 +4,17 @@
  * 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 "nsContentSecurityManager.h"
 #include "nsEscape.h"
 #include "nsDataHandler.h"
 #include "nsIChannel.h"
 #include "nsIHttpChannelInternal.h"
+#include "nsINode.h"
 #include "nsIStreamListener.h"
 #include "nsILoadInfo.h"
 #include "nsIOService.h"
 #include "nsContentUtils.h"
 #include "nsCORSListenerProxy.h"
 #include "nsIStreamListener.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIURIFixup.h"
@@ -337,17 +338,17 @@ DoContentSecurityChecks(nsIChannel* aCha
     }
 
     case nsIContentPolicy::TYPE_XMLHTTPREQUEST: {
       // alias nsIContentPolicy::TYPE_DATAREQUEST:
       requestingContext = aLoadInfo->LoadingNode();
 #ifdef DEBUG
       {
         nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
-        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+        MOZ_ASSERT(!node || node->NodeType() == nsINode::DOCUMENT_NODE,
                    "type_xml requires requestingContext of type Document");
       }
 #endif
       // We're checking for the external TYPE_XMLHTTPREQUEST here in case
       // an addon creates a request with that type.
       if (internalContentPolicyType ==
             nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST ||
           internalContentPolicyType ==
@@ -364,30 +365,30 @@ DoContentSecurityChecks(nsIChannel* aCha
     }
 
     case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: {
       mimeTypeGuess = EmptyCString();
       requestingContext = aLoadInfo->LoadingNode();
 #ifdef DEBUG
       {
         nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
-        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE,
+        MOZ_ASSERT(!node || node->NodeType() == nsINode::ELEMENT_NODE,
                    "type_subrequest requires requestingContext of type Element");
       }
 #endif
       break;
     }
 
     case nsIContentPolicy::TYPE_DTD: {
       mimeTypeGuess = EmptyCString();
       requestingContext = aLoadInfo->LoadingNode();
 #ifdef DEBUG
       {
         nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
-        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+        MOZ_ASSERT(!node || node->NodeType() == nsINode::DOCUMENT_NODE,
                    "type_dtd requires requestingContext of type Document");
       }
 #endif
       break;
     }
 
     case nsIContentPolicy::TYPE_FONT: {
       mimeTypeGuess = EmptyCString();
@@ -401,17 +402,17 @@ DoContentSecurityChecks(nsIChannel* aCha
       }
       else {
         mimeTypeGuess = EmptyCString();
       }
       requestingContext = aLoadInfo->LoadingNode();
 #ifdef DEBUG
       {
         nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
-        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE,
+        MOZ_ASSERT(!node || node->NodeType() == nsINode::ELEMENT_NODE,
                    "type_media requires requestingContext of type Element");
       }
 #endif
       break;
     }
 
     case nsIContentPolicy::TYPE_WEBSOCKET: {
       // Websockets have to use the proxied URI:
@@ -435,30 +436,30 @@ DoContentSecurityChecks(nsIChannel* aCha
     }
 
     case nsIContentPolicy::TYPE_XSLT: {
       mimeTypeGuess = NS_LITERAL_CSTRING("application/xml");
       requestingContext = aLoadInfo->LoadingNode();
 #ifdef DEBUG
       {
         nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
-        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+        MOZ_ASSERT(!node || node->NodeType() == nsINode::DOCUMENT_NODE,
                    "type_xslt requires requestingContext of type Document");
       }
 #endif
       break;
     }
 
     case nsIContentPolicy::TYPE_BEACON: {
       mimeTypeGuess = EmptyCString();
       requestingContext = aLoadInfo->LoadingNode();
 #ifdef DEBUG
       {
         nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
-        MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+        MOZ_ASSERT(!node || node->NodeType() == nsINode::DOCUMENT_NODE,
                    "type_beacon requires requestingContext of type Document");
       }
 #endif
       break;
     }
 
     case nsIContentPolicy::TYPE_FETCH: {
       mimeTypeGuess = EmptyCString();
--- a/dom/svg/nsSVGElement.h
+++ b/dom/svg/nsSVGElement.h
@@ -129,18 +129,16 @@ public:
   static const MappedAttributeEntry sViewportsMap[];
   static const MappedAttributeEntry sMarkersMap[];
   static const MappedAttributeEntry sColorMap[];
   static const MappedAttributeEntry sFiltersMap[];
   static const MappedAttributeEntry sFEFloodMap[];
   static const MappedAttributeEntry sLightingEffectsMap[];
   static const MappedAttributeEntry sMaskMap[];
 
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
   NS_DECL_NSIDOMSVGELEMENT
 
   NS_IMPL_FROMCONTENT(nsSVGElement, kNameSpaceID_SVG)
 
   // Gets the element that establishes the rectangular viewport against which
   // we should resolve percentage lengths (our "coordinate context"). Returns
   // nullptr for outer <svg> or SVG without an <svg> parent (invalid SVG).
   mozilla::dom::SVGViewportElement* GetCtx() const;
deleted file mode 100644
--- a/dom/time/DateCacheCleaner.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 "DateCacheCleaner.h"
-
-#include "js/Date.h"
-#include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/Hal.h"
-#include "mozilla/StaticPtr.h"
-
-using namespace mozilla::hal;
-
-namespace mozilla {
-namespace dom {
-namespace time {
-
-class DateCacheCleaner : public SystemTimezoneChangeObserver
-{
-public:
-  DateCacheCleaner()
-  {
-    RegisterSystemTimezoneChangeObserver(this);
-  }
-
-  ~DateCacheCleaner()
-  {
-    UnregisterSystemTimezoneChangeObserver(this);
-  }
-
-  void Notify(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo) override
-  {
-    JS::ResetTimeZone();
-  }
-
-};
-
-StaticAutoPtr<DateCacheCleaner> sDateCacheCleaner;
-
-void
-InitializeDateCacheCleaner()
-{
-  if (!sDateCacheCleaner) {
-    sDateCacheCleaner = new DateCacheCleaner();
-    ClearOnShutdown(&sDateCacheCleaner);
-  }
-}
-
-} // namespace time
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/time/DateCacheCleaner.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-/*
- * InitializeDateCacheCleaner registers DateCacheCleaner to
- * SystemTimeChangeObserver. When time zone is changed, DateCacheCleaner calls
- * JS::ResetTimeZone to update the time zone information.
- */
-
-namespace mozilla {
-namespace dom {
-namespace time {
-void InitializeDateCacheCleaner();
-} //namespace time
-} //namespace dom
-} //namespace mozilla
deleted file mode 100644
--- a/dom/time/TimeChangeObserver.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 "TimeChangeObserver.h"
-#include "mozilla/Hal.h"
-#include "mozilla/Observer.h"
-#include "mozilla/HalTypes.h"
-#include "nsWeakPtr.h"
-#include "nsTObserverArray.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/Services.h"
-#include "mozilla/StaticPtr.h"
-#include "nsPIDOMWindow.h"
-#include "nsContentUtils.h"
-#include "nsIObserverService.h"
-#include "nsIDocument.h"
-
-using namespace mozilla;
-using namespace mozilla::hal;
-using namespace mozilla::services;
-
-class nsSystemTimeChangeObserver : public SystemClockChangeObserver,
-                                   public SystemTimezoneChangeObserver
-{
-  typedef nsTObserverArray<nsWeakPtr> ListenerArray;
-public:
-  static nsSystemTimeChangeObserver* GetInstance();
-  virtual ~nsSystemTimeChangeObserver();
-
-  // Implementing hal::SystemClockChangeObserver::Notify()
-  void Notify(const int64_t& aClockDeltaMS) override;
-
-  // Implementing hal::SystemTimezoneChangeObserver::Notify()
-  void Notify(
-    const mozilla::hal::SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo) override;
-
-  nsresult AddWindowListenerImpl(nsPIDOMWindowInner* aWindow);
-  nsresult RemoveWindowListenerImpl(nsPIDOMWindowInner* aWindow);
-
-private:
-  nsSystemTimeChangeObserver() { };
-  ListenerArray mWindowListeners;
-  void FireMozTimeChangeEvent();
-};
-
-StaticAutoPtr<nsSystemTimeChangeObserver> sObserver;
-
-nsSystemTimeChangeObserver* nsSystemTimeChangeObserver::GetInstance()
-{
-  if (!sObserver) {
-    sObserver = new nsSystemTimeChangeObserver();
-    ClearOnShutdown(&sObserver);
-  }
-  return sObserver;
-}
-
-nsSystemTimeChangeObserver::~nsSystemTimeChangeObserver()
-{
-  UnregisterSystemClockChangeObserver(this);
-  UnregisterSystemTimezoneChangeObserver(this);
-}
-
-void
-nsSystemTimeChangeObserver::FireMozTimeChangeEvent()
-{
-  ListenerArray::ForwardIterator iter(mWindowListeners);
-  while (iter.HasMore()) {
-    nsWeakPtr weakWindow = iter.GetNext();
-    nsCOMPtr<nsPIDOMWindowInner> innerWindow = do_QueryReferent(weakWindow);
-    nsCOMPtr<nsPIDOMWindowOuter> outerWindow;
-    nsCOMPtr<nsIDocument> document;
-    if (!innerWindow ||
-        !(document = innerWindow->GetExtantDoc()) ||
-        !(outerWindow = innerWindow->GetOuterWindow())) {
-      mWindowListeners.RemoveElement(weakWindow);
-      continue;
-    }
-
-    nsContentUtils::DispatchTrustedEvent(document, outerWindow,
-      NS_LITERAL_STRING("moztimechange"), /* bubbles = */ true,
-      /* canceable = */ false);
-  }
-}
-
-void
-nsSystemTimeChangeObserver::Notify(const int64_t& aClockDeltaMS)
-{
-  // Notify observers that the system clock has been adjusted.
-  nsCOMPtr<nsIObserverService> observerService = GetObserverService();
-  if (observerService) {
-    nsString dataStr;
-    dataStr.AppendFloat(static_cast<double>(aClockDeltaMS));
-    observerService->NotifyObservers(
-      nullptr, "system-clock-change", dataStr.get());
-  }
-
-  FireMozTimeChangeEvent();
-}
-
-void
-nsSystemTimeChangeObserver::Notify(
-  const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
-{
-  FireMozTimeChangeEvent();
-}
-
-nsresult
-mozilla::time::AddWindowListener(nsPIDOMWindowInner* aWindow)
-{
-  return nsSystemTimeChangeObserver::GetInstance()->AddWindowListenerImpl(aWindow);
-}
-
-nsresult
-nsSystemTimeChangeObserver::AddWindowListenerImpl(nsPIDOMWindowInner* aWindow)
-{
-  if (!aWindow) {
-    return NS_ERROR_ILLEGAL_VALUE;
-  }
-
-  nsWeakPtr windowWeakRef = do_GetWeakReference(aWindow);
-  NS_ASSERTION(windowWeakRef, "nsIDOMWindow implementations shuld support weak ref");
-
-  if (mWindowListeners.IndexOf(windowWeakRef) !=
-      ListenerArray::array_type::NoIndex) {
-    return NS_OK;
-  }
-
-  if (mWindowListeners.IsEmpty()) {
-    RegisterSystemClockChangeObserver(sObserver);
-    RegisterSystemTimezoneChangeObserver(sObserver);
-  }
-
-  mWindowListeners.AppendElement(windowWeakRef);
-  return NS_OK;
-}
-
-nsresult
-mozilla::time::RemoveWindowListener(nsPIDOMWindowInner* aWindow)
-{
-  if (!sObserver) {
-    return NS_OK;
-  }
-
-  return nsSystemTimeChangeObserver::GetInstance()->RemoveWindowListenerImpl(aWindow);
-}
-
-nsresult
-nsSystemTimeChangeObserver::RemoveWindowListenerImpl(nsPIDOMWindowInner* aWindow)
-{
-  if (!aWindow) {
-    return NS_OK;
-  }
-
-  nsWeakPtr windowWeakRef = do_GetWeakReference(aWindow);
-  mWindowListeners.RemoveElement(windowWeakRef);
-
-  if (mWindowListeners.IsEmpty()) {
-    UnregisterSystemClockChangeObserver(sObserver);
-    UnregisterSystemTimezoneChangeObserver(sObserver);
-  }
-
-  return NS_OK;
-}
deleted file mode 100644
--- a/dom/time/TimeChangeObserver.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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_time_change_observer_h_
-#define _mozilla_time_change_observer_h_
-
-#include "nscore.h"
-
-class nsPIDOMWindowInner;
-
-namespace mozilla {
-namespace time {
-
-nsresult AddWindowListener(nsPIDOMWindowInner* aWindow);
-nsresult RemoveWindowListener(nsPIDOMWindowInner* aWindow);
-
-} // namespace time
-} // namespace mozilla
-
-#endif //_mozilla_time_change_observer_h_
deleted file mode 100644
--- a/dom/time/TimeManager.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 "TimeManager.h"
-
-#include "mozilla/dom/Date.h"
-#include "mozilla/dom/MozTimeManagerBinding.h"
-#include "nsITimeService.h"
-#include "nsServiceManagerUtils.h"
-
-namespace mozilla {
-namespace dom {
-namespace time {
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TimeManager)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(TimeManager)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(TimeManager)
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TimeManager, mWindow)
-
-JSObject*
-TimeManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return MozTimeManagerBinding::Wrap(aCx, this, aGivenProto);
-}
-
-void
-TimeManager::Set(Date& aDate)
-{
-  Set(aDate.ToDouble());
-}
-
-void
-TimeManager::Set(double aTime)
-{
-  nsCOMPtr<nsITimeService> timeService = do_GetService(TIMESERVICE_CONTRACTID);
-  if (timeService) {
-    timeService->Set(aTime);
-  }
-}
-
-} // namespace time
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/time/TimeManager.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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_time_TimeManager_h
-#define mozilla_dom_time_TimeManager_h
-
-#include "mozilla/Attributes.h"
-#include "nsISupports.h"
-#include "nsPIDOMWindow.h"
-#include "nsWrapperCache.h"
-
-namespace mozilla {
-namespace dom {
-
-class Date;
-
-namespace time {
-
-class TimeManager final : public nsISupports
-                        , public nsWrapperCache
-{
-public:
-  static bool PrefEnabled(JSContext* aCx, JSObject* aGlobal)
-  {
-#ifdef MOZ_TIME_MANAGER
-    return true;
-#else
-    return false;
-#endif
-  }
-
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TimeManager)
-
-  explicit TimeManager(nsPIDOMWindowInner* aWindow)
-    : mWindow(aWindow)
-  {
-  }
-
-  nsPIDOMWindowInner* GetParentObject() const
-  {
-    return mWindow;
-  }
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
-  void Set(Date& aDate);
-  void Set(double aTime);
-
-private:
-  ~TimeManager() {}
-
-  nsCOMPtr<nsPIDOMWindowInner> mWindow;
-};
-
-} // namespace time
-} // namespace dom
-} // namespace mozilla
-
-#endif //mozilla_dom_time_TimeManager_h
deleted file mode 100644
--- a/dom/time/TimeService.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 "base/basictypes.h"
-#include "jsapi.h"
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/Hal.h"
-#include "TimeService.h"
-
-namespace mozilla {
-namespace dom {
-namespace time {
-
-NS_IMPL_ISUPPORTS(TimeService, nsITimeService)
-
-/* static */ StaticRefPtr<TimeService> TimeService::sSingleton;
-
-/* static */ already_AddRefed<TimeService>
-TimeService::GetInstance()
-{
-  if (!sSingleton) {
-    sSingleton = new TimeService();
-    ClearOnShutdown(&sSingleton);
-  }
-  RefPtr<TimeService> service = sSingleton.get();
-  return service.forget();
-}
-
-NS_IMETHODIMP
-TimeService::Set(int64_t aTimeInMS) {
-  hal::AdjustSystemClock(aTimeInMS - (JS_Now() / PR_USEC_PER_MSEC));
-  return NS_OK;
-}
-
-} // namespace time
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/time/TimeService.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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_time_TimeService_h
-#define mozilla_dom_time_TimeService_h
-
-#include "mozilla/StaticPtr.h"
-#include "nsITimeService.h"
-
-namespace mozilla {
-namespace dom {
-namespace time {
-
-/**
- * This class implements a service which lets us modify the system clock time.
- */
-class TimeService : public nsITimeService
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSITIMESERVICE
-
-  static already_AddRefed<TimeService> GetInstance();
-
-private:
-  virtual ~TimeService() {};
-
-  static StaticRefPtr<TimeService> sSingleton;
-};
-
-} // namespace time
-} // namespace dom
-} // namespace mozilla
-
-#endif //mozilla_dom_time_TimeService_h
deleted file mode 100644
--- a/dom/time/moz.build
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-with Files("**"):
-    BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
-
-XPIDL_SOURCES += [
-    'nsITimeService.idl',
-]
-
-XPIDL_MODULE = 'dom_time'
-
-EXPORTS.mozilla.dom.time += [
-    'DateCacheCleaner.h',
-    'TimeChangeObserver.h',
-    'TimeManager.h',
-    'TimeService.h',
-]
-
-UNIFIED_SOURCES += [
-    'DateCacheCleaner.cpp',
-    'TimeChangeObserver.cpp',
-    'TimeManager.cpp',
-    'TimeService.cpp',
-]
-
-include('/ipc/chromium/chromium-config.mozbuild')
-
-FINAL_LIBRARY = 'xul'
deleted file mode 100644
--- a/dom/time/nsITimeService.idl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* 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 "nsISupports.idl"
-
-%{C++
-#define NS_TIMESERVICE_CID { 0x80d6f9cc, 0xf16d, 0x40c3, { 0xa5, 0x2e, 0xc4, 0xe6, 0x56, 0xe3, 0x65, 0xb4 } }
-#define TIMESERVICE_CONTRACTID "@mozilla.org/time/timeservice;1"
-%}
-
-[scriptable, builtinclass, uuid(1fc7fde2-0090-11e2-bdd6-0fea4b9f41f8)]
-interface nsITimeService : nsISupports
-{
-  /* Set the system time.
-   *
-   * The |aTimeInMS| argument is the time in milliseconds since the epoch.
-   */
-  void set(in int64_t aTimeInMS);
-};
--- a/dom/url/URLWorker.cpp
+++ b/dom/url/URLWorker.cpp
@@ -704,24 +704,32 @@ URLWorker::GetHref(nsAString& aHref, Err
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHref, aHref,
                        mURLProxy);
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::SetHref(const nsAString& aHref, ErrorResult& aRv)
 {
+  SetHrefInternal(aHref, eUseProxyIfNeeded, aRv);
+}
+
+void
+URLWorker::SetHrefInternal(const nsAString& aHref, Strategy aStrategy,
+                           ErrorResult& aRv)
+{
   nsAutoCString scheme;
   nsresult rv = net_ExtractURLScheme(NS_ConvertUTF16toUTF8(aHref), scheme);
   if (NS_FAILED(rv)) {
     aRv.ThrowTypeError<MSG_INVALID_URL>(aHref);
     return;
   }
 
-  if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) {
+  if (aStrategy == eUseProxyIfNeeded &&
+      (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))) {
     nsCOMPtr<nsIURI> uri;
     aRv = NS_MutateURI(new nsStandardURL::Mutator())
             .SetSpec(NS_ConvertUTF16toUTF8(aHref))
             .Finalize(uri);
     mStdURL = static_cast<net::nsStandardURL*>(uri.get());
     if (mURLProxy) {
       mWorkerPrivate->AssertIsOnWorkerThread();
 
@@ -802,37 +810,51 @@ URLWorker::GetProtocol(nsAString& aProto
                        mURLProxy);
 
   runnable->Dispatch(aRv);
 }
 
 void
 URLWorker::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv)
 {
+  nsAString::const_iterator start, end;
+  aProtocol.BeginReading(start);
+  aProtocol.EndReading(end);
+  nsAString::const_iterator iter(start);
+
+  FindCharInReadable(':', iter, end);
+  NS_ConvertUTF16toUTF8 scheme(Substring(start, iter));
+
+  // If we are using nsStandardURL on the owning thread, we can continue only if
+  // the scheme is http or https.
+  if (mStdURL &&
+      (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))) {
+    mStdURL->SetScheme(scheme);
+    return;
+  }
+
+  // If we are using mStandardURL but the new scheme is not http nor https, we
+  // have to migrate to the URL proxy.
   if (mStdURL) {
-    nsAString::const_iterator start, end;
-    aProtocol.BeginReading(start);
-    aProtocol.EndReading(end);
-    nsAString::const_iterator iter(start);
-
-    FindCharInReadable(':', iter, end);
-
-    nsresult rv = mStdURL->SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)));
+    nsAutoCString href;
+    nsresult rv = mStdURL->GetSpec(href);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
 
-    nsAutoCString href;
-    rv = mStdURL->GetSpec(href);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
+    SetHrefInternal(NS_ConvertUTF8toUTF16(href), eAlwaysUseProxy, aRv);
+    if (NS_WARN_IF(aRv.Failed())) {
       return;
     }
 
-    SetHref(NS_ConvertUTF8toUTF16(href), aRv);
-    return;
+    // We want a proxy here.
+    MOZ_ASSERT(!mStdURL);
+    MOZ_ASSERT(mURLProxy);
+
+    // Now we can restart setting the protocol.
   }
 
   MOZ_ASSERT(mURLProxy);
   RefPtr<SetterRunnable> runnable =
     new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterProtocol,
                        aProtocol, mURLProxy);
 
   runnable->Dispatch(aRv);
--- a/dom/url/URLWorker.h
+++ b/dom/url/URLWorker.h
@@ -117,16 +117,26 @@ public:
   virtual void UpdateURLSearchParams() override;
 
   virtual void
   SetSearchInternal(const nsAString& aSearch, ErrorResult& aRv) override;
 
 private:
   ~URLWorker();
 
+  enum Strategy {
+    eAlwaysUseProxy,
+    eUseProxyIfNeeded,
+  };
+
+  void
+  SetHrefInternal(const nsAString& aHref,
+                  Strategy aStrategy,
+                  ErrorResult& aRv);
+
   workers::WorkerPrivate* mWorkerPrivate;
   RefPtr<URLProxy> mURLProxy;
   RefPtr<net::nsStandardURL> mStdURL;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/url/tests/mochitest.ini
+++ b/dom/url/tests/mochitest.ini
@@ -16,8 +16,10 @@ support-files =
 [test_urlSearchParams_utf8.html]
 [test_urlutils_stringify.html]
 [test_worker_url.html]
 [test_worker_urlApi.html]
 [test_worker_url_exceptions.html]
 [test_worker_urlSearchParams.html]
 [test_unknown_url_origin.html]
 [test_bloburl_location.html]
+[test_worker_protocol.html]
+support-files = protocol_worker.js
new file mode 100644
--- /dev/null
+++ b/dom/url/tests/protocol_worker.js
@@ -0,0 +1,25 @@
+function ok(a, msg) {
+  postMessage({ type: "status", status: !!a, msg });
+}
+
+function is(a, b, msg) {
+  ok(a === b, msg);
+}
+
+function finish() {
+  postMessage({ type: "finish" });
+}
+
+let url = new URL("http://example.com");
+is(url.protocol, "http:", "http: expected");
+
+url.protocol = "https:";
+is(url.protocol, "https:", "http: -> https:");
+
+url.protocol = "ftp:";
+is(url.protocol, "ftp:", "https: -> ftp:");
+
+url.protocol = "https:";
+is(url.protocol, "https:", "ftp: -> https:");
+
+finish();
new file mode 100644
--- /dev/null
+++ b/dom/url/tests/test_worker_protocol.html
@@ -0,0 +1,41 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for URL protocol setter in workers</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+  let worker = new Worker("protocol_worker.js");
+
+  worker.onmessage = function(event) {
+    is(event.target, worker, "Correct worker");
+
+    if (event.data.type == "finish") {
+      SimpleTest.finish();
+      return;
+    }
+
+    if (event.data.type == "status") {
+      ok(event.data.status, event.data.msg);
+      return;
+    }
+
+    ok(false, "Invalid message.");
+  };
+
+  SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
+++ b/dom/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
@@ -2,16 +2,17 @@
  * 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 "WebBrowserPersistLocalDocument.h"
 #include "WebBrowserPersistDocumentParent.h"
 
 #include "mozilla/dom/Attr.h"
+#include "mozilla/dom/Comment.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLAnchorElement.h"
 #include "mozilla/dom/HTMLAreaElement.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "mozilla/dom/HTMLLinkElement.h"
 #include "mozilla/dom/HTMLObjectElement.h"
 #include "mozilla/dom/HTMLOptionElement.h"
 #include "mozilla/dom/HTMLSharedElement.h"
@@ -22,17 +23,16 @@
 #include "nsContentCID.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMAttributeMap.h"
 #include "nsFrameLoader.h"
 #include "nsIComponentRegistrar.h"
 #include "nsIContent.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMDocument.h"
-#include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIDOMHTMLMediaElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeFilter.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMProcessingInstruction.h"
 #include "nsIDOMTreeWalker.h"
 #include "nsIDOMWindowUtils.h"
@@ -592,22 +592,25 @@ private:
     nsClassHashtable<nsCStringHashKey, nsCString> mMap;
     nsCOMPtr<nsIURI> mCurrentBaseURI;
     nsCOMPtr<nsIURI> mTargetBaseURI;
 
     bool IsFlagSet(uint32_t aFlag) const {
         return mParent->GetPersistFlags() & aFlag;
     }
 
-    nsresult GetNodeToFixup(nsIDOMNode* aNodeIn, nsIDOMNode** aNodeOut);
+    // Helper for XPCOM FixupNode.
+    nsresult FixupNode(nsINode *aNodeIn, bool *aSerializeCloneKids,
+                       nsINode **aNodeOut);
+    nsresult GetNodeToFixup(nsINode* aNodeIn, nsINode** aNodeOut);
     nsresult FixupURI(nsAString& aURI);
-    nsresult FixupAttribute(nsIDOMNode* aNode,
+    nsresult FixupAttribute(nsINode* aNode,
                             const char* aAttribute,
                             const char* aNamespaceURI = "");
-    nsresult FixupAnchor(nsIDOMNode* aNode);
+    nsresult FixupAnchor(nsINode* aNode);
     nsresult FixupXMLStyleSheetLink(nsIDOMProcessingInstruction* aPI,
                                     const nsAString& aHref);
 
     using IWBP = nsIWebBrowserPersist;
 };
 
 NS_IMPL_ISUPPORTS(PersistNodeFixup, nsIDocumentEncoderNodeFixup)
 
@@ -632,29 +635,30 @@ PersistNodeFixup::PersistNodeFixup(WebBr
             if (NS_SUCCEEDED(rv)) {
                 mMap.Put(urlFrom, urlTo);
             }
         }
     }
 }
 
 nsresult
-PersistNodeFixup::GetNodeToFixup(nsIDOMNode *aNodeIn, nsIDOMNode **aNodeOut)
+PersistNodeFixup::GetNodeToFixup(nsINode *aNodeIn, nsINode **aNodeOut)
 {
     // Avoid mixups in FixupNode that could leak objects; this goes
     // against the usual out parameter convention, but it's a private
     // method so shouldn't be a problem.
     MOZ_ASSERT(!*aNodeOut);
 
     if (!IsFlagSet(IWBP::PERSIST_FLAGS_FIXUP_ORIGINAL_DOM)) {
-        nsresult rv = aNodeIn->CloneNode(false, 1, aNodeOut);
-        NS_ENSURE_SUCCESS(rv, rv);
-    } else {
-        NS_ADDREF(*aNodeOut = aNodeIn);
+        ErrorResult rv;
+        *aNodeOut = aNodeIn->CloneNode(false, rv).take();
+        return rv.StealNSResult();
     }
+
+    NS_ADDREF(*aNodeOut = aNodeIn);
     return NS_OK;
 }
 
 nsresult
 PersistNodeFixup::FixupURI(nsAString &aURI)
 {
     // get the current location of the file (absolutized)
     nsCOMPtr<nsIURI> uri;
@@ -672,22 +676,22 @@ PersistNodeFixup::FixupURI(nsAString &aU
     }
     if (!replacement->IsEmpty()) {
         aURI = NS_ConvertUTF8toUTF16(*replacement);
     }
     return NS_OK;
 }
 
 nsresult
-PersistNodeFixup::FixupAttribute(nsIDOMNode* aNode,
+PersistNodeFixup::FixupAttribute(nsINode* aNode,
                                  const char* aAttribute,
                                  const char* aNamespaceURI)
 {
-    nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
-    MOZ_ASSERT(element);
+    MOZ_ASSERT(aNode->IsElement());
+    dom::Element* element = aNode->AsElement();
 
     RefPtr<nsDOMAttributeMap> attrMap = element->Attributes();
 
     NS_ConvertASCIItoUTF16 attribute(aAttribute);
     NS_ConvertASCIItoUTF16 namespaceURI(aNamespaceURI);
     RefPtr<dom::Attr> attr = attrMap->GetNamedItemNS(namespaceURI, attribute);
     nsresult rv = NS_OK;
     if (attr) {
@@ -699,24 +703,24 @@ PersistNodeFixup::FixupAttribute(nsIDOMN
             attr->SetValue(uri, err);
         }
     }
 
     return rv;
 }
 
 nsresult
-PersistNodeFixup::FixupAnchor(nsIDOMNode *aNode)
+PersistNodeFixup::FixupAnchor(nsINode *aNode)
 {
     if (IsFlagSet(IWBP::PERSIST_FLAGS_DONT_FIXUP_LINKS)) {
         return NS_OK;
     }
 
-    nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
-    MOZ_ASSERT(element);
+    MOZ_ASSERT(aNode->IsElement());
+    dom::Element* element = aNode->AsElement();
 
     RefPtr<nsDOMAttributeMap> attrMap = element->Attributes();
 
     // Make all anchor links absolute so they point off onto the Internet
     nsString attribute(NS_LITERAL_STRING("href"));
     RefPtr<dom::Attr> attr = attrMap->GetNamedItem(attribute);
     if (attr) {
         nsString oldValue;
@@ -850,35 +854,53 @@ PersistNodeFixup::FixupXMLStyleSheetLink
     return rv;
 }
 
 NS_IMETHODIMP
 PersistNodeFixup::FixupNode(nsIDOMNode *aNodeIn,
                             bool *aSerializeCloneKids,
                             nsIDOMNode **aNodeOut)
 {
+    nsCOMPtr<nsINode> nodeIn = do_QueryInterface(aNodeIn);
+    nsCOMPtr<nsINode> nodeOut;
+    nsresult rv = FixupNode(nodeIn, aSerializeCloneKids,
+                            getter_AddRefs(nodeOut));
+    // FixupNode can return NS_OK and a null outparam, so check
+    // the actual value we got before dereferencing it.
+    if (nodeOut) {
+      NS_ADDREF(*aNodeOut = nodeOut->AsDOMNode());
+    } else {
+      *aNodeOut = nullptr;
+    }
+
+    return rv;
+}
+
+nsresult
+PersistNodeFixup::FixupNode(nsINode* aNodeIn,
+                            bool* aSerializeCloneKids,
+                            nsINode** aNodeOut)
+{
     *aNodeOut = nullptr;
     *aSerializeCloneKids = false;
 
-    uint16_t type;
-    nsresult rv = aNodeIn->GetNodeType(&type);
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (type != nsIDOMNode::ELEMENT_NODE &&
-        type != nsIDOMNode::PROCESSING_INSTRUCTION_NODE) {
+    uint16_t type = aNodeIn->NodeType();
+    if (type != nsINode::ELEMENT_NODE &&
+        type != nsINode::PROCESSING_INSTRUCTION_NODE) {
         return NS_OK;
     }
 
     // Fixup xml-stylesheet processing instructions
     nsCOMPtr<nsIDOMProcessingInstruction> nodeAsPI = do_QueryInterface(aNodeIn);
     if (nodeAsPI) {
         nsAutoString target;
         nodeAsPI->GetTarget(target);
         if (target.EqualsLiteral("xml-stylesheet"))
         {
-            rv = GetNodeToFixup(aNodeIn, aNodeOut);
+            nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
             if (NS_SUCCEEDED(rv) && *aNodeOut) {
                 nsCOMPtr<nsIDOMProcessingInstruction> outNode =
                     do_QueryInterface(*aNodeOut);
                 nsAutoString href;
                 GetXMLStyleSheetLink(nodeAsPI, href);
                 if (!href.IsEmpty()) {
                     FixupURI(href);
                     FixupXMLStyleSheetLink(outNode, href);
@@ -891,222 +913,214 @@ PersistNodeFixup::FixupNode(nsIDOMNode *
     nsCOMPtr<nsIContent> content = do_QueryInterface(aNodeIn);
     if (!content) {
         return NS_OK;
     }
 
     // BASE elements are replaced by a comment so relative links are not hosed.
     if (!IsFlagSet(IWBP::PERSIST_FLAGS_NO_BASE_TAG_MODIFICATIONS) &&
         content->IsHTMLElement(nsGkAtoms::base)) {
-        nsCOMPtr<nsIDOMDocument> ownerDocument;
         // Base uses HTMLSharedElement, which would be awkward to implement
         // FromContent on, since it represents multiple elements. Since we've
         // already checked IsHTMLElement here, just cast as we were doing.
         auto* base = static_cast<dom::HTMLSharedElement*>(content.get());
-        base->GetOwnerDocument(getter_AddRefs(ownerDocument));
-        if (ownerDocument) {
-            nsAutoString href;
-            base->GetHref(href); // Doesn't matter if this fails
-            nsCOMPtr<nsIDOMComment> comment;
-            nsAutoString commentText;
-            commentText.AssignLiteral(" base ");
-            if (!href.IsEmpty()) {
-                commentText += NS_LITERAL_STRING("href=\"") + href
-                    + NS_LITERAL_STRING("\" ");
-            }
-            rv = ownerDocument->CreateComment(commentText,
-                                              getter_AddRefs(comment));
-            if (comment) {
-                return CallQueryInterface(comment, aNodeOut);
-            }
+        nsIDocument* ownerDoc = base->OwnerDoc();
+
+        nsAutoString href;
+        base->GetHref(href); // Doesn't matter if this fails
+        nsAutoString commentText;
+        commentText.AssignLiteral(" base ");
+        if (!href.IsEmpty()) {
+            commentText += NS_LITERAL_STRING("href=\"") + href
+                + NS_LITERAL_STRING("\" ");
         }
+        *aNodeOut = ownerDoc->CreateComment(commentText).take();
         return NS_OK;
     }
 
     // Fix up href and file links in the elements
     RefPtr<dom::HTMLAnchorElement> nodeAsAnchor = dom::HTMLAnchorElement::FromContent(content);
     if (nodeAsAnchor) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAnchor(*aNodeOut);
         }
         return rv;
     }
 
     RefPtr<dom::HTMLAreaElement> nodeAsArea = dom::HTMLAreaElement::FromContent(content);
     if (nodeAsArea) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAnchor(*aNodeOut);
         }
         return rv;
     }
 
     if (content->IsHTMLElement(nsGkAtoms::body)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "background");
         }
         return rv;
     }
 
     if (content->IsHTMLElement(nsGkAtoms::table)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "background");
         }
         return rv;
     }
 
     if (content->IsHTMLElement(nsGkAtoms::tr)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "background");
         }
         return rv;
     }
 
     if (content->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "background");
         }
         return rv;
     }
 
     if (content->IsHTMLElement(nsGkAtoms::img)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             // Disable image loads
             nsCOMPtr<nsIImageLoadingContent> imgCon =
                 do_QueryInterface(*aNodeOut);
             if (imgCon) {
                 imgCon->SetLoadingEnabled(false);
             }
             FixupAnchor(*aNodeOut);
             FixupAttribute(*aNodeOut, "src");
         }
         return rv;
     }
 
     nsCOMPtr<nsIDOMHTMLMediaElement> nodeAsMedia = do_QueryInterface(aNodeIn);
     if (nodeAsMedia) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "src");
         }
         return rv;
     }
 
     if (content->IsHTMLElement(nsGkAtoms::source)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "src");
         }
         return rv;
     }
 
     if (content->IsSVGElement(nsGkAtoms::img)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             // Disable image loads
             nsCOMPtr<nsIImageLoadingContent> imgCon =
                 do_QueryInterface(*aNodeOut);
             if (imgCon)
                 imgCon->SetLoadingEnabled(false);
 
             // FixupAnchor(*aNodeOut);  // XXXjwatt: is this line needed?
             FixupAttribute(*aNodeOut, "href", "http://www.w3.org/1999/xlink");
         }
         return rv;
     }
 
     if (content->IsHTMLElement(nsGkAtoms::script)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "src");
         }
         return rv;
     }
 
     if (content->IsSVGElement(nsGkAtoms::script)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "href", "http://www.w3.org/1999/xlink");
         }
         return rv;
     }
 
     if (content->IsHTMLElement(nsGkAtoms::embed)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "src");
         }
         return rv;
     }
 
     if (content->IsHTMLElement(nsGkAtoms::object)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "data");
         }
         return rv;
     }
 
     if (content->IsHTMLElement(nsGkAtoms::link)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             // First see if the link represents linked content
             rv = FixupAttribute(*aNodeOut, "href");
             if (NS_FAILED(rv)) {
                 // Perhaps this link is actually an anchor to related content
                 FixupAnchor(*aNodeOut);
             }
             // TODO if "type" attribute == "text/css"
             //        fixup stylesheet
         }
         return rv;
     }
 
     if (content->IsHTMLElement(nsGkAtoms::frame)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "src");
         }
         return rv;
     }
 
     if (content->IsHTMLElement(nsGkAtoms::iframe)) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "src");
         }
         return rv;
     }
 
     RefPtr<dom::HTMLInputElement> nodeAsInput =
         dom::HTMLInputElement::FromContentOrNull(content);
     if (nodeAsInput) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             // Disable image loads
             nsCOMPtr<nsIImageLoadingContent> imgCon =
                 do_QueryInterface(*aNodeOut);
             if (imgCon) {
                 imgCon->SetLoadingEnabled(false);
             }
 
             FixupAttribute(*aNodeOut, "src");
 
             nsAutoString valueStr;
             NS_NAMED_LITERAL_STRING(valueAttr, "value");
             // Update element node attributes with user-entered form state
-            nsCOMPtr<nsIContent> content = do_QueryInterface(*aNodeOut);
             RefPtr<dom::HTMLInputElement> outElt =
-              dom::HTMLInputElement::FromContentOrNull(content);
+                dom::HTMLInputElement::FromContent((*aNodeOut)->AsContent());
             nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(*aNodeOut);
             switch (formControl->ControlType()) {
                 case NS_FORM_INPUT_EMAIL:
                 case NS_FORM_INPUT_SEARCH:
                 case NS_FORM_INPUT_TEXT:
                 case NS_FORM_INPUT_TEL:
                 case NS_FORM_INPUT_URL:
                 case NS_FORM_INPUT_NUMBER:
@@ -1115,17 +1129,18 @@ PersistNodeFixup::FixupNode(nsIDOMNode *
                 case NS_FORM_INPUT_TIME:
                 case NS_FORM_INPUT_COLOR:
                     nodeAsInput->GetValue(valueStr, dom::CallerType::System);
                     // Avoid superfluous value="" serialization
                     if (valueStr.IsEmpty()) {
                       IgnoredErrorResult ignored;
                       outElt->RemoveAttribute(valueAttr, ignored);
                     } else {
-                      outElt->SetAttribute(valueAttr, valueStr);
+                      IgnoredErrorResult ignored;
+                      outElt->SetAttribute(valueAttr, valueStr, ignored);
                     }
                     break;
                 case NS_FORM_INPUT_CHECKBOX:
                 case NS_FORM_INPUT_RADIO:
                     {
                         bool checked = nodeAsInput->Checked();
                         IgnoredErrorResult ignored;
                         outElt->SetDefaultChecked(checked, ignored);
@@ -1135,35 +1150,36 @@ PersistNodeFixup::FixupNode(nsIDOMNode *
                     break;
             }
         }
         return rv;
     }
 
     dom::HTMLTextAreaElement* nodeAsTextArea = dom::HTMLTextAreaElement::FromContent(content);
     if (nodeAsTextArea) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             // Tell the document encoder to serialize the text child we create below
             *aSerializeCloneKids = true;
 
             nsAutoString valueStr;
             nodeAsTextArea->GetValue(valueStr);
 
-            (*aNodeOut)->SetTextContent(valueStr);
+            IgnoredErrorResult err;
+            (*aNodeOut)->SetTextContent(valueStr, err);
         }
         return rv;
     }
 
     dom::HTMLOptionElement* nodeAsOption = dom::HTMLOptionElement::FromContent(content);
     if (nodeAsOption) {
-        rv = GetNodeToFixup(aNodeIn, aNodeOut);
+        nsresult rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
-            nsCOMPtr<nsIContent> outContent = do_QueryInterface(*aNodeOut);
-            dom::HTMLOptionElement* outElt = dom::HTMLOptionElement::FromContent(outContent);
+            dom::HTMLOptionElement* outElt =
+                dom::HTMLOptionElement::FromContent((*aNodeOut)->AsContent());
             bool selected = nodeAsOption->Selected();
             IgnoredErrorResult ignored;
             outElt->SetDefaultSelected(selected, ignored);
         }
         return rv;
     }
 
     return NS_OK;
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -1,14 +1,15 @@
 /* -*- 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/.
  *
- * http://dxr.mozilla.org/mozilla-central/source/dom/interfaces/core/nsIDOMDocument.idl
+ * https://dom.spec.whatwg.org/#interface-document
+ * https://html.spec.whatwg.org/multipage/dom.html#the-document-object
  */
 
 interface WindowProxy;
 interface nsISupports;
 interface URI;
 interface nsIDocShell;
 interface nsILoadGroup;
 
@@ -17,17 +18,17 @@ enum VisibilityState { "hidden", "visibl
 /* https://dom.spec.whatwg.org/#dictdef-elementcreationoptions */
 dictionary ElementCreationOptions {
   DOMString is;
 
   [ChromeOnly]
   DOMString pseudo;
 };
 
-/* http://dom.spec.whatwg.org/#interface-document */
+/* https://dom.spec.whatwg.org/#interface-document */
 [Constructor]
 interface Document : Node {
   [Throws]
   readonly attribute DOMImplementation implementation;
   [Pure, Throws, BinaryName="documentURIFromJS", NeedsCallerType]
   readonly attribute DOMString URL;
   [Pure, Throws, BinaryName="documentURIFromJS", NeedsCallerType]
   readonly attribute DOMString documentURI;
@@ -100,32 +101,33 @@ interface Document : Node {
   Attr createAttributeNS(DOMString? namespace, DOMString name);
 
   // Allows setting innerHTML without automatic sanitization.
   // Do not use this.
   [ChromeOnly]
   attribute boolean allowUnsafeHTML;
 };
 
-// http://www.whatwg.org/specs/web-apps/current-work/#the-document-object
+// https://html.spec.whatwg.org/multipage/dom.html#the-document-object
 partial interface Document {
   [PutForwards=href, Unforgeable] readonly attribute Location? location;
   //(HTML only)         attribute DOMString domain;
   readonly attribute DOMString referrer;
   //(HTML only)         attribute DOMString cookie;
   readonly attribute DOMString lastModified;
   readonly attribute DOMString readyState;
 
   // DOM tree accessors
   //(Not proxy yet)getter object (DOMString name);
   [CEReactions, SetterThrows, Pure]
            attribute DOMString title;
   [CEReactions, Pure]
            attribute DOMString dir;
-  //(HTML only)         attribute HTMLElement? body;
+  [CEReactions, Pure, SetterThrows]
+           attribute HTMLElement? body;
   //(HTML only)readonly attribute HTMLHeadElement? head;
   //(HTML only)readonly attribute HTMLCollection images;
   //(HTML only)readonly attribute HTMLCollection embeds;
   //(HTML only)readonly attribute HTMLCollection plugins;
   //(HTML only)readonly attribute HTMLCollection links;
   //(HTML only)readonly attribute HTMLCollection forms;
   //(HTML only)readonly attribute HTMLCollection scripts;
   [Pure]
--- a/dom/webidl/HTMLDocument.webidl
+++ b/dom/webidl/HTMLDocument.webidl
@@ -8,18 +8,16 @@
 interface HTMLDocument : Document {
            [SetterThrows]
            attribute DOMString? domain;
            [Throws]
            attribute DOMString cookie;
   // DOM tree accessors
   [Throws]
   getter object (DOMString name);
-  [CEReactions, Pure, SetterThrows]
-           attribute HTMLElement? body;
   [Pure]
   readonly attribute HTMLHeadElement? head;
   [Pure]
   readonly attribute HTMLCollection images;
   [Pure]
   readonly attribute HTMLCollection embeds;
   [Pure]
   readonly attribute HTMLCollection plugins;
deleted file mode 100644
--- a/dom/webidl/MozTimeManager.webidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* 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/. */
-
-[Func="mozilla::dom::time::TimeManager::PrefEnabled"]
-interface MozTimeManager {
-  /* Set the system time.
-   *
-   * The |time| argument can be either a Date object or a number.
-   *
-   * - If |time| is a number, it's interpreted as milliseconds
-   *   since the epoch (midnight UTC on January 1, 1970).
-   * - If |time| is a Date object, |set(time)| is equivalent to
-   *   |set(time.getTime())|.
-   */
-  void set(Date time);
-  void set(double time);
-};
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -229,24 +229,16 @@ partial interface Navigator {
   [ChromeOnly, Pref="dom.vr.enabled"]
   void requestVRPresentation(VRDisplay display);
 };
 partial interface Navigator {
   [Pref="dom.vr.test.enabled"]
   VRServiceTest requestVRServiceTest();
 };
 
-#ifdef MOZ_TIME_MANAGER
-// nsIDOMMozNavigatorTime
-partial interface Navigator {
-  [Throws, ChromeOnly]
-  readonly attribute MozTimeManager mozTime;
-};
-#endif // MOZ_TIME_MANAGER
-
 callback NavigatorUserMediaSuccessCallback = void (MediaStream stream);
 callback NavigatorUserMediaErrorCallback = void (MediaStreamError error);
 
 partial interface Navigator {
   [Throws, Func="Navigator::HasUserMediaSupport"]
   readonly attribute MediaDevices mediaDevices;
 
   // Deprecated. Use mediaDevices.getUserMedia instead.
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -206,19 +206,16 @@ with Files("*Record*"):
     BUG_COMPONENT = ("Core", "Audio/Video: Recording")
 
 with Files("Media*Track*"):
     BUG_COMPONENT = ("Core", "WebRTC: Audio/Video")
 
 with Files("Mouse*"):
     BUG_COMPONENT = ("Core", "DOM: Events")
 
-with Files("MozTimeManager.webidl"):
-    BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
-
 with Files("MutationEvent.webidl"):
     BUG_COMPONENT = ("Core", "DOM: Events")
 
 with Files("NativeOSFileInternals.webidl"):
     BUG_COMPONENT = ("Toolkit", "OS.File")
 
 with Files("Net*"):
     BUG_COMPONENT = ("Core", "Networking")
@@ -359,17 +356,16 @@ with Files("Worker*"):
     BUG_COMPONENT = ("Core", "DOM: Workers")
 
 GENERATED_WEBIDL_FILES = [
     'CSS2Properties.webidl',
 ]
 
 PREPROCESSED_WEBIDL_FILES = [
     'ChromeUtils.webidl',
-    'Navigator.webidl',
     'Node.webidl',
     'Window.webidl',
 ]
 
 WEBIDL_FILES = [
     'AbortController.webidl',
     'AbortSignal.webidl',
     'AbstractWorker.webidl',
@@ -685,21 +681,21 @@ WEBIDL_FILES = [
     'MessagePort.webidl',
     'MimeType.webidl',
     'MimeTypeArray.webidl',
     'MouseEvent.webidl',
     'MouseScrollEvent.webidl',
     'MozStorageAsyncStatementParams.webidl',
     'MozStorageStatementParams.webidl',
     'MozStorageStatementRow.webidl',
-    'MozTimeManager.webidl',
     'MutationEvent.webidl',
     'MutationObserver.webidl',
     'NamedNodeMap.webidl',
     'NativeOSFileInternals.webidl',
+    'Navigator.webidl',
     'NetDashboard.webidl',
     'NetworkInformation.webidl',
     'NetworkOptions.webidl',
     'NodeFilter.webidl',
     'NodeIterator.webidl',
     'NodeList.webidl',
     'Notification.webidl',
     'NotificationEvent.webidl',
--- a/dom/xbl/nsXBLContentSink.cpp
+++ b/dom/xbl/nsXBLContentSink.cpp
@@ -917,17 +917,17 @@ nsXBLContentSink::AddAttributesToXULProt
                                    getter_AddRefs(localName), &nameSpaceID);
 
     if (nameSpaceID == kNameSpaceID_None) {
       attrs[i].mName.SetTo(localName);
     }
     else {
       RefPtr<NodeInfo> ni;
       ni = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
-                                         nsIDOMNode::ATTRIBUTE_NODE);
+                                         nsINode::ATTRIBUTE_NODE);
       attrs[i].mName.SetTo(ni);
     }
 
     rv = aElement->SetAttrAt(i, nsDependentString(aAtts[i * 2 + 1]),
                              mDocumentURI);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -1239,17 +1239,17 @@ nsXBLPrototypeBinding::ReadContentNode(n
   if (!prefix.IsEmpty())
     prefixAtom = NS_Atomize(prefix);
 
   rv = aStream->ReadString(tag);
   NS_ENSURE_SUCCESS(rv, rv);
 
   RefPtr<nsAtom> tagAtom = NS_Atomize(tag);
   RefPtr<NodeInfo> nodeInfo =
-    aNim->GetNodeInfo(tagAtom, prefixAtom, namespaceID, nsIDOMNode::ELEMENT_NODE);
+    aNim->GetNodeInfo(tagAtom, prefixAtom, namespaceID, nsINode::ELEMENT_NODE);
 
   uint32_t attrCount;
   rv = aStream->Read32(&attrCount);
   NS_ENSURE_SUCCESS(rv, rv);
 
   RefPtr<Element> element;
   // Create XUL prototype elements, or regular elements for other namespaces.
   // This needs to match the code in nsXBLContentSink::CreateElement.
@@ -1287,17 +1287,17 @@ nsXBLPrototypeBinding::ReadContentNode(n
       }
       else {
         RefPtr<nsAtom> prefixAtom;
         if (!prefix.IsEmpty())
           prefixAtom = NS_Atomize(prefix);
 
         RefPtr<NodeInfo> ni =
           aNim->GetNodeInfo(nameAtom, prefixAtom,
-                            namespaceID, nsIDOMNode::ATTRIBUTE_NODE);
+                            namespaceID, nsINode::ATTRIBUTE_NODE);
         attrs[i].mName.SetTo(ni);
       }
 
       rv = prototype->SetAttrAt(i, val, documentURI);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     nsresult rv =
@@ -1380,23 +1380,23 @@ nsXBLPrototypeBinding::WriteContentNode(
                                         nsIContent* aNode)
 {
   nsresult rv;
 
   if (!aNode->IsElement()) {
     // Text is writen out as a single byte for the type, followed by the text.
     uint8_t type = XBLBinding_Serialize_NoContent;
     switch (aNode->NodeType()) {
-      case nsIDOMNode::TEXT_NODE:
+      case nsINode::TEXT_NODE:
         type = XBLBinding_Serialize_TextNode;
         break;
-      case nsIDOMNode::CDATA_SECTION_NODE:
+      case nsINode::CDATA_SECTION_NODE:
         type = XBLBinding_Serialize_CDATANode;
         break;
-      case nsIDOMNode::COMMENT_NODE:
+      case nsINode::COMMENT_NODE:
         type = XBLBinding_Serialize_CommentNode;
         break;
       default:
         break;
     }
 
     rv = aStream->Write8(type);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/xml/CDATASection.h
+++ b/dom/xml/CDATASection.h
@@ -14,43 +14,40 @@ namespace mozilla {
 namespace dom {
 
 class CDATASection final : public Text,
                            public nsIDOMText
 {
 private:
   void Init()
   {
-    MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE,
+    MOZ_ASSERT(mNodeInfo->NodeType() == CDATA_SECTION_NODE,
                "Bad NodeType in aNodeInfo");
   }
 
   virtual ~CDATASection();
 
 public:
   explicit CDATASection(already_AddRefed<mozilla::dom::NodeInfo> aNodeInfo)
     : Text(aNodeInfo)
   {
     Init();
   }
 
   explicit CDATASection(nsNodeInfoManager* aNodeInfoManager)
     : Text(aNodeInfoManager->GetNodeInfo(nsGkAtoms::cdataTagName,
                                          nullptr, kNameSpaceID_None,
-                                         nsIDOMNode::CDATA_SECTION_NODE))
+                                         CDATA_SECTION_NODE))
   {
     Init();
   }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-
   // nsIDOMCharacterData
   NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
   using nsGenericDOMDataNode::SetData; // Prevent hiding overloaded virtual function.
 
   // nsIDOMText
   NS_FORWARD_NSIDOMTEXT(nsGenericDOMDataNode::)
 
   // nsINode
--- a/dom/xml/ProcessingInstruction.cpp
+++ b/dom/xml/ProcessingInstruction.cpp
@@ -29,33 +29,33 @@ NS_NewXMLProcessingInstruction(nsNodeInf
     RefPtr<XMLStylesheetProcessingInstruction> pi =
       new XMLStylesheetProcessingInstruction(aNodeInfoManager, aData);
     return pi.forget();
   }
 
   RefPtr<mozilla::dom::NodeInfo> ni;
   ni = aNodeInfoManager->GetNodeInfo(nsGkAtoms::processingInstructionTagName,
                                      nullptr, kNameSpaceID_None,
-                                     nsIDOMNode::PROCESSING_INSTRUCTION_NODE,
+                                     nsINode::PROCESSING_INSTRUCTION_NODE,
                                      target);
 
   RefPtr<ProcessingInstruction> instance =
     new ProcessingInstruction(ni.forget(), aData);
 
   return instance.forget();
 }
 
 namespace mozilla {
 namespace dom {
 
 ProcessingInstruction::ProcessingInstruction(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
                                              const nsAString& aData)
   : nsGenericDOMDataNode(Move(aNodeInfo))
 {
-  MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::PROCESSING_INSTRUCTION_NODE,
+  MOZ_ASSERT(mNodeInfo->NodeType() == nsINode::PROCESSING_INSTRUCTION_NODE,
              "Bad NodeType in aNodeInfo");
 
   SetTextInternal(0, mText.GetLength(),
                   aData.BeginReading(), aData.Length(),
                   false);  // Don't notify (bug 420429).
 }
 
 ProcessingInstruction::~ProcessingInstruction()
--- a/dom/xml/ProcessingInstruction.h
+++ b/dom/xml/ProcessingInstruction.h
@@ -20,19 +20,16 @@ class ProcessingInstruction : public nsG
 {
 public:
   ProcessingInstruction(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
                         const nsAString& aData);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-
   // nsIDOMCharacterData
   NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
   using nsGenericDOMDataNode::SetData; // Prevent hiding overloaded virtual function.
 
   // nsIDOMProcessingInstruction
   NS_DECL_NSIDOMPROCESSINGINSTRUCTION
 
   // nsINode
--- a/dom/xml/XMLStylesheetProcessingInstruction.h
+++ b/dom/xml/XMLStylesheetProcessingInstruction.h
@@ -26,17 +26,17 @@ public:
   {
   }
 
   XMLStylesheetProcessingInstruction(nsNodeInfoManager* aNodeInfoManager,
                                      const nsAString& aData)
     : ProcessingInstruction(aNodeInfoManager->GetNodeInfo(
                                        nsGkAtoms::processingInstructionTagName,
                                        nullptr, kNameSpaceID_None,
-                                       nsIDOMNode::PROCESSING_INSTRUCTION_NODE,
+                                       PROCESSING_INSTRUCTION_NODE,
                                        nsGkAtoms::xml_stylesheet), aData)
   {
   }
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
--- a/dom/xml/nsXMLContentSink.cpp
+++ b/dom/xml/nsXMLContentSink.cpp
@@ -981,17 +981,17 @@ nsXMLContentSink::HandleStartElement(con
                                  getter_AddRefs(localName), &nameSpaceID);
 
   if (!OnOpenContainer(aAtts, aAttsCount, nameSpaceID, localName, aLineNumber)) {
     return NS_OK;
   }
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   result = CreateElement(aAtts, aAttsCount, nodeInfo, aLineNumber,
                          getter_AddRefs(content), &appendContent,
                          FROM_PARSER_NETWORK);
   NS_ENSURE_SUCCESS(result, result);
 
   // Have to do this before we push the new content on the stack... and have to
   // do that before we set attributes, call BindToTree, etc.  Ideally we'd push
@@ -1363,25 +1363,18 @@ nsXMLContentSink::ReportError(const char
   // XXX need to stop scripts here -- hsivonen
 
   // stop observing in order to avoid crashing when removing content
   mDocument->RemoveObserver(this);
   mIsDocumentObserver = false;
 
   // Clear the current content
   mDocumentChildren.Clear();
-  nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mDocument));
-  if (node) {
-    for (;;) {
-      nsCOMPtr<nsIDOMNode> child, dummy;
-      node->GetLastChild(getter_AddRefs(child));
-      if (!child)
-        break;
-      node->RemoveChild(child, getter_AddRefs(dummy));
-    }
+  while (mDocument->GetLastChild()) {
+    mDocument->GetLastChild()->Remove();
   }
   mDocElement = nullptr;
 
   // Clear any buffered-up text we have.  It's enough to set the length to 0.
   // The buffer itself is allocated when we're created and deleted in our
   // destructor, so don't mess with it.
   mTextLength = 0;
 
--- a/dom/xml/nsXMLElement.h
+++ b/dom/xml/nsXMLElement.h
@@ -19,22 +19,16 @@ public:
   explicit nsXMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : mozilla::dom::Element(aNodeInfo)
   {
   }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-
-  // nsIDOMElement
-  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
-
   // nsINode interface methods
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   virtual nsIDOMNode* AsDOMNode() override { return this; }
 
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
--- a/dom/xml/nsXMLFragmentContentSink.cpp
+++ b/dom/xml/nsXMLFragmentContentSink.cpp
@@ -311,25 +311,18 @@ nsXMLFragmentContentSink::ReportError(co
           NS_LossyConvertUTF16toASCII(aErrorText).get(),
           NS_LossyConvertUTF16toASCII(aSourceText).get());
 #endif
 
   // The following code is similar to the cleanup in nsXMLContentSink::ReportError()
   mState = eXMLContentSinkState_InProlog;
 
   // Clear the current content
-  nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mRoot));
-  if (node) {
-    for (;;) {
-      nsCOMPtr<nsIDOMNode> child, dummy;
-      node->GetLastChild(getter_AddRefs(child));
-      if (!child)
-        break;
-      node->RemoveChild(child, getter_AddRefs(dummy));
-    }
+  while (mRoot->GetLastChild()) {
+    mRoot->GetLastChild()->Remove();
   }
 
   // Clear any buffered-up text we have.  It's enough to set the length to 0.
   // The buffer itself is allocated when we're created and deleted in our
   // destructor, so don't mess with it.
   mTextLength = 0;
 
   return NS_OK;
--- a/dom/xslt/xpath/XPathExpression.cpp
+++ b/dom/xslt/xpath/XPathExpression.cpp
@@ -7,16 +7,17 @@
 #include "XPathExpression.h"
 #include "txExpr.h"
 #include "txExprResult.h"
 #include "txIXPathContext.h"
 #include "nsError.h"
 #include "nsIDOMCharacterData.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIDOMDocument.h"
+#include "nsINode.h"
 #include "XPathResult.h"
 #include "txURIUtils.h"
 #include "txXPathTreeWalker.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/XPathResultBinding.h"
 
 using mozilla::Move;
 
@@ -118,18 +119,18 @@ XPathExpression::EvaluateWithContext(nsI
         if (doc != aContextNode.OwnerDoc()) {
             aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
             return nullptr;
         }
     }
 
     uint16_t nodeType = aContextNode.NodeType();
 
-    if (nodeType == nsIDOMNode::TEXT_NODE ||
-        nodeType == nsIDOMNode::CDATA_SECTION_NODE) {
+    if (nodeType == nsINode::TEXT_NODE ||
+        nodeType == nsINode::CDATA_SECTION_NODE) {
         nsCOMPtr<nsIDOMCharacterData> textNode =
             do_QueryInterface(&aContextNode);
         if (!textNode) {
             aRv.Throw(NS_ERROR_FAILURE);
             return nullptr;
         }
 
         uint32_t textLength;
@@ -137,21 +138,21 @@ XPathExpression::EvaluateWithContext(nsI
         if (textLength == 0) {
             aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
             return nullptr;
         }
 
         // XXX Need to get logical XPath text node for CDATASection
         //     and Text nodes.
     }
-    else if (nodeType != nsIDOMNode::DOCUMENT_NODE &&
-             nodeType != nsIDOMNode::ELEMENT_NODE &&
-             nodeType != nsIDOMNode::ATTRIBUTE_NODE &&
-             nodeType != nsIDOMNode::COMMENT_NODE &&
-             nodeType != nsIDOMNode::PROCESSING_INSTRUCTION_NODE) {
+    else if (nodeType != nsINode::DOCUMENT_NODE &&
+             nodeType != nsINode::ELEMENT_NODE &&
+             nodeType != nsINode::ATTRIBUTE_NODE &&
+             nodeType != nsINode::COMMENT_NODE &&
+             nodeType != nsINode::PROCESSING_INSTRUCTION_NODE) {
         aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
         return nullptr;
     }
 
     nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(&aContextNode));
     if (!contextNode) {
       aRv.Throw(NS_ERROR_FAILURE);
       return nullptr;
--- a/dom/xslt/xpath/txMozillaXPathTreeWalker.cpp
+++ b/dom/xslt/xpath/txMozillaXPathTreeWalker.cpp
@@ -2,19 +2,19 @@
 /* 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 "txXPathTreeWalker.h"
 #include "nsAtom.h"
 #include "nsIAttribute.h"
 #include "nsIDOMDocument.h"
-#include "nsIDOMNode.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMProcessingInstruction.h"
+#include "nsINode.h"
 #include "nsPrintfCString.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsTextFragment.h"
 #include "txXMLUtils.h"
 #include "txLog.h"
 #include "nsUnicharUtils.h"
 #include "nsAttrName.h"
@@ -302,21 +302,17 @@ txXPathNodeUtils::getLocalName(const txX
     if (aNode.isContent()) {
         if (aNode.mNode->IsElement()) {
             RefPtr<nsAtom> localName =
                 aNode.Content()->NodeInfo()->NameAtom();
             return localName.forget();
         }
 
         if (aNode.mNode->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
-            nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode.mNode);
-            nsAutoString target;
-            node->GetNodeName(target);
-
-            return NS_Atomize(target);
+            return NS_Atomize(aNode.mNode->NodeName());
         }
 
         return nullptr;
     }
 
     // This is an attribute node, so we necessarily come from an element.
     RefPtr<nsAtom> localName =
       aNode.Content()->AsElement()->GetAttrNameAt(aNode.mIndex)->LocalName();
@@ -354,19 +350,19 @@ txXPathNodeUtils::getLocalName(const txX
         if (aNode.mNode->IsElement()) {
             mozilla::dom::NodeInfo* nodeInfo = aNode.Content()->NodeInfo();
             nodeInfo->GetName(aLocalName);
             return;
         }
 
         if (aNode.mNode->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
             // PIs don't have a nodeinfo but do have a name
-            nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode.mNode);
-            node->GetNodeName(aLocalName);
-
+            // XXXbz Not actually true, but this function looks like it wants
+            // different things from elements and PIs for "local name"...
+            aLocalName = aNode.mNode->NodeName();
             return;
         }
 
         aLocalName.Truncate();
 
         return;
     }
 
@@ -388,18 +384,17 @@ txXPathNodeUtils::getNodeName(const txXP
         aName.Truncate();
 
         return;
     }
 
     if (aNode.isContent()) {
         // Elements and PIs have a name
         if (aNode.mNode->IsElement() ||
-            aNode.mNode->NodeType() ==
-            nsIDOMNode::PROCESSING_INSTRUCTION_NODE) {
+            aNode.mNode->NodeType() == nsINode::PROCESSING_INSTRUCTION_NODE) {
             aName = aNode.Content()->NodeName();
             return;
         }
 
         aName.Truncate();
 
         return;
     }
@@ -638,17 +633,17 @@ txXPathNativeNode::createXPathNode(nsICo
     return new txXPathNode(aContent, txXPathNode::eContent, root);
 }
 
 /* static */
 txXPathNode*
 txXPathNativeNode::createXPathNode(nsINode* aNode, bool aKeepRootAlive)
 {
     uint16_t nodeType = aNode->NodeType();
-    if (nodeType == nsIDOMNode::ATTRIBUTE_NODE) {
+    if (nodeType == nsINode::ATTRIBUTE_NODE) {
         nsCOMPtr<nsIAttribute> attr = do_QueryInterface(aNode);
         NS_ASSERTION(attr, "doesn't implement nsIAttribute");
 
         mozilla::dom::NodeInfo *nodeInfo = attr->NodeInfo();
         mozilla::dom::Element* parent =
           static_cast<Attr*>(attr.get())->GetElement();
         if (!parent) {
             return nullptr;
@@ -667,17 +662,17 @@ txXPathNativeNode::createXPathNode(nsINo
         NS_ERROR("Couldn't find the attribute in its parent!");
 
         return nullptr;
     }
 
     uint32_t index;
     nsINode* root = aKeepRootAlive ? aNode : nullptr;
 
-    if (nodeType == nsIDOMNode::DOCUMENT_NODE) {
+    if (nodeType == nsINode::DOCUMENT_NODE) {
         index = txXPathNode::eDocument;
     }
     else {
         index = txXPathNode::eContent;
         if (root) {
             root = txXPathNode::RootOf(root);
         }
     }
--- a/dom/xslt/xpath/txXPathNode.h
+++ b/dom/xslt/xpath/txXPathNode.h
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef txXPathNode_h__
 #define txXPathNode_h__
 
 #include "nsAutoPtr.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
-#include "nsIDOMNode.h"
+#include "nsINode.h"
 #include "nsNameSpaceManager.h"
 #include "nsContentUtils.h" // For NameSpaceManager().
 
-typedef nsIDOMNode txXPathNodeType;
+typedef nsINode txXPathNodeType;
 
 class txXPathNode
 {
 public:
     bool operator==(const txXPathNode& aNode) const;
     bool operator!=(const txXPathNode& aNode) const
     {
         return !(*this == aNode);
--- a/dom/xslt/xslt/txMozillaXMLOutput.cpp
+++ b/dom/xslt/xslt/txMozillaXMLOutput.cpp
@@ -522,17 +522,17 @@ txMozillaXMLOutput::startElementInternal
     }
 
     mTableState = NORMAL;
     mOpenedElementIsHTML = false;
 
     // Create the element
     RefPtr<NodeInfo> ni =
         mNodeInfoManager->GetNodeInfo(aLocalName, aPrefix, aNsID,
-                                      nsIDOMNode::ELEMENT_NODE);
+                                      nsINode::ELEMENT_NODE);
 
     NS_NewElement(getter_AddRefs(mOpenedElement), ni.forget(),
                   mCreatingNewDocument ?
                   FROM_PARSER_XSLT : FROM_PARSER_FRAGMENT);
 
     // Set up the element and adjust state
     if (!mNoFixup) {
         if (aNsID == kNameSpaceID_XHTML) {
@@ -918,17 +918,17 @@ txMozillaXMLOutput::createHTMLElement(ns
     NS_ASSERTION(mOutputFormat.mMethod == eHTMLOutput,
                  "need to adjust createHTMLElement");
 
     *aResult = nullptr;
 
     RefPtr<NodeInfo> ni;
     ni = mNodeInfoManager->GetNodeInfo(aName, nullptr,
                                        kNameSpaceID_XHTML,
-                                       nsIDOMNode::ELEMENT_NODE);
+                                       nsINode::ELEMENT_NODE);
 
     nsCOMPtr<Element> el;
     nsresult rv =
         NS_NewHTMLElement(getter_AddRefs(el), ni.forget(),
                           mCreatingNewDocument ?
                             FROM_PARSER_XSLT : FROM_PARSER_FRAGMENT);
     el.forget(aResult);
     return rv;
--- a/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
+++ b/dom/xslt/xslt/txMozillaXSLTProcessor.cpp
@@ -186,22 +186,20 @@ txToFragmentHandlerFactory::createHandle
                                               txAXMLEventHandler** aHandler)
 {
     *aHandler = nullptr;
     switch (aFormat->mMethod) {
         case eMethodNotSet:
         {
             txOutputFormat format;
             format.merge(*aFormat);
-            nsCOMPtr<nsIDOMDocument> domdoc;
-            mFragment->GetOwnerDocument(getter_AddRefs(domdoc));
-            NS_ASSERTION(domdoc, "unable to get ownerdocument");
-            nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
+            nsCOMPtr<nsINode> node = do_QueryInterface(mFragment);
+            nsCOMPtr<nsIDocument> doc = node->OwnerDoc();
 
-            if (doc && doc->IsHTMLDocument()) {
+            if (doc->IsHTMLDocument()) {
                 format.mMethod = eHTMLOutput;
             } else {
                 format.mMethod = eXMLOutput;
             }
 
             *aHandler = new txMozillaXMLOutput(&format, mFragment, false);
             break;
         }
@@ -386,17 +384,17 @@ txMozillaXSLTProcessor::SetSourceContent
         return NS_OK;
     }
 
     mSource = aDocument->CreateDocumentFragment();
 
     ErrorResult rv;
     for (nsIContent* child : aSource) {
         // XPath data model doesn't have DocumentType nodes.
-        if (child->NodeType() != nsIDOMNode::DOCUMENT_TYPE_NODE) {
+        if (child->NodeType() != nsINode::DOCUMENT_TYPE_NODE) {
             mSource->AppendChild(*child, rv);
             if (rv.Failed()) {
                 return rv.StealNSResult();
             }
         }
     }
 
     if (mStylesheet) {
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -3375,17 +3375,17 @@ XULDocument::CreateElementFromPrototype(
         // If it's not a XUL element, it's gonna be heavyweight no matter
         // what. So we need to copy everything out of the prototype
         // into the element.  Get a nodeinfo from our nodeinfo manager
         // for this node.
         RefPtr<mozilla::dom::NodeInfo> newNodeInfo;
         newNodeInfo = mNodeInfoManager->GetNodeInfo(aPrototype->mNodeInfo->NameAtom(),
                                                     aPrototype->mNodeInfo->GetPrefixAtom(),
                                                     aPrototype->mNodeInfo->NamespaceID(),
-                                                    nsIDOMNode::ELEMENT_NODE);
+                                                    ELEMENT_NODE);
         if (!newNodeInfo) return NS_ERROR_OUT_OF_MEMORY;
         RefPtr<mozilla::dom::NodeInfo> xtfNi = newNodeInfo;
         rv = NS_NewElement(getter_AddRefs(result), newNodeInfo.forget(),
                            NOT_FROM_PARSER);
         if (NS_FAILED(rv))
             return rv;
 
         rv = AddAttributes(aPrototype, result);
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -95,19 +95,16 @@ public:
     NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aContent) override;
     NS_IMETHOD OnPrototypeLoadDone(bool aResumeWalk) override;
     bool OnDocumentParserError() override;
 
     // nsINode interface overrides
     virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                            bool aPreallocateChildren) const override;
 
-    // nsIDOMNode interface
-    NS_FORWARD_NSIDOMNODE_TO_NSINODE
-
     // nsIDOMDocument interface
     using nsDocument::CreateElement;
     using nsDocument::CreateElementNS;
     NS_FORWARD_NSIDOMDOCUMENT(XMLDocument::)
     // And explicitly import the things from nsDocument that we just shadowed
     using mozilla::dom::DocumentOrShadowRoot::GetElementById;
     using nsDocument::GetImplementation;
     using nsDocument::GetTitle;
--- a/dom/xul/nsXULCommandDispatcher.cpp
+++ b/dom/xul/nsXULCommandDispatcher.cpp
@@ -355,22 +355,21 @@ nsXULCommandDispatcher::UpdateCommands(c
     if (!mPendingUpdates.Contains(aEventName)) {
       mPendingUpdates.AppendElement(aEventName);
     }
 
     return NS_OK;
   }
 
   nsAutoString id;
-  nsCOMPtr<nsIDOMElement> element;
-  GetFocusedElement(getter_AddRefs(element));
+  nsCOMPtr<nsIDOMElement> domElement;
+  GetFocusedElement(getter_AddRefs(domElement));
+  nsCOMPtr<Element> element = do_QueryInterface(domElement);
   if (element) {
-    nsresult rv = element->GetAttribute(NS_LITERAL_STRING("id"), id);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get element's id");
-    if (NS_FAILED(rv)) return rv;
+    element->GetAttribute(NS_LITERAL_STRING("id"), id);
   }
 
   nsCOMArray<nsIContent> updaters;
 
   for (Updater* updater = mUpdaters; updater != nullptr; updater = updater->mNext) {
     // Skip any nodes that don't match our 'events' or 'targets'
     // filters.
     if (! Matches(updater->mEvents, aEventName))
--- a/dom/xul/nsXULContentSink.cpp
+++ b/dom/xul/nsXULContentSink.cpp
@@ -404,17 +404,17 @@ XULContentSinkImpl::NormalizeAttributeSt
         aName.SetTo(localName);
 
         return NS_OK;
     }
 
     RefPtr<mozilla::dom::NodeInfo> ni;
     ni = mNodeInfoManager->GetNodeInfo(localName, prefix,
                                        nameSpaceID,
-                                       nsIDOMNode::ATTRIBUTE_NODE);
+                                       nsINode::ATTRIBUTE_NODE);
     aName.SetTo(ni);
 
     return NS_OK;
 }
 
 nsresult
 XULContentSinkImpl::CreateElement(mozilla::dom::NodeInfo *aNodeInfo,
                                   nsXULPrototypeElement** aResult)
@@ -451,17 +451,17 @@ XULContentSinkImpl::HandleStartElement(c
 
   int32_t nameSpaceID;
   RefPtr<nsAtom> prefix, localName;
   nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
                                  getter_AddRefs(localName), &nameSpaceID);
 
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID,
-                                           nsIDOMNode::ELEMENT_NODE);
+                                           nsINode::ELEMENT_NODE);
 
   nsresult rv = NS_OK;
   switch (mState) {
   case eInProlog:
       // We're the root document element
       rv = OpenRoot(aAtts, aAttsCount, nodeInfo);
       break;
 
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -234,17 +234,17 @@ nsXULElement::Create(nsXULPrototypeEleme
     if (! aResult)
         return NS_ERROR_NULL_POINTER;
 
     RefPtr<mozilla::dom::NodeInfo> nodeInfo;
     if (aDocument) {
         mozilla::dom::NodeInfo* ni = aPrototype->mNodeInfo;
         nodeInfo = aDocument->NodeInfoManager()->
           GetNodeInfo(ni->NameAtom(), ni->GetPrefixAtom(), ni->NamespaceID(),
-                      nsIDOMNode::ELEMENT_NODE);
+                      ELEMENT_NODE);
     } else {
         nodeInfo = aPrototype->mNodeInfo;
     }
 
     RefPtr<nsXULElement> element = Create(aPrototype, nodeInfo,
                                             aIsScriptable, aIsRoot);
     element.forget(aResult);
 
@@ -2081,18 +2081,17 @@ nsXULPrototypeElement::Serialize(nsIObje
 
     nsAutoString attributeValue;
     uint32_t i;
     for (i = 0; i < mNumAttributes; ++i) {
         RefPtr<mozilla::dom::NodeInfo> ni;
         if (mAttributes[i].mName.IsAtom()) {
             ni = mNodeInfo->NodeInfoManager()->
                 GetNodeInfo(mAttributes[i].mName.Atom(), nullptr,
-                            kNameSpaceID_None,
-                            nsIDOMNode::ATTRIBUTE_NODE);
+                            kNameSpaceID_None, nsINode::ATTRIBUTE_NODE);
             NS_ASSERTION(ni, "the nodeinfo should already exist");
         } else {
             ni = mAttributes[i].mName.NodeInfo();
         }
 
         index = aNodeInfos->IndexOf(ni);
         NS_ASSERTION(index >= 0, "unknown mozilla::dom::NodeInfo index");
         tmp = aStream->Write32(index);
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -389,25 +389,16 @@ public:
     virtual bool IsNodeOfType(uint32_t aFlags) const override;
     virtual bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse) override;
 
     NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
     virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
                                                 int32_t aModType) const override;
     NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
-    // nsIDOMNode
-    NS_FORWARD_NSIDOMNODE_TO_NSINODE
-    // And since that shadowed GetParentElement with the XPCOM
-    // signature, pull in the one we care about.
-    using nsStyledElement::GetParentElement;
-
-    // nsIDOMElement
-    NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
-
     // nsIDOMXULElement
     NS_DECL_NSIDOMXULELEMENT
 
     virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                            bool aPreallocateChildren) const override;
     virtual mozilla::EventStates IntrinsicState() const override;
 
     nsresult GetFrameLoaderXPCOM(nsIFrameLoader** aFrameLoader);
--- a/dom/xul/nsXULPopupListener.cpp
+++ b/dom/xul/nsXULPopupListener.cpp
@@ -220,77 +220,72 @@ nsXULPopupListener::HandleEvent(nsIDOMEv
 
   return NS_OK;
 }
 
 #ifndef NS_CONTEXT_MENU_IS_MOUSEUP
 nsresult
 nsXULPopupListener::FireFocusOnTargetContent(nsIDOMNode* aTargetNode, bool aIsTouch)
 {
-  nsresult rv;
-  nsCOMPtr<nsIDOMDocument> domDoc;
-  rv = aTargetNode->GetOwnerDocument(getter_AddRefs(domDoc));
-  if(NS_SUCCEEDED(rv) && domDoc)
-  {
-    nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
-
-    // Get nsIDOMElement for targetNode
-    nsIPresShell *shell = doc->GetShell();
-    if (!shell)
-      return NS_ERROR_FAILURE;
+  nsCOMPtr<nsIContent> content = do_QueryInterface(aTargetNode);
+  nsCOMPtr<nsIDocument> doc = content->OwnerDoc();
 
-    // strong reference to keep this from going away between events
-    // XXXbz between what events?  We don't use this local at all!
-    RefPtr<nsPresContext> context = shell->GetPresContext();
+  // Get nsIDOMElement for targetNode
+  nsIPresShell *shell = doc->GetShell();
+  if (!shell)
+    return NS_ERROR_FAILURE;
 
-    nsCOMPtr<nsIContent> content = do_QueryInterface(aTargetNode);
-    nsIFrame* targetFrame = content->GetPrimaryFrame();
-    if (!targetFrame) return NS_ERROR_FAILURE;
+  // strong reference to keep this from going away between events
+  // XXXbz between what events?  We don't use this local at all!
+  RefPtr<nsPresContext> context = shell->GetPresContext();
 
-    const nsStyleUserInterface* ui = targetFrame->StyleUserInterface();
-    bool suppressBlur = (ui->mUserFocus == StyleUserFocus::Ignore);
-
-    nsCOMPtr<nsIDOMElement> element;
-    nsCOMPtr<nsIContent> newFocus = do_QueryInterface(content);
+  nsIFrame* targetFrame = content->GetPrimaryFrame();
+  if (!targetFrame) return NS_ERROR_FAILURE;
 
-    nsIFrame* currFrame = targetFrame;
-    // Look for the nearest enclosing focusable frame.
-    while (currFrame) {
-        int32_t tabIndexUnused;
-        if (currFrame->IsFocusable(&tabIndexUnused, true)) {
-          newFocus = currFrame->GetContent();
-          nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(newFocus));
-          if (domElement) {
-            element = domElement;
-            break;
-          }
-        }
-        currFrame = currFrame->GetParent();
-    }
+  const nsStyleUserInterface* ui = targetFrame->StyleUserInterface();
+  bool suppressBlur = (ui->mUserFocus == StyleUserFocus::Ignore);
+
+  nsCOMPtr<nsIDOMElement> element;
+  nsCOMPtr<nsIContent> newFocus = content;
 
-    nsIFocusManager* fm = nsFocusManager::GetFocusManager();
-    if (fm) {
-      if (element) {
-        uint32_t focusFlags = nsIFocusManager::FLAG_BYMOUSE |
-                              nsIFocusManager::FLAG_NOSCROLL;
-        if (aIsTouch) {
-          focusFlags |= nsIFocusManager::FLAG_BYTOUCH;
-        }
-        fm->SetFocus(element, focusFlags);
-      } else if (!suppressBlur) {
-        nsPIDOMWindowOuter *window = doc->GetWindow();
-        fm->ClearFocus(window);
+  nsIFrame* currFrame = targetFrame;
+  // Look for the nearest enclosing focusable frame.
+  while (currFrame) {
+    int32_t tabIndexUnused;
+    if (currFrame->IsFocusable(&tabIndexUnused, true)) {
+      newFocus = currFrame->GetContent();
+      nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(newFocus));
+      if (domElement) {
+        element = domElement;
+        break;
       }
     }
+    currFrame = currFrame->GetParent();
+  }
 
-    EventStateManager* esm = context->EventStateManager();
-    nsCOMPtr<nsIContent> focusableContent = do_QueryInterface(element);
-    esm->SetContentState(focusableContent, NS_EVENT_STATE_ACTIVE);
+  nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+  if (fm) {
+    if (element) {
+      uint32_t focusFlags = nsIFocusManager::FLAG_BYMOUSE |
+                            nsIFocusManager::FLAG_NOSCROLL;
+      if (aIsTouch) {
+        focusFlags |= nsIFocusManager::FLAG_BYTOUCH;
+      }
+      fm->SetFocus(element, focusFlags);
+    } else if (!suppressBlur) {
+      nsPIDOMWindowOuter *window = doc->GetWindow();
+      fm->ClearFocus(window);
+    }
   }
-  return rv;
+
+  EventStateManager* esm = context->EventStateManager();
+  nsCOMPtr<nsIContent> focusableContent = do_QueryInterface(element);
+  esm->SetContentState(focusableContent, NS_EVENT_STATE_ACTIVE);
+
+  return NS_OK;
 }
 #endif
 
 // ClosePopup
 //
 // Do everything needed to shut down the popup.
 //
 // NOTE: This routine is safe to call even if the popup is already closed.
--- a/dom/xul/nsXULPrototypeDocument.cpp
+++ b/dom/xul/nsXULPrototypeDocument.cpp
@@ -243,17 +243,17 @@ GetNodeInfos(nsXULPrototypeElement* aPro
     // Search attributes
     uint32_t i;
     for (i = 0; i < aPrototype->mNumAttributes; ++i) {
         RefPtr<mozilla::dom::NodeInfo> ni;
         nsAttrName* name = &aPrototype->mAttributes[i].mName;
         if (name->IsAtom()) {
             ni = aPrototype->mNodeInfo->NodeInfoManager()->
                 GetNodeInfo(name->Atom(), nullptr, kNameSpaceID_None,
-                            nsIDOMNode::ATTRIBUTE_NODE);
+                            nsINode::ATTRIBUTE_NODE);
         }
         else {
             ni = name->NodeInfo();
         }
 
         if (aArray.IndexOf(ni) == aArray.NoIndex) {
             aArray.AppendElement(ni);
         }
--- a/editor/composer/moz.build
+++ b/editor/composer/moz.build
@@ -28,16 +28,18 @@ UNIFIED_SOURCES += [
 EXPORTS.mozilla += [
     'ComposerCommandsUpdater.h',
     'EditorSpellCheck.h',
 ]
 
 # Needed because we include HTMLEditor.h which indirectly includes nsDocument.h
 LOCAL_INCLUDES += [
     '/dom/base',
+    '/dom/html',  # For nsHTMLDocument
+    '/layout/style', # For things nsHTMLDocument includes.
 ]
 
 FINAL_LIBRARY = 'xul'
 RESOURCE_FILES += [
     'res/EditorOverride.css',
     'res/grabber.gif',
     'res/table-add-column-after-active.gif',
     'res/table-add-column-after-hover.gif',
--- a/editor/composer/nsComposerCommands.cpp
+++ b/editor/composer/nsComposerCommands.cpp
@@ -3,17 +3,19 @@
  * 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 <stdio.h>                      // for printf
 
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/EditorBase.h"         // for EditorBase
+#include "mozilla/ErrorResult.h"
 #include "mozilla/HTMLEditor.h"         // for HTMLEditor
+#include "mozilla/dom/Element.h"
 #include "nsAString.h"
 #include "nsCOMPtr.h"                   // for nsCOMPtr, do_QueryInterface, etc
 #include "nsComponentManagerUtils.h"    // for do_CreateInstance
 #include "nsComposerCommands.h"
 #include "nsDebug.h"                    // for NS_ENSURE_TRUE, etc
 #include "nsError.h"                    // for NS_OK, NS_ERROR_FAILURE, etc
 #include "nsGkAtoms.h"                  // for nsGkAtoms, nsGkAtoms::font, etc
 #include "nsAtom.h"                    // for nsAtom, etc
@@ -24,16 +26,18 @@
 #include "nsIEditor.h"                  // for nsIEditor
 #include "nsIHTMLEditor.h"              // for nsIHTMLEditor, etc
 #include "nsLiteralString.h"            // for NS_LITERAL_STRING
 #include "nsReadableUtils.h"            // for EmptyString
 #include "nsString.h"                   // for nsAutoString, nsString, etc
 #include "nsStringFwd.h"                // for nsString
 
 class nsISupports;
+using mozilla::dom::Element;
+using mozilla::ErrorResult;
 
 //prototype
 nsresult GetListState(mozilla::HTMLEditor* aHTMLEditor,
                       bool* aMixed,
                       nsAString& aLocalName);
 nsresult RemoveOneProperty(mozilla::HTMLEditor* aHTMLEditor,
                            const nsAString& aProp);
 nsresult RemoveTextProperty(mozilla::HTMLEditor* aHTMLEditor,
@@ -1525,18 +1529,22 @@ nsInsertTagCommand::DoCommandParams(cons
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   nsCOMPtr<nsIDOMElement> domElem;
   rv = htmlEditor->CreateElementWithDefaults(nsDependentAtomString(mTagName),
                                              getter_AddRefs(domElem));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = domElem->SetAttribute(attributeType, attrib);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<Element> elem = do_QueryInterface(domElem);
+  ErrorResult err;
+  elem->SetAttribute(attributeType, attrib, err);
+  if (NS_WARN_IF(err.Failed())) {
+    return err.StealNSResult();
+  }
 
   // do actual insertion
   if (mTagName == nsGkAtoms::a) {
     return htmlEditor->InsertLinkAroundSelection(domElem);
   }
   return htmlEditor->InsertElementAtSelection(domElem, true);
 }
 
--- a/editor/composer/nsEditingSession.cpp
+++ b/editor/composer/nsEditingSession.cpp
@@ -20,17 +20,17 @@
 #include "nsIChannel.h"                 // for nsIChannel
 #include "nsICommandManager.h"          // for nsICommandManager
 #include "nsIContentViewer.h"           // for nsIContentViewer
 #include "nsIController.h"              // for nsIController
 #include "nsIControllerContext.h"       // for nsIControllerContext
 #include "nsIControllers.h"             // for nsIControllers
 #include "nsID.h"                       // for NS_GET_IID, etc
 #include "nsIDOMDocument.h"             // for nsIDOMDocument
-#include "nsIDOMHTMLDocument.h"         // for nsIDOMHTMLDocument
+#include "nsHTMLDocument.h"             // for nsHTMLDocument
 #include "nsIDOMWindow.h"               // for nsIDOMWindow
 #include "nsIDocShell.h"                // for nsIDocShell
 #include "nsIDocument.h"                // for nsIDocument
 #include "nsIDocumentStateListener.h"
 #include "nsIEditor.h"                  // for nsIEditor
 #include "nsIHTMLDocument.h"            // for nsIHTMLDocument, etc
 #include "nsIInterfaceRequestorUtils.h"  // for do_GetInterface
 #include "nsIPlaintextEditor.h"         // for nsIPlaintextEditor, etc
@@ -663,23 +663,20 @@ nsEditingSession::OnStateChange(nsIWebPr
         IsProgressForTargetDocument(aWebProgress);
 
       if (progressIsForTargetDocument) {
         nsCOMPtr<mozIDOMWindowProxy> window;
         aWebProgress->GetDOMWindow(getter_AddRefs(window));
 
         auto* piWindow = nsPIDOMWindowOuter::From(window);
         nsCOMPtr<nsIDocument> doc = piWindow->GetDoc();
-
-        nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(doc));
-
+        nsHTMLDocument* htmlDoc = doc ? doc->AsHTMLDocument() : nullptr;
         if (htmlDoc && htmlDoc->IsWriting()) {
-          nsCOMPtr<nsIDOMHTMLDocument> htmlDomDoc = do_QueryInterface(doc);
           nsAutoString designMode;
-          htmlDomDoc->GetDesignMode(designMode);
+          htmlDoc->GetDesignMode(designMode);
 
           if (designMode.EqualsLiteral("on")) {
             // This notification is for data coming in through
             // document.open/write/close(), ignore it.
 
             return NS_OK;
           }
         }
--- a/editor/libeditor/CSSEditUtils.cpp
+++ b/editor/libeditor/CSSEditUtils.cpp
@@ -318,17 +318,17 @@ bool
 CSSEditUtils::IsCSSEditableProperty(nsINode* aNode,
                                     nsAtom* aProperty,
                                     nsAtom* aAttribute)
 {
   MOZ_ASSERT(aNode);
 
   nsINode* node = aNode;
   // we need an element node here
-  if (node->NodeType() == nsIDOMNode::TEXT_NODE) {
+  if (node->NodeType() == nsINode::TEXT_NODE) {
     node = node->GetParentNode();
     NS_ENSURE_TRUE(node, false);
   }
 
   // html inline styles B I TT U STRIKE and COLOR/FACE on FONT
   if (nsGkAtoms::b == aProperty ||
       nsGkAtoms::i == aProperty ||
       nsGkAtoms::tt == aProperty ||
@@ -1328,17 +1328,17 @@ CSSEditUtils::GetInlineStyles(Element* a
   (*aCssDecl)->GetLength(aLength);
   return NS_OK;
 }
 
 Element*
 CSSEditUtils::GetElementContainerOrSelf(nsINode* aNode)
 {
   MOZ_ASSERT(aNode);
-  if (nsIDOMNode::DOCUMENT_NODE == aNode->NodeType()) {
+  if (nsINode::DOCUMENT_NODE == aNode->NodeType()) {
     return nullptr;
   }
 
   nsINode* node = aNode;
   // Loop until we find an element.
   while (node && !node->IsElement()) {
     node = node->GetParentNode();
   }
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -59,27 +59,27 @@
 #include "nsComponentManagerUtils.h"    // for do_CreateInstance
 #include "nsComputedDOMStyle.h"         // for nsComputedDOMStyle
 #include "nsContentUtils.h"             // for nsContentUtils
 #include "nsDOMString.h"                // for DOMStringIsNull
 #include "nsDebug.h"                    // for NS_ENSURE_TRUE, etc.
 #include "nsError.h"                    // for NS_OK, etc.
 #include "nsFocusManager.h"             // for nsFocusManager
 #include "nsFrameSelection.h"           // for nsFrameSelection
+#include "nsGenericHTMLElement.h"       // for nsGenericHTMLElement
 #include "nsGkAtoms.h"                  // for nsGkAtoms, nsGkAtoms::dir
 #include "nsIAbsorbingTransaction.h"    // for nsIAbsorbingTransaction
 #include "nsAtom.h"                    // for nsAtom
 #include "nsIContent.h"                 // for nsIContent
 #include "nsIDOMCharacterData.h"        // for nsIDOMCharacterData
 #include "nsIDOMDocument.h"             // for nsIDOMDocument
 #include "nsIDOMElement.h"              // for nsIDOMElement
 #include "nsIDOMEvent.h"                // for nsIDOMEvent
 #include "nsIDOMEventListener.h"        // for nsIDOMEventListener
 #include "nsIDOMEventTarget.h"          // for nsIDOMEventTarget
-#include "nsIDOMHTMLElement.h"          // for nsIDOMHTMLElement
 #include "nsIDOMMouseEvent.h"           // for nsIDOMMouseEvent
 #include "nsIDOMNode.h"                 // for nsIDOMNode, etc.
 #include "nsIDOMNodeList.h"             // for nsIDOMNodeList
 #include "nsIDocumentStateListener.h"   // for nsIDocumentStateListener
 #include "nsIEditActionListener.h"      // for nsIEditActionListener
 #include "nsIEditorObserver.h"          // for nsIEditorObserver
 #include "nsIEditorSpellCheck.h"        // for nsIEditorSpellCheck
 #include "nsIFrame.h"                   // for nsIFrame
@@ -110,20 +110,16 @@
 #include "nsTextNode.h"                 // for nsTextNode
 #include "nsThreadUtils.h"              // for nsRunnable
 #include "nsTransactionManager.h"       // for nsTransactionManager
 #include "prtime.h"                     // for PR_Now
 
 class nsIOutputStream;
 class nsITransferable;
 
-#ifdef DEBUG
-#include "nsIDOMHTMLDocument.h"         // for nsIDOMHTMLDocument
-#endif
-
 namespace mozilla {
 
 using namespace dom;
 using namespace widget;
 
 /*****************************************************************************
  * mozilla::EditorBase
  *****************************************************************************/
@@ -446,33 +442,30 @@ EditorBase::GetDesiredSpellCheckState()
   }
 
   // Check DOM state
   nsCOMPtr<nsIContent> content = GetExposedRoot();
   if (!content) {
     return false;
   }
 
-  nsCOMPtr<nsIDOMHTMLElement> element = do_QueryInterface(content);
+  auto element = nsGenericHTMLElement::FromContent(content);
   if (!element) {
     return false;
   }
 
   if (!IsPlaintextEditor()) {
     // Some of the page content might be editable and some not, if spellcheck=
     // is explicitly set anywhere, so if there's anything editable on the page,
     // return true and let the spellchecker figure it out.
     nsCOMPtr<nsIHTMLDocument> doc = do_QueryInterface(content->GetUncomposedDoc());
     return doc && doc->IsEditingOn();
   }
 
-  bool enable;
-  element->GetSpellcheck(&enable);
-
-  return enable;
+  return element->Spellcheck();
 }
 
 NS_IMETHODIMP
 EditorBase::PreDestroy(bool aDestroyingFrames)
 {
   if (mDidPreDestroy)
     return NS_OK;
 
@@ -1140,17 +1133,17 @@ EditorBase::BeginningOfDocument()
 
   // find first editable thingy
   nsCOMPtr<nsINode> firstNode = GetFirstEditableNode(rootElement);
   if (!firstNode) {
     // just the root node, set selection to inside the root
     return selection->Collapse(rootElement, 0);
   }
 
-  if (firstNode->NodeType() == nsIDOMNode::TEXT_NODE) {
+  if (firstNode->NodeType() == nsINode::TEXT_NODE) {
     // If firstNode is text, set selection to beginning of the text node.
     return selection->Collapse(firstNode, 0);
   }
 
   // Otherwise, it's a leaf node and we set the selection just in front of it.
   nsCOMPtr<nsIContent> parent = firstNode->GetParent();
   if (!parent) {
     return NS_ERROR_NULL_POINTER;
@@ -1322,24 +1315,24 @@ EditorBase::GetAttributeValue(nsIDOMElem
                               nsAString& aResultValue,
                               bool* aResultIsSet)
 {
   NS_ENSURE_TRUE(aResultIsSet, NS_ERROR_NULL_POINTER);
   *aResultIsSet = false;
   if (!aElement) {
     return NS_OK;
   }
+  nsCOMPtr<Element> element = do_QueryInterface(aElement);
   nsAutoString value;
-  nsresult rv = aElement->GetAttribute(aAttribute, value);
-  NS_ENSURE_SUCCESS(rv, rv);
+  element->GetAttribute(aAttribute, value);
   if (!DOMStringIsNull(value)) {
     *aResultIsSet = true;
     aResultValue = value;
   }
-  return rv;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 EditorBase::RemoveAttribute(nsIDOMElement* aElement,
                             const nsAString& aAttribute)
 {
   if (NS_WARN_IF(aAttribute.IsEmpty())) {
     return NS_ERROR_FAILURE;
@@ -2385,25 +2378,19 @@ EditorBase::DumpContentTree()
 NS_IMETHODIMP
 EditorBase::DebugDumpContent()
 {
 #ifdef DEBUG
   nsCOMPtr<nsIDocument> document = GetDocument();
   if (NS_WARN_IF(!document)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
-  nsCOMPtr<nsIDOMHTMLDocument> domHTMLDocument = do_QueryInterface(document);
-  if (NS_WARN_IF(!domHTMLDocument)) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-  nsCOMPtr<nsIDOMHTMLElement> bodyElement;
-  domHTMLDocument->GetBody(getter_AddRefs(bodyElement));
-  nsCOMPtr<nsIContent> content = do_QueryInterface(bodyElement);
-  if (content) {
-    content->List();
+  Element* body = document->GetBody();
+  if (body) {
+    body->List();
   }
 #endif
   return NS_OK;
 }
 
 NS_IMETHODIMP
 EditorBase::DebugUnitTests(int32_t* outNumTests,
                            int32_t* outNumTestsFailed)
@@ -3555,19 +3542,19 @@ EditorBase::GetChildOffset(nsINode* aChi
 already_AddRefed<nsIDOMNode>
 EditorBase::GetNodeLocation(nsIDOMNode* aChild,
                             int32_t* outOffset)
 {
   MOZ_ASSERT(aChild && outOffset);
   NS_ENSURE_TRUE(aChild && outOffset, nullptr);
   *outOffset = -1;
 
-  nsCOMPtr<nsIDOMNode> parent;
-
-  MOZ_ALWAYS_SUCCEEDS(aChild->GetParentNode(getter_AddRefs(parent)));
+  nsCOMPtr<nsINode> child = do_QueryInterface(aChild);
+  nsCOMPtr<nsIDOMNode> parent = do_QueryInterface(child->GetParentNode());
+
   if (parent) {
     *outOffset = GetChildOffset(aChild, parent);
<