Merge mozilla-central to inbound. a=merge on a CLOSED TREE
authorCosmin Sabou <csabou@mozilla.com>
Wed, 28 Mar 2018 12:56:23 +0300
changeset 410466 f4f8e10c031ae5a93eb9b230cfc0984f16906234
parent 410465 bb13eb4b2c587c6f95036a699adcce39c484868f (current diff)
parent 410372 5bf126434fac78a31256c994b9dbf4b1031b0350 (diff)
child 410467 fd0e344e9bce082468cfc20015554ca5e6015b05
push id33729
push userrgurzau@mozilla.com
push dateWed, 28 Mar 2018 21:55:49 +0000
treeherdermozilla-central@6aa3b57955fe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to inbound. a=merge on a CLOSED TREE
browser/components/places/content/bookmarksPanel.js
browser/components/places/content/bookmarksPanel.xul
browser/components/places/content/history-panel.js
browser/components/places/content/history-panel.xul
browser/components/places/content/organizer.css
browser/components/places/content/sidebarUtils.js
layout/style/nsCSSPseudoClassList.h
layout/style/nsCSSPseudoClasses.cpp
layout/style/nsCSSPseudoClasses.h
services/sync/tps/extensions/tps/chrome.manifest
toolkit/mozapps/extensions/content/about.js
toolkit/mozapps/extensions/content/about.xul
toolkit/mozapps/extensions/test/browser/addon_about.xul
toolkit/mozapps/extensions/test/browser/browser_about.js
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -115,25 +115,23 @@
              oncommand="zoomWindow();" />
 #endif
   </commandset>
 
 #include ../../components/places/content/placesCommands.inc.xul
 
   <broadcasterset id="mainBroadcasterSet">
     <broadcaster id="viewBookmarksSidebar" autoCheck="false" label="&bookmarksButton.label;"
-                 type="checkbox" group="sidebar" sidebarurl="chrome://browser/content/bookmarks/bookmarksPanel.xul"
+                 type="checkbox" group="sidebar"
+                 sidebarurl="chrome://browser/content/places/bookmarksSidebar.xul"
                  oncommand="SidebarUI.toggle('viewBookmarksSidebar');"/>
 
-    <!-- for both places and non-places, the sidebar lives at
-         chrome://browser/content/history/history-panel.xul so there are no
-         problems when switching between versions -->
     <broadcaster id="viewHistorySidebar" autoCheck="false" sidebartitle="&historyButton.label;"
                  type="checkbox" group="sidebar"
-                 sidebarurl="chrome://browser/content/history/history-panel.xul"
+                 sidebarurl="chrome://browser/content/places/historySidebar.xul"
                  oncommand="SidebarUI.toggle('viewHistorySidebar');"/>
 
     <broadcaster id="viewWebPanelsSidebar" autoCheck="false"
                  type="checkbox" group="sidebar" sidebarurl="chrome://browser/content/web-panels.xul"
                  oncommand="SidebarUI.toggle('viewWebPanelsSidebar');"/>
 
     <broadcaster id="bookmarkThisPageBroadcaster"
                  label="&bookmarkThisPageCmd.label;"
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1276,17 +1276,17 @@ var gBrowserInit = {
         gBrowser.setIcon(gBrowser.selectedTab, "chrome://branding/content/icon32.png");
       } else if (uriToLoad == "about:privatebrowsing") {
         gBrowser.setIcon(gBrowser.selectedTab, "chrome://browser/skin/privatebrowsing/favicon.svg");
       }
     });
 
     this._setInitialFocus();
 
-    gBrowser.tabContainer.updateVisibility();
+    window.TabBarVisibility.update();
     TabsInTitlebar.onDOMContentLoaded();
   },
 
   onLoad() {
     gBrowser.addEventListener("DOMUpdateBlockedPopups", gPopupBlockerObserver);
 
     Services.obs.addObserver(gPluginHandler.NPAPIPluginCrashed, "plugin-crashed");
 
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -849,17 +849,17 @@ window._gBrowser = {
 
     if (tab._labelIsContentTitle) {
       // Strip out any null bytes in the content title, since the
       // underlying widget implementations of nsWindow::SetTitle pass
       // null-terminated strings to system APIs.
       docTitle = tab.getAttribute("label").replace(/\0/g, "");
     }
 
-    if (!docTitle || docTitle == this.tabContainer.emptyTabTitle)
+    if (!docTitle)
       docTitle = docElement.getAttribute("titledefault");
 
     var modifier = docElement.getAttribute("titlemodifier");
     if (docTitle) {
       newTitle += docElement.getAttribute("titlepreface");
       newTitle += docTitle;
       if (modifier)
         newTitle += sep;
@@ -1770,17 +1770,16 @@ window._gBrowser = {
       // For remote browsers, we need to make sure that the webProgress is
       // instantiated, otherwise the parent won't get informed about the state
       // of the preloaded browser until it gets attached to a tab.
       browser.webProgress;
     }
 
     browser.loadURI(BROWSER_NEW_TAB_URL);
     browser.docShellIsActive = false;
-    browser.renderLayers = true;
     browser._urlbarFocused = true;
 
     // Make sure the preloaded browser is loaded with desired zoom level
     let tabURI = Services.io.newURI(BROWSER_NEW_TAB_URL);
     FullZoom.onLocationChange(tabURI, false, browser);
   },
 
   _createBrowser(aParams) {
@@ -2279,17 +2278,17 @@ window._gBrowser = {
       // If this new tab is owned by another, assert that relationship
       if (aOwner)
         t.owner = aOwner;
 
       var position = this.tabs.length - 1;
       t._tPos = position;
       this.tabContainer._setPositionalAttributes();
 
-      this.tabContainer.updateVisibility();
+      TabBarVisibility.update();
 
       // If we don't have a preferred remote type, and we have a remote
       // opener, use the opener's remote type.
       if (!aPreferredRemoteType && aOpenerBrowser) {
         aPreferredRemoteType = aOpenerBrowser.remoteType;
       }
 
       // If URI is about:blank and we don't have a preferred remote type,
@@ -2753,17 +2752,17 @@ window._gBrowser = {
 
     // Invalidate hovered tab state tracking for this closing tab.
     if (this.tabContainer._hoveredTab == aTab)
       aTab._mouseleave();
 
     if (newTab)
       this.addTab(BROWSER_NEW_TAB_URL, { skipAnimation: true });
     else
-      this.tabContainer.updateVisibility();
+      TabBarVisibility.update();
 
     // We're committed to closing the tab now.
     // Dispatch a notification.
     // We dispatch it before any teardown so that event listeners can
     // inspect the tab that's about to close.
     var evt = new CustomEvent("TabClose", { bubbles: true, detail: { adoptedBy: aAdoptedByTab } });
     aTab.dispatchEvent(evt);
 
@@ -4700,8 +4699,33 @@ var StatusPanel = {
     }
 
     if (!this.panel.hasAttribute("sizelimit")) {
       this.panel.setAttribute("sizelimit", "true");
       this._mouseTargetRect = null;
     }
   }
 };
+
+var TabBarVisibility = {
+  _initialUpdateDone: false,
+
+  update() {
+    let toolbar = document.getElementById("TabsToolbar");
+    let collapse = false;
+    if (gBrowser.tabs.length - gBrowser._removingTabs.length == 1) {
+      collapse = !window.toolbar.visible;
+    }
+
+    if (collapse == toolbar.collapsed && this._initialUpdateDone) {
+      return;
+    }
+    this._initialUpdateDone = true;
+
+    toolbar.collapsed = collapse;
+
+    document.getElementById("menu_closeWindow").hidden = collapse;
+    document.getElementById("menu_close").setAttribute("label",
+      gTabBrowserBundle.GetStringFromName(collapse ? "tabs.close" : "tabs.closeTab"));
+
+    TabsInTitlebar.allowedBy("tabs-visible", !collapse);
+  }
+};
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -364,60 +364,16 @@
 
       <field name="_tabDropIndicator">
         document.getAnonymousElementByAttribute(this, "anonid", "tab-drop-indicator");
       </field>
 
       <field name="_dragOverDelay">350</field>
       <field name="_dragTime">0</field>
 
-      <field name="_container" readonly="true"><![CDATA[
-        this.parentNode && this.parentNode.localName == "toolbar" ? this.parentNode : this;
-      ]]></field>
-
-      <field name="_propagatedVisibilityOnce">false</field>
-
-      <property name="visible"
-                onget="return !this._container.collapsed;">
-        <setter><![CDATA[
-          if (val == this.visible &&
-              this._propagatedVisibilityOnce)
-            return val;
-
-          this._container.collapsed = !val;
-
-          this._propagateVisibility();
-          this._propagatedVisibilityOnce = true;
-
-          return val;
-        ]]></setter>
-      </property>
-
-      <method name="_propagateVisibility">
-        <body><![CDATA[
-          let visible = this.visible;
-
-          document.getElementById("menu_closeWindow").hidden = !visible;
-          document.getElementById("menu_close").setAttribute("label",
-            gTabBrowserBundle.GetStringFromName(visible ? "tabs.closeTab" : "tabs.close"));
-
-          TabsInTitlebar.allowedBy("tabs-visible", visible);
-        ]]></body>
-      </method>
-
-      <method name="updateVisibility">
-        <body><![CDATA[
-          if (this.childNodes.length - gBrowser._removingTabs.length == 1) {
-            this.visible = window.toolbar.visible;
-          } else {
-            this.visible = true;
-          }
-        ]]></body>
-      </method>
-
       <field name="_closeButtonsUpdatePending">false</field>
       <method name="_updateCloseButtons">
         <body><![CDATA[
           // If we're overflowing, tabs are at their minimum widths.
           if (this.getAttribute("overflow") == "true") {
             this.setAttribute("closebuttons", "activetab");
             return;
           }
--- a/browser/components/places/PlacesUIUtils.jsm
+++ b/browser/components/places/PlacesUIUtils.jsm
@@ -5,23 +5,24 @@
 
 var EXPORTED_SYMBOLS = ["PlacesUIUtils"];
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/Timer.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
+  AppConstants: "resource://gre/modules/AppConstants.jsm",
   OpenInTabsUtils: "resource:///modules/OpenInTabsUtils.jsm",
+  PlacesTransactions: "resource://gre/modules/PlacesTransactions.jsm",
   PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
   PluralForm: "resource://gre/modules/PluralForm.jsm",
   PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
+  PromiseUtils: "resource://gre/modules/PromiseUtils.jsm",
   RecentWindow: "resource:///modules/RecentWindow.jsm",
-  PromiseUtils: "resource://gre/modules/PromiseUtils.jsm",
-  PlacesTransactions: "resource://gre/modules/PlacesTransactions.jsm",
   Weave: "resource://services-sync/main.js",
 });
 
 XPCOMUtils.defineLazyGetter(this, "bundle", function() {
   return Services.strings.createBundle("chrome://browser/locale/places/places.properties");
 });
 
 const gInContentProcess = Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
@@ -1026,16 +1027,104 @@ var PlacesUIUtils = {
     }
 
     await this.batchUpdatesForNode(resultForBatching, itemsCount, async () => {
       await PlacesTransactions.batch(batchingItem);
     });
 
     return guidsToSelect;
   },
+
+  onSidebarTreeClick(event) {
+    // right-clicks are not handled here
+    if (event.button == 2)
+      return;
+
+    let tree = event.target.parentNode;
+    let tbo = tree.treeBoxObject;
+    let cell = tbo.getCellAt(event.clientX, event.clientY);
+    if (cell.row == -1 || cell.childElt == "twisty")
+      return;
+
+    // getCoordsForCellItem returns the x coordinate in logical coordinates
+    // (i.e., starting from the left and right sides in LTR and RTL modes,
+    // respectively.)  Therefore, we make sure to exclude the blank area
+    // before the tree item icon (that is, to the left or right of it in
+    // LTR and RTL modes, respectively) from the click target area.
+    let win = tree.ownerGlobal;
+    let rect = tbo.getCoordsForCellItem(cell.row, cell.col, "image");
+    let isRTL = win.getComputedStyle(tree).direction == "rtl";
+    let mouseInGutter = isRTL ? event.clientX > rect.x
+                              : event.clientX < rect.x;
+
+    let metaKey = AppConstants.platform === "macosx" ? event.metaKey
+                                                     : event.ctrlKey;
+    let modifKey = metaKey || event.shiftKey;
+    let isContainer = tbo.view.isContainer(cell.row);
+    let openInTabs = isContainer &&
+                     (event.button == 1 || (event.button == 0 && modifKey)) &&
+                     PlacesUtils.hasChildURIs(tree.view.nodeForTreeIndex(cell.row));
+
+    if (event.button == 0 && isContainer && !openInTabs) {
+      tbo.view.toggleOpenState(cell.row);
+    } else if (!mouseInGutter && openInTabs &&
+               event.originalTarget.localName == "treechildren") {
+      tbo.view.selection.select(cell.row);
+      this.openContainerNodeInTabs(tree.selectedNode, event, tree);
+    } else if (!mouseInGutter && !isContainer &&
+               event.originalTarget.localName == "treechildren") {
+      // Clear all other selection since we're loading a link now. We must
+      // do this *before* attempting to load the link since openURL uses
+      // selection as an indication of which link to load.
+      tbo.view.selection.select(cell.row);
+      this.openNodeWithEvent(tree.selectedNode, event);
+    }
+  },
+
+  onSidebarTreeKeyPress(event) {
+    let node = event.target.selectedNode;
+    if (node) {
+      if (event.keyCode == KeyEvent.DOM_VK_RETURN)
+        this.openNodeWithEvent(node, event);
+    }
+  },
+
+  /**
+   * The following function displays the URL of a node that is being
+   * hovered over.
+   */
+  onSidebarTreeMouseMove(event) {
+    let treechildren = event.target;
+    if (treechildren.localName != "treechildren")
+      return;
+
+    let tree = treechildren.parentNode;
+    let cell = tree.treeBoxObject.getCellAt(event.clientX, event.clientY);
+
+    // cell.row is -1 when the mouse is hovering an empty area within the tree.
+    // To avoid showing a URL from a previously hovered node for a currently
+    // hovered non-url node, we must clear the moused-over URL in these cases.
+    if (cell.row != -1) {
+      let node = tree.view.nodeForTreeIndex(cell.row);
+      if (PlacesUtils.nodeIsURI(node)) {
+        this.setMouseoverURL(node.uri, tree.ownerGlobal);
+        return;
+      }
+    }
+    this.setMouseoverURL("", tree.ownerGlobal);
+  },
+
+  setMouseoverURL(url, win) {
+    // When the browser window is closed with an open sidebar, the sidebar
+    // unload event happens after the browser's one.  In this case
+    // top.XULBrowserWindow has been nullified already.
+    if (win.top.XULBrowserWindow) {
+      win.top.XULBrowserWindow.setOverLink(url, null);
+    }
+  }
 };
 
 // These are lazy getters to avoid importing PlacesUtils immediately.
 XPCOMUtils.defineLazyGetter(PlacesUIUtils, "PLACES_FLAVORS", () => {
   return [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
           PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
           PlacesUtils.TYPE_X_MOZ_PLACE];
 });
rename from browser/components/places/content/bookmarksPanel.js
rename to browser/components/places/content/bookmarksSidebar.js
--- a/browser/components/places/content/bookmarksPanel.js
+++ b/browser/components/places/content/bookmarksSidebar.js
@@ -1,16 +1,21 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 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/. */
 
 /* import-globals-from ../../../../toolkit/components/places/PlacesUtils.jsm */
 
 function init() {
+  let uidensity = window.top.document.documentElement.getAttribute("uidensity");
+  if (uidensity) {
+    document.documentElement.setAttribute("uidensity", uidensity);
+  }
+
   document.getElementById("bookmarks-view").place =
     "place:type=" + Ci.nsINavHistoryQueryOptions.RESULTS_AS_ROOTS_QUERY;
 }
 
 function searchBookmarks(aSearchString) {
   var tree = document.getElementById("bookmarks-view");
   if (!aSearchString)
     tree.place = tree.place;
rename from browser/components/places/content/bookmarksPanel.xul
rename to browser/components/places/content/bookmarksSidebar.xul
--- a/browser/components/places/content/bookmarksPanel.xul
+++ b/browser/components/places/content/bookmarksSidebar.xul
@@ -1,34 +1,32 @@
-<?xml version="1.0"?> <!-- -*- Mode: SGML; indent-tabs-mode: nil; -*- -->
+<?xml version="1.0"?> <!-- -*- Mode: xml; indent-tabs-mode: nil; -*- -->
 <!-- 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/. -->
 
+<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/content/places/places.css"?>
 <?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
 
 <!DOCTYPE page [
 <!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
 %placesDTD;
-<!ENTITY % editMenuOverlayDTD SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
-%editMenuOverlayDTD;
+<!ENTITY % editMenuDTD SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
+%editMenuDTD;
 ]>
 
 <page id="bookmarksPanel"
       xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
       onload="init();"
-      onunload="SidebarUtils.setMouseoverURL('');">
+      onunload="PlacesUIUtils.setMouseoverURL('', window);">
 
   <script type="application/javascript"
-          src="chrome://browser/content/bookmarks/sidebarUtils.js"/>
-  <script type="application/javascript"
-          src="chrome://browser/content/bookmarks/bookmarksPanel.js"/>
+          src="chrome://browser/content/places/bookmarksSidebar.js"/>
   <script type="application/javascript"
           src="chrome://global/content/globalOverlay.js"/>
   <script type="application/javascript"
           src="chrome://browser/content/utilityOverlay.js"/>
   <script type="application/javascript"><![CDATA[
     ChromeUtils.defineModuleGetter(window,
       "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm");
     ChromeUtils.defineModuleGetter(window,
@@ -51,23 +49,25 @@
 
   <hbox id="sidebar-search-container" align="center">
     <textbox id="search-box" flex="1" type="search"
              placeholder="&bookmarksSearch.placeholder;"
              aria-controls="bookmarks-view"
              oncommand="searchBookmarks(this.value);"/>
   </hbox>
 
-  <tree id="bookmarks-view" class="sidebar-placesTree" type="places"
+  <tree id="bookmarks-view"
+        class="sidebar-placesTree"
+        type="places"
         flex="1"
         hidecolumnpicker="true"
         context="placesContext"
-        onkeypress="SidebarUtils.handleTreeKeyPress(event);"
-        onclick="SidebarUtils.handleTreeClick(this, event, true);"
-        onmousemove="SidebarUtils.handleTreeMouseMove(event);"
-        onmouseout="SidebarUtils.setMouseoverURL('');">
+        onkeypress="PlacesUIUtils.onSidebarTreeKeyPress(event);"
+        onclick="PlacesUIUtils.onSidebarTreeClick(event);"
+        onmousemove="PlacesUIUtils.onSidebarTreeMouseMove(event);"
+        onmouseout="PlacesUIUtils.setMouseoverURL('', window);">
     <treecols>
       <treecol id="title" flex="1" primary="true" hideheader="true"/>
     </treecols>
-    <treechildren id="bookmarks-view-children" view="bookmarks-view"
+    <treechildren view="bookmarks-view"
                   class="sidebar-placesTreechildren" flex="1" tooltip="bhTooltip"/>
   </tree>
 </page>
rename from browser/components/places/content/history-panel.js
rename to browser/components/places/content/historySidebar.js
--- a/browser/components/places/content/history-panel.js
+++ b/browser/components/places/content/historySidebar.js
@@ -8,16 +8,21 @@
 ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm");
 
 var gHistoryTree;
 var gSearchBox;
 var gHistoryGrouping = "";
 var gSearching = false;
 
 function HistorySidebarInit() {
+  let uidensity = window.top.document.documentElement.getAttribute("uidensity");
+  if (uidensity) {
+    document.documentElement.setAttribute("uidensity", uidensity);
+  }
+
   gHistoryTree = document.getElementById("historyTree");
   gSearchBox = document.getElementById("search-box");
 
   gHistoryGrouping = document.getElementById("viewButton").
                               getAttribute("selectedsort");
 
   if (gHistoryGrouping == "site")
     document.getElementById("bysite").setAttribute("checked", "true");
@@ -79,17 +84,17 @@ function searchHistory(aInput) {
   options.sortingMode = sortingMode;
   options.resultType = resultType;
   options.includeHidden = !!aInput;
 
   if (gHistoryGrouping == "lastvisited")
     this.TelemetryStopwatch.start("HISTORY_LASTVISITED_TREE_QUERY_TIME_MS");
 
   // call load() on the tree manually
-  // instead of setting the place attribute in history-panel.xul
+  // instead of setting the place attribute in historySidebar.xul
   // otherwise, we will end up calling load() twice
   gHistoryTree.load(query, options);
 
   if (gHistoryGrouping == "lastvisited")
     this.TelemetryStopwatch.finish("HISTORY_LASTVISITED_TREE_QUERY_TIME_MS");
 }
 
 window.addEventListener("SidebarFocused",
rename from browser/components/places/content/history-panel.xul
rename to browser/components/places/content/historySidebar.xul
--- a/browser/components/places/content/history-panel.xul
+++ b/browser/components/places/content/historySidebar.xul
@@ -1,37 +1,32 @@
 <?xml version="1.0"?> <!-- -*- Mode: xml; indent-tabs-mode: nil; -*- -->
-
-# 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/.
+<!-- 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/. -->
 
 <?xml-stylesheet href="chrome://browser/content/places/places.css"?>
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
 
 <!DOCTYPE page [
 <!ENTITY % placesDTD SYSTEM "chrome://browser/locale/places/places.dtd">
 %placesDTD;
 <!ENTITY % editMenuDTD SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
 %editMenuDTD;
 ]>
 
-<!-- we need to keep id="history-panel" for upgrade and switching
-     between versions of the browser -->
-
-<page id="history-panel" orient="vertical"
+<page id="history-panel"
+      orient="vertical"
       xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
       onload="HistorySidebarInit();"
-      onunload="SidebarUtils.setMouseoverURL('');">
+      onunload="PlacesUIUtils.setMouseoverURL('', window);">
 
   <script type="application/javascript"
-          src="chrome://browser/content/bookmarks/sidebarUtils.js"/>
-  <script type="application/javascript"
-          src="chrome://browser/content/places/history-panel.js"/>
+          src="chrome://browser/content/places/historySidebar.js"/>
   <script type="application/javascript"
           src="chrome://global/content/globalOverlay.js"/>
   <script type="application/javascript"
           src="chrome://browser/content/utilityOverlay.js"/>
   <script type="application/javascript"><![CDATA[
     ChromeUtils.defineModuleGetter(window,
       "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm");
     ChromeUtils.defineModuleGetter(window,
@@ -91,20 +86,20 @@
       </menupopup>
     </button>
   </hbox>
 
   <tree id="historyTree"
         class="sidebar-placesTree"
         flex="1"
         type="places"
+        hidecolumnpicker="true"
         context="placesContext"
-        hidecolumnpicker="true"
-        onkeypress="SidebarUtils.handleTreeKeyPress(event);"
-        onclick="SidebarUtils.handleTreeClick(this, event, true);"
-        onmousemove="SidebarUtils.handleTreeMouseMove(event);"
-        onmouseout="SidebarUtils.setMouseoverURL('');">
+        onkeypress="PlacesUIUtils.onSidebarTreeKeyPress(event);"
+        onclick="PlacesUIUtils.onSidebarTreeClick(event);"
+        onmousemove="PlacesUIUtils.onSidebarTreeMouseMove(event);"
+        onmouseout="PlacesUIUtils.setMouseoverURL('', window);">
     <treecols>
       <treecol id="title" flex="1" primary="true" hideheader="true"/>
     </treecols>
     <treechildren class="sidebar-placesTreechildren" flex="1" tooltip="bhTooltip"/>
   </tree>
 </page>
deleted file mode 100644
--- a/browser/components/places/content/organizer.css
+++ /dev/null
@@ -1,7 +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/. */
-
-#searchFilter {
-  width: 23em;
-}
--- a/browser/components/places/content/places.css
+++ b/browser/components/places/content/places.css
@@ -30,8 +30,12 @@ menupopup[placespopup="true"] {
 /* Apply crisp rendering for favicons at exactly 2dppx resolution */
 @media (resolution: 2dppx) {
   #bookmarksChildren,
   .sidebar-placesTreechildren,
   .placesTree > treechildren {
     image-rendering: -moz-crisp-edges;
   }
 }
+
+#searchFilter {
+  max-width: 23em;
+}
--- a/browser/components/places/content/places.xul
+++ b/browser/components/places/content/places.xul
@@ -1,16 +1,15 @@
 <?xml version="1.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/.
 
 <?xml-stylesheet href="chrome://browser/content/places/places.css"?>
-<?xml-stylesheet href="chrome://browser/content/places/organizer.css"?>
 
 <?xml-stylesheet href="chrome://global/skin/"?>
 <?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
 <?xml-stylesheet href="chrome://browser/skin/places/organizer.css"?>
 <?xml-stylesheet href="chrome://browser/skin/places/editBookmark.css"?>
 
 <?xml-stylesheet href="chrome://browser/content/downloads/downloads.css"?>
 <?xml-stylesheet href="chrome://browser/skin/downloads/allDownloadsView.css"?>
@@ -348,16 +347,17 @@
 #else
         </menu>
       </menubar>
 #endif
 
       <spacer id="libraryToolbarSpacer" flex="1"/>
 
       <textbox id="searchFilter"
+               flex="1"
                type="search"
                aria-controls="placeContent"
                oncommand="PlacesSearchBox.search(this.value);"
                collection="bookmarks">
       </textbox>
       <toolbarbutton id="clearDownloadsButton"
 #ifdef XP_MACOSX
                      class="tabbable"
deleted file mode 100644
--- a/browser/components/places/content/sidebarUtils.js
+++ /dev/null
@@ -1,108 +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/. */
-
-/* import-globals-from ../PlacesUIUtils.jsm */
-/* import-globals-from ../../../../toolkit/components/places/PlacesUtils.jsm */
-
-ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
-
-let uidensity = window.top.document.documentElement.getAttribute("uidensity");
-if (uidensity) {
-  document.documentElement.setAttribute("uidensity", uidensity);
-}
-
-var SidebarUtils = {
-  handleTreeClick: function SU_handleTreeClick(aTree, aEvent, aGutterSelect) {
-    // right-clicks are not handled here
-    if (aEvent.button == 2)
-      return;
-
-    var tbo = aTree.treeBoxObject;
-    var cell = tbo.getCellAt(aEvent.clientX, aEvent.clientY);
-
-    if (cell.row == -1 || cell.childElt == "twisty")
-      return;
-
-    var mouseInGutter = false;
-    if (aGutterSelect) {
-      var rect = tbo.getCoordsForCellItem(cell.row, cell.col, "image");
-      // getCoordsForCellItem returns the x coordinate in logical coordinates
-      // (i.e., starting from the left and right sides in LTR and RTL modes,
-      // respectively.)  Therefore, we make sure to exclude the blank area
-      // before the tree item icon (that is, to the left or right of it in
-      // LTR and RTL modes, respectively) from the click target area.
-      var isRTL = window.getComputedStyle(aTree).direction == "rtl";
-      if (isRTL)
-        mouseInGutter = aEvent.clientX > rect.x;
-      else
-        mouseInGutter = aEvent.clientX < rect.x;
-    }
-
-    var metaKey = AppConstants.platform === "macosx" ? aEvent.metaKey
-                                                     : aEvent.ctrlKey;
-    var modifKey = metaKey || aEvent.shiftKey;
-    var isContainer = tbo.view.isContainer(cell.row);
-    var openInTabs = isContainer &&
-                     (aEvent.button == 1 ||
-                      (aEvent.button == 0 && modifKey)) &&
-                     PlacesUtils.hasChildURIs(aTree.view.nodeForTreeIndex(cell.row));
-
-    if (aEvent.button == 0 && isContainer && !openInTabs) {
-      tbo.view.toggleOpenState(cell.row);
-    } else if (!mouseInGutter && openInTabs &&
-            aEvent.originalTarget.localName == "treechildren") {
-      tbo.view.selection.select(cell.row);
-      PlacesUIUtils.openContainerNodeInTabs(aTree.selectedNode, aEvent, aTree);
-    } else if (!mouseInGutter && !isContainer &&
-             aEvent.originalTarget.localName == "treechildren") {
-      // Clear all other selection since we're loading a link now. We must
-      // do this *before* attempting to load the link since openURL uses
-      // selection as an indication of which link to load.
-      tbo.view.selection.select(cell.row);
-      PlacesUIUtils.openNodeWithEvent(aTree.selectedNode, aEvent);
-    }
-  },
-
-  handleTreeKeyPress: function SU_handleTreeKeyPress(aEvent) {
-    let node = aEvent.target.selectedNode;
-    if (node) {
-      if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
-        PlacesUIUtils.openNodeWithEvent(node, aEvent);
-    }
-  },
-
-  /**
-   * The following function displays the URL of a node that is being
-   * hovered over.
-   */
-  handleTreeMouseMove: function SU_handleTreeMouseMove(aEvent) {
-    if (aEvent.target.localName != "treechildren")
-      return;
-
-    var tree = aEvent.target.parentNode;
-    var tbo = tree.treeBoxObject;
-    var cell = tbo.getCellAt(aEvent.clientX, aEvent.clientY);
-
-    // cell.row is -1 when the mouse is hovering an empty area within the tree.
-    // To avoid showing a URL from a previously hovered node for a currently
-    // hovered non-url node, we must clear the moused-over URL in these cases.
-    if (cell.row != -1) {
-      var node = tree.view.nodeForTreeIndex(cell.row);
-      if (PlacesUtils.nodeIsURI(node))
-        this.setMouseoverURL(node.uri);
-      else
-        this.setMouseoverURL("");
-    } else
-      this.setMouseoverURL("");
-  },
-
-  setMouseoverURL: function SU_setMouseoverURL(aURL) {
-    // When the browser window is closed with an open sidebar, the sidebar
-    // unload event happens after the browser's one.  In this case
-    // top.XULBrowserWindow has been nullified already.
-    if (top.XULBrowserWindow) {
-      top.XULBrowserWindow.setOverLink(aURL, null);
-    }
-  }
-};
--- a/browser/components/places/jar.mn
+++ b/browser/components/places/jar.mn
@@ -4,25 +4,20 @@
 
 browser.jar:
 # Provide another URI for the bookmarkProperties dialog so we can persist the
 # attributes separately
 *   content/browser/places/bookmarkProperties2.xul       (content/bookmarkProperties.xul)
 *   content/browser/places/places.xul                    (content/places.xul)
     content/browser/places/places.js                     (content/places.js)
     content/browser/places/places.css                    (content/places.css)
-    content/browser/places/organizer.css                 (content/organizer.css)
 *   content/browser/places/bookmarkProperties.xul        (content/bookmarkProperties.xul)
     content/browser/places/bookmarkProperties.js         (content/bookmarkProperties.js)
     content/browser/places/menu.xml                      (content/menu.xml)
     content/browser/places/tree.xml                      (content/tree.xml)
     content/browser/places/controller.js                 (content/controller.js)
     content/browser/places/treeView.js                   (content/treeView.js)
     content/browser/places/browserPlacesViews.js         (content/browserPlacesViews.js)
-# keep the Places version of the history sidebar at history/history-panel.xul
-# to prevent having to worry about between versions of the browser
-*   content/browser/history/history-panel.xul            (content/history-panel.xul)
-    content/browser/places/history-panel.js              (content/history-panel.js)
-# ditto for the bookmarks sidebar
-*   content/browser/bookmarks/bookmarksPanel.xul         (content/bookmarksPanel.xul)
-    content/browser/bookmarks/bookmarksPanel.js          (content/bookmarksPanel.js)
-    content/browser/bookmarks/sidebarUtils.js            (content/sidebarUtils.js)
+*   content/browser/places/historySidebar.xul            (content/historySidebar.xul)
+    content/browser/places/historySidebar.js             (content/historySidebar.js)
+*   content/browser/places/bookmarksSidebar.xul          (content/bookmarksSidebar.xul)
+    content/browser/places/bookmarksSidebar.js           (content/bookmarksSidebar.js)
     content/browser/places/editBookmark.js               (content/editBookmark.js)
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.js
@@ -28,17 +28,16 @@ function updateTPInfo() {
   tpSubHeader.classList.toggle("tp-off", !trackingEnabled);
 }
 
 document.addEventListener("DOMContentLoaded", function() {
   let aboutCapabilities = document.aboutCapabilities;
   if (!aboutCapabilities.isWindowPrivate()) {
     document.documentElement.classList.remove("private");
     document.documentElement.classList.add("normal");
-    document.title = document.querySelector("title").getAttribute("notprivatetitle");
     document.getElementById("favicon").setAttribute("href", FAVICON_QUESTION);
     document.getElementById("startPrivateBrowsing").addEventListener("click", function() {
       aboutCapabilities.sendAsyncMessage("OpenPrivateWindow", null);
     });
     return;
   }
 
   document.getElementById("startTour").addEventListener("click", function() {
--- a/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
+++ b/browser/components/privatebrowsing/content/aboutPrivateBrowsing.xhtml
@@ -18,17 +18,16 @@
 ]>
 
 <html xmlns="http://www.w3.org/1999/xhtml" class="private">
   <head>
     <meta http-equiv="Content-Security-Policy" content="default-src chrome:"/>
     <link id="favicon" rel="icon" type="image/png" href="chrome://browser/skin/privatebrowsing/favicon.svg"/>
     <link rel="stylesheet" href="chrome://browser/content/aboutPrivateBrowsing.css" type="text/css" media="all"/>
     <link rel="stylesheet" href="chrome://browser/skin/privatebrowsing/aboutPrivateBrowsing.css" type="text/css" media="all"/>
-    <title notprivatetitle="&aboutPrivateBrowsing.notPrivate.title;">&aboutPrivateBrowsing.title;</title>
     <script type="application/javascript" src="chrome://browser/content/aboutPrivateBrowsing.js"></script>
   </head>
 
   <body dir="&locale.dir;">
     <p class="showNormal">&aboutPrivateBrowsing.notPrivate;</p>
     <button id="startPrivateBrowsing"
             class="showNormal"
             accesskey="&privatebrowsingpage.openPrivateWindow.accesskey;">&privatebrowsingpage.openPrivateWindow.label;</button>
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_windowtitle.js
@@ -18,24 +18,24 @@ add_task(async function test() {
   let page_without_title;
   let about_pb_title;
   let pb_page_with_title;
   let pb_page_without_title;
   let pb_about_pb_title;
   if (isOSX) {
     page_with_title = test_title;
     page_without_title = app_name;
-    about_pb_title = "Open a private window?";
+    about_pb_title = app_name;
     pb_page_with_title = test_title + " - (Private Browsing)";
     pb_page_without_title = app_name + " - (Private Browsing)";
     pb_about_pb_title = app_name + " - (Private Browsing)";
   } else {
     page_with_title = test_title + " - " + app_name;
     page_without_title = app_name;
-    about_pb_title = "Open a private window? - " + app_name;
+    about_pb_title = app_name;
     pb_page_with_title = test_title + " - " + app_name + " (Private Browsing)";
     pb_page_without_title = app_name + " (Private Browsing)";
     pb_about_pb_title = app_name + " (Private Browsing)";
   }
 
   async function testTabTitle(aWindow, url, insidePB, expected_title) {
     let tab = (await BrowserTestUtils.openNewForegroundTab(aWindow.gBrowser));
     await BrowserTestUtils.loadURI(tab.linkedBrowser, url);
--- a/browser/locales/en-US/chrome/browser/aboutPrivateBrowsing.dtd
+++ b/browser/locales/en-US/chrome/browser/aboutPrivateBrowsing.dtd
@@ -1,17 +1,12 @@
 <!-- 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/. -->
 
-<!-- LOCALIZATION NOTE (aboutPrivateBrowsing.title):
-     Please ensure this exactly matches tabs.emptyPrivateTabTitle in tabbrowser.properties -->
-<!ENTITY aboutPrivateBrowsing.title                      "Private Browsing">
-<!ENTITY aboutPrivateBrowsing.notPrivate.title           "Open a private window?">
-
 <!ENTITY aboutPrivateBrowsing.notPrivate                 "You are currently not in a private window.">
 <!ENTITY privatebrowsingpage.openPrivateWindow.label     "Open a Private Window">
 <!ENTITY privatebrowsingpage.openPrivateWindow.accesskey "P">
 
 <!ENTITY privateBrowsing.title                           "Private Browsing">
 <!ENTITY privateBrowsing.title.tracking                  "Private Browsing with Tracking Protection">
 <!ENTITY aboutPrivateBrowsing.info.notsaved.before       "When you browse in a Private Window, Firefox ">
 <!ENTITY aboutPrivateBrowsing.info.notsaved.emphasize    "does not save">
--- a/browser/locales/en-US/chrome/browser/tabbrowser.properties
+++ b/browser/locales/en-US/chrome/browser/tabbrowser.properties
@@ -1,16 +1,14 @@
 # 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/.
 
 tabs.restoreLastTabs=Restore Tabs From Last Time
 tabs.emptyTabTitle=New Tab
-# LOCALIZATION NOTE (tabs.emptyPrivateTabTitle)
-# Please ensure this exactly matches aboutPrivateBrowsing.dtd's window title (aboutPrivateBrowsing.title).
 tabs.emptyPrivateTabTitle=Private Browsing
 tabs.closeTab=Close Tab
 tabs.close=Close
 tabs.closeWarningTitle=Confirm close
 # LOCALIZATION NOTE (tabs.closeWarningMultiple):
 # Semicolon-separated list of plural forms. See:
 # http://developer.mozilla.org/en/docs/Localization_and_Plurals
 # The singular form is not considered since this string is used only for
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Tabs.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/Tabs.jsm
@@ -127,17 +127,17 @@ var Tabs = {
 
 /* helpers */
 
 async function allTabTitlesDisplayed(browserWindow) {
   let specToTitleMap = {
     "about:home": "New Tab",
     "about:newtab": "New Tab",
     "about:addons": "Add-ons Manager",
-    "about:privatebrowsing": "Open a private window?"
+    "about:privatebrowsing": "about:privatebrowsing"
   };
   specToTitleMap[PREFS_TAB] = "browser/skin/settings.svg";
   specToTitleMap[CUST_TAB] = "browser/skin/customize.svg";
   specToTitleMap[DEFAULT_FAVICON_TAB] = "No favicon";
 
   let tabTitlePromises = [];
   for (let tab of browserWindow.gBrowser.tabs) {
     function tabTitleLoaded(spec) {
--- a/devtools/client/animationinspector/test/head.js
+++ b/devtools/client/animationinspector/test/head.js
@@ -20,19 +20,23 @@ const ANIMATION_L10N =
 registerCleanupFunction(async function() {
   await closeAnimationInspector();
 
   while (gBrowser.tabs.length > 1) {
     gBrowser.removeCurrentTab();
   }
 });
 
+// Disable new animation inspector.
+Services.prefs.setBoolPref("devtools.new-animationinspector.enabled", false);
+
 // Clean-up all prefs that might have been changed during a test run
 // (safer here because if the test fails, then the pref is never reverted)
 registerCleanupFunction(() => {
+  Services.prefs.clearUserPref("devtools.new-animationinspector.enabled");
   Services.prefs.clearUserPref("devtools.debugger.log");
 });
 
 // Some animation features are not enabled by default in release/beta channels
 // yet including:
 // * parts of the Web Animations API (Bug 1264101), and
 // * the frames() timing function (Bug 1379582).
 function enableAnimationFeatures() {
--- a/devtools/client/inspector/animation/test/head.js
+++ b/devtools/client/inspector/animation/test/head.js
@@ -10,24 +10,20 @@ Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/inspector/test/head.js", this);
 
 const FRAME_SCRIPT_URL = CHROME_URL_ROOT + "doc_frame_script.js";
 const TAB_NAME = "newanimationinspector";
 
 const ANIMATION_L10N =
   new LocalizationHelper("devtools/client/locales/animationinspector.properties");
 
-// Enable new animation inspector.
-Services.prefs.setBoolPref("devtools.new-animationinspector.enabled", true);
-
 // Auto clean-up when a test ends.
 // Clean-up all prefs that might have been changed during a test run
 // (safer here because if the test fails, then the pref is never reverted)
 registerCleanupFunction(() => {
-  Services.prefs.clearUserPref("devtools.new-animationinspector.enabled");
   Services.prefs.clearUserPref("devtools.toolsidebar-width.inspector");
 });
 
 /**
  * Open the toolbox, with the inspector tool visible and the animationinspector
  * sidebar selected.
  *
  * @return {Promise} that resolves when the inspector is ready.
--- a/devtools/client/inspector/markup/test/browser_markup_events_click_to_close.js
+++ b/devtools/client/inspector/markup/test/browser_markup_events_click_to_close.js
@@ -50,19 +50,24 @@ add_task(async function() {
   await onHidden;
   info("previous tooltip hidden");
 
   await onShown;
   info("event tooltip for the second div is shown");
 
   info("Click on the animation inspector tab");
   let onHighlighterHidden = toolbox.once("node-unhighlight");
-  let onTabInspectorSelected = inspector.sidebar.once("animationinspector-selected");
-  let animationInspectorTab = inspector.panelDoc.querySelector("#animationinspector-tab");
+  let onTabInspectorSelected = inspector.sidebar.once("newanimationinspector-selected");
+  let onInspectorUpdated = inspector.once("inspector-updated");
+  let animationInspectorTab =
+    inspector.panelDoc.querySelector("#newanimationinspector-tab");
   EventUtils.synthesizeMouseAtCenter(animationInspectorTab, {},
     inspector.panelDoc.defaultView);
 
   await onTabInspectorSelected;
   info("animation inspector was selected");
 
+  await onInspectorUpdated;
+  info("animation inspector was updated");
+
   await onHighlighterHidden;
   info("box model highlighter hidden after moving the mouse out of the markup view");
 });
--- a/devtools/client/preferences/devtools.js
+++ b/devtools/client/preferences/devtools.js
@@ -67,18 +67,22 @@ pref("devtools.inspector.flexboxHighligh
 // Enable the CSS shapes highlighter
 pref("devtools.inspector.shapesHighlighter.enabled", true);
 // Enable the Changes View
 pref("devtools.changesview.enabled", false);
 // Enable the Events View
 pref("devtools.eventsview.enabled", false);
 // Enable the Flexbox Inspector panel
 pref("devtools.flexboxinspector.enabled", false);
-// Enable the new Animation Inspector
+// Enable the new Animation Inspector in Nightly only
+#if defined(NIGHTLY_BUILD)
+pref("devtools.new-animationinspector.enabled", true);
+#else
 pref("devtools.new-animationinspector.enabled", false);
+#endif
 // Enable the Variable Fonts editor
 pref("devtools.inspector.fonteditor.enabled", false);
 
 // Grid highlighter preferences
 pref("devtools.gridinspector.gridOutlineMaxColumns", 50);
 pref("devtools.gridinspector.gridOutlineMaxRows", 50);
 pref("devtools.gridinspector.showGridAreas", false);
 pref("devtools.gridinspector.showGridLineNumbers", false);
--- a/devtools/server/actors/highlighters/css-grid.js
+++ b/devtools/server/actors/highlighters/css-grid.js
@@ -1136,21 +1136,21 @@ class CssGridHighlighter extends AutoRef
    *         The line position along the x-axis for a column grid line and
    *         y-axis for a row grid line.
    * @param  {Number} startPos
    *         The start position of the cross side of the grid line.
    * @param  {Number} breadth
    *         The grid line breadth value.
    * @param  {String} dimensionType
    *         The grid dimension type which is either the constant COLUMNS or ROWS.
-   * @param  {Number||undefined} stackedLineIndex
-   *         The line index position of the stacked line.
+   * @param  {Boolean||undefined} isStackedLine
+   *         Boolean indicating if the line is stacked.
    */
   renderGridLineNumber(lineNumber, linePos, startPos, breadth, dimensionType,
-    stackedLineIndex) {
+    isStackedLine) {
     let displayPixelRatio = getDisplayPixelRatio(this.win);
     let { devicePixelRatio } = this.win;
     let offset = (displayPixelRatio / 2) % 1;
     let fontSize = GRID_FONT_SIZE * displayPixelRatio;
     let canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
     let canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
 
     linePos = Math.round(linePos);
@@ -1201,17 +1201,17 @@ class CssGridHighlighter extends AutoRef
         x -= offsetFromEdge;
       } else {
         x += offsetFromEdge;
       }
     }
 
     [x, y] = apply(this.currentMatrix, [x, y]);
 
-    if (stackedLineIndex) {
+    if (isStackedLine) {
       // Offset the stacked line number by half of the box's width/height.
       const xOffset = boxWidth / 4;
       const yOffset = boxHeight / 4;
 
       if (lineNumber > 0) {
         x -= xOffset;
         y -= yOffset;
       } else {
@@ -1349,17 +1349,17 @@ class CssGridHighlighter extends AutoRef
         y += (boxHeight + arrowSize + radius) - boxHeight / 2;
         break;
     }
 
     // Write the line number inside of the rectangle.
     this.ctx.textAlign = "center";
     this.ctx.textBaseline = "middle";
     this.ctx.fillStyle = "black";
-    const numberText = stackedLineIndex ? "" : lineNumber;
+    const numberText = isStackedLine ? "" : lineNumber;
     this.ctx.fillText(numberText, x, y);
     this.ctx.restore();
   }
 
   /**
    * Render the grid line on the css grid highlighter canvas.
    *
    * @param  {Number} linePos
@@ -1467,48 +1467,42 @@ class CssGridHighlighter extends AutoRef
    * @param  {String} dimensionType
    *         The grid dimension type which is either the constant COLUMNS or ROWS.
    * @param  {Number} startPos
    *         The start position of the cross side ("left" for ROWS and "top" for COLUMNS)
    *         of the grid dimension.
    */
   renderLineNumbers(gridDimension, dimensionType, startPos) {
     const { lines, tracks } = gridDimension;
-    // Keep track of the number of collapsed lines per line position.
-    let stackedLines = [];
 
     for (let i = 0, line; (line = lines[i++]);) {
       // If you place something using negative numbers, you can trigger some implicit
       // grid creation above and to the left of the explicit grid (assuming a
       // horizontal-tb writing mode).
       //
       // The first explicit grid line gets the number of 1, and any implicit grid lines
       // before 1 get negative numbers. Since here we're rendering only the positive line
       // numbers, we have to skip any implicit grid lines before the first one that is
       // explicit. The API returns a 0 as the line's number for these implicit lines that
       // occurs before the first explicit line.
       if (line.number === 0) {
         continue;
       }
 
-      // Check for overlapping lines. We render a second box beneath the last overlapping
+      // Check for overlapping lines by measuring the track width between them.
+      // We render a second box beneath the last overlapping
       // line number to indicate there are lines beneath it.
-      const gridLine = tracks[line.number - 1];
+      const gridTrack = tracks[i - 1];
 
-      if (gridLine) {
-        const { breadth }  = gridLine;
+      if (gridTrack) {
+        const { breadth }  = gridTrack;
 
         if (breadth === 0) {
-          stackedLines.push(lines[i].number);
-
-          if (stackedLines.length > 0) {
-            this.renderGridLineNumber(line.number, line.start, startPos, line.breadth,
-              dimensionType, 1);
-          }
-
+          this.renderGridLineNumber(line.number, line.start, startPos, line.breadth,
+            dimensionType, true);
           continue;
         }
       }
 
       this.renderGridLineNumber(line.number, line.start, startPos, line.breadth,
         dimensionType);
     }
   }
@@ -1522,54 +1516,41 @@ class CssGridHighlighter extends AutoRef
    * @param  {String} dimensionType
    *         The grid dimension type which is either the constant COLUMNS or ROWS.
    * @param  {Number} startPos
    *         The start position of the cross side ("left" for ROWS and "top" for COLUMNS)
    *         of the grid dimension.
    */
   renderNegativeLineNumbers(gridDimension, dimensionType, startPos) {
     const { lines, tracks } = gridDimension;
-    // Keep track of the number of collapsed lines per line position.
-    let stackedLines = [];
 
     for (let i = 0, line; (line = lines[i++]);) {
       let linePos = line.start;
       let negativeLineNumber = line.negativeNumber;
 
       // Don't render any negative line number greater than -1.
       if (negativeLineNumber == 0) {
         break;
       }
 
-      // Check for overlapping lines. We render a second box beneath the last overlapping
+      // Check for overlapping lines by measuring the track width between them.
+      // We render a second box beneath the last overlapping
       // line number to indicate there are lines beneath it.
-      const gridLine = tracks[line.number - 1];
-
-      if (gridLine) {
-        const { breadth }  = gridLine;
+      const gridTrack = tracks[i - 1];
+      if (gridTrack) {
+        const { breadth } = gridTrack;
 
-        if (breadth === 0) {
-          stackedLines.push(negativeLineNumber);
-
-          if (stackedLines.length > 0) {
-            this.renderGridLineNumber(negativeLineNumber, linePos, startPos,
-              line.breadth, dimensionType, 1);
-          }
-
+        // Ensure "-1" is always visible, since it is always the largest number.
+        if (breadth === 0 && negativeLineNumber != -1) {
+          this.renderGridLineNumber(negativeLineNumber, linePos, startPos,
+            line.breadth, dimensionType, true);
           continue;
         }
       }
 
-      // For negative line numbers, we want to display the smallest
-      // value at the front of the stack.
-      if (stackedLines.length) {
-        negativeLineNumber = stackedLines[0];
-        stackedLines = [];
-      }
-
       this.renderGridLineNumber(negativeLineNumber, linePos, startPos, line.breadth,
         dimensionType);
     }
   }
 
   /**
    * Update the highlighter on the current highlighted node (the one that was
    * passed as an argument to show(node)). Should be called whenever node's geometry
--- a/dom/animation/test/mozilla/file_restyles.html
+++ b/dom/animation/test/mozilla/file_restyles.html
@@ -625,17 +625,17 @@ waitForAllPaints(() => {
                   100 * MS_PER_SEC);
     parentElement.appendChild(div);
 
     await animation.ready;
     ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
 
     const expectedRestyleCount = tweakExpectedRestyleCount(animation, 20);
 
-    var markers = await observeStyling(expectedRestyleCount);
+    var markers = await observeStyling(20);
     is(markers.length, expectedRestyleCount,
        'Finite transform animation in out-of-view element should never be ' +
        'throttled');
 
     await ensureElementRemoval(parentElement);
   });
 
   add_task(async function restyling_main_thread_animations_in_scrolled_out_element() {
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -270,20 +270,16 @@ ShadowRoot::RuleChanged(StyleSheet&, css
 
 void
 ShadowRoot::ApplicableRulesChanged()
 {
   if (!IsComposedDocParticipant()) {
     return;
   }
 
-  if (!IsComposedDocParticipant()) {
-    return;
-  }
-
   nsIDocument* doc = OwnerDoc();
   if (nsIPresShell* shell = doc->GetShell()) {
     doc->BeginUpdate(UPDATE_STYLE);
     shell->RecordShadowStyleChange(*this);
     doc->EndUpdate(UPDATE_STYLE);
   }
 }
 
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -241,24 +241,16 @@ public:
     NS_ASSERTION(!IsInNativeAnonymousSubtree() || GetBindingParent() ||
                  (!IsInUncomposedDoc() &&
                   static_cast<nsIContent*>(SubtreeRoot())->IsInNativeAnonymousSubtree()),
                  "Must have binding parent when in native anonymous subtree which is in document.\n"
                  "Native anonymous subtree which is not in document must have native anonymous root.");
     return IsInNativeAnonymousSubtree() || (!IsInShadowTree() && GetBindingParent() != nullptr);
   }
 
-  /*
-   * Return true if this node is the shadow root of an use-element shadow tree.
-   */
-  bool IsRootOfUseElementShadowTree() const {
-    return GetParent() && GetParent()->IsSVGElement(nsGkAtoms::use) &&
-           IsRootOfAnonymousSubtree();
-  }
-
   /**
    * Return true iff this node is in an HTML document (in the HTML5 sense of
    * the term, i.e. not in an XHTML/XML document).
    */
   inline bool IsInHTMLDocument() const;
 
 
   /**
--- a/dom/base/test/file_bug416317.xhtml
+++ b/dom/base/test/file_bug416317.xhtml
@@ -222,23 +222,17 @@
     ::select { background: red; }
 
     ..test { background: red; color: yellow; }
     .foo..quux { background: red; color: yellow; }
     .bar. { background: red; color: yellow; }
   </span>
   <script><![CDATA[
   window.onload = function() {
-    if (window.parent && window.parent.SpecialPowers) {
-      window.parent.SpecialPowers.pushPrefEnv(
-        { 'set': [[ "layout.css.scope-pseudo.enabled", true]] },
-        doTest);
-    } else {
-      doTest();
-    }
+    doTest();
   }
 
   function doTest(){
     if ( !window.location.hash.includes("target") )
       window.location.hash = "#target";
 
     var root = document.getElementById("root");
     var root2 = document.getElementById("root2");
--- a/dom/xslt/base/txDouble.cpp
+++ b/dom/xslt/base/txDouble.cpp
@@ -22,29 +22,28 @@
 
 /*
  * Converts the given String to a double, if the String value does not
  * represent a double, NaN will be returned
  */
 class txStringToDouble
 {
 public:
-    typedef char16_t input_type;
-    typedef char16_t value_type;
     txStringToDouble(): mState(eWhitestart), mSign(ePositive) {}
 
     void
-    write(const input_type* aSource, uint32_t aSourceLength)
+    Parse(const nsAString& aSource)
     {
         if (mState == eIllegal) {
             return;
         }
         uint32_t i = 0;
         char16_t c;
-        for ( ; i < aSourceLength; ++i) {
+        auto len = aSource.Length();
+        for ( ; i < len; ++i) {
             c = aSource[i];
             switch (mState) {
                 case eWhitestart:
                     if (c == '-') {
                         mState = eDecimal;
                         mSign = eNegative;
                     }
                     else if (c >= '0' && c <= '9') {
@@ -122,18 +121,17 @@ private:
         eNegative = -1,
         ePositive = 1
     } mSign;
 };
 
 double txDouble::toDouble(const nsAString& aSrc)
 {
     txStringToDouble sink;
-    nsAString::const_iterator fromBegin, fromEnd;
-    copy_string(aSrc.BeginReading(fromBegin), aSrc.EndReading(fromEnd), sink);
+    sink.Parse(aSrc);
     return sink.getDouble();
 }
 
 /*
  * Converts the value of the given double to a String, and places
  * The result into the destination String.
  * @return the given dest string
  */
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -170,17 +170,18 @@ void
 js::InitMallocAllocator()
 {
     MallocArena = moz_create_arena();
 }
 
 void
 js::ShutDownMallocAllocator()
 {
-    moz_dispose_arena(MallocArena);
+    // Until Bug 1364359 is fixed it is unsafe to call moz_dispose_arena.
+    // moz_dispose_arena(MallocArena);
 }
 
 JS_PUBLIC_API(void)
 JS_Assert(const char* s, const char* file, int ln)
 {
     MOZ_ReportAssertionFailure(s, file, ln);
     MOZ_CRASH();
 }
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -16,17 +16,16 @@
 #include "nsComputedDOMStyle.h"
 #include "nsContentDLF.h"
 #include "nsContentUtils.h"
 #include "nsCSSAnonBoxes.h"
 #include "mozilla/css/ErrorReporter.h"
 #include "nsCSSKeywords.h"
 #include "nsCSSParser.h"
 #include "nsCSSProps.h"
-#include "nsCSSPseudoClasses.h"
 #include "nsCSSPseudoElements.h"
 #include "nsCSSRendering.h"
 #include "nsGenericHTMLFrameElement.h"
 #include "mozilla/dom/Attr.h"
 #include "nsDOMClassInfo.h"
 #include "mozilla/EventListenerManager.h"
 #include "nsFrame.h"
 #include "nsGlobalWindow.h"
@@ -139,17 +138,16 @@ nsLayoutStatics::Initialize()
 
   nsresult rv;
 
   ContentParent::StartUp();
 
   // Register static atoms. Note that nsGkAtoms must be initialized earlier
   // than here, so it's done in NS_InitAtomTable() instead.
   nsCSSAnonBoxes::RegisterStaticAtoms();
-  nsCSSPseudoClasses::RegisterStaticAtoms();
   nsCSSPseudoElements::RegisterStaticAtoms();
   nsCSSKeywords::AddRefTable();
   nsCSSProps::AddRefTable();
   nsColorNames::AddRefTable();
 
   NS_SetStaticAtomsDone();
 
   StartupJSEnvironment();
--- a/layout/inspector/InspectorUtils.cpp
+++ b/layout/inspector/InspectorUtils.cpp
@@ -27,17 +27,16 @@
 #include "ChildIterator.h"
 #include "nsComputedDOMStyle.h"
 #include "mozilla/EventStateManager.h"
 #include "nsAtom.h"
 #include "nsRange.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/dom/CharacterData.h"
 #include "mozilla/dom/Element.h"
-#include "nsCSSPseudoClasses.h"
 #include "mozilla/dom/CSSLexer.h"
 #include "mozilla/dom/InspectorUtilsBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "nsCSSParser.h"
 #include "nsCSSProps.h"
 #include "nsCSSValue.h"
 #include "nsColor.h"
 #include "mozilla/StyleSetHandleInlines.h"
@@ -975,49 +974,21 @@ InspectorUtils::GetUsedFontFaces(GlobalO
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
 }
 
 static EventStates
 GetStatesForPseudoClass(const nsAString& aStatePseudo)
 {
-  // An array of the states that are relevant for various pseudoclasses.
-  // XXXbz this duplicates code in nsCSSRuleProcessor
-  static const EventStates sPseudoClassStates[] = {
-#define CSS_PSEUDO_CLASS(_name, _value, _flags, _pref) \
-    EventStates(),
-#define CSS_STATE_PSEUDO_CLASS(_name, _value, _flags, _pref, _states) \
-    _states,
-#include "nsCSSPseudoClassList.h"
-#undef CSS_STATE_PSEUDO_CLASS
-#undef CSS_PSEUDO_CLASS
-
-    // Add more entries for our fake values to make sure we can't
-    // index out of bounds into this array no matter what.
-    EventStates(),
-    EventStates()
-  };
-  static_assert(MOZ_ARRAY_LENGTH(sPseudoClassStates) ==
-                static_cast<size_t>(CSSPseudoClassType::MAX),
-                "Length of PseudoClassStates array is incorrect");
-
-  RefPtr<nsAtom> atom = NS_Atomize(aStatePseudo);
-  CSSPseudoClassType type = nsCSSPseudoClasses::
-    GetPseudoType(atom, CSSEnabledState::eIgnoreEnabledState);
-
-  // Ignore :any-link so we don't give the element simultaneous
-  // visited and unvisited style state
-  if (type == CSSPseudoClassType::anyLink ||
-      type == CSSPseudoClassType::mozAnyLink) {
+  if (aStatePseudo.IsEmpty() || aStatePseudo[0] != u':') {
     return EventStates();
   }
-  // Our array above is long enough that indexing into it with
-  // NotPseudo is ok.
-  return sPseudoClassStates[static_cast<CSSPseudoClassTypeBase>(type)];
+  NS_ConvertUTF16toUTF8 statePseudo(Substring(aStatePseudo, 1));
+  return EventStates(Servo_PseudoClass_GetStates(&statePseudo));
 }
 
 /* static */ void
 InspectorUtils::GetCSSPseudoElementNames(GlobalObject& aGlobalObject,
                                          nsTArray<nsString>& aResult)
 {
   const CSSPseudoElementTypeBase pseudoCount =
     static_cast<CSSPseudoElementTypeBase>(CSSPseudoElementType::Count);
--- a/layout/style/CSSKeyframesRule.h
+++ b/layout/style/CSSKeyframesRule.h
@@ -2,30 +2,32 @@
 /* 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_CSSKeyframesRule_h
 #define mozilla_dom_CSSKeyframesRule_h
 
-#include "mozilla/css/GroupRule.h"
+#include "mozilla/css/Rule.h"
 #include "mozilla/dom/CSSKeyframeRule.h"
 
 namespace mozilla {
 namespace dom {
 
-class CSSKeyframesRule : public css::GroupRule
+class CSSKeyframesRule : public css::Rule
 {
 protected:
-  using css::GroupRule::GroupRule;
+  using css::Rule::Rule;
   virtual ~CSSKeyframesRule() {}
 
 public:
   int32_t GetType() const final { return Rule::KEYFRAMES_RULE; }
+  // Let's not worry for now about sorting out whether we're a leaf or not.
+  bool IsCCLeaf() const override { return false; }
 
   // WebIDL interface
   uint16_t Type() const final { return CSSRuleBinding::KEYFRAMES_RULE; }
   virtual void GetName(nsAString& aName) const = 0;
   virtual void SetName(const nsAString& aName) = 0;
   virtual CSSRuleList* CssRules() = 0;
   virtual void AppendRule(const nsAString& aRule) = 0;
   virtual void DeleteRule(const nsAString& aKey) = 0;
--- a/layout/style/GroupRule.cpp
+++ b/layout/style/GroupRule.cpp
@@ -13,76 +13,30 @@
 
 #include "mozilla/dom/CSSRuleList.h"
 
 using namespace mozilla::dom;
 
 namespace mozilla {
 namespace css {
 
-#define CALL_INNER(inner_, call_)               \
-  ((inner_).is<DummyGroupRuleRules>()           \
-    ? (inner_).as<DummyGroupRuleRules>().call_  \
-    : (inner_).as<ServoGroupRuleRules>().call_)
-
-
-// -------------------------------
-// ServoGroupRuleRules
-//
-
-ServoGroupRuleRules::~ServoGroupRuleRules()
-{
-  if (mRuleList) {
-    mRuleList->DropReference();
-  }
-}
-
-#ifdef DEBUG
-void
-ServoGroupRuleRules::List(FILE* out, int32_t aIndent) const
-{
-  // TODO list something reasonable?
-}
-#endif
-
-size_t
-ServoGroupRuleRules::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
-{
-  // TODO how to implement?
-  return 0;
-}
-
-// -------------------------------
-// GroupRule
-//
-
-GroupRule::GroupRule(uint32_t aLineNumber, uint32_t aColumnNumber)
-  : Rule(aLineNumber, aColumnNumber)
-  , mInner(DummyGroupRuleRules())
-{
-}
-
 GroupRule::GroupRule(already_AddRefed<ServoCssRules> aRules,
                      uint32_t aLineNumber, uint32_t aColumnNumber)
   : Rule(aLineNumber, aColumnNumber)
-  , mInner(ServoGroupRuleRules(Move(aRules)))
+  , mRuleList(new ServoCSSRuleList(Move(aRules), nullptr))
 {
-  mInner.as<ServoGroupRuleRules>().SetParentRule(this);
-}
-
-GroupRule::GroupRule(const GroupRule& aCopy)
-  : Rule(aCopy)
-  , mInner(aCopy.mInner)
-{
-  CALL_INNER(mInner, SetParentRule(this));
+  mRuleList->SetParentRule(this);
 }
 
 GroupRule::~GroupRule()
 {
   MOZ_ASSERT(!mSheet, "SetStyleSheet should have been called");
+  if (mRuleList) {
+    mRuleList->DropReference();
+  }
 }
 
 NS_IMPL_ADDREF_INHERITED(GroupRule, Rule)
 NS_IMPL_RELEASE_INHERITED(GroupRule, Rule)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GroupRule)
 NS_INTERFACE_MAP_END_INHERITING(Rule)
 
@@ -91,53 +45,59 @@ GroupRule::IsCCLeaf() const
 {
   // Let's not worry for now about sorting out whether we're a leaf or not.
   return false;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(GroupRule)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(GroupRule, Rule)
-  CALL_INNER(tmp->mInner, SetParentRule(nullptr));
-  // If tmp does not have a stylesheet, neither do its descendants.  In that
-  // case, don't try to null out their stylesheet, to avoid O(N^2) behavior in
-  // depth of group rule nesting.  But if tmp _does_ have a stylesheet (which
-  // can happen if it gets unlinked earlier than its owning stylesheet), then we
-  // need to null out the stylesheet pointer on descendants now, before we clear
-  // tmp->mRules.
-  if (tmp->GetStyleSheet()) {
-    CALL_INNER(tmp->mInner, SetStyleSheet(nullptr));
+  if (tmp->mRuleList) {
+    tmp->mRuleList->SetParentRule(nullptr);
+    // If tmp does not have a stylesheet, neither do its descendants.
+    // In that case, don't try to null out their stylesheet, to avoid
+    // O(N^2) behavior in depth of group rule nesting.  But if tmp
+    // _does_ have a stylesheet (which can happen if it gets unlinked
+    // earlier than its owning stylesheet), then we need to null out the
+    // stylesheet pointer on descendants now, before we clear mRuleList.
+    if (tmp->GetStyleSheet()) {
+      tmp->mRuleList->SetStyleSheet(nullptr);
+    }
+    tmp->mRuleList->DropReference();
+    tmp->mRuleList = nullptr;
   }
-  CALL_INNER(tmp->mInner, Clear());
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GroupRule, Rule)
-  CALL_INNER(tmp->mInner, Traverse(cb));
+  ImplCycleCollectionTraverse(cb, tmp->mRuleList, "mRuleList");
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
+#ifdef DEBUG
+void
+GroupRule::List(FILE* out, int32_t aIndent) const
+{
+  // TODO list something reasonable?
+}
+#endif
+
 /* virtual */ void
 GroupRule::SetStyleSheet(StyleSheet* aSheet)
 {
   // Don't set the sheet on the kids if it's already the same as the sheet we
   // already have.  This is needed to avoid O(N^2) behavior in group nesting
   // depth when seting the sheet to null during unlink, if we happen to unlin in
   // order from most nested rule up to least nested rule.
   if (aSheet != GetStyleSheet()) {
-    CALL_INNER(mInner, SetStyleSheet(aSheet));
+    if (mRuleList) {
+      mRuleList->SetStyleSheet(aSheet);
+    }
     Rule::SetStyleSheet(aSheet);
   }
 }
 
-
-CSSRuleList*
-GroupRule::CssRules()
-{
-  return CALL_INNER(mInner, CssRules(this));
-}
-
 uint32_t
 GroupRule::InsertRule(const nsAString& aRule, uint32_t aIndex, ErrorResult& aRv)
 {
   StyleSheet* sheet = GetStyleSheet();
   if (NS_WARN_IF(!sheet)) {
     aRv.Throw(NS_ERROR_FAILURE);
     return 0;
   }
@@ -176,12 +136,17 @@ GroupRule::DeleteRule(uint32_t aIndex, E
   NS_ASSERTION(count <= INT32_MAX, "Too many style rules!");
 
   nsresult rv = sheet->DeleteRuleFromGroup(this, aIndex);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
 }
 
-#undef CALL_INNER
+size_t
+GroupRule::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  // TODO how to implement?
+  return 0;
+}
 
 } // namespace css
 } // namespace mozilla
--- a/layout/style/GroupRule.h
+++ b/layout/style/GroupRule.h
@@ -11,181 +11,80 @@
 
 #ifndef mozilla_css_GroupRule_h__
 #define mozilla_css_GroupRule_h__
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/ServoCSSRuleList.h"
-#include "mozilla/Variant.h"
 #include "mozilla/css/Rule.h"
 #include "nsCycleCollectionParticipant.h"
 
-class nsPresContext;
-class nsMediaQueryResultCacheKey;
-
 namespace mozilla {
 
 class StyleSheet;
 
 namespace dom {
 class CSSRuleList;
 } // namespace dom
 
 namespace css {
 
-class GroupRule;
-class GroupRuleRuleList;
-
-
-struct ServoGroupRuleRules
-{
-  explicit ServoGroupRuleRules(already_AddRefed<ServoCssRules> aRawRules)
-    : mRuleList(new ServoCSSRuleList(Move(aRawRules), nullptr)) {}
-  ServoGroupRuleRules(ServoGroupRuleRules&& aOther)
-    : mRuleList(Move(aOther.mRuleList)) {}
-  ServoGroupRuleRules(const ServoGroupRuleRules& aCopy) {
-    // Do we ever clone Servo rules?
-    MOZ_ASSERT_UNREACHABLE("stylo: Cloning GroupRule not implemented");
-  }
-  ~ServoGroupRuleRules();
-
-  void SetParentRule(GroupRule* aParentRule) {
-    if (mRuleList) {
-      mRuleList->SetParentRule(aParentRule);
-    }
-  }
-  void SetStyleSheet(StyleSheet* aSheet) {
-    if (mRuleList) {
-      mRuleList->SetStyleSheet(aSheet);
-    }
-  }
-
-  void Clear() {
-    if (mRuleList) {
-      mRuleList->DropReference();
-      mRuleList = nullptr;
-    }
-  }
-  void Traverse(nsCycleCollectionTraversalCallback& cb) {
-    ImplCycleCollectionTraverse(cb, mRuleList, "mRuleList");
-  }
-
-#ifdef DEBUG
-  void List(FILE* out, int32_t aIndent) const;
-#endif
-
-  int32_t StyleRuleCount() const { return mRuleList->Length(); }
-  Rule* GetStyleRuleAt(int32_t aIndex) const {
-    return mRuleList->GetRule(aIndex);
-  }
-
-  nsresult DeleteStyleRuleAt(uint32_t aIndex) {
-    return mRuleList->DeleteRule(aIndex);
-  }
-
-  dom::CSSRuleList* CssRules(GroupRule* aParentRule) {
-    return mRuleList;
-  }
-
-  size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
-
-  RefPtr<ServoCSSRuleList> mRuleList;
-};
-
-struct DummyGroupRuleRules
-{
-  void SetParentRule(GroupRule* aParentRule) {}
-  void SetStyleSheet(StyleSheet* aSheet) {}
-  void Clear() {}
-  void Traverse(nsCycleCollectionTraversalCallback& cb) {}
-#ifdef DEBUG
-  void List(FILE* out, int32_t aIndex) const {}
-#endif
-  int32_t StyleRuleCount() const { return 0; }
-  Rule* GetStyleRuleAt(int32_t aIndex) const { return nullptr; }
-  nsresult DeleteStyleRuleAt(uint32_t aIndex) { return NS_ERROR_NOT_IMPLEMENTED; }
-  dom::CSSRuleList* CssRules(GroupRule* aParentRule) { return nullptr; }
-  size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { return 0; }
-};
-
-#define REDIRECT_TO_INNER(call_)                   \
-  if (mInner.is<DummyGroupRuleRules>()) {          \
-    return mInner.as<DummyGroupRuleRules>().call_; \
-  } else {                                         \
-    return mInner.as<ServoGroupRuleRules>().call_; \
-  }
-
 // inherits from Rule so it can be shared between
 // MediaRule and DocumentRule
 class GroupRule : public Rule
 {
 protected:
-  GroupRule(uint32_t aLineNumber, uint32_t aColumnNumber);
   GroupRule(already_AddRefed<ServoCssRules> aRules,
             uint32_t aLineNumber, uint32_t aColumnNumber);
-  GroupRule(const GroupRule& aCopy);
+  GroupRule(const GroupRule& aCopy) = delete;
   virtual ~GroupRule();
 public:
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(GroupRule, Rule)
   NS_DECL_ISUPPORTS_INHERITED
   virtual bool IsCCLeaf() const override;
 
 #ifdef DEBUG
-  void List(FILE* out = stdout, int32_t aIndent = 0) const override {
-    REDIRECT_TO_INNER(List(out, aIndent))
-  }
+  void List(FILE* out = stdout, int32_t aIndent = 0) const override;
 #endif
   virtual void SetStyleSheet(StyleSheet* aSheet) override;
 
 public:
 
-  int32_t StyleRuleCount() const {
-    REDIRECT_TO_INNER(StyleRuleCount())
-  }
-  Rule* GetStyleRuleAt(uint32_t aIndex) const {
-    REDIRECT_TO_INNER(GetStyleRuleAt(aIndex))
+  int32_t StyleRuleCount() const { return mRuleList->Length(); }
+
+  Rule* GetStyleRuleAt(int32_t aIndex) const {
+    return mRuleList->GetRule(aIndex);
   }
 
-
   /*
-   * The next two methods should never be called unless you have first
-   * called WillDirty() on the parent stylesheet.  After they are
-   * called, DidDirty() needs to be called on the sheet.
+   * The next method should never be called unless you have first called
+   * WillDirty() on the parent stylesheet. After it's called, DidDirty()
+   * needs to be called on the sheet.
    */
   nsresult DeleteStyleRuleAt(uint32_t aIndex) {
-    REDIRECT_TO_INNER(DeleteStyleRuleAt(aIndex));
+    return mRuleList->DeleteRule(aIndex);
   }
 
   // non-virtual -- it is only called by subclasses
-  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
-    REDIRECT_TO_INNER(SizeOfExcludingThis(aMallocSizeOf))
-  }
+  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override = 0;
 
   // WebIDL API
-  dom::CSSRuleList* CssRules();
+  dom::CSSRuleList* CssRules() { return mRuleList; }
   uint32_t InsertRule(const nsAString& aRule, uint32_t aIndex,
                       ErrorResult& aRv);
   void DeleteRule(uint32_t aIndex, ErrorResult& aRv);
 
-protected:
-
 private:
-  // This only reason for the DummyGroupRuleRules is that ServoKeyframesRule
-  // inherits from CSSKeyframesRules (and thus GroupRule). Once
-  // ServoKeyframesRule can be made to inherit from Rule, the
-  // DummyGroupRuleRules can be removed.
-  Variant<DummyGroupRuleRules, ServoGroupRuleRules> mInner;
+  RefPtr<ServoCSSRuleList> mRuleList;
 };
 
-#undef REDIRECT_TO_INNER
-
 // Implementation of WebIDL CSSConditionRule.
 class ConditionRule : public GroupRule
 {
 protected:
   using GroupRule::GroupRule;
 
 public:
   virtual void GetConditionText(nsAString& aConditionText) = 0;
--- a/layout/style/Rule.h
+++ b/layout/style/Rule.h
@@ -88,20 +88,29 @@ public:
   nsIDocument* GetDocument() const
   {
     StyleSheet* sheet = GetStyleSheet();
     return sheet ? sheet->GetAssociatedDocument() : nullptr;
   }
 
   virtual void SetStyleSheet(StyleSheet* aSheet);
 
-  void SetParentRule(GroupRule* aRule) {
-    // We don't reference count this up reference. The group rule
-    // will tell us when it's going away or when we're detached from
-    // it.
+  // We don't reference count this up reference. The rule will tell us
+  // when it's going away or when we're detached from it.
+  void SetParentRule(Rule* aRule) {
+#ifdef DEBUG
+    if (aRule) {
+      int16_t type = aRule->Type();
+      MOZ_ASSERT(type == dom::CSSRuleBinding::MEDIA_RULE ||
+                 type == dom::CSSRuleBinding::DOCUMENT_RULE ||
+                 type == dom::CSSRuleBinding::SUPPORTS_RULE ||
+                 (type == dom::CSSRuleBinding::KEYFRAMES_RULE &&
+                  Type() == dom::CSSRuleBinding::KEYFRAME_RULE));
+    }
+#endif
     mParentRule = aRule;
   }
 
   uint32_t GetLineNumber() const { return mLineNumber; }
   uint32_t GetColumnNumber() const { return mColumnNumber; }
 
   /**
    * Clones |this|. Never returns nullptr.
@@ -124,17 +133,17 @@ public:
 protected:
   // True if we're known-live for cycle collection purposes.
   bool IsKnownLive() const;
 
   // This is sometimes null (e.g., for style attributes).
   StyleSheet* mSheet;
   // When the parent GroupRule is destroyed, it will call SetParentRule(nullptr)
   // on this object. (Through SetParentRuleReference);
-  GroupRule* MOZ_NON_OWNING_REF mParentRule;
+  Rule* MOZ_NON_OWNING_REF mParentRule;
 
   // Keep the same type so that MSVC packs them.
   uint32_t          mLineNumber;
   uint32_t          mColumnNumber;
 };
 
 } // namespace css
 } // namespace mozilla
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -815,15 +815,17 @@ SERVO_BINDING_FUNC(Servo_ParseFontShorth
                    RawGeckoURLExtraData* data,
                    RefPtr<SharedFontList>* family,
                    nsCSSValueBorrowedMut style,
                    nsCSSValueBorrowedMut stretch,
                    nsCSSValueBorrowedMut weight);
 
 SERVO_BINDING_FUNC(Servo_Property_IsShorthand, bool,
                    const nsACString* name, bool* found);
+SERVO_BINDING_FUNC(Servo_PseudoClass_GetStates, uint64_t,
+                   const nsACString* name)
 
 // AddRef / Release functions
 #define SERVO_ARC_TYPE(name_, type_)                                \
   SERVO_BINDING_FUNC(Servo_##name_##_AddRef, void, type_##Borrowed) \
   SERVO_BINDING_FUNC(Servo_##name_##_Release, void, type_##Borrowed)
 #include "mozilla/ServoArcTypeList.h"
 #undef SERVO_ARC_TYPE
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -24,16 +24,17 @@
 #include "nsDeviceContext.h"
 #include "nsIContentInlines.h"
 #include "nsICrashReporter.h"
 #include "nsIDOMNode.h"
 #include "nsIDocumentInlines.h"
 #include "nsILoadContext.h"
 #include "nsIFrame.h"
 #include "nsIMemoryReporter.h"
+#include "nsIMozBrowserFrame.h"
 #include "nsINode.h"
 #include "nsIPresShell.h"
 #include "nsIPresShellInlines.h"
 #include "nsIPrincipal.h"
 #include "nsIURI.h"
 #include "nsFontMetrics.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsMappedAttributes.h"
@@ -296,23 +297,16 @@ Gecko_ElementState(RawGeckoElementBorrow
 }
 
 bool
 Gecko_IsRootElement(RawGeckoElementBorrowed aElement)
 {
   return aElement->OwnerDoc()->GetRootElement() == aElement;
 }
 
-bool
-Gecko_MatchesElement(CSSPseudoClassType aType,
-                     RawGeckoElementBorrowed aElement)
-{
-  return nsCSSPseudoClasses::MatchesElement(aType, aElement).value();
-}
-
 // Dirtiness tracking.
 void
 Gecko_SetNodeFlags(RawGeckoNodeBorrowed aNode, uint32_t aFlags)
 {
   const_cast<nsINode*>(aNode)->SetFlags(aFlags);
 }
 
 void
@@ -846,21 +840,48 @@ Gecko_GetLookAndFeelSystemColor(int32_t 
 bool
 Gecko_MatchLang(RawGeckoElementBorrowed aElement,
                 nsAtom* aOverrideLang,
                 bool aHasOverrideLang,
                 const char16_t* aValue)
 {
   MOZ_ASSERT(!(aOverrideLang && !aHasOverrideLang),
              "aHasOverrideLang should only be set when aOverrideLang is null");
-
-  return nsCSSPseudoClasses::LangPseudoMatches(
-      aElement,
-      aHasOverrideLang ? aOverrideLang : nullptr,
-      aHasOverrideLang, aValue, aElement->OwnerDoc());
+  MOZ_ASSERT(aValue, "null lang parameter");
+  if (!aValue || !*aValue) {
+    return false;
+  }
+
+  // We have to determine the language of the current element.  Since
+  // this is currently no property and since the language is inherited
+  // from the parent we have to be prepared to look at all parent
+  // nodes.  The language itself is encoded in the LANG attribute.
+  if (auto* language = aHasOverrideLang ? aOverrideLang : aElement->GetLang()) {
+    return nsStyleUtil::DashMatchCompare(nsDependentAtomString(language),
+                                         nsDependentString(aValue),
+                                         nsASCIICaseInsensitiveStringComparator());
+  }
+
+  // Try to get the language from the HTTP header or if this
+  // is missing as well from the preferences.
+  // The content language can be a comma-separated list of
+  // language codes.
+  nsAutoString language;
+  aElement->OwnerDoc()->GetContentLanguage(language);
+
+  nsDependentString langString(aValue);
+  language.StripWhitespace();
+  for (auto const& lang : language.Split(char16_t(','))) {
+    if (nsStyleUtil::DashMatchCompare(lang,
+                                      langString,
+                                      nsASCIICaseInsensitiveStringComparator())) {
+      return true;
+    }
+  }
+  return false;
 }
 
 nsAtom*
 Gecko_GetXMLLangValue(RawGeckoElementBorrowed aElement)
 {
   const nsAttrValue* attr =
     aElement->GetParsedAttr(nsGkAtoms::lang, kNameSpaceID_XML);
 
@@ -875,16 +896,35 @@ Gecko_GetXMLLangValue(RawGeckoElementBor
 }
 
 nsIDocument::DocumentTheme
 Gecko_GetDocumentLWTheme(const nsIDocument* aDocument)
 {
   return aDocument->ThreadSafeGetDocumentLWTheme();
 }
 
+bool
+Gecko_IsTableBorderNonzero(RawGeckoElementBorrowed aElement)
+{
+  if (!aElement->IsHTMLElement(nsGkAtoms::table)) {
+    return false;
+  }
+  const nsAttrValue *val = aElement->GetParsedAttr(nsGkAtoms::border);
+  return val && (val->Type() != nsAttrValue::eInteger ||
+                 val->GetIntegerValue() != 0);
+}
+
+bool
+Gecko_IsBrowserFrame(RawGeckoElementBorrowed aElement)
+{
+  nsIMozBrowserFrame* browserFrame =
+    const_cast<Element*>(aElement)->GetAsMozBrowserFrame();
+  return browserFrame && browserFrame->GetReallyIsBrowser();
+}
+
 template <typename Implementor>
 static nsAtom*
 AtomAttrValue(Implementor* aElement, nsAtom* aName)
 {
   const nsAttrValue* attr = aElement->GetParsedAttr(aName);
   return attr ? attr->GetAtomValue() : nullptr;
 }
 
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -14,17 +14,16 @@
 #include "mozilla/ServoBindingTypes.h"
 #include "mozilla/ServoElementSnapshot.h"
 #include "mozilla/css/SheetLoadData.h"
 #include "mozilla/css/SheetParsingMode.h"
 #include "mozilla/css/URLMatchingFunction.h"
 #include "mozilla/EffectCompositor.h"
 #include "mozilla/ComputedTimingFunction.h"
 #include "nsChangeHint.h"
-#include "nsCSSPseudoClasses.h"
 #include "nsIDocument.h"
 #include "nsStyleStruct.h"
 
 /*
  * API for Servo to access Gecko data structures.
  *
  * Functions beginning with Gecko_ are implemented in Gecko and invoked from Servo.
  * Functions beginning with Servo_ are implemented in Servo and invoked from Gecko.
@@ -185,22 +184,23 @@ Gecko_LoadStyleSheet(mozilla::css::Loade
                      RawGeckoURLExtraData* base_url_data,
                      const uint8_t* url_bytes,
                      uint32_t url_length,
                      RawServoMediaListStrong media_list);
 
 // Selector Matching.
 uint64_t Gecko_ElementState(RawGeckoElementBorrowed element);
 bool Gecko_IsRootElement(RawGeckoElementBorrowed element);
-bool Gecko_MatchesElement(mozilla::CSSPseudoClassType type, RawGeckoElementBorrowed element);
 bool Gecko_MatchLang(RawGeckoElementBorrowed element,
                      nsAtom* override_lang, bool has_override_lang,
                      const char16_t* value);
 nsAtom* Gecko_GetXMLLangValue(RawGeckoElementBorrowed element);
 nsIDocument::DocumentTheme Gecko_GetDocumentLWTheme(const nsIDocument* aDocument);
+bool Gecko_IsTableBorderNonzero(RawGeckoElementBorrowed element);
+bool Gecko_IsBrowserFrame(RawGeckoElementBorrowed element);
 
 // Attributes.
 #define SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(prefix_, implementor_)  \
   nsAtom* prefix_##AtomAttrValue(implementor_ element, nsAtom* attribute);    \
   nsAtom* prefix_##LangValue(implementor_ element);                           \
   bool prefix_##HasAttr(implementor_ element, nsAtom* ns, nsAtom* name);      \
   bool prefix_##AttrEquals(implementor_ element, nsAtom* ns, nsAtom* name,    \
                            nsAtom* str, bool ignoreCase);                     \
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -182,17 +182,16 @@ rusty-enums = [
     "mozilla::StyleGridTrackBreadth",
     "mozilla::StyleOverscrollBehavior",
     "mozilla::StyleWhiteSpace",
     "nsStyleImageType",
     "nsStyleSVGPaintType",
     "nsStyleSVGFallbackType",
     "nsINode_BooleanFlag",
     "mozilla::CSSPseudoElementType",
-    "mozilla::CSSPseudoClassType",
     "mozilla::LookAndFeel_ColorID",
     "mozilla::LookAndFeel_FontID",
     "nsStyleTransformMatrix::MatrixTransformOperator",
     "mozilla::StyleGeometryBox",
     "mozilla::SystemColor",
 ]
 constified-enum-variants = [
     { enum = "nsCSSPropertyID", variants = ["eCSSProperty_COUNT.*"] },
@@ -227,17 +226,16 @@ whitelist-types = [
     "mozilla::ComputedTimingFunction::BeforeFlag",
     "mozilla::SeenPtrs",
     "mozilla::ServoElementSnapshot.*",
     "mozilla::ComputedStyle",
     "mozilla::ServoStyleSheet",
     "mozilla::ServoStyleSheetInner",
     "mozilla::ServoStyleSetSizes",
     "mozilla::ServoTraversalStatistics",
-    "mozilla::CSSPseudoClassType",
     "mozilla::css::ErrorReporter",
     "mozilla::css::LoaderReusableStyleSheets",
     "mozilla::css::SheetLoadData",
     "mozilla::css::SheetParsingMode",
     "mozilla::css::URLMatchingFunction",
     "mozilla::dom::IterationCompositeOperation",
     "mozilla::dom::StyleChildrenIterator",
     "mozilla::HalfCorner",
@@ -510,17 +508,16 @@ structs-types = [
     "RawGeckoStyleChildrenIterator",
     "RawGeckoServoStyleRuleList",
     "RawGeckoURLExtraData",
     "RawGeckoXBLBinding",
     "RawServoSelectorList",
     "RawServoSourceSizeList",
     "RefPtr",
     "RustString",
-    "CSSPseudoClassType",
     "CSSPseudoElementType",
     "ServoTraversalFlags",
     "ComputedTimingFunction_BeforeFlag",
     "CounterStylePtr",
     "FontFamilyType",
     "FontSizePrefs",
     "GeckoFontMetrics",
     "IterationCompositeOperation",
--- a/layout/style/ServoElementSnapshot.cpp
+++ b/layout/style/ServoElementSnapshot.cpp
@@ -1,15 +1,16 @@
 /* -*- 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 "mozilla/ServoElementSnapshot.h"
+#include "mozilla/ServoBindings.h"
 #include "mozilla/dom/Element.h"
 #include "nsIContentInlines.h"
 #include "nsContentUtils.h"
 
 namespace mozilla {
 
 ServoElementSnapshot::ServoElementSnapshot(const Element* aElement)
   : mState(0)
@@ -31,19 +32,15 @@ void
 ServoElementSnapshot::AddOtherPseudoClassState(Element* aElement)
 {
   MOZ_ASSERT(aElement);
 
   if (HasOtherPseudoClassState()) {
     return;
   }
 
-  mIsTableBorderNonzero =
-    *nsCSSPseudoClasses::MatchesElement(CSSPseudoClassType::mozTableBorderNonzero,
-                                        aElement);
-  mIsMozBrowserFrame =
-    *nsCSSPseudoClasses::MatchesElement(CSSPseudoClassType::mozBrowserFrame,
-                                        aElement);
+  mIsTableBorderNonzero = Gecko_IsTableBorderNonzero(aElement);
+  mIsMozBrowserFrame = Gecko_IsBrowserFrame(aElement);
 
   mContains |= Flags::OtherPseudoClassState;
 }
 
 } // namespace mozilla
--- a/layout/style/ServoKeyframesRule.cpp
+++ b/layout/style/ServoKeyframesRule.cpp
@@ -153,20 +153,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 // -------------------------------------------
 // ServoKeyframesRule
 //
 
 ServoKeyframesRule::ServoKeyframesRule(RefPtr<RawServoKeyframesRule> aRawRule,
                                        uint32_t aLine, uint32_t aColumn)
-  // Although this class inherits from GroupRule, we don't want to use
-  // it at all, so it is fine to call the constructor for Gecko. We can
-  // make CSSKeyframesRule inherit from Rule directly once we can get
-  // rid of nsCSSKeyframeRule.
   : dom::CSSKeyframesRule(aLine, aColumn)
   , mRawRule(Move(aRawRule))
 {
 }
 
 ServoKeyframesRule::~ServoKeyframesRule()
 {
   if (mKeyframeList) {
@@ -342,16 +338,15 @@ ServoKeyframesRule::FindRule(const nsASt
   }
   return nullptr;
 }
 
 /* virtual */ size_t
 ServoKeyframesRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
-  n += GroupRule::SizeOfExcludingThis(aMallocSizeOf);
   if (mKeyframeList) {
     n += mKeyframeList->SizeOfIncludingThis(aMallocSizeOf);
   }
   return n;
 }
 
 } // namespace mozilla
--- a/layout/style/ServoStyleRule.cpp
+++ b/layout/style/ServoStyleRule.cpp
@@ -7,17 +7,16 @@
 /* representation of CSSStyleRule for stylo */
 
 #include "mozilla/ServoStyleRule.h"
 
 #include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoDeclarationBlock.h"
 #include "mozilla/dom/CSSStyleRuleBinding.h"
-#include "nsCSSPseudoClasses.h"
 
 #include "mozAutoDocUpdate.h"
 
 using namespace mozilla::dom;
 
 namespace mozilla {
 
 // -- ServoStyleRuleDeclaration ---------------------------------------
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -36,18 +36,16 @@ EXPORTS += [
     'nsCSSKeywordList.h',
     'nsCSSKeywords.h',
     'nsCSSParser.h',
     'nsCSSPropAliasList.h',
     'nsCSSPropertyID.h',
     'nsCSSPropertyIDSet.h',
     'nsCSSPropList.h',
     'nsCSSProps.h',
-    'nsCSSPseudoClasses.h',
-    'nsCSSPseudoClassList.h',
     'nsCSSPseudoElementList.h',
     'nsCSSPseudoElements.h',
     'nsCSSScanner.h',
     'nsCSSValue.h',
     'nsDOMCSSAttrDeclaration.h',
     'nsDOMCSSDeclaration.h',
     'nsDOMCSSRGBColor.h',
     'nsICSSDeclaration.h',
@@ -184,17 +182,16 @@ UNIFIED_SOURCES += [
     'MediaList.cpp',
     'MediaQueryList.cpp',
     'nsAnimationManager.cpp',
     'nsComputedDOMStyle.cpp',
     'nsCSSCounterStyleRule.cpp',
     'nsCSSFontFaceRule.cpp',
     'nsCSSKeywords.cpp',
     'nsCSSProps.cpp',
-    'nsCSSPseudoClasses.cpp',
     'nsCSSScanner.cpp',
     'nsCSSValue.cpp',
     'nsDOMCSSAttrDeclaration.cpp',
     'nsDOMCSSDeclaration.cpp',
     'nsDOMCSSRect.cpp',
     'nsDOMCSSRGBColor.cpp',
     'nsDOMCSSValueList.cpp',
     'nsFontFaceLoader.cpp',
@@ -235,18 +232,16 @@ UNIFIED_SOURCES += [
     'StyleAnimationValue.cpp',
     'StylePrefs.cpp',
     'StyleSheet.cpp',
     'URLExtraData.cpp',
 ]
 
 SOURCES += [
     'nsCSSAnonBoxes.cpp',
-    # Both nsCSSPseudoElements.cpp and nsCSSPseudoClasses.cpp defined a
-    # 'mozPlaceholder' static atom.
     'nsCSSPseudoElements.cpp',
     # nsLayoutStylesheetCache.cpp uses nsExceptionHandler.h, which includes
     # windows.h.
     'nsLayoutStylesheetCache.cpp',
 ]
 if CONFIG['CC_TYPE'] == 'msvc':
     # Needed for gCSSAnonBoxAtoms.
     SOURCES['nsCSSAnonBoxes.cpp'].flags += ['-Zc:externConstexpr']
deleted file mode 100644
--- a/layout/style/nsCSSPseudoClassList.h
+++ /dev/null
@@ -1,269 +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/. */
-
-/* atom list for CSS pseudo-classes */
-
-/*
- * This file contains the list of nsAtoms and their values for CSS
- * pseudo-classes.  It is designed to be used as inline input to
- * nsCSSPseudoClasses.cpp *only* through the magic of C preprocessing.
- * All entries must be enclosed in the macros CSS_PSEUDO_CLASS,
- * CSS_STATE_DEPENDENT_PSEUDO_CLASS, or CSS_STATE_PSEUDO_CLASS which
- * will have cruel and unusual things done to them.  The entries should
- * be kept in some sort of logical order.  The common arguments to these
- * macros are:
- * name_  : The C++ identifier used for the atom (which will be a member
- *          of nsCSSPseudoClasses)
- * value_ : The pseudo-class as a string, including the initial colon,
- *          used as the string value of the atom.
- * flags_ : A bitfield containing flags defined in nsCSSPseudoClasses.h
- * pref_  : The name of the preference controlling whether the
- *          pseudo-class is recognized by the parser, or the empty
- *          string if it's unconditional.
- * CSS_STATE_PSEUDO_CLASS has an additional argument:
- * bit_   : The event state bit or bits that corresponds to the
- *          pseudo-class, i.e., causes it to match (only one bit
- *          required to match).
- * CSS_STATE_DEPENDENT_PSEUDO_CLASS has an additional argument:
- * bit_   : The event state bits that affect whether the pseudo-class
- *          matches.  Matching depends on a customized per-class
- *          algorithm which should be defined in SelectorMatches() in
- *          nsCSSRuleProcessor.cpp.
- *
- * If CSS_STATE_PSEUDO_CLASS is not defined, it'll be automatically
- * defined to CSS_STATE_DEPENDENT_PSEUDO_CLASS;
- * if CSS_STATE_DEPENDENT_PSEUDO_CLASS is not defined, it'll be
- * automatically defined to CSS_PSEUDO_CLASS.
- */
-
-// OUTPUT_CLASS=nsCSSPseudoClasses
-// MACRO_NAME=CSS_PSEUDO_CLASS
-
-#ifdef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
-#error "CSS_STATE_DEPENDENT_PSEUDO_CLASS shouldn't be defined"
-#endif
-
-#ifndef CSS_STATE_DEPENDENT_PSEUDO_CLASS
-#define CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _flags, _pref, _bit)  \
-  CSS_PSEUDO_CLASS(_name, _value, _flags, _pref)
-#define DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
-#endif
-
-#ifdef DEFINED_CSS_STATE_PSEUDO_CLASS
-#error "CSS_STATE_PSEUDO_CLASS shouldn't be defined"
-#endif
-
-#ifndef CSS_STATE_PSEUDO_CLASS
-#define CSS_STATE_PSEUDO_CLASS(_name, _value, _flags, _pref, _bit)      \
-  CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _flags, _pref, _bit)
-#define DEFINED_CSS_STATE_PSEUDO_CLASS
-#endif
-
-// The CSS_PSEUDO_CLASS entries should all come before the
-// CSS_STATE_PSEUDO_CLASS entries.  The CSS_PSEUDO_CLASS entry order
-// must be the same as the order of cases in SelectorMatches.  :not
-// must be the last CSS_PSEUDO_CLASS.
-
-CSS_PSEUDO_CLASS(empty, ":empty", 0, "")
-CSS_PSEUDO_CLASS(mozOnlyWhitespace, ":-moz-only-whitespace", 0, "")
-CSS_PSEUDO_CLASS(lang, ":lang", 0, "")
-CSS_PSEUDO_CLASS(root, ":root", 0, "")
-CSS_PSEUDO_CLASS(any, ":-moz-any", 0, "")
-
-CSS_PSEUDO_CLASS(firstChild, ":first-child", 0, "")
-CSS_PSEUDO_CLASS(firstNode, ":-moz-first-node", 0, "")
-CSS_PSEUDO_CLASS(lastChild, ":last-child", 0, "")
-CSS_PSEUDO_CLASS(lastNode, ":-moz-last-node", 0, "")
-CSS_PSEUDO_CLASS(onlyChild, ":only-child", 0, "")
-CSS_PSEUDO_CLASS(firstOfType, ":first-of-type", 0, "")
-CSS_PSEUDO_CLASS(lastOfType, ":last-of-type", 0, "")
-CSS_PSEUDO_CLASS(onlyOfType, ":only-of-type", 0, "")
-CSS_PSEUDO_CLASS(nthChild, ":nth-child", 0, "")
-CSS_PSEUDO_CLASS(nthLastChild, ":nth-last-child", 0, "")
-CSS_PSEUDO_CLASS(nthOfType, ":nth-of-type", 0, "")
-CSS_PSEUDO_CLASS(nthLastOfType, ":nth-last-of-type", 0, "")
-
-// Match nodes that are HTML but not XHTML
-CSS_PSEUDO_CLASS(mozIsHTML, ":-moz-is-html", 0, "")
-
-// Matches nodes that are in a native-anonymous subtree (i.e., nodes in
-// a subtree of C++ anonymous content constructed by Gecko for its own
-// purposes).
-CSS_PSEUDO_CLASS(mozNativeAnonymous, ":-moz-native-anonymous",
-                 CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "")
-
-CSS_PSEUDO_CLASS(mozUseShadowTreeRoot, ":-moz-use-shadow-tree-root",
-                 CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "")
-
-// -moz-locale-dir(ltr) and -moz-locale-dir(rtl) may be used
-// to match based on the locale's chrome direction
-CSS_PSEUDO_CLASS(mozLocaleDir, ":-moz-locale-dir", 0, "")
-
-// -moz-lwtheme may be used to match a document that has a lightweight theme
-CSS_PSEUDO_CLASS(mozLWTheme, ":-moz-lwtheme", 0, "")
-
-// -moz-lwtheme-brighttext matches a document that has a dark lightweight theme
-CSS_PSEUDO_CLASS(mozLWThemeBrightText, ":-moz-lwtheme-brighttext", 0, "")
-
-// -moz-lwtheme-darktext matches a document that has a bright lightweight theme
-CSS_PSEUDO_CLASS(mozLWThemeDarkText, ":-moz-lwtheme-darktext", 0, "")
-
-// Matches anything when the containing window is inactive
-CSS_PSEUDO_CLASS(mozWindowInactive, ":-moz-window-inactive", 0, "")
-
-// Matches any table elements that have a nonzero border attribute,
-// according to HTML integer attribute parsing rules.
-CSS_PSEUDO_CLASS(mozTableBorderNonzero, ":-moz-table-border-nonzero",
-                 CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "")
-
-// Matches HTML frame/iframe elements which are mozbrowser.
-CSS_PSEUDO_CLASS(mozBrowserFrame, ":-moz-browser-frame",
-                 CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "")
-
-// Matches whatever the contextual reference elements are for the
-// matching operation.
-CSS_PSEUDO_CLASS(scope, ":scope", 0, "layout.css.scope-pseudo.enabled")
-
-// :not needs to come at the end of the non-bit pseudo-class list, since
-// it doesn't actually get directly matched on in SelectorMatches.
-CSS_PSEUDO_CLASS(negation, ":not", 0, "")
-
-// :dir(ltr) and :dir(rtl) match elements whose resolved
-// directionality in the markup language is ltr or rtl respectively.
-CSS_STATE_DEPENDENT_PSEUDO_CLASS(dir, ":dir", 0, "",
-                                 NS_EVENT_STATE_LTR | NS_EVENT_STATE_RTL)
-
-CSS_STATE_PSEUDO_CLASS(link, ":link", 0, "", NS_EVENT_STATE_UNVISITED)
-// what matches :link or :visited
-CSS_STATE_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link", 0, "",
-                       NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)
-CSS_STATE_PSEUDO_CLASS(anyLink, ":any-link", 0, "",
-                       NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)
-CSS_STATE_PSEUDO_CLASS(visited, ":visited", 0, "", NS_EVENT_STATE_VISITED)
-
-CSS_STATE_PSEUDO_CLASS(active, ":active", 0, "", NS_EVENT_STATE_ACTIVE)
-CSS_STATE_PSEUDO_CLASS(checked, ":checked", 0, "", NS_EVENT_STATE_CHECKED)
-CSS_STATE_PSEUDO_CLASS(disabled, ":disabled", 0, "", NS_EVENT_STATE_DISABLED)
-CSS_STATE_PSEUDO_CLASS(enabled, ":enabled", 0, "", NS_EVENT_STATE_ENABLED)
-CSS_STATE_PSEUDO_CLASS(focus, ":focus", 0, "", NS_EVENT_STATE_FOCUS)
-CSS_STATE_PSEUDO_CLASS(focusWithin, ":focus-within", 0, "", NS_EVENT_STATE_FOCUS_WITHIN)
-CSS_STATE_PSEUDO_CLASS(hover, ":hover", 0, "", NS_EVENT_STATE_HOVER)
-CSS_STATE_PSEUDO_CLASS(mozDragOver, ":-moz-drag-over", 0, "", NS_EVENT_STATE_DRAGOVER)
-CSS_STATE_PSEUDO_CLASS(target, ":target", 0, "", NS_EVENT_STATE_URLTARGET)
-CSS_STATE_PSEUDO_CLASS(indeterminate, ":indeterminate", 0, "",
-                       NS_EVENT_STATE_INDETERMINATE)
-
-CSS_STATE_PSEUDO_CLASS(mozDevtoolsHighlighted, ":-moz-devtools-highlighted",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "",
-                       NS_EVENT_STATE_DEVTOOLS_HIGHLIGHTED)
-CSS_STATE_PSEUDO_CLASS(mozStyleeditorTransitioning, ":-moz-styleeditor-transitioning",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "",
-                       NS_EVENT_STATE_STYLEEDITOR_TRANSITIONING)
-
-// Matches the element which is being displayed full-screen, and
-// any containing frames.
-CSS_STATE_PSEUDO_CLASS(fullscreen, ":fullscreen",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME,
-                       "full-screen-api.unprefix.enabled",
-                       NS_EVENT_STATE_FULL_SCREEN)
-CSS_STATE_PSEUDO_CLASS(mozFullScreen, ":-moz-full-screen", 0, "", NS_EVENT_STATE_FULL_SCREEN)
-
-// Matches if the element is focused and should show a focus ring
-CSS_STATE_PSEUDO_CLASS(mozFocusRing, ":-moz-focusring", 0, "", NS_EVENT_STATE_FOCUSRING)
-
-// Image, object, etc state pseudo-classes
-CSS_STATE_PSEUDO_CLASS(mozBroken, ":-moz-broken", 0, "", NS_EVENT_STATE_BROKEN)
-CSS_STATE_PSEUDO_CLASS(mozLoading, ":-moz-loading", 0, "", NS_EVENT_STATE_LOADING)
-
-CSS_STATE_PSEUDO_CLASS(mozUserDisabled, ":-moz-user-disabled",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
-                       NS_EVENT_STATE_USERDISABLED)
-CSS_STATE_PSEUDO_CLASS(mozSuppressed, ":-moz-suppressed",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
-                       NS_EVENT_STATE_SUPPRESSED)
-CSS_STATE_PSEUDO_CLASS(mozHandlerClickToPlay, ":-moz-handler-clicktoplay",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
-                       NS_EVENT_STATE_TYPE_CLICK_TO_PLAY)
-CSS_STATE_PSEUDO_CLASS(mozHandlerVulnerableUpdatable, ":-moz-handler-vulnerable-updatable",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
-                       NS_EVENT_STATE_VULNERABLE_UPDATABLE)
-CSS_STATE_PSEUDO_CLASS(mozHandlerVulnerableNoUpdate, ":-moz-handler-vulnerable-no-update",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
-                       NS_EVENT_STATE_VULNERABLE_NO_UPDATE)
-CSS_STATE_PSEUDO_CLASS(mozHandlerDisabled, ":-moz-handler-disabled",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
-                       NS_EVENT_STATE_HANDLER_DISABLED)
-CSS_STATE_PSEUDO_CLASS(mozHandlerBlocked, ":-moz-handler-blocked",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
-                       NS_EVENT_STATE_HANDLER_BLOCKED)
-CSS_STATE_PSEUDO_CLASS(mozHandlerCrashed, ":-moz-handler-crashed",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
-                       NS_EVENT_STATE_HANDLER_CRASHED)
-
-CSS_STATE_PSEUDO_CLASS(mozMathIncrementScriptLevel,
-                       ":-moz-math-increment-script-level", 0, "",
-                       NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL)
-
-CSS_STATE_PSEUDO_CLASS(mozHasDirAttr, ":-moz-has-dir-attr",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "",
-                       NS_EVENT_STATE_HAS_DIR_ATTR)
-CSS_STATE_PSEUDO_CLASS(mozDirAttrLTR, ":-moz-dir-attr-ltr",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "",
-                       NS_EVENT_STATE_DIR_ATTR_LTR)
-CSS_STATE_PSEUDO_CLASS(mozDirAttrRTL, ":-moz-dir-attr-rtl",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "",
-                       NS_EVENT_STATE_DIR_ATTR_RTL)
-CSS_STATE_PSEUDO_CLASS(mozDirAttrLikeAuto, ":-moz-dir-attr-like-auto",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS, "",
-                       NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO)
-
-CSS_STATE_PSEUDO_CLASS(mozAutofill, ":-moz-autofill",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
-                       NS_EVENT_STATE_AUTOFILL)
-CSS_STATE_PSEUDO_CLASS(mozAutofillPreview, ":-moz-autofill-preview",
-                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
-                       NS_EVENT_STATE_AUTOFILL_PREVIEW)
-
-// CSS 3 UI
-// http://www.w3.org/TR/2004/CR-css3-ui-20040511/#pseudo-classes
-CSS_STATE_PSEUDO_CLASS(required, ":required", 0, "", NS_EVENT_STATE_REQUIRED)
-CSS_STATE_PSEUDO_CLASS(optional, ":optional", 0, "", NS_EVENT_STATE_OPTIONAL)
-CSS_STATE_PSEUDO_CLASS(valid, ":valid", 0, "", NS_EVENT_STATE_VALID)
-CSS_STATE_PSEUDO_CLASS(invalid, ":invalid", 0, "", NS_EVENT_STATE_INVALID)
-CSS_STATE_PSEUDO_CLASS(inRange, ":in-range", 0, "", NS_EVENT_STATE_INRANGE)
-CSS_STATE_PSEUDO_CLASS(outOfRange, ":out-of-range", 0, "", NS_EVENT_STATE_OUTOFRANGE)
-CSS_STATE_PSEUDO_CLASS(defaultPseudo, ":default", 0, "", NS_EVENT_STATE_DEFAULT)
-CSS_STATE_PSEUDO_CLASS(placeholderShown, ":placeholder-shown", 0, "",
-                       NS_EVENT_STATE_PLACEHOLDERSHOWN)
-CSS_STATE_PSEUDO_CLASS(mozReadOnly, ":-moz-read-only", 0, "",
-                       NS_EVENT_STATE_MOZ_READONLY)
-CSS_STATE_PSEUDO_CLASS(mozReadWrite, ":-moz-read-write", 0, "",
-                       NS_EVENT_STATE_MOZ_READWRITE)
-CSS_STATE_PSEUDO_CLASS(mozSubmitInvalid, ":-moz-submit-invalid", 0, "",
-                       NS_EVENT_STATE_MOZ_SUBMITINVALID)
-CSS_STATE_PSEUDO_CLASS(mozUIInvalid, ":-moz-ui-invalid", 0, "",
-                       NS_EVENT_STATE_MOZ_UI_INVALID)
-CSS_STATE_PSEUDO_CLASS(mozUIValid, ":-moz-ui-valid", 0, "",
-                       NS_EVENT_STATE_MOZ_UI_VALID)
-CSS_STATE_PSEUDO_CLASS(mozMeterOptimum, ":-moz-meter-optimum", 0, "",
-                       NS_EVENT_STATE_OPTIMUM)
-CSS_STATE_PSEUDO_CLASS(mozMeterSubOptimum, ":-moz-meter-sub-optimum", 0, "",
-                       NS_EVENT_STATE_SUB_OPTIMUM)
-CSS_STATE_PSEUDO_CLASS(mozMeterSubSubOptimum, ":-moz-meter-sub-sub-optimum", 0, "",
-                       NS_EVENT_STATE_SUB_SUB_OPTIMUM)
-
-// Those values should be parsed but do nothing.
-CSS_STATE_PSEUDO_CLASS(mozPlaceholder, ":-moz-placeholder", 0, "", NS_EVENT_STATE_IGNORE)
-
-#ifdef DEFINED_CSS_STATE_PSEUDO_CLASS
-#undef DEFINED_CSS_STATE_PSEUDO_CLASS
-#undef CSS_STATE_PSEUDO_CLASS
-#endif
-
-#ifdef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
-#undef DEFINED_CSS_STATE_DEPENDENT_PSEUDO_CLASS
-#undef CSS_STATE_DEPENDENT_PSEUDO_CLASS
-#endif
deleted file mode 100644
--- a/layout/style/nsCSSPseudoClasses.cpp
+++ /dev/null
@@ -1,335 +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/. */
-
-/* atom list for CSS pseudo-classes */
-
-#include "mozilla/ArrayUtils.h"
-
-#include "nsCSSPseudoClasses.h"
-#include "nsCSSPseudoElements.h"
-#include "nsStaticAtom.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/dom/Element.h"
-#include "nsString.h"
-#include "nsAttrValueInlines.h"
-#include "nsIMozBrowserFrame.h"
-#include "nsStyleUtil.h"
-
-using namespace mozilla;
-
-#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-  static_assert(!((flags_) & CSS_PSEUDO_CLASS_ENABLED_IN_CHROME) || \
-                ((flags_) & CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), \
-                "Pseudo-class '" #name_ "' is enabled in chrome, so it " \
-                "should also be enabled in UA sheets");
-#include "nsCSSPseudoClassList.h"
-#undef CSS_PSEUDO_CLASS
-
-namespace detail {
-
-struct CSSPseudoClassAtoms
-{
-  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-    NS_STATIC_ATOM_DECL_STRING(name_, value_)
-  #include "nsCSSPseudoClassList.h"
-  #undef CSS_PSEUDO_CLASS
-
-  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-    NS_STATIC_ATOM_DECL_ATOM(name_)
-  #include "nsCSSPseudoClassList.h"
-  #undef CSS_PSEUDO_CLASS
-};
-
-MOZ_PUSH_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
-static constexpr CSSPseudoClassAtoms sCSSPseudoClassAtoms = {
-  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-    NS_STATIC_ATOM_INIT_STRING(value_)
-  #include "nsCSSPseudoClassList.h"
-  #undef CSS_PSEUDO_CLASS
-
-  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-    NS_STATIC_ATOM_INIT_ATOM(CSSPseudoClassAtoms, name_, value_)
-  #include "nsCSSPseudoClassList.h"
-  #undef CSS_PSEUDO_CLASS
-};
-MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
-
-} // namespace detail
-
-class CSSPseudoClassAtoms
-{
-public:
-  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-    NS_STATIC_ATOM_DECL_PTR(name_)
-  #include "nsCSSPseudoClassList.h"
-  #undef CSS_PSEUDO_CLASS
-};
-
-#define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-  NS_STATIC_ATOM_DEFN_PTR(CSSPseudoClassAtoms, name_)
-#include "nsCSSPseudoClassList.h"
-#undef CSS_PSEUDO_CLASS
-
-static const nsStaticAtomSetup sCSSPseudoClassAtomSetup[] = {
-  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-    NS_STATIC_ATOM_SETUP( \
-      ::detail::sCSSPseudoClassAtoms, CSSPseudoClassAtoms, name_)
-  #include "nsCSSPseudoClassList.h"
-  #undef CSS_PSEUDO_CLASS
-};
-
-// Flags data for each of the pseudo-classes, which must be separate
-// from the previous array since there's no place for it in
-// nsStaticAtomSetup.
-/* static */ const uint32_t
-nsCSSPseudoClasses::kPseudoClassFlags[] = {
-  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-    flags_,
-  #include "nsCSSPseudoClassList.h"
-  #undef CSS_PSEUDO_CLASS
-};
-
-/* static */ bool
-nsCSSPseudoClasses::sPseudoClassEnabled[] = {
-  // If the pseudo class has any "ENABLED_IN" flag set, it is disabled by
-  // default. Note that, if a pseudo class has pref, whatever its default value
-  // is, it'll later be changed in nsCSSPseudoClasses::RegisterStaticAtoms() If
-  // the pseudo class has "ENABLED_IN" flags but doesn't have a pref, it is an
-  // internal pseudo class which is disabled elsewhere.
-  #define IS_ENABLED_BY_DEFAULT(flags_) \
-    (!((flags_) & CSS_PSEUDO_CLASS_ENABLED_MASK))
-  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_) \
-    IS_ENABLED_BY_DEFAULT(flags_),
-  #include "nsCSSPseudoClassList.h"
-  #undef CSS_PSEUDO_CLASS
-  #undef IS_ENABLED_BY_DEFAULT
-};
-
-void nsCSSPseudoClasses::RegisterStaticAtoms()
-{
-  NS_RegisterStaticAtoms(sCSSPseudoClassAtomSetup);
-
-  #define CSS_PSEUDO_CLASS(name_, value_, flags_, pref_)                      \
-    if (pref_[0]) {                                                           \
-      auto idx = static_cast<CSSPseudoElementTypeBase>(Type::name_);          \
-      Preferences::AddBoolVarCache(&sPseudoClassEnabled[idx], pref_);         \
-    }
-  #include "nsCSSPseudoClassList.h"
-  #undef CSS_PSEUDO_CLASS
-}
-
-bool
-nsCSSPseudoClasses::HasStringArg(Type aType)
-{
-  return aType == Type::lang ||
-         aType == Type::mozLocaleDir ||
-         aType == Type::dir;
-}
-
-bool
-nsCSSPseudoClasses::HasNthPairArg(Type aType)
-{
-  return aType == Type::nthChild ||
-         aType == Type::nthLastChild ||
-         aType == Type::nthOfType ||
-         aType == Type::nthLastOfType;
-}
-
-void
-nsCSSPseudoClasses::PseudoTypeToString(Type aType, nsAString& aString)
-{
-  MOZ_ASSERT(aType < Type::Count, "Unexpected type");
-  auto idx = static_cast<CSSPseudoClassTypeBase>(aType);
-  (*sCSSPseudoClassAtomSetup[idx].mAtomp)->ToString(aString);
-}
-
-/* static */ CSSPseudoClassType
-nsCSSPseudoClasses::GetPseudoType(nsAtom* aAtom, EnabledState aEnabledState)
-{
-  Maybe<uint32_t> index =
-    nsStaticAtomUtils::Lookup(aAtom, sCSSPseudoClassAtomSetup);
-  if (index.isSome()) {
-    Type type = Type(*index);
-    if (IsEnabled(type, aEnabledState)) {
-      return type;
-    }
-  }
-  return Type::NotPseudo;
-}
-
-/* static */ bool
-nsCSSPseudoClasses::IsUserActionPseudoClass(Type aType)
-{
-  // See http://dev.w3.org/csswg/selectors4/#useraction-pseudos
-  return aType == Type::hover ||
-         aType == Type::active ||
-         aType == Type::focus;
-}
-
-/* static */ bool
-nsCSSPseudoClasses::LangPseudoMatches(const mozilla::dom::Element* aElement,
-                                      const nsAtom* aOverrideLang,
-                                      bool aHasOverrideLang,
-                                      const char16_t* aString,
-                                      const nsIDocument* aDocument)
-{
-  NS_ASSERTION(aString, "null lang parameter");
-  if (!aString || !*aString) {
-    return false;
-  }
-
-  // We have to determine the language of the current element.  Since
-  // this is currently no property and since the language is inherited
-  // from the parent we have to be prepared to look at all parent
-  // nodes.  The language itself is encoded in the LANG attribute.
-  if (auto* language = aHasOverrideLang ? aOverrideLang : aElement->GetLang()) {
-    return nsStyleUtil::DashMatchCompare(nsDependentAtomString(language),
-                                         nsDependentString(aString),
-                                         nsASCIICaseInsensitiveStringComparator());
-  }
-
-  if (!aDocument) {
-    return false;
-  }
-
-  // Try to get the language from the HTTP header or if this
-  // is missing as well from the preferences.
-  // The content language can be a comma-separated list of
-  // language codes.
-  nsAutoString language;
-  aDocument->GetContentLanguage(language);
-
-  nsDependentString langString(aString);
-  language.StripWhitespace();
-  for (auto const& lang : language.Split(char16_t(','))) {
-    if (nsStyleUtil::DashMatchCompare(lang,
-                                      langString,
-                                      nsASCIICaseInsensitiveStringComparator())) {
-      return true;
-    }
-  }
-  return false;
-}
-
-/* static */ bool
-nsCSSPseudoClasses::StringPseudoMatches(const mozilla::dom::Element* aElement,
-                                        CSSPseudoClassType aPseudo,
-                                        const char16_t* aString,
-                                        const nsIDocument* aDocument,
-                                        EventStates aStateMask,
-                                        bool* const aDependence)
-{
-
-  switch (aPseudo) {
-    case CSSPseudoClassType::mozLocaleDir:
-      {
-        const bool docIsRTL =
-          aDocument->GetDocumentState().HasState(NS_DOCUMENT_STATE_RTL_LOCALE);
-        nsDependentString dirString(aString);
-
-        if (dirString.EqualsLiteral("rtl")) {
-          if (!docIsRTL) {
-            return false;
-          }
-        } else if (dirString.EqualsLiteral("ltr")) {
-          if (docIsRTL) {
-            return false;
-          }
-        } else {
-          // Selectors specifying other directions never match.
-          return false;
-        }
-      }
-      break;
-
-    case CSSPseudoClassType::dir:
-      {
-        if (aDependence) {
-          EventStates states = sPseudoClassStateDependences[
-            static_cast<CSSPseudoClassTypeBase>(aPseudo)];
-          if (aStateMask.HasAtLeastOneOfStates(states)) {
-            *aDependence = true;
-            return false;
-          }
-        }
-
-        // If we only had to consider HTML, directionality would be
-        // exclusively LTR or RTL.
-        //
-        // However, in markup languages where there is no direction attribute
-        // we have to consider the possibility that neither dir(rtl) nor
-        // dir(ltr) matches.
-        EventStates state = aElement->StyleState();
-        nsDependentString dirString(aString);
-
-        if (dirString.EqualsLiteral("rtl")) {
-          if (!state.HasState(NS_EVENT_STATE_RTL)) {
-            return false;
-          }
-        } else if (dirString.EqualsLiteral("ltr")) {
-          if (!state.HasState(NS_EVENT_STATE_LTR)) {
-            return false;
-          }
-        } else {
-          // Selectors specifying other directions never match.
-          return false;
-        }
-      }
-      break;
-
-    case CSSPseudoClassType::lang:
-      if (LangPseudoMatches(aElement, nullptr, false, aString, aDocument)) {
-        break;
-      }
-      return false;
-
-    default: MOZ_ASSERT_UNREACHABLE("Called StringPseudoMatches() with unknown string-like pseudo");
-  }
-  return true;
-}
-
-/* static */ Maybe<bool>
-nsCSSPseudoClasses::MatchesElement(Type aType, const dom::Element* aElement)
-{
-  switch (aType) {
-    case CSSPseudoClassType::mozNativeAnonymous:
-      return Some(aElement->IsInNativeAnonymousSubtree());
-    case CSSPseudoClassType::mozUseShadowTreeRoot:
-      return Some(aElement->IsRootOfUseElementShadowTree());
-    case CSSPseudoClassType::mozTableBorderNonzero: {
-      if (!aElement->IsHTMLElement(nsGkAtoms::table)) {
-        return Some(false);
-      }
-      const nsAttrValue *val = aElement->GetParsedAttr(nsGkAtoms::border);
-      return Some(val && (val->Type() != nsAttrValue::eInteger ||
-                          val->GetIntegerValue() != 0));
-    }
-    case CSSPseudoClassType::mozBrowserFrame: {
-      nsIMozBrowserFrame* browserFrame =
-        const_cast<Element*>(aElement)->GetAsMozBrowserFrame();
-      return Some(browserFrame && browserFrame->GetReallyIsBrowser());
-    }
-    default:
-      return Nothing();
-  }
-}
-
-// The dependencies for all state dependent pseudo-classes (i.e. those declared
-// using CSS_STATE_DEPENDENT_PSEUDO_CLASS, the only one of which is :dir(...)).
-const EventStates
-nsCSSPseudoClasses::sPseudoClassStateDependences[size_t(CSSPseudoClassType::Count) + 2] = {
-#define CSS_PSEUDO_CLASS(_name, _value, _flags, _pref) \
-  EventStates(),
-#define CSS_STATE_DEPENDENT_PSEUDO_CLASS(_name, _value, _flags, _pref, _states) \
-  _states,
-#include "nsCSSPseudoClassList.h"
-#undef CSS_STATE_DEPENDENT_PSEUDO_CLASS
-#undef CSS_PSEUDO_CLASS
-  // Add more entries for our fake values to make sure we can't
-  // index out of bounds into this array no matter what.
-  EventStates(),
-  EventStates()
-};
deleted file mode 100644
--- a/layout/style/nsCSSPseudoClasses.h
+++ /dev/null
@@ -1,139 +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/. */
-
-/* atom list for CSS pseudo-classes */
-
-#ifndef nsCSSPseudoClasses_h___
-#define nsCSSPseudoClasses_h___
-
-#include "nsStringFwd.h"
-#include "mozilla/CSSEnabledState.h"
-#include "mozilla/EventStates.h"
-#include "mozilla/Maybe.h"
-
-// The following two flags along with the pref defines where this pseudo
-// class can be used:
-// * If none of the two flags is presented, the pref completely controls
-//   the availability of this pseudo class. And in that case, if it has
-//   no pref, this property is usable everywhere.
-// * If any of the flags is set, this pseudo class is always enabled in
-//   the specific contexts regardless of the value of the pref. If there
-//   is no pref for this pseudo class at all in this case, it is an
-//   internal-only pseudo class, which cannot be used anywhere else.
-#define CSS_PSEUDO_CLASS_ENABLED_MASK                  (3<<0)
-#define CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS          (1<<0)
-#define CSS_PSEUDO_CLASS_ENABLED_IN_CHROME             (1<<1)
-#define CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME \
-  (CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS | CSS_PSEUDO_CLASS_ENABLED_IN_CHROME)
-
-class nsAtom;
-class nsIDocument;
-
-namespace mozilla {
-namespace dom {
-class Element;
-} // namespace dom
-
-// The total count of CSSPseudoClassType is less than 256,
-// so use uint8_t as its underlying type.
-typedef uint8_t CSSPseudoClassTypeBase;
-enum class CSSPseudoClassType : CSSPseudoClassTypeBase
-{
-#define CSS_PSEUDO_CLASS(_name, _value, _flags, _pref) \
-  _name,
-#include "nsCSSPseudoClassList.h"
-#undef CSS_PSEUDO_CLASS
-  Count,
-  NotPseudo,  // This value MUST be second last! SelectorMatches depends on it.
-  MAX
-};
-
-} // namespace mozilla
-
-class nsCSSPseudoClasses
-{
-  typedef mozilla::CSSPseudoClassType Type;
-  typedef mozilla::CSSEnabledState EnabledState;
-
-public:
-  static void RegisterStaticAtoms();
-
-  static Type GetPseudoType(nsAtom* aAtom, EnabledState aEnabledState);
-  static bool HasStringArg(Type aType);
-  static bool HasNthPairArg(Type aType);
-  static bool HasSelectorListArg(Type aType) {
-    return aType == Type::any;
-  }
-  static bool IsUserActionPseudoClass(Type aType);
-
-  // Should only be used on types other than Count and NotPseudoClass
-  static void PseudoTypeToString(Type aType, nsAString& aString);
-
-  static bool IsEnabled(Type aType, EnabledState aEnabledState)
-  {
-    auto index = static_cast<size_t>(aType);
-    MOZ_ASSERT(index < static_cast<size_t>(Type::Count));
-    if (sPseudoClassEnabled[index] ||
-        aEnabledState == EnabledState::eIgnoreEnabledState) {
-      return true;
-    }
-    auto flags = kPseudoClassFlags[index];
-    if (((aEnabledState & EnabledState::eInChrome) &&
-         (flags & CSS_PSEUDO_CLASS_ENABLED_IN_CHROME)) ||
-        ((aEnabledState & EnabledState::eInUASheets) &&
-         (flags & CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS))) {
-      return true;
-    }
-    return false;
-  }
-
-  // Checks whether the given pseudo class matches the element.
-  // It returns Some(result) if this function is able to check
-  // the pseudo-class, Nothing() otherwise.
-  static mozilla::Maybe<bool>
-    MatchesElement(Type aType, const mozilla::dom::Element* aElement);
-
-  /**
-   * Checks if a function-like ident-containing pseudo (:pseudo(ident))
-   * matches a given element.
-   *
-   * Returns true if it parses and matches, Some(false) if it
-   * parses but does not match. Asserts if it fails to parse; only
-   * call this when you're sure it's a string-like pseudo.
-   *
-   * In Servo mode, please ensure that UpdatePossiblyStaleDocumentState()
-   * has been called first.
-   *
-   * @param aElement The element we are trying to match
-   * @param aPseudo The name of the pseudoselector
-   * @param aString The identifier inside the pseudoselector (cannot be null)
-   * @param aDocument The document
-   * @param aStateMask Mask containing states which we should exclude.
-   *                   Ignored if aDependence is null
-   * @param aDependence Pointer to be set to true if we ignored a state due to
-   *                    aStateMask. Can be null.
-   */
-  static bool StringPseudoMatches(const mozilla::dom::Element* aElement,
-                                  mozilla::CSSPseudoClassType aPseudo,
-                                  const char16_t* aString,
-                                  const nsIDocument* aDocument,
-                                  mozilla::EventStates aStateMask,
-                                  bool* const aDependence = nullptr);
-
-  static bool LangPseudoMatches(const mozilla::dom::Element* aElement,
-                                const nsAtom* aOverrideLang,
-                                bool aHasOverrideLang,
-                                const char16_t* aString,
-                                const nsIDocument* aDocument);
-
-  static const mozilla::EventStates sPseudoClassStateDependences[size_t(Type::Count) + 2];
-
-private:
-  static const uint32_t kPseudoClassFlags[size_t(Type::Count)];
-  static bool sPseudoClassEnabled[size_t(Type::Count)];
-};
-
-#endif /* nsCSSPseudoClasses_h___ */
--- a/memory/build/mozjemalloc.cpp
+++ b/memory/build/mozjemalloc.cpp
@@ -4544,32 +4544,35 @@ ArenaCollection::GetById(arena_id_t aAre
   mozilla::AlignedStorage2<arena_t> key;
   key.addr()->mId = aArenaId;
   MutexAutoLock lock(mLock);
   arena_t* result = (aIsPrivate ? mPrivateArenas : mArenas).Search(key.addr());
   MOZ_RELEASE_ASSERT(result);
   return result;
 }
 
-#ifdef NIGHTLY_BUILD
 template<>
 inline arena_id_t
 MozJemalloc::moz_create_arena_with_params(arena_params_t* aParams)
 {
   if (malloc_init()) {
     arena_t* arena = gArenas.CreateArena(/* IsPrivate = */ true, aParams);
     return arena->mId;
   }
   return 0;
 }
 
 template<>
 inline void
 MozJemalloc::moz_dispose_arena(arena_id_t aArenaId)
 {
+  // Until Bug 1364359 is fixed it is unsafe to call moz_dispose_arena.
+  // We want to catch any such occurances of that behavior.
+  MOZ_CRASH("Do not call moz_dispose_arena until Bug 1364359 is fixed.");
+
   arena_t* arena = gArenas.GetById(aArenaId, /* IsPrivate = */ true);
   MOZ_RELEASE_ASSERT(arena);
   gArenas.DisposeArena(arena);
 }
 
 #define MALLOC_DECL(name, return_type, ...)                                    \
   template<>                                                                   \
   inline return_type MozJemalloc::moz_arena_##name(                            \
@@ -4577,30 +4580,16 @@ MozJemalloc::moz_dispose_arena(arena_id_
   {                                                                            \
     BaseAllocator allocator(                                                   \
       gArenas.GetById(aArenaId, /* IsPrivate = */ true));                      \
     return allocator.name(ARGS_HELPER(ARGS, ##__VA_ARGS__));                   \
   }
 #define MALLOC_FUNCS MALLOC_FUNCS_MALLOC_BASE
 #include "malloc_decls.h"
 
-#else
-
-#define MALLOC_DECL(name, return_type, ...)                                    \
-  template<>                                                                   \
-  inline return_type MozJemalloc::name(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) \
-  {                                                                            \
-    return DummyArenaAllocator<MozJemalloc>::name(                             \
-      ARGS_HELPER(ARGS, ##__VA_ARGS__));                                       \
-  }
-#define MALLOC_FUNCS MALLOC_FUNCS_ARENA
-#include "malloc_decls.h"
-
-#endif
-
 // End non-standard functions.
 // ***************************************************************************
 // Begin library-private functions, used by threading libraries for protection
 // of malloc during fork().  These functions are only called if the program is
 // running in threaded mode, so there is no need to check whether the program
 // is threaded here.
 #ifndef XP_DARWIN
 static
--- a/memory/gtest/TestJemalloc.cpp
+++ b/memory/gtest/TestJemalloc.cpp
@@ -11,17 +11,16 @@
 #include "nsCOMPtr.h"
 #include "nsICrashReporter.h"
 #include "nsServiceManagerUtils.h"
 #include "Utils.h"
 
 #include "gtest/gtest.h"
 
 
-#ifdef NIGHTLY_BUILD
 #if defined(DEBUG) && !defined(XP_WIN) && !defined(ANDROID)
 #define HAS_GDB_SLEEP_DURATION 1
 extern unsigned int _gdb_sleep_duration;
 #endif
 
 // Death tests are too slow on OSX because of the system crash reporter.
 #ifndef XP_DARWIN
 static void DisableCrashReporter()
@@ -36,17 +35,17 @@ static void DisableCrashReporter()
 // Wrap ASSERT_DEATH_IF_SUPPORTED to disable the crash reporter
 // when entering the subprocess, so that the expected crashes don't
 // create a minidump that the gtest harness will interpret as an error.
 #define ASSERT_DEATH_WRAP(a, b) \
   ASSERT_DEATH_IF_SUPPORTED({ DisableCrashReporter(); a; }, b)
 #else
 #define ASSERT_DEATH_WRAP(a, b)
 #endif
-#endif
+
 
 using namespace mozilla;
 
 static inline void
 TestOne(size_t size)
 {
   size_t req = size;
   size_t adv = malloc_good_size(req);
@@ -250,48 +249,50 @@ TEST(Jemalloc, PtrInfo)
   // these addresses; this is more about checking that we don't crash.
   for (size_t i = 0; i < stats.chunksize; i += 256) {
     jemalloc_ptr_info(&chunk[i], &info);
   }
 
   jemalloc_thread_local_arena(false);
 }
 
-#ifdef NIGHTLY_BUILD
 size_t sSizes[] = { 1,      42,      79,      918,     1.5_KiB,
                     73_KiB, 129_KiB, 1.1_MiB, 2.6_MiB, 5.1_MiB };
 
 TEST(Jemalloc, Arenas)
 {
   arena_id_t arena = moz_create_arena();
   ASSERT_TRUE(arena != 0);
   void* ptr = moz_arena_malloc(arena, 42);
   ASSERT_TRUE(ptr != nullptr);
   ptr = moz_arena_realloc(arena, ptr, 64);
   ASSERT_TRUE(ptr != nullptr);
   moz_arena_free(arena, ptr);
   ptr = moz_arena_calloc(arena, 24, 2);
   // For convenience, free can be used to free arena pointers.
   free(ptr);
-  moz_dispose_arena(arena);
+  // Until Bug 1364359 is fixed it is unsafe to call moz_dispose_arena.
+  // moz_dispose_arena(arena);
 
 #ifdef HAS_GDB_SLEEP_DURATION
   // Avoid death tests adding some unnecessary (long) delays.
   unsigned int old_gdb_sleep_duration = _gdb_sleep_duration;
   _gdb_sleep_duration = 0;
 #endif
 
   // Can't use an arena after it's disposed.
-  ASSERT_DEATH_WRAP(moz_arena_malloc(arena, 80), "");
+  // ASSERT_DEATH_WRAP(moz_arena_malloc(arena, 80), "");
 
   // Arena id 0 can't be used to somehow get to the main arena.
   ASSERT_DEATH_WRAP(moz_arena_malloc(0, 80), "");
 
   arena = moz_create_arena();
   arena_id_t arena2 = moz_create_arena();
+  // Ensure arena2 is used to prevent OSX errors:
+  (void)arena2;
 
   // For convenience, realloc can also be used to reallocate arena pointers.
   // The result should be in the same arena. Test various size class transitions.
   for (size_t from_size : sSizes) {
     SCOPED_TRACE(testing::Message() << "from_size = " << from_size);
     for (size_t to_size : sSizes) {
       SCOPED_TRACE(testing::Message() << "to_size = " << to_size);
       ptr = moz_arena_malloc(arena, from_size);
@@ -300,18 +301,20 @@ TEST(Jemalloc, Arenas)
       ASSERT_DEATH_WRAP(moz_arena_free(arena2, ptr), "");
       // Likewise for moz_arena_realloc.
       ASSERT_DEATH_WRAP(moz_arena_realloc(arena2, ptr, from_size), "");
       // The following will crash if it's not in the right arena.
       moz_arena_free(arena, ptr);
     }
   }
 
-  moz_dispose_arena(arena2);
-  moz_dispose_arena(arena);
+  // Until Bug 1364359 is fixed it is unsafe to call moz_dispose_arena.
+  // moz_dispose_arena(arena2);
+  // Until Bug 1364359 is fixed it is unsafe to call moz_dispose_arena.
+  // moz_dispose_arena(arena);
 
 #ifdef HAS_GDB_SLEEP_DURATION
   _gdb_sleep_duration = old_gdb_sleep_duration;
 #endif
 }
 
 // Check that a buffer aPtr is entirely filled with a given character from
 // aOffset to aSize. For faster comparison, the caller is required to fill a
@@ -424,17 +427,18 @@ TEST(Jemalloc, InPlace)
         EXPECT_EQ(ptr, ptr2);
       } else {
         EXPECT_NE(ptr, ptr2);
       }
       moz_arena_free(arena, ptr2);
     }
   }
 
-  moz_dispose_arena(arena);
+  // Until Bug 1364359 is fixed it is unsafe to call moz_dispose_arena.
+  // moz_dispose_arena(arena);
 }
 
 TEST(Jemalloc, JunkPoison)
 {
   jemalloc_stats_t stats;
   jemalloc_stats(&stats);
 
   // Create buffers in a separate arena, for faster comparisons with
@@ -605,15 +609,16 @@ TEST(Jemalloc, JunkPoison)
           ASSERT_NO_FATAL_FAILURE(bulk_compare(
             ptr2, from_size, rounded_to_size, junk_buf, stats.page_size));
         }
         moz_arena_free(arena, ptr2);
       }
     }
   }
 
-  moz_dispose_arena(arena);
+  // Until Bug 1364359 is fixed it is unsafe to call moz_dispose_arena.
+  // moz_dispose_arena(arena);
 
   moz_arena_free(buf_arena, poison_buf);
   moz_arena_free(buf_arena, junk_buf);
-  moz_dispose_arena(buf_arena);
+  // Until Bug 1364359 is fixed it is unsafe to call moz_dispose_arena.
+  // moz_dispose_arena(buf_arena);
 }
-#endif
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -3057,19 +3057,16 @@ pref("layout.css.prefixes.gradients", tr
 // Are webkit-prefixed properties & property-values supported?
 pref("layout.css.prefixes.webkit", true);
 
 // Are "-webkit-{min|max}-device-pixel-ratio" media queries supported?
 // (Note: this pref has no effect if the master 'layout.css.prefixes.webkit'
 // pref is set to false.)
 pref("layout.css.prefixes.device-pixel-ratio-webkit", false);
 
-// Is support for the :scope selector enabled?
-pref("layout.css.scope-pseudo.enabled", true);
-
 // Is support for background-blend-mode enabled?
 pref("layout.css.background-blend-mode.enabled", true);
 
 // Is support for CSS text-combine-upright (tate-chu-yoko) enabled?
 pref("layout.css.text-combine-upright.enabled", true);
 // Is support for CSS text-combine-upright: digits 2-4 enabled?
 pref("layout.css.text-combine-upright-digits.enabled", false);
 
--- a/parser/xml/nsISAXXMLReader.idl
+++ b/parser/xml/nsISAXXMLReader.idl
@@ -56,34 +56,16 @@ interface nsISAXXMLReader : nsIStreamLis
    * recommended that all SAX applications implement an error handler
    * to avoid unexpected bugs.
    *
    * Applications may register a new or different handler in the
    * middle of a parse, and the SAX parser must begin using the new
    * handler immediately.
    */
   attribute nsISAXErrorHandler errorHandler;
-
-  /**
-   * @param str The UTF16 string to be parsed
-   * @param contentType The content type of the string (see parseFromStream)
-   */
-  void parseFromString(in AString str, in string contentType);
-
-  /**
-   * @param stream The byte stream whose contents are parsed
-   * @param charset The character set that was used to encode the byte
-   *                stream. NULL if not specified.
-   * @param contentType The content type of the string - either text/xml,
-   *                    application/xml, or application/xhtml+xml.
-   *                    Must not be NULL.
-   */
-  void parseFromStream(in nsIInputStream stream,
-                       in string charset,
-                       in string contentType);
   
   /**
    * Begin an asynchronous parse. This method initializes the parser,
    * and must be called before any nsIStreamListener methods. It is
    * then the caller's duty to call nsIStreamListener methods to drive
    * the parser. Once this method is called, the caller must not call
    * one of the other parse methods.
    *
--- a/parser/xml/nsSAXXMLReader.cpp
+++ b/parser/xml/nsSAXXMLReader.cpp
@@ -237,122 +237,16 @@ nsSAXXMLReader::GetErrorHandler(nsISAXEr
 NS_IMETHODIMP
 nsSAXXMLReader::SetErrorHandler(nsISAXErrorHandler *aErrorHandler)
 {
   mErrorHandler = aErrorHandler;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSAXXMLReader::ParseFromString(const nsAString &aStr,
-                                const char *aContentType)
-{
-  // Don't call this in the middle of an async parse
-  NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
-
-  NS_ConvertUTF16toUTF8 data(aStr);
-
-  // The new stream holds a reference to the buffer
-  nsCOMPtr<nsIInputStream> stream;
-  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
-                                      data.get(), data.Length(),
-                                      NS_ASSIGNMENT_DEPEND);
-  NS_ENSURE_SUCCESS(rv, rv);
-  return ParseFromStream(stream, "UTF-8", aContentType);
-}
-
-NS_IMETHODIMP
-nsSAXXMLReader::ParseFromStream(nsIInputStream *aStreamPtr,
-                                const char *aCharset,
-                                const char *aContentType)
-{
-  // Don't call this in the middle of an async parse
-  NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);
-
-  NS_ENSURE_ARG(aStreamPtr);
-  NS_ENSURE_ARG(aContentType);
-
-  // Put the nsCOMPtr out here so we hold a ref to the stream as needed
-  nsresult rv;
-  nsCOMPtr<nsIInputStream> stream = aStreamPtr;
-  if (!NS_InputStreamIsBuffered(stream)) {
-    nsCOMPtr<nsIInputStream> bufferedStream;
-    rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
-                                   stream.forget(), 4096);
-    NS_ENSURE_SUCCESS(rv, rv);
-    stream = bufferedStream;
-  }
- 
-  rv = EnsureBaseURI();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIPrincipal> nullPrincipal = NullPrincipal::Create();
-
-  // The following channel is never openend, so it does not matter what
-  // securityFlags we pass; let's follow the principle of least privilege.
-  nsCOMPtr<nsIChannel> parserChannel;
-  nsCOMPtr<nsIInputStream> tmpStream = stream;
-  rv = NS_NewInputStreamChannel(getter_AddRefs(parserChannel),
-                                mBaseURI,
-                                tmpStream.forget(),
-                                nullPrincipal,
-                                nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
-                                nsIContentPolicy::TYPE_OTHER,
-                                nsDependentCString(aContentType));
-  if (!parserChannel || NS_FAILED(rv))
-    return NS_ERROR_FAILURE;
-
-  if (aCharset)
-    parserChannel->SetContentCharset(nsDependentCString(aCharset));
-
-  rv = InitParser(nullptr, parserChannel);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = mListener->OnStartRequest(parserChannel, nullptr);
-  if (NS_FAILED(rv))
-    parserChannel->Cancel(rv);
-
-  nsresult status;
-  parserChannel->GetStatus(&status);
-
-  uint64_t offset = 0;
-  while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
-    uint64_t available;
-    rv = stream->Available(&available);
-    if (rv == NS_BASE_STREAM_CLOSED) {
-      rv = NS_OK;
-      available = 0;
-    }
-    if (NS_FAILED(rv)) {
-      parserChannel->Cancel(rv);
-      break;
-    }
-    if (! available)
-      break; // blocking input stream has none available when done
-
-    if (available > UINT32_MAX)
-      available = UINT32_MAX;
-
-    rv = mListener->OnDataAvailable(parserChannel, nullptr,
-                                    stream,
-                                    offset,
-                                    (uint32_t)available);
-    if (NS_SUCCEEDED(rv))
-      offset += available;
-    else
-      parserChannel->Cancel(rv);
-    parserChannel->GetStatus(&status);
-  }
-  rv = mListener->OnStopRequest(parserChannel, nullptr, status);
-  mListener = nullptr;
-
-  return rv;
-}
-
-NS_IMETHODIMP
 nsSAXXMLReader::ParseAsync(nsIRequestObserver *aObserver)
 {
   mParserObserver = aObserver;
   mIsAsyncParse = true;
   return NS_OK;
 }
 
 // nsIRequestObserver
--- a/parser/xml/test/unit/test_parser.js
+++ b/parser/xml/test/unit/test_parser.js
@@ -1,9 +1,11 @@
-function updateDocumentSourceMaps(source) {
+ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
+
+function updateDocumentSourceMaps(src) {
   const nsIDOMNode = Ci.nsIDOMNode;
 
   const nsISAXXMLReader = Ci.nsISAXXMLReader;
   const saxReader = Cc["@mozilla.org/saxparser/xmlreader;1"]
                       .createInstance(nsISAXXMLReader);
   try {
     saxReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
     saxReader.setFeature("http://xml.org/sax/features/namespace", true);
@@ -71,17 +73,44 @@ function updateDocumentSourceMaps(source
     ignorableWarning: function ignorableWarning(aError) {
       do_parse_check(!aError, "XML ignorable warning");
     }
   };
 
   saxReader.contentHandler = contentHandler;
   saxReader.errorHandler   = errorHandler;
 
-  saxReader.parseFromString(source, "application/xml");
+  let type = "application/xml";
+  let uri = NetUtil.newURI("http://example.org/");
+
+  let sStream = Cc["@mozilla.org/io/string-input-stream;1"]
+               .createInstance(Ci.nsIStringInputStream);
+  sStream.setData(src, src.length);
+  var bStream = Cc["@mozilla.org/network/buffered-input-stream;1"]
+                .createInstance(Ci.nsIBufferedInputStream);
+  bStream.init(sStream, 4096);
+
+  let channel = Cc["@mozilla.org/network/input-stream-channel;1"].
+    createInstance(Ci.nsIInputStreamChannel);
+  channel.setURI(uri);
+  channel.contentStream = bStream;
+  channel.QueryInterface(Ci.nsIChannel);
+  channel.contentType = type;
+
+  saxReader.parseAsync(null, uri);
+  saxReader.onStartRequest(channel, uri);
+
+  let pos = 0;
+  let count = bStream.available();
+  while (count > 0) {
+    saxReader.onDataAvailable(channel, null, bStream, pos, count);
+    pos += count;
+    count = bStream.available();
+  }
+  saxReader.onStopRequest(channel, null, Cr.NS_OK);
 
   // Just in case it leaks.
   saxReader.contentHandler = null;
   saxReader.errorHandler   = null;
 
   return parseErrorLog;
 }
 
@@ -92,16 +121,17 @@ function do_check_true_with_dump(aCondit
   Assert.ok(aCondition);
 }
 
 function run_test() {
   var src;
   src = "<!DOCTYPE foo>\n<!-- all your foo are belong to bar -->";
   src += "<foo id='foo'>\n<?foo wooly bully?>\nfoo";
   src += "<![CDATA[foo fighters]]></foo>\n";
+
   var parseErrorLog = updateDocumentSourceMaps(src);
 
   if (parseErrorLog.length > 0) {
     dump(parseErrorLog.join("\n"));
   }
   do_check_true_with_dump(parseErrorLog.length == 0, parseErrorLog);
 
   // End tag isn't well-formed.
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -1167,26 +1167,23 @@ class PackageFrontend(MachCommandBase):
 
         '''
         pass
 
     def _make_artifacts(self, tree=None, job=None, skip_cache=False):
         state_dir = self._mach_context.state_dir
         cache_dir = os.path.join(state_dir, 'package-frontend')
 
-        here = os.path.abspath(os.path.dirname(__file__))
-        build_obj = MozbuildObject.from_environment(cwd=here)
-
         hg = None
-        if conditions.is_hg(build_obj):
-            hg = build_obj.substs['HG']
+        if conditions.is_hg(self):
+            hg = self.substs['HG']
 
         git = None
-        if conditions.is_git(build_obj):
-            git = build_obj.substs['GIT']
+        if conditions.is_git(self):
+            git = self.substs['GIT']
 
         from mozbuild.artifacts import Artifacts
         artifacts = Artifacts(tree, self.substs, self.defines, job,
                               log=self.log, cache_dir=cache_dir,
                               skip_cache=skip_cache, hg=hg, git=git,
                               topsrcdir=self.topsrcdir)
         return artifacts
 
--- a/security/manager/ssl/nsNSSCertHelper.cpp
+++ b/security/manager/ssl/nsNSSCertHelper.cpp
@@ -20,68 +20,16 @@
 #include "nsNSSCertValidity.h"
 #include "nsNSSCertificate.h"
 #include "nsServiceManagerUtils.h"
 #include "prerror.h"
 #include "secder.h"
 
 using namespace mozilla;
 
-/* Object Identifier constants */
-#define CONST_OID static const unsigned char
-#define MICROSOFT_OID 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37
-#define PKIX_OID 0x2b, 0x6, 0x01, 0x05, 0x05, 0x07
-CONST_OID msCertExtCerttype[] = { MICROSOFT_OID, 20, 2 };
-CONST_OID msNTPrincipalName[] = { MICROSOFT_OID, 20, 2, 3 };
-CONST_OID msCertsrvCAVersion[] = { MICROSOFT_OID, 21, 1 };
-CONST_OID msNTDSReplication[] = { MICROSOFT_OID, 25, 1 };
-CONST_OID pkixLogotype[] = { PKIX_OID, 1, 12 };
-
-#define OI(x)                                                                  \
-  {                                                                            \
-    siDEROID, (unsigned char*)x, sizeof x                                      \
-  }
-#define OD(oid, desc, mech, ext)                                               \
-  {                                                                            \
-    OI(oid), SEC_OID_UNKNOWN, desc, mech, ext                                  \
-  }
-#define SEC_OID(tag) more_oids[tag].offset
-
-static SECOidData more_oids[] = {
-/* Microsoft OIDs */
-#define MS_CERT_EXT_CERTTYPE 0
-  OD(msCertExtCerttype,
-     "Microsoft Certificate Template Name",
-     CKM_INVALID_MECHANISM,
-     INVALID_CERT_EXTENSION),
-
-#define MS_NT_PRINCIPAL_NAME 1
-  OD(msNTPrincipalName,
-     "Microsoft Principal Name",
-     CKM_INVALID_MECHANISM,
-     INVALID_CERT_EXTENSION),
-
-#define MS_CERTSERV_CA_VERSION 2
-  OD(msCertsrvCAVersion,
-     "Microsoft CA Version",
-     CKM_INVALID_MECHANISM,
-     INVALID_CERT_EXTENSION),
-
-#define MS_NTDS_REPLICATION 3
-  OD(msNTDSReplication,
-     "Microsoft Domain GUID",
-     CKM_INVALID_MECHANISM,
-     INVALID_CERT_EXTENSION),
-
-#define PKIX_LOGOTYPE 4
-  OD(pkixLogotype, "Logotype", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION),
-};
-
-static const unsigned int numOids = (sizeof more_oids) / (sizeof more_oids[0]);
-
 static nsresult
 GetPIPNSSBundle(nsIStringBundle** pipnssBundle)
 {
   nsCOMPtr<nsIStringBundleService> bundleService(
     do_GetService(NS_STRINGBUNDLE_CONTRACTID));
   if (!bundleService) {
     return NS_ERROR_NOT_AVAILABLE;
   }
@@ -586,29 +534,17 @@ GetOIDText(SECItem* oid, nsAString& text
       break;
     case SEC_OID_SECG_EC_SECT571K1:
       bundlekey = "CertDumpECsect571k1";
       break;
     case SEC_OID_SECG_EC_SECT571R1:
       bundlekey = "CertDumpECsect571r1";
       break;
     default:
-      if (oidTag == SEC_OID(MS_CERT_EXT_CERTTYPE)) {
-        bundlekey = "CertDumpMSCerttype";
-        break;
-      }
-      if (oidTag == SEC_OID(MS_CERTSERV_CA_VERSION)) {
-        bundlekey = "CertDumpMSCAVersion";
-        break;
-      }
-      if (oidTag == SEC_OID(PKIX_LOGOTYPE)) {
-        bundlekey = "CertDumpLogotype";
-        break;
-      }
-      /* fallthrough */
+      break;
   }
 
   if (bundlekey) {
     rv = GetPIPNSSBundleString(bundlekey, text);
   } else {
     nsAutoString text2;
     rv = GetDefaultOIDFormat(oid, text2, ' ');
     if (NS_FAILED(rv))
@@ -940,107 +876,33 @@ AppendBMPtoUTF16(const UniquePLArenaPool
         false, data, len, utf8Val, utf8ValLen, &utf8ValLen)) {
     return NS_ERROR_FAILURE;
   }
   AppendUTF8toUTF16((char*)utf8Val, text);
   return NS_OK;
 }
 
 static nsresult
-ProcessBMPString(SECItem* extData, nsAString& text)
-{
-  UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
-  if (!arena) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  SECItem item;
-  if (SEC_ASN1DecodeItem(
-        arena.get(), &item, SEC_ASN1_GET(SEC_BMPStringTemplate), extData) !=
-      SECSuccess) {
-    return NS_ERROR_FAILURE;
-  }
-
-  return AppendBMPtoUTF16(arena, item.data, item.len, text);
-}
-
-static nsresult
 ProcessGeneralName(const UniquePLArenaPool& arena, CERTGeneralName* current,
                    nsAString& text)
 {
   NS_ENSURE_ARG_POINTER(current);
 
   nsAutoString key;
   nsAutoString value;
   nsresult rv = NS_OK;
 
   switch (current->type) {
-    case certOtherName: {
-      SECOidTag oidTag = SECOID_FindOIDTag(&current->name.OthName.oid);
-      if (oidTag == SEC_OID(MS_NT_PRINCIPAL_NAME)) {
-        /* The type of this name is apparently nowhere explicitly
-         documented. However, in the generated templates, it is always
-         UTF-8. So try to decode this as UTF-8; if that fails, dump the
-         raw data. */
-        SECItem decoded;
-        GetPIPNSSBundleString("CertDumpMSNTPrincipal", key);
-        if (SEC_ASN1DecodeItem(arena.get(),
-                               &decoded,
-                               SEC_ASN1_GET(SEC_UTF8StringTemplate),
-                               &current->name.OthName.name) == SECSuccess) {
-          AppendUTF8toUTF16(nsAutoCString((char*)decoded.data, decoded.len),
-                            value);
-        } else {
-          ProcessRawBytes(&current->name.OthName.name, value);
-        }
-        break;
-      } else if (oidTag == SEC_OID(MS_NTDS_REPLICATION)) {
-        /* This should be a 16-byte GUID */
-        SECItem guid;
-        GetPIPNSSBundleString("CertDumpMSDomainGUID", key);
-        if (SEC_ASN1DecodeItem(arena.get(),
-                               &guid,
-                               SEC_ASN1_GET(SEC_OctetStringTemplate),
-                               &current->name.OthName.name) == SECSuccess &&
-            guid.len == 16) {
-          char buf[40];
-          unsigned char* d = guid.data;
-          SprintfLiteral(buf,
-                         "{%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%"
-                         ".2x%.2x%.2x%.2x%.2x}",
-                         d[3],
-                         d[2],
-                         d[1],
-                         d[0],
-                         d[5],
-                         d[4],
-                         d[7],
-                         d[6],
-                         d[8],
-                         d[9],
-                         d[10],
-                         d[11],
-                         d[12],
-                         d[13],
-                         d[14],
-                         d[15]);
-          value.AssignASCII(buf);
-        } else {
-          ProcessRawBytes(&current->name.OthName.name, value);
-        }
-      } else {
-        rv = GetDefaultOIDFormat(
-          &current->name.OthName.oid, key, ' ');
-        if (NS_FAILED(rv)) {
-          return rv;
-        }
-        ProcessRawBytes(&current->name.OthName.name, value);
+    case certOtherName:
+      rv = GetDefaultOIDFormat(&current->name.OthName.oid, key, ' ');
+      if (NS_FAILED(rv)) {
+        return rv;
       }
+      ProcessRawBytes(&current->name.OthName.name, value);
       break;
-    }
     case certRFC822Name:
       GetPIPNSSBundleString("CertDumpRFC822Name", key);
       value.AssignASCII((char*)current->name.other.data,
                         current->name.other.len);
       break;
     case certDNSName:
       GetPIPNSSBundleString("CertDumpDNSName", key);
       value.AssignASCII((char*)current->name.other.data,
@@ -1489,48 +1351,16 @@ ProcessAuthInfoAccess(SECItem* extData, 
       return rv;
     }
   }
 
   return rv;
 }
 
 static nsresult
-ProcessMSCAVersion(SECItem* extData, nsAString& text)
-{
-  MOZ_ASSERT(extData);
-  NS_ENSURE_ARG(extData);
-
-  ScopedAutoSECItem decoded;
-  if (SEC_ASN1DecodeItem(
-        nullptr, &decoded, SEC_ASN1_GET(SEC_IntegerTemplate), extData) !=
-      SECSuccess) {
-    /* This extension used to be an Integer when this code
-       was written, but apparently isn't anymore. Display
-       the raw bytes instead. */
-    return ProcessRawBytes(extData, text);
-  }
-
-  unsigned long version;
-  if (SEC_ASN1DecodeInteger(&decoded, &version) != SECSuccess) {
-    /* Value out of range, display raw bytes */
-    return ProcessRawBytes(extData, text);
-  }
-
-  /* Apparently, the encoding is <minor><major>, with 16 bits each */
-  char buf[50];
-  if (SprintfLiteral(buf, "%lu.%lu", version & 0xFFFF, version >> 16) <= 0) {
-    return NS_ERROR_FAILURE;
-  }
-
-  text.AppendASCII(buf);
-  return NS_OK;
-}
-
-static nsresult
 ProcessExtensionData(SECOidTag oidTag, SECItem* extData, nsAString& text)
 {
   nsresult rv;
   switch (oidTag) {
     case SEC_OID_X509_KEY_USAGE:
       rv = ProcessKeyUsageExtension(extData, text);
       break;
     case SEC_OID_X509_BASIC_CONSTRAINTS:
@@ -1554,24 +1384,16 @@ ProcessExtensionData(SECOidTag oidTag, S
       break;
     case SEC_OID_X509_CRL_DIST_POINTS:
       rv = ProcessCrlDistPoints(extData, text);
       break;
     case SEC_OID_X509_AUTH_INFO_ACCESS:
       rv = ProcessAuthInfoAccess(extData, text);
       break;
     default:
-      if (oidTag == SEC_OID(MS_CERT_EXT_CERTTYPE)) {
-        rv = ProcessBMPString(extData, text);
-        break;
-      }
-      if (oidTag == SEC_OID(MS_CERTSERV_CA_VERSION)) {
-        rv = ProcessMSCAVersion(extData, text);
-        break;
-      }
       rv = ProcessRawBytes(extData, text);
       break;
   }
   return rv;
 }
 
 static nsresult
 ProcessSingleExtension(CERTCertExtension* extension,
@@ -1804,44 +1626,19 @@ ProcessExtensions(CERTCertExtension** ex
 
     asn1Objects->AppendElement(newExtension);
   }
   parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
   asn1Objects->AppendElement(extensionSequence);
   return NS_OK;
 }
 
-static bool registered;
-static SECStatus
-RegisterDynamicOids()
-{
-  unsigned int i;
-  SECStatus rv = SECSuccess;
-
-  if (registered)
-    return rv;
-
-  for (i = 0; i < numOids; i++) {
-    SECOidTag tag = SECOID_AddEntry(&more_oids[i]);
-    if (tag == SEC_OID_UNKNOWN) {
-      rv = SECFailure;
-      continue;
-    }
-    more_oids[i].offset = tag;
-  }
-  registered = true;
-  return rv;
-}
-
 nsresult
 nsNSSCertificate::CreateTBSCertificateASN1Struct(nsIASN1Sequence** retSequence)
 {
-  if (RegisterDynamicOids() != SECSuccess)
-    return NS_ERROR_FAILURE;
-
   //
   //   TBSCertificate  ::=  SEQUENCE  {
   //        version         [0]  EXPLICIT Version DEFAULT v1,
   //        serialNumber         CertificateSerialNumber,
   //        signature            AlgorithmIdentifier,
   //        issuer               Name,
   //        validity             Validity,
   //        subject              Name,
--- a/services/sync/tps/extensions/tps/bootstrap.js
+++ b/services/sync/tps/extensions/tps/bootstrap.js
@@ -6,19 +6,23 @@
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/osfile.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "categoryManager",
                                    "@mozilla.org/categorymanager;1",
                                    "nsICategoryManager");
 
+XPCOMUtils.defineLazyServiceGetter(this, "resProto",
+                                   "@mozilla.org/network/protocol;1?name=resource",
+                                   "nsISubstitutingProtocolHandler");
+
 const Cm = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
 
-const CATMAN_CONTRACTID         = "@mozilla.org/categorymanager;1";
+const CATMAN_CONTRACTID        = "@mozilla.org/categorymanager;1";
 
 const CATEGORY_NAME = "command-line-handler";
 const CATEGORY_ENTRY = "m-tps";
 
 function TPSCmdLine() {}
 
 TPSCmdLine.prototype = {
   factory: XPCOMUtils._getFactory(TPSCmdLine),
@@ -84,16 +88,18 @@ TPSCmdLine.prototype = {
   helpInfo: "  --tps <file>              Run TPS tests with the given test file.\n" +
             "  --tpsphase <phase>        Run the specified phase in the TPS test.\n" +
             "  --tpslogfile <file>       Logfile for TPS output.\n" +
             "  --ignore-unused-engines   Don't load engines not used in tests.\n",
 };
 
 function startup(data, reason) {
   TPSCmdLine.prototype.register();
+  resProto.setSubstitution("tps", Services.io.newURI("resource", null, data.resourceURI));
 }
 
 function shutdown(data, reason) {
+  resProto.setSubstitution("tps", null);
   TPSCmdLine.prototype.unregister();
 }
 
 function install(data, reason) {}
 function uninstall(data, reason) {}
deleted file mode 100644
--- a/services/sync/tps/extensions/tps/chrome.manifest
+++ /dev/null
@@ -1,1 +0,0 @@
-resource tps resource/
--- a/services/sync/tps/extensions/tps/install.rdf
+++ b/services/sync/tps/extensions/tps/install.rdf
@@ -10,17 +10,17 @@
     <em:version>0.5</em:version>
     <em:bootstrap>true</em:bootstrap>
 
     <em:targetApplication>
       <!-- Firefox -->
       <Description>
         <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
         <em:minVersion>24.0.*</em:minVersion>
-        <em:maxVersion>31.0.*</em:maxVersion>
+        <em:maxVersion>*</em:maxVersion>
       </Description>
     </em:targetApplication>
 
     <!-- front-end metadata -->
     <em:name>TPS</em:name>
     <em:description>Sync test extension</em:description>
     <em:creator>Jonathan Griffin</em:creator>
     <em:contributor>Henrik Skupin</em:contributor>
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -1630,17 +1630,17 @@ dependencies = [
 [[package]]
 name = "malloc_size_of"
 version = "0.0.1"
 dependencies = [
  "app_units 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
- "mozjs 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mozjs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "serde_bytes 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo_arc 0.1.1",
  "smallbitvec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1808,17 +1808,17 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "mozjs"
-version = "0.4.1"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozjs_sys 0.50.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2485,28 +2485,29 @@ dependencies = [
  "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.4.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper_serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "jstraceable_derive 0.0.1",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.0.1",
  "metrics 0.0.1",
  "mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozangle 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "mozjs 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mozjs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3898,17 +3899,17 @@ dependencies = [
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
 "checksum mime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d69889cdc6336ed56b174514ce876c4c3dc564cc23dd872e7bca589bb2a36c8"
 "checksum mime_guess 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76da6df85047af8c0edfa53f48eb1073012ce1cc95c8fedc0a374f659a89dd65"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
 "checksum mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "75f72a93f046f1517e3cfddc0a096eb756a2ba727d36edc8227dee769a50a9b0"
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
 "checksum mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9de3eca27871df31c33b807f834b94ef7d000956f57aa25c5aed9c5f0aae8f6f"
 "checksum mozangle 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1f0583e6792917f498bb3a7440f777a59353102063445ab7f5e9d1dc4ed593aa"
-"checksum mozjs 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ab870a85b83df2a5def5a941e5a50493994da0989067b16ab254ce1c770add"
+"checksum mozjs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71268984a252907b3ee8c7dec2c0dffcf6acaba8af35a45865fa7626bc393c38"
 "checksum mozjs_sys 0.50.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e61a792a125b1364c5ec50255ed8343ce02dc56098f8868dd209d472c8de006a"
 "checksum mp3-metadata 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ab5f1d2693586420208d1200ce5a51cd44726f055b635176188137aff42c7de"
 "checksum mp4parse 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f821e3799bc0fd16d9b861fb02fa7ee1b5fba29f45ad591dade105c48ca9a1a0"
 "checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67"
 "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
 "checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
 "checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40"
 "checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37"
--- a/servo/components/malloc_size_of/Cargo.toml
+++ b/servo/components/malloc_size_of/Cargo.toml
@@ -18,17 +18,17 @@ servo = [
     "xml5ever",
 ]
 
 [dependencies]
 app_units = "0.6"
 cssparser = "0.23.0"
 euclid = "0.17"
 hashglobe = { path = "../hashglobe" }
-mozjs = { version = "0.4", features = ["promises"], optional = true }
+mozjs = { version = "0.5.0", features = ["promises"], optional = true }
 selectors = { path = "../selectors" }
 serde_bytes = { version = "0.10", optional = true }
 servo_arc = { path = "../servo_arc" }
 smallbitvec = "1.0.3"
 smallvec = "0.6"
 string_cache = { version = "0.7", optional = true }
 url = { version = "1.2", optional = true }
 webrender_api = { git = "https://github.com/servo/webrender", features = ["ipc"], optional = true }
--- a/servo/components/script/Cargo.toml
+++ b/servo/components/script/Cargo.toml
@@ -47,27 +47,28 @@ euclid = "0.17"
 fnv = "1.0"
 gleam = "0.4.29"
 half = "1.0"
 html5ever = "0.22"
 hyper = "0.10"
 hyper_serde = "0.8"
 image = "0.18"
 ipc-channel = "0.10"
+itertools = "0.7.6"
 jstraceable_derive = {path = "../jstraceable_derive"}
 lazy_static = "1"
 libc = "0.2"
 log = "0.3.5"
 malloc_size_of = { path = "../malloc_size_of" }
 malloc_size_of_derive = { path = "../malloc_size_of_derive" }
 metrics = {path = "../metrics"}
 mitochondria = "1.1.2"
 mime = "0.2.1"
 mime_guess = "1.8.0"
-mozjs = { version = "0.4", features = ["promises"]}
+mozjs = { version = "0.5.0", features = ["promises"]}
 msg = {path = "../msg"}
 net_traits = {path = "../net_traits"}
 num-traits = "0.1.32"
 offscreen_gl_context = { version = "0.15", features = ["serde"] }
 parking_lot = "0.5"
 phf = "0.7.18"
 profile_traits = {path = "../profile_traits"}
 ref_filter_map = "1.0.1"
--- a/servo/components/script/body.rs
+++ b/servo/components/script/body.rs
@@ -11,18 +11,20 @@ use dom::bindings::trace::RootedTraceabl
 use dom::blob::{Blob, BlobImpl};
 use dom::formdata::FormData;
 use dom::globalscope::GlobalScope;
 use dom::promise::Promise;
 use js::jsapi::Heap;
 use js::jsapi::JSContext;
 use js::jsapi::JSObject;
 use js::jsapi::JS_ClearPendingException;
+use js::jsapi::JS_GetPendingException;
 use js::jsapi::JS_ParseJSON;
 use js::jsapi::Value as JSValue;
+use js::jsval::JSVal;
 use js::jsval::UndefinedValue;
 use js::typedarray::{ArrayBuffer, CreateWith};
 use mime::{Mime, TopLevel, SubLevel};
 use std::cell::Ref;
 use std::ptr;
 use std::rc::Rc;
 use std::str;
 use url::form_urlencoded;
@@ -37,16 +39,17 @@ pub enum BodyType {
 }
 
 pub enum FetchedData {
     Text(String),
     Json(RootedTraceableBox<Heap<JSValue>>),
     BlobData(DomRoot<Blob>),
     FormData(DomRoot<FormData>),
     ArrayBuffer(RootedTraceableBox<Heap<*mut JSObject>>),
+    JSException(RootedTraceableBox<Heap<JSVal>>)
 }
 
 // https://fetch.spec.whatwg.org/#concept-body-consume-body
 #[allow(unrooted_must_root)]
 pub fn consume_body<T: BodyOperations + DomObject>(object: &T, body_type: BodyType) -> Rc<Promise> {
     let promise = Promise::new(&object.global());
 
     // Step 1
@@ -85,17 +88,18 @@ pub fn consume_body_with_promise<T: Body
 
     match pkg_data_results {
         Ok(results) => {
             match results {
                 FetchedData::Text(s) => promise.resolve_native(&USVString(s)),
                 FetchedData::Json(j) => promise.resolve_native(&j),
                 FetchedData::BlobData(b) => promise.resolve_native(&b),
                 FetchedData::FormData(f) => promise.resolve_native(&f),
-                FetchedData::ArrayBuffer(a) => promise.resolve_native(&a)
+                FetchedData::ArrayBuffer(a) => promise.resolve_native(&a),
+                FetchedData::JSException(e) => promise.reject_native(&e.handle()),
             };
         },
         Err(err) => promise.reject_error(err),
     }
 }
 
 // https://fetch.spec.whatwg.org/#concept-body-package-data
 #[allow(unsafe_code)]
@@ -128,19 +132,20 @@ fn run_json_data_algorithm(cx: *mut JSCo
     let json_text = String::from_utf8_lossy(&bytes);
     let json_text: Vec<u16> = json_text.encode_utf16().collect();
     rooted!(in(cx) let mut rval = UndefinedValue());
     unsafe {
         if !JS_ParseJSON(cx,
                          json_text.as_ptr(),
                          json_text.len() as u32,
                          rval.handle_mut()) {
+            rooted!(in(cx) let mut exception = UndefinedValue());
+            assert!(JS_GetPendingException(cx, exception.handle_mut()));
             JS_ClearPendingException(cx);
-            // TODO: See issue #13464. Exception should be thrown instead of cleared.
-            return Err(Error::Type("Failed to parse JSON".to_string()));
+            return Ok(FetchedData::JSException(RootedTraceableBox::from_box(Heap::boxed(exception.get()))));
         }
         let rooted_heap = RootedTraceableBox::from_box(Heap::boxed(rval.get()));
         Ok(FetchedData::Json(rooted_heap))
     }
 }
 
 fn run_blob_data_algorithm(root: &GlobalScope,
                            bytes: Vec<u8>,
--- a/servo/components/script/lib.rs
+++ b/servo/components/script/lib.rs
@@ -102,17 +102,16 @@ extern crate url;
 extern crate utf8;
 extern crate uuid;
 extern crate webrender_api;
 extern crate webvr_traits;
 extern crate xml5ever;
 
 #[macro_use]
 mod task;
-
 mod body;
 pub mod clipboard_provider;
 mod devtools;
 pub mod document_loader;
 #[macro_use]
 mod dom;
 pub mod fetch;
 mod layout_image;
@@ -145,17 +144,20 @@ pub mod layout_exports {
     pub use dom::document::{Document, LayoutDocumentHelpers, PendingRestyle};
     pub use dom::element::{Element, LayoutElementHelpers, RawLayoutElementHelpers};
     pub use dom::node::NodeFlags;
     pub use dom::node::{LayoutNodeHelpers, Node};
     pub use dom::text::Text;
 }
 
 use dom::bindings::codegen::RegisterBindings;
+use dom::bindings::conversions::is_dom_proxy;
 use dom::bindings::proxyhandler;
+use dom::bindings::utils::is_platform_object;
+use js::jsapi::JSObject;
 use script_traits::SWManagerSenders;
 use serviceworker_manager::ServiceWorkerManager;
 
 #[cfg(target_os = "linux")]
 #[allow(unsafe_code)]
 fn perform_platform_specific_initialization() {
     use std::mem;
     // 4096 is default max on many linux systems
@@ -196,19 +198,26 @@ fn perform_platform_specific_initializat
 fn perform_platform_specific_initialization() {}
 
 pub fn init_service_workers(sw_senders: SWManagerSenders) {
     // Spawn the service worker manager passing the constellation sender
     ServiceWorkerManager::spawn_manager(sw_senders);
 }
 
 #[allow(unsafe_code)]
+unsafe extern "C" fn is_dom_object(obj: *mut JSObject) -> bool {
+  !obj.is_null() && (is_platform_object(obj) || is_dom_proxy(obj))
+}
+
+#[allow(unsafe_code)]
 pub fn init() {
     unsafe {
         proxyhandler::init();
 
         // Create the global vtables used by the (generated) DOM
         // bindings to implement JS proxies.
         RegisterBindings::RegisterProxyHandlers();
+
+        js::glue::InitializeMemoryReporter(Some(is_dom_object));
     }
 
     perform_platform_specific_initialization();
 }
--- a/servo/components/script/mem.rs
+++ b/servo/components/script/mem.rs
@@ -1,32 +1,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/. */
 
 //! Routines for handling measuring the memory usage of arbitrary DOM nodes.
 
-use dom::bindings::conversions::get_dom_class;
-use dom::bindings::reflector::DomObject;
 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use std::os::raw::c_void;
 
-// This is equivalent to measuring a Box<T>, except that DOM objects lose their
-// associated box in order to stash their pointers in a reserved slot of their
-// JS reflector.
-#[allow(unsafe_code)]
-pub fn malloc_size_of_including_self<T: DomObject + MallocSizeOf>(
-    ops: &mut MallocSizeOfOps, obj: &T) -> usize
-{
-    unsafe {
-        let class = get_dom_class(obj.reflector().get_jsobject().get()).unwrap();
-        (class.malloc_size_of)(ops, obj as *const T as *const c_void)
-    }
-}
-
 /// Used by codegen to include the pointer to the `MallocSizeOf` implementation of each
 /// IDL interface. This way we don't have to find the most-derived interface of DOM
 /// objects by hand in code.
 #[allow(unsafe_code)]
 pub unsafe fn malloc_size_of_including_raw_self<T: MallocSizeOf>(
     ops: &mut MallocSizeOfOps, obj: *const c_void) -> usize
 {
     ops.malloc_size_of(obj) + (*(obj as *const T)).size_of(ops)
--- a/servo/components/script/script_runtime.rs
+++ b/servo/components/script/script_runtime.rs
@@ -1,31 +1,34 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! The script runtime contains common traits and structs commonly used by the
 //! script thread, the dom, and the worker threads.
 
 use dom::bindings::codegen::Bindings::PromiseBinding::PromiseJobCallback;
+use dom::bindings::conversions::get_dom_class;
+use dom::bindings::conversions::private_from_object;
 use dom::bindings::refcounted::{LiveDOMReferences, trace_refcounted_objects};
 use dom::bindings::root::trace_roots;
 use dom::bindings::settings_stack;
 use dom::bindings::trace::{JSTraceable, trace_traceables};
 use dom::bindings::utils::DOM_CALLBACKS;
 use dom::globalscope::GlobalScope;
 use js::glue::CollectServoSizes;
 use js::jsapi::{DisableIncrementalGC, GCDescription, GCProgress, HandleObject};
 use js::jsapi::{JSContext, JS_GetRuntime, JSRuntime, JSTracer, SetDOMCallbacks, SetGCSliceCallback};
 use js::jsapi::{JSGCInvocationKind, JSGCStatus, JS_AddExtraGCRootsTracer, JS_SetGCCallback};
 use js::jsapi::{JSGCMode, JSGCParamKey, JS_SetGCParameter, JS_SetGlobalJitCompilerOption};
 use js::jsapi::{JSJitCompilerOption, JS_SetOffthreadIonCompilationEnabled, JS_SetParallelParsingEnabled};
 use js::jsapi::{JSObject, RuntimeOptionsRef, SetPreserveWrapperCallback, SetEnqueuePromiseJobCallback};
 use js::panic::wrap_panic;
 use js::rust::Runtime as RustRuntime;
+use malloc_size_of::MallocSizeOfOps;
 use microtask::{EnqueuedPromiseCallback, Microtask};
 use msg::constellation_msg::PipelineId;
 use profile_traits::mem::{Report, ReportKind, ReportsChan};
 use script_thread::trace_thread;
 use servo_config::opts;
 use servo_config::prefs::PREFS;
 use std::cell::Cell;
 use std::fmt;
@@ -308,23 +311,41 @@ pub unsafe fn new_rt_and_cx() -> Runtime
             JS_SetGCParameter(runtime.rt(), JSGCParamKey::JSGC_MAX_EMPTY_CHUNK_COUNT, val as u32);
         }
     }
 
     Runtime(runtime)
 }
 
 #[allow(unsafe_code)]
+unsafe extern "C" fn get_size(obj: *mut JSObject) -> usize {
+    match get_dom_class(obj) {
+        Ok(v) => {
+            let dom_object = private_from_object(obj) as *const c_void;
+
+            if dom_object.is_null() {
+                return 0;
+            }
+            let mut ops = MallocSizeOfOps::new(::servo_allocator::usable_size, None, None);
+            (v.malloc_size_of)(&mut ops, dom_object)
+        }
+        Err(_e) => {
+            return 0;
+        }
+    }
+}
+
+#[allow(unsafe_code)]
 pub fn get_reports(cx: *mut JSContext, path_seg: String) -> Vec<Report> {
     let mut reports = vec![];
 
     unsafe {
         let rt = JS_GetRuntime(cx);
         let mut stats = ::std::mem::zeroed();
-        if CollectServoSizes(rt, &mut stats) {
+        if CollectServoSizes(rt, &mut stats, Some(get_size)) {
             let mut report = |mut path_suffix, kind, size| {
                 let mut path = path![path_seg, "js"];
                 path.append(&mut path_suffix);
                 reports.push(Report {
                     path: path,
                     kind: kind,
                     size: size as usize,
                 })
--- a/servo/components/script/script_thread.rs
+++ b/servo/components/script/script_thread.rs
@@ -12,16 +12,18 @@
 //! While the non-blocking request is ongoing, the script thread is free to process further events,
 //! noting when they pertain to ongoing loads (such as resizes/viewport adjustments). When the
 //! initial response is received for an ongoing load, the second phase starts - the frame tree
 //! entry is created, along with the Window and Document objects, and the appropriate parser
 //! takes over the response body. Once parsing is complete, the document lifecycle for loading
 //! a page runs its course and the script thread returns to processing events in the main event
 //! loop.
 
+extern crate itertools;
+
 use bluetooth_traits::BluetoothRequest;
 use canvas_traits::webgl::WebGLPipeline;
 use devtools;
 use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo};
 use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
 use devtools_traits::CSSError;
 use document_loader::DocumentLoader;
 use dom::bindings::cell::DomRefCell;
@@ -67,27 +69,25 @@ use hyper::header::ReferrerPolicy as Ref
 use hyper::mime::{Mime, SubLevel, TopLevel};
 use hyper_serde::Serde;
 use ipc_channel::ipc::{self, IpcSender};
 use ipc_channel::router::ROUTER;
 use js::glue::GetWindowProxyClass;
 use js::jsapi::{JSAutoCompartment, JSContext, JS_SetWrapObjectCallbacks};
 use js::jsapi::{JSTracer, SetWindowProxyClass};
 use js::jsval::UndefinedValue;
-use malloc_size_of::MallocSizeOfOps;
-use mem::malloc_size_of_including_self;
 use metrics::{MAX_TASK_NS, PaintTimeMetrics};
 use microtask::{MicrotaskQueue, Microtask};
 use msg::constellation_msg::{BrowsingContextId, PipelineId, PipelineNamespace, TopLevelBrowsingContextId};
 use net_traits::{FetchMetadata, FetchResponseListener, FetchResponseMsg};
 use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads};
 use net_traits::image_cache::{ImageCache, PendingImageResponse};
 use net_traits::request::{CredentialsMode, Destination, RedirectMode, RequestInit};
 use net_traits::storage_thread::StorageType;
-use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan};
+use profile_traits::mem::{self, OpaqueSender, ReportsChan};
 use profile_traits::time::{self, ProfilerCategory, profile};
 use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowGoal};
 use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
 use script_runtime::{ScriptPort, get_reports, new_rt_and_cx, Runtime};
 use script_traits::{CompositorEvent, ConstellationControlMsg};
 use script_traits::{DiscardBrowsingContext, DocumentActivity, EventResult};
 use script_traits::{InitialScriptState, JsEvalResult, LayoutMsg, LoadData};
 use script_traits::{MouseButton, MouseEventType, NewLayoutInfo};
@@ -1575,44 +1575,21 @@ impl ScriptThread {
         if load_data.url.as_str() == "about:blank" {
             self.start_page_load_about_blank(new_load, load_data.js_eval_result);
         } else {
             self.pre_page_load(new_load, load_data);
         }
     }
 
     fn collect_reports(&self, reports_chan: ReportsChan) {
-        let mut path_seg = String::from("url(");
-        let mut dom_tree_size = 0;
-        let mut reports = vec![];
-        // Servo uses vanilla jemalloc, which doesn't have a
-        // malloc_enclosing_size_of function.
-        let mut ops = MallocSizeOfOps::new(::servo_allocator::usable_size, None, None);
-
-        for (_, document) in self.documents.borrow().iter() {
-            let current_url = document.url();
+        let documents = self.documents.borrow();
+        let urls = itertools::join(documents.iter().map(|(_, d)| d.url().to_string()), ", ");
+        let path_seg = format!("url({})", urls);
 
-            for child in document.upcast::<Node>().traverse_preorder() {
-                dom_tree_size += malloc_size_of_including_self(&mut ops, &*child);
-            }
-            dom_tree_size += malloc_size_of_including_self(&mut ops, document.window());
-
-            if reports.len() > 0 {
-                path_seg.push_str(", ");
-            }
-            path_seg.push_str(current_url.as_str());
-
-            reports.push(Report {
-                path: path![format!("url({})", current_url.as_str()), "dom-tree"],
-                kind: ReportKind::ExplicitJemallocHeapSize,
-                size: dom_tree_size,
-            });
-        }
-
-        path_seg.push_str(")");
+        let mut reports = vec![];
         reports.extend(get_reports(self.get_cx(), path_seg));
         reports_chan.send(reports);
     }
 
     /// Updates iframe element after a change in visibility
     fn handle_visibility_change_complete_msg(&self,
                                              parent_pipeline_id: PipelineId,
                                              browsing_context_id: BrowsingContextId,
--- a/servo/components/style/gecko/generated/bindings.rs
+++ b/servo/components/style/gecko/generated/bindings.rs
@@ -49,17 +49,16 @@ use gecko_bindings::structs::RawGeckoSty
 use gecko_bindings::structs::RawGeckoStyleChildrenIterator;
 use gecko_bindings::structs::RawGeckoServoStyleRuleList;
 use gecko_bindings::structs::RawGeckoURLExtraData;
 use gecko_bindings::structs::RawGeckoXBLBinding;
 use gecko_bindings::structs::RawServoSelectorList;
 use gecko_bindings::structs::RawServoSourceSizeList;
 use gecko_bindings::structs::RefPtr;
 use gecko_bindings::structs::RustString;
-use gecko_bindings::structs::CSSPseudoClassType;
 use gecko_bindings::structs::CSSPseudoElementType;
 use gecko_bindings::structs::ServoTraversalFlags;
 use gecko_bindings::structs::ComputedTimingFunction_BeforeFlag;
 use gecko_bindings::structs::CounterStylePtr;
 use gecko_bindings::structs::FontFamilyType;
 use gecko_bindings::structs::FontSizePrefs;
 use gecko_bindings::structs::GeckoFontMetrics;
 use gecko_bindings::structs::IterationCompositeOperation;
@@ -623,36 +622,36 @@ extern "C" {
 }
 extern "C" {
     pub fn Gecko_ElementState(element: RawGeckoElementBorrowed) -> u64;
 }
 extern "C" {
     pub fn Gecko_IsRootElement(element: RawGeckoElementBorrowed) -> bool;
 }
 extern "C" {
-    pub fn Gecko_MatchesElement(
-        type_: CSSPseudoClassType,
-        element: RawGeckoElementBorrowed,
-    ) -> bool;
-}
-extern "C" {
     pub fn Gecko_MatchLang(
         element: RawGeckoElementBorrowed,
         override_lang: *mut nsAtom,
         has_override_lang: bool,
         value: *const u16,
     ) -> bool;
 }
 extern "C" {
     pub fn Gecko_GetXMLLangValue(element: RawGeckoElementBorrowed) -> *mut nsAtom;
 }
 extern "C" {
     pub fn Gecko_GetDocumentLWTheme(aDocument: *const nsIDocument) -> nsIDocument_DocumentTheme;
 }
 extern "C" {
+    pub fn Gecko_IsTableBorderNonzero(element: RawGeckoElementBorrowed) -> bool;
+}
+extern "C" {
+    pub fn Gecko_IsBrowserFrame(element: RawGeckoElementBorrowed) -> bool;
+}
+extern "C" {
     pub fn Gecko_AtomAttrValue(
         element: RawGeckoElementBorrowed,
         attribute: *mut nsAtom,
     ) -> *mut nsAtom;
 }
 extern "C" {
     pub fn Gecko_LangValue(element: RawGeckoElementBorrowed) -> *mut nsAtom;
 }
--- a/servo/components/style/gecko/generated/structs.rs
+++ b/servo/components/style/gecko/generated/structs.rs
@@ -12262,107 +12262,16 @@ pub mod root {
                 concat!(
                     "Offset of field: ",
                     stringify!(EffectCompositor),
                     "::",
                     stringify!(mIsInPreTraverse)
                 )
             );
         }
-        pub type CSSPseudoClassTypeBase = u8;
-        #[repr(u8)]
-        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-        pub enum CSSPseudoClassType {
-            empty = 0,
-            mozOnlyWhitespace = 1,
-            lang = 2,
-            root = 3,
-            any = 4,
-            firstChild = 5,
-            firstNode = 6,
-            lastChild = 7,
-            lastNode = 8,
-            onlyChild = 9,
-            firstOfType = 10,
-            lastOfType = 11,
-            onlyOfType = 12,
-            nthChild = 13,
-            nthLastChild = 14,
-            nthOfType = 15,
-            nthLastOfType = 16,
-            mozIsHTML = 17,
-            mozNativeAnonymous = 18,
-            mozUseShadowTreeRoot = 19,
-            mozLocaleDir = 20,
-            mozLWTheme = 21,
-            mozLWThemeBrightText = 22,
-            mozLWThemeDarkText = 23,
-            mozWindowInactive = 24,
-            mozTableBorderNonzero = 25,
-            mozBrowserFrame = 26,
-            scope = 27,
-            negation = 28,
-            dir = 29,
-            link = 30,
-            mozAnyLink = 31,
-            anyLink = 32,
-            visited = 33,
-            active = 34,
-            checked = 35,
-            disabled = 36,
-            enabled = 37,
-            focus = 38,
-            focusWithin = 39,
-            hover = 40,
-            mozDragOver = 41,
-            target = 42,
-            indeterminate = 43,
-            mozDevtoolsHighlighted = 44,
-            mozStyleeditorTransitioning = 45,
-            fullscreen = 46,
-            mozFullScreen = 47,
-            mozFocusRing = 48,
-            mozBroken = 49,
-            mozLoading = 50,
-            mozUserDisabled = 51,
-            mozSuppressed = 52,
-            mozHandlerClickToPlay = 53,
-            mozHandlerVulnerableUpdatable = 54,
-            mozHandlerVulnerableNoUpdate = 55,
-            mozHandlerDisabled = 56,
-            mozHandlerBlocked = 57,
-            mozHandlerCrashed = 58,
-            mozMathIncrementScriptLevel = 59,
-            mozHasDirAttr = 60,
-            mozDirAttrLTR = 61,
-            mozDirAttrRTL = 62,
-            mozDirAttrLikeAuto = 63,
-            mozAutofill = 64,
-            mozAutofillPreview = 65,
-            required = 66,
-            optional = 67,
-            valid = 68,
-            invalid = 69,
-            inRange = 70,
-            outOfRange = 71,
-            defaultPseudo = 72,
-            placeholderShown = 73,
-            mozReadOnly = 74,
-            mozReadWrite = 75,
-            mozSubmitInvalid = 76,
-            mozUIInvalid = 77,
-            mozUIValid = 78,
-            mozMeterOptimum = 79,
-            mozMeterSubOptimum = 80,
-            mozMeterSubSubOptimum = 81,
-            mozPlaceholder = 82,
-            Count = 83,
-            NotPseudo = 84,
-            MAX = 85,
-        }
         #[repr(C)]
         pub struct GeckoFont {
             pub gecko: root::nsStyleFont,
         }
         #[test]
         fn bindgen_test_layout_GeckoFont() {
             assert_eq!(
                 ::std::mem::size_of::<GeckoFont>(),
--- a/servo/components/style/gecko/non_ts_pseudo_class_list.rs
+++ b/servo/components/style/gecko/non_ts_pseudo_class_list.rs
@@ -23,19 +23,16 @@
  *
  * The `string` and `keyword` variables will be applied to pseudoclasses that are of the form of
  * functions with string or keyword arguments.
  *
  * Pending pseudo-classes:
  *
  *  :scope -> <style scoped>, pending discussion.
  *
- * This follows the order defined in layout/style/nsCSSPseudoClassList.h when
- * possible.
- *
  * $gecko_type can be either "_" or an ident in Gecko's CSSPseudoClassType.
  * $state can be either "_" or an expression of type ElementState.  If present,
  *        the semantics are that the pseudo-class matches if any of the bits in
  *        $state are set on the element.
  * $flags can be either "_" or an expression of type NonTSPseudoClassFlag,
  * see selector_parser.rs for more details.
  */
 
--- a/servo/components/style/gecko/selector_parser.rs
+++ b/servo/components/style/gecko/selector_parser.rs
@@ -1,17 +1,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/. */
 
 //! Gecko-specific bits for selector-parsing.
 
 use cssparser::{BasicParseError, BasicParseErrorKind, Parser, ToCss, Token, CowRcStr, SourceLocation};
 use element_state::{DocumentState, ElementState};
-use gecko_bindings::structs::{self, CSSPseudoClassType};
+use gecko_bindings::structs;
 use gecko_bindings::structs::RawServoSelectorList;
 use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
 use invalidation::element::document_state::InvalidationMatchingData;
 use selector_parser::{Direction, SelectorParser};
 use selectors::SelectorList;
 use selectors::parser::{self as selector_parser, Selector, Visit, SelectorParseErrorKind};
 use selectors::visitor::SelectorVisitor;
 use std::fmt;
@@ -128,16 +128,32 @@ impl Visit for NonTSPseudoClass {
         }
 
         true
     }
 }
 
 
 impl NonTSPseudoClass {
+    /// Parses the name and returns a non-ts-pseudo-class if succeeds.
+    /// None otherwise. It doesn't check whether the pseudo-class is enabled
+    /// in a particular state.
+    pub fn parse_non_functional(name: &str) -> Option<Self> {
+        macro_rules! pseudo_class_parse {
+            (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
+             string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
+                match_ignore_ascii_case! { &name,
+                    $($css => Some(NonTSPseudoClass::$name),)*
+                    _ => None,
+                }
+            }
+        }
+        apply_non_ts_list!(pseudo_class_parse)
+    }
+
     /// Returns true if this pseudo-class has any of the given flags set.
     fn has_any_flag(&self, flags: NonTSPseudoClassFlag) -> bool {
         macro_rules! check_flag {
             (_) => (false);
             ($flags:ident) => (NonTSPseudoClassFlag::$flags.intersects(flags));
         }
         macro_rules! pseudo_class_check_is_enabled_in {
             (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
@@ -237,38 +253,16 @@ impl NonTSPseudoClass {
                   NonTSPseudoClass::MozWindowInactive |
                   // Similar for the document themes.
                   NonTSPseudoClass::MozLWTheme |
                   NonTSPseudoClass::MozLWThemeBrightText |
                   NonTSPseudoClass::MozLWThemeDarkText
         )
     }
 
-    /// Convert NonTSPseudoClass to Gecko's CSSPseudoClassType.
-    pub fn to_gecko_pseudoclasstype(&self) -> Option<CSSPseudoClassType> {
-        macro_rules! gecko_type {
-            (_) => (None);
-            ($gecko_type:ident) =>
-                (Some(::gecko_bindings::structs::CSSPseudoClassType::$gecko_type));
-        }
-        macro_rules! pseudo_class_geckotype {
-            (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
-             string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
-                match *self {
-                    $(NonTSPseudoClass::$name => gecko_type!($gecko_type),)*
-                    $(NonTSPseudoClass::$s_name(..) => gecko_type!($s_gecko_type),)*
-                    NonTSPseudoClass::MozLocaleDir(_) => gecko_type!(mozLocaleDir),
-                    NonTSPseudoClass::Dir(_) => gecko_type!(dir),
-                    NonTSPseudoClass::MozAny(_) => gecko_type!(any),
-                }
-            }
-        }
-        apply_non_ts_list!(pseudo_class_geckotype)
-    }
-
     /// Returns true if the evaluation of the pseudo-class depends on the
     /// element's attributes.
     pub fn is_attr_based(&self) -> bool {
         matches!(*self,
                  NonTSPseudoClass::MozTableBorderNonzero |
                  NonTSPseudoClass::MozBrowserFrame |
                  NonTSPseudoClass::Lang(..))
     }
@@ -368,33 +362,22 @@ impl<'a, 'i> ::selectors::Parser<'i> for
             name.starts_with("-moz-tree-")
     }
 
     fn parse_non_ts_pseudo_class(
         &self,
         location: SourceLocation,
         name: CowRcStr<'i>,
     ) -> Result<NonTSPseudoClass, ParseError<'i>> {
-        macro_rules! pseudo_class_parse {
-            (bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
-             string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
-                match_ignore_ascii_case! { &name,
-                    $($css => NonTSPseudoClass::$name,)*
-                    _ => return Err(location.new_custom_error(
-                        SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone())
-                    ))
-                }
+        if let Some(pseudo_class) = NonTSPseudoClass::parse_non_functional(&name) {
+            if self.is_pseudo_class_enabled(&pseudo_class) {
+                return Ok(pseudo_class);
             }
         }
-        let pseudo_class = apply_non_ts_list!(pseudo_class_parse);
-        if self.is_pseudo_class_enabled(&pseudo_class) {
-            Ok(pseudo_class)
-        } else {
-            Err(location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name)))
-        }
+        Err(location.new_custom_error(SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name)))
     }
 
     fn parse_non_ts_functional_pseudo_class<'t>(
         &self,
         name: CowRcStr<'i>,
         parser: &mut Parser<'i, 't>,
     ) -> Result<NonTSPseudoClass, ParseError<'i>> {
         macro_rules! pseudo_class_string_parse {
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -27,17 +27,16 @@ use font_metrics::{FontMetrics, FontMetr
 use gecko::data::GeckoStyleSheet;
 use gecko::global_style_data::GLOBAL_STYLE_DATA;
 use gecko::selector_parser::{SelectorImpl, NonTSPseudoClass, PseudoElement};
 use gecko::snapshot_helpers;
 use gecko_bindings::bindings;
 use gecko_bindings::bindings::{Gecko_ConstructStyleChildrenIterator, Gecko_DestroyStyleChildrenIterator};
 use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentLWTheme};
 use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetNextStyleChild};
-use gecko_bindings::bindings::{Gecko_IsRootElement, Gecko_MatchesElement};
 use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
 use gecko_bindings::bindings::Gecko_ClassOrClassList;
 use gecko_bindings::bindings::Gecko_ElementHasAnimations;
 use gecko_bindings::bindings::Gecko_ElementHasCSSAnimations;
 use gecko_bindings::bindings::Gecko_ElementHasCSSTransitions;
 use gecko_bindings::bindings::Gecko_GetActiveLinkAttrDeclarationBlock;
 use gecko_bindings::bindings::Gecko_GetAnimationRule;
 use gecko_bindings::bindings::Gecko_GetExtraContentStyleDeclarations;
@@ -809,16 +808,31 @@ impl<'le> GeckoElement<'le> {
 
     /// This logic is duplicated in Gecko's nsIContent::IsInAnonymousSubtree.
     #[inline]
     fn is_in_anonymous_subtree(&self) -> bool {
         self.is_in_native_anonymous_subtree() ||
         (!self.as_node().is_in_shadow_tree() && self.has_xbl_binding_parent())
     }
 
+    /// Returns true if this node is the shadow root of an use-element shadow tree.
+    #[inline]
+    fn is_root_of_use_element_shadow_tree(&self) -> bool {
+        if !self.is_root_of_anonymous_subtree() {
+            return false
+        }
+        match self.parent_element() {
+            Some(e) => {
+                e.local_name() == &*local_name!("use") &&
+                    e.namespace() == &*ns!("http://www.w3.org/2000/svg")
+            },
+            None => false,
+        }
+    }
+
     fn css_transitions_info(&self) -> FnvHashMap<LonghandId, Arc<AnimationValue>> {
         use gecko_bindings::bindings::Gecko_ElementTransitions_EndValueAt;
         use gecko_bindings::bindings::Gecko_ElementTransitions_Length;
 
         let collection_length =
             unsafe { Gecko_ElementTransitions_Length(self.0) } as usize;
         let mut map = FnvHashMap::with_capacity_and_hasher(
             collection_length,
@@ -1976,17 +1990,17 @@ impl<'le> ::selectors::Element for Gecko
             None => return false,
         };
 
         if !parent_node.is_document() {
             return false;
         }
 
         unsafe {
-            Gecko_IsRootElement(self.0)
+            bindings::Gecko_IsRootElement(self.0)
         }
     }
 
     fn is_empty(&self) -> bool {
         !self.as_node().dom_children().any(|child| unsafe {
             Gecko_IsSignificantChild(child.0, true)
         })
     }
@@ -2098,21 +2112,27 @@ impl<'le> ::selectors::Element for Gecko
             }
             NonTSPseudoClass::MozOnlyWhitespace => {
                 flags_setter(self, ElementSelectorFlags::HAS_EMPTY_SELECTOR);
                 if self.as_node().dom_children().any(|c| c.contains_non_whitespace_content()) {
                     return false
                 }
                 true
             }
-            NonTSPseudoClass::MozTableBorderNonzero |
-            NonTSPseudoClass::MozBrowserFrame |
-            NonTSPseudoClass::MozNativeAnonymous |
-            NonTSPseudoClass::MozUseShadowTreeRoot => unsafe {
-                Gecko_MatchesElement(pseudo_class.to_gecko_pseudoclasstype().unwrap(), self.0)
+            NonTSPseudoClass::MozNativeAnonymous => {
+                self.is_in_native_anonymous_subtree()
+            }
+            NonTSPseudoClass::MozUseShadowTreeRoot => {
+                self.is_root_of_use_element_shadow_tree()
+            }
+            NonTSPseudoClass::MozTableBorderNonzero => unsafe {
+                bindings::Gecko_IsTableBorderNonzero(self.0)
+            }
+            NonTSPseudoClass::MozBrowserFrame => unsafe {
+                bindings::Gecko_IsBrowserFrame(self.0)
             },
             NonTSPseudoClass::MozIsHTML => {
                 self.is_html_element_in_html_document()
             }
             NonTSPseudoClass::MozLWTheme => {
                 self.document_theme() != DocumentTheme::Doc_Theme_None
             }
             NonTSPseudoClass::MozLWThemeBrightText => {
@@ -2230,30 +2250,20 @@ impl<'le> ::selectors::Element for Gecko
 
     #[inline]
     fn ignores_nth_child_selectors(&self) -> bool {
         self.is_root_of_anonymous_subtree()
     }
 
     #[inline]
     fn blocks_ancestor_combinators(&self) -> bool {
-        if !self.is_root_of_anonymous_subtree() {
-            return false
-        }
-
-        match self.parent_element() {
-            Some(e) => {
-                // If this element is the shadow root of an use-element shadow
-                // tree, according to the spec, we should not match rules
-                // cross the shadow DOM boundary.
-                e.local_name() == &*local_name!("use") &&
-                e.namespace() == &*ns!("http://www.w3.org/2000/svg")
-            },
-            None => false,
-        }
+        // If this element is the shadow root of an use-element shadow tree,
+        // according to the spec, we should not match rules cross the shadow
+        // DOM boundary.
+        self.is_root_of_use_element_shadow_tree()
     }
 }
 
 /// A few helpers to help with attribute selectors and snapshotting.
 pub trait NamespaceConstraintHelpers {
     /// Returns the namespace of the selector, or null otherwise.
     fn atom_or_null(&self) -> *mut nsAtom;
 }
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -26,17 +26,17 @@ use style::data::{ElementStyles, self};
 use style::dom::{ShowSubtreeData, TDocument, TElement, TNode};
 use style::driver;
 use style::element_state::{DocumentState, ElementState};
 use style::error_reporting::{ContextualParseError, NullReporter, ParseErrorReporter};
 use style::font_metrics::{FontMetricsProvider, get_metrics_provider_for_product};
 use style::gecko::data::{GeckoStyleSheet, PerDocumentStyleData, PerDocumentStyleDataImpl};
 use style::gecko::global_style_data::{GLOBAL_STYLE_DATA, GlobalStyleData, STYLE_THREAD_POOL};
 use style::gecko::restyle_damage::GeckoRestyleDamage;
-use style::gecko::selector_parser::PseudoElement;
+use style::gecko::selector_parser::{NonTSPseudoClass, PseudoElement};
 use style::gecko::traversal::RecalcStyleOnly;
 use style::gecko::wrapper::{GeckoElement, GeckoNode};
 use style::gecko_bindings::bindings;
 use style::gecko_bindings::bindings::{RawGeckoElementBorrowed, RawGeckoElementBorrowedOrNull, RawGeckoNodeBorrowed};
 use style::gecko_bindings::bindings::{RawGeckoKeyframeListBorrowed, RawGeckoKeyframeListBorrowedMut};
 use style::gecko_bindings::bindings::{RawServoAuthorStyles, RawServoAuthorStylesBorrowed};
 use style::gecko_bindings::bindings::{RawServoAuthorStylesBorrowedMut, RawServoAuthorStylesOwned};
 use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
@@ -5110,8 +5110,19 @@ pub extern "C" fn Servo_ParseCounterStyl
     );
     counter_style::parse_counter_style_descriptor(
         &context,
         &mut parser,
         descriptor,
         result,
     ).is_ok()
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_PseudoClass_GetStates(name: *const nsACString) -> u64 {
+    let name = name.as_ref().unwrap().as_str_unchecked();
+    match NonTSPseudoClass::parse_non_functional(name) {
+        None => 0,
+        // Ignore :any-link since it contains both visited and unvisited state.
+        Some(NonTSPseudoClass::AnyLink) => 0,
+        Some(pseudo_class) => pseudo_class.state_flag().bits(),
+    }
+}
--- a/toolkit/components/feeds/FeedProcessor.js
+++ b/toolkit/components/feeds/FeedProcessor.js
@@ -1241,29 +1241,16 @@ FeedProcessor.prototype = {
       if (this.listener != null)
         this.listener.handleResult(this._result);
     } finally {
       this._result = null;
     }
   },
 
   // Parsing functions
-  parseFromStream: function FP_parseFromStream(stream, uri) {
-    this._init(uri);
-    this._reader.parseFromStream(stream, null, stream.available(),
-                                 "application/xml");
-    this._reader = null;
-  },
-
-  parseFromString: function FP_parseFromString(inputString, uri) {
-    this._init(uri);
-    this._reader.parseFromString(inputString, "application/xml");
-    this._reader = null;
-  },
-
   parseAsync: function FP_parseAsync(requestObserver, uri) {
     this._init(uri);
     this._reader.parseAsync(requestObserver);
   },
 
   // nsIStreamListener
 
   // The XMLReader will throw sensible exceptions if these get called
--- a/toolkit/components/feeds/nsIFeedProcessor.idl
+++ b/toolkit/components/feeds/nsIFeedProcessor.idl
@@ -23,32 +23,16 @@ interface nsIFeedProcessor : nsIStreamLi
 
   // Level is where to listen for the extension, a constant: FEED,
   // ENTRY, BOTH.
   //
   // XXX todo void registerExtensionHandler(in
   // nsIFeedExtensionHandler, in long level);
   
   /**
-   * Parse a feed from an nsIInputStream.
-   *
-   * @param stream The input stream.
-   * @param uri The base URI.
-   */
-  void parseFromStream(in nsIInputStream stream, in nsIURI uri);
-
-  /**
-   * Parse a feed from a string.
-   *
-   * @param str The string to parse.
-   * @param uri The base URI.
-   */
-  void parseFromString(in AString str, in nsIURI uri);		
-
-  /**
    * Parse a feed asynchronously. The caller must then call the
    * nsIFeedProcessor's nsIStreamListener methods to drive the
    * parse. Do not call the other parse methods during an asynchronous
    * parse.
    *
    * @param requestObserver The observer to notify on start/stop. This
    *                        argument can be null.
    * @param uri The base URI.
--- a/toolkit/components/feeds/test/test_xml.js
+++ b/toolkit/components/feeds/test/test_xml.js
@@ -20,16 +20,18 @@
  *             |
  *             -- atom/testcase.xml
  *
  * To add more tests, just include the file in the xml subfolder and add its name to xpcshell.ini
  */
 
 "use strict";
 
+ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
+
 // Listens to feeds being loaded. Runs the tests built into the feed afterwards to veryify they
 // were parsed correctly.
 function FeedListener(testcase) {
   this.testcase = testcase;
 }
 
 FeedListener.prototype = {
   handleResult(result) {
@@ -62,26 +64,45 @@ function createTest(data) {
       uri = data.base;
     }
 
     info("Testing " + data.file.leafName);
 
     var parser = Cc["@mozilla.org/feed-processor;1"].createInstance(Ci.nsIFeedProcessor);
     var stream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
     stream.init(data.file, 0x01, parseInt("0444", 8), 0);
+    var bStream = Cc["@mozilla.org/network/buffered-input-stream;1"].createInstance(Ci.nsIBufferedInputStream);
+    bStream.init(stream, 4096);
     parser.listener = new FeedListener(data);
 
     try {
-      parser.parseFromStream(stream, uri);
+      let channel = Cc["@mozilla.org/network/input-stream-channel;1"].
+        createInstance(Ci.nsIInputStreamChannel);
+      channel.setURI(uri);
+      channel.contentStream = bStream;
+      channel.QueryInterface(Ci.nsIChannel);
+      channel.contentType = "text/xml";
+
+      parser.parseAsync(null, uri);
+      parser.onStartRequest(channel, uri);
+
+      let pos = 0;
+      let count = bStream.available();
+      while (count > 0) {
+        parser.onDataAvailable(channel, null, bStream, pos, count);
+        pos += count;
+        count = bStream.available();
+      }
+      parser.onStopRequest(channel, null, Cr.NS_OK);
     } catch (e) {
       Assert.ok(false, "parse failed for " + data.file.leafName + " ---- " + e.message);
       // If the parser failed, the listener won't be notified, run the next test here.
       run_next_test();
     } finally {
-      stream.close();
+      bStream.close();
     }
   };
 }
 
 function run_test() {
   // Get the 'xml' directory in here
   var topDir = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
   topDir.append("xml");